xA/xW: dehighlight current buffer appropriately
This commit is contained in:
parent
977b073b58
commit
cd76702ab2
150
xA/xA.go
150
xA/xA.go
@ -363,61 +363,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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// --- 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
|
||||
@ -432,22 +377,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) {
|
||||
@ -515,6 +469,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{} }
|
||||
@ -756,6 +767,7 @@ func refreshBuffer(b *buffer) {
|
||||
bufferPrintAndWatchTrailingDateChanges()
|
||||
wRichText.Refresh()
|
||||
bufferScrollToBottom()
|
||||
recheckHighlighted()
|
||||
}
|
||||
|
||||
// --- Event processing --------------------------------------------------------
|
||||
@ -1374,6 +1386,9 @@ func (l *customLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) {
|
||||
}
|
||||
if toBottom {
|
||||
bufferScrollToBottom()
|
||||
} else {
|
||||
recheckHighlighted()
|
||||
refreshStatus()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1497,11 +1512,7 @@ func main() {
|
||||
a.Lifecycle().SetOnEnteredForeground(func() {
|
||||
// TODO(p): Does this need locking?
|
||||
inForeground = true
|
||||
if b := bufferByName(bufferCurrent); b != nil {
|
||||
b.highlighted = false
|
||||
refreshIcon()
|
||||
refreshBufferList()
|
||||
}
|
||||
recheckHighlighted()
|
||||
})
|
||||
a.Lifecycle().SetOnExitedForeground(func() {
|
||||
inForeground = false
|
||||
@ -1542,7 +1553,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()
|
||||
|
175
xW/xW.cpp
175
xW/xW.cpp
@ -255,73 +255,6 @@ buffer_by_name(const std::wstring &name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_activate(const std::wstring &name)
|
||||
{
|
||||
auto activate = new Relay::CommandData_BufferActivate();
|
||||
activate->buffer_name = name;
|
||||
relay_send(activate);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_toggle_unimportant(const std::wstring &name)
|
||||
{
|
||||
auto toggle = new Relay::CommandData_BufferToggleUnimportant();
|
||||
toggle->buffer_name = name;
|
||||
relay_send(toggle);
|
||||
}
|
||||
|
||||
// --- Current buffer ----------------------------------------------------------
|
||||
|
||||
static void
|
||||
buffer_toggle_log(
|
||||
const std::wstring &error, const Relay::ResponseData_BufferLog *response)
|
||||
{
|
||||
if (!response) {
|
||||
show_error_message(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring log;
|
||||
if (!LibertyXDR::utf8_to_wstring(
|
||||
response->log.data(), response->log.size(), log)) {
|
||||
show_error_message(L"Invalid encoding.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring filtered;
|
||||
for (auto wch : log) {
|
||||
if (wch == L'\n')
|
||||
filtered += L"\r\n";
|
||||
else
|
||||
filtered += wch;
|
||||
}
|
||||
|
||||
SetWindowText(g.hwndBufferLog, filtered.c_str());
|
||||
ShowWindow(g.hwndBuffer, SW_HIDE);
|
||||
ShowWindow(g.hwndBufferLog, SW_SHOW);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_toggle_log()
|
||||
{
|
||||
if (IsWindowVisible(g.hwndBufferLog)) {
|
||||
ShowWindow(g.hwndBufferLog, SW_HIDE);
|
||||
ShowWindow(g.hwndBuffer, SW_SHOW);
|
||||
SetWindowText(g.hwndBufferLog, L"");
|
||||
return;
|
||||
}
|
||||
|
||||
auto log = new Relay::CommandData_BufferLog();
|
||||
log->buffer_name = g.buffer_current;
|
||||
relay_send(log, [name = g.buffer_current](auto error, auto response) {
|
||||
if (g.buffer_current != name)
|
||||
return;
|
||||
buffer_toggle_log(error,
|
||||
dynamic_cast<const Relay::ResponseData_BufferLog *>(response));
|
||||
});
|
||||
}
|
||||
|
||||
static bool
|
||||
buffer_at_bottom()
|
||||
{
|
||||
@ -354,6 +287,7 @@ refresh_icon()
|
||||
if (b.highlighted)
|
||||
icon = g.hiconHighlighted;
|
||||
|
||||
// XXX: This may not change the taskbar icon.
|
||||
SendMessage(g.hwndMain, WM_SETICON, ICON_SMALL, (LPARAM) icon);
|
||||
SendMessage(g.hwndMain, WM_SETICON, ICON_BIG, (LPARAM) icon);
|
||||
}
|
||||
@ -430,6 +364,88 @@ refresh_status()
|
||||
SetWindowText(g.hwndStatus, status.c_str());
|
||||
}
|
||||
|
||||
static void
|
||||
recheck_highlighted()
|
||||
{
|
||||
// Corresponds to the logic toggling the bool on.
|
||||
auto b = buffer_by_name(g.buffer_current);
|
||||
if (b && b->highlighted && buffer_at_bottom() &&
|
||||
!IsIconic(g.hwndMain) && !IsWindowVisible(g.hwndBufferLog)) {
|
||||
b->highlighted = false;
|
||||
refresh_icon();
|
||||
refresh_buffer_list();
|
||||
}
|
||||
}
|
||||
|
||||
// --- Buffer actions ----------------------------------------------------------
|
||||
|
||||
static void
|
||||
buffer_activate(const std::wstring &name)
|
||||
{
|
||||
auto activate = new Relay::CommandData_BufferActivate();
|
||||
activate->buffer_name = name;
|
||||
relay_send(activate);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_toggle_unimportant(const std::wstring &name)
|
||||
{
|
||||
auto toggle = new Relay::CommandData_BufferToggleUnimportant();
|
||||
toggle->buffer_name = name;
|
||||
relay_send(toggle);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_toggle_log(
|
||||
const std::wstring &error, const Relay::ResponseData_BufferLog *response)
|
||||
{
|
||||
if (!response) {
|
||||
show_error_message(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring log;
|
||||
if (!LibertyXDR::utf8_to_wstring(
|
||||
response->log.data(), response->log.size(), log)) {
|
||||
show_error_message(L"Invalid encoding.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring filtered;
|
||||
for (auto wch : log) {
|
||||
if (wch == L'\n')
|
||||
filtered += L"\r\n";
|
||||
else
|
||||
filtered += wch;
|
||||
}
|
||||
|
||||
SetWindowText(g.hwndBufferLog, filtered.c_str());
|
||||
ShowWindow(g.hwndBuffer, SW_HIDE);
|
||||
ShowWindow(g.hwndBufferLog, SW_SHOW);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_toggle_log()
|
||||
{
|
||||
if (IsWindowVisible(g.hwndBufferLog)) {
|
||||
ShowWindow(g.hwndBufferLog, SW_HIDE);
|
||||
ShowWindow(g.hwndBuffer, SW_SHOW);
|
||||
SetWindowText(g.hwndBufferLog, L"");
|
||||
|
||||
recheck_highlighted();
|
||||
return;
|
||||
}
|
||||
|
||||
auto log = new Relay::CommandData_BufferLog();
|
||||
log->buffer_name = g.buffer_current;
|
||||
relay_send(log, [name = g.buffer_current](auto error, auto response) {
|
||||
if (g.buffer_current != name)
|
||||
return;
|
||||
buffer_toggle_log(error,
|
||||
dynamic_cast<const Relay::ResponseData_BufferLog *>(response));
|
||||
});
|
||||
}
|
||||
|
||||
// --- Rich Edit formatting ----------------------------------------------------
|
||||
|
||||
static COLORREF
|
||||
@ -728,6 +744,7 @@ refresh_buffer(const Buffer &b)
|
||||
|
||||
buffer_print_and_watch_trailing_date_changes();
|
||||
buffer_scroll_to_bottom();
|
||||
// We will get a scroll event, so no need to recheck_highlighted() here.
|
||||
|
||||
SendMessage(g.hwndBuffer, WM_SETREDRAW, (WPARAM) TRUE, 0);
|
||||
InvalidateRect(g.hwndBuffer, NULL, TRUE);
|
||||
@ -749,8 +766,9 @@ relay_process_buffer_line(Buffer &b, Relay::EventData_BufferLine &m)
|
||||
// Retained mode is complicated.
|
||||
bool display = (!m.is_unimportant || !bc->hide_unimportant) &&
|
||||
(b.buffer_name == g.buffer_current || m.leak_to_active);
|
||||
// XXX: It would be great if it didn't autoscroll when focused.
|
||||
bool to_bottom = display &&
|
||||
buffer_at_bottom();
|
||||
(buffer_at_bottom() || GetFocus() == g.hwndBuffer);
|
||||
bool visible = display &&
|
||||
to_bottom &&
|
||||
!IsIconic(g.hwndMain) &&
|
||||
@ -1465,6 +1483,7 @@ richedit_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
|
||||
{
|
||||
// Dragging the scrollbar doesn't result in EN_VSCROLL.
|
||||
LRESULT lResult = DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
||||
recheck_highlighted();
|
||||
refresh_status();
|
||||
return lResult;
|
||||
}
|
||||
@ -1522,8 +1541,12 @@ process_resize(UINT w, UINT h)
|
||||
MoveWindow(g.hwndBufferList, 3, top, 150, h - top - bottom, FALSE);
|
||||
MoveWindow(g.hwndBuffer, 156, top, w - 159, h - top - bottom, FALSE);
|
||||
MoveWindow(g.hwndBufferLog, 156, top, w - 159, h - top - bottom, FALSE);
|
||||
if (to_bottom)
|
||||
if (to_bottom) {
|
||||
buffer_scroll_to_bottom();
|
||||
} else {
|
||||
recheck_highlighted();
|
||||
refresh_status();
|
||||
}
|
||||
|
||||
InvalidateRect(g.hwndMain, NULL, TRUE);
|
||||
}
|
||||
@ -1685,8 +1708,10 @@ window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
}
|
||||
case WM_SYSCOMMAND:
|
||||
{
|
||||
// We're not deiconified yet, so duplicate recheck_highlighted().
|
||||
auto b = buffer_by_name(g.buffer_current);
|
||||
if (b && wParam == SC_RESTORE) {
|
||||
if (wParam == SC_RESTORE && b && b->highlighted && buffer_at_bottom() &&
|
||||
!IsWindowVisible(g.hwndBufferLog)) {
|
||||
b->highlighted = false;
|
||||
refresh_icon();
|
||||
}
|
||||
@ -1694,13 +1719,15 @@ window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
if (!lParam)
|
||||
if (!lParam) {
|
||||
process_accelerator(LOWORD(wParam));
|
||||
else if (lParam == (LPARAM) g.hwndBufferList)
|
||||
} else if (lParam == (LPARAM) g.hwndBufferList) {
|
||||
process_bufferlist_notification(HIWORD(wParam));
|
||||
else if (lParam == (LPARAM) g.hwndBuffer &&
|
||||
HIWORD(wParam) == EN_VSCROLL)
|
||||
} else if (lParam == (LPARAM) g.hwndBuffer &&
|
||||
HIWORD(wParam) == EN_VSCROLL) {
|
||||
recheck_highlighted();
|
||||
refresh_status();
|
||||
}
|
||||
return 0;
|
||||
case WM_NOTIFY:
|
||||
switch (((LPNMHDR) lParam)->code) {
|
||||
|
Loading…
Reference in New Issue
Block a user