JDK-4708614 : JTabbedPane should allow arbitrary component as tab
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.0
  • Priority: P5
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2002-06-26
  • Updated: 2005-08-17
  • Resolved: 2005-08-17
Related Reports
Duplicate :  
Description
Name: jk109818			Date: 06/26/2002


FULL PRODUCT VERSION :
java version "1.4.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)

A DESCRIPTION OF THE PROBLEM :
Presently the display of Tabs in a JTabbedPane is entirely
handled by the TabbedPaneUI for the current look-and-feel;
this means that certain behaviours are impossible which can
be done in other environments. For example, a context-
sensitive popup menu cannot be added to the tab; A close
button cannot be added to a Tab; a Tab cannot be given a
DragGestureRecognizer and rearranged or dragged into
another JTabbedPane (a la Adobe Photoshop and other
applications with a 'Palette' UI concept.) (This particular
behaviour would also require that the TabArea of a
JTabbedPane be given a DropTarget, but this could also be
accomplished.)
Current UI for the tabs could be reproduced by painting a
border around a JLabel; as a result, I suggest the addition
of the following methods.

  To JTabbedPane:
protected JComponent createTabComponent(String title, Icon
icon, Icon disabledIcon, Component component, String tip);
protected Component getTabArea();

  To TabbedPaneUI:
public LayoutManager prepareTabAreaComponent(JTabbedPane
pane);
public JComponent prepareTabComponent(JTabbedPane pane,
JComponent tabComponent);

createTabComponent would create a JLabel, or some L&F-
specific component (returned by a method on TabbedPaneUI)
satisfying the parameters; it could be overridden to create
instances of another class, or, for example, to create a
DragGestureRecognizer for the default component.

getTabArea would return the component in which the tabs
would be displayed. (This allows the DropTarget to be
created, as well as any other desired behaviour.)

createTabAreaLayoutManager would create a L&F-specific
LayoutManager to layout the tab components in the tab area
component. (This means that for Metal, the components don't
move no matter who is selected, while for Windows and
Motif, the rotate behaviour can still be used.)
This could even assign the LayoutManager to the TabArea
(because of the getter method), but it's probably best left
to the JTabbedPane for clarity.

prepareTabComponent would apply any L&F-specific properties
to the newly created component (ie. adding an appropriate
border, or adding a MouseListener to set selected and
unselected colors when a tab is clicked.) This might
involve placing the given component on another component,
which would be returned, so that opaque custom tab
components would not be surprised to find their colors
altered.

Changes to other behaviours would be:
- Instantiate the TabArea component during initialization
- set the TabArea's LayoutManager during UpdateUI
- call createTabComponent, then prepareTabComponent during
addTab/insertTab/etc. before adding that result to the
TabArea component.

This suggestion does have the downside of creating an
additional component(or 2) per tab, instead of using a
rubber stamp component to draw the tab titles; this
increases memory usage and slows things down, which were
already problems in Swing in general.

REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER WORKAROUND :
Some behaviours can be generated through other means. For
example, for a close button on a tab, an implementation of
Icon, say CompositeIcon, can be made which draws two icons
side by side; in a subclass of JTabbedPane, when a tab is
added with a non-null Icon, it can be substituted in the
super call with a CompositeIcon placing a Close icon on the
left, and the given icon on the right. (When no icon is
given, the Close icon can be used on its own.) Then, a
MouseListener can be added to the JTabbedPane using the
TabbedPaneUI moethods to determine when a click occured
inside the Close icon of any particular tab; when this
occurs, appropriate action can be taken. Per-tab Popup
menus can be accomplished similarly; Tabs which can be
dragged away cannot be implemented at all using
JTabbedPane. A JComponent which implements these behaviours
in this manner could be implemented, but it would have to
duplicate functionality already present in JTabbedPane in
order to do so.
(Review ID: 158501) 
======================================================================