Spicing up your JTabbedPane - part IV
This is the fourth part of the series that describes the additional capabilities that you can get on your tabbed panes once you start using the Substance look-and-feel.
- The first part described close buttons and animation on modified tabs
- The second part described vetoable close buttons and vertical tabs.
- The third part described single-click close of multiple tabs and ustom alignment of tab texts on left and right placement.
This entry describes new features available in the next version of Substance look-and-feel (code-named Firenze, currently available in core code freeze - release candidate planned April 30).
The first feature is hover preview popup of tabs and is borrowed from Opera 9.0 beta browser. Move the mouse over a tab, wait for 2 seconds (configurable) and you will be shown a small preview popup window with the contents of the tab:

Later part of this entry describes how to customize the popup delay, popup dimension, popup existence itself (disable this feature on app-specific basis for some tabs) and preview painting (to provide app-specific preview painting logic).
The second feature is tab overview dialog and borrows from ideas from both IE7 and various Firefox extensions. First, the overview of existing functionality in the above browsers:
- QuickTabs in IE7 (currently in Beta2). When more there are at least two open tabs, a button is displayed in the left portion of the tab strip. When you click on it, the contents of the current tab are overlayed with a tab overview, showing a thumbnail for each open tab.
- Tab Sidebar Firefox extension. Opens a side bar (much like Office Taskbar) with single column thumbnail view of all open tabs.
- Reveal Firefox extension. When F2 or Alt-` is clicked, a horizontally scrollable two-row preview is shown. This preview allows tab rearranging as well as many other operations.
- foxPose Firefox extension. Adds a button in the bottom left corner of the window. When the button is clicked, a new tab with thumbnails is added to the browser.
- Tab Catalog Firefox extension. Adds a button in the right portion of the menu bar. When mouse hovers over this button, an overview window is shown.
- Ctrl Tab Firefox extension. When Ctrl-Tab is pressed, a three-window view allows switching between open tabs (like Alt-Tab in Windows Vista).
The current drop of Substance 2.3 allows adding the overview functionality to your tabbed panes. When enabled, the overview button is shown alongside your tabs (depending on the tab placement and orientation):

When this button is clicked, an overview dialog is shown. This dialog contains thumbnails for all tabs. Clicking on a thumbnail close the overview dialog and selects the corresponding tab:

The overview thumbnails are generated in a separate thread and faded-in as soon as they are available. This keeps your application responsive and user experience pleasant (hopefully). Below I describe how to customize the dialog dimension and location, overview existence itself (disable this feature on app-specific basis for some tabbed panes) and preview painting (to provide app-specific preview painting logic).
In order to enable the above functionality, all you need to do is to put the following client property on your tabbed pane(s) or globally on the UIManager:
<font color="#ffffff"> </font><font color="#000000">jtp.putClientProperty</font><font color="#000000">(</font><font color="#000000">SubstanceLookAndFeel.TABBED_PANE_PREVIEW_PAINTER,</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>new </b></font><font color="#000000">DefaultTabPreviewPainter</font><font color="#000000">())</font><font color="#000000">;</font>
The DefaultTabPreviewPainter is the default implementation of the tab preview and overview logic. Depending on your need, you can easily provide you own specific logic for all or some of the functionality. Here is a list of all customizable features:
<font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Base class for tab preview painters.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@author </font><font color="#3f5fbf">Kirill Grouchnikov</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#7f0055"><b>public abstract class </b></font><font color="#000000">TabPreviewPainter </font><font color="#000000">{</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Draws a tab preview on the specified graphics.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabPane</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabIndex</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* tabIndex Tab index for the preview paint.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">g</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Graphics context.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">x</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* X coordinate of the preview area.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">y</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Y coordinate of the preview area.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">w</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Width of the preview area.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">h</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Height of the preview area.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>void </b></font><font color="#000000">previewTab</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane, </font><font color="#7f0055"><b>int </b></font><font color="#000000">tabIndex, Graphics g,</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">x, </font><font color="#7f0055"><b>int </b></font><font color="#000000">y, </font><font color="#7f0055"><b>int </b></font><font color="#000000">w, </font><font color="#7f0055"><b>int </b></font><font color="#000000">h</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Checks whether the specified tab component is previewable.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabPane</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabIndex</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tab index for the preview paint.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@return </font><font color="#7f7f9f"><code></font><font color="#3f5fbf">true</font><font color="#7f7f9f"></code> </font><font color="#3f5fbf">if the specified tab component is</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* previewable, </font><font color="#7f7f9f"><code></font><font color="#3f5fbf">false</font><font color="#7f7f9f"></code> </font><font color="#3f5fbf">otherwise.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>boolean </b></font><font color="#000000">hasPreview</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane, </font><font color="#7f0055"><b>int </b></font><font color="#000000">tabIndex</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return false</b></font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Returns the screen bounds of the tab preview dialog window.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabPane</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@return </font><font color="#3f5fbf">Screen bounds of the preview dialog window of the specified</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#000000">Rectangle getPreviewDialogScreenBounds</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#000000">Rectangle tabPaneBounds = tabPane.getBounds</font><font color="#000000">()</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">Point tabPaneScreenLoc = tabPane.getLocationOnScreen</font><font color="#000000">()</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return new </b></font><font color="#000000">Rectangle</font><font color="#000000">(</font><font color="#000000">tabPaneScreenLoc.x, tabPaneScreenLoc.y,</font><br/>
<font color="#ffffff"> </font><font color="#000000">tabPaneBounds.width, tabPaneBounds.height</font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Returns the owner of the overview dialog of the specified tabbed pane. If</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* this function retuns a non-</font><font color="#7f7f9f"><code></font><font color="#3f5fbf">null</font><font color="#7f7f9f"></code> </font><font color="#3f5fbf">value, the overview</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* dialog will be modal for the corresponding frame.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabPane</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@return </font><font color="#3f5fbf">If not </font><font color="#7f7f9f"><code></font><font color="#3f5fbf">null</font><font color="#7f7f9f"></code></font><font color="#3f5fbf">, the overview dialog for the</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* specified tabbed pane will be modal for the corresponding frame.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#000000">JFrame getModalOwner</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return null</b></font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Checks whether the specified tabbed pane has an overview dialog.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabPane</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@return </font><font color="#7f7f9f"><code></font><font color="#3f5fbf">true</font><font color="#7f7f9f"></code> </font><font color="#3f5fbf">if the specified tabbed pane has an overview</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* dialog, </font><font color="#7f7f9f"><code></font><font color="#3f5fbf">false</font><font color="#7f7f9f"></code> </font><font color="#3f5fbf">otherwise.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>boolean </b></font><font color="#000000">hasOverviewDialog</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return false</b></font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Checks whether the specified tabbed pane has a preview window for the</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* specified tab.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabPane</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabIndex</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tab index.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@return </font><font color="#7f7f9f"><code></font><font color="#3f5fbf">true</font><font color="#7f7f9f"></code> </font><font color="#3f5fbf">if the specified tabbed pane has a preview</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* window for the specified tab, </font><font color="#7f7f9f"><code></font><font color="#3f5fbf">false</font><font color="#7f7f9f"></code> </font><font color="#3f5fbf">otherwise.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>boolean </b></font><font color="#000000">hasPreviewWindow</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane, </font><font color="#7f0055"><b>int </b></font><font color="#000000">tabIndex</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return false</b></font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Returns the dimension for the tab preview window.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabPane</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabIndex</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tab index.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@return </font><font color="#3f5fbf">Dimension of the tab preview window for the specified tab in the</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* specified tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#000000">Dimension getPreviewWindowDimension</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane, </font><font color="#7f0055"><b>int </b></font><font color="#000000">tabIndex</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return new </b></font><font color="#000000">Dimension</font><font color="#000000">(</font><font color="#990000">300</font><font color="#000000">, </font><font color="#990000">200</font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Returns extra delay (in milliseconds) for showing the tab preview window.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* The base delay is 2000 milliseconds (2 seconds). This function must</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* return a non-negative value.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabPane</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tabbed pane.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@param </font><font color="#3f5fbf">tabIndex</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Tab index.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@return </font><font color="#3f5fbf">Non-negative extra delay (in milliseconds) for showing the tab</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* preview window.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>int </b></font><font color="#000000">getPreviewWindowExtraDelay</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane, </font><font color="#7f0055"><b>int </b></font><font color="#000000">tabIndex</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return </b></font><font color="#990000">0</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#000000">}</font>
The default logic provides implementations of the following four functions (note the implementation of previewTab that simply scales down the current state of the tab - thanks to Romain for contributing the efficient thumbnail computation code):
<font color="#3f5fbf">/**</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* Default implementation of the tab preview painter. The tab preview is a</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* scaled-down (as necessary) thumbnail of the relevant tab.</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@author </font><font color="#3f5fbf">Kirill Grouchnikov</font><br/>
<font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br/>
<font color="#7f0055"><b>public class </b></font><font color="#000000">DefaultTabPreviewPainter </font><font color="#7f0055"><b>extends </b></font><font color="#000000">TabPreviewPainter </font><font color="#000000">{</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">/*</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* (non-Javadoc)</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* </font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* @see org.jvnet.substance.tabbed.TabPreviewPainter#hasPreview(javax.swing.JTabbedPane,</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* int)</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">*/</font><br/>
<font color="#ffffff"> </font><font color="#000000">@Override</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>boolean </b></font><font color="#000000">hasPreview</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane, </font><font color="#7f0055"><b>int </b></font><font color="#000000">tabIndex</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return </b></font><font color="#000000">(</font><font color="#000000">tabPane.getComponentAt</font><font color="#000000">(</font><font color="#000000">tabIndex</font><font color="#000000">) </font><font color="#000000">!= </font><font color="#7f0055"><b>null</b></font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">/*</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* (non-Javadoc)</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* </font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* @see org.jvnet.substance.tabbed.TabPreviewPainter#previewTab(javax.swing.JTabbedPane,</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* int, java.awt.Graphics, int, int, int, int)</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">*/</font><br/>
<font color="#ffffff"> </font><font color="#000000">@Override</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>void </b></font><font color="#000000">previewTab</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane, </font><font color="#7f0055"><b>int </b></font><font color="#000000">tabIndex, Graphics g,</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">x, </font><font color="#7f0055"><b>int </b></font><font color="#000000">y, </font><font color="#7f0055"><b>int </b></font><font color="#000000">w, </font><font color="#7f0055"><b>int </b></font><font color="#000000">h</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#000000">Component tabComponent = tabPane.getComponentAt</font><font color="#000000">(</font><font color="#000000">tabIndex</font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">tabComponent == </font><font color="#7f0055"><b>null</b></font><font color="#000000">)</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return</b></font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">// if (!tabComponent.isShowing())</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">// return;</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">compWidth = tabComponent.getWidth</font><font color="#000000">()</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">compHeight = tabComponent.getHeight</font><font color="#000000">()</font><font color="#000000">;</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">((</font><font color="#000000">compWidth > </font><font color="#990000">0</font><font color="#000000">) </font><font color="#000000">&& </font><font color="#000000">(</font><font color="#000000">compHeight > </font><font color="#990000">0</font><font color="#000000">)) {</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">// draw tab component</font><br/>
<font color="#ffffff"> </font><font color="#000000">BufferedImage tempCanvas = </font><font color="#7f0055"><b>new </b></font><font color="#000000">BufferedImage</font><font color="#000000">(</font><font color="#000000">compWidth, compHeight,</font><br/>
<font color="#ffffff"> </font><font color="#000000">BufferedImage.TYPE_INT_ARGB</font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">Graphics tempCanvasGraphics = tempCanvas.getGraphics</font><font color="#000000">()</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">tabComponent.paint</font><font color="#000000">(</font><font color="#000000">tempCanvasGraphics</font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">// check if need to scale down</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>double </b></font><font color="#000000">coef = Math.min</font><font color="#000000">((</font><font color="#7f0055"><b>double</b></font><font color="#000000">) </font><font color="#000000">w / </font><font color="#000000">(</font><font color="#7f0055"><b>double</b></font><font color="#000000">) </font><font color="#000000">compWidth, </font><font color="#000000">(</font><font color="#7f0055"><b>double</b></font><font color="#000000">) </font><font color="#000000">h</font><br/>
<font color="#ffffff"> </font><font color="#000000">/ </font><font color="#000000">(</font><font color="#7f0055"><b>double</b></font><font color="#000000">) </font><font color="#000000">compHeight</font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">coef < </font><font color="#990000">1.0</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">sdWidth = </font><font color="#000000">(</font><font color="#7f0055"><b>int</b></font><font color="#000000">) (</font><font color="#000000">coef * compWidth</font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">sdHeight = </font><font color="#000000">(</font><font color="#7f0055"><b>int</b></font><font color="#000000">) (</font><font color="#000000">coef * compHeight</font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">dx = </font><font color="#000000">(</font><font color="#000000">w - sdWidth</font><font color="#000000">) </font><font color="#000000">/ </font><font color="#990000">2</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">dy = </font><font color="#000000">(</font><font color="#000000">h - sdHeight</font><font color="#000000">) </font><font color="#000000">/ </font><font color="#990000">2</font><font color="#000000">;</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#000000">g.drawImage</font><font color="#000000">(</font><font color="#000000">SubstanceCoreUtilities.createThumbnail</font><font color="#000000">(</font><font color="#000000">tempCanvas,</font><br/>
<font color="#ffffff"> </font><font color="#000000">sdWidth</font><font color="#000000">)</font><font color="#000000">, dx, dy, </font><font color="#7f0055"><b>null</b></font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#000000">} </font><font color="#7f0055"><b>else </b></font><font color="#000000">{</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">// System.out.println("Putting " + frame.hashCode() + "</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">// -> " + snapshot.hashCode());</font><br/>
<font color="#ffffff"> </font><font color="#000000">g.drawImage</font><font color="#000000">(</font><font color="#000000">tempCanvas, </font><font color="#990000">0</font><font color="#000000">, </font><font color="#990000">0</font><font color="#000000">, </font><font color="#7f0055"><b>null</b></font><font color="#000000">)</font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">/*</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* (non-Javadoc)</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* </font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* @see org.jvnet.substance.tabbed.TabPreviewPainter#hasPreviewWindow(javax.swing.JTabbedPane,</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* int)</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">*/</font><br/>
<font color="#ffffff"> </font><font color="#000000">@Override</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>boolean </b></font><font color="#000000">hasPreviewWindow</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane, </font><font color="#7f0055"><b>int </b></font><font color="#000000">tabIndex</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return true</b></font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#ffffff"></font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">/*</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* (non-Javadoc)</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* </font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">* @see org.jvnet.substance.tabbed.TabPreviewPainter#hasOverviewDialog(javax.swing.JTabbedPane)</font><br/>
<font color="#ffffff"> </font><font color="#3f7f5f">*/</font><br/>
<font color="#ffffff"> </font><font color="#000000">@Override</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>boolean </b></font><font color="#000000">hasOverviewDialog</font><font color="#000000">(</font><font color="#000000">JTabbedPane tabPane</font><font color="#000000">) {</font><br/>
<font color="#ffffff"> </font><font color="#7f0055"><b>return true</b></font><font color="#000000">;</font><br/>
<font color="#ffffff"> </font><font color="#000000">}</font><br/>
<font color="#000000">}</font>The features describe above were the last to be added before the core feature freeze for the next version of Substance LAF (RC on April 30, release on May 14). You are welcome to download the jars and play with the test application or run the WebStart demo application. Note that the first time you run the tab overview dialog it will be a bit slow due to the multi-colored buttons in the second tab. After that, the subsequent operations will be much faster (due to image caching in Substance).
In addition, i would like to thank the community for using and testing Substance, reporting the bugs, suggesting new features and providing bug fixes and helping in internationaliztion efforts.
- Login or register to post comments
- Printer-friendly version
- kirillcool's blog
- 2733 reads





