diff options
| author | Matthias Melcher <github@matthiasm.com> | 2023-09-06 17:02:08 +0200 |
|---|---|---|
| committer | Matthias Melcher <github@matthiasm.com> | 2023-09-06 17:02:13 +0200 |
| commit | 5ef29202ede1042da22044bb10017e2db04a89df (patch) | |
| tree | fe96cbf8769cddec45a783777afec61971556366 /src/Fl_Tabs.cxx | |
| parent | a683752e4b312530067e9973f489edf9476db744 (diff) | |
Fixes Fl_Tabs to be more robust.
No children in Fl_Tabs should no longer crash the draw
method. Also, drawing an Fl_Tabs with no children inside
is now defined and documented.
Diffstat (limited to 'src/Fl_Tabs.cxx')
| -rw-r--r-- | src/Fl_Tabs.cxx | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/src/Fl_Tabs.cxx b/src/Fl_Tabs.cxx index 7a402df7d..f84a0002f 100644 --- a/src/Fl_Tabs.cxx +++ b/src/Fl_Tabs.cxx @@ -60,6 +60,8 @@ void Fl_Tabs::on_remove(int index) { else if (index>0) value(child(index-1)); } + if (children()==1) + damage(FL_DAMAGE_ALL); Fl_Group::on_remove(index); } @@ -99,8 +101,19 @@ void Fl_Tabs::resize(int X, int Y, int W, int H) { The protected variable `tab_count` is set to the currently allocated size, i.e. the number of children (`nc`). - \returns Index of the selected item, counting from 1 to nc. - \retval 0 If the number of children is 0 (zero). + \returns Index of the selected item + \retval -1 If the number of children is 0 (zero). + + \note Return values in 1.3 were not documented. Return values before Sep 2023 + were documented as 1 based index and 0 if there were no children. This + was actually never the case. It always returned a 0 based index and + the (useless) value of also 0 if there were no children. The current + version return -1 if there are no children. + + \note For this method to work, only on single child should be selected. + Calling the method \ref value() before calling \ref tab_positions() + will ensure that exactly one child is selected and return a pointer + to that child. \see clear_tab_positions() */ @@ -115,7 +128,7 @@ int Fl_Tabs::tab_positions() { } tab_count = nc; } - if (nc == 0) return 0; + if (nc == 0) return -1; int selected = 0; Fl_Widget*const* a = array(); int i; @@ -743,8 +756,18 @@ void Fl_Tabs::draw() { // MARGIN is the minimal distance to the left and right edge of Fl_Tabs for // the selected tabs if the overflow mode allows scrolling - Fl_Widget *selected_child = value(); - int selected = tab_positions(); + if (children() == 0) { + fl_rectf(x(), y(), w(), h(), color()); + if (align() & FL_ALIGN_INSIDE) + draw_label(); + clear_damage(); + return; + } + + Fl_Widget *selected_child = value(); // return the first visible child and hide all others + tab_positions(); + int selected = find(selected_child); // find that child in the list and return 0..children()-1 + if (selected == children()) selected = -1; // if anything fails, selected is -1 and int H = tab_height(); Fl_Color selected_tab_color = selected_child ? selected_child->color() : color(); bool tabs_at_top = (H > 0); @@ -793,31 +816,38 @@ void Fl_Tabs::draw() { // -- draw selection border fl_push_clip(x(), selection_border_y, w(), selection_border_h); - int stem_x = x() + tab_pos[selected] + tab_offset; - int stem_w = fl_min(tab_pos[selected+1] - tab_pos[selected], tab_width[selected]); if (colored_selection_border) { draw_box(box(), x(), child_area_y, w(), child_area_h, selected_tab_color); draw_box(box(), x(), selection_border_y, w(), selection_border_h, selection_color()); - if (tabs_at_top) - fl_rectf(stem_x, selection_border_y, stem_w, selection_border_h/2, selection_color()); - else - fl_rectf(stem_x, selection_border_y+selection_border_h-selection_border_h/2, stem_w, selection_border_h/2, selection_color()); } else { draw_box(box(), x(), child_area_y, w(), child_area_h, selected_tab_color); - fl_rectf(stem_x, child_area_y-tabs_h, stem_w, child_area_h+2*tabs_h, selection_color()); + } + // draw the stem, the area that reaches from the tab into the selection border + if (selected != -1) { + int stem_x = x() + tab_pos[selected] + tab_offset; + int stem_w = fl_min(tab_pos[selected+1] - tab_pos[selected], tab_width[selected]); + if (colored_selection_border) { + if (tabs_at_top) + fl_rectf(stem_x, selection_border_y, stem_w, selection_border_h/2, selection_color()); + else + fl_rectf(stem_x, selection_border_y+selection_border_h-selection_border_h/2, stem_w, selection_border_h/2, selection_color()); + } else { + fl_rectf(stem_x, child_area_y-tabs_h, stem_w, child_area_h+2*tabs_h, selection_color()); + } } fl_pop_clip(); // -- draw all tabs fl_push_clip(x(), tabs_y, w(), tabs_h); int i; - for (i=0; i<selected; i++) + int safe_selected = selected == -1 ? children() : selected; + for (i=0; i<safe_selected; i++) draw_tab(x()+tab_pos[i], x()+tab_pos[i+1], tab_width[i], H, child(i), tab_flags[i], LEFT); - for (i=children()-1; i > selected; i--) + for (i=children()-1; i > safe_selected; i--) draw_tab(x()+tab_pos[i], x()+tab_pos[i+1], tab_width[i], H, child(i), tab_flags[i], RIGHT); - if (selected_child) + if (selected > -1) draw_tab(x()+tab_pos[selected], x()+tab_pos[selected+1], tab_width[selected], H, selected_child, tab_flags[selected], SELECTED); fl_pop_clip(); |
