Skip to content

Commit

Permalink
update the table incrementally when the new frame is for the same band
Browse files Browse the repository at this point in the history
  • Loading branch information
ftl committed Aug 25, 2024
1 parent 005a236 commit d5924d1
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 31 deletions.
38 changes: 18 additions & 20 deletions core/bandmap/bandmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (m *Bandmap) run() {
func (m *Bandmap) update() {
m.entries.CleanOut(m.maximumAge, m.clock.Now(), m.weights)

entryOnFrequency, entryOnFrequencyAvailable := m.nextVisibleEntry(m.activeFrequency, 2, func(entry core.BandmapEntry) bool {
entryOnFrequency, entryOnFrequencyAvailable := m.nextVisibleEntryBy(core.BandmapByDistance(m.activeFrequency), 2, func(entry core.BandmapEntry) bool {
return entry.OnFrequency(m.activeFrequency)
})
m.entries.emitEntryOnFrequency(entryOnFrequency, entryOnFrequencyAvailable)
Expand All @@ -124,18 +124,18 @@ func (m *Bandmap) update() {
}

selectedEntry, selected := m.entries.SelectedEntry()
if selected && m.entryVisible(selectedEntry) && selectedEntry.OnFrequency(m.activeFrequency) {
if selected && m.entryVisible(selectedEntry) {
frame.SelectedEntry = selectedEntry
}

nearestEntry, nearestEntryFound := m.nextVisibleEntry(m.activeFrequency, 0, func(entry core.BandmapEntry) bool {
nearestEntry, nearestEntryFound := m.nextVisibleEntryBy(core.BandmapByDistance(m.activeFrequency), 0, func(entry core.BandmapEntry) bool {
return !entry.OnFrequency(m.activeFrequency) && entry.Source != core.WorkedSpot
})
if nearestEntryFound {
frame.NearestEntry = nearestEntry
}

highestValueEntry, highestValueEntryFound := m.nextVisibleEntryBy(core.BandmapByDescendingValue, 0, func(entry core.BandmapEntry) bool {
highestValueEntry, highestValueEntryFound := m.nextVisibleEntryBy(core.Descending(core.BandmapByValue), 0, func(entry core.BandmapEntry) bool {
return entry.Source != core.WorkedSpot
})
if highestValueEntryFound {
Expand Down Expand Up @@ -299,10 +299,15 @@ func (m *Bandmap) Query(order core.BandmapOrder, filters ...core.BandmapFilter)

func (m *Bandmap) SelectEntry(id core.BandmapEntryID) {
m.do <- func() {
m.entries.Select(id)
m.selectEntry(id)
}
}

func (m *Bandmap) selectEntry(id core.BandmapEntryID) {
m.entries.Select(id)
m.update()
}

func (m *Bandmap) SelectByCallsign(call callsign.Callsign) bool {
result := make(chan bool, 1)
callStr := call.String()
Expand All @@ -315,14 +320,14 @@ func (m *Bandmap) SelectByCallsign(call callsign.Callsign) bool {
}
return false
})
m.entries.Select(foundEntryID)
m.selectEntry(foundEntryID)
result <- (foundEntryID > core.NoEntryID)
}
return <-result
}

func (m *Bandmap) GotoHighestValueEntry() {
m.findAndSelectNextVisibleEntryBy(core.BandmapByDescendingValue, func(entry core.BandmapEntry) bool {
m.findAndSelectNextVisibleEntryBy(core.Descending(core.BandmapByValue), func(entry core.BandmapEntry) bool {
return entry.Source != core.WorkedSpot
})
}
Expand All @@ -335,38 +340,31 @@ func (m *Bandmap) GotoNearestEntry() {

func (m *Bandmap) GotoNextEntryUp() {
m.findAndSelectNextVisibleEntry(func(entry core.BandmapEntry) bool {
return entry.Frequency > m.activeFrequency && entry.Source != core.WorkedSpot
selectedEntry, selected := m.entries.SelectedEntry()
return ((entry.Frequency > m.activeFrequency) || (selected && entry.Frequency == m.activeFrequency && entry.ID > selectedEntry.ID)) && entry.Source != core.WorkedSpot
})
}

func (m *Bandmap) GotoNextEntryDown() {
m.findAndSelectNextVisibleEntry(func(entry core.BandmapEntry) bool {
return entry.Frequency < m.activeFrequency && entry.Source != core.WorkedSpot
selectedEntry, selected := m.entries.SelectedEntry()
return ((entry.Frequency < m.activeFrequency) || (selected && entry.Frequency == m.activeFrequency && entry.ID < selectedEntry.ID)) && entry.Source != core.WorkedSpot
})
}

func (m *Bandmap) findAndSelectNextVisibleEntry(f func(entry core.BandmapEntry) bool) {
m.do <- func() {
entry, found := m.nextVisibleEntry(m.activeFrequency, 0, f)
if found {
m.entries.Select(entry.ID)
}
}
m.findAndSelectNextVisibleEntryBy(core.BandmapByDistance(m.activeFrequency), f)
}

func (m *Bandmap) findAndSelectNextVisibleEntryBy(order core.BandmapOrder, f func(entry core.BandmapEntry) bool) {
m.do <- func() {
entry, found := m.nextVisibleEntryBy(order, 0, f)
if found {
m.entries.Select(entry.ID)
m.selectEntry(entry.ID)
}
}
}

func (m *Bandmap) nextVisibleEntry(frequency core.Frequency, limit int, f func(core.BandmapEntry) bool) (core.BandmapEntry, bool) {
return m.nextVisibleEntryBy(core.BandmapByDistance(frequency), limit, f)
}

func (m *Bandmap) nextVisibleEntryBy(order core.BandmapOrder, limit int, f func(core.BandmapEntry) bool) (core.BandmapEntry, bool) {
entries := m.entries.AllBy(order)
if limit == 0 || limit > len(entries) {
Expand Down
3 changes: 3 additions & 0 deletions core/bandmap/entries.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ func (l *Entries) cleanOutOldEntries(maximumAge time.Duration, now time.Time) {
l.entries = filterSlice(l.entries, func(e *Entry) bool {
stillValid := e.RemoveSpotsBefore(deadline)
if !stillValid {
if l.selectedEntry != nil && e.ID == l.selectedEntry.ID {
l.selectedEntry = nil
}
l.emitEntryRemoved(*e)
}
return stillValid
Expand Down
13 changes: 11 additions & 2 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -1003,19 +1003,28 @@ func Descending(o BandmapOrder) BandmapOrder {
}

func BandmapByFrequency(a, b BandmapEntry) bool {
if a.Frequency == b.Frequency {
return a.ID < b.ID
}
return a.Frequency < b.Frequency
}

func BandmapByDistance(referenceFrequency Frequency) BandmapOrder {
return func(a, b BandmapEntry) bool {
deltaA := math.Abs(float64(a.Frequency - referenceFrequency))
deltaB := math.Abs(float64(b.Frequency - referenceFrequency))
if deltaA == deltaB {
return a.ID < b.ID
}
return deltaA < deltaB
}
}

func BandmapByDescendingValue(a, b BandmapEntry) bool {
return a.Info.WeightedValue > b.Info.WeightedValue
func BandmapByValue(a, b BandmapEntry) bool {
if a.Info.WeightedValue == b.Info.WeightedValue {
return a.ID < b.ID
}
return a.Info.WeightedValue < b.Info.WeightedValue
}

type BandmapFilter func(entry BandmapEntry) bool
Expand Down
53 changes: 49 additions & 4 deletions ui/spotsTableView.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,16 +232,59 @@ func (v *spotsView) showFrameInTable(frame core.BandmapFrame) {
}
}

func (v *spotsView) getTablePathForEntry(entry core.BandmapEntry) (*gtk.TreePath, bool) {
func (v *spotsView) addTableEntry(index int, entry core.BandmapEntry) {
newRow := v.tableContent.Insert(index)
err := v.fillEntryToTableRow(newRow, entry)
if err != nil {
log.Printf("Cannot insert entry into spots table row %v: %v", entry, err)
}
}

func (v *spotsView) updateTableEntry(index int, entry core.BandmapEntry) {
row, found := v.getTableRowForIndex(index)
if !found {
return
}

err := v.fillEntryToTableRow(row, entry)
if err != nil {
log.Printf("Cannot update entry in spots table row %v: %v", entry, err)
}
}

func (v *spotsView) removeTableEntry(index int) {
row, found := v.getTableRowForIndex(index)
if !found {
return
}

v.tableContent.Remove(row)
}

func (v *spotsView) getTableRowForIndex(index int) (*gtk.TreeIter, bool) {
row, err := v.tableContent.GetIterFromString(fmt.Sprintf("%d", index))
if err != nil {
log.Printf("cannot find table row with index %d", index)
// panic(fmt.Errorf("cannot find table row with index %d", index))
return nil, false
}

return row, true
}

func (v *spotsView) getTableRowForEntry(entry core.BandmapEntry) (*gtk.TreeIter, bool) {
index, found := v.currentFrame.IndexOf(entry.ID)
if !found {
log.Printf("cannot find index for entry with ID %d", entry.ID)
return nil, false
}

row, err := v.tableContent.GetIterFromString(fmt.Sprintf("%d", index))
if err != nil {
log.Printf("cannot find table row with ID %d", entry.ID)
return v.getTableRowForIndex(index)
}

func (v *spotsView) getTablePathForEntry(entry core.BandmapEntry) (*gtk.TreePath, bool) {
row, found := v.getTableRowForEntry(entry)
if !found {
return nil, false
}

Expand All @@ -267,12 +310,14 @@ func (v *spotsView) revealTableEntry(entry core.BandmapEntry) {
func (v *spotsView) setSelectedTableEntry(entry core.BandmapEntry) {
path, found := v.getTablePathForEntry(entry)
if !found {
v.clearSelection()
return
}

selection, err := v.table.GetSelection()
if err != nil {
log.Printf("no table selection available: %v", err)
return
}
selection.SelectPath(path)
column := v.table.GetColumn(1)
Expand Down
39 changes: 34 additions & 5 deletions ui/spotsView.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ui

import (
"fmt"
"log"

"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
Expand Down Expand Up @@ -70,6 +71,7 @@ func (v *spotsView) ShowFrame(frame core.BandmapFrame) {
// frequencyChanged := v.currentFrame.Frequency != frame.Frequency
bandChanged := (v.currentFrame.ActiveBand != frame.ActiveBand) || (v.currentFrame.VisibleBand != frame.VisibleBand)
selectionChanged := v.currentFrame.SelectedEntry.ID != frame.SelectedEntry.ID
isEntrySelected := frame.SelectedEntry.ID != core.NoEntryID

oldFrame := v.currentFrame
v.currentFrame = frame
Expand All @@ -79,11 +81,11 @@ func (v *spotsView) ShowFrame(frame core.BandmapFrame) {
if bandChanged {
v.showFrameInTable(frame)
} else {
v.updateFrame(oldFrame, frame)
v.updateTableFromFrame(oldFrame, frame)
}

if selectionChanged {
if frame.SelectedEntry.ID != core.NoEntryID {
if selectionChanged || bandChanged {
if isEntrySelected {
v.setSelectedTableEntry(frame.SelectedEntry)
} else {
v.clearSelection()
Expand All @@ -96,8 +98,35 @@ func (v *spotsView) ShowFrame(frame core.BandmapFrame) {
})
}

func (v *spotsView) updateFrame(oldFrame core.BandmapFrame, newFrame core.BandmapFrame) {
v.showFrameInTable(newFrame)
func (v *spotsView) updateTableFromFrame(oldFrame core.BandmapFrame, newFrame core.BandmapFrame) {
visitedEntries := make(map[core.BandmapEntryID]bool, len(newFrame.Entries))
newEntries := make([]core.BandmapEntryID, 0, len(newFrame.Entries))
for _, entry := range newFrame.Entries {
visitedEntries[entry.ID] = true
oldIndex, existed := oldFrame.IndexOf(entry.ID)
if existed {
v.updateTableEntry(oldIndex, entry)
} else {
newEntries = append(newEntries, entry.ID)
}
}

for i := len(oldFrame.Entries) - 1; i >= 0; i-- {
entry := oldFrame.Entries[i]
visited := visitedEntries[entry.ID]
if !visited {
v.removeTableEntry(i)
}
}

for _, id := range newEntries {
index, found := newFrame.IndexOf(id)
if !found {
log.Printf("cannot find new entry with ID %d", id)
continue
}
v.addTableEntry(index, newFrame.Entries[index])
}
}

func (v *spotsView) setupBands(bands []core.BandSummary) {
Expand Down

0 comments on commit d5924d1

Please sign in to comment.