summaryrefslogtreecommitdiff
path: root/dw/fltkcomplexbutton.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dw/fltkcomplexbutton.cc')
-rw-r--r--dw/fltkcomplexbutton.cc345
1 files changed, 104 insertions, 241 deletions
diff --git a/dw/fltkcomplexbutton.cc b/dw/fltkcomplexbutton.cc
index f80d0eb0..359367bf 100644
--- a/dw/fltkcomplexbutton.cc
+++ b/dw/fltkcomplexbutton.cc
@@ -1,7 +1,5 @@
-
-// fltkcomplexbutton.cc contains code from FLTK2's src/Button.cxx
-// that is Copyright 1998-2006 by Bill Spitzak and others.
-// (see http://svn.easysw.com/public/fltk/fltk/trunk/src/Button.cxx)
+// fltkcomplexbutton.cc contains code from FLTK 1.3's src/Fl_Button.cxx
+// that is Copyright 1998-2010 by Bill Spitzak and others.
/*
* This program is free software; you can redistribute it and/or modify
@@ -18,263 +16,128 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <fltk/events.h>
-#include <fltk/damage.h>
-#include <fltk/Group.h>
-#include <fltk/Box.h>
-#include <stdlib.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Window.H>
#include "fltkcomplexbutton.hh"
-using namespace fltk;
using namespace dw::fltk::ui;
-/*! \class fltk::ComplexButton
-
- ComplexButtons generate callbacks when they are clicked by the user. You
- control exactly when and how by changing the values for when():
- - fltk::WHEN_NEVER: The callback is not done, instead changed() is
- turned on.
- - fltk::WHEN_RELEASE: This is the default, the callback is done
- after the user successfully clicks the button (i.e. they let it go
- with the mouse still pointing at it), or when a shortcut is typed.
- - fltk::WHEN_CHANGED : The callback is done each time the value()
- changes (when the user pushes and releases the button, and as the
- mouse is dragged around in and out of the button).
-
- ComplexButtons can also generate callbacks in response to fltk::SHORTCUT
- events. The button can either have an explicit shortcut() value or a
- letter shortcut can be indicated in the label() with an '&'
- character before it. For the label shortcut it does not matter if
- Alt is held down, but if you have an input field in the same window,
- the user will have to hold down the Alt key so that the input field
- does not eat the event first as an fltk::KEY event.
-
- \image html buttons.gif
-*/
-
-/*! \fn bool ComplexButton::value() const
- The current value. True means it is pushed down, false means it is
- not pushed down. The ToggleComplexButton subclass provides the ability for
- the user to change this value permanently, otherwise it is just
- temporary while the user is holding the button down.
-
- This is the same as Widget::state().
-*/
-
-/*! \fn bool ComplexButton::value(bool)
- Change the value(). Redraws the button and returns true if the new
- value is different. This is the same function as Widget::state().
- See also Widget::set(), Widget::clear(), and Widget::setonly().
-
- If you turn it on, a normal button will draw pushed-in, until
- the user clicks it and releases it.
-*/
-
-static bool initial_state;
+/**
+ Sets the current value of the button.
+ A non-zero value sets the button to 1 (ON), and zero sets it to 0 (OFF).
+ \param[in] v button value.
+ */
+int ComplexButton::value(int v) {
+ v = v ? 1 : 0;
+ oldval = v;
+ clear_changed();
+ if (value_ != v) {
+ value_ = v;
+ if (box()) redraw();
+ return 1;
+ } else {
+ return 0;
+ }
+}
-int ComplexButton::handle(int event) {
- return handle(event, Rectangle(w(),h()));
+void ComplexButton::draw() {
+ Fl_Color col = value() ? selection_color() : color();
+ draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col);
+ if (Fl::focus() == this) draw_focus();
+
+ // ComplexButton is a Group; draw its children
+ for (int i = children () - 1; i >= 0; i--) {
+ // set absolute coordinates for fltk-1.3 --jcid
+ child (i)->position(x()+(w()-child(i)->w())/2,y()+(h()-child(i)->h())/2);
+ draw_child (*child (i));
+ }
}
-int ComplexButton::handle(int event, const Rectangle& rectangle) {
+int ComplexButton::handle(int event) {
+ int newval;
switch (event) {
- case ENTER:
- case LEAVE:
- redraw_highlight();
- case MOVE:
+ case FL_ENTER: /* FALLTHROUGH */
+ case FL_LEAVE:
return 1;
- case PUSH:
- if (pushed()) return 1; // ignore extra pushes on currently-pushed button
- initial_state = state();
- clear_flag(PUSHED);
- /* do_callback(); */
- case DRAG: {
- bool inside = event_inside(rectangle);
- if (inside) {
- if (!flag(PUSHED)) {
- set_flag(PUSHED);
- redraw(DAMAGE_VALUE);
- }
- } else {
- if (flag(PUSHED)) {
- clear_flag(PUSHED);
- redraw(DAMAGE_VALUE);
- }
- }
- if (when() & WHEN_CHANGED) { // momentary button must record state()
- if (state(inside ? !initial_state : initial_state))
- do_callback();
+ case FL_PUSH:
+ if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this);
+ case FL_DRAG:
+ if (Fl::event_inside(this)) {
+ newval = !oldval;
+ } else
+ {
+ clear_changed();
+ newval = oldval;
}
- return 1;}
- case RELEASE:
- if (!flag(PUSHED)) return 1;
- clear_flag(PUSHED);
- redraw(DAMAGE_VALUE);
- if (type() == RADIO)
- setonly();
- else if (type() == TOGGLE)
- state(!initial_state);
- else {
- state(initial_state);
- if (when() & WHEN_CHANGED) {do_callback(); return 1;}
+ if (newval != value_) {
+ value_ = newval;
+ set_changed();
+ redraw();
+ if (when() & FL_WHEN_CHANGED) do_callback();
}
- if (when() & WHEN_RELEASE) do_callback(); else set_changed();
return 1;
- case FOCUS:
- redraw(1); // minimal redraw to just add the focus box
- // grab initial focus if we are an ReturnComplexButton:
- return shortcut()==ReturnKey ? 2 : 1;
- case UNFOCUS:
- redraw(DAMAGE_HIGHLIGHT);
- return 1;
- case KEY:
- if (event_key() == ' ' || event_key() == ReturnKey
- || event_key() == KeypadEnter) goto EXECUTE;
- return 0;
- case SHORTCUT:
- if (!test_shortcut()) return 0;
- EXECUTE:
- if (type() == RADIO) {
- if (!state()) {
- setonly();
- if (when() & WHEN_CHANGED) do_callback(); else set_changed();
- }
- } else if (type() == TOGGLE) {
- state(!state());
- if (when() & WHEN_CHANGED) do_callback(); else set_changed();
+ case FL_RELEASE:
+ if (value_ == oldval) {
+ if (when() & FL_WHEN_NOT_CHANGED) do_callback();
+ return 1;
}
- if (when() & WHEN_RELEASE) do_callback();
+ set_changed();
+ value(oldval);
+ set_changed();
+ if (when() & FL_WHEN_CHANGED) {
+ Fl_Widget_Tracker wp(this);
+ do_callback();
+ if (wp.deleted()) return 1;
+ }
+ if (when() & FL_WHEN_RELEASE) do_callback();
return 1;
+ case FL_FOCUS : /* FALLTHROUGH */
+ case FL_UNFOCUS :
+ if (Fl::visible_focus()) {
+ if (box() == FL_NO_BOX) {
+ // Widgets with the FL_NO_BOX boxtype need a parent to
+ // redraw, since it is responsible for redrawing the
+ // background...
+ int X = x() > 0 ? x() - 1 : 0;
+ int Y = y() > 0 ? y() - 1 : 0;
+ if (window()) window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2);
+ } else redraw();
+ return 1;
+ } else return 0;
+ case FL_KEYBOARD :
+ if (Fl::focus() == this && Fl::event_key() == ' ' &&
+ !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) {
+ set_changed();
+ Fl_Widget_Tracker wp(this);
+ if (wp.deleted()) return 1;
+ if (when() & FL_WHEN_RELEASE) do_callback();
+ return 1;
+ }
default:
return 0;
}
}
-////////////////////////////////////////////////////////////////
-
-#include <fltk/draw.h>
-
-extern Widget* fl_did_clipping;
-
-/*!
- This function provides a mess of back-compatabilty and Windows
- emulation to subclasses of ComplexButton to draw with. It will draw the
- button according to the current state of being pushed and it's
- state(). If non-zero is passed for \a glyph_width then the glyph()
- is drawn in that space on the left (or on the right if negative),
- and it assummes the glyph indicates the state(), so the box is only
- used to indicate the pushed state.
-*/
-void ComplexButton::draw(int glyph_width) const
-{
- // For back-compatability, setting color() or box() directly on a plain
- // button will cause it to act like buttoncolor() or buttonbox() are
- // set:
- Style localstyle;
- const Style* style = this->style();
- if (!glyph_width) {
- localstyle = *style;
- if (localstyle.color_) localstyle.buttoncolor_ = localstyle.color_;
- if (localstyle.box_) localstyle.buttonbox_ = localstyle.box_;
- if (localstyle.labelcolor_) localstyle.textcolor_ = localstyle.labelcolor_;
- style = &localstyle;
- }
-
- Box* box = style->buttonbox();
-
- Flags box_flags = flags() | OUTPUT;
- Flags glyph_flags = box_flags & ~(HIGHLIGHT|OUTPUT);
- if (glyph_width) box_flags &= ~STATE;
-
- // only draw "inside" labels:
- Rectangle r(0,0,w(),h());
-
- if (box == NO_BOX) {
- Color bg;
- if (box_flags & HIGHLIGHT && (bg = style->highlight_color())) {
- setcolor(bg);
- fillrect(r);
- } else if (label() || (damage()&(DAMAGE_EXPOSE|DAMAGE_HIGHLIGHT))) {
- // erase the background so we can redraw the label in the new color:
- draw_background();
- }
- // this allows these buttons to be put into browser/menus:
- //fg = fl_item_labelcolor(this);
- } else {
- if ((damage()&(DAMAGE_EXPOSE|DAMAGE_HIGHLIGHT))
- && !box->fills_rectangle()) {
- // Erase the area behind non-square boxes
- draw_background();
- }
- }
-
- // Draw the box:
- drawstyle(style,box_flags);
- // For back-compatability we use any directly-set selection_color()
- // to color the box:
- if (!glyph_width && state() && style->selection_color_) {
- setbgcolor(style->selection_color_);
- setcolor(contrast(style->selection_textcolor(),style->selection_color_));
- }
- box->draw(r);
- Rectangle r1(r); box->inset(r1);
-
- if (glyph_width) {
- int g = abs(glyph_width);
- Rectangle lr(r1);
- Rectangle gr(r1, g, g);
- if (glyph_width < 0) {
- lr.w(lr.w()-g-3);
- gr.x(r1.r()-g-3);
- } else {
- lr.set_x(g+3);
- gr.x(r1.x()+3);
- }
- this->draw_label(lr, box_flags);
- drawstyle(style,glyph_flags);
- this->glyph()->draw(gr);
- drawstyle(style,box_flags);
- } else {
- this->draw_label(r1, box_flags);
- }
- box->draw_symbol_overlay(r);
-}
-
-void ComplexButton::draw() {
- if (type() == HIDDEN) {
- fl_did_clipping = this;
- return;
- }
- draw(0);
-
- // ComplexButton is a Group, draw its children
- for (int i = children () - 1; i >= 0; i--)
- draw_child (*child (i));
+/**
+ The constructor creates the button using the given position, size and label.
+ \param[in] X, Y, W, H position and size of the widget
+ \param[in] L widget label, default is no label
+ */
+ComplexButton::ComplexButton(int X, int Y, int W, int H, const char *L)
+: Fl_Group(X,Y,W,H,L) {
+ Fl_Group::current(0);
+ box(FL_UP_BOX);
+ down_box(FL_NO_BOX);
+ value_ = oldval = 0;
}
-////////////////////////////////////////////////////////////////
-
-static NamedStyle style("ComplexButton", 0, &ComplexButton::default_style);
-NamedStyle* ComplexButton::default_style = &::style;
-
-ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) :
- Group(x,y,w,h,l)
-{
- style(default_style);
- highlight_color(GRAY20);
- //set_click_to_focus();
+ComplexButton::~ComplexButton() {
+ /*
+ * The Fl_Group destructor clear()s the children, but layout expects
+ * the flat view to be around until it deletes if.
+ */
+ remove(0);
}
-
-////////////////////////////////////////////////////////////////
-
-/*! \class fltk::ToggleComplexButton
- This button turns the state() on and off each release of a click
- inside of it.
-
- You can also convert a regular button into this by doing
- type(ComplexButton::TOGGLE) to it.
-*/
-
-//
-//