001: /*
002: * Copyright (C) 2004 NNL Technology AB
003: * Visit www.infonode.net for information about InfoNode(R)
004: * products and how to contact NNL Technology AB.
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
019: * MA 02111-1307, USA.
020: */
021:
022: // $Id: LookAndFeelTheme.java,v 1.20 2005/12/04 13:46:05 jesper Exp $
023: package net.infonode.tabbedpanel.theme;
024:
025: import net.infonode.gui.DimensionProvider;
026: import net.infonode.gui.InsetsUtil;
027: import net.infonode.gui.componentpainter.ComponentPainter;
028: import net.infonode.gui.hover.HoverEvent;
029: import net.infonode.gui.hover.HoverListener;
030: import net.infonode.properties.propertymap.PropertyMapManager;
031: import net.infonode.tabbedpanel.*;
032: import net.infonode.tabbedpanel.theme.internal.laftheme.PaneUI;
033: import net.infonode.tabbedpanel.theme.internal.laftheme.PaneUIListener;
034: import net.infonode.tabbedpanel.titledtab.TitledTab;
035: import net.infonode.tabbedpanel.titledtab.TitledTabBorderSizePolicy;
036: import net.infonode.tabbedpanel.titledtab.TitledTabProperties;
037: import net.infonode.tabbedpanel.titledtab.TitledTabSizePolicy;
038: import net.infonode.util.Direction;
039:
040: import javax.swing.border.Border;
041: import java.awt.*;
042:
043: /**
044: * <p>
045: * An <strong>experimental</strong> theme that tries to replicate the look of
046: * the active look and feel. This may or may not work depending on the look and
047: * feel used.
048: * </p>
049: *
050: * <p>
051: * This is a theme that tries to replicate the JTabbedPane's look using the
052: * active look and feel. The theme uses a heavyweight AWT component internally
053: * so the {@link #dispose()} method must be called when the theme is no longer
054: * needed, otherwise the native resources will not be disposed.
055: * </p>
056: *
057: * <p>
058: * The theme uses the hover mechanism so that tab hover effects can be
059: * replicated.
060: * </p>
061: *
062: * <p>
063: * <strong>This theme is considered to be experimental and is not guaranteed to
064: * be an exact replica of the active look and feel. It is also not guaranteed to
065: * work together with the active look and feel. The theme may be changed,
066: * removed etc in future versions. No support is given for the theme. This theme
067: * doesn't work well with Aqua Look and Feel on Macintosh.</strong>
068: * </p>
069: *
070: * @author johan
071: * @version $Revision: 1.20 $
072: * @since ITP 1.4.0
073: */
074: public class LookAndFeelTheme extends TabbedPanelTitledTabTheme {
075: private static TabbedPanelProperties tpProps = new TabbedPanelProperties();
076:
077: private static TitledTabProperties tabProps = new TitledTabProperties();
078:
079: private TabbedPanelProperties themeTpProps = new TabbedPanelProperties();
080:
081: private TitledTabProperties themeTabProps = new TitledTabProperties();
082:
083: private static int themeCounter = 0;
084:
085: private static PaneUI ui;
086:
087: private boolean disposed = false;
088:
089: /**
090: * Constructs a Look and Feel Theme
091: */
092: public LookAndFeelTheme() {
093: if (themeCounter == 0) {
094: ui = new PaneUI(new PaneUIListener() {
095: public void updating() {
096: }
097:
098: public void updated() {
099: initTheme();
100: }
101:
102: });
103:
104: ui.init();
105: }
106:
107: themeCounter++;
108:
109: themeTpProps.addSuperObject(tpProps);
110: themeTabProps.addSuperObject(tabProps);
111: }
112:
113: /**
114: * Gets the name for this theme
115: *
116: * @return the name
117: */
118: public String getName() {
119: return "Look and Feel Theme";
120: }
121:
122: /**
123: * Gets the TabbedPanelProperties for this theme
124: *
125: * @return the TabbedPanelProperties
126: */
127: public TabbedPanelProperties getTabbedPanelProperties() {
128: return themeTpProps;
129: }
130:
131: /**
132: * Gets the TitledTabProperties for this theme
133: *
134: * @return the TitledTabProperties
135: */
136: public TitledTabProperties getTitledTabProperties() {
137: return themeTabProps;
138: }
139:
140: /**
141: * <p>
142: * Disposes this theme.
143: * </p>
144: *
145: * <p>
146: * This method must be called in order to dispose the heavyweight AWT
147: * component used internally.
148: * </p>
149: */
150: public void dispose() {
151: if (!disposed) {
152: disposed = true;
153:
154: themeCounter--;
155:
156: if (themeCounter == 0) {
157: ui.dispose();
158:
159: PropertyMapManager.runBatch(new Runnable() {
160: public void run() {
161: tpProps.getMap().clear(true);
162: tabProps.getMap().clear(true);
163: }
164: });
165: }
166: }
167: }
168:
169: private void initTheme() {
170: PropertyMapManager.runBatch(new Runnable() {
171: public void run() {
172: tpProps.getMap().clear(true);
173: tabProps.getMap().clear(true);
174:
175: {
176: tpProps.setShadowEnabled(false).setTabSpacing(
177: ui.getTabSpacing()).setTabScrollingOffset(
178: ui.getScrollOffset())
179: .setEnsureSelectedTabVisible(true);
180: tpProps.getTabAreaComponentsProperties()
181: .getComponentProperties().setBorder(null)
182: .setInsets(InsetsUtil.EMPTY_INSETS);
183:
184: tpProps.getTabAreaProperties()
185: .getComponentProperties().setInsets(
186: InsetsUtil.EMPTY_INSETS).setBorder(
187: new Border() {
188: public void paintBorder(
189: Component c,
190: Graphics g, int x,
191: int y, int width,
192: int height) {
193: }
194:
195: public Insets getBorderInsets(
196: Component c) {
197: TabbedPanel tp = TabbedUtils
198: .getParentTabbedPanel(c);
199: return tp
200: .isTabAreaVisible() ? ui
201: .getTabAreaInsets(tp
202: .getProperties()
203: .getTabAreaOrientation())
204: : InsetsUtil.EMPTY_INSETS;
205: }
206:
207: public boolean isBorderOpaque() {
208: return false;
209: }
210:
211: });
212:
213: tpProps.getTabAreaComponentsProperties()
214: .getShapedPanelProperties().setOpaque(
215: ui.isTabAreaComponentsOpaque());
216:
217: tpProps.getTabAreaProperties()
218: .getShapedPanelProperties().setOpaque(
219: ui.isTabAreaOpaque())
220: .setComponentPainter(
221: new ComponentPainter() {
222:
223: public void paint(
224: Component component,
225: Graphics g, int x,
226: int y, int width,
227: int height) {
228: }
229:
230: public void paint(
231: Component component,
232: Graphics g, int x,
233: int y, int width,
234: int height,
235: Direction direction,
236: boolean horizontalFlip,
237: boolean verticalFlip) {
238: ui
239: .paintTabArea(
240: TabbedUtils
241: .getParentTabbedPanel(component),
242: g, x, y,
243: width,
244: height);
245: }
246:
247: public boolean isOpaque(
248: Component component) {
249: return false;
250: }
251:
252: public Color getColor(
253: Component component) {
254: return null;
255: }
256: });
257:
258: tpProps.getContentPanelProperties()
259: .getShapedPanelProperties().setOpaque(
260: ui.isContentOpaque())
261: .setComponentPainter(
262: new ComponentPainter() {
263: public void paint(
264: Component component,
265: Graphics g, int x,
266: int y, int width,
267: int height) {
268: }
269:
270: public void paint(
271: Component component,
272: Graphics g, int x,
273: int y, int width,
274: int height,
275: Direction direction,
276: boolean horizontalFlip,
277: boolean verticalFlip) {
278: TabbedPanelContentPanel p = TabbedUtils
279: .getParentTabbedPanelContentPanel(component);
280: ui
281: .paintContentArea(
282: p, g, x, y,
283: width,
284: height);
285: }
286:
287: public boolean isOpaque(
288: Component component) {
289: return false;
290: }
291:
292: public Color getColor(
293: Component component) {
294: return null;
295: }
296: });
297:
298: tpProps.getContentPanelProperties()
299: .getComponentProperties().setInsets(
300: InsetsUtil.EMPTY_INSETS).setBorder(
301: new Border() {
302: public void paintBorder(
303: Component c,
304: Graphics g, int x,
305: int y, int width,
306: int height) {
307: }
308:
309: public Insets getBorderInsets(
310: Component c) {
311: TabbedPanel tp = TabbedUtils
312: .getParentTabbedPanelContentPanel(
313: c)
314: .getTabbedPanel();
315: return ui
316: .getContentInsets(
317: tp
318: .getProperties()
319: .getTabAreaOrientation(),
320: tp
321: .isTabAreaVisible());
322: }
323:
324: public boolean isBorderOpaque() {
325: return false;
326: }
327: });
328: }
329:
330: {
331: tabProps
332: .setSizePolicy(
333: TitledTabSizePolicy.INDIVIDUAL_SIZE)
334: .setBorderSizePolicy(
335: TitledTabBorderSizePolicy.EQUAL_SIZE)
336: .setHighlightedRaised(
337: ui.getSelectedRaised(Direction.UP))
338: .setFocusMarkerEnabled(false);
339:
340: tabProps.getNormalProperties().setIconTextGap(
341: ui.getTextIconGap())
342: .setTextTitleComponentGap(
343: ui.getTextIconGap());
344:
345: tabProps.getNormalProperties()
346: .getComponentProperties().setInsets(
347: InsetsUtil.EMPTY_INSETS).setBorder(
348: createTabInsetsBorder(false))
349: .setFont(ui.getFont());
350: tabProps.getHighlightedProperties()
351: .getComponentProperties().setBorder(
352: createTabInsetsBorder(true));
353:
354: tabProps.getDisabledProperties()
355: .getComponentProperties().setBorder(
356: createTabInsetsBorder(false));
357:
358: tabProps.getNormalProperties()
359: .getShapedPanelProperties()
360: .setOpaque(false).setComponentPainter(null);
361:
362: tabProps
363: .setMinimumSizeProvider(new DimensionProvider() {
364: public Dimension getDimension(
365: Component c) {
366: return ui
367: .getTabExternalMinSize(TabbedUtils
368: .getParentTab(c)
369: .getTabbedPanel()
370: .getProperties()
371: .getTabAreaOrientation());
372: }
373: });
374:
375: tabProps.setHoverListener(new HoverListener() {
376: public void mouseEntered(HoverEvent event) {
377: ui.setHoveredTab((Tab) event.getSource());
378: }
379:
380: public void mouseExited(HoverEvent event) {
381: ui.setHoveredTab(null);
382: }
383: });
384: }
385: }
386: });
387: }
388:
389: private Border createTabInsetsBorder(final boolean selected) {
390: return new Border() {
391: public void paintBorder(Component c, Graphics g, int x,
392: int y, int width, int height) {
393: }
394:
395: public Insets getBorderInsets(Component c) {
396: TitledTab tab = (TitledTab) TabbedUtils.getParentTab(c);
397:
398: if (tab.getTabbedPanel() == null)
399: return new Insets(0, 0, 0, 0);
400:
401: Direction areaOrientation = tab.getTabbedPanel()
402: .getProperties().getTabAreaOrientation();
403: Direction tabDirection = selected ? tab.getProperties()
404: .getHighlightedProperties().getDirection()
405: : tab.getProperties().getNormalProperties()
406: .getDirection();
407:
408: return selected ? ui.getSelectedTabInsets(
409: areaOrientation, tabDirection) : ui
410: .getNormalTabInsets(areaOrientation,
411: tabDirection);
412: }
413:
414: public boolean isBorderOpaque() {
415: return false;
416: }
417: };
418: }
419:
420: public Color getBorderColor(Direction d) {
421: return ui.getContentTabAreaBorderColor(d);
422: }
423: }
|