Fl_Tree +/- buttons are no longer drawn using bitmaps, different default line color (#995)

Fl_Tree changed to support system color themes (PR #995)

merging CyprinusCarpio's mods carried over from from issue #972.

* Fl_Tree: use named (colormap) colors to support system color themes (see issue #972). changed connectorcolor() default from gray ramp color to FL_INACTIVE_COLOR (Fl_Color(8)), and similar named colormap colors for icon drawing.

* Fl_Tree ⊞ / ⊟ icons (and on macs, ▶ / ▼icons) are now drawn w/fl_draw() functions instead of with xpm bitmaps for colormap control

---------
Co-authored-by: Greg Ercolano <erco@seriss.com>
This commit is contained in:
Cyprinus Carpio 2024-06-30 18:08:00 +02:00 committed by GitHub
parent 1c6a0c1a8f
commit a69c5c5c92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 55 additions and 136 deletions

View File

@ -298,6 +298,8 @@ public:
inline Fl_Image *openicon() const { inline Fl_Image *openicon() const {
return(_openimage); return(_openimage);
} }
inline int openicon_w() const { return _openimage ? _openimage->w() : 11; }
inline int openicon_h() const { return _openimage ? _openimage->h() : 11; }
void openicon(Fl_Image *val); void openicon(Fl_Image *val);
/// Gets the default 'close' icon /// Gets the default 'close' icon
/// Returns the Fl_Image* of the icon, or 0 if none. /// Returns the Fl_Image* of the icon, or 0 if none.
@ -305,6 +307,8 @@ public:
inline Fl_Image *closeicon() const { inline Fl_Image *closeicon() const {
return(_closeimage); return(_closeimage);
} }
inline int closeicon_w() const { return _closeimage ? _closeimage->w() : 11; }
inline int closeicon_h() const { return _closeimage ? _closeimage->h() : 11; }
void closeicon(Fl_Image *val); void closeicon(Fl_Image *val);
/// Gets the default 'user icon' (default is 0) /// Gets the default 'user icon' (default is 0)
inline Fl_Image *usericon() const { inline Fl_Image *usericon() const {

View File

@ -200,12 +200,8 @@ public:
// the implementations of local_to_mac_roman() and mac_roman_to_local() are in fl_encoding_mac_roman.cxx // the implementations of local_to_mac_roman() and mac_roman_to_local() are in fl_encoding_mac_roman.cxx
virtual const char *local_to_mac_roman(const char *t, int n); virtual const char *local_to_mac_roman(const char *t, int n);
virtual const char *mac_roman_to_local(const char *t, int n); virtual const char *mac_roman_to_local(const char *t, int n);
// the default implementations of tree_openpixmap() and tree_closepixmap() are // draw default tree view expando button
// in Fl_Tree_Prefs.cxx and can be enough virtual void tree_draw_expando_button(int x, int y, bool state, bool active);
virtual Fl_Pixmap *tree_openpixmap();
virtual Fl_Pixmap *tree_closepixmap();
static const char *const tree_open_xpm[]; // used by tree_openpixmap()
static const char * const tree_close_xpm[]; // used by tree_closepixmap()
// the default implementation of tree_connector_style() is in Fl_Tree_Prefs.cxx and can be enough // the default implementation of tree_connector_style() is in Fl_Tree_Prefs.cxx and can be enough
virtual int tree_connector_style(); virtual int tree_connector_style();
virtual void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0); virtual void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0);

View File

@ -676,8 +676,8 @@ void Fl_Tree::calc_tree() {
int W = _tiw; int W = _tiw;
// Adjust root's X/W if connectors off // Adjust root's X/W if connectors off
if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) { if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) {
X -= _prefs.openicon()->w(); X -= _prefs.openicon_w();
W += _prefs.openicon()->w(); W += _prefs.openicon_w();
} }
int xmax = 0, render = 0, ytop = Y; int xmax = 0, render = 0, ytop = Y;
fl_font(_prefs.labelfont(), _prefs.labelsize()); fl_font(_prefs.labelfont(), _prefs.labelsize());
@ -718,8 +718,8 @@ void Fl_Tree::draw() {
int W = _tiw - X + _tix; int W = _tiw - X + _tix;
// Adjust root's X/W if connectors off // Adjust root's X/W if connectors off
if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) { if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) {
X -= _prefs.openicon()->w(); X -= _prefs.openicon_w();
W += _prefs.openicon()->w(); W += _prefs.openicon_w();
} }
// Draw entire tree, starting with root // Draw entire tree, starting with root
fl_push_clip(_tix,_tiy,_tiw,_tih); fl_push_clip(_tix,_tiy,_tiw,_tih);

View File

@ -9,6 +9,7 @@
#include <FL/Fl_Tree_Prefs.H> #include <FL/Fl_Tree_Prefs.H>
#include <FL/Fl_Tree.H> #include <FL/Fl_Tree.H>
#include <FL/fl_string_functions.h> #include <FL/fl_string_functions.h>
#include "Fl_System_Driver.H"
////////////////////// //////////////////////
// Fl_Tree_Item.cxx // Fl_Tree_Item.cxx
@ -804,7 +805,7 @@ Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly)
/// - visibility (if !is_visible(), returns 0) /// - visibility (if !is_visible(), returns 0)
/// - labelfont() height: if label() != NULL /// - labelfont() height: if label() != NULL
/// - widget() height: if widget() != NULL /// - widget() height: if widget() != NULL
/// - openicon() height (if not NULL) /// - openicon() height (if has children)
/// - usericon() height (if not NULL) /// - usericon() height (if not NULL)
/// Does NOT include Fl_Tree::linespacing(); /// Does NOT include Fl_Tree::linespacing();
/// \returns maximum pixel height /// \returns maximum pixel height
@ -821,8 +822,8 @@ int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) const {
H < widget()->h()) { H < widget()->h()) {
H = widget()->h(); H = widget()->h();
} }
if ( has_children() && prefs.openicon() && H<prefs.openicon()->h() ) if ( has_children() && H < prefs.openicon_h() )
H = prefs.openicon()->h(); H = prefs.openicon_h();
if ( usericon() && H<usericon()->h() ) if ( usericon() && H<usericon()->h() )
H = usericon()->h(); H = usericon()->h();
return(H); return(H);
@ -990,13 +991,13 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Tree_Item *itemfocus,
// We don't care about items clipped off the viewport; they won't get mouse events. // We don't care about items clipped off the viewport; they won't get mouse events.
// //
int item_y_center = Y+(H/2); int item_y_center = Y+(H/2);
_collapse_xywh[2] = prefs.openicon()->w(); _collapse_xywh[2] = prefs.openicon_w();
int &icon_w = _collapse_xywh[2]; int &icon_w = _collapse_xywh[2];
_collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3; _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3;
int &icon_x = _collapse_xywh[0]; int &icon_x = _collapse_xywh[0];
_collapse_xywh[1] = item_y_center - (prefs.openicon()->h()/2); _collapse_xywh[1] = item_y_center - prefs.openicon_h()/2;
int &icon_y = _collapse_xywh[1]; int &icon_y = _collapse_xywh[1];
_collapse_xywh[3] = prefs.openicon()->h(); _collapse_xywh[3] = prefs.openicon_h();
// Horizontal connector values // Horizontal connector values
// Must calculate these even if(clipped) because 'draw children' code (below) // Must calculate these even if(clipped) because 'draw children' code (below)
@ -1080,11 +1081,19 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Tree_Item *itemfocus,
if ( render && has_children() && prefs.showcollapse() ) { if ( render && has_children() && prefs.showcollapse() ) {
// Draw icon image // Draw icon image
if ( is_open() ) { if ( is_open() ) {
if ( active ) prefs.closeicon()->draw(icon_x,icon_y); if ( prefs.closeicon() ) {
else prefs.closedeicon()->draw(icon_x,icon_y); if ( active ) prefs.closeicon()->draw(icon_x, icon_y);
else prefs.closedeicon()->draw(icon_x, icon_y);
} else {
Fl::system_driver()->tree_draw_expando_button(icon_x, icon_y, false, active);
}
} else { } else {
if ( active ) prefs.openicon()->draw(icon_x,icon_y); if ( prefs.openicon() ) {
else prefs.opendeicon()->draw(icon_x,icon_y); if ( active ) prefs.openicon()->draw(icon_x, icon_y);
else prefs.opendeicon()->draw(icon_x, icon_y);
} else {
Fl::system_driver()->tree_draw_expando_button(icon_x, icon_y, true, active);
}
} }
} }
// Draw user icon (if any) // Draw user icon (if any)

View File

@ -22,12 +22,9 @@
#include "Fl_System_Driver.H" #include "Fl_System_Driver.H"
#include <FL/Fl.H> #include <FL/Fl.H>
#include <FL/Fl_Pixmap.H> #include <FL/Fl_Image.H>
#include <FL/Fl_Tree_Prefs.H> #include <FL/Fl_Tree_Prefs.H>
#include <FL/fl_draw.H>
// INTERNAL: BUILT IN OPEN/STOW XPMS
// These can be replaced via prefs.openicon()/closeicon()
//
/** /**
\cond DriverDev \cond DriverDev
@ -35,61 +32,16 @@
\{ \{
*/ */
const char * const Fl_System_Driver::tree_open_xpm[] = { // Draw non-OS specific Fl_Tree open/close icons
"11 11 3 1", // ┌───┐ ┌───┐
". c #fefefe", // │ + │ │ - │
"# c #444444", // └───┘ └───┘
"@ c #000000", void Fl_System_Driver::tree_draw_expando_button(int x, int y, bool state, bool active) {
"###########", fl_rectf(x, y, 11, 11, active ? FL_BACKGROUND2_COLOR : fl_inactive(FL_BACKGROUND2_COLOR)); // fill
"#.........#", fl_rect(x, y, 11, 11, FL_INACTIVE_COLOR); // outline
"#.........#", fl_color(active ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR);
"#....@....#", fl_line(x + 3, y + 5, x + 7, y + 5); // horiz line
"#....@....#", if (state) fl_line(x + 5, y + 3, x + 5, y + 7); // vert line
"#..@@@@@..#",
"#....@....#",
"#....@....#",
"#.........#",
"#.........#",
"###########"
};
const char * const Fl_System_Driver::tree_close_xpm[] = {
"11 11 3 1",
". c #fefefe",
"# c #444444",
"@ c #000000",
"###########",
"#.........#",
"#.........#",
"#.........#",
"#.........#",
"#..@@@@@..#",
"#.........#",
"#.........#",
"#.........#",
"#.........#",
"###########"
};
/**
Return the address of a pixmap that show a plus in a box.
This pixmap is used to indicate a brach of a tree that is closed and
can be opened by clicking it.
Other platforms may use other symbols which can be reimplemented in the
driver. Notably, Apple Mac systems mark a closed branch with a triangle
pointing to the right, and an open branch with a triangle pointing down.
*/
Fl_Pixmap *Fl_System_Driver::tree_openpixmap() {
static Fl_Pixmap *pixmap = new Fl_Pixmap(tree_open_xpm);
return pixmap;
}
Fl_Pixmap *Fl_System_Driver::tree_closepixmap() {
static Fl_Pixmap *pixmap = new Fl_Pixmap(tree_close_xpm);
return pixmap;
} }
int Fl_System_Driver::tree_connector_style() { int Fl_System_Driver::tree_connector_style() {
@ -109,7 +61,7 @@ int Fl_System_Driver::tree_connector_style() {
/// \param[in] val -- The new image, or zero to use the default [+] icon. /// \param[in] val -- The new image, or zero to use the default [+] icon.
/// ///
void Fl_Tree_Prefs::openicon(Fl_Image *val) { void Fl_Tree_Prefs::openicon(Fl_Image *val) {
_openimage = val ? val : Fl::system_driver()->tree_openpixmap(); _openimage = val ? val : 0;
// Update deactivated version of icon.. // Update deactivated version of icon..
if ( _opendeimage ) delete _opendeimage; if ( _opendeimage ) delete _opendeimage;
if ( _openimage ) { if ( _openimage ) {
@ -126,7 +78,7 @@ void Fl_Tree_Prefs::openicon(Fl_Image *val) {
/// \param[in] val -- The new image, or zero to use the default [-] icon. /// \param[in] val -- The new image, or zero to use the default [-] icon.
/// ///
void Fl_Tree_Prefs::closeicon(Fl_Image *val) { void Fl_Tree_Prefs::closeicon(Fl_Image *val) {
_closeimage = val ? val : Fl::system_driver()->tree_closepixmap(); _closeimage = val ? val : 0;
// Update deactivated version of icon.. // Update deactivated version of icon..
if ( _closedeimage ) delete _closedeimage; if ( _closedeimage ) delete _closedeimage;
if ( _closeimage ) { if ( _closeimage ) {
@ -151,15 +103,13 @@ Fl_Tree_Prefs::Fl_Tree_Prefs() {
_linespacing = 0; _linespacing = 0;
_labelfgcolor = FL_FOREGROUND_COLOR; _labelfgcolor = FL_FOREGROUND_COLOR;
_labelbgcolor = 0xffffffff; // we use this as 'transparent' _labelbgcolor = 0xffffffff; // we use this as 'transparent'
_connectorcolor = Fl_Color(43); _connectorcolor = FL_INACTIVE_COLOR;
_connectorstyle = (Fl_Tree_Connector)Fl::system_driver()->tree_connector_style(); _connectorstyle = (Fl_Tree_Connector)Fl::system_driver()->tree_connector_style();
_openimage = Fl::system_driver()->tree_openpixmap(); _openimage = 0;
_closeimage = Fl::system_driver()->tree_closepixmap(); _closeimage = 0;
_userimage = 0; _userimage = 0;
_opendeimage = _openimage->copy(); _opendeimage = 0;
_opendeimage->inactive(); _closedeimage = 0;
_closedeimage = _closeimage->copy();
_closedeimage->inactive();
_userdeimage = 0; _userdeimage = 0;
_showcollapse = 1; _showcollapse = 1;
_showroot = 1; _showroot = 1;

View File

@ -64,10 +64,7 @@ public:
const char *latin1_to_local(const char *t, int n) FL_OVERRIDE; const char *latin1_to_local(const char *t, int n) FL_OVERRIDE;
const char *local_to_mac_roman(const char *t, int n) FL_OVERRIDE; const char *local_to_mac_roman(const char *t, int n) FL_OVERRIDE;
const char *mac_roman_to_local(const char *t, int n) FL_OVERRIDE; const char *mac_roman_to_local(const char *t, int n) FL_OVERRIDE;
Fl_Pixmap *tree_openpixmap() FL_OVERRIDE; void tree_draw_expando_button(int x, int y, bool state, bool active) FL_OVERRIDE;
static const char * const tree_open_xpm_darwin[]; // used by tree_openpixmap()
Fl_Pixmap *tree_closepixmap() FL_OVERRIDE;
static const char * const tree_close_xpm_darwin[]; // used by tree_closepixmap()
int tree_connector_style() FL_OVERRIDE; int tree_connector_style() FL_OVERRIDE;
const char *filename_name(const char *buf) FL_OVERRIDE; const char *filename_name(const char *buf) FL_OVERRIDE;
void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE;

View File

@ -21,6 +21,7 @@
#include <FL/Fl_Tree_Prefs.H> #include <FL/Fl_Tree_Prefs.H>
#include <FL/Fl_Pixmap.H> #include <FL/Fl_Pixmap.H>
#include <FL/platform.H> #include <FL/platform.H>
#include <FL/fl_draw.H>
#include "../../flstring.h" #include "../../flstring.h"
#include <string.h> #include <string.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
@ -357,50 +358,12 @@ Fl_Sys_Menu_Bar_Driver *Fl_Darwin_System_Driver::sys_menu_bar_driver()
return Fl_MacOS_Sys_Menu_Bar_Driver::driver(); return Fl_MacOS_Sys_Menu_Bar_Driver::driver();
} }
const char * const Fl_Darwin_System_Driver::tree_open_xpm_darwin[] = { // Draw Mac-specific Fl_Tree open/close icons
"11 11 2 1", void Fl_Darwin_System_Driver::tree_draw_expando_button(int x, int y, bool state, bool active) {
". c None", fl_color(active ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR);
"@ c #000000", if(state) fl_polygon(x + 3, y, x + 3, y + 11, x + 8, y + 5); // right arrow: ▶
"...@.......", else fl_polygon(x, y + 3, x + 11, y + 3, x + 5, y + 8); // down arrow: ▼
"...@@......",
"...@@@.....",
"...@@@@....",
"...@@@@@...",
"...@@@@@@..",
"...@@@@@...",
"...@@@@....",
"...@@@.....",
"...@@......",
"...@......."
};
const char * const Fl_Darwin_System_Driver::tree_close_xpm_darwin[] = {
"11 11 2 1",
". c None",
"@ c #000000",
"...........",
"...........",
"...........",
"@@@@@@@@@@@",
".@@@@@@@@@.",
"..@@@@@@@..",
"...@@@@@...",
"....@@@....",
".....@.....",
"...........",
"..........."
};
Fl_Pixmap *Fl_Darwin_System_Driver::tree_openpixmap() {
static Fl_Pixmap *pixmap = new Fl_Pixmap(tree_open_xpm_darwin);
return pixmap;
} }
Fl_Pixmap *Fl_Darwin_System_Driver::tree_closepixmap() {
static Fl_Pixmap *pixmap = new Fl_Pixmap(tree_close_xpm_darwin);
return pixmap;
}
int Fl_Darwin_System_Driver::tree_connector_style() { int Fl_Darwin_System_Driver::tree_connector_style() {
return FL_TREE_CONNECTOR_NONE; return FL_TREE_CONNECTOR_NONE;
} }