From ab58971bcf9cedee6ecd131ca032087ff7d1623c Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Fri, 14 Jan 2022 17:17:09 +0100 Subject: Improve focus box drawing and documentation Add new method Fl_Widget::draw_focus(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color bg) ... with background color for correct contrast testing (in Fl_Tabs) Draw the focus box of the "tabs" of Fl_Tabs widgets with the correct boxtype and background color. Make 'unsigned int visible_focus()' const so it can be used in 'const' methods. Do not draw the focus box if the per-widget focus box option is off. --- FL/Fl_Widget.H | 27 +++++++++++++++++++++++---- FL/fl_draw.H | 7 ++++++- src/Fl_Tabs.cxx | 4 ++-- src/Fl_Widget.cxx | 46 +++++++++++++++++++++++++++++++++++++--------- 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/FL/Fl_Widget.H b/FL/Fl_Widget.H index 0745b9063..1c90848de 100644 --- a/FL/Fl_Widget.H +++ b/FL/Fl_Widget.H @@ -169,9 +169,28 @@ protected: void draw_box(Fl_Boxtype t, Fl_Color c) const; void draw_box(Fl_Boxtype t, int x,int y,int w,int h, Fl_Color c) const; void draw_backdrop() const; - /** draws a focus rectangle around the widget */ - void draw_focus() {draw_focus(box(),x(),y(),w(),h());} - void draw_focus(Fl_Boxtype t, int x,int y,int w,int h) const; + + /** Draws a focus rectangle around the widget. + This method uses the widget's boxtype and coordinates and its + background color color(). + \see Fl_Widget::draw_focus(Fl_Boxtype, int, int, int, int, Fl_Color) const + */ + void draw_focus() const { + draw_focus(box(), x(), y(), w(), h(), color()); + } + + /** Draws a focus rectangle around the widget. + This method uses the given boxtype and coordinates and the widget's + background color color(). + \see Fl_Widget::draw_focus(Fl_Boxtype, int, int, int, int, Fl_Color) const + */ + void draw_focus(Fl_Boxtype t, int X, int Y, int W, int H) const { + draw_focus(t, X, Y, W, H, color()); + + } + // See documentation in Fl_Widget.cxx + void draw_focus(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color bg) const; + void draw_label() const; void draw_label(int, int, int, int) const; @@ -845,7 +864,7 @@ public: \retval 0 if this widget has no visible focus. \see visible_focus(int), set_visible_focus(), clear_visible_focus() */ - unsigned int visible_focus() { return flags_ & VISIBLE_FOCUS; } + unsigned int visible_focus() const { return flags_ & VISIBLE_FOCUS; } /** The default callback for all widgets that don't set a callback. diff --git a/FL/fl_draw.H b/FL/fl_draw.H index 8db59b43b..66125d351 100644 --- a/FL/fl_draw.H +++ b/FL/fl_draw.H @@ -299,7 +299,12 @@ inline void fl_rect(Fl_Rect r) { fl_rect(r.x(), r.y(), r.w(), r.h()); } -/** Draw a dotted rectangle, used to indicate keyboard focus on a widget. */ +/** Draw a dotted rectangle, used to indicate keyboard focus on a widget. + + This method draws the rectangle in the current color and independent of + the Fl::visible_focus() option. You may need to set the current color + with fl_color() before you call this. +*/ inline void fl_focus_rect(int x, int y, int w, int h) { fl_graphics_driver->focus_rect(x, y, w, h); } diff --git a/src/Fl_Tabs.cxx b/src/Fl_Tabs.cxx index 4c83b6476..9b626456b 100644 --- a/src/Fl_Tabs.cxx +++ b/src/Fl_Tabs.cxx @@ -417,7 +417,7 @@ void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) { o->draw_label(x1, y() + yofs, W, H - yofs, tab_align()); if (Fl::focus() == this && o->visible()) - draw_focus(box(), x1, y(), W, H); + draw_focus(bt, x1, y(), W, H, bc); fl_pop_clip(); } else { @@ -435,7 +435,7 @@ void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) { o->draw_label(x1, y() + h() - H, W, H - yofs, tab_align()); if (Fl::focus() == this && o->visible()) - draw_focus(box(), x1, y() + h() - H, W, H); + draw_focus(bt, x1, y() + h() - H, W, H, bc); fl_pop_clip(); } diff --git a/src/Fl_Widget.cxx b/src/Fl_Widget.cxx index 8b4de1a2a..16bf7bc5d 100644 --- a/src/Fl_Widget.cxx +++ b/src/Fl_Widget.cxx @@ -182,11 +182,38 @@ Fl_Widget::~Fl_Widget() { if (callback_ == default_callback) cleanup_readqueue(this); } -/** Draws a focus box for the widget at the given position and size. */ +/** + Draws a focus box for the widget at the given position and size. + + This method does nothing if + - the global option Fl::visible_focus() or + - the per-widget option visible_focus() + is false (off). + + This means that Fl_Widget::draw_focus() or one of the more specialized + methods can be called without checking these visible focus options. + + \note This method must only be called if the widget has the focus. + This is not tested internally. + + The boxtype \p bt is used to calculate the inset so the focus box is drawn + inside the box borders. -void Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const { + The default focus box drawing color is black. The background color \p bg + is used to determine a better visible color if necessary by using + fl_contrast() with the given background color. + + \param[in] bt Boxtype that needs to be considered (frame width) + \param[in] X,Y,W,H Bounding box + \param[in] bg Background color + + \see Fl_Widget::draw_focus() + \see Fl_Widget::draw_focus(Fl_Boxtype, int, int, int, int) const +*/ +void Fl_Widget::draw_focus(Fl_Boxtype bt, int X, int Y, int W, int H, Fl_Color bg) const { if (!Fl::visible_focus()) return; - switch (B) { + if (!visible_focus()) return; + switch (bt) { case FL_DOWN_BOX: case FL_DOWN_FRAME: case FL_THIN_DOWN_BOX: @@ -196,16 +223,17 @@ void Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const { default: break; } - X += Fl::box_dx(B); - Y += Fl::box_dy(B); - W -= Fl::box_dw(B)+1; - H -= Fl::box_dh(B)+1; + X += Fl::box_dx(bt); + Y += Fl::box_dy(bt); + W -= Fl::box_dw(bt)+1; + H -= Fl::box_dh(bt)+1; - fl_color(fl_contrast(FL_BLACK, color())); + Fl_Color savecolor = fl_color(); + fl_color(fl_contrast(FL_BLACK, bg)); fl_focus_rect(X, Y, W, H); + fl_color(savecolor); } - void Fl_Widget::activate() { if (!active()) { clear_flag(INACTIVE); -- cgit v1.2.3