DRC | 2ff39b8 | 2011-07-28 08:38:59 +0000 | [diff] [blame] | 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 | |
| 29 | #include <FL/Fl.H> |
| 30 | #include <FL/Fl_File_Input.H> |
| 31 | #include <FL/Fl_Window.H> |
| 32 | #include <FL/fl_draw.H> |
| 33 | #include <FL/filename.H> |
| 34 | #include <stdio.h> |
| 35 | #include "flstring.h" |
| 36 | |
| 37 | |
| 38 | // |
| 39 | // Height of directory buttons... |
| 40 | // |
| 41 | |
| 42 | #define DIR_HEIGHT 10 |
| 43 | |
| 44 | |
| 45 | // |
| 46 | // Redraw bit for directory bar... |
| 47 | // |
| 48 | |
| 49 | #define FL_DAMAGE_BAR 0x10 |
| 50 | |
| 51 | |
| 52 | /** |
| 53 | Creates a new Fl_File_Input widget using the given position, |
| 54 | size, and label string. The default boxtype is FL_DOWN_BOX. |
| 55 | \param[in] X, Y, W, H position and size of the widget |
| 56 | \param[in] L widget label, default is no label |
| 57 | */ |
| 58 | Fl_File_Input::Fl_File_Input(int X, int Y, int W, int H, const char *L) |
| 59 | : Fl_Input(X, Y, W, H, L) { |
| 60 | buttons_[0] = 0; |
| 61 | errorcolor_ = FL_RED; |
| 62 | ok_entry_ = 1; |
| 63 | pressed_ = -1; |
| 64 | |
| 65 | down_box(FL_UP_BOX); |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | Draw directory buttons. |
| 70 | */ |
| 71 | void Fl_File_Input::draw_buttons() { |
| 72 | int i, // Looping var |
| 73 | X; // Current X position |
| 74 | |
| 75 | |
| 76 | if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) { |
| 77 | update_buttons(); |
| 78 | } |
| 79 | |
| 80 | for (X = 0, i = 0; buttons_[i]; i ++) |
| 81 | { |
| 82 | if ((X + buttons_[i]) > xscroll()) { |
| 83 | if (X < xscroll()) { |
| 84 | draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), |
| 85 | x(), y(), X + buttons_[i] - xscroll(), DIR_HEIGHT, FL_GRAY); |
| 86 | } else if ((X + buttons_[i] - xscroll()) > w()) { |
| 87 | draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), |
| 88 | x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, |
| 89 | FL_GRAY); |
| 90 | } else { |
| 91 | draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), |
| 92 | x() + X - xscroll(), y(), buttons_[i], DIR_HEIGHT, FL_GRAY); |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | X += buttons_[i]; |
| 97 | } |
| 98 | |
| 99 | if (X < w()) { |
| 100 | draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), |
| 101 | x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, FL_GRAY); |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | Update the sizes of the directory buttons. |
| 107 | */ |
| 108 | void Fl_File_Input::update_buttons() { |
| 109 | int i; // Looping var |
| 110 | const char *start, // Start of path component |
| 111 | *end; // End of path component |
| 112 | |
| 113 | |
| 114 | // puts("update_buttons()"); |
| 115 | |
| 116 | // Set the current font & size... |
| 117 | fl_font(textfont(), textsize()); |
| 118 | |
| 119 | // Loop through the value string, setting widths... |
| 120 | for (i = 0, start = value(); |
| 121 | start && i < (int)(sizeof(buttons_) / sizeof(buttons_[0]) - 1); |
| 122 | start = end, i ++) { |
| 123 | // printf(" start = \"%s\"\n", start); |
| 124 | if ((end = strchr(start, '/')) == NULL) |
| 125 | #if defined(WIN32) || defined(__EMX__) |
| 126 | if ((end = strchr(start, '\\')) == NULL) |
| 127 | #endif // WIN32 || __EMX__ |
| 128 | break; |
| 129 | |
| 130 | end ++; |
| 131 | |
| 132 | buttons_[i] = (short)fl_width(start, end - start); |
| 133 | if (!i) buttons_[i] += Fl::box_dx(box()) + 6; |
| 134 | } |
| 135 | |
| 136 | // printf(" found %d components/buttons...\n", i); |
| 137 | |
| 138 | buttons_[i] = 0; |
| 139 | } |
| 140 | |
| 141 | |
| 142 | /** |
| 143 | Sets the value of the widget given a new string value and its length. |
| 144 | Returns non 0 on success. |
| 145 | \param[in] str new string value |
| 146 | \param[in] len lengh of value |
| 147 | */ |
| 148 | int // O - TRUE on success |
| 149 | Fl_File_Input::value(const char *str, // I - New string value |
| 150 | int len) { // I - Length of value |
| 151 | damage(FL_DAMAGE_BAR); |
| 152 | return Fl_Input::value(str,len); |
| 153 | } |
| 154 | |
| 155 | |
| 156 | /** |
| 157 | Sets the value of the widget given a new string value. |
| 158 | Returns non 0 on success. |
| 159 | \param[in] str new string value |
| 160 | */ |
| 161 | int // O - TRUE on success |
| 162 | Fl_File_Input::value(const char *str) { // I - New string value |
| 163 | damage(FL_DAMAGE_BAR); |
| 164 | return Fl_Input::value(str); |
| 165 | } |
| 166 | |
| 167 | |
| 168 | /** |
| 169 | Draws the file input widget |
| 170 | */ |
| 171 | void Fl_File_Input::draw() { |
| 172 | Fl_Boxtype b = box(); |
| 173 | if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) draw_buttons(); |
| 174 | // this flag keeps Fl_Input_::drawtext from drawing a bogus box! |
| 175 | char must_trick_fl_input_ = |
| 176 | Fl::focus()!=this && !size() && !(damage()&FL_DAMAGE_ALL); |
| 177 | if ((damage() & FL_DAMAGE_ALL) || must_trick_fl_input_) |
| 178 | draw_box(b,x(),y()+DIR_HEIGHT,w(),h()-DIR_HEIGHT,color()); |
| 179 | if (!must_trick_fl_input_) |
| 180 | Fl_Input_::drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b)+DIR_HEIGHT, |
| 181 | w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b)-DIR_HEIGHT); |
| 182 | } |
| 183 | |
| 184 | |
| 185 | |
| 186 | /** |
| 187 | Handle events in the widget. |
| 188 | Return non zero if event is handled. |
| 189 | \param[in] event |
| 190 | */ |
| 191 | int // O - TRUE if we handled event |
| 192 | Fl_File_Input::handle(int event) // I - Event |
| 193 | { |
| 194 | // printf("handle(event = %d)\n", event); |
| 195 | static char inButtonBar = 0; |
| 196 | |
| 197 | switch (event) { |
| 198 | case FL_MOVE : |
| 199 | case FL_ENTER : |
| 200 | if (active_r()) { |
| 201 | if (Fl::event_y() < (y() + DIR_HEIGHT)) |
| 202 | window()->cursor(FL_CURSOR_DEFAULT); |
| 203 | else |
| 204 | window()->cursor(FL_CURSOR_INSERT); |
| 205 | } |
| 206 | |
| 207 | return 1; |
| 208 | |
| 209 | case FL_PUSH : |
| 210 | inButtonBar = (Fl::event_y() < (y() + DIR_HEIGHT)); |
| 211 | case FL_RELEASE : |
| 212 | case FL_DRAG : |
| 213 | if (inButtonBar) |
| 214 | return handle_button(event); |
| 215 | else |
| 216 | return Fl_Input::handle(event); |
| 217 | |
| 218 | default : |
| 219 | { Fl_Widget_Tracker wp(this); |
| 220 | if (Fl_Input::handle(event)) { |
| 221 | if (wp.exists()) |
| 222 | damage(FL_DAMAGE_BAR); |
| 223 | return 1; |
| 224 | } |
| 225 | } |
| 226 | return 0; |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | |
| 231 | |
| 232 | /** |
| 233 | Handles button events in the widget. |
| 234 | Return non zero if event is handled. |
| 235 | \param[in] event |
| 236 | */ |
| 237 | int // O - TRUE if we handled event |
| 238 | Fl_File_Input::handle_button(int event) // I - Event |
| 239 | { |
| 240 | int i, // Looping var |
| 241 | X; // Current X position |
| 242 | char *start, // Start of path component |
| 243 | *end; // End of path component |
| 244 | char newvalue[FL_PATH_MAX]; // New value |
| 245 | |
| 246 | |
| 247 | // Figure out which button is being pressed... |
| 248 | for (X = 0, i = 0; buttons_[i]; i ++) |
| 249 | { |
| 250 | X += buttons_[i]; |
| 251 | |
| 252 | if (X > xscroll() && Fl::event_x() < (x() + X - xscroll())) break; |
| 253 | } |
| 254 | |
| 255 | // printf("handle_button(event = %d), button = %d\n", event, i); |
| 256 | |
| 257 | // Redraw the directory bar... |
| 258 | if (event == FL_RELEASE) pressed_ = -1; |
| 259 | else pressed_ = (short)i; |
| 260 | |
| 261 | window()->make_current(); |
| 262 | draw_buttons(); |
| 263 | |
| 264 | // Return immediately if the user is clicking on the last button or |
| 265 | // has not released the mouse button... |
| 266 | if (!buttons_[i] || event != FL_RELEASE) return 1; |
| 267 | |
| 268 | // Figure out where to truncate the path... |
| 269 | strlcpy(newvalue, value(), sizeof(newvalue)); |
| 270 | |
| 271 | for (start = newvalue, end = start; start && i >= 0; start = end, i --) { |
| 272 | // printf(" start = \"%s\"\n", start); |
| 273 | if ((end = strchr(start, '/')) == NULL) |
| 274 | #if defined(WIN32) || defined(__EMX__) |
| 275 | if ((end = strchr(start, '\\')) == NULL) |
| 276 | #endif // WIN32 || __EMX__ |
| 277 | break; |
| 278 | |
| 279 | end ++; |
| 280 | } |
| 281 | |
| 282 | if (i < 0) { |
| 283 | // Found the end; truncate the value and update the buttons... |
| 284 | *start = '\0'; |
| 285 | value(newvalue, start - newvalue); |
| 286 | |
| 287 | // Then do the callbacks, if necessary... |
| 288 | set_changed(); |
| 289 | if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback(); |
| 290 | } |
| 291 | |
| 292 | return 1; |
| 293 | } |
| 294 | |
| 295 | |
| 296 | // |
| 297 | // End of "$Id: Fl_File_Input.cxx 8063 2010-12-19 21:20:10Z matt $". |
| 298 | // |