summaryrefslogtreecommitdiff
path: root/src/fl_draw_arrow.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/fl_draw_arrow.cxx')
-rw-r--r--src/fl_draw_arrow.cxx256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/fl_draw_arrow.cxx b/src/fl_draw_arrow.cxx
new file mode 100644
index 000000000..2aef43889
--- /dev/null
+++ b/src/fl_draw_arrow.cxx
@@ -0,0 +1,256 @@
+//
+// Arrow drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2022 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
+// file is missing or damaged, see the license at:
+//
+// https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+// https://www.fltk.org/bugs.php
+//
+
+// These functions implement drawing of all "arrow like" GUI elements in scrollbars,
+// choice widgets, menus, etc.
+
+// Implementation of fl_draw_arrow(...) dependent on the active FLTK Scheme.
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/fl_utf8.h>
+
+#ifndef DEBUG_ARROW
+#define DEBUG_ARROW (0) // 0 = off, 1 = green background, 2 = red frame, 3 = both
+#endif
+
+void debug_arrow(Fl_Rect r) {
+
+#if (DEBUG_ARROW & 1)
+ fl_color(fl_lighter(FL_GREEN));
+ fl_rectf(r);
+#endif
+
+#if (DEBUG_ARROW & 2)
+ fl_color(FL_RED);
+ fl_line_style(FL_SOLID, 1); // work around X11 bug with default line width 0
+ fl_rect(r);
+ fl_line_style(FL_SOLID, 0); // reset line style
+#endif
+
+} // debug_arrow
+
+// Calculate the applicable arrow size.
+// Imagine an arrow pointing to the right side:
+// - the calculated size s is the width of the arrow,
+// - the height of the arrow is 2 * s.
+// The calculation takes into account that we need one pixel padding at
+// all sides and that the available space doesn't need to be a square,
+// i.e. it's possible that r.w() != r.h().
+
+static int arrow_size(Fl_Rect r, Fl_Orientation o, int num = 1) {
+
+ int s, d1, d2;
+
+ switch(o) {
+ case FL_ORIENT_LEFT:
+ case FL_ORIENT_RIGHT:
+ d1 = (r.w() - 2) / num;
+ d2 = (r.h() - 2) / 2;
+ break;
+ default: // up or down arrow
+ d1 = (r.h() - 2) / num;
+ d2 = (r.w() - 2) / 2;
+ break;
+ }
+ s = d1 < d2 ? d1 : d2;
+ if (s < 2) s = 2;
+ else if (s > 6) s = 6;
+ return s;
+}
+
+// Draw a "Single Arrow" in an arbitrary direction (0°, 90°, 180°, 270°).
+// This is the basic arrow drawing function for all "standard" widgets.
+// It is used in Fl_Scrollbars and similar and in all combinations, for
+// instance when "Double Arrows" or other combinations are needed.
+
+static int fl_draw_arrow_single(Fl_Rect r, Fl_Orientation o, Fl_Color col, int d = -1) {
+
+ int x1, y1;
+
+ x1 = r.x();
+ y1 = r.y();
+ if (d < 0)
+ d = arrow_size(r, o);
+
+ fl_color(col);
+
+ switch(o) {
+
+ case FL_ORIENT_LEFT:
+ x1 += (r.w()-d)/2 - 1;
+ y1 += r.h()/2;
+ if (Fl::is_scheme("gtk+"))
+ fl_polygon(x1, y1, x1+d, y1-d, x1+d-1, y1, x1+d, y1+d);
+ else
+ fl_polygon(x1, y1, x1+d, y1-d, x1+d, y1+d);
+ return 1;
+
+ case FL_ORIENT_RIGHT:
+ x1 += (r.w()-d)/2;
+ y1 += r.h()/2;
+ if (Fl::is_scheme("gtk+"))
+ fl_polygon(x1, y1-d, x1+1, y1, x1, y1+d, x1+d, y1);
+ else
+ fl_polygon(x1, y1-d, x1, y1+d, x1+d, y1);
+ return 1;
+
+ case FL_ORIENT_UP:
+ x1 += r.w()/2;
+ y1 += (r.h()-d)/2 - 1;
+ if (Fl::is_scheme("gtk+"))
+ fl_polygon(x1, y1, x1+d, y1+d, x1, y1+d-1, x1-d, y1+d);
+ else
+ fl_polygon(x1, y1, x1+d, y1+d, x1-d, y1+d);
+ return 1;
+
+ case FL_ORIENT_DOWN:
+ x1 += r.w()/2-d;
+ y1 += (r.h()-d)/2;
+ if (Fl::is_scheme("gtk+")) {
+ fl_polygon(x1, y1, x1+d, y1+1, x1+d, y1+d);
+ fl_polygon(x1+d, y1+1, x1+2*d, y1, x1+d, y1+d);
+ } else {
+ fl_polygon(x1, y1, x1+d, y1+d, x1+2*d, y1);
+ }
+ return 1;
+
+ default: // orientation not handled: return error
+ return 0;
+ }
+ return 0;
+} // fl_draw_arrow_single()
+
+
+// Draw a "Double Arrow" in an arbitrary direction (0°, 90°, 180°, 270°).
+// This is the basic arrow drawing function for all "standard" widgets.
+// It is used in Fl_Scrollbars and similar and in all combinations, for
+// instance when "Double Arrows" or other combinations are needed.
+
+static int fl_draw_arrow_double(Fl_Rect r, Fl_Orientation o, Fl_Color col) {
+
+ int d = arrow_size(r, o, 2);
+ int x1 = r.x();
+ int y1 = r.y();
+ int da = (d+1)/2;
+
+ switch(o) {
+
+ case FL_ORIENT_LEFT:
+ case FL_ORIENT_RIGHT:
+ r.x(x1 - da);
+ fl_draw_arrow_single(r, o, col, d);
+ r.x(x1 + da);
+ return fl_draw_arrow_single(r, o, col, d);
+
+ case FL_ORIENT_UP:
+ case FL_ORIENT_DOWN:
+ r.y(y1 - da);
+ fl_draw_arrow_single(r, o, col, d);
+ r.y(y1 + da);
+ return fl_draw_arrow_single(r, o, col, d);
+
+ default: // orientation not handled: return error
+ return 0;
+ }
+ return 0;
+} // fl_draw_arrow_double()
+
+
+// Draw a "Choice Arrow". The direction and type is determined by the scheme.
+
+static int fl_draw_arrow_choice(Fl_Rect r, Fl_Color col) {
+
+ int w1 = (r.w() - 4) / 3; if (w1 < 1) w1 = 1;
+ int x1 = r.x() + (r.w() - 2 * w1 - 1) / 2;
+ int y1 = r.y() + (r.h() - w1 - 1) / 2;
+
+ if (Fl::is_scheme("gtk+") ||
+ Fl::is_scheme("gleam")) {
+ // Show smaller up/down arrows ...
+ int x1 = r.x() + (r.w() - 6)/2;
+ int y1 = r.y() + r.h() / 2;
+ fl_color(col);
+ fl_polygon(x1, y1 - 2, x1 + 3, y1 - 5, x1 + 6, y1 - 2);
+ fl_polygon(x1, y1 + 2, x1 + 3, y1 + 5, x1 + 6, y1 + 2);
+ return 1;
+ }
+ else if (Fl::is_scheme("plastic")) {
+ // Show larger up/down arrows...
+ fl_color(col);
+ fl_polygon(x1, y1 + 3, x1 + w1, y1 + w1 + 3, x1 + 2 * w1, y1 + 3);
+ fl_polygon(x1, y1 + 1, x1 + w1, y1 - w1 + 1, x1 + 2 * w1, y1 + 1);
+ return 1;
+ }
+ else { // none, default // single down arrow
+ return fl_draw_arrow_single(r, FL_ORIENT_DOWN, col);
+ }
+ return 0;
+} // fl_draw_arrow_double()
+
+
+/**
+ Draw an "arrow like" GUI element for the selected scheme.
+
+ In the future this function should be integrated in Fl_Scheme
+ as a virtual method, i.e. it would call a method like ...
+ \code
+ Fl_Scheme::current()->draw_arrow(r, t, o, col);
+ \endcode
+
+ \param[in] r bounding box
+ \param[in] t arrow type
+ \param[in] o orientation
+ \param[in] col arrow color
+*/
+
+void fl_draw_arrow(Fl_Rect r, Fl_Arrow_Type t, Fl_Orientation o, Fl_Color col) {
+
+ int ret = 0;
+ debug_arrow(r);
+
+ // implementation of all arrow types
+
+ switch(t) {
+ case FL_ARROW_SINGLE:
+ ret = fl_draw_arrow_single(r, o, col);
+ break;
+
+ case FL_ARROW_DOUBLE:
+ ret = fl_draw_arrow_double(r, o, col);
+ break;
+
+ case FL_ARROW_CHOICE:
+ ret = fl_draw_arrow_choice(r, col);
+ break;
+
+ default: // unknown arrow type
+ ret = 0;
+ break;
+ }
+
+ // draw an error flag (red rectangle with cross) if not successful
+
+ if (!ret) {
+ fl_color(FL_RED);
+ fl_rectf(r);
+ fl_color(FL_BLACK);
+ fl_rect(r);
+ fl_line(r.x(), r.y(), r.r(), r.b());
+ fl_line(r.x(), r.b(), r.r(), r.y());
+ }
+
+} // fl_draw_arrow()