PageRenderTime 23ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Utilities/FLTK/src/Fl_Menu_.cxx

https://github.com/paniwani/OTB
C++ | 232 lines | 153 code | 21 blank | 58 comment | 57 complexity | 8065b10c806ac109385fcb8de82bf657 MD5 | raw file
  1. //
  2. // "$Id$"
  3. //
  4. // Common menu code 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. // This is a base class for all items that have a menu:
  28. // Fl_Menu_Bar, Fl_Menu_Button, Fl_Choice
  29. // This provides storage for a menu item, functions to add/modify/delete
  30. // items, and a call for when the user picks a menu item.
  31. // More code in Fl_Menu_add.cxx
  32. #include <FL/Fl.H>
  33. #include <FL/Fl_Menu_.H>
  34. #include "flstring.h"
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. // Set 'pathname' of specified menuitem
  38. // If finditem==NULL, mvalue() is used (the most recently picked menuitem)
  39. // Returns:
  40. // 0 : OK
  41. // -1 : item not found (name="")
  42. // -2 : 'name' not large enough (name="")
  43. //
  44. #define SAFE_STRCAT(s) \
  45. { len += strlen(s); if ( len >= namelen ) { *name='\0'; return(-2); } else strcat(name,(s)); }
  46. int Fl_Menu_::item_pathname(char *name, int namelen, const Fl_Menu_Item *finditem) const {
  47. int len = 0;
  48. finditem = finditem ? finditem : mvalue();
  49. name[0] = '\0';
  50. for ( int t=0; t<size(); t++ ) {
  51. const Fl_Menu_Item *m = &(menu()[t]);
  52. if ( m->submenu() ) { // submenu? descend
  53. if (*name) SAFE_STRCAT("/");
  54. if (m->label()) SAFE_STRCAT(m->label());
  55. } else {
  56. if (m->label()) { // menu item?
  57. if ( m == finditem ) { // found? tack on itemname, done.
  58. SAFE_STRCAT("/");
  59. SAFE_STRCAT(m->label());
  60. return(0);
  61. }
  62. } else { // end of submenu? pop
  63. char *ss = strrchr(name, '/');
  64. if ( ss ) { *ss = 0; len = strlen(name); } // "File/Edit" -> "File"
  65. else { name[0] = '\0'; len = 0; } // "File" -> ""
  66. continue;
  67. }
  68. }
  69. }
  70. *name = '\0';
  71. return(-1); // item not found
  72. }
  73. // FIND MENU ITEM INDEX, GIVEN MENU PATHNAME
  74. // eg. "Edit/Copy"
  75. // Will also return submenus, eg. "Edit"
  76. // Returns NULL if not found.
  77. //
  78. const Fl_Menu_Item *
  79. Fl_Menu_::find_item(const char *name)
  80. {
  81. char menupath[1024] = ""; // File/Export
  82. for ( int t=0; t < size(); t++ ) {
  83. Fl_Menu_Item *m = menu_ + t;
  84. if (m->flags&FL_SUBMENU) {
  85. // IT'S A SUBMENU
  86. // we do not support searches through FL_SUBMENU_POINTER links
  87. if (menupath[0]) strlcat(menupath, "/", sizeof(menupath));
  88. strlcat(menupath, m->label(), sizeof(menupath));
  89. if (!strcmp(menupath, name)) return m;
  90. } else {
  91. if (!m->label()) {
  92. // END OF SUBMENU? Pop back one level.
  93. char *ss = strrchr(menupath, '/');
  94. if ( ss ) *ss = 0;
  95. else menupath[0] = '\0';
  96. continue;
  97. }
  98. // IT'S A MENU ITEM
  99. char itempath[1024]; // eg. Edit/Copy
  100. strcpy(itempath, menupath);
  101. if (itempath[0]) strlcat(itempath, "/", sizeof(itempath));
  102. strlcat(itempath, m->label(), sizeof(itempath));
  103. if (!strcmp(itempath, name)) return m;
  104. }
  105. }
  106. return (const Fl_Menu_Item *)0;
  107. }
  108. int Fl_Menu_::value(const Fl_Menu_Item* m) {
  109. clear_changed();
  110. if (value_ != m) {value_ = m; return 1;}
  111. return 0;
  112. }
  113. // When user picks a menu item, call this. It will do the callback.
  114. // Unfortunatly this also casts away const for the checkboxes, but this
  115. // was necessary so non-checkbox menus can really be declared const...
  116. const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) {
  117. if (v) {
  118. if (v->radio()) {
  119. if (!v->value()) { // they are turning on a radio item
  120. set_changed();
  121. ((Fl_Menu_Item*)v)->setonly();
  122. }
  123. redraw();
  124. } else if (v->flags & FL_MENU_TOGGLE) {
  125. set_changed();
  126. ((Fl_Menu_Item*)v)->flags ^= FL_MENU_VALUE;
  127. redraw();
  128. } else if (v != value_) { // normal item
  129. set_changed();
  130. }
  131. value_ = v;
  132. if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) {
  133. if (changed() || when()&FL_WHEN_NOT_CHANGED) {
  134. if (value_ && value_->callback_) value_->do_callback((Fl_Widget*)this);
  135. else do_callback();
  136. }
  137. }
  138. }
  139. return v;
  140. }
  141. // turn on one of a set of radio buttons
  142. void Fl_Menu_Item::setonly() {
  143. flags |= FL_MENU_RADIO | FL_MENU_VALUE;
  144. Fl_Menu_Item* j;
  145. for (j = this; ; ) { // go down
  146. if (j->flags & FL_MENU_DIVIDER) break; // stop on divider lines
  147. j++;
  148. if (!j->text || !j->radio()) break; // stop after group
  149. j->clear();
  150. }
  151. for (j = this-1; ; j--) { // go up
  152. if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break;
  153. j->clear();
  154. }
  155. }
  156. Fl_Menu_::Fl_Menu_(int X,int Y,int W,int H,const char* l)
  157. : Fl_Widget(X,Y,W,H,l) {
  158. set_flag(SHORTCUT_LABEL);
  159. box(FL_UP_BOX);
  160. when(FL_WHEN_RELEASE_ALWAYS);
  161. value_ = menu_ = 0;
  162. alloc = 0;
  163. selection_color(FL_SELECTION_COLOR);
  164. textfont(FL_HELVETICA);
  165. textsize((uchar)FL_NORMAL_SIZE);
  166. textcolor(FL_FOREGROUND_COLOR);
  167. down_box(FL_NO_BOX);
  168. }
  169. int Fl_Menu_::size() const {
  170. if (!menu_) return 0;
  171. return menu_->size();
  172. }
  173. void Fl_Menu_::menu(const Fl_Menu_Item* m) {
  174. clear();
  175. value_ = menu_ = (Fl_Menu_Item*)m;
  176. }
  177. // this version is ok with new Fl_Menu_add code with fl_menu_array_owner:
  178. void Fl_Menu_::copy(const Fl_Menu_Item* m, void* ud) {
  179. int n = m->size();
  180. Fl_Menu_Item* newMenu = new Fl_Menu_Item[n];
  181. memcpy(newMenu, m, n*sizeof(Fl_Menu_Item));
  182. menu(newMenu);
  183. alloc = 1; // make destructor free array, but not strings
  184. // for convienence, provide way to change all the user data pointers:
  185. if (ud) for (; n--;) {
  186. if (newMenu->callback_) newMenu->user_data_ = ud;
  187. newMenu++;
  188. }
  189. }
  190. Fl_Menu_::~Fl_Menu_() {
  191. clear();
  192. }
  193. // Fl_Menu::add() uses this to indicate the owner of the dynamically-
  194. // expanding array. We must not free this array:
  195. Fl_Menu_* fl_menu_array_owner = 0;
  196. void Fl_Menu_::clear() {
  197. if (alloc) {
  198. if (alloc>1) for (int i = size(); i--;)
  199. if (menu_[i].text) free((void*)menu_[i].text);
  200. if (this == fl_menu_array_owner)
  201. fl_menu_array_owner = 0;
  202. else
  203. delete[] menu_;
  204. menu_ = 0;
  205. value_ = 0;
  206. alloc = 0;
  207. }
  208. }
  209. //
  210. // End of "$Id$".
  211. //