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