diff options
| author | citrons <citrons@mondecitronne.com> | 2025-06-07 14:57:04 -0500 |
|---|---|---|
| committer | citrons <citrons@mondecitronne.com> | 2025-06-07 16:02:18 -0500 |
| commit | 855e61c53c8a401c6f0be84a63808cb94cb19903 (patch) | |
| tree | 5f03c5357cf6aa75db05376cf6a42cc67d1e33c8 | |
| parent | 553ebc26cda61b567418205f7ee60be122b3c84f (diff) | |
channel list scrolling
| -rw-r--r-- | client/application.go | 16 | ||||
| -rw-r--r-- | client/buffer/buffer.go | 3 | ||||
| -rw-r--r-- | client/channel_list.go | 44 | ||||
| -rw-r--r-- | client/ui.go | 9 | ||||
| -rw-r--r-- | tui/layout.go | 38 | ||||
| -rw-r--r-- | tui/scroll_state.go | 43 |
6 files changed, 88 insertions, 65 deletions
diff --git a/client/application.go b/client/application.go index b1fbf5b..f77e0e1 100644 --- a/client/application.go +++ b/client/application.go @@ -4,6 +4,7 @@ import ( "citrons.xyz/talk/client/client" "citrons.xyz/talk/client/object" "citrons.xyz/talk/client/window" + "citrons.xyz/talk/tui" "citrons.xyz/talk/proto" ) @@ -19,6 +20,7 @@ type application struct { currentWindow window.Location windowHist []window.Location channelList channelList + channelScroll tui.ScrollState redraw bool cmdWindow cmdWindow prompts []window.Prompt @@ -209,9 +211,7 @@ func (a *application) join(channelName string) { a.Request(proto.NewCmd("join", ch.Id), func(response proto.Command) { switch response.Kind { case "ok": - a.channelList.add(channelName, channelLocation {id: ch.Id}) - a.goTo(channelLocation {id: ch.Id}) - + a.newChannel(*ch) w := a.windowCache.Get(channelLocation {id: ch.Id}) switch w.(type) { case *channelWindow: @@ -233,9 +233,7 @@ func (a *application) createChannel(name string) { switch response.Kind { case "create": if len(response.Args) > 0 { - ch := response.Args[0] - a.channelList.add(ch.Fields[""], channelLocation {id: ch.Id}) - a.goTo(channelLocation {id: ch.Id}) + a.newChannel(response.Args[0]) } case "fail": if len(response.Args) > 0 { @@ -246,6 +244,12 @@ func (a *application) createChannel(name string) { }) } +func (a *application) newChannel(ch proto.Object) { + a.channelList.add(ch.Fields[""], channelLocation {id: ch.Id}) + a.channelScroll.Set(0) + a.goTo(channelLocation {id: ch.Id}) +} + func (a *application) getNick() string { if !a.authenticated { return "" diff --git a/client/buffer/buffer.go b/client/buffer/buffer.go index 9750932..b7e79e9 100644 --- a/client/buffer/buffer.go +++ b/client/buffer/buffer.go @@ -94,10 +94,11 @@ func (b *Buffer) AtTop() bool { } func (b *Buffer) Show(id string) (atTop bool) { - tui.Push(id, tui.Box { + mouse := tui.Push(id, tui.Box { Width: tui.Fill, Height: tui.Fill, Dir: tui.Up, Overflow: true, Style: &tui.Style {Fg: tui.White, Bg: 232}, Scroll: &b.scroll, }) + b.scroll.ByMouse(mouse, true) defer tui.Pop() for m := b.bottom; m != nil; m = m.prev { diff --git a/client/channel_list.go b/client/channel_list.go index 6ac2141..f7413fd 100644 --- a/client/channel_list.go +++ b/client/channel_list.go @@ -52,9 +52,9 @@ func (cl *channelList) remove(location channelLocation) { } } -func (cl *channelList) traverse(direction int) { +func (cl *channelList) traverse(direction int) int { if len(*cl) == 0 { - return + return 0 } var i int @@ -73,6 +73,7 @@ func (cl *channelList) traverse(direction int) { } } globalApp.goTo((*cl)[i].location) + return i } func (cl *channelList) add(name string, location channelLocation) { @@ -81,8 +82,11 @@ func (cl *channelList) add(name string, location channelLocation) { *cl = append([]channelListEntry {entry}, *cl...) } -func (cl *channelList) show() { - mouse := tui.Push("channel list", tui.Box {Width: 12, Height: tui.Fill}) +func (cl *channelList) show(scroll *tui.ScrollState) { + mouse := tui.Push("channel list", tui.Box { + Width: 12, Height: tui.Fill, Overflow: true, Scroll: scroll, + }) + scroll.ByMouse(mouse, false) for i, entry := range *cl { var style *tui.Style if entry.location == globalApp.currentWindow { @@ -95,20 +99,22 @@ func (cl *channelList) show() { Width: tui.Fill, Height: 1, NoWrap: true, Style: style, }) - if mouse.Pressed { - globalApp.redraw = true - entry.clicked = true - } - if mouse.Released { - globalApp.redraw = true - if entry.clicked { - globalApp.goTo(entry.location) - } else { - for j, entry2 := range *cl { - if entry2.clicked { - entry2.clicked = false - (*cl)[j] = entry - entry = entry2 + if mouse.Button == 0 { + if mouse.Pressed { + globalApp.redraw = true + entry.clicked = true + } + if mouse.Released { + globalApp.redraw = true + if entry.clicked { + globalApp.goTo(entry.location) + } else { + for j, entry2 := range *cl { + if entry2.clicked { + entry2.clicked = false + (*cl)[j] = entry + entry = entry2 + } } } } @@ -124,7 +130,7 @@ func (cl *channelList) show() { (*cl)[i] = entry } - if mouse.ReleasedAnywhere { + if mouse.Button == 0 && mouse.ReleasedAnywhere { for i, entry := range *cl { globalApp.redraw = globalApp.redraw || entry.clicked entry.clicked = false diff --git a/client/ui.go b/client/ui.go index ab5e190..d3692ce 100644 --- a/client/ui.go +++ b/client/ui.go @@ -58,7 +58,6 @@ func (a *application) onInput(ev tui.Event) { } buf := win.Buffer() - buf.Scroll(-ev.Mouse.Scroll * 5) scroll := tui.Size().Height - 5 switch ev.Key { @@ -96,9 +95,11 @@ func (a *application) onInput(ev tui.Event) { } case keys.Up | keys.Alt: - a.channelList.traverse(-1) + index := a.channelList.traverse(-1) + a.channelScroll.Set(index - 5) case keys.Down | keys.Alt: - a.channelList.traverse(1) + index := a.channelList.traverse(1) + a.channelScroll.Set(index - 5) case 'p' | keys.Ctrl: a.traverseHistory(-1) @@ -196,7 +197,7 @@ func (a *application) show() { Dir: tui.Right, }) - a.channelList.show() + a.channelList.show(&a.channelScroll) tui.Push("border", tui.Box {Width: 1, Height: tui.Fill}) tui.Text(strings.Repeat("│", s.Height), nil) tui.Pop() diff --git a/tui/layout.go b/tui/layout.go index 1835d72..ede0fa6 100644 --- a/tui/layout.go +++ b/tui/layout.go @@ -43,37 +43,8 @@ type textRun struct { hasCursor bool } -type ScrollState struct { - at string - offset int - absolute int - atFirst bool - atLast bool -} - var Selected string -func (s *ScrollState) ToStart() { - *s = ScrollState {} -} - -func (s *ScrollState) AtFirst() bool { - return s.atFirst -} - -func (s *ScrollState) AtLast() bool { - return s.atLast -} - -func (s *ScrollState) Scroll(amnt int) { - s.offset += amnt - s.absolute += amnt -} - -func (s *ScrollState) Get() int { - return s.absolute -} - var layout struct { front map[string]*Box back map[string]*Box @@ -319,12 +290,7 @@ func (b *Box) computePositions(axis int) { if b.Dir.reverse() { p = b.computedSize[axis] - p } - b.Scroll.absolute = p - if !b.Dir.reverse() { - b.Scroll.absolute += b.Scroll.offset - } else { - b.Scroll.absolute += b.Scroll.offset - } + b.Scroll.absolute = p + b.Scroll.offset } if !b.Dir.reverse() { @@ -467,10 +433,12 @@ func (b *Box) mouseEvents(ev MouseEvent) { bev.Y -= b.computedRect.min[1] bev.Pressed = false bev.Released = false + bev.Scroll = 0 if bev.X >= 0 && bev.Y >= 0 && bev.X < b.computedSize[0] && bev.Y < b.computedSize[1] { bev.Pressed = ev.Pressed bev.Released = ev.Released + bev.Scroll = ev.Scroll } b.mouseEvent = bev for _, c := range b.children { diff --git a/tui/scroll_state.go b/tui/scroll_state.go new file mode 100644 index 0000000..75797b1 --- /dev/null +++ b/tui/scroll_state.go @@ -0,0 +1,43 @@ +package tui + +type ScrollState struct { + at string + offset int + absolute int + atFirst bool + atLast bool +} + +func (s *ScrollState) ToStart() { + *s = ScrollState {} +} + +func (s *ScrollState) AtFirst() bool { + return s.atFirst +} + +func (s *ScrollState) AtLast() bool { + return s.atLast +} + +func (s *ScrollState) Scroll(amnt int) { + s.offset += amnt + s.absolute += amnt +} + +func (s *ScrollState) ByMouse(ev MouseEvent, reverse bool) { + scroll := ev.Scroll * 5 + if reverse { + scroll *= -1 + } + s.Scroll(scroll) +} + +func (s *ScrollState) Get() int { + return s.absolute +} + +func (s *ScrollState) Set(amnt int) { + s.at = "" + s.absolute = amnt +} |
