Adds linespacing() to Fl_Browser_ and all derived widgets

This commit is contained in:
Matthias Melcher 2023-11-25 18:20:02 +01:00
parent 0080850092
commit 34ed30fe1a
10 changed files with 60 additions and 46 deletions

View File

@ -96,6 +96,7 @@ class FL_EXPORT Fl_Browser_ : public Fl_Group {
void *redraw1,*redraw2; // minimal update pointers void *redraw1,*redraw2; // minimal update pointers
void* max_width_item; // which item has max_width_ void* max_width_item; // which item has max_width_
int scrollbar_size_; // size of scrollbar trough int scrollbar_size_; // size of scrollbar trough
int linespacing_;
void update_top(); void update_top();
@ -400,6 +401,17 @@ public:
*/ */
void scrollbar_left() { scrollbar.align(FL_ALIGN_LEFT); } void scrollbar_left() { scrollbar.align(FL_ALIGN_LEFT); }
void sort(int flags=0); void sort(int flags=0);
/**
Add some space between browser lines.
\param[in] pixels number of additional pixels between lines.
*/
void linespacing(int pixels) { linespacing_ = pixels; }
/** Return the height of additional spacing between browser lines.
\return spacing height in pixel units.
*/
int linespacing() const { return linespacing_; }
}; };
#endif #endif

View File

@ -46,7 +46,7 @@ class FL_EXPORT Fl_File_Browser : public Fl_Browser {
int item_height(void *) const FL_OVERRIDE; int item_height(void *) const FL_OVERRIDE;
int item_width(void *) const FL_OVERRIDE; int item_width(void *) const FL_OVERRIDE;
void item_draw(void *, int, int, int, int) const FL_OVERRIDE; void item_draw(void *, int, int, int, int) const FL_OVERRIDE;
int incr_height() const FL_OVERRIDE { return (item_height(0)); } int incr_height() const FL_OVERRIDE { return (item_height(0) + linespacing()); }
public: public:
enum { FILES, DIRECTORIES }; enum { FILES, DIRECTORIES };

View File

@ -644,6 +644,7 @@ Fl_Window* build_ui() {
"Groups"); "Groups");
g_headline_browser->align(FL_ALIGN_TOP); g_headline_browser->align(FL_ALIGN_TOP);
g_headline_browser->textsize(FL_NORMAL_SIZE+1); g_headline_browser->textsize(FL_NORMAL_SIZE+1);
g_headline_browser->linespacing(4);
add_headlines(g_headline_browser); add_headlines(g_headline_browser);
// -- scrollable area for all options inside a group // -- scrollable area for all options inside a group
g_option_scroll = new Fl_Scroll(FO_GAP + FO_BROWSER_W + FO_GAP, FO_GAP + FO_TITLE_H, g_option_scroll = new Fl_Scroll(FO_GAP + FO_BROWSER_W + FO_GAP, FO_GAP + FO_TITLE_H,

View File

@ -252,7 +252,7 @@ int Widget_Browser::item_height(void *l) const {
\return height in FLTK units \return height in FLTK units
*/ */
int Widget_Browser::incr_height() const { int Widget_Browser::incr_height() const {
return textsize()+5; return textsize() + 5 + linespacing();
} }
/** /**
@ -552,15 +552,15 @@ void Widget_Browser::display(Fl_Type *inNode) {
Fl_Type *p=Fl_Type::first; Fl_Type *p=Fl_Type::first;
for ( ; p && p!=inNode; p=p->next) { for ( ; p && p!=inNode; p=p->next) {
if (p->visible) if (p->visible)
nodeV += item_height(p); nodeV += item_height(p) + linespacing();
} }
if (p) { if (p) {
int xx, yy, ww, hh; int xx, yy, ww, hh;
bbox(xx, yy, ww, hh); bbox(xx, yy, ww, hh);
int frame_top = xx-x(); int frame_top = xx-x();
int frame_bottom = frame_top + hh; int frame_bottom = frame_top + hh;
int node_height = item_height(inNode); int node_height = item_height(inNode) + linespacing();
int margin_height = 2 * item_quick_height(inNode); int margin_height = 2 * (item_quick_height(inNode) + linespacing());
if (margin_height>hh/2) margin_height = hh/2; if (margin_height>hh/2) margin_height = hh/2;
// is the inNode above the current scroll position? // is the inNode above the current scroll position?
if (nodeV<currentV+margin_height) if (nodeV<currentV+margin_height)

View File

@ -208,7 +208,7 @@ FL_BLINE* Fl_Browser::_remove(int line) {
cacheline = line-1; cacheline = line-1;
cache = ttt->prev; cache = ttt->prev;
lines--; lines--;
full_height_ -= item_height(ttt); full_height_ -= item_height(ttt) + linespacing();
if (ttt->prev) ttt->prev->next = ttt->next; if (ttt->prev) ttt->prev->next = ttt->next;
else first = ttt->next; else first = ttt->next;
if (ttt->next) ttt->next->prev = ttt->prev; if (ttt->next) ttt->next->prev = ttt->prev;
@ -264,7 +264,7 @@ void Fl_Browser::insert(int line, FL_BLINE* item) {
cacheline = line; cacheline = line;
cache = item; cache = item;
lines++; lines++;
full_height_ += item_height(item); full_height_ += item_height(item) + linespacing();
redraw_line(item); redraw_line(item);
} }
@ -489,7 +489,7 @@ int Fl_Browser::full_height() const {
incr_height(), full_height() incr_height(), full_height()
*/ */
int Fl_Browser::incr_height() const { int Fl_Browser::incr_height() const {
return textsize()+2; return textsize() + 2 + linespacing();
} }
/** /**
@ -620,9 +620,9 @@ void Fl_Browser::lineposition(int line, Fl_Line_Position pos) {
FL_BLINE* l; FL_BLINE* l;
for (l=first; l && line>1; l = l->next) { for (l=first; l && line>1; l = l->next) {
line--; p += item_height(l); line--; p += item_height(l) + linespacing();
} }
if (l && (pos == BOTTOM)) p += item_height (l); if (l && (pos == BOTTOM)) p += item_height(l) + linespacing();
int final = p, X, Y, W, H; int final = p, X, Y, W, H;
bbox(X, Y, W, H); bbox(X, Y, W, H);
@ -670,7 +670,7 @@ void Fl_Browser::textsize(Fl_Fontsize newSize) {
full_height_ = 0; full_height_ = 0;
if (lines == 0) return; if (lines == 0) return;
for (FL_BLINE* itm=(FL_BLINE *)item_first(); itm; itm=(FL_BLINE *)item_next(itm)) { for (FL_BLINE* itm=(FL_BLINE *)item_first(); itm; itm=(FL_BLINE *)item_next(itm)) {
full_height_ += item_height(itm); full_height_ += item_height(itm) + linespacing();
} }
} }
@ -769,7 +769,7 @@ void Fl_Browser::show(int line) {
FL_BLINE* t = find_line(line); FL_BLINE* t = find_line(line);
if (t->flags & NOTDISPLAYED) { if (t->flags & NOTDISPLAYED) {
t->flags &= ~NOTDISPLAYED; t->flags &= ~NOTDISPLAYED;
full_height_ += item_height(t); full_height_ += item_height(t) + linespacing();
if (Fl_Browser_::displayed(t)) redraw(); if (Fl_Browser_::displayed(t)) redraw();
} }
} }
@ -786,7 +786,7 @@ void Fl_Browser::show(int line) {
void Fl_Browser::hide(int line) { void Fl_Browser::hide(int line) {
FL_BLINE* t = find_line(line); FL_BLINE* t = find_line(line);
if (!(t->flags & NOTDISPLAYED)) { if (!(t->flags & NOTDISPLAYED)) {
full_height_ -= item_height(t); full_height_ -= item_height(t) + linespacing();
t->flags |= NOTDISPLAYED; t->flags |= NOTDISPLAYED;
if (Fl_Browser_::displayed(t)) redraw(); if (Fl_Browser_::displayed(t)) redraw();
} }

View File

@ -148,13 +148,13 @@ void Fl_Browser_::update_top() {
offset_ = 0; offset_ = 0;
real_position_ = 0; real_position_ = 0;
} else { } else {
int hh = item_quick_height(l); int hh = item_quick_height(l) + linespacing();
// step through list until we find line containing this point: // step through list until we find line containing this point:
while (ly > yy) { while (ly > yy) {
void* l1 = item_prev(l); void* l1 = item_prev(l);
if (!l1) {ly = 0; break;} // hit the top if (!l1) {ly = 0; break;} // hit the top
l = l1; l = l1;
hh = item_quick_height(l); hh = item_quick_height(l) + linespacing();
ly -= hh; ly -= hh;
} }
while ((ly+hh) <= yy) { while ((ly+hh) <= yy) {
@ -162,16 +162,16 @@ void Fl_Browser_::update_top() {
if (!l1) {yy = ly+hh-1; break;} if (!l1) {yy = ly+hh-1; break;}
l = l1; l = l1;
ly += hh; ly += hh;
hh = item_quick_height(l); hh = item_quick_height(l) + linespacing();
} }
// top item must *really* be visible, use slow height: // top item must *really* be visible, use slow height:
for (;;) { for (;;) {
hh = item_height(l); hh = item_height(l) + linespacing();
if ((ly+hh) > yy) break; // it is big enough to see if ((ly+hh) > yy) break; // it is big enough to see
// go up to top of previous item: // go up to top of previous item:
void* l1 = item_prev(l); void* l1 = item_prev(l);
if (!l1) {ly = yy = 0; break;} // hit the top if (!l1) {ly = yy = 0; break;} // hit the top
l = l1; yy = position_ = ly = ly-item_quick_height(l); l = l1; yy = position_ = ly = ly-item_quick_height(l) + linespacing();
} }
// use it: // use it:
top_ = l; top_ = l;
@ -229,7 +229,7 @@ int Fl_Browser_::displayed(void* item) const {
int yy = H+offset_; int yy = H+offset_;
for (void* l = top_; l && yy > 0; l = item_next(l)) { for (void* l = top_; l && yy > 0; l = item_next(l)) {
if (l == item) return 1; if (l == item) return 1;
yy -= item_height(l); yy -= item_height(l) + linespacing();
} }
return 0; return 0;
} }
@ -257,7 +257,7 @@ void Fl_Browser_::display(void* item) {
// 3rd special case - want to display item just above top of browser? // 3rd special case - want to display item just above top of browser?
void* lp = item_prev(l); void* lp = item_prev(l);
if (lp == item) { vposition(real_position_+Y-item_quick_height(lp)); return; } if (lp == item) { vposition(real_position_+Y-item_quick_height(lp)-linespacing()); return; }
#ifdef DISPLAY_SEARCH_BOTH_WAYS_AT_ONCE #ifdef DISPLAY_SEARCH_BOTH_WAYS_AT_ONCE
// search for item. We search both up and down the list at the same time, // search for item. We search both up and down the list at the same time,
@ -265,7 +265,7 @@ void Fl_Browser_::display(void* item) {
// much slower for going up than for going down. // much slower for going up than for going down.
while (l || lp) { while (l || lp) {
if (l) { if (l) {
h1 = item_quick_height(l); h1 = item_quick_height(l) + linespacing();
if (l == item) { if (l == item) {
if (Y <= H) { // it is visible or right at bottom if (Y <= H) { // it is visible or right at bottom
Y = Y+h1-H; // find where bottom edge is Y = Y+h1-H; // find where bottom edge is
@ -279,7 +279,7 @@ void Fl_Browser_::display(void* item) {
l = item_next(l); l = item_next(l);
} }
if (lp) { if (lp) {
h1 = item_quick_height(lp); h1 = item_quick_height(lp) + linespacing();
Yp -= h1; Yp -= h1;
if (lp == item) { if (lp == item) {
if ((Yp + h1) >= 0) vposition(real_position_+Yp); if ((Yp + h1) >= 0) vposition(real_position_+Yp);
@ -294,7 +294,7 @@ void Fl_Browser_::display(void* item) {
// search forward for it: // search forward for it:
l = top_; l = top_;
for (; l; l = item_next(l)) { for (; l; l = item_next(l)) {
h1 = item_quick_height(l); h1 = item_quick_height(l) + linespacing();
if (l == item) { if (l == item) {
if (Y <= H) { // it is visible or right at bottom if (Y <= H) { // it is visible or right at bottom
Y = Y+h1-H; // find where bottom edge is Y = Y+h1-H; // find where bottom edge is
@ -310,7 +310,7 @@ void Fl_Browser_::display(void* item) {
l = lp; l = lp;
Y = -offset_; Y = -offset_;
for (; l; l = item_prev(l)) { for (; l; l = item_prev(l)) {
h1 = item_quick_height(l); h1 = item_quick_height(l) + linespacing();
Y -= h1; Y -= h1;
if (l == item) { if (l == item) {
if ((Y + h1) >= 0) position(real_position_+Y); if ((Y + h1) >= 0) position(real_position_+Y);
@ -395,7 +395,7 @@ J1:
void* l = top(); void* l = top();
int yy = -offset_; int yy = -offset_;
for (; l && yy < H; l = item_next(l)) { for (; l && yy < H; l = item_next(l)) {
int hh = item_height(l); int hh = item_height(l) + linespacing();
if (hh <= 0) continue; if (hh <= 0) continue;
if ((damage()&(FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) || l == redraw1 || l == redraw2) { if ((damage()&(FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) || l == redraw1 || l == redraw2) {
if (item_selected(l)) { if (item_selected(l)) {
@ -448,7 +448,7 @@ J1:
// update the scrollbars and redraw them: // update the scrollbars and redraw them:
int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
int dy = top_ ? item_quick_height(top_) : 0; if (dy < 10) dy = 10; int dy = top_ ? item_quick_height(top_) + linespacing() : 0; if (dy < 10) dy = 10;
if (scrollbar.visible()) { if (scrollbar.visible()) {
scrollbar.damage_resize( scrollbar.damage_resize(
scrollbar.align()&FL_ALIGN_LEFT ? X-scrollsize : X+W, scrollbar.align()&FL_ALIGN_LEFT ? X-scrollsize : X+W,
@ -585,7 +585,7 @@ void* Fl_Browser_::find_item(int ypos) {
int yy = Y-offset_; int yy = Y-offset_;
for (void *l = top_; l; l = item_next(l)) { for (void *l = top_; l; l = item_next(l)) {
int hh = item_height(l); if (hh <= 0) continue; int hh = item_height(l); if (hh <= 0) continue;
yy += hh; yy += hh + linespacing();
if (ypos <= yy || yy>=(Y+H)) return l; if (ypos <= yy || yy>=(Y+H)) return l;
} }
return 0; return 0;
@ -954,7 +954,8 @@ J1:
Fl_Browser_::Fl_Browser_(int X, int Y, int W, int H, const char* L) Fl_Browser_::Fl_Browser_(int X, int Y, int W, int H, const char* L)
: Fl_Group(X, Y, W, H, L), : Fl_Group(X, Y, W, H, L),
scrollbar(0, 0, 0, 0, 0), // they will be resized by draw() scrollbar(0, 0, 0, 0, 0), // they will be resized by draw()
hscrollbar(0, 0, 0, 0, 0) hscrollbar(0, 0, 0, 0, 0),
linespacing_(0)
{ {
box(FL_NO_BOX); box(FL_NO_BOX);
align(FL_ALIGN_BOTTOM); align(FL_ALIGN_BOTTOM);
@ -1053,7 +1054,7 @@ int Fl_Browser_::item_quick_height(void* item) const {
\returns The average height of items, in pixels. \returns The average height of items, in pixels.
*/ */
int Fl_Browser_::incr_height() const { int Fl_Browser_::incr_height() const {
return item_quick_height(item_first()); return item_quick_height(item_first()) + linespacing();
} }
/** /**

View File

@ -176,7 +176,8 @@ int Fl_Check_Browser::item_width(void *v) const {
return int(fl_width(((cb_item *)v)->text)) + CHECK_SIZE + 8; return int(fl_width(((cb_item *)v)->text)) + CHECK_SIZE + 8;
} }
void Fl_Check_Browser::item_draw(void *v, int X, int Y, int, int) const { void Fl_Check_Browser::item_draw(void *v, int X, int Y, int, int H) const {
Y += (H - item_height(v)) / 2;
cb_item *i = (cb_item *)v; cb_item *i = (cb_item *)v;
char *s = i->text; char *s = i->text;
int tsize = textsize(); int tsize = textsize();

View File

@ -76,7 +76,7 @@ Fl_File_Browser::full_height() const
for (i = 0, th = 0; i < size(); i ++) for (i = 0, th = 0; i < size(); i ++)
th += item_height(find_line(i)); th += item_height(find_line(i)) + linespacing();
return (th); return (th);
} }
@ -234,7 +234,7 @@ Fl_File_Browser::item_draw(void *p, // I - List item data
int X, // I - Upper-lefthand X coordinate int X, // I - Upper-lefthand X coordinate
int Y, // I - Upper-lefthand Y coordinate int Y, // I - Upper-lefthand Y coordinate
int W, // I - Width of item int W, // I - Width of item
int) const // I - Height of item int H) const// I - Height of item
{ {
int i; // Looping var int i; // Looping var
FL_BLINE *line; // Pointer to line FL_BLINE *line; // Pointer to line
@ -271,25 +271,23 @@ Fl_File_Browser::item_draw(void *p, // I - List item data
{ {
// Draw the icon if it is set... // Draw the icon if it is set...
if (line->data) if (line->data)
((Fl_File_Icon *)line->data)->draw(X, Y, iconsize_, iconsize_, ((Fl_File_Icon *)line->data)->draw(X, Y + (H - iconsize_) / 2,
(line->flags & SELECTED) ? FL_YELLOW : iconsize_, iconsize_,
(line->flags & SELECTED) ? FL_YELLOW :
FL_LIGHT2, FL_LIGHT2,
active_r()); active_r());
// Draw the text offset to the right... // Draw the text offset to the right...
X += iconsize_ + 9; X += iconsize_ + 9;
W -= iconsize_ - 10; W -= iconsize_ - 10;
// Center the text vertically...
height = fl_height();
for (t = line->txt; *t != '\0'; t ++)
if (*t == '\n')
height += fl_height();
if (height < iconsize_)
Y += (iconsize_ - height) / 2;
} }
// Center the text vertically...
height = fl_height();
for (t = line->txt; *t != '\0'; t ++)
if (*t == '\n')
height += fl_height();
Y += (H - height) / 2;
// Draw the text... // Draw the text...
line = (FL_BLINE *)p; line = (FL_BLINE *)p;

View File

@ -86,7 +86,7 @@ void button_cb(Fl_Widget *w, void *v) {
break; break;
case 1: { // Copy case 1: { // Copy
const char *text = message_box->label(); const char *text = message_box->label();
const int len = strlen(text); const int len = (int)strlen(text);
Fl::copy(text, len, 1); Fl::copy(text, len, 1);
} }
printf("Message copied to clipboard.\n"); printf("Message copied to clipboard.\n");

View File

@ -454,6 +454,7 @@ int main(int argc, char** argv) {
browser->align(FL_ALIGN_TOP|FL_ALIGN_LEFT); browser->align(FL_ALIGN_TOP|FL_ALIGN_LEFT);
browser->when(FL_WHEN_CHANGED); browser->when(FL_WHEN_CHANGED);
browser->callback(ui_browser_cb); browser->callback(ui_browser_cb);
browser->linespacing(2);
int n = UnitTest::num_tests(); int n = UnitTest::num_tests();
for (i=0; i<n; i++) { for (i=0; i<n; i++) {