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.

299 lines
7.5KB

  1. //
  2. // "$Id: Fl_File_Input.cxx 8063 2010-12-19 21:20:10Z matt $"
  3. //
  4. // File_Input header file for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2010 by Bill Spitzak and others.
  7. // Original version Copyright 1998 by Curtis Edwards.
  8. //
  9. // This library is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU Library General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. //
  14. // This library is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. // Library General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU Library General Public
  20. // License along with this library; if not, write to the Free Software
  21. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  22. // USA.
  23. //
  24. // Please report all bugs and problems on the following page:
  25. //
  26. // http://www.fltk.org/str.php
  27. //
  28. #include <FL/Fl.H>
  29. #include <FL/Fl_File_Input.H>
  30. #include <FL/Fl_Window.H>
  31. #include <FL/fl_draw.H>
  32. #include <FL/filename.H>
  33. #include <stdio.h>
  34. #include "flstring.h"
  35. //
  36. // Height of directory buttons...
  37. //
  38. #define DIR_HEIGHT 10
  39. //
  40. // Redraw bit for directory bar...
  41. //
  42. #define FL_DAMAGE_BAR 0x10
  43. /**
  44. Creates a new Fl_File_Input widget using the given position,
  45. size, and label string. The default boxtype is FL_DOWN_BOX.
  46. \param[in] X, Y, W, H position and size of the widget
  47. \param[in] L widget label, default is no label
  48. */
  49. Fl_File_Input::Fl_File_Input(int X, int Y, int W, int H, const char *L)
  50. : Fl_Input(X, Y, W, H, L) {
  51. buttons_[0] = 0;
  52. errorcolor_ = FL_RED;
  53. ok_entry_ = 1;
  54. pressed_ = -1;
  55. down_box(FL_UP_BOX);
  56. }
  57. /**
  58. Draw directory buttons.
  59. */
  60. void Fl_File_Input::draw_buttons() {
  61. int i, // Looping var
  62. X; // Current X position
  63. if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) {
  64. update_buttons();
  65. }
  66. for (X = 0, i = 0; buttons_[i]; i ++)
  67. {
  68. if ((X + buttons_[i]) > xscroll()) {
  69. if (X < xscroll()) {
  70. draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
  71. x(), y(), X + buttons_[i] - xscroll(), DIR_HEIGHT, FL_GRAY);
  72. } else if ((X + buttons_[i] - xscroll()) > w()) {
  73. draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
  74. x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT,
  75. FL_GRAY);
  76. } else {
  77. draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
  78. x() + X - xscroll(), y(), buttons_[i], DIR_HEIGHT, FL_GRAY);
  79. }
  80. }
  81. X += buttons_[i];
  82. }
  83. if (X < w()) {
  84. draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
  85. x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, FL_GRAY);
  86. }
  87. }
  88. /**
  89. Update the sizes of the directory buttons.
  90. */
  91. void Fl_File_Input::update_buttons() {
  92. int i; // Looping var
  93. const char *start, // Start of path component
  94. *end; // End of path component
  95. // puts("update_buttons()");
  96. // Set the current font & size...
  97. fl_font(textfont(), textsize());
  98. // Loop through the value string, setting widths...
  99. for (i = 0, start = value();
  100. start && i < (int)(sizeof(buttons_) / sizeof(buttons_[0]) - 1);
  101. start = end, i ++) {
  102. // printf(" start = \"%s\"\n", start);
  103. if ((end = strchr(start, '/')) == NULL)
  104. #if defined(WIN32) || defined(__EMX__)
  105. if ((end = strchr(start, '\\')) == NULL)
  106. #endif // WIN32 || __EMX__
  107. break;
  108. end ++;
  109. buttons_[i] = (short)fl_width(start, end - start);
  110. if (!i) buttons_[i] += Fl::box_dx(box()) + 6;
  111. }
  112. // printf(" found %d components/buttons...\n", i);
  113. buttons_[i] = 0;
  114. }
  115. /**
  116. Sets the value of the widget given a new string value and its length.
  117. Returns non 0 on success.
  118. \param[in] str new string value
  119. \param[in] len lengh of value
  120. */
  121. int // O - TRUE on success
  122. Fl_File_Input::value(const char *str, // I - New string value
  123. int len) { // I - Length of value
  124. damage(FL_DAMAGE_BAR);
  125. return Fl_Input::value(str,len);
  126. }
  127. /**
  128. Sets the value of the widget given a new string value.
  129. Returns non 0 on success.
  130. \param[in] str new string value
  131. */
  132. int // O - TRUE on success
  133. Fl_File_Input::value(const char *str) { // I - New string value
  134. damage(FL_DAMAGE_BAR);
  135. return Fl_Input::value(str);
  136. }
  137. /**
  138. Draws the file input widget
  139. */
  140. void Fl_File_Input::draw() {
  141. Fl_Boxtype b = box();
  142. if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) draw_buttons();
  143. // this flag keeps Fl_Input_::drawtext from drawing a bogus box!
  144. char must_trick_fl_input_ =
  145. Fl::focus()!=this && !size() && !(damage()&FL_DAMAGE_ALL);
  146. if ((damage() & FL_DAMAGE_ALL) || must_trick_fl_input_)
  147. draw_box(b,x(),y()+DIR_HEIGHT,w(),h()-DIR_HEIGHT,color());
  148. if (!must_trick_fl_input_)
  149. Fl_Input_::drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b)+DIR_HEIGHT,
  150. w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b)-DIR_HEIGHT);
  151. }
  152. /**
  153. Handle events in the widget.
  154. Return non zero if event is handled.
  155. \param[in] event
  156. */
  157. int // O - TRUE if we handled event
  158. Fl_File_Input::handle(int event) // I - Event
  159. {
  160. // printf("handle(event = %d)\n", event);
  161. static char inButtonBar = 0;
  162. switch (event) {
  163. case FL_MOVE :
  164. case FL_ENTER :
  165. if (active_r()) {
  166. if (Fl::event_y() < (y() + DIR_HEIGHT))
  167. window()->cursor(FL_CURSOR_DEFAULT);
  168. else
  169. window()->cursor(FL_CURSOR_INSERT);
  170. }
  171. return 1;
  172. case FL_PUSH :
  173. inButtonBar = (Fl::event_y() < (y() + DIR_HEIGHT));
  174. case FL_RELEASE :
  175. case FL_DRAG :
  176. if (inButtonBar)
  177. return handle_button(event);
  178. else
  179. return Fl_Input::handle(event);
  180. default :
  181. { Fl_Widget_Tracker wp(this);
  182. if (Fl_Input::handle(event)) {
  183. if (wp.exists())
  184. damage(FL_DAMAGE_BAR);
  185. return 1;
  186. }
  187. }
  188. return 0;
  189. }
  190. }
  191. /**
  192. Handles button events in the widget.
  193. Return non zero if event is handled.
  194. \param[in] event
  195. */
  196. int // O - TRUE if we handled event
  197. Fl_File_Input::handle_button(int event) // I - Event
  198. {
  199. int i, // Looping var
  200. X; // Current X position
  201. char *start, // Start of path component
  202. *end; // End of path component
  203. char newvalue[FL_PATH_MAX]; // New value
  204. // Figure out which button is being pressed...
  205. for (X = 0, i = 0; buttons_[i]; i ++)
  206. {
  207. X += buttons_[i];
  208. if (X > xscroll() && Fl::event_x() < (x() + X - xscroll())) break;
  209. }
  210. // printf("handle_button(event = %d), button = %d\n", event, i);
  211. // Redraw the directory bar...
  212. if (event == FL_RELEASE) pressed_ = -1;
  213. else pressed_ = (short)i;
  214. window()->make_current();
  215. draw_buttons();
  216. // Return immediately if the user is clicking on the last button or
  217. // has not released the mouse button...
  218. if (!buttons_[i] || event != FL_RELEASE) return 1;
  219. // Figure out where to truncate the path...
  220. strlcpy(newvalue, value(), sizeof(newvalue));
  221. for (start = newvalue, end = start; start && i >= 0; start = end, i --) {
  222. // printf(" start = \"%s\"\n", start);
  223. if ((end = strchr(start, '/')) == NULL)
  224. #if defined(WIN32) || defined(__EMX__)
  225. if ((end = strchr(start, '\\')) == NULL)
  226. #endif // WIN32 || __EMX__
  227. break;
  228. end ++;
  229. }
  230. if (i < 0) {
  231. // Found the end; truncate the value and update the buttons...
  232. *start = '\0';
  233. value(newvalue, start - newvalue);
  234. // Then do the callbacks, if necessary...
  235. set_changed();
  236. if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback();
  237. }
  238. return 1;
  239. }
  240. //
  241. // End of "$Id: Fl_File_Input.cxx 8063 2010-12-19 21:20:10Z matt $".
  242. //