FLTK 1.3.0
Fl_Input_Choice.H
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 
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 {
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) :
71  Fl_Menu_Button(x,y,w,h,l) { box(FL_UP_BOX); }
72  };
73 
74  Fl_Input *inp_;
75  InputMenuButton *menu_;
76 
77  static void menu_cb(Fl_Widget*, void *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();
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 
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
126  inline int inp_x() { return(x() + Fl::box_dx(box())); }
127  inline int inp_y() { return(y() + Fl::box_dy(box())); }
128  inline int inp_w() { return(w() - Fl::box_dw(box()) - 20); }
129  inline int inp_h() { return(h() - Fl::box_dh(box())); }
130 
131  inline int menu_x() { return(x() + w() - 20 - Fl::box_dx(box())); }
132  inline int menu_y() { return(y() + Fl::box_dy(box())); }
133  inline int menu_w() { return(20); }
134  inline int menu_h() { return(h() - Fl::box_dh(box())); }
135 
136 public:
142  Fl_Input_Choice (int x,int y,int w,int h,const char*l=0) : Fl_Group(x,y,w,h,l) {
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
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 
158  void add(const char *s) { menu_->add(s); }
159  int changed() const { return inp_->changed() | Fl_Widget::changed();}
160  void clear_changed() {
161  inp_->clear_changed();
163  }
164  void set_changed() {
165  inp_->set_changed();
166  // no need to call Fl_Widget::set_changed()
167  }
169  void clear() { menu_->clear(); }
171  Fl_Boxtype down_box() const { return (menu_->down_box()); }
173  void down_box(Fl_Boxtype b) { menu_->down_box(b); }
175  const Fl_Menu_Item *menu() { return (menu_->menu()); }
177  void menu(const Fl_Menu_Item *m) { menu_->menu(m); }
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  }
184  Fl_Color textcolor() const { return (inp_->textcolor());}
186  void textcolor(Fl_Color c) { inp_->textcolor(c);}
188  Fl_Font textfont() const { return (inp_->textfont());}
190  void textfont(Fl_Font f) { inp_->textfont(f);}
192  Fl_Fontsize textsize() const { return (inp_->textsize()); }
194  void textsize(Fl_Fontsize s) { inp_->textsize(s); }
196  const char* value() const { return (inp_->value()); }
204  void value(const char *val) { inp_->value(val); }
206  void value(int val) {
207  menu_->value(val);
208  inp_->value(menu_->text(val));
209  }
211  Fl_Menu_Button *menubutton() { return menu_; }
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 //