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