Fl_File_Input.cxx 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. //
  2. // "$Id: Fl_File_Input.cxx 11575 2016-04-10 18:36:47Z manolo $"
  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. Distribution and use rights are outlined in
  10. // the file "COPYING" which should have been included with this file. If this
  11. // file is missing or damaged, see the license at:
  12. //
  13. // http://www.fltk.org/COPYING.php
  14. //
  15. // Please report all bugs and problems on the following page:
  16. //
  17. // http://www.fltk.org/str.php
  18. //
  19. #include <FL/Fl.H>
  20. #include <FL/Fl_System_Driver.H>
  21. #include <FL/Fl_File_Input.H>
  22. #include <FL/Fl_Window.H>
  23. #include <FL/fl_draw.H>
  24. #include <FL/filename.H>
  25. #include <stdio.h>
  26. #include "flstring.h"
  27. //
  28. // Height of directory buttons...
  29. //
  30. #define DIR_HEIGHT 10
  31. //
  32. // Redraw bit for directory bar...
  33. //
  34. #define FL_DAMAGE_BAR 0x10
  35. /**
  36. Creates a new Fl_File_Input widget using the given position,
  37. size, and label string. The default boxtype is FL_DOWN_BOX.
  38. \param[in] X, Y, W, H position and size of the widget
  39. \param[in] L widget label, default is no label
  40. */
  41. Fl_File_Input::Fl_File_Input(int X, int Y, int W, int H, const char *L)
  42. : Fl_Input(X, Y, W, H, L) {
  43. buttons_[0] = 0;
  44. errorcolor_ = FL_RED;
  45. ok_entry_ = 1;
  46. pressed_ = -1;
  47. down_box(FL_UP_BOX);
  48. }
  49. /**
  50. Draw directory buttons.
  51. */
  52. void Fl_File_Input::draw_buttons() {
  53. int i, // Looping var
  54. X; // Current X position
  55. if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) {
  56. update_buttons();
  57. }
  58. for (X = 0, i = 0; buttons_[i]; i ++)
  59. {
  60. if ((X + buttons_[i]) > xscroll()) {
  61. if (X < xscroll()) {
  62. draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
  63. x(), y(), X + buttons_[i] - xscroll(), DIR_HEIGHT, FL_GRAY);
  64. } else if ((X + buttons_[i] - xscroll()) > w()) {
  65. draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
  66. x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT,
  67. FL_GRAY);
  68. } else {
  69. draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
  70. x() + X - xscroll(), y(), buttons_[i], DIR_HEIGHT, FL_GRAY);
  71. }
  72. }
  73. X += buttons_[i];
  74. }
  75. if (X < w()) {
  76. draw_box(pressed_ == i ? fl_down(down_box()) : down_box(),
  77. x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, FL_GRAY);
  78. }
  79. }
  80. /**
  81. Update the sizes of the directory buttons.
  82. */
  83. void Fl_File_Input::update_buttons() {
  84. int i; // Looping var
  85. const char *start, // Start of path component
  86. *end; // End of path component
  87. // puts("update_buttons()");
  88. // Set the current font & size...
  89. fl_font(textfont(), textsize());
  90. // Loop through the value string, setting widths...
  91. for (i = 0, start = value();
  92. start && i < (int)(sizeof(buttons_) / sizeof(buttons_[0]) - 1);
  93. start = end, i ++) {
  94. // printf(" start = \"%s\"\n", start);
  95. if ((end = Fl::system_driver()->next_dir_sep(start)) == NULL)
  96. break;
  97. end ++;
  98. buttons_[i] = (short)fl_width(start, (int) (end - start));
  99. if (!i) buttons_[i] += Fl::box_dx(box()) + 6;
  100. }
  101. // printf(" found %d components/buttons...\n", i);
  102. buttons_[i] = 0;
  103. }
  104. /**
  105. Sets the value of the widget given a new string value and its length.
  106. Returns non 0 on success.
  107. \param[in] str new string value
  108. \param[in] len lengh of value
  109. */
  110. int // O - TRUE on success
  111. Fl_File_Input::value(const char *str, // I - New string value
  112. int len) { // I - Length of value
  113. damage(FL_DAMAGE_BAR);
  114. return Fl_Input::value(str,len);
  115. }
  116. /**
  117. Sets the value of the widget given a new string value.
  118. Returns non 0 on success.
  119. \param[in] str new string value
  120. */
  121. int // O - TRUE on success
  122. Fl_File_Input::value(const char *str) { // I - New string value
  123. damage(FL_DAMAGE_BAR);
  124. return Fl_Input::value(str);
  125. }
  126. /**
  127. Draws the file input widget
  128. */
  129. void Fl_File_Input::draw() {
  130. Fl_Boxtype b = box();
  131. if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) draw_buttons();
  132. // this flag keeps Fl_Input_::drawtext from drawing a bogus box!
  133. char must_trick_fl_input_ =
  134. Fl::focus()!=this && !size() && !(damage()&FL_DAMAGE_ALL);
  135. if ((damage() & FL_DAMAGE_ALL) || must_trick_fl_input_)
  136. draw_box(b,x(),y()+DIR_HEIGHT,w(),h()-DIR_HEIGHT,color());
  137. if (!must_trick_fl_input_)
  138. Fl_Input_::drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b)+DIR_HEIGHT,
  139. w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b)-DIR_HEIGHT);
  140. }
  141. /**
  142. Handle events in the widget.
  143. Return non zero if event is handled.
  144. \param[in] event
  145. */
  146. int // O - TRUE if we handled event
  147. Fl_File_Input::handle(int event) // I - Event
  148. {
  149. // printf("handle(event = %d)\n", event);
  150. static char inButtonBar = 0;
  151. switch (event) {
  152. case FL_MOVE :
  153. case FL_ENTER :
  154. if (active_r()) {
  155. if (Fl::event_y() < (y() + DIR_HEIGHT))
  156. window()->cursor(FL_CURSOR_DEFAULT);
  157. else
  158. window()->cursor(FL_CURSOR_INSERT);
  159. }
  160. return 1;
  161. case FL_PUSH :
  162. inButtonBar = (Fl::event_y() < (y() + DIR_HEIGHT));
  163. case FL_RELEASE :
  164. case FL_DRAG :
  165. if (inButtonBar)
  166. return handle_button(event);
  167. else
  168. return Fl_Input::handle(event);
  169. default :
  170. { Fl_Widget_Tracker wp(this);
  171. if (Fl_Input::handle(event)) {
  172. if (wp.exists())
  173. damage(FL_DAMAGE_BAR);
  174. return 1;
  175. }
  176. }
  177. return 0;
  178. }
  179. }
  180. /**
  181. Handles button events in the widget.
  182. Return non zero if event is handled.
  183. \param[in] event
  184. */
  185. int // O - TRUE if we handled event
  186. Fl_File_Input::handle_button(int event) // I - Event
  187. {
  188. int i, // Looping var
  189. X; // Current X position
  190. char *start, // Start of path component
  191. *end; // End of path component
  192. char newvalue[FL_PATH_MAX]; // New value
  193. // Figure out which button is being pressed...
  194. for (X = 0, i = 0; buttons_[i]; i ++)
  195. {
  196. X += buttons_[i];
  197. if (X > xscroll() && Fl::event_x() < (x() + X - xscroll())) break;
  198. }
  199. // printf("handle_button(event = %d), button = %d\n", event, i);
  200. // Redraw the directory bar...
  201. if (event == FL_RELEASE) pressed_ = -1;
  202. else pressed_ = (short)i;
  203. window()->make_current();
  204. draw_buttons();
  205. // Return immediately if the user is clicking on the last button or
  206. // has not released the mouse button...
  207. if (!buttons_[i] || event != FL_RELEASE) return 1;
  208. // Figure out where to truncate the path...
  209. strlcpy(newvalue, value(), sizeof(newvalue));
  210. for (start = newvalue, end = start; start && i >= 0; start = end, i --) {
  211. // printf(" start = \"%s\"\n", start);
  212. if ((end = (char*)Fl::system_driver()->next_dir_sep(start)) == NULL)
  213. break;
  214. end ++;
  215. }
  216. if (i < 0) {
  217. // Found the end; truncate the value and update the buttons...
  218. *start = '\0';
  219. value(newvalue, (int) (start - newvalue) );
  220. // Then do the callbacks, if necessary...
  221. set_changed();
  222. if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback();
  223. }
  224. return 1;
  225. }
  226. //
  227. // End of "$Id: Fl_File_Input.cxx 11575 2016-04-10 18:36:47Z manolo $".
  228. //