forked from google/gxui
/
filtered_list_adapter.go
72 lines (60 loc) · 1.57 KB
/
filtered_list_adapter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gxui
import (
"sort"
"strings"
)
type FilteredListItem struct {
Name string
Data interface{}
}
type FilteredListAdapter struct {
DefaultAdapter
items []FilteredListItem
}
func (a *FilteredListAdapter) SetItems(items []FilteredListItem) {
// Clone, as the order can be mutated
a.items = append([]FilteredListItem{}, items...)
a.DefaultAdapter.SetItems(a.items)
}
func (a *FilteredListAdapter) Sort(partial string) {
partialLower := strings.ToLower(partial)
sorter := flaSorter{items: a.items, scores: make([]int, len(a.items))}
for i, s := range a.items {
sorter.scores[i] = flaScore(s.Name, strings.ToLower(s.Name), partial, partialLower)
}
sort.Sort(sorter)
a.DefaultAdapter.SetItems(a.items)
}
type flaSorter struct {
items []FilteredListItem
scores []int
}
func (s flaSorter) Len() int {
return len(s.items)
}
func (s flaSorter) Less(i, j int) bool {
return s.scores[i] > s.scores[j]
}
func (s flaSorter) Swap(i, j int) {
items, scores := s.items, s.scores
items[i], items[j] = items[j], items[i]
scores[i], scores[j] = scores[j], scores[i]
}
func flaScore(str, strLower, partial, partialLower string) int {
l := len(partial)
for i := l; i > 0; i-- {
c := 0
if strings.Contains(str, partial[:i]) {
c = i*i + 1
} else if strings.Contains(strLower, partialLower[:i]) {
c = i * i
}
if c > 0 {
return c + flaScore(str, strLower, partial[i:], partialLower[i:])
}
}
return 0
}