FLTK logo

STR #3211

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 Home  |  Articles & FAQs  |  Bugs & Features  |  Documentation  |  Download  |  Screenshots  ]
 

Return to Bugs & Features | SVN ⇄ GIT ]

STR #3211

Application:FLTK Library
Status:1 - Closed w/Resolution
Priority:1 - Request for Enhancement, e.g. asking for a feature
Scope:3 - Applies to all machines and operating systems
Subsystem:Core Library
Summary:Scrolling Tabs Widget
Version:1.4-feature
Created By:FlyingJester
Assigned To:matt
Fix Version:1.4.0
Fix Commit:e0830305a2c36bbc56f4a2dc0d009729592a438a
Update Notification:

Receive EMails Don't Receive EMails

Trouble Report Files:


Name/Time/Date Filename/Size  
 
#1 greg.ercolano
20:34 Mar 26, 2015
x.png
0k
 
 
#2 greg.ercolano
20:35 Mar 26, 2015
x.h
2k
 
 
#3 AlbrechtS
04:35 Mar 27, 2015
test.diff
0k
 
 
#4 AlbrechtS
04:39 Mar 27, 2015
resized_and_clicked.png
7k
 
 
#5 AlbrechtS
05:47 Mar 27, 2015
test2.diff
2k
 
 
#6 Teklad
16:37 Sep 24, 2016
example.png
19k
 
 
#7 Teklad
18:47 Feb 18, 2017
Fl_Tabs.H.patch
1k
 
     

Trouble Report Comments:


Name/Time/Date Text  
 
#1 FlyingJester
21:21 Mar 25, 2015
I've been working on a scrolling tabs widget (much like how tabs work in Firefox). It's similar to the existing tabs widget, except that it includes scroll buttons for when too many tabs exist, and each tab has a button that closes/removes the tab.

I am wondering if there is interest in including such a widget in FLTK, and what I would need to do to make it suitable for inclusion.

The code and test application can be found at https://github.com/FlyingJester/Fl_Scroll_Tabs

Feedback is very welcome!
 
 
#2 AlbrechtS
05:38 Mar 26, 2015
Please see STR #3052 for a similar proposal.  
 
#3 AlbrechtS
05:54 Mar 26, 2015
Tested, works (basically).

I believe that there is interest in such an extension of Fl_Tabs, since there have been more such queries and there is at least one alternate proposal.

I wonder if it would be useful to derive the new class from Fl_Tabs instead of Fl_Group so it can benefit from (re)using some of its methods, particularly client_area(), but maybe more.

Regarding your question how to make it suitable for inclusion:

(1) Please take a look at the CMP and make the code compliant to the FLTK coding standards, particularly indenting, space after keywords, etc.
http://fltk.org/cmp.php#CODING_STANDARDS

(2) We need doxygen docs for all our widgets. These should be supplied with the code in the .cxx or in the header file:
http://fltk.org/cmp.php#DOCUMENTATION

There is likely more but I don't have the time to do more testing and/or code review now.

We should compare both proposals and pick the best parts of both. I'd prefer one that inherits Fl_Tabs.
 
 
#5 AlbrechtS
06:09 Mar 26, 2015
Some more comments (just my own opinions as a user, not as a FLTK dev):

(1) The drawing of the 'x' button needs improvement. It looks like a textual 'x' (I didn't verify this in the code though). There should perhaps be an own draw function or an image (pixmap) that can be drawn as the 'x'.

(2) The borders of the tabs and the 'x' button should be separated better (optically), maybe with a wider spacing or another border.

(3) Text that is too wide should maybe be cut and get '...' at the end, not just be clipped.

All this would be to make it /look/ better, but maybe not necessary.

These comments may apply to STR #3052 as well (or not). I should have posted a direct link before, so FWIW:

http://www.fltk.org/str.php?L3052
 
 
#6 FlyingJester
14:49 Mar 26, 2015
I've updated (mostly) to use K&R formatting, and changed to inherit from Fl_Tabs.

My initial thought was that Fl_Tabs and this widget have rather different intentions, since Fl_Tabs is best suited for fixed information and this widget is intended to be dynamic. But I thought about it, and I agree that it should inherit from Fl_Tabs. Most of the API, particularly for selecting tabs, is shared shared anyway.

I will need to do more testing now that I've changed its base class, of course.

The X is currently drawn textually. I had heard that is what GTK does in this circumstance, and I didn't know of any case where FLTK already drew an X like that. I'm not especially happy with how that part looks, either. I'll see about drawing my own X for it.

I think I would actually like to have proportional tab sizes like Fl_Tabs has, but allow a maximum and minimum tab size.
 
 
#7 greg.ercolano
20:34 Mar 26, 2015
Neat -- thanks for the contribution.

Looked at it, would like to see the left/right buttons disappear
when there's nothing to scroll to, or all tabs are visible.
(e.g. when you X out enough tabs that they're all on screen)

The 'X's are kinda huge, could be more subtle. I figure an inline
.xpm or .png could handle drawing a nice antialiased X with some
transparency.

I've attached x.png which is an 8x8 transparent 'x' that might be good.
I'll also attach it as an x.h which is a raw RGBA hex dump of the image
which can I think be compiled into the code and passed to Fl_RGB_Image
so that a full 8 bit alpha can be used to 'composite' the transparent
"x" over the tabs, regardless of what their color content might be.
 
 
#8 FlyingJester
21:12 Mar 26, 2015
Hmm, the X appears antialiased to me on OS X. Using a preset image would mean needing a double-resolution version as well for high-dpi displays, I assume?

Adjusting the X's proportions is pretty simple with the widget as it is. Should it really be aa'ed? If it's just pure diagonal lines...

Removing the arrows when the tabs aren't overflowing shouldn't be too difficult, I'll have a look.
 
 
#9 AlbrechtS
04:35 Mar 27, 2015
Wow, that was a quick reaction. The code looks much better now (more FLTK-compliant), inheritance (from Fl_Tabs) is fixed, and doxygen comments were added. Well done, thanks for this great contribution!

Please see attached tiny patch for test.cxx to add missing end() statements (just for completeness) and make the window resizable. A resizable window can help testing the layout (see below).

Comments/suggestions/opinions:

(1) The close button should have a max. (fixed?) width. It is too big if the tabs are higher than in the default test program (use my patch and resize the window to see what I mean). I think 24-30 would be a good size (width). If the tabs are higher, then the X should be centered vertically.

(2) The same (max. or fixed width) would be good for the left and right scroll buttons (arrows).

(3) A tab that is clicked should become fully visible _when_ it is clicked, i.e. clicking a partially visible tab would scroll the tabs to make the active tab fully visible. It can be moved outside the visible area later. IIRC the proposal in STR #3052 does this.

(4) Scrolling the tabs when holding the mouse button is a great feature. However I'd also like that clicking only once would scroll by at least one full tab. Can this both be done and combined? Maybe so that the scroll offset is (always) adjusted to the next tab when the mouse button is released? I assume it can be done, but I didn't look at the code in all details yet.


One more note (just a thought): this contribution is (of course) ABI preserving, hence we can add it whenever we like. Now that Fl_Scroll_Tabs inherits Fl_Tabs it _might_ be useful to modify Fl_Tabs so Fl_Scroll_Tabs could share more code/methods. Since we are planning to start working on FLTK 1.4 soon I could imagine to have ABI breaking changes in Fl_Tabs if needed (maybe new virtual methods). This should be considered if it would improve the integration of this new widget.
 
 
#10 AlbrechtS
04:39 Mar 27, 2015
Please see attached image resized_and_clicked.png for my points (1) to (3) in comment #9: I resized the window and clicked the "Interaction" tab after scrolling it partially out of the visible area.  
 
#11 AlbrechtS
05:47 Mar 27, 2015
More test results and suggestions:

Fl_Scroll_Tabs could be used as a drop-in replacement for Fl_Tabs if clear_closebutton() is used (or is the default). However, my tests showed these issues:

(1) The label text is clipped as if clear_closebutton() was not used, i.e. an empty space is shown instead of more text.

(2) The tabs can only be in the top position, whereas Fl_Tabs allows the tabs to be at the bottom of the widget, depending on the sizes and positions of the children. Although I personally don't think that this feature is widely used it should be preserved if we wanted Fl_Scroll_Tabs to be usable as a drop-on replacement.

Please apply attached test2.diff _after_ test.diff for more enhancements (test features) and correction of group sizes. There are two #define's to select the widget type and the relative group positions (24 => tabs at top, 0 => tabs at bottom) resp. and two commented statements at the end to enable other test features.

    // scroll_tabs->resizable(group1);

Uncomment this to make the tab height fixed when resizing the window.

    // scroll_tabs->clear_closebutton();

Uncomment this to remove the close button.
 
 
#12 FlyingJester
14:49 Mar 27, 2015
I've added proportional text, truncation, and tab size limits. Buttons now have a limited width, although they are not centered vertically yet, just vertically stretched. The X's are, of course, no longer textual.

Selecting a tab now puts the entire tab label into view. I still need to make the scrolling roll over to the next tab when it stops.

I fixed many bugs with with the scroll buttons.

Regarding when to switch over to tabs on bottom, I assume that should happen when there is insufficient space above the tab groups for the tab bar, but there is enough room below?

I also noticed that Fl_Tabs seems to get its tab bar spacing from its first tab group. I have been checking the spacing of all tab groups. Should I change to how Fl_Tabs does it, or is it fine/better to check all the groups?
 
 
#13 AlbrechtS
16:11 Mar 27, 2015
Regarding tab positions: it is documented in text form, but unfortunately the method Fl_Tabs::tab_height() is not documented (doesn't have doxygen docs). There are obviously some methods still lacking docs... oh, I see: they are private!

That's maybe one of these ABI breaking changes we could need that I mentioned before: make tab_height() at least protected, but we could also make it public (why not?). I'm not sure if this would really break the ABI, but maybe.

See http://www.fltk.org/doc-1.3/classFl__Tabs.html#details :

"The size of the tabs is controlled by the bounding box of the children (there should be some space between the children and the edge of the Fl_Tabs), and the tabs may be placed "inverted" on the bottom - this is determined by which gap is larger."

You should probably use Fl_Tabs::tab_height() to determine the best position and to be consistent with Fl_Tabs.

You wrote:
"I also noticed that Fl_Tabs seems to get its tab bar spacing from its first tab group. I have been checking the spacing of all tab groups. Should I change to how Fl_Tabs does it, or is it fine/better to check all the groups?"

Did you get this from client_area()? I remember that we added client_area(), but I don't know why this method returns the values of child(0) if a child exists. This is certainly suboptimal (say: wrong?). I'll take a look into it, but you should ignore this method for now. Stick with tab_height() and you should be fine. Until we decide how to proceed (make it protected or public) you can probably copy this method and use it in your own code.

I'll take a look at your other changes tomorrow (it's after midnight here).
 
 
#14 FlyingJester
17:50 Mar 27, 2015
Yeah, I saw that most of the interesting parts of Fl_Tabs are private rather than protected. That's why I initially inherited directly from Fl_Group, I can only share a part of what I'd like to with Fl_Tabs.

I'm currently duplicating some of the tab size and position calculation logic that exists in Fl_Tabs, but that's also kind of unavoidable since I'm adding close buttons to the tabs themselves.
Same for drawing each tab, I'm doing it a little differently than Fl_Tabs, but there's not really a reason other than that I can't touch a lot of the guts that I'd need to to share this stuff with Fl_Tabs.

Alright, I'll copy tab_height from Fl_Tabs and use that. I do need to do a few more calculations on top of that for the scroll button and close button sizes at the same time, too, but I'll integrate the use of tab_height so if it goes to protected it'll just work.
 
 
#15 FlyingJester
18:55 Mar 27, 2015
OK, I copied tab_height() from Fl_Tabs and set things up to use that to calculate tab height.

I've enabled tabs on bottom, which seems to work fine now.
 
 
#16 AlbrechtS
05:30 Mar 31, 2015
Sorry, I'm too much distracted by other work now to reply with useful test results and/or code review. Only one note to tabs on bottom: it looks like there's a border on the bottom instead of the top of the tabs. The layout should be "mirrored" WRT tabs on top. But I may be wrong...

I need a few days timeout, but I'll try to be back to this soon.

You can however tell us which methods of Fl_Tabs you might want to reuse. We're approaching the end of the FLTK 1.3.x series, and we may break the ABI in 1.4.0. If we assume that your code will be in 1.4 we can make it work with changed Fl_Tabs code, hence you can assume that the methods you need will be protected or public.

We can also add ABI guards in FLTK 1.3.4 to enable your code in "ABI feature mode", although I believe that this will likely not be the case, because the time is too short to make it into FLTK 1.3.4.
 
 
#17 FlyingJester
15:46 Apr 02, 2015
You're right about it not drawing right with tabs on bottom, but I don't think the issue is that I'm drawing a border of the whole widget. I think that's just the border of the tabs being drawn with the vertical offsets for selection they should have if they are on top, instead of the offset being reversed for tabs on bottom.

The whole widget draws itself as a FL_FLAT_BOX. I do not draw the widget behind it when the tab bar is not full yet, since I figure the tab bar is a part of the widget. It shouldn't be transparent the same why a scrollbar is not transparent behind the handle.

I've updated to make the tabs scroll on to the next, partially revealed tab when you scrolling stops.

So, just recapping for myself, still to do:

 * make the vertical size of the close buttons proportional
 * Fix vertical tab drawing offset for tabs on bottom
 * Properly integrate the use of client_area
 * Fix label drawing to use the child's label font and styling rather than the Fl_Scroll_Tab's.
 
 
#18 guyben
10:47 Apr 03, 2015
Hi! I'm Guy, from the two proposals http://www.fltk.org/str.php?L3052 and http://www.fltk.org/str.php?L3053

I think we should consolidate the discussion in one thread, so let's do it here :)

You can now get the code for my version of the tabs here: https://bitbucket.org/guyben/fltk_tabs

I've fixed the code to be compliant with the coding (I think? At least should be viewable with tab size 8)

--------------

I have two different classes:

Fl_Scroll_Tabs
==============
An Fl_Tabs with the ability to scroll the tab list left/right if there are too many tabs. It doesn't give the ability to create or destroy tabs.

Fl_Drag_Tabs
============
Can inherit from either Fl_Scroll_Tabs OR Fl_Tabs, and adds the ability to drag tabs to reorder them, drag them to new windows or between windows (try the main_complex.cc file to see how it works). It doesn't give the ability to create or destroy tabs either (main_complex.cc creates that option in the program, but it isn't part of the Fl_Drag_Tabs)

-------------------

So about inheritance: I don't think Fl_Scroll_Tabs should inherit from Fl_Tabs. Why? Because it has to replace the existing "which" method (that returns which tab title is at location x,y), which means making this method virtual, which I really am against.

For example, in the current #3211 implementation of Fl_Scroll_Tabs, if I do:

Fl_Tabs *tabs = new Fl_Scroll_Tabs();
//....
Fl_Widget *pressed = tabs->which(x,y);

I will get the wrong widget.

Instead, I think Fl_Scroll_Tabs should _combine_ with the existing Fl_Tabs, so there's an option (in the flags) to make it into a scrolling tabs.

--------------------

Adding the close button to the tabs is OK, but should be done via the fltk flags as well I think. However, I don't like that we have multiple callbacks in one widget. The "normal" fltk behavior is that each widget type has a single action type, and there's a uniform way to set the callback for that action (via the Fl_Widget interface).

Having an additional action here seems wrong, and would make some existing things problematic - like fluid for example.

I don't have a good solution for it - that's why I didn't add a close button to my tabs.

The best thing I can think about (and did it in the main_complex.cc) is to have a single button that closes the current tab, and have that outside of the Fl_Tabs:

A wrapper widget that gets an internal Fl_Tabs and has a "new" and "close" button, both activate its default action. I can write this wrapper widget if we decide it's the way to go.

------------------------------

Fl_Drag_Tabs: I had to reimplement the dnd (drag and drop) mechanics for it. I just copied the dnd function and changed it slightly. I needed a really minor change to make it more "useful" for other kind of drag and drops - and I think this should be merged with the current dnd function. Not only to remove redundancy, but to make the current dnd function more useful to any other "cross-widget drags" people might want to implement in the future.

I still need to polish this implementation a bit - for example, the deletable state should be in the flags, and I'm not sure I like the "creator" function (that creates a new parent window if you drag a tab to a new area). Like I said - I don't like adding new "action functions". Maybe this Fl_Drag_Tabs should also be a wrapper around Fl_Tabs.

-------------------------------
 
 
#19 AlbrechtS
14:49 Apr 03, 2015
Hi Guy, thanks for joining us here and for modifying and posting your code. I could download your code (git clone) and I took a first look at it. I also read your comment(s) here, but I'm still too busy to give any useful comments. Currently I can only tell Martin (FlyingJester) and you that I'm still interested in adding an extended Fl_Tabs widget. Other devs will have to check and vote, but let's see how it works out first.

Thanks
Albrecht
 
 
#20 FlyingJester
16:47 Apr 03, 2015
I wasn't too worried that a cast breaks some aspects of the Fl_Scroll_Tabs, I suspect this happens with my implementation as well. I've had this happen with other fltk widgets, notable Fl_Menu_Bar and the Sys_Menu_Bar, I thought it was acceptable?

Changing to have a single callback could make sense. I just put two in because there are no other Fl_Group widgets that allow you to remove children, so I had nothing to go on. Just making it a different `when' would work.

Having the close button is one of the features that rather I want to have. Dragging being another.

I think it would make more sense for this to be separate from Fl_Tabs. I always thought Fl_Tabs was for static content, and this would be for dynamic content. There are much finer distinctions that result in multiple widgets in fltk.
 
 
#21 guyben
21:13 Apr 03, 2015
Fl_Sys_Menu_Bar inherits from Fl_Menu_Bar is to avoid code duplication - it's actually a different implementation (for a different system). I guess technically they should both inherit from the same common base, each specialized for a different system.

However, there really isn't a "code duplication" reason to have Fl_Scroll_Tabs inherit from Fl_Tabs. The only reason to inherit is so that a widget that is supposed to receive an Fl_Tabs can receive an Fl_Scroll_Tabs instead. If we don't give people that option to begin with (because of the non-virtual "which") then there's no point to have them inherit. I mean, what's the benefit? If Fl_Scroll_Tabs isn't "is a" of Fl_Tabs, and we don't use the same code at all, then what's the point of inheritance?

--------------------------------

About the static vs. dynamic content: I tend to agree. Fl_Tabs does make more sense (currently at least) as a static tabs thing.

However, even a static tabs widget could benefit from adding scrolling capabilities, especially if the size of the widget can be changed. Even for static tabs, if you make it small enough the tabs become unusable in the current Fl_Tabs, and allowing it add scrolling titles would be beneficial.

Think of it like the "Fl_Hor_Nice_Slider" that looks like a specialization of "Fl_Slider", and technically it is, but actually it just sets the default type to type(FL_HOR_NICE_SLIDER);

I imagine the same thing here: you can set the type to add scrolling to any tab, and all Fl_Scroll_Tabs does is set this type by default.

------------------------------

Regarding delete (and actually also new, and even other things as well):

Note that you don't actually do the "delete", you just send a message that the X was pressed. Deleting is just one of many things one would want to do with dynamic tabs. Here are a few others, that usually have buttons on the tab line:

- delete / hide

- new

- open closed / hidden tabs (similar to new, but instead of a button that creates an empty tab it opens a menu that lists all the currently hidden tabs)

- duplicate

- rename (usually using a right click on the tab)

your solution is good for the often used case of delete, but we want to make tabs general for any action - not just hard coded for one.

I don't like solving just one of these and leaving the rest unsolved. At the very least if you have a "close" button on tabs, you would want a "new" button on the right of the tab list.

-----------------------

I would want to say "instead of a close button on each tab, have a "close current tab" button on the right. And instead of that, actually have a "leave enough space at the right of the tab bar for this thing I need" and then have a widget placed there - so one person would have nothing, another would have "close / add" buttons, another would have a drop-down menu with options, another would have a "reload" button.

Another option I really liked - but is a bit too much of a change from current fltk - is to have the tab list as a completely separate widget! That way you can place the tab-list in one place and the tabbed widgets themselves some other place (meaning you can size / position them in such a way that leaves space for whatever buttons / address bar you want).

-----------------

bottom line - the reason I dislike the X is that they are too specific, when users might want slightly different things. I'd rather have a solution that allows any kind of widget to be places on one side of the tab-list.
 
 
#22 FlyingJester
14:47 Apr 04, 2015
There is a code de-duplication reason to inherit from Fl_Tabs, though. If you look at my implementation, the tab height, client area, and tab widths and positions are duplicated from Fl_Tabs. If a few simple non-API-breaking changes are made to Fl_Tabs from 1.3 to 1.4, much more could be shared as well, including drawing the tabs themselves and drawing the labels.

For what I am using my implementation for, I cannot say I have had a need for rename or duplicate or having hidden tabs. I added a close button to solve the problems I ran into when writing a tabbed text editor.

I don't like the idea of a single, close-current-tab button, because that's not how the most common uses of dynamic tabs work (Firefox/XUL, Chrome, Codelite & Code::Blocks/WxWidgets). FLTK would be the only toolkit that works that way. XUL and WxWidgets have individual close buttons, I find this to be easier to use. These implementations also do not have a dedicated new-tab button.

---

If adding the ability to delete a tab really opens this kind of floodgate, personally I would much rather see just scrolling tabs with max/min tab sizes, and nothing else. That solves the only real shortcoming of Fl_Tabs.
 
 
#23 AlbrechtS
16:07 Apr 04, 2015
Only a few comments w/o concrete code analysis or such:

Code sharing can be improved. We're probably talking about FLTK 1.4 for the new widget(s) anyway (which is to start development soon), so we should be free to make ABI breaking changes in Fl_Tabs.

If need be, we could also do this for FLTK 1.3.4 with FL_ABI_VERSION guards. FLTK 1.3.4 should be released in May 2015 (hopefully), but my priority is on the release and not on additional widgets.

Possible changes in Fl_Tabs include making some methods virtual. I don't see problems if we need to make some methods virtual. FLTK 1.4 will have more virtual methods anyway. But I need to read what Guy wrote about his concerns related to virtual methods (or not). Maybe I misunderstood something.

Guy is right in that many widgets in FLTK have one class that serves all and derived classes only set a type() value. I'm not keen on duplicating this approach, but I was also thinking about integrating some of the code (features) of Fl_Scroll_Tabs in Fl_Tabs and adding methods to enable or disable features like the close button(s) and tab scrolling. Some of this is only a matter of taste or how complex the additional code would be. If the additional code would be too much it would probably be better to use a real subclass so that users that only need a classic Fl_Tabs widget don't suffer from increasing code size.

Just my thoughts for now...
 
 
#24 guyben
22:14 Apr 04, 2015
I still think that if Fl_Scroll_Tabs inherits from Fl_Tabs, it must function correctly if stored in an Fl_Tabs*. However, if we can change the `which` function to be virtual this could solve the problem. The reason I don't want to do it is that it changes current Fl_Tabs interface. If we're OK with it then cool.

I still think there are benefits to having it a style choice for the regular Fl_Tabs, but I don't feel too strongly about it.

You're right that the current standard is to have the close button on the tabs. So yea, I'm convinced that if we do add it - it should be on the tabs.

It's probably best though to only have a single close button, only on the current tab. That the behavior you often get (it's the default in wxwidgets, and it's what firefox/chrome defaults to when you have a lot of tabs). It will both simplify the code and keep the program light (only one image to display)

I could live with this solution: turning `which` to virtual, adding close button on the current tab (obviously it should be an option to not have a close button), keeping it to a single callback.
 
 
#25 FlyingJester
10:29 Apr 24, 2015
I've basically just copied some of the methods from Fl_Tabs, and I would think that when 1.4 comes around the methods would be made at least protected, if not virtual in Fl_Tabs.

I've fixed the scaling of the close buttons and many issues with tabs on bottom.
 
 
#26 Teklad
16:36 Sep 24, 2016
I found this a bit late while plugging away at my own version of closing tabs, so I figured I'd post on this just to show an example of what I came up with, since the code for it is super simple.

Originally I was using fonts to display the "x" button, but after AlbrechtS pointed me in the right direction I was led here.

So after a bit of experimentation I came up with something that's pretty flexible while still being light.

You can see an example by compiling the code from:
https://github.com/Teklad/flyde

Otherwise, you can grab the tabs.h/cpp files along with the x.h provided here.

I'm attaching an image to give an example of what it looks like... (it works both on normal and inverted tabs).
 
 
#27 Teklad
04:59 Sep 25, 2016
I ended up rewriting more of the tabs code than I thought I would... Got a little slap happy with trying to make it behave more like a modern tab widget.

I've done my best to keep it as compliant as possible.  A side effect from some of the code changes made has allowed the widget to support a "crap" ton of tabs without freaking out(yay for math?).

Just to touch on a few key changes:
- tab_positions() Uses a different method for stacking tabs when the bar starts getting full, which allows it to store a lot more tabs without looking "weird". Minor floating point math involved.

- draw_tab() is now index-based and uses a helper_function tab_dimensions() to get the correct location/width/height for the tab placement.  This allowed cutting out the entire if(H >= 0)/else bit, which makes it a one-shot function.

- close buttons are semi-dynamic... When tab space gets limited and the mode is to show close buttons on all tabs, it will hide them for all but the active tab until some space is free.  This greatly reduces the chance for "misclicks" (Everybody hates an oopsie.)

- STATES! An initial implementation to keep track of the tab widget's current UI state.  Its good for allowing functions to know what's going on(i.e. are tabs being truncated/close buttons being hidden)

- There's an experimental feature that involves coloring the close button on hover.  This is going to be moved to its own derived class... since its purely cosmetic and doesn't really have any business in the base class.

I'll try to keep this thread updated with progress on this so I can get opinions on the changes. :)
 
 
#28 Teklad
18:49 Feb 18, 2017
Uploaded my first attempt at getting Fl_Tabs to be more reasonable with its base class.... if there's any changes that need made, let me know so I can smack it with a large trout. :P  
 
#29 AlbrechtS
08:42 May 22, 2017
I committed svn r12243 in branch-1.4 which makes more methods of Fl_Tabs virtual and/or protected as discussed above for easier subclassing. Changed methods and new attributes:

clear_tab_positions:    protected, virtual
draw_tab:               protected, virtual
redraw_tabs:            protected, virtual
tab_height:             protected, virtual
tab_positions:          protected, virtual
which:                  (public), virtual

New and/or changed member variables:

tab_count:              protected
tab_pos:                protected
tab_width:              protected

Attributes in parentheses like (public): not changed in this commit.

These methods have not (yet?) been changed but might be if requested:

client_area:            (public) maybe virtual?

To do: document methods changed from private to protected or public. Note to myself: clear_tab_positions(), draw_tab(), redraw_tabs(), tab_height(), tab_positions(), and member variables tab_count, tab_pos, tab_width.

I apologize for the long delay to all who proposed patches. I'd appreciate if you could rewrite/rebase your patches on the latest svn commit so they reuse the protected methods and post updated patches or links to your own repositories.

I'll try to check these patches ASAP and commit/merge as appropriate.

My current thoughts for further development: we can (maybe) add some small parts to the existing Fl_Tabs widget as options (maybe the optional delete buttons?), but only as long as the code additions are very small. All additions to Fl_Tabs must be optional, small, and must not change its appearance for backwards compatibility. Users that link statically and maybe write software for embedded systems shall not pay for new features they don't use. I consider the overhead of adding more virtual methods acceptable.

I imagine that we may have this widget hierarchy:

  Fl_Tabs
    |
    |-- Fl_Scroll_Tabs
          |
          |-- Fl_Drag(gable)_Tabs

... but I'm open for other proposals.

Fl_Scroll_Tabs and Fl_Drag_Tabs may IMO have the new tabs layout as they are new and 'modern' widgets, whereas Fl_Tabs should keep the old FLTK layout.

My goal is to get the new Fl_Tabs widget(s) ready and committed within 4-8 weeks, if possible.

Thanks for all your contributions.
 
 
#30 AlbrechtS
09:34 May 22, 2017
Note: changed from 1.3-feature to 1.4-feature, assigned to myself, set status to 'active'.

This STR and related ones have now high priority on my personal to-do list. I'll try to react quickly on discussions and new patches, and I'll try to coordinate and consolidate patches to get ready for commit(s).

If you're interested or one of the contributors of new Fl_Tabs widgets (patches), please follow the discussion in fltk.coredev, thread "New Fl_Tabs widgets", started today. All comments are welcome.
 
 
#31 matt
15:28 Jan 04, 2023
In GitHub PR #628 I have implemented Close buttons for Tabs. Sorry, I have not read the entire text in this STR yet.  
 
#32 AlbrechtS
16:02 Jan 04, 2023
Note: I unassigned this STR.

@Matt: please feel free to take over...
 
 
#33 matt
05:19 Jan 05, 2023
Fixed in Git repository.

There are some additional features pending that I may or may not get to in the next days.
 
 
#34 matt
16:29 Jan 14, 2023
Fixed in https://github.com/fltk/fltk/pull/628  
 
#35 matt
16:31 Jan 14, 2023
Fixed in Git repository.  
     

Return to Bugs & Features ]

 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.