diff options
Diffstat (limited to 'xA')
-rw-r--r-- | xA/Makefile | 6 | ||||
-rw-r--r-- | xA/xA.go | 162 |
2 files changed, 104 insertions, 64 deletions
diff --git a/xA/Makefile b/xA/Makefile index da62944..d0f0449 100644 --- a/xA/Makefile +++ b/xA/Makefile @@ -4,8 +4,10 @@ AWK = env LC_ALL=C awk tools = ../liberty/tools -outputs = FyneApp.toml xA proto.go xA.png xA-highlighted.png beep.raw +generated = FyneApp.toml xA.png xA-highlighted.png beep.raw proto.go +outputs = xA $(generated) all: $(outputs) +generate: $(generated) FyneApp.toml: ../xK-version printf "\ @@ -27,7 +29,7 @@ beep.raw: proto.go: $(tools)/lxdrgen.awk $(tools)/lxdrgen-go.awk ../xC.lxdr $(AWK) -f $(tools)/lxdrgen.awk -f $(tools)/lxdrgen-go.awk \ -v PrefixCamel=Relay ../xC.lxdr > $@ -xA: xA.go proto.go ../xK-version xA.png xA-highlighted.png beep.raw +xA: xA.go ../xK-version $(generated) go build -ldflags "-X 'main.projectVersion=$$(cat ../xK-version)'" -o $@ \ -gcflags=all="-N -l" clean: @@ -281,7 +281,11 @@ func beep() { } go func() { <-otoReady - otoContext.NewPlayer(bytes.NewReader(beepSample)).Play() + p := otoContext.NewPlayer(bytes.NewReader(beepSample)) + p.Play() + for p.IsPlaying() { + time.Sleep(time.Second) + } }() } @@ -363,50 +367,6 @@ func bufferByName(name string) *buffer { return nil } -func bufferActivate(name string) { - relaySend(RelayCommandData{ - Variant: &RelayCommandDataBufferActivate{BufferName: name}, - }, nil) -} - -func bufferToggleUnimportant(name string) { - relaySend(RelayCommandData{ - Variant: &RelayCommandDataBufferToggleUnimportant{BufferName: name}, - }, nil) -} - -// --- Current buffer ---------------------------------------------------------- - -func bufferToggleLogFinish(err string, response *RelayResponseDataBufferLog) { - if response == nil { - showErrorMessage(err) - return - } - - wLog.SetText(string(response.Log)) - wLog.Show() - wRichScroll.Hide() -} - -func bufferToggleLog() { - if wLog.Visible() { - wRichScroll.Show() - wLog.Hide() - wLog.SetText("") - return - } - - name := bufferCurrent - relaySend(RelayCommandData{Variant: &RelayCommandDataBufferLog{ - BufferName: name, - }}, func(err string, response *RelayResponseData) { - if bufferCurrent == name { - bufferToggleLogFinish( - err, response.Variant.(*RelayResponseDataBufferLog)) - } - }) -} - func bufferAtBottom() bool { return wRichScroll.Offset.Y >= wRichScroll.Content.Size().Height-wRichScroll.Size().Height @@ -421,22 +381,31 @@ func bufferScrollToBottom() { refreshStatus() } +func bufferPushLine(b *buffer, line bufferLine) { + b.lines = append(b.lines, line) + + // Fyne's text layouting is extremely slow. + // The limit could be made configurable, + // and we could use a ring buffer approach to storing the lines. + if len(b.lines) > 100 { + b.lines = slices.Delete(b.lines, 0, 1) + } +} + // --- UI state refresh -------------------------------------------------------- func refreshIcon() { - highlighted := false + resource := resourceIconNormal for _, b := range buffers { if b.highlighted { - highlighted = true + resource = resourceIconHighlighted break } } - if highlighted { - wWindow.SetIcon(resourceIconHighlighted) - } else { - wWindow.SetIcon(resourceIconNormal) - } + // Prevent deadlocks (though it might have a race condition). + // https://github.com/fyne-io/fyne/issues/5266 + go func() { wWindow.SetIcon(resource) }() } func refreshTopic(topic []bufferLineItem) { @@ -504,6 +473,63 @@ func refreshStatus() { wStatus.SetText(status) } +func recheckHighlighted() { + // Corresponds to the logic toggling the bool on. + if b := bufferByName(bufferCurrent); b != nil && + b.highlighted && bufferAtBottom() && + inForeground && !wLog.Visible() { + b.highlighted = false + refreshIcon() + refreshBufferList() + } +} + +// --- Buffer actions ---------------------------------------------------------- + +func bufferActivate(name string) { + relaySend(RelayCommandData{ + Variant: &RelayCommandDataBufferActivate{BufferName: name}, + }, nil) +} + +func bufferToggleUnimportant(name string) { + relaySend(RelayCommandData{ + Variant: &RelayCommandDataBufferToggleUnimportant{BufferName: name}, + }, nil) +} + +func bufferToggleLogFinish(err string, response *RelayResponseDataBufferLog) { + if response == nil { + showErrorMessage(err) + return + } + + wLog.SetText(string(response.Log)) + wLog.Show() + wRichScroll.Hide() +} + +func bufferToggleLog() { + if wLog.Visible() { + wRichScroll.Show() + wLog.Hide() + wLog.SetText("") + + recheckHighlighted() + return + } + + name := bufferCurrent + relaySend(RelayCommandData{Variant: &RelayCommandDataBufferLog{ + BufferName: name, + }}, func(err string, response *RelayResponseData) { + if bufferCurrent == name { + bufferToggleLogFinish( + err, response.Variant.(*RelayResponseDataBufferLog)) + } + }) +} + // --- RichText formatting ----------------------------------------------------- func defaultBufferLineItem() bufferLineItem { return bufferLineItem{} } @@ -745,6 +771,7 @@ func refreshBuffer(b *buffer) { bufferPrintAndWatchTrailingDateChanges() wRichText.Refresh() bufferScrollToBottom() + recheckHighlighted() } // --- Event processing -------------------------------------------------------- @@ -755,7 +782,7 @@ func relayProcessBufferLine(b *buffer, m *RelayEventDataBufferLine) { // Initial sync: skip all other processing, let highlights be. bc := bufferByName(bufferCurrent) if bc == nil { - b.lines = append(b.lines, line) + bufferPushLine(b, line) return } @@ -767,7 +794,7 @@ func relayProcessBufferLine(b *buffer, m *RelayEventDataBufferLine) { separate := display && !visible && bc.newMessages == 0 && bc.newUnimportantMessages == 0 - b.lines = append(b.lines, line) + bufferPushLine(b, line) if !(visible || m.LeakToActive) || b.newMessages != 0 || b.newUnimportantMessages != 0 { if line.isUnimportant || m.LeakToActive { @@ -780,7 +807,7 @@ func relayProcessBufferLine(b *buffer, m *RelayEventDataBufferLine) { if m.LeakToActive { leakedLine := line leakedLine.leaked = true - bc.lines = append(bc.lines, leakedLine) + bufferPushLine(bc, leakedLine) if !visible || bc.newMessages != 0 || bc.newUnimportantMessages != 0 { if line.isUnimportant { @@ -910,11 +937,11 @@ func relayProcessMessage(m *RelayEventMessage) { b.bufferName = data.New - refreshBufferList() if data.BufferName == bufferCurrent { bufferCurrent = data.New refreshStatus() } + refreshBufferList() if data.BufferName == bufferLast { bufferLast = data.New } @@ -1311,7 +1338,8 @@ func (e *inputEntry) SetText(text string) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type logEntry struct { - // XXX: Sadly, we can't seem to make it read-only in any way. + // XXX: Sadly, we can't seem to make it actually read-only. + // https://github.com/fyne-io/fyne/issues/5263 widget.Entry } @@ -1323,6 +1351,12 @@ func newLogEntry() *logEntry { return e } +func (e *logEntry) SetText(text string) { + e.OnChanged = nil + e.Entry.SetText(text) + e.OnChanged = func(string) { e.Entry.SetText(text) } +} + func (e *logEntry) AcceptsTab() bool { return false } @@ -1356,6 +1390,9 @@ func (l *customLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { } if toBottom { bufferScrollToBottom() + } else { + recheckHighlighted() + refreshStatus() } } @@ -1472,16 +1509,14 @@ func main() { a := app.New() a.Settings().SetTheme(&customTheme{}) + a.SetIcon(resourceIconNormal) wWindow = a.NewWindow(projectName) wWindow.Resize(fyne.NewSize(640, 480)) a.Lifecycle().SetOnEnteredForeground(func() { // TODO(p): Does this need locking? inForeground = true - if b := bufferByName(bufferCurrent); b != nil { - b.highlighted = false - refreshIcon() - } + recheckHighlighted() }) a.Lifecycle().SetOnExitedForeground(func() { inForeground = false @@ -1522,7 +1557,10 @@ func main() { wRichText = widget.NewRichText() wRichText.Wrapping = fyne.TextWrapWord wRichScroll = container.NewVScroll(wRichText) - wRichScroll.OnScrolled = func(position fyne.Position) { refreshStatus() } + wRichScroll.OnScrolled = func(position fyne.Position) { + recheckHighlighted() + refreshStatus() + } wLog = newLogEntry() wLog.Wrapping = fyne.TextWrapWord wLog.Hide() |