2

I want to make my tab labels share the JTabbedPane width. If there's one tab, fit whole width, if two tabs, share width, if three, 1/3 for each and so on...

i don't even know if it's possible to do it without putting a component there and resizing it, maybe JTabbedPane has a way of resizing it's tab label via method and i don't know...

Anyone got any idea how to make it by the easiest way possible?

Kalle Richter
  • 8,008
  • 26
  • 77
  • 177

2 Answers2

6

As @trashgod already noted, the tab layout is handled by the LAF-specific SomeLAFTabbedPaneUI, more specifically the TabbedPaneLayout. So the way to go is

  • implement a custom subclass MySomeLAFTabbedPaneUI which has a custom extended TabbedPaneLayout (you need to do that for every SomeLAF you want to support
  • replace the normal ui by your custom class

The first boils down to hook into the calculation of the rectangles which are used for painting the tabs/locating custom tabComponents. Something like (note: obviously not production ready :-)

public class XMetalTabbedPaneUI extends MetalTabbedPaneUI {

    public static ComponentUI createUI(JComponent c) {
        return new XMetalTabbedPaneUI();
    }

    @Override
    protected LayoutManager createLayoutManager() {
        return new XTabbedPaneLayout();
    }


    protected class XTabbedPaneLayout extends MetalTabbedPaneUI.TabbedPaneLayout {

        protected Container tabContainer;

        @Override
        protected void calculateTabRects(int tabPlacement, int tabCount) {
            super.calculateTabRects(tabPlacement, tabCount);
            // TODO: check if it makes sense to stretch
            int max = 0;
            int sum = 0;
            Rectangle r = new Rectangle();
            for (int i = 0; i < tabCount; i++) {
                getTabBounds(i, r);
                max = Math.max(max, r.width);
                sum += r.width;
            }
            // TODO: calculate real width, that is -insets
            int paneWidth = tabPane.getWidth() - 10; 
            int free = paneWidth - sum;
            // nothing to distribute
            if (free < tabCount) return;
            int add = free /tabCount;
            int offset = 0;
            for (int i = 0; i < tabCount; i++) {
                r = rects[i]; 
                r.x += offset;
                r.width += add;
                offset += add;
            }

        }

    }
}

The second is highly simplified (biased me, as the maintainer of the project :-) by the plaf enhancement mechanism provided by SwingX (actually all you need is its plaf module and dependencies). Its basic building block is a TabbedPaneAddon which loads the custom ui:

public class TabbedPaneAddon extends AbstractComponentAddon {

    /**
     * @param name
     */
    public TabbedPaneAddon() {
        super("TabbedPane");
    }

    @Override
    protected void addMetalDefaults(LookAndFeelAddons addon,
            DefaultsList defaults) {
        // remove old ui
        UIManager.getLookAndFeelDefaults().put("TabbedPaneUI", null);
        defaults.add("TabbedPaneUI",
                // here goes the full classname of your custom ui
                // this is an example only :-)
                "org.jdesktop.swingx.XMetalTabbedPaneUI");
    }

    // implement other addXXDefault as needed for 
    // supporting more LAFs
}

The make the replacement happen, you have to contribute the addon ("early") in your application:

LookAndFeelAddons.contribute(new TabbedPaneAddon()); 
kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • This answer looks like it could solve my question. I'll check on it as soon as i'm done with some more urgent functions in my program. Thank you for your time answering and as soon as i test it, i'll post my reply. I'd vote up, but i have no qualifications for it yet... – Thiago Pantaleão Jul 22 '13 at 12:32
  • hmm .. .always thought you could vote on answers to your _own_ question right from the start, do you see the up/down arrows? – kleopatra Jul 23 '13 at 10:26
  • yeah, tried that, a message pops up saying "Vote Up requires 15 reputation". – Thiago Pantaleão Jul 24 '13 at 11:53
2

Is there a Look & Feel that has this "tab fitting" capability?

I don't know of one, but you might post an illustration for others who may have seen something similar. As the appearance is controlled by the L&F's UI delegate, TabbedPaneUI, you need to either look for an existing implementation or subclass one of its descendants: BasicTabbedPaneUI or MetalTabbedPaneUI.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thank you for your reply. As kleopatra said, this is the start to find my answer, but there isn't an explicit method or change in variables that gives me this feature right away, i think i'll have to tweak the rectangles a little... Anyway, about not posting illustrations, my reputation is still low for that. I indeed wanted to post some, but i can't. – Thiago Pantaleão Jul 24 '13 at 11:56
  • @ThiagoPantaleão: You can edit your question to include an [sscce](http://sscce.org/) based on the example cited. – trashgod Jul 24 '13 at 16:19