You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
6.7KB

  1. //
  2. // "$Id: Fl_Check_Browser.cxx 8354 2011-02-01 15:41:04Z manolo $"
  3. //
  4. // Fl_Check_Browser header file for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2010 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. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include "flstring.h"
  30. #include <FL/fl_draw.H>
  31. #include <FL/Fl_Check_Browser.H>
  32. /* This uses a cache for faster access when you're scanning the list
  33. either forwards or backwards. */
  34. Fl_Check_Browser::cb_item *Fl_Check_Browser::find_item(int n) const {
  35. int i = n;
  36. cb_item *p = first;
  37. if (n <= 0 || n > nitems_ || p == 0) {
  38. return 0;
  39. }
  40. if (n == cached_item) {
  41. p = cache;
  42. n = 1;
  43. } else if (n == cached_item + 1) {
  44. p = cache->next;
  45. n = 1;
  46. } else if (n == cached_item - 1) {
  47. p = cache->prev;
  48. n = 1;
  49. }
  50. while (--n) {
  51. p = p->next;
  52. }
  53. /* Cast to not const and cache it. */
  54. ((Fl_Check_Browser *)this)->cache = p;
  55. ((Fl_Check_Browser *)this)->cached_item = i;
  56. return p;
  57. }
  58. int Fl_Check_Browser::lineno(cb_item *p0) const {
  59. cb_item *p = first;
  60. if (p == 0) {
  61. return 0;
  62. }
  63. int i = 1;
  64. while (p) {
  65. if (p == p0) {
  66. return i;
  67. }
  68. i++;
  69. p = p->next;
  70. }
  71. return 0;
  72. }
  73. Fl_Check_Browser::Fl_Check_Browser(int X, int Y, int W, int H, const char *l)
  74. /** The constructor makes an empty browser.*/
  75. : Fl_Browser_(X, Y, W, H, l) {
  76. type(FL_SELECT_BROWSER);
  77. when(FL_WHEN_NEVER);
  78. first = last = 0;
  79. nitems_ = nchecked_ = 0;
  80. cached_item = -1;
  81. }
  82. void *Fl_Check_Browser::item_first() const {
  83. return first;
  84. }
  85. void *Fl_Check_Browser::item_next(void *l) const {
  86. return ((cb_item *)l)->next;
  87. }
  88. void *Fl_Check_Browser::item_prev(void *l) const {
  89. return ((cb_item *)l)->prev;
  90. }
  91. int Fl_Check_Browser::item_height(void *) const {
  92. return textsize() + 2;
  93. }
  94. #define CHECK_SIZE (textsize()-2)
  95. int Fl_Check_Browser::item_width(void *v) const {
  96. fl_font(textfont(), textsize());
  97. return int(fl_width(((cb_item *)v)->text)) + CHECK_SIZE + 8;
  98. }
  99. void Fl_Check_Browser::item_draw(void *v, int X, int Y, int, int) const {
  100. cb_item *i = (cb_item *)v;
  101. char *s = i->text;
  102. int tsize = textsize();
  103. Fl_Color col = active_r() ? textcolor() : fl_inactive(textcolor());
  104. int cy = Y + (tsize + 1 - CHECK_SIZE) / 2;
  105. X += 2;
  106. fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR));
  107. fl_loop(X, cy, X, cy + CHECK_SIZE,
  108. X + CHECK_SIZE, cy + CHECK_SIZE, X + CHECK_SIZE, cy);
  109. if (i->checked) {
  110. int tx = X + 3;
  111. int tw = CHECK_SIZE - 4;
  112. int d1 = tw/3;
  113. int d2 = tw-d1;
  114. int ty = cy + (CHECK_SIZE+d2)/2-d1-2;
  115. for (int n = 0; n < 3; n++, ty++) {
  116. fl_line(tx, ty, tx+d1, ty+d1);
  117. fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1);
  118. }
  119. }
  120. fl_font(textfont(), tsize);
  121. if (i->selected) {
  122. col = fl_contrast(col, selection_color());
  123. }
  124. fl_color(col);
  125. fl_draw(s, X + CHECK_SIZE + 8, Y + tsize - 1);
  126. }
  127. void Fl_Check_Browser::item_select(void *v, int state) {
  128. cb_item *i = (cb_item *)v;
  129. if (state) {
  130. if (i->checked) {
  131. i->checked = 0;
  132. nchecked_--;
  133. } else {
  134. i->checked = 1;
  135. nchecked_++;
  136. }
  137. }
  138. }
  139. int Fl_Check_Browser::item_selected(void *v) const {
  140. cb_item *i = (cb_item *)v;
  141. return i->selected;
  142. }
  143. /**
  144. Add a new unchecked line to the end of the browser.
  145. \see add(char *s, int b)
  146. */
  147. int Fl_Check_Browser::add(char *s) {
  148. return (add(s, 0));
  149. }
  150. /**
  151. Add a new line to the end of the browser. The text is copied
  152. using the strdup() function. It may also be NULL to make
  153. a blank line. It can set the item checked if \p b is not 0.
  154. */
  155. int Fl_Check_Browser::add(char *s, int b) {
  156. cb_item *p = (cb_item *)malloc(sizeof(cb_item));
  157. p->next = 0;
  158. p->prev = 0;
  159. p->checked = b;
  160. p->selected = 0;
  161. p->text = strdup(s);
  162. if (b) {
  163. nchecked_++;
  164. }
  165. if (last == 0) {
  166. first = last = p;
  167. } else {
  168. last->next = p;
  169. p->prev = last;
  170. last = p;
  171. }
  172. nitems_++;
  173. return (nitems_);
  174. }
  175. /**
  176. Remove line n and make the browser one line shorter. Returns the
  177. number of lines left in the browser.
  178. */
  179. int Fl_Check_Browser::remove(int item) {
  180. cb_item *p = find_item(item);
  181. // line at item exists
  182. if(p) {
  183. // tell the Browser_ what we will do
  184. deleting(p);
  185. // fix checked count
  186. if(p->checked)
  187. --nchecked_;
  188. // remove the node
  189. if (p->prev)
  190. p->prev->next = p->next;
  191. else
  192. first = p->next;
  193. if (p->next)
  194. p->next->prev = p->prev;
  195. else
  196. last = p->prev;
  197. free(p->text);
  198. free(p);
  199. --nitems_;
  200. cached_item = -1;
  201. }
  202. return (nitems_);
  203. }
  204. /** Remove every item from the browser.*/
  205. void Fl_Check_Browser::clear() {
  206. cb_item *p = first;
  207. cb_item *next;
  208. if (p == 0) {
  209. return;
  210. }
  211. new_list();
  212. do {
  213. next = p->next;
  214. free(p->text);
  215. free(p);
  216. p = next;
  217. } while (p);
  218. first = last = 0;
  219. nitems_ = nchecked_ = 0;
  220. cached_item = -1;
  221. }
  222. /** Gets the current status of item item. */
  223. int Fl_Check_Browser::checked(int i) const {
  224. cb_item *p = find_item(i);
  225. if (p) return p->checked;
  226. return 0;
  227. }
  228. /** Sets the check status of item item to b. */
  229. void Fl_Check_Browser::checked(int i, int b) {
  230. cb_item *p = find_item(i);
  231. if (p && (p->checked ^ b)) {
  232. p->checked = b;
  233. if (b) {
  234. nchecked_++;
  235. } else {
  236. nchecked_--;
  237. }
  238. redraw();
  239. }
  240. }
  241. /** Returns the index of the currently selected item.*/
  242. int Fl_Check_Browser::value() const {
  243. return lineno((cb_item *)selection());
  244. }
  245. /** Return a pointer to an internal buffer holding item item's text.*/
  246. char *Fl_Check_Browser::text(int i) const {
  247. cb_item *p = find_item(i);
  248. if (p) return p->text;
  249. return 0;
  250. }
  251. /** Sets all the items checked.*/
  252. void Fl_Check_Browser::check_all() {
  253. cb_item *p;
  254. nchecked_ = nitems_;
  255. for (p = first; p; p = p->next) {
  256. p->checked = 1;
  257. }
  258. redraw();
  259. }
  260. /** Sets all the items unchecked.*/
  261. void Fl_Check_Browser::check_none() {
  262. cb_item *p;
  263. nchecked_ = 0;
  264. for (p = first; p; p = p->next) {
  265. p->checked = 0;
  266. }
  267. redraw();
  268. }
  269. int Fl_Check_Browser::handle(int event) {
  270. if (event==FL_PUSH)
  271. deselect();
  272. return Fl_Browser_::handle(event);
  273. }
  274. //
  275. // End of "$Id: Fl_Check_Browser.cxx 8354 2011-02-01 15:41:04Z manolo $".
  276. //