Farewell to Space Consuming Weird Tabs
By Geertjan-Oracle on Jun 07, 2006
Another problem is that you can right-click on those tabs (even when you've removed the "x", via a setting in the etc/foo.conf file) and click "Close", thus closing the tab, even when you wouldn't want the user to be able to do so.
Well, Dave and others, take a look at this:
Now there's no tab, right? Compare it to the one in NetBeans Platform: Also For Small Applications?, and you'll see the difference.
To paraphrase Tim Boudreau in a recent thread on dev@openide.netbeans.org, Swing controls have a notion of a "UI delegate" in other words, a Swing component isn't responsible for painting itself. Instead, there is an object that a Swing component asks "please paint me" when it wants to be painted. Same for mouse and keyboard handling. Change the UI delegate and you get a different look or behavior. So this is what makes pluggable look and feels possible. The tab control in NetBeans uses the exact same mechanisms for its appearance and behavior. So, if you replace the UI delegate (via Class TabDisplayerUI), you can have different appearance and behavior, including having no tabs at all.
The steps to take in making it happen are as follows:
- Use the Module Installer wizard to create... a module installer. You don't only get a class that extends ModuleInstall, but an entry is added to the Manifest file and a dependency is declared in the project.xml file. A module installer is a Java class that provides hooks for running code on startup or when a module is loaded. It can also run cleanup code when a module is uninstalled or disabled. As a free gift, NetBeans gives you a skeleton restored() method. Fill it out as follows:
public void restored() { UIManager.put("EditorTabDisplayerUI", "org.yourorghere.NoTabsTabDisplayerUI"); }
What is very important is that you set the appropriate values here (duh). Firstly, "EditorTabDisplayerUI" implies that the TopComponents that you're interested in will be positioned in the "editor" position (in the IDE or in your own application), which is something you can change manually (very quickly and easily) in the layer.xml file. If you wanted to remove the tabs from positions such as output, explorer, and properties, you would use ViewTabDisplayerUI instead. There are also other values you could put there, but the only one I'm interested in is the one that affects the editor position. It is pretty cool that not ALL the tabs will be removed, because I think there are many scenarios where one would ONLY want the editor position to be affected, as suggested by Ramón Ramos here.
Secondly, the org.yourorghere.NoTabsTabDisplayerUI should point to the class that contains the information for overriding your tabs. Step 3 below describes this class.
- Set up your module to depend on Tab Control, Utilities API, Module System API, and Look & Feel Customization Library.
- Create a Java class called NoTabsTabDisplayerUI.java, which will replace the standard UI delegate for editor tabs with one that is 0 size and does nothing:
public class NoTabsTabDisplayerUI extends TabDisplayerUI { /\*\* Creates a new instance of NoTabsTabDisplayerUI \*/ public NoTabsTabDisplayerUI(TabDisplayer displayer) { super(displayer); } public static ComponentUI createUI(JComponent jc) { assert jc instanceof TabDisplayer; return new NoTabsTabDisplayerUI((TabDisplayer) jc); } private static final int[] PTS = new int[] { 0, 0, 0 }; public Polygon getExactTabIndication(int i) { //Should never be called return new Polygon(PTS, PTS, PTS.length); } public Polygon getInsertTabIndication(int i) { return new Polygon(PTS, PTS, PTS.length); } public int tabForCoordinate(Point point) { return -1; } public Rectangle getTabRect(int i, Rectangle rectangle) { return new Rectangle(0,0,0,0); } protected SingleSelectionModel createSelectionModel() { return new DefaultSingleSelectionModel(); } public java.lang.String getCommandAtPoint(Point point) { return null; } public int dropIndexOfPoint(Point point) { return -1; } public void registerShortcuts(javax.swing.JComponent jComponent) { //do nothing } public void unregisterShortcuts(javax.swing.JComponent jComponent) { //do nothing } protected void requestAttention(int i) { //do nothing } protected void cancelRequestAttention(int i) { //do nothing } public Dimension getPreferredSize(javax.swing.JComponent c) { return new Dimension(0, 0); } public Dimension getMinimumSize(javax.swing.JComponent c) { return new Dimension(0, 0); } public Dimension getMaximumSize(javax.swing.JComponent c) { return new Dimension(0, 0); } }
This may seem like a bit of work and in some ways it is. It would be nice if I could set some sort of property that excludes tabs from TopComponents in one or more positions. However, until such a property (or a simpler approach) is available, it is at least possible to remove those tabs when they're not needed.
Posted by Dave on June 08, 2006 at 12:35 AM PDT #
Good luck with your meetings and, should you have any other questions or whatever, just drop a line.
Posted by Geertjan on June 08, 2006 at 01:11 AM PDT #
Posted by Rich Unger on June 09, 2006 at 02:09 AM PDT #
if (loud.Scream.Of.Annoyance == true {
UIManager.put("EditorTabDisplayerUI", "org.yourorghere.NoTabsTabDisplayerUI");
}
Posted by Geertjan on June 09, 2006 at 02:16 AM PDT #
Posted by Cynic on June 30, 2006 at 04:06 AM PDT #
Posted by Tim Boudreau on July 04, 2006 at 03:36 AM PDT #
Posted by Hervé on July 17, 2006 at 03:47 AM PDT #
Posted by Roxie on August 04, 2006 at 09:54 AM PDT #
There is still the status bar in the bottom of the window to be removed, in order to have the same UI.
Posted by Vincent on October 01, 2007 at 01:47 PM PDT #
... and an horizontal scroll bar as well.
Posted by Vincent on October 01, 2007 at 01:48 PM PDT #
I can't find the key to get rid of the "top separator". Does anybody know which one it is?
Posted by Javier Molina on October 30, 2007 at 09:04 PM PDT #
Rather than removing tabs, I'd like to use this method for changing the font size that appears on the tabs.
I've had a look at the documenation and I think I can use the getTxtFont() method in TabDisplayerUI.
I'm new to Java though and would like to know what the original TabDisplayerUI looked like before the changes were made to remove the tabs.
I can then add a getTxtFont() to this and hopefully solve my problems.
Do you know where I can find this?
Thanks
Posted by Alastair Badman on January 21, 2009 at 02:40 AM PST #
Try adding:
UIManager.put(DefaultTabbedContainerUI.KEY_EDITOR_CONTENT_BORDER,BorderFactory.createEmptyBorder());
to remove the 3 sided border.
Posted by Michael b on April 27, 2009 at 09:59 AM PDT #
Here my solution to remove TabDisplayer or just the navigation buttons on a per-TopComponent basis:
public static void hideTabDisplayer(final TopComponent topComponent) {
WindowManager.getDefault().invokeWhenUIReady(
new Runnable() {
@Override
public void run() {
try {
Container tabbedContainer = UIUtilities.findAncestorByClassName(topComponent, TabbedContainer.class.getName());
Component tabDisplayer = UIUtilities.findComponentByClassName(tabbedContainer, TabDisplayer.class.getName());
tabDisplayer.setVisible(false);
} catch (Exception ex) {
}
}
});
}
public static void hideTabNavigationButtons(final TopComponent topComponent) {
WindowManager.getDefault().invokeWhenUIReady(
new Runnable() {
@Override
public void run() {
try {
Container tabbedContainer = UIUtilities.findAncestorByClassName(topComponent, TabbedContainer.class.getName());
Component dropDownButton = UIUtilities.findComponentByClassName(tabbedContainer, TabControlButtonFactory.class.getName() + "$DropDownButton");
dropDownButton.getParent().setVisible(false);
} catch (Exception ex) {
}
}
});
}
Last, if tab must be preserved but the popup menu removed, just override TopComponent.getActions() to return null.
Posted by guest on July 21, 2011 at 06:52 PM PDT #
Sorry for digging up this older post, but it kind of helped and kind of totally messed things up... :D
It definitely hides the tab-bar.
Now let me explain my problem: my program has a wizard/dialog-structure, which means, you see one window, click a few things, click on "next" and a totally different window pops up.
The designer didn't allow to take the builtin Netbeans-RCP-Wizard-feature, so I did it this way: every time I click on next, the current TopComponent gets .close() and another one is .open[ed](). This solution works perfectly fine - until I want to hide my tabs.
Now do you know, if that code has stolen some functionality in opening new TopComponents in the Editor?
For me the following happens: the last seen TopComp loads fine but if I hit "next" or "back", instead of the next or previous TopComp I get an empty one and no Java-Exception.
Posted by guest on October 27, 2011 at 02:11 PM PDT #
I noticed that the deploy of a netbeans platform application is very 'expensive' in terms of disk space and in packaging.
I tried deploy my simple application wich contains a simple topcomponent, no extra modules (just a few dependencies with jfreechart adn javolution), no lookapi api, no need of extra tabs or special features of the ui. Just one window with a jfreechart and some bujttons/textboex/comboboxes. When I deploy the aspplication via Package as ->ZIP distribution, and then I unpack the zip file on the production machine, the content of the folder is more then 30MB!!! In particular the 'platform' subdirectory is 29MB!!! Is there a way to compact the packaging? I am sure I'm using a lot of stuff no need in my case.
Then, there is also another stuff to say. My application is just one small piece of all the system I need to provide. Mine is a complete suite of programs, some in C/C++, some in Java command line, some other in java desktop application (like this one) etc. I have my main directory with my structure. I jave a structure like this:
<installdir>
- bin
- etc
- log
- <some other>
- <some other other>
I have all my executables in the bin directory. I have both C/C++ programs and Java program. For example there is a command line program in java called jobmgr.jar in the bin directory. I simply run it using 'java -jar <installdir>/bin/jobmgr.jar -config <installdir>/etc/jobmgr.config' and it works perfectly well. The 'bin' directory has a 'lib' subdirectory which contains all the dependencies of the jobmgr.jar program. I have some other tasks written in java, put in the 'bin' directory. I use the same 'lib' subdirectory to contains dependencies of all the java programs so that they can share everything. The deploy of a netbenas platform application acts like if it was the one and only program and creates a directory structure that can't be used in the scenario I described above. How can I fit the deploy of a netbeans platform appllication in such a scenario? Please help.
Posted by Magallo on March 05, 2013 at 02:04 AM PST #
Not sure how any of this relates to this blog entry. Why not write to the dev@platform.netbeans.org mailing list with these questions? You'll start a discussion with many people, instead of just with me.
Posted by Geertjan on March 05, 2013 at 02:20 AM PST #
PS: Here's the most minimal NetBeans Platform application, but you know this tutorial since you must have worked through the NetBeans Platform Learning Trail already:
Posted by Geertjan on March 05, 2013 at 02:22 AM PST #
PS: If you're not on the mailing list yet, here's how to join it, otherwise you can't send mails there:
Posted by Geertjan on March 05, 2013 at 02:51 AM PST #
Ok, sorry for the off topic. Anyway I think this is a topic that should be faced because it frighten a lot of people I guess.
Posted by Magallo on March 05, 2013 at 03:13 AM PST #
No, it doesn't frighten anyone (see hundreds of applications here:), because what you're saying isn't true. That's what I'm trying to tell you. Did you follow the tutorial above? It shows you a minimal NetBeans Platform application. Also, most applications on the NetBeans Platform are large anyway, that's the purpose of the NetBeans Platform: to offer a framework for large applications. Some small ones too, but typically large ones. But why don't we have this discussion on the mailing list instead of here?
Posted by Geertjan on March 05, 2013 at 03:21 AM PST #
Does this still work for Netbeans 7.2 and Java 1.7? I have been trying this with my application and it does not work.
Posted by guest on June 27, 2013 at 12:15 PM PDT #
Put the code in the 'restored()' method into a SwingUtilities.invokeLater.
Posted by Geertjan on June 27, 2013 at 03:59 PM PDT #
I modified the contents of the restored() function to look like this:
public void restored() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
UIManager.put("EditorTabDisplayerUI", "org.foo.NoTabsTabDisplayerUI");
}
});
}
Is that right? I'm still getting tabs...
Posted by guest on June 28, 2013 at 05:28 AM PDT #
Oops, looks like I spoke too soon. It was an interaction with another module in the application that was preventing it from working. Thanks for your help!
Posted by guest on June 28, 2013 at 06:21 AM PDT #
it is not work for Netbeans 8 and Java 1.8 windows64. Please give me some advises.
Posted by guest on October 25, 2014 at 06:41 PM PDT #
Advice: read the book --
Posted by Geertjan on October 26, 2014 at 12:23 AM PDT #