From 5f29781005e9fe9373ce2a46b1e202636752882f Mon Sep 17 00:00:00 2001 From: aurc <54873456+aurc@users.noreply.github.com> Date: Wed, 17 Aug 2022 20:42:39 +1000 Subject: [PATCH] Added support for natural mouse selection (ctrl+n) --- internal/loggo/app_scaffold.go | 2 +- internal/loggo/log_view.go | 4 +- internal/loggo/log_view_key_events.go | 3 ++ internal/loggo/log_view_nav_menu.go | 72 +++++++++++++++++++++------ internal/uitest/helper/json_gen.go | 14 ++++-- 5 files changed, 72 insertions(+), 23 deletions(-) diff --git a/internal/loggo/app_scaffold.go b/internal/loggo/app_scaffold.go index 2dfa80c..a1db309 100644 --- a/internal/loggo/app_scaffold.go +++ b/internal/loggo/app_scaffold.go @@ -109,7 +109,7 @@ func (a *appScaffold) ShowPopMessage(text string, waitSecs int64, resetFocusTo t mainContent.SetBackgroundColor(tcell.ColorDarkBlue).SetBorderPadding(0, 0, 2, 2) modal.AddItem(mainContent, 0, 1, false) modal.AddItem(countdownText, 1, 1, false) - a.ShowModal(modal, len(text)/2, 5, tcell.ColorDarkBlue, nil) + a.ShowModal(modal, int(float64(len(text))/1.3), 5, tcell.ColorDarkBlue, nil) countdownText.SetTextColor(tcell.ColorLightGrey).SetBackgroundColor(tcell.ColorDarkBlue) go func() { for i := waitSecs; i >= 0; i-- { diff --git a/internal/loggo/log_view.go b/internal/loggo/log_view.go index 3968a1f..a2048c1 100644 --- a/internal/loggo/log_view.go +++ b/internal/loggo/log_view.go @@ -64,6 +64,8 @@ type LogView struct { isFollowing bool hideFilter bool rebufferFilter bool + selectionEnabled bool + mouseSel *tview.TextView } func NewLogReader(app *LoggoApp, reader reader.Reader) *LogView { @@ -237,7 +239,7 @@ func (l *LogView) toggleFilter() { func (l *LogView) makeLayouts() { mainContent := tview.NewFlex().SetDirection(tview.FlexColumn). AddItem(l.table, 0, 2, true). - AddItem(l.navMenu, 24, 1, false) + AddItem(l.navMenu, 26, 1, false) l.Flex.Clear().SetDirection(tview.FlexRow) if !l.hideFilter { diff --git a/internal/loggo/log_view_key_events.go b/internal/loggo/log_view_key_events.go index d671646..a2afe2b 100644 --- a/internal/loggo/log_view_key_events.go +++ b/internal/loggo/log_view_key_events.go @@ -35,6 +35,9 @@ func (l *LogView) keyEvents() { return l.app.inputCapture(event) } switch event.Key() { + case tcell.KeyCtrlN: + l.toggleSelectionMouse() + return nil case tcell.KeyCtrlA: go func() { l.showAbout() diff --git a/internal/loggo/log_view_nav_menu.go b/internal/loggo/log_view_nav_menu.go index 91dae77..944733e 100644 --- a/internal/loggo/log_view_nav_menu.go +++ b/internal/loggo/log_view_nav_menu.go @@ -31,7 +31,30 @@ import ( "github.com/rivo/tview" ) +const ( + selectionMouseEnabledMenu = `[yellow::b] ^n [-::u]["1"]Enable Selection[""]` + selectionMouseDisabledMenu = `[yellow::b] ^n [-::u]["1"]Enable Mouse[""]` + templateMenu = `[yellow::b] ^t [-::u]["1"]Template[""]` + localFilterMenu = `[yellow::b] : [-::u]["1"]Local Filter[""]` + viewEntryMenu = `[yellow::b] Enter[-::-] View Entry` + navigateMenu = `[yellow::b] ↓ ← ↑ →[-::-] Navigate` + goTopMenu = `[yellow::b] g [-::u]["1"]Top[""]` + goBottomMenu = `[yellow::b] G [-::u]["1"]Bottom[""]` + pageUpMenu = `[yellow::b] ^b [-::u]["1"]Pg Up[""]` + pageDownMenu = `[yellow::b] ^f [-::u]["1"]Pg Down[""]` + mouseHoMenu = `[yellow::b] ⌥ 🖱 [-::-]Horizontal` + mouseVeMenu = `[yellow::b] ⌥ ⌘ 🖱 [-::-]Vertical` + aboutMenu = `[yellow::b] ^a [-::u]["1"]About[""]` + quitMenu = `[yellow::b] ^c [-::u]["1"]Quit[""]` + autoScrollOnMenu = `[yellow::b] ^Space [-::u]["1"]Auto-Scroll[::-] [green::bi]ON[-::-][""]` + autoScrollOffMenu = `[yellow::b] ^Space [-::u]["1"]Auto-Scroll[::-] [red::bi]OFF[-::-][""]` +) + func (l *LogView) populateMenu() { + l.mouseSel = tview.NewTextView(). + SetDynamicColors(true).SetRegions(true). + SetText(selectionMouseEnabledMenu) + l.navMenu = tview.NewFlex().SetDirection(tview.FlexRow) l.navMenu. SetBackgroundColor(color.ColorBackgroundField).SetBorderPadding(0, 0, 0, 0) @@ -45,7 +68,7 @@ func (l *LogView) populateMenu() { AddItem(l.followingView, 1, 2, false). AddItem(l.textViewMenuControl(tview.NewTextView(). SetDynamicColors(true).SetRegions(true). - SetText(`[yellow::b] ^t [-::u]["1"]Template[""]`), func() { + SetText(templateMenu), func() { if l.isTemplateViewShown() { // TODO: Find a reliable way to respond to external closure } else { @@ -54,7 +77,7 @@ func (l *LogView) populateMenu() { }), 1, 2, false). AddItem(l.textViewMenuControl(tview.NewTextView(). SetDynamicColors(true).SetRegions(true). - SetText(`[yellow::b] : [-::u]["1"]Local Filter[""]`), func() { + SetText(localFilterMenu), func() { l.toggleFilter() }), 1, 2, false). ////////////////////////////////////////////////////////////////// @@ -64,13 +87,13 @@ func (l *LogView) populateMenu() { NewHorizontalSeparator(sepStyle, LineHThick, "Navigation", sepForeground), 1, 2, false). AddItem(tview.NewTextView(). SetDynamicColors(true). - SetText("[yellow::b] Enter[-::-] View Entry"), 1, 3, false). + SetText(viewEntryMenu), 1, 3, false). AddItem(tview.NewTextView(). SetDynamicColors(true). - SetText("[yellow::b] ↓ ↑ ← →[-::-] Navigate"), 1, 3, false). + SetText(navigateMenu), 1, 3, false). AddItem(l.textViewMenuControl(tview.NewTextView(). SetDynamicColors(true).SetRegions(true). - SetText(`[yellow::b] g [-::u]["1"]Top[""]`), func() { + SetText(goTopMenu), func() { l.isFollowing = false l.table.ScrollToBeginning() if len(l.inSlice) > 1 { @@ -79,35 +102,37 @@ func (l *LogView) populateMenu() { }), 1, 1, false). AddItem(l.textViewMenuControl(tview.NewTextView(). SetDynamicColors(true).SetRegions(true). - SetText(`[yellow::b] G [-::u]["1"]Bottom[""]`), func() { + SetText(goBottomMenu), func() { l.isFollowing = false l.table.ScrollToEnd() go l.table.Select(len(l.inSlice), 0) }), 1, 2, false). AddItem(l.textViewMenuControl(tview.NewTextView(). SetDynamicColors(true).SetRegions(true). - SetText(`[yellow::b] ^b [-::u]["1"]Pg Up[""]`), func() { + SetText(pageUpMenu), func() { l.isFollowing = false l.table.InputHandler()(tcell.NewEventKey(tcell.KeyPgUp, '0', 0), func(p tview.Primitive) {}) }), 1, 2, false). AddItem(l.textViewMenuControl(tview.NewTextView(). SetDynamicColors(true).SetRegions(true). - SetText(`[yellow::b] ^f [-::u]["1"]Pg Down[""]`), func() { + SetText(pageDownMenu), func() { l.isFollowing = false l.table.InputHandler()(tcell.NewEventKey(tcell.KeyPgDn, '0', 0), func(p tview.Primitive) {}) }), 1, 2, false) ////////////////////////////////////////////////////////////////// // Selection Menu ////////////////////////////////////////////////////////////////// + l.navMenu. + AddItem(NewHorizontalSeparator(sepStyle, LineHThick, "Selection", sepForeground), 1, 2, false). + AddItem(l.textViewMenuControl(l.mouseSel, l.toggleSelectionMouse), 1, 2, false) if runtime.GOOS != "windows" { l.navMenu. - AddItem(NewHorizontalSeparator(sepStyle, LineHThick, "Selection", sepForeground), 1, 2, false). AddItem(tview.NewTextView(). SetDynamicColors(true). - SetText("[yellow::b] ⌥ 🖱 [-::-] Horizontal"), 1, 3, false). + SetText(mouseHoMenu), 1, 3, false). AddItem(tview.NewTextView(). SetDynamicColors(true). - SetText("[yellow::b] ⌥ ⌘ 🖱 [-::-] Vertical"), 1, 3, false) + SetText(mouseVeMenu), 1, 3, false) } ////////////////////////////////////////////////////////////////// // Application Menu @@ -116,14 +141,14 @@ func (l *LogView) populateMenu() { AddItem(NewHorizontalSeparator(sepStyle, LineHThick, "Application", sepForeground), 1, 2, false). AddItem(l.textViewMenuControl(tview.NewTextView(). SetDynamicColors(true).SetRegions(true). - SetText(`[yellow::b] ^a [-::u]["1"]About[""]`), func() { + SetText(aboutMenu), func() { go func() { l.showAbout() }() }), 1, 2, false). AddItem(l.textViewMenuControl(tview.NewTextView().SetRegions(true). SetDynamicColors(true). - SetText(`[yellow::b] ^c [-::u]["1"]Quit[""]`), func() { + SetText(quitMenu), func() { l.app.Stop() }), 1, 1, false). AddItem(NewHorizontalSeparator(sepStyle, LineHThick, "", sepForeground), 1, 2, false). @@ -167,7 +192,7 @@ func (l *LogView) updateBottomBarMenu() { l.mainMenu. AddItem(l.textViewMenuControl(tview.NewTextView().SetRegions(true). SetDynamicColors(true). - SetText(`[yellow::b](^C) [-::u]["1"]Quit[""]`), func() { + SetText(`[yellow::b](^c) [-::u]["1"]Quit[""]`), func() { l.app.Stop() }), 0, 2, false). AddItem(l.linesView, 0, 3, false) @@ -211,8 +236,23 @@ func (l *LogView) updateLineView() { l.globalCount)) } if l.isFollowing { - l.followingView.SetText(`[yellow::b] ^Space [-::u]["1"]Auto-Scroll[::-] [green::bi]ON[-::-][""]`) + l.followingView.SetText(autoScrollOnMenu) } else { - l.followingView.SetText(`[yellow::b] ^Space [-::u]["1"]Auto-Scroll[::-] [red::bi]OFF[-::-][""]`) + l.followingView.SetText(autoScrollOffMenu) } } + +func (l *LogView) toggleSelectionMouse() { + l.selectionEnabled = !l.selectionEnabled + l.app.app.EnableMouse(!l.selectionEnabled) + go func() { + if l.selectionEnabled { + l.app.ShowPopMessage("Mouse disabled! Click and drag to select...", 2, l.table) + l.mouseSel.SetText(selectionMouseDisabledMenu) + } else { + l.app.ShowPopMessage("Selection disabled! Mouse input active...", 2, l.table) + l.mouseSel.SetText(selectionMouseEnabledMenu) + } + l.app.Draw() + }() +} diff --git a/internal/uitest/helper/json_gen.go b/internal/uitest/helper/json_gen.go index 0cc5e90..0c3ffaf 100644 --- a/internal/uitest/helper/json_gen.go +++ b/internal/uitest/helper/json_gen.go @@ -42,11 +42,11 @@ func JsonGenerator(writer io.Writer) { _ = json.Unmarshal(b, &jm) i := 0 for { - if i != 0 && i%(rand.Intn(27)+1) == 0 { - _, _ = fmt.Fprintln(writer, "bad json") - i++ - continue - } + //if i != 0 && i%(rand.Intn(27)+1) == 0 { + // _, _ = fmt.Fprintln(writer, "bad json") + // i++ + // continue + //} i++ uid1 := uuid.New().String() uid2 := uuid.New().String() @@ -59,5 +59,9 @@ func JsonGenerator(writer io.Writer) { b, _ = json.Marshal(jm) _, _ = fmt.Fprintln(writer, string(b)) time.Sleep(time.Millisecond * time.Duration(rand.Intn(800))) + if i%(rand.Intn(5)+1) == 0 { + time.Sleep(time.Second * time.Duration(rand.Intn(5))) + } + } }