Separated Fl_Input_Choice.H and Fl_Input_Choice.cxx (STR #2750).

As proposed in STR #2750 and #2752: only status quo, i.e.:

  - no new method Fl_Input_Choice::maximum_size(int) (STR #2750 and #2752)
  - no handling of FL_Down key to open menu (STR #2752)


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12192 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Albrecht Schlosser 2017-03-11 23:26:32 +00:00
parent 5544404f7a
commit a1d555bd80
6 changed files with 297 additions and 185 deletions

View File

@ -45,6 +45,7 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2017
Other Improvements
- (add new items here)
- Separated Fl_Input_Choice.H and Fl_Input_Choice.cxx (STR #2750, #2752).
- Separated Fl_Spinner.H and Fl_Spinner.cxx (STR #2776).
- New method Fl_Spinner::wrap(int) allows to set wrap mode at bounds if
value is changed by pressing or holding one of the buttons (STR #3365).

View File

@ -7,7 +7,7 @@
// | input area || \/ |
// |______________||____|
//
// Copyright 1998-2010 by Bill Spitzak and others.
// Copyright 1998-2017 by Bill Spitzak and others.
// Copyright 2004 by Greg Ercolano.
//
// This library is free software. Distribution and use rights are outlined in
@ -31,134 +31,41 @@
#include <FL/Fl_Group.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/fl_draw.H>
#include <string.h>
/**
// Leaving these two headers so builds don't break if user includes this
// header and uses items from fl_draw or string (but doesn't include in src).
// Note: this would ensure compatibility with FLTK 1.3.x.
// Shall we? Currently not!
// #include <FL/fl_draw.H>
// #include <string.h>
/*
A combination of the input widget and a menu button.
\image html input_choice.jpg
\image latex input_choice.jpg "Fl_Input_Choice widget" width=6cm
The user can either type into the input area, or use the
menu button chooser on the right to choose an item which loads
the input area with the selected text.
The application can directly access both the internal Fl_Input
and Fl_Menu_Button widgets respectively using the input() and menubutton()
accessor methods.
The default behavior is to invoke the Fl_Input_Choice::callback()
if the user changes the input field's contents, either by typing,
pasting, or clicking a different item in the choice menu.
The callback can determine if an item was picked vs. typing
into the input field by checking the value of menubutton()->changed(),
which will be:
- 1: the user picked a different item in the choice menu
- 0: the user typed or pasted directly into the input field
Example use:
\code
#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Input_Choice.H>
void choice_cb(Fl_Widget *w, void *userdata) {
// Show info about the picked item
Fl_Input_Choice *choice = (Fl_Input_Choice*)w;
const Fl_Menu_Item *item = choice->menubutton()->mvalue();
printf("*** Choice Callback:\n");
printf(" item label()='%s'\n", item ? item->label() : "(No item)");
printf(" item value()=%d\n", choice->menubutton()->value());
printf(" input value()='%s'\n", choice->input()->value());
printf(" The user %s\n", choice->menubutton()->changed()
? "picked a menu item"
: "typed text");
}
int main() {
Fl_Double_Window win(200,100,"Input Choice");
win.begin();
Fl_Input_Choice choice(10,10,100,30);
choice.callback(choice_cb, 0);
choice.add("Red");
choice.add("Orange");
choice.add("Yellow");
//choice.value("Red"); // uncomment to make "Red" default
win.end();
win.show();
return Fl::run();
}
\endcode
Note: doxygen docs in src/Fl_Input_Choice.cxx
*/
class FL_EXPORT Fl_Input_Choice : public Fl_Group {
// Private class to handle slightly 'special' behavior of menu button
class InputMenuButton : public Fl_Menu_Button {
void draw() {
draw_box(FL_UP_BOX, color());
fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor()));
int xc = x()+w()/2, yc=y()+h()/2;
fl_polygon(xc-5,yc-3,xc+5,yc-3,xc,yc+3);
if (Fl::focus() == this) draw_focus();
}
void draw();
public:
InputMenuButton(int X,int Y,int W,int H,const char*L=0) :
Fl_Menu_Button(X, Y, W, H, L) { box(FL_UP_BOX); }
InputMenuButton(int X, int Y, int W, int H, const char *L=0);
};
Fl_Input *inp_;
InputMenuButton *menu_;
// note: this is used by the Fl_Input_Choice ctor defined in Fl_Group.
static void menu_cb(Fl_Widget*, void *data) {
Fl_Input_Choice *o=(Fl_Input_Choice *)data;
Fl_Widget_Tracker wp(o);
const Fl_Menu_Item *item = o->menubutton()->mvalue();
if (item && item->flags & (FL_SUBMENU|FL_SUBMENU_POINTER)) return; // ignore submenus
if (!strcmp(o->inp_->value(), o->menu_->text()))
{
o->Fl_Widget::clear_changed();
if (o->when() & FL_WHEN_NOT_CHANGED)
o->do_callback();
}
else
{
o->inp_->value(o->menu_->text());
o->inp_->set_changed();
o->Fl_Widget::set_changed();
if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
o->do_callback();
}
if (wp.deleted()) return;
// note: this is used by the Fl_Input_Choice ctor.
static void menu_cb(Fl_Widget*, void *data);
if (o->callback() != default_callback)
{
o->Fl_Widget::clear_changed();
o->inp_->clear_changed();
}
}
// note: this is used by the Fl_Input_Choice ctor defined in Fl_Group.
static void inp_cb(Fl_Widget*, void *data) {
Fl_Input_Choice *o=(Fl_Input_Choice *)data;
Fl_Widget_Tracker wp(o);
if (o->inp_->changed()) {
o->Fl_Widget::set_changed();
if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
o->do_callback();
} else {
o->Fl_Widget::clear_changed();
if (o->when() & FL_WHEN_NOT_CHANGED)
o->do_callback();
}
if (wp.deleted()) return;
if (o->callback() != default_callback)
o->Fl_Widget::clear_changed();
}
// note: this is used by the Fl_Input_Choice ctor.
static void inp_cb(Fl_Widget*, void *data);
// Custom resize behavior -- input stretches, menu button doesn't
inline int inp_x() { return(x() + Fl::box_dx(box())); }
@ -172,92 +79,96 @@ class FL_EXPORT Fl_Input_Choice : public Fl_Group {
inline int menu_h() { return(h() - Fl::box_dh(box())); }
public:
/**
Creates a new Fl_Input_Choice widget using the given position, size,
and label string.
Inherited destructor destroys the widget and any values associated with it.
*/
Fl_Input_Choice(int X,int Y,int W,int H,const char*L=0);
Fl_Input_Choice(int X, int Y, int W, int H, const char *L=0);
void resize(int X, int Y, int W, int H);
/** Adds an item to the menu.
You can access the more complex Fl_Menu_Button::add() methods
(setting callbacks, userdata, etc), via menubutton(). Example:
\code
Fl_Input_Choice *choice = new Fl_Input_Choice(100,10,120,25,"Fonts");
Fl_Menu_Button *mb = choice->menubutton(); // use Fl_Input_Choice's Fl_Menu_Button
mb->add("Helvetica", 0, MyFont_CB, (void*)mydata); // use Fl_Menu_Button's add() methods
mb->add("Courier", 0, MyFont_CB, (void*)mydata);
mb->add("More..", 0, FontDialog_CB, (void*)mydata);
\endcode
*/
void add(const char *s) { menu_->add(s); }
You can access the more complex Fl_Menu_Button::add() methods
(setting callbacks, userdata, etc), via menubutton(). Example:
\code
Fl_Input_Choice *choice = new Fl_Input_Choice(100,10,120,25,"Fonts");
Fl_Menu_Button *mb = choice->menubutton(); // use Fl_Input_Choice's Fl_Menu_Button
mb->add("Helvetica", 0, MyFont_CB, (void*)mydata); // use Fl_Menu_Button's add() methods
mb->add("Courier", 0, MyFont_CB, (void*)mydata);
mb->add("More..", 0, FontDialog_CB, (void*)mydata);
\endcode
*/
void add(const char *s) { menu_->add(s); }
/** Returns the combined changed() state of the input and menu button widget. */
int changed() const { return inp_->changed() | Fl_Widget::changed(); }
/** Clears the changed() state of both input and menu button widgets. */
void clear_changed() {
inp_->clear_changed();
Fl_Widget::clear_changed();
}
/** Sets the changed() state of both input and menu button widgets
to the specfied value.*/
void set_changed() {
inp_->set_changed();
// no need to call Fl_Widget::set_changed()
}
// Clears the changed() state of both input and menu button widgets.
void clear_changed();
// Sets the changed() state of both input and menu button widgets.
void set_changed();
/** Removes all items from the menu. */
void clear() { menu_->clear(); }
/** Gets the box type of the menu button */
Fl_Boxtype down_box() const { return (menu_->down_box()); }
/** Sets the box type of the menu button */
void down_box(Fl_Boxtype b) { menu_->down_box(b); }
/** Gets the Fl_Menu_Item array used for the menu. */
const Fl_Menu_Item *menu() { return (menu_->menu()); }
/** Sets the Fl_Menu_Item array used for the menu. */
void menu(const Fl_Menu_Item *m) { menu_->menu(m); }
void resize(int X, int Y, int W, int H) {
Fl_Group::resize(X,Y,W,H);
inp_->resize(inp_x(), inp_y(), inp_w(), inp_h());
menu_->resize(menu_x(), menu_y(), menu_w(), menu_h());
}
/// Gets the Fl_Input text field's text color.
Fl_Color textcolor() const { return (inp_->textcolor());}
/// Sets the Fl_Input text field's text color to \p c.
void textcolor(Fl_Color c) { inp_->textcolor(c);}
/// Gets the Fl_Input text field's font style.
Fl_Font textfont() const { return (inp_->textfont());}
/// Sets the Fl_Input text field's font style to \p f.
void textfont(Fl_Font f) { inp_->textfont(f);}
/// Gets the Fl_Input text field's font size
Fl_Fontsize textsize() const { return (inp_->textsize()); }
/// Sets the Fl_Input text field's font size to \p s.
void textsize(Fl_Fontsize s) { inp_->textsize(s); }
/// Returns the Fl_Input text field's current contents.
const char* value() const { return (inp_->value()); }
/** Sets the Fl_Input text field's contents to \p val.
Does not affect the menu selection.*/
Does not affect the menu selection.
\see void value(int val)
*/
void value(const char *val) { inp_->value(val); }
/** Chooses item# \p val in the menu, and sets the Fl_Input text field
to that value. Any previous text is cleared.*/
void value(int val) {
menu_->value(val);
inp_->value(menu_->text(val));
}
/* Chooses item# \p val in the menu, and sets the Fl_Input text field
to that value. Any previous text is cleared. */
void value(int val);
/** Returns a pointer to the internal Fl_Menu_Button widget.
This can be used to access any of the methods of the menu button, e.g.
\code
Fl_Input_Choice *choice = new Fl_Input_Choice(100,10,120,25,"Choice:");
[..]
// Print all the items in the choice menu
for ( int t=0; t<choice->menubutton()->size(); t++ ) {
This can be used to access any of the methods of the menu button, e.g.
\code
Fl_Input_Choice *choice = new Fl_Input_Choice(100,10,120,25,"Choice:");
[..]
// Print all the items in the choice menu
for ( int t=0; t<choice->menubutton()->size(); t++ ) {
const Fl_Menu_Item &item = choice->menubutton()->menu()[t];
printf("item %d -- label=%s\n", t, item.label() ? item.label() : "(Null)");
}
\endcode
}
\endcode
*/
Fl_Menu_Button *menubutton() { return menu_; }
/** Returns a pointer to the internal Fl_Input widget.
This can be used to directly access all of the Fl_Input widget's
methods.*/
This can be used to directly access all of the Fl_Input widget's methods.
*/
Fl_Input *input() { return inp_; }
};

View File

@ -32,6 +32,7 @@ set (CPPFILES
Fl_Image_Surface.cxx
Fl_Input.cxx
Fl_Input_.cxx
Fl_Input_Choice.cxx
Fl_Light_Button.cxx
Fl_Menu.cxx
Fl_Menu_.cxx

View File

@ -3,7 +3,7 @@
//
// Group widget for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2010 by Bill Spitzak and others.
// Copyright 1998-2017 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -28,10 +28,6 @@
#include <FL/fl_draw.H>
#include <stdlib.h>
#include <FL/Fl_Input_Choice.H>
#include <FL/Fl_Spinner.H>
Fl_Group* Fl_Group::current_;
// Hack: A single child is stored in the pointer to the array, while
@ -834,24 +830,6 @@ void Fl_Group::draw_outside_label(const Fl_Widget& widget) const {
}
Fl_Input_Choice::Fl_Input_Choice (int X,int Y,int W,int H,const char*L)
: Fl_Group(X,Y,W,H,L)
{
Fl_Group::box(FL_DOWN_BOX);
align(FL_ALIGN_LEFT); // default like Fl_Input
inp_ = new Fl_Input(inp_x(), inp_y(),
inp_w(), inp_h());
inp_->callback(inp_cb, (void*)this);
inp_->box(FL_FLAT_BOX); // cosmetic
inp_->when(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED);
menu_ = new InputMenuButton(menu_x(), menu_y(),
menu_w(), menu_h());
menu_->callback(menu_cb, (void*)this);
menu_->box(FL_FLAT_BOX); // cosmetic
end();
}
//
// End of "$Id$".
//

220
src/Fl_Input_Choice.cxx Normal file
View File

@ -0,0 +1,220 @@
//
// "$Id$"
//
// An input/chooser widget.
// ______________ ____
// | || __ |
// | input area || \/ |
// |______________||____|
//
// Copyright 1998-2017 by Bill Spitzak and others.
// Copyright 2004 by Greg Ercolano.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/* \file
Fl_Input_Choice widget . */
#include <FL/Fl_Input_Choice.H>
#include <FL/fl_draw.H>
#include <string.h>
/**
\class Fl_Input_Choice
\brief A combination of the input widget and a menu button.
\image html input_choice.jpg
\image latex input_choice.jpg "Fl_Input_Choice widget" width=6cm
The user can either type into the input area, or use the
menu button chooser on the right to choose an item which loads
the input area with the selected text.
The application can directly access both the internal Fl_Input
and Fl_Menu_Button widgets respectively using the input() and menubutton()
accessor methods.
The default behavior is to invoke the Fl_Input_Choice::callback()
if the user changes the input field's contents, either by typing,
pasting, or clicking a different item in the choice menu.
The callback can determine if an item was picked vs. typing
into the input field by checking the value of menubutton()->changed(),
which will be:
- 1: the user picked a different item in the choice menu
- 0: the user typed or pasted directly into the input field
Example use:
\code
#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Input_Choice.H>
void choice_cb(Fl_Widget *w, void *userdata) {
// Show info about the picked item
Fl_Input_Choice *choice = (Fl_Input_Choice*)w;
const Fl_Menu_Item *item = choice->menubutton()->mvalue();
printf("*** Choice Callback:\n");
printf(" item label()='%s'\n", item ? item->label() : "(No item)");
printf(" item value()=%d\n", choice->menubutton()->value());
printf(" input value()='%s'\n", choice->input()->value());
printf(" The user %s\n", choice->menubutton()->changed()
? "picked a menu item"
: "typed text");
}
int main() {
Fl_Double_Window win(200,100,"Input Choice");
win.begin();
Fl_Input_Choice choice(10,10,100,30);
choice.callback(choice_cb, 0);
choice.add("Red");
choice.add("Orange");
choice.add("Yellow");
//choice.value("Red"); // uncomment to make "Red" default
win.end();
win.show();
return Fl::run();
}
\endcode
*/
/** Constructor for private menu button. */
Fl_Input_Choice::InputMenuButton::InputMenuButton(int x,int y,int w,int h,const char*l)
:Fl_Menu_Button(x,y,w,h,l)
{
box(FL_UP_BOX);
};
/** Draws the private menu button. */
void Fl_Input_Choice::InputMenuButton::draw() {
draw_box(FL_UP_BOX, color());
fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor()));
int xc = x()+w()/2, yc=y()+h()/2;
fl_polygon(xc-5,yc-3,xc+5,yc-3,xc,yc+3);
if (Fl::focus() == this) draw_focus();
}
/** Callback for the Fl_Input_Choice menu. */
void Fl_Input_Choice::menu_cb(Fl_Widget*, void *data) {
Fl_Input_Choice *o=(Fl_Input_Choice *)data;
Fl_Widget_Tracker wp(o);
const Fl_Menu_Item *item = o->menubutton()->mvalue();
if (item && item->flags & (FL_SUBMENU|FL_SUBMENU_POINTER)) return; // ignore submenus
if (!strcmp(o->inp_->value(), o->menu_->text()))
{
o->Fl_Widget::clear_changed();
if (o->when() & FL_WHEN_NOT_CHANGED)
o->do_callback();
}
else
{
o->inp_->value(o->menu_->text());
o->inp_->set_changed();
o->Fl_Widget::set_changed();
if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
o->do_callback();
}
if (wp.deleted()) return;
if (o->callback() != default_callback)
{
o->Fl_Widget::clear_changed();
o->inp_->clear_changed();
}
}
/** Callback for the Fl_Input_Choice input field. */
void Fl_Input_Choice::inp_cb(Fl_Widget*, void *data) {
Fl_Input_Choice *o=(Fl_Input_Choice *)data;
Fl_Widget_Tracker wp(o);
if (o->inp_->changed()) {
o->Fl_Widget::set_changed();
if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
o->do_callback();
} else {
o->Fl_Widget::clear_changed();
if (o->when() & FL_WHEN_NOT_CHANGED)
o->do_callback();
}
if (wp.deleted()) return;
if (o->callback() != default_callback)
o->Fl_Widget::clear_changed();
}
/**
Creates a new Fl_Input_Choice widget using the given position, size,
and label string.
Inherited destructor destroys the widget and any values associated with it.
*/
Fl_Input_Choice::Fl_Input_Choice (int X, int Y, int W, int H, const char *L)
: Fl_Group(X,Y,W,H,L) {
Fl_Group::box(FL_DOWN_BOX);
align(FL_ALIGN_LEFT); // default like Fl_Input
inp_ = new Fl_Input(inp_x(), inp_y(),
inp_w(), inp_h());
inp_->callback(inp_cb, (void*)this);
inp_->box(FL_FLAT_BOX); // cosmetic
inp_->when(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED);
menu_ = new InputMenuButton(menu_x(), menu_y(),
menu_w(), menu_h());
menu_->callback(menu_cb, (void*)this);
menu_->box(FL_FLAT_BOX); // cosmetic
end();
}
/** Resizes the Fl_Input_Choice widget.
*/
void Fl_Input_Choice::resize(int X, int Y, int W, int H) {
Fl_Group::resize(X,Y,W,H);
inp_->resize(inp_x(), inp_y(), inp_w(), inp_h());
menu_->resize(menu_x(), menu_y(), menu_w(), menu_h());
}
/** Chooses item# \p val in the menu, and sets the Fl_Input text field
to that value. Any previous text is cleared.
\see void value(const char *val)
*/
void Fl_Input_Choice::value(int val) {
menu_->value(val);
inp_->value(menu_->text(val));
}
/** Sets the changed() state of both input and menu button widgets
to the specified value.
*/
void Fl_Input_Choice::set_changed() {
inp_->set_changed();
// no need to call Fl_Widget::set_changed()
}
/** Clears the changed() state of both input and menu button widgets. */
void Fl_Input_Choice::clear_changed() {
inp_->clear_changed();
Fl_Widget::clear_changed();
}
//
// End of "$Id$".
//

View File

@ -51,6 +51,7 @@ CPPFILES = \
Fl_Image_Surface.cxx \
Fl_Input.cxx \
Fl_Input_.cxx \
Fl_Input_Choice.cxx \
Fl_Light_Button.cxx \
Fl_Menu.cxx \
Fl_Menu_.cxx \