1 // 2 // "$Id: Fl_Input_Choice.H 8022 2010-12-12 23:21:03Z AlbrechtS $" 3 // 4 // An input/chooser widget. 5 // ______________ ____ 6 // | || __ | 7 // | input area || \/ | 8 // |______________||____| 9 // 10 // Copyright 1998-2010 by Bill Spitzak and others. 11 // Copyright 2004 by Greg Ercolano. 12 // 13 // This library is free software; you can redistribute it and/or 14 // modify it under the terms of the GNU Library General Public 15 // License as published by the Free Software Foundation; either 16 // version 2 of the License, or (at your option) any later version. 17 // 18 // This library is distributed in the hope that it will be useful, 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 // Library General Public License for more details. 22 // 23 // You should have received a copy of the GNU Library General Public 24 // License along with this library; if not, write to the Free Software 25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 26 // USA. 27 // 28 // Please report all bugs and problems on the following page: 29 // 30 // http://www.fltk.org/str.php 31 // 32 33 /* \file 34 Fl_Input_Choice widget . */ 35 36 37 38 #ifndef Fl_Input_Choice_H 39 #define Fl_Input_Choice_H 40 41 #include <FL/Fl.H> 42 #include <FL/Fl_Group.H> 43 #include <FL/Fl_Input.H> 44 #include <FL/Fl_Menu_Button.H> 45 #include <FL/fl_draw.H> 46 #include <string.h> 47 48 /** 49 A combination of the input widget and a menu button. 50 The user can either type into the input area, or use the 51 menu button chooser on the right, which loads the input area 52 with predefined text. Normally it is drawn with an inset box 53 and a white background. 54 <P> 55 The application can directly access both the input and menu 56 widgets directly, using the menubutton() 57 and input() accessor methods. 58 */ 59 class FL_EXPORT Fl_Input_Choice : public Fl_Group { 60 // Private class to handle slightly 'special' behavior of menu button 61 class InputMenuButton : public Fl_Menu_Button { draw()62 void draw() { 63 draw_box(FL_UP_BOX, color()); 64 fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor())); 65 int xc = x()+w()/2, yc=y()+h()/2; 66 fl_polygon(xc-5,yc-3,xc+5,yc-3,xc,yc+3); 67 if (Fl::focus() == this) draw_focus(); 68 } 69 public: 70 InputMenuButton(int x,int y,int w,int h,const char*l=0) : Fl_Menu_Button(x,y,w,h,l)71 Fl_Menu_Button(x,y,w,h,l) { box(FL_UP_BOX); } 72 }; 73 74 Fl_Input *inp_; 75 InputMenuButton *menu_; 76 menu_cb(Fl_Widget *,void * data)77 static void menu_cb(Fl_Widget*, void *data) { 78 Fl_Input_Choice *o=(Fl_Input_Choice *)data; 79 Fl_Widget_Tracker wp(o); 80 const Fl_Menu_Item *item = o->menubutton()->mvalue(); 81 if (item && item->flags & (FL_SUBMENU|FL_SUBMENU_POINTER)) return; // ignore submenus 82 if (!strcmp(o->inp_->value(), o->menu_->text())) 83 { 84 o->Fl_Widget::clear_changed(); 85 if (o->when() & FL_WHEN_NOT_CHANGED) 86 o->do_callback(); 87 } 88 else 89 { 90 o->inp_->value(o->menu_->text()); 91 o->inp_->set_changed(); 92 o->Fl_Widget::set_changed(); 93 if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE)) 94 o->do_callback(); 95 } 96 97 if (wp.deleted()) return; 98 99 if (o->callback() != default_callback) 100 { 101 o->Fl_Widget::clear_changed(); 102 o->inp_->clear_changed(); 103 } 104 } 105 inp_cb(Fl_Widget *,void * data)106 static void inp_cb(Fl_Widget*, void *data) { 107 Fl_Input_Choice *o=(Fl_Input_Choice *)data; 108 Fl_Widget_Tracker wp(o); 109 if (o->inp_->changed()) { 110 o->Fl_Widget::set_changed(); 111 if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE)) 112 o->do_callback(); 113 } else { 114 o->Fl_Widget::clear_changed(); 115 if (o->when() & FL_WHEN_NOT_CHANGED) 116 o->do_callback(); 117 } 118 119 if (wp.deleted()) return; 120 121 if (o->callback() != default_callback) 122 o->Fl_Widget::clear_changed(); 123 } 124 125 // Custom resize behavior -- input stretches, menu button doesn't inp_x()126 inline int inp_x() { return(x() + Fl::box_dx(box())); } inp_y()127 inline int inp_y() { return(y() + Fl::box_dy(box())); } inp_w()128 inline int inp_w() { return(w() - Fl::box_dw(box()) - 20); } inp_h()129 inline int inp_h() { return(h() - Fl::box_dh(box())); } 130 menu_x()131 inline int menu_x() { return(x() + w() - 20 - Fl::box_dx(box())); } menu_y()132 inline int menu_y() { return(y() + Fl::box_dy(box())); } menu_w()133 inline int menu_w() { return(20); } menu_h()134 inline int menu_h() { return(h() - Fl::box_dh(box())); } 135 136 public: 137 /** 138 Creates a new Fl_Input_Choice widget using the given position, size, 139 and label string. 140 <P> Inherited destructor Destroys the widget and any value associated with it. 141 */ Fl_Group(x,y,w,h,l)142 Fl_Input_Choice (int x,int y,int w,int h,const char*l=0) : Fl_Group(x,y,w,h,l) { 143 Fl_Group::box(FL_DOWN_BOX); 144 align(FL_ALIGN_LEFT); // default like Fl_Input 145 inp_ = new Fl_Input(inp_x(), inp_y(), 146 inp_w(), inp_h()); 147 inp_->callback(inp_cb, (void*)this); 148 inp_->box(FL_FLAT_BOX); // cosmetic 149 inp_->when(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED); 150 menu_ = new InputMenuButton(menu_x(), menu_y(), 151 menu_w(), menu_h()); 152 menu_->callback(menu_cb, (void*)this); 153 menu_->box(FL_FLAT_BOX); // cosmetic 154 end(); 155 } 156 157 /** Adds an item to the menu.*/ add(const char * s)158 void add(const char *s) { menu_->add(s); } changed()159 int changed() const { return inp_->changed() | Fl_Widget::changed();} clear_changed()160 void clear_changed() { 161 inp_->clear_changed(); 162 Fl_Widget::clear_changed(); 163 } set_changed()164 void set_changed() { 165 inp_->set_changed(); 166 // no need to call Fl_Widget::set_changed() 167 } 168 /** Removes all items from the menu. */ clear()169 void clear() { menu_->clear(); } 170 /** Gets the box type of the menu button */ down_box()171 Fl_Boxtype down_box() const { return (menu_->down_box()); } 172 /** Sets the box type of the menu button */ down_box(Fl_Boxtype b)173 void down_box(Fl_Boxtype b) { menu_->down_box(b); } 174 /** Gets the Fl_Menu_Item array used for the menu. */ menu()175 const Fl_Menu_Item *menu() { return (menu_->menu()); } 176 /** Sets the Fl_Menu_Item array used for the menu. */ menu(const Fl_Menu_Item * m)177 void menu(const Fl_Menu_Item *m) { menu_->menu(m); } resize(int X,int Y,int W,int H)178 void resize(int X, int Y, int W, int H) { 179 Fl_Group::resize(X,Y,W,H); 180 inp_->resize(inp_x(), inp_y(), inp_w(), inp_h()); 181 menu_->resize(menu_x(), menu_y(), menu_w(), menu_h()); 182 } 183 /** Gets the encapsulated input text color attributes */ textcolor()184 Fl_Color textcolor() const { return (inp_->textcolor());} 185 /** Sets the encapsulated input text color attributes */ textcolor(Fl_Color c)186 void textcolor(Fl_Color c) { inp_->textcolor(c);} 187 /** Gets the encapsulated input text font attributes */ textfont()188 Fl_Font textfont() const { return (inp_->textfont());} 189 /** Sets the encapsulated input text font attributes */ textfont(Fl_Font f)190 void textfont(Fl_Font f) { inp_->textfont(f);} 191 /** Gets the encapsulated input size attributes */ textsize()192 Fl_Fontsize textsize() const { return (inp_->textsize()); } 193 /** Sets the encapsulated input size attributes */ textsize(Fl_Fontsize s)194 void textsize(Fl_Fontsize s) { inp_->textsize(s); } 195 /** See void Fl_Input_Choice::value(const char *s) */ value()196 const char* value() const { return (inp_->value()); } 197 /** 198 Sets or returns the input widget's current contents. The 199 second form sets the contents using the index into the menu 200 which you can set as an integer. Setting the value effectively 201 'chooses' this menu item, and sets it as the new input text, 202 deleting the previous text. 203 */ value(const char * val)204 void value(const char *val) { inp_->value(val); } 205 /** See void Fl_Input_Choice::value(const char *s) */ value(int val)206 void value(int val) { 207 menu_->value(val); 208 inp_->value(menu_->text(val)); 209 } 210 /** Returns a reference to the internal Fl_Menu_Button widget. */ menubutton()211 Fl_Menu_Button *menubutton() { return menu_; } 212 /** 213 Returns a reference to the internal Fl_Input widget.</p> 214 */ input()215 Fl_Input *input() { return inp_; } 216 }; 217 218 #endif // !Fl_Input_Choice_H 219 220 // 221 // End of "$Id: Fl_Input_Choice.H 8022 2010-12-12 23:21:03Z AlbrechtS $". 222 // 223