From c5ec94a78f712332dcbe8002d2d1ae9bd288a2c2 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Mon, 30 Apr 2018 12:40:28 +0300 Subject: Add mouse scrolling support to room list (ref #34) --- ui/room-list.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++------ ui/view-main.go | 57 ++++++++++++++++++++-------------- 2 files changed, 118 insertions(+), 33 deletions(-) (limited to 'ui') diff --git a/ui/room-list.go b/ui/room-list.go index 1cb71c9..3a43872 100644 --- a/ui/room-list.go +++ b/ui/room-list.go @@ -46,6 +46,8 @@ type RoomList struct { selected *rooms.Room selectedTag string + scrollOffset int + // The item main text color. mainTextColor tcell.Color // The text color for selected items. @@ -60,6 +62,8 @@ func NewRoomList() *RoomList { items: make(map[string][]*rooms.Room), tags: []string{"m.favourite", "net.maunium.gomuks.fake.direct", "", "m.lowpriority"}, + scrollOffset: 0, + mainTextColor: tcell.ColorWhite, selectedTextColor: tcell.ColorWhite, selectedBackgroundColor: tcell.ColorDarkGreen, @@ -217,6 +221,12 @@ func (list *RoomList) Clear() { func (list *RoomList) SetSelected(tag string, room *rooms.Room) { list.selected = room list.selectedTag = tag + pos := list.index(tag, room) + _, _, _, height := list.GetRect() + if pos < list.scrollOffset || pos > list.scrollOffset+height { + // TODO this does weird stuff sometimes, needs to be fixed + //list.scrollOffset = pos + } debug.Print("Selecting", room.GetTitle(), "in", list.GetTagDisplayName(tag)) } @@ -232,6 +242,18 @@ func (list *RoomList) SelectedRoom() *rooms.Room { return list.selected } +func (list *RoomList) AddScrollOffset(offset int) { + list.scrollOffset += offset + if list.scrollOffset < 0 { + list.scrollOffset = 0 + } + _, _, _, viewHeight := list.GetRect() + contentHeight := list.ContentHeight() + if list.scrollOffset > contentHeight-viewHeight { + list.scrollOffset = contentHeight - viewHeight + } +} + func (list *RoomList) First() (string, *rooms.Room) { for _, tag := range list.tags { items := list.items[tag] @@ -326,7 +348,52 @@ func (list *RoomList) indexInTag(tag string, room *rooms.Room) int { return roomIndex } +func (list *RoomList) index(tag string, room *rooms.Room) int { + tagIndex := list.IndexTag(tag) + if tagIndex == -1 { + return -1 + } + + localIndex := list.indexInTag(tag, room) + if localIndex == -1 { + return -1 + } + + // Tag header + localIndex += 1 + + if tagIndex > 0 { + for i := 0; i < tagIndex; i++ { + previousTag := list.tags[i] + previousItems := list.items[previousTag] + + tagDisplayName := list.GetTagDisplayName(previousTag) + if len(tagDisplayName) > 0 { + // Previous tag header + space + localIndex += 2 + // Previous tag items + localIndex += len(previousItems) + } + } + } + + return localIndex +} + +func (list *RoomList) ContentHeight() (height int) { + for _, tag := range list.tags { + items := list.items[tag] + tagDisplayName := list.GetTagDisplayName(tag) + if len(tagDisplayName) == 0 { + continue + } + height += 2 + len(items) + } + return +} + func (list *RoomList) Get(n int) (string, *rooms.Room) { + n += list.scrollOffset if n < 0 { return "", nil } @@ -377,12 +444,7 @@ func (list *RoomList) Draw(screen tcell.Screen) { x, y, width, height := list.GetInnerRect() bottomLimit := y + height - var offset int - /* TODO fix offset - currentItemIndex := list.Index(list.selected) - if currentItemIndex >= height { - offset = currentItemIndex + 1 - height - }*/ + handledOffset := 0 // Draw the list items. for _, tag := range list.tags { @@ -392,20 +454,32 @@ func (list *RoomList) Draw(screen tcell.Screen) { continue } + localOffset := 0 + + if handledOffset < list.scrollOffset { + if handledOffset+len(items) < list.scrollOffset { + handledOffset += len(items) + 2 + continue + } else { + localOffset = list.scrollOffset - handledOffset + handledOffset += localOffset + } + } + widget.WriteLine(screen, tview.AlignLeft, tagDisplayName, x, y, width, tcell.StyleDefault.Underline(true).Bold(true)) y++ for i := len(items) - 1; i >= 0; i-- { item := items[i] index := len(items) - 1 - i - if index < offset { - continue - } - if y >= bottomLimit { break } + if index < localOffset { + continue + } + text := item.GetTitle() lineWidth := width diff --git a/ui/view-main.go b/ui/view-main.go index 4b01829..b7bbf6d 100644 --- a/ui/view-main.go +++ b/ui/view-main.go @@ -213,39 +213,47 @@ func (view *MainView) MouseEventHandler(roomView *RoomView, event *tcell.EventMo msgView := roomView.MessageView() x, y := event.Position() - switch event.Buttons() { - case tcell.WheelUp: - if msgView.IsAtTop() { - go view.LoadHistory(roomView.Room.ID) - } else { - msgView.AddScrollOffset(WheelScrollOffsetDiff) + switch { + case isInArea(x, y, msgView): + mx, my, _, _ := msgView.GetRect() + switch event.Buttons() { + case tcell.WheelUp: + if msgView.IsAtTop() { + go view.LoadHistory(roomView.Room.ID) + } else { + msgView.AddScrollOffset(WheelScrollOffsetDiff) - view.parent.Render() - } - case tcell.WheelDown: - msgView.AddScrollOffset(-WheelScrollOffsetDiff) + view.parent.Render() + } + case tcell.WheelDown: + msgView.AddScrollOffset(-WheelScrollOffsetDiff) - view.parent.Render() + view.parent.Render() - if msgView.ScrollOffset == 0 { - roomView.Room.MarkRead() - } - default: - if isInArea(x, y, msgView) { - mx, my, _, _ := msgView.GetRect() + if msgView.ScrollOffset == 0 { + roomView.Room.MarkRead() + } + default: if msgView.HandleClick(x-mx, y-my, event.Buttons()) { view.parent.Render() } - } else if isInArea(x, y, view.roomList) && event.Buttons() == tcell.Button1 { + } + case isInArea(x, y, view.roomList): + switch event.Buttons() { + case tcell.WheelUp: + view.roomList.AddScrollOffset(-WheelScrollOffsetDiff) + view.parent.Render() + case tcell.WheelDown: + view.roomList.AddScrollOffset(WheelScrollOffsetDiff) + view.parent.Render() + case tcell.Button1: _, rly, _, _ := msgView.GetRect() n := y - rly + 1 view.SwitchRoom(view.roomList.Get(n)) - } else { - debug.Print("Unhandled mouse event:", event.Buttons(), event.Modifiers(), x, y) } - return event + default: + debug.Print("Unhandled mouse event:", event.Buttons(), event.Modifiers(), x, y) } - return event } @@ -305,7 +313,10 @@ func (view *MainView) GetRoom(roomID string) ifc.RoomView { room, ok := view.rooms[roomID] if !ok { view.AddRoom(roomID) - room, _ := view.rooms[roomID] + room, ok := view.rooms[roomID] + if !ok { + return nil + } return room } return room -- cgit v1.2.3