diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2020-11-22 19:19:19 +0100 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2022-11-22 19:32:54 +0100 |
| commit | ecc47d0cc3e1784e17ac94829202f2bdbd38a682 (patch) | |
| tree | 2519c9b11a598ed4ad1faf9d07c205da5c4903c7 /src/Fl_Counter.cxx | |
| parent | 4daec2a9408c674f8d62f8770ec8c035c25f2294 (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.cxx | 155 |
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; |
