1 /*
2 * item_list.cc
3 * DIN Is Noise is copyright (c) 2006-2021 Jagannathan Sampath
4 * DIN Is Noise is released under GNU Public License 2.0
5 * For more information, please visit https://dinisnoise.org/
6 */
7
8 #include "item_list.h"
9 #include "font.h"
10 #include "input.h"
11 #include "utils.h"
12 #include "tokenizer.h"
13
14 #include <sstream>
15 using namespace std;
16
17 extern int mousex, mouseyy;
18 extern char BUFFER [];
19 extern int line_height;
20
item_list()21 item_list::item_list () {
22 cur = hov = -1;
23 last = nsel = 0;
24 sel_lis = 0; // selection
25 set_listener (this); // click
26 }
27
calc()28 void item_list::calc () {
29 n = items.size ();
30 n_1 = n - 1;
31 nums.resize (n);
32 for (int i = 0; i < n; ++i) {
33 sprintf (BUFFER, " [%d]", i+1);
34 nums[i] = BUFFER;
35 }
36 }
add(const string & item)37 void item_list::add (const string& item) {
38 items.push_back ( itemt (item) );
39 calc ();
40 }
41
42
clear()43 void item_list::clear () {
44 cur = hov = -1;
45 last = nsel = 0;
46 items.clear ();
47 }
48
remove(int i)49 void item_list::remove (int i) {
50 nsel -= items[i].sel;
51 items.erase (items.begin () + i);
52 calc ();
53 clamp (0, last, n_1);
54 }
55
insert(int i,const string & t)56 void item_list::insert (int i, const string& t) {
57 if (n && i < n) {
58 items.insert (items.begin() + i, itemt(t));
59 calc ();
60 }
61 }
62
set_pos(int x,int y)63 void item_list::set_pos (int x, int y) {
64 posx = x;
65 posy = y;
66 extents.left = extents.right = posx;
67 extents.top = extents.bottom = posy;
68 for (int i = 0; i < n; ++i) extents.right = max (extents.right, posx + get_char_width (items[i].name));
69 extents.bottom -= (n * line_height);
70 yt = extents.top - line_height;
71 extents.calc ();
72 }
73
draw()74 void item_list::draw () {
75 int x = extents.left, y = yt, xp = 0;
76 for (int i = 0; i < n; ++i) {
77 if (i == hov) glColor3f (0, 1, 0);
78 else if (items[i].sel) glColor3f (0, 1, 1);
79 else glColor3f (clr.r, clr.g, clr.b);
80 xp = draw_string (items[i].name, x, y);
81 draw_string (nums[i], xp, y);
82 y -= line_height;
83 }
84 }
85
select(int w)86 void item_list::select (int w) {
87 for (int i = 0; i < n; ++i) items[i].sel = w;
88 nsel = n * w;
89 if (sel_lis) sel_lis->selected (*this, get_first ());
90 }
91
select(int i,int j)92 void item_list::select (int i, int j) {
93 if (i > j) std::swap (i, j);
94 nsel -= items[i].sel;
95 for (int k = i, l = j + 1; k < l; ++k) items[k].sel = 1;
96 last = j;
97 nsel += (j - i + 1);
98 }
99
invert_select()100 void item_list::invert_select () {
101 for (int i = 0; i < n; ++i) {
102 int& si = items[i].sel;
103 nsel -= si;
104 si = !si;
105 nsel += si;
106 }
107 if (sel_lis) sel_lis->selected (*this, get_first ());
108 }
109
select_these(tokenizer & tz)110 int item_list::select_these (tokenizer& tz) {
111 int m; tz >> m;
112 if (m) {
113 select (0);
114 for (int i = 0, j = 0; i < m; ++i) {
115 tz >> j;
116 items[j].sel = 1;
117 ++nsel;
118 }
119 if (sel_lis) sel_lis->selected (*this, get_first ());
120 }
121 return m;
122 }
123
handle_input()124 int item_list::handle_input () {
125 int r = button::handle_input ();
126 if (hover && n) {
127 hov = -1;
128 int m = (mouseyy - extents.bottom) / line_height;
129 if (m > -1 && m < n) hov = n_1 - m;
130 }
131 return r;
132 }
133
clicked(button & b)134 void item_list::clicked (button& b) {
135 if (hov != -1) {
136 cur = hov;
137 if (SHIFT)
138 select (last, cur);
139 else {
140 int& shi = items[cur].sel;
141 nsel -= shi;
142 shi = !shi;
143 nsel += shi;
144 last = cur;
145 }
146 if (sel_lis) sel_lis->selected (*this, cur);
147 }
148 }
149
get_selected()150 string item_list::get_selected () {
151 std::stringstream ss;
152 for (int i = 0; i < n; ++i) if (items[i].sel) ss << i << spc;
153 return ss.str ();
154 }
155
get_first()156 int item_list::get_first () {
157 for (int i = 0; i < n; ++i) if (items[i].sel) return i;
158 return -1;
159 }
160