summaryrefslogtreecommitdiff
path: root/src/Fl_Counter.cxx
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2020-11-22 19:19:19 +0100
committerAlbrecht Schlosser <albrechts.fltk@online.de>2022-11-22 19:32:54 +0100
commitecc47d0cc3e1784e17ac94829202f2bdbd38a682 (patch)
tree2519c9b11a598ed4ad1faf9d07c205da5c4903c7 /src/Fl_Counter.cxx
parent4daec2a9408c674f8d62f8770ec8c035c25f2294 (diff)
Refactor and simplify "arrow drawing" in widgets
"Arrows" in widgets are those GUI elements mostly represented by triangles pointing in a particular direction as in scrollbars, choice widgets, some menus, valuators and Fl_Counter widgets. The code has been simplified and standardized such that all these GUI elements are drawn identically per FLTK scheme. Widget authors no longer need to write code to calculate arrow sizes and draw polygons etc. Different schemes can and do implement different drawing functions. Todo: see comments "FIXME_ARROW" in src/Fl_Menu_Button.cxx and src/Fl_Menu.cxx
Diffstat (limited to 'src/Fl_Counter.cxx')
-rw-r--r--src/Fl_Counter.cxx155
1 files changed, 103 insertions, 52 deletions
diff --git a/src/Fl_Counter.cxx b/src/Fl_Counter.cxx
index ed856c208..9a9b4bbfc 100644
--- a/src/Fl_Counter.cxx
+++ b/src/Fl_Counter.cxx
@@ -19,67 +19,118 @@
#include <FL/Fl_Simple_Counter.H>
#include <FL/fl_draw.H>
-void Fl_Counter::draw() {
- int i; Fl_Boxtype boxtype[5];
- Fl_Color selcolor;
-
- boxtype[0] = box();
- if (boxtype[0] == FL_UP_BOX) boxtype[0] = FL_DOWN_BOX;
- if (boxtype[0] == FL_THIN_UP_BOX) boxtype[0] = FL_THIN_DOWN_BOX;
- for (i=1; i<5; i++)
- if (mouseobj == i)
- boxtype[i] = fl_down(box());
- else
- boxtype[i] = box();
+// This struct describes the four arrow boxes
+struct arrow_box {
+ int width;
+ Fl_Arrow_Type arrow_type;
+ Fl_Boxtype boxtype;
+ Fl_Orientation orientation;
+ arrow_box() { // constructor
+ width = 0;
+ boxtype = FL_NO_BOX;
+ orientation = FL_ORIENT_RIGHT;
+ arrow_type = FL_ARROW_SINGLE;
+ }
+};
- int xx[5], ww[5];
- if (type() == FL_NORMAL_COUNTER) {
- int W = w()*15/100;
- xx[1] = x(); ww[1] = W;
- xx[2] = x()+1*W; ww[2] = W;
- xx[0] = x()+2*W; ww[0] = w()-4*W;
- xx[3] = x()+w()-2*W; ww[3] = W;
- xx[4] = x()+w()-1*W; ww[4] = W;
+/**
+ Compute sizes (widths) of arrow boxes.
+
+ This method computes the two sizes of the arrow boxes of Fl_Counter.
+ You can override it in a subclass if you want to draw fancy arrows
+ or change the layout. However, the basic layout is fixed and can't
+ be changed w/o overriding the draw() and handle() methods.
+
+ Basic layout:
+ \code
+ +------+-----+-------------+-----+------+
+ | << | < | value | > | >> |
+ +------+-----+-------------+-----+------+
+ \endcode
+
+ The returned value \p w2 should be zero if the counter type() is FL_SIMPLE_COUNTER.
+
+ \param[out] w1 width of single arrow box
+ \param[out] w2 width of double arrow box
+*/
+void Fl_Counter::arrow_widths(int &w1, int &w2) {
+ if (type() == FL_SIMPLE_COUNTER) {
+ w1 = w() * 20/100;
+ w2 = 0;
} else {
- int W = w()*20/100;
- xx[1] = 0; ww[1] = 0;
- xx[2] = x(); ww[2] = W;
- xx[0] = x()+W; ww[0] = w()-2*W;
- xx[3] = x()+w()-1*W; ww[3] = W;
- xx[4] = 0; ww[4] = 0;
+ w1 = w() * 13/100;
+ w2 = w() * 17/100;
}
+ // limit arrow box sizes to reserve more space for the text box
+ if (w1 > 18) w1 = 18;
+ if (w2 > 24) w2 = 24;
+}
+
+void Fl_Counter::draw() {
+ struct arrow_box ab[4];
+
+ // text box setup
+ Fl_Boxtype tbt = box();
+ if (tbt == FL_UP_BOX) tbt = FL_DOWN_BOX;
+ if (tbt == FL_THIN_UP_BOX) tbt = FL_THIN_DOWN_BOX;
- draw_box(boxtype[0], xx[0], y(), ww[0], h(), FL_BACKGROUND2_COLOR);
+ // array boxes
+ for (int i = 0; i < 4; i++) {
+ if (mouseobj_ == i + 1)
+ ab[i].boxtype = fl_down(box());
+ else
+ ab[i].boxtype = box();
+ }
+
+ ab[0].arrow_type = ab[3].arrow_type = FL_ARROW_DOUBLE; // first and last arrow
+ ab[0].orientation = ab[1].orientation = FL_ORIENT_LEFT; // left arrows
+
+ int w1 = 0, w2 = 0;
+ arrow_widths(w1, w2);
+ if (type() == FL_SIMPLE_COUNTER)
+ w2 = 0;
+
+ ab[0].width = ab[3].width = w2; // double arrows
+ ab[1].width = ab[2].width = w1; // single arrows
+
+ int tw = w() - 2 * (w1 + w2); // text box width
+ int tx = x() + w1 + w2; // text box position
+
+ // printf("w() = %3d, w1 = %3d, w2 = %3d, tw = %3d\n", w(), w1, w2, tw);
+
+ // always draw text box and text
+ draw_box(tbt, tx, y(), tw, h(), FL_BACKGROUND2_COLOR);
fl_font(textfont(), textsize());
fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
char str[128]; format(str);
- fl_draw(str, xx[0], y(), ww[0], h(), FL_ALIGN_CENTER);
- if (Fl::focus() == this) draw_focus(boxtype[0], xx[0], y(), ww[0], h());
+ fl_draw(str, tx, y(), tw, h(), FL_ALIGN_CENTER);
+ if (Fl::focus() == this) draw_focus(tbt, tx, y(), tw, h());
if (!(damage()&FL_DAMAGE_ALL)) return; // only need to redraw text
+ Fl_Color arrow_color;
if (active_r())
- selcolor = labelcolor();
+ arrow_color = labelcolor();
else
- selcolor = fl_inactive(labelcolor());
+ arrow_color = fl_inactive(labelcolor());
- if (type() == FL_NORMAL_COUNTER) {
- draw_box(boxtype[1], xx[1], y(), ww[1], h(), color());
- fl_draw_symbol("@-4<<", xx[1], y(), ww[1], h(), selcolor);
- }
- draw_box(boxtype[2], xx[2], y(), ww[2], h(), color());
- fl_draw_symbol("@-4<", xx[2], y(), ww[2], h(), selcolor);
- draw_box(boxtype[3], xx[3], y(), ww[3], h(), color());
- fl_draw_symbol("@-4>", xx[3], y(), ww[3], h(), selcolor);
- if (type() == FL_NORMAL_COUNTER) {
- draw_box(boxtype[4], xx[4], y(), ww[4], h(), color());
- fl_draw_symbol("@-4>>", xx[4], y(), ww[4], h(), selcolor);
+ // draw arrow boxes
+ int xo = x();
+ for (int i = 0; i < 4; i++) {
+ if (ab[i].width > 0) {
+ draw_box(ab[i].boxtype, xo, y(), ab[i].width, h(), color());
+ Fl_Rect bb(xo, y(), ab[i].width, h(), ab[i].boxtype);
+ fl_draw_arrow(bb, ab[i].arrow_type, ab[i].orientation, arrow_color);
+ xo += ab[i].width;
+ }
+ if (i == 1) xo += tw;
}
-}
+
+} // draw()
void Fl_Counter::increment_cb() {
- if (!mouseobj) return;
+ if (!mouseobj_) return;
double v = value();
- switch (mouseobj) {
+ switch (mouseobj_) {
case 1: v -= lstep_; break;
case 2: v = increment(v, -1); break;
case 3: v = increment(v, 1); break;
@@ -95,7 +146,7 @@ void Fl_Counter::repeat_callback(void* v) {
Fl_Counter* b = (Fl_Counter*)v;
int buttons = Fl::event_state() & FL_BUTTONS; // any mouse button pressed
int focus = (Fl::focus() == b); // the widget has focus
- if (b->mouseobj && buttons && focus) {
+ if (b->mouseobj_ && buttons && focus) {
Fl::add_timeout(REPEAT, repeat_callback, b);
b->increment_cb();
}
@@ -120,9 +171,9 @@ int Fl_Counter::handle(int event) {
int i;
switch (event) {
case FL_RELEASE:
- if (mouseobj) {
+ if (mouseobj_) {
Fl::remove_timeout(repeat_callback, this);
- mouseobj = 0;
+ mouseobj_ = 0;
redraw();
}
handle_release();
@@ -135,9 +186,9 @@ int Fl_Counter::handle(int event) {
}
case FL_DRAG:
i = calc_mouseobj();
- if (i != mouseobj) {
+ if (i != mouseobj_) {
Fl::remove_timeout(repeat_callback, this);
- mouseobj = (uchar)i;
+ mouseobj_ = (uchar)i;
if (i > 0)
Fl::add_timeout(INITIALREPEAT, repeat_callback, this);
Fl_Widget_Tracker wp(this);
@@ -159,7 +210,7 @@ int Fl_Counter::handle(int event) {
}
// break not required because of switch...
case FL_UNFOCUS :
- mouseobj = 0;
+ mouseobj_ = 0;
/* FALLTHROUGH */
case FL_FOCUS :
if (Fl::visible_focus()) {
@@ -195,7 +246,7 @@ Fl_Counter::Fl_Counter(int X, int Y, int W, int H, const char* L)
bounds(-1000000.0, 1000000.0);
Fl_Valuator::step(1, 10);
lstep_ = 1.0;
- mouseobj = 0;
+ mouseobj_ = 0;
textfont_ = FL_HELVETICA;
textsize_ = FL_NORMAL_SIZE;
textcolor_ = FL_FOREGROUND_COLOR;