Add mouse scrolling support to room list (ref #34)

This commit is contained in:
Tulir Asokan 2018-04-30 12:40:28 +03:00
parent d8dba100e0
commit c5ec94a78f
2 changed files with 118 additions and 33 deletions

View File

@ -46,6 +46,8 @@ type RoomList struct {
selected *rooms.Room selected *rooms.Room
selectedTag string selectedTag string
scrollOffset int
// The item main text color. // The item main text color.
mainTextColor tcell.Color mainTextColor tcell.Color
// The text color for selected items. // The text color for selected items.
@ -60,6 +62,8 @@ func NewRoomList() *RoomList {
items: make(map[string][]*rooms.Room), items: make(map[string][]*rooms.Room),
tags: []string{"m.favourite", "net.maunium.gomuks.fake.direct", "", "m.lowpriority"}, tags: []string{"m.favourite", "net.maunium.gomuks.fake.direct", "", "m.lowpriority"},
scrollOffset: 0,
mainTextColor: tcell.ColorWhite, mainTextColor: tcell.ColorWhite,
selectedTextColor: tcell.ColorWhite, selectedTextColor: tcell.ColorWhite,
selectedBackgroundColor: tcell.ColorDarkGreen, selectedBackgroundColor: tcell.ColorDarkGreen,
@ -217,6 +221,12 @@ func (list *RoomList) Clear() {
func (list *RoomList) SetSelected(tag string, room *rooms.Room) { func (list *RoomList) SetSelected(tag string, room *rooms.Room) {
list.selected = room list.selected = room
list.selectedTag = tag 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)) debug.Print("Selecting", room.GetTitle(), "in", list.GetTagDisplayName(tag))
} }
@ -232,6 +242,18 @@ func (list *RoomList) SelectedRoom() *rooms.Room {
return list.selected 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) { func (list *RoomList) First() (string, *rooms.Room) {
for _, tag := range list.tags { for _, tag := range list.tags {
items := list.items[tag] items := list.items[tag]
@ -326,7 +348,52 @@ func (list *RoomList) indexInTag(tag string, room *rooms.Room) int {
return roomIndex 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) { func (list *RoomList) Get(n int) (string, *rooms.Room) {
n += list.scrollOffset
if n < 0 { if n < 0 {
return "", nil return "", nil
} }
@ -377,12 +444,7 @@ func (list *RoomList) Draw(screen tcell.Screen) {
x, y, width, height := list.GetInnerRect() x, y, width, height := list.GetInnerRect()
bottomLimit := y + height bottomLimit := y + height
var offset int handledOffset := 0
/* TODO fix offset
currentItemIndex := list.Index(list.selected)
if currentItemIndex >= height {
offset = currentItemIndex + 1 - height
}*/
// Draw the list items. // Draw the list items.
for _, tag := range list.tags { for _, tag := range list.tags {
@ -392,20 +454,32 @@ func (list *RoomList) Draw(screen tcell.Screen) {
continue 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)) widget.WriteLine(screen, tview.AlignLeft, tagDisplayName, x, y, width, tcell.StyleDefault.Underline(true).Bold(true))
y++ y++
for i := len(items) - 1; i >= 0; i-- { for i := len(items) - 1; i >= 0; i-- {
item := items[i] item := items[i]
index := len(items) - 1 - i index := len(items) - 1 - i
if index < offset {
continue
}
if y >= bottomLimit { if y >= bottomLimit {
break break
} }
if index < localOffset {
continue
}
text := item.GetTitle() text := item.GetTitle()
lineWidth := width lineWidth := width

View File

@ -213,39 +213,47 @@ func (view *MainView) MouseEventHandler(roomView *RoomView, event *tcell.EventMo
msgView := roomView.MessageView() msgView := roomView.MessageView()
x, y := event.Position() x, y := event.Position()
switch event.Buttons() { switch {
case tcell.WheelUp: case isInArea(x, y, msgView):
if msgView.IsAtTop() { mx, my, _, _ := msgView.GetRect()
go view.LoadHistory(roomView.Room.ID) switch event.Buttons() {
} else { case tcell.WheelUp:
msgView.AddScrollOffset(WheelScrollOffsetDiff) 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() view.parent.Render()
}
case tcell.WheelDown:
msgView.AddScrollOffset(-WheelScrollOffsetDiff)
view.parent.Render() if msgView.ScrollOffset == 0 {
roomView.Room.MarkRead()
if msgView.ScrollOffset == 0 { }
roomView.Room.MarkRead() default:
}
default:
if isInArea(x, y, msgView) {
mx, my, _, _ := msgView.GetRect()
if msgView.HandleClick(x-mx, y-my, event.Buttons()) { if msgView.HandleClick(x-mx, y-my, event.Buttons()) {
view.parent.Render() 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() _, rly, _, _ := msgView.GetRect()
n := y - rly + 1 n := y - rly + 1
view.SwitchRoom(view.roomList.Get(n)) 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 return event
} }
@ -305,7 +313,10 @@ func (view *MainView) GetRoom(roomID string) ifc.RoomView {
room, ok := view.rooms[roomID] room, ok := view.rooms[roomID]
if !ok { if !ok {
view.AddRoom(roomID) view.AddRoom(roomID)
room, _ := view.rooms[roomID] room, ok := view.rooms[roomID]
if !ok {
return nil
}
return room return room
} }
return room return room