1 | // |
---|
2 | // "$Id$" |
---|
3 | // |
---|
4 | // Fl_Check_Browser header file for the Fast Light Tool Kit (FLTK). |
---|
5 | // |
---|
6 | // Copyright 1998-2005 by Bill Spitzak and others. |
---|
7 | // |
---|
8 | // This library is free software; you can redistribute it and/or |
---|
9 | // modify it under the terms of the GNU Library General Public |
---|
10 | // License as published by the Free Software Foundation; either |
---|
11 | // version 2 of the License, or (at your option) any later version. |
---|
12 | // |
---|
13 | // This library is distributed in the hope that it will be useful, |
---|
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
16 | // Library General Public License for more details. |
---|
17 | // |
---|
18 | // You should have received a copy of the GNU Library General Public |
---|
19 | // License along with this library; if not, write to the Free Software |
---|
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
---|
21 | // USA. |
---|
22 | // |
---|
23 | // Please report all bugs and problems on the following page: |
---|
24 | // |
---|
25 | // http://www.fltk.org/str.php |
---|
26 | // |
---|
27 | |
---|
28 | #include <stdio.h> |
---|
29 | #include <stdlib.h> |
---|
30 | #include "flstring.h" |
---|
31 | #include <FL/fl_draw.H> |
---|
32 | #include <FL/Fl_Check_Browser.H> |
---|
33 | |
---|
34 | /* This uses a cache for faster access when you're scanning the list |
---|
35 | either forwards or backwards. */ |
---|
36 | |
---|
37 | Fl_Check_Browser::cb_item *Fl_Check_Browser::find_item(int n) const { |
---|
38 | int i = n; |
---|
39 | cb_item *p = first; |
---|
40 | |
---|
41 | if (n <= 0 || n > nitems_ || p == 0) { |
---|
42 | return 0; |
---|
43 | } |
---|
44 | |
---|
45 | if (n == cached_item) { |
---|
46 | p = cache; |
---|
47 | n = 1; |
---|
48 | } else if (n == cached_item + 1) { |
---|
49 | p = cache->next; |
---|
50 | n = 1; |
---|
51 | } else if (n == cached_item - 1) { |
---|
52 | p = cache->prev; |
---|
53 | n = 1; |
---|
54 | } |
---|
55 | |
---|
56 | while (--n) { |
---|
57 | p = p->next; |
---|
58 | } |
---|
59 | |
---|
60 | /* Cast to not const and cache it. */ |
---|
61 | |
---|
62 | ((Fl_Check_Browser *)this)->cache = p; |
---|
63 | ((Fl_Check_Browser *)this)->cached_item = i; |
---|
64 | |
---|
65 | return p; |
---|
66 | } |
---|
67 | |
---|
68 | int Fl_Check_Browser::lineno(cb_item *p0) const { |
---|
69 | cb_item *p = first; |
---|
70 | |
---|
71 | if (p == 0) { |
---|
72 | return 0; |
---|
73 | } |
---|
74 | |
---|
75 | int i = 1; |
---|
76 | while (p) { |
---|
77 | if (p == p0) { |
---|
78 | return i; |
---|
79 | } |
---|
80 | i++; |
---|
81 | p = p->next; |
---|
82 | } |
---|
83 | |
---|
84 | return 0; |
---|
85 | } |
---|
86 | |
---|
87 | Fl_Check_Browser::Fl_Check_Browser(int X, int Y, int W, int H, const char *l) |
---|
88 | : Fl_Browser_(X, Y, W, H, l) { |
---|
89 | type(FL_SELECT_BROWSER); |
---|
90 | when(FL_WHEN_NEVER); |
---|
91 | first = last = 0; |
---|
92 | nitems_ = nchecked_ = 0; |
---|
93 | cached_item = -1; |
---|
94 | } |
---|
95 | |
---|
96 | void *Fl_Check_Browser::item_first() const { |
---|
97 | return first; |
---|
98 | } |
---|
99 | |
---|
100 | void *Fl_Check_Browser::item_next(void *l) const { |
---|
101 | return ((cb_item *)l)->next; |
---|
102 | } |
---|
103 | |
---|
104 | void *Fl_Check_Browser::item_prev(void *l) const { |
---|
105 | return ((cb_item *)l)->prev; |
---|
106 | } |
---|
107 | |
---|
108 | int Fl_Check_Browser::item_height(void *) const { |
---|
109 | return textsize() + 2; |
---|
110 | } |
---|
111 | |
---|
112 | #define CHECK_SIZE (textsize()-2) |
---|
113 | |
---|
114 | int Fl_Check_Browser::item_width(void *v) const { |
---|
115 | fl_font(textfont(), textsize()); |
---|
116 | return int(fl_width(((cb_item *)v)->text)) + CHECK_SIZE + 8; |
---|
117 | } |
---|
118 | |
---|
119 | void Fl_Check_Browser::item_draw(void *v, int X, int Y, int, int) const { |
---|
120 | cb_item *i = (cb_item *)v; |
---|
121 | char *s = i->text; |
---|
122 | int tsize = textsize(); |
---|
123 | Fl_Color col = active_r() ? textcolor() : fl_inactive(textcolor()); |
---|
124 | int cy = Y + (tsize + 1 - CHECK_SIZE) / 2; |
---|
125 | X += 2; |
---|
126 | |
---|
127 | fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR)); |
---|
128 | fl_loop(X, cy, X, cy + CHECK_SIZE, |
---|
129 | X + CHECK_SIZE, cy + CHECK_SIZE, X + CHECK_SIZE, cy); |
---|
130 | if (i->checked) { |
---|
131 | int tx = X + 3; |
---|
132 | int tw = CHECK_SIZE - 4; |
---|
133 | int d1 = tw/3; |
---|
134 | int d2 = tw-d1; |
---|
135 | int ty = cy + (CHECK_SIZE+d2)/2-d1-2; |
---|
136 | for (int n = 0; n < 3; n++, ty++) { |
---|
137 | fl_line(tx, ty, tx+d1, ty+d1); |
---|
138 | fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1); |
---|
139 | } |
---|
140 | } |
---|
141 | fl_font(textfont(), tsize); |
---|
142 | if (i->selected) { |
---|
143 | col = fl_contrast(col, selection_color()); |
---|
144 | } |
---|
145 | fl_color(col); |
---|
146 | fl_draw(s, X + CHECK_SIZE + 8, Y + tsize - 1); |
---|
147 | } |
---|
148 | |
---|
149 | void Fl_Check_Browser::item_select(void *v, int state) { |
---|
150 | cb_item *i = (cb_item *)v; |
---|
151 | |
---|
152 | if (state) { |
---|
153 | if (i->checked) { |
---|
154 | i->checked = 0; |
---|
155 | nchecked_--; |
---|
156 | } else { |
---|
157 | i->checked = 1; |
---|
158 | nchecked_++; |
---|
159 | } |
---|
160 | } |
---|
161 | } |
---|
162 | |
---|
163 | int Fl_Check_Browser::item_selected(void *v) const { |
---|
164 | cb_item *i = (cb_item *)v; |
---|
165 | return i->selected; |
---|
166 | } |
---|
167 | |
---|
168 | int Fl_Check_Browser::add(char *s) { |
---|
169 | return (add(s, 0)); |
---|
170 | } |
---|
171 | |
---|
172 | int Fl_Check_Browser::add(char *s, int b) { |
---|
173 | cb_item *p = (cb_item *)malloc(sizeof(cb_item)); |
---|
174 | p->next = 0; |
---|
175 | p->prev = 0; |
---|
176 | p->checked = b; |
---|
177 | p->selected = 0; |
---|
178 | p->text = strdup(s); |
---|
179 | |
---|
180 | if (b) { |
---|
181 | nchecked_++; |
---|
182 | } |
---|
183 | |
---|
184 | if (last == 0) { |
---|
185 | first = last = p; |
---|
186 | } else { |
---|
187 | last->next = p; |
---|
188 | p->prev = last; |
---|
189 | last = p; |
---|
190 | } |
---|
191 | nitems_++; |
---|
192 | |
---|
193 | return (nitems_); |
---|
194 | } |
---|
195 | |
---|
196 | int Fl_Check_Browser::remove(int item) { |
---|
197 | cb_item *p = find_item(item); |
---|
198 | |
---|
199 | // line at item exists |
---|
200 | if(p) { |
---|
201 | // tell the Browser_ what we will do |
---|
202 | deleting(p); |
---|
203 | |
---|
204 | // fix checked count |
---|
205 | if(p->checked) |
---|
206 | --nchecked_; |
---|
207 | |
---|
208 | // remove the node |
---|
209 | if (p->prev) |
---|
210 | p->prev->next = p->next; |
---|
211 | else |
---|
212 | first = p->next; |
---|
213 | if (p->next) |
---|
214 | p->next->prev = p->prev; |
---|
215 | else |
---|
216 | last = p->prev; |
---|
217 | |
---|
218 | free(p->text); |
---|
219 | free(p); |
---|
220 | |
---|
221 | --nitems_; |
---|
222 | cached_item = -1; |
---|
223 | } |
---|
224 | |
---|
225 | return (nitems_); |
---|
226 | } |
---|
227 | |
---|
228 | void Fl_Check_Browser::clear() { |
---|
229 | cb_item *p = first; |
---|
230 | cb_item *next; |
---|
231 | |
---|
232 | if (p == 0) { |
---|
233 | return; |
---|
234 | } |
---|
235 | |
---|
236 | new_list(); |
---|
237 | do { |
---|
238 | next = p->next; |
---|
239 | free(p->text); |
---|
240 | free(p); |
---|
241 | p = next; |
---|
242 | } while (p); |
---|
243 | |
---|
244 | first = last = 0; |
---|
245 | nitems_ = nchecked_ = 0; |
---|
246 | cached_item = -1; |
---|
247 | } |
---|
248 | |
---|
249 | int Fl_Check_Browser::checked(int i) const { |
---|
250 | cb_item *p = find_item(i); |
---|
251 | |
---|
252 | if (p) return p->checked; |
---|
253 | return 0; |
---|
254 | } |
---|
255 | |
---|
256 | void Fl_Check_Browser::checked(int i, int b) { |
---|
257 | cb_item *p = find_item(i); |
---|
258 | |
---|
259 | if (p && (p->checked ^ b)) { |
---|
260 | p->checked = b; |
---|
261 | if (b) { |
---|
262 | nchecked_++; |
---|
263 | } else { |
---|
264 | nchecked_--; |
---|
265 | } |
---|
266 | redraw(); |
---|
267 | } |
---|
268 | } |
---|
269 | |
---|
270 | int Fl_Check_Browser::value() const { |
---|
271 | return lineno((cb_item *)selection()); |
---|
272 | } |
---|
273 | |
---|
274 | char *Fl_Check_Browser::text(int i) const { |
---|
275 | cb_item *p = find_item(i); |
---|
276 | |
---|
277 | if (p) return p->text; |
---|
278 | return 0; |
---|
279 | } |
---|
280 | |
---|
281 | void Fl_Check_Browser::check_all() { |
---|
282 | cb_item *p; |
---|
283 | |
---|
284 | nchecked_ = nitems_; |
---|
285 | for (p = first; p; p = p->next) { |
---|
286 | p->checked = 1; |
---|
287 | } |
---|
288 | redraw(); |
---|
289 | } |
---|
290 | |
---|
291 | void Fl_Check_Browser::check_none() { |
---|
292 | cb_item *p; |
---|
293 | |
---|
294 | nchecked_ = 0; |
---|
295 | for (p = first; p; p = p->next) { |
---|
296 | p->checked = 0; |
---|
297 | } |
---|
298 | redraw(); |
---|
299 | } |
---|
300 | |
---|
301 | int Fl_Check_Browser::handle(int event) { |
---|
302 | if (event==FL_PUSH) |
---|
303 | deselect(); |
---|
304 | return Fl_Browser_::handle(event); |
---|
305 | } |
---|
306 | |
---|
307 | // |
---|
308 | // End of "$Id$". |
---|
309 | // |
---|