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: InfoNodeLookAndFeel.java,v 1.22 2005/12/04 13:46:03 jesper Exp $
023: package net.infonode.gui.laf;
024:
025: import net.infonode.gui.icon.button.TreeIcon;
026: import net.infonode.gui.laf.ui.SlimComboBoxUI;
027: import net.infonode.gui.laf.ui.SlimInternalFrameUI;
028: import net.infonode.gui.laf.ui.SlimMenuItemUI;
029: import net.infonode.gui.laf.ui.SlimSplitPaneUI;
030: import net.infonode.util.ArrayUtil;
031: import net.infonode.util.ColorUtil;
032:
033: import javax.swing.*;
034: import javax.swing.border.Border;
035: import javax.swing.plaf.ColorUIResource;
036: import javax.swing.plaf.FontUIResource;
037: import javax.swing.plaf.IconUIResource;
038: import javax.swing.plaf.UIResource;
039: import javax.swing.plaf.metal.DefaultMetalTheme;
040: import javax.swing.plaf.metal.MetalBorders;
041: import javax.swing.plaf.metal.MetalLookAndFeel;
042: import javax.swing.plaf.metal.MetalTheme;
043: import java.awt.*;
044: import java.lang.reflect.InvocationTargetException;
045:
046: /**
047: * A Look and Feel that's based on Metal. It's slimmer and use other colors than the standard Metal Look and Feel.
048: * Under Java 1.5 the currect Metal theme is stored when the InfoNode Look and Feel is applied, and restored when
049: * another Look and Feel is set. Under Java 1.4 or earlier it is not possible to get the current theme and a
050: * DefaultMetalTheme is set instead.
051: * <p>
052: * To set the look and feel use:
053: * <pre>
054: * UIManager.setLookAndFeel(new InfoNodeLookAndFeel());
055: * </pre>
056: * Or, if you want to use a different theme, use:
057: * <pre>
058: * InfoNodeLookAndFeelTheme theme = new InfoNodeLookAndFeelTheme(...);
059: * // Modify the theme colors, fonts etc.
060: * UIManager.setLookAndFeel(new InfoNodeLookAndFeel(theme));
061: * </pre>
062: * Do not modify the theme after it has been used in the look and feel!
063: *
064: * @author $Author: jesper $
065: * @version $Revision: 1.22 $
066: */
067: public class InfoNodeLookAndFeel extends MetalLookAndFeel {
068: public static final UIManager.LookAndFeelInfo LOOK_AND_FEEL_INFO = new UIManager.LookAndFeelInfo(
069: "InfoNode", InfoNodeLookAndFeel.class.getName());
070:
071: private static MetalTheme oldMetalTheme;
072:
073: private transient InfoNodeLookAndFeelTheme theme;
074:
075: private transient DefaultMetalTheme defaultTheme = new DefaultMetalTheme() {
076: public ColorUIResource getPrimaryControlHighlight() {
077: return theme.getPrimaryControlHighlightColor();
078: }
079:
080: public ColorUIResource getMenuBackground() {
081: return theme.getControlColor();
082: }
083:
084: public ColorUIResource getControlHighlight() {
085: return theme.getControlHighlightColor();
086: }
087:
088: public ColorUIResource getControl() {
089: return theme.getControlColor();
090: }
091:
092: public ColorUIResource getControlShadow() {
093: return theme.getControlShadowColor();
094: }
095:
096: public ColorUIResource getControlDarkShadow() {
097: return theme.getControlDarkShadowColor();
098: }
099:
100: // Scrollbars, popups etc.
101: public ColorUIResource getPrimaryControl() {
102: return theme.getPrimaryControlColor();
103: }
104:
105: public ColorUIResource getPrimaryControlShadow() {
106: return theme.getPrimaryControlShadowColor();
107: }
108:
109: public ColorUIResource getPrimaryControlDarkShadow() {
110: return theme.getPrimaryControlDarkShadowColor();
111: }
112:
113: // End scrollbars
114:
115: public ColorUIResource getTextHighlightColor() {
116: return theme.getSelectedTextBackgroundColor();
117: }
118:
119: public ColorUIResource getMenuSelectedBackground() {
120: return theme.getSelectedMenuBackgroundColor();
121: }
122:
123: public ColorUIResource getWindowBackground() {
124: return theme.getBackgroundColor();
125: }
126:
127: protected ColorUIResource getWhite() {
128: return theme.getBackgroundColor();
129: }
130:
131: public ColorUIResource getDesktopColor() {
132: return theme.getDesktopColor();
133: }
134:
135: public ColorUIResource getHighlightedTextColor() {
136: return theme.getSelectedTextColor();
137: }
138:
139: protected ColorUIResource getBlack() {
140: return theme.getTextColor();
141: }
142:
143: public ColorUIResource getMenuForeground() {
144: return theme.getTextColor();
145: }
146:
147: public ColorUIResource getMenuSelectedForeground() {
148: return theme.getSelectedMenuForegroundColor();
149: }
150:
151: public ColorUIResource getFocusColor() {
152: return theme.getFocusColor();
153: }
154:
155: public ColorUIResource getControlDisabled() {
156: return theme.getControlColor();
157: }
158:
159: public ColorUIResource getSystemTextColor() {
160: return theme.getTextColor();
161: }
162:
163: public ColorUIResource getControlTextColor() {
164: return theme.getTextColor();
165: }
166:
167: public ColorUIResource getInactiveControlTextColor() {
168: return theme.getInactiveTextColor();
169: }
170:
171: public ColorUIResource getInactiveSystemTextColor() {
172: return theme.getInactiveTextColor();
173: }
174:
175: public ColorUIResource getUserTextColor() {
176: return theme.getTextColor();
177: }
178:
179: // --------------- Fonts --------------------------
180:
181: public FontUIResource getControlTextFont() {
182: return getSystemTextFont();
183: }
184:
185: public FontUIResource getSystemTextFont() {
186: return theme.getFont();
187: }
188:
189: public FontUIResource getUserTextFont() {
190: return getSystemTextFont();
191: }
192:
193: public FontUIResource getMenuTextFont() {
194: return getSystemTextFont();
195: }
196:
197: public FontUIResource getWindowTitleFont() {
198: return getSystemTextFont();
199: }
200:
201: public FontUIResource getSubTextFont() {
202: return getSystemTextFont();
203: }
204:
205: };
206:
207: /**
208: * Constructor.
209: */
210: public InfoNodeLookAndFeel() {
211: this (new InfoNodeLookAndFeelTheme());
212: }
213:
214: /**
215: * Constructor.
216: *
217: * @param theme the theme to use. Do not modify the theme after this constructor has been called!
218: */
219: public InfoNodeLookAndFeel(InfoNodeLookAndFeelTheme theme) {
220: this .theme = theme;
221: }
222:
223: /**
224: * Gets the active theme
225: *
226: * @return the active theme
227: */
228: public InfoNodeLookAndFeelTheme getTheme() {
229: return theme;
230: }
231:
232: public void initialize() {
233: super .initialize();
234:
235: if (oldMetalTheme == null) {
236: // Try to obtain the old Metal theme if possible
237: try {
238: oldMetalTheme = (MetalTheme) MetalLookAndFeel.class
239: .getMethod("getCurrentTheme", null).invoke(
240: null, null);
241: } catch (NoSuchMethodException e) {
242: // Ignore
243: } catch (IllegalAccessException e) {
244: // Ignore
245: } catch (InvocationTargetException e) {
246: // Ignore
247: }
248: }
249:
250: setCurrentTheme(defaultTheme);
251: }
252:
253: public void uninitialize() {
254: setCurrentTheme(oldMetalTheme == null ? new DefaultMetalTheme()
255: : oldMetalTheme);
256: oldMetalTheme = null;
257: }
258:
259: public String getName() {
260: return LOOK_AND_FEEL_INFO.getName();
261: }
262:
263: public String getDescription() {
264: return "A slim look and feel based on Metal.";
265: }
266:
267: protected void initClassDefaults(UIDefaults table) {
268: super .initClassDefaults(table);
269:
270: try {
271: {
272: Class cl = SlimSplitPaneUI.class;
273: table.put("SplitPaneUI", cl.getName());
274: table.put(cl.getName(), cl);
275: }
276:
277: {
278: Class cl = SlimInternalFrameUI.class;
279: table.put("InternalFrameUI", cl.getName());
280: table.put(cl.getName(), cl);
281: }
282:
283: {
284: Class cl = SlimComboBoxUI.class;
285: SlimComboBoxUI.NORMAL_BORDER = theme
286: .getListItemBorder();
287: SlimComboBoxUI.FOCUS_BORDER = theme
288: .getListFocusedItemBorder();
289: table.put("ComboBoxUI", cl.getName());
290: table.put(cl.getName(), cl);
291: }
292:
293: {
294: Class cl = SlimMenuItemUI.class;
295: table.put("MenuItemUI", cl.getName());
296: table.put(cl.getName(), cl);
297: }
298: } catch (Exception ex) {
299: throw new RuntimeException(ex);
300: }
301: }
302:
303: private static class MyListCellRenderer extends
304: DefaultListCellRenderer {
305: private Border normalBorder;
306: private Border focusBorder;
307:
308: MyListCellRenderer(Border normalBorder, Border focusBorder) {
309: this .normalBorder = normalBorder;
310: this .focusBorder = focusBorder;
311: }
312:
313: public Component getListCellRendererComponent(JList list,
314: Object value, int index, boolean isSelected,
315: boolean cellHasFocus) {
316: JLabel label = (JLabel) super .getListCellRendererComponent(
317: list, value, index, isSelected, cellHasFocus);
318: label.setBorder(cellHasFocus ? focusBorder : normalBorder);
319: return label;
320: }
321:
322: public static class UIResource extends MyListCellRenderer
323: implements javax.swing.plaf.UIResource {
324: public UIResource(Border normalBorder, Border focusBorder) {
325: super (normalBorder, focusBorder);
326: }
327: }
328: }
329:
330: protected void initComponentDefaults(UIDefaults table) {
331: super .initComponentDefaults(table);
332:
333: Class iconClass = MetalLookAndFeel.class;
334: UIResource menuItemBorder = new MetalBorders.MenuItemBorder() {
335: public Insets getBorderInsets(Component c) {
336: return new Insets(2, 0, 2, 0);
337: }
338: };
339:
340: Object[] defaults = {
341: "SplitPane.dividerSize",
342: new Integer(theme.getSplitPaneDividerSize()),
343: // "SplitPaneDivider.border", new BorderUIResource(splitPaneDividerBorder),
344: // "SplitPane.border", new BorderUIResource(splitPaneBorder),
345:
346: // "TabbedPane.contentBorderInsets", tabbedPaneContentInsets,
347: // "TabbedPane.tabAreaInsets", new InsetsUIResource(0, 0, 0, 0),
348: // "TabbedPane.selectedTabPadInsets", new InsetsUIResource(0, 0, 0, 0),
349: // "TabbedPane.tabInsets", new InsetsUIResource(0, 0, 0, 0),
350: "TabbedPane.background",
351: theme.getControlLightShadowColor(),
352: //"TabbedPane.darkShadow", new Color(160, 160, 160),
353:
354: "ComboBox.selectionBackground",
355: theme.getSelectedMenuBackgroundColor(),
356: "ComboBox.selectionForeground",
357: theme.getSelectedMenuForegroundColor(),
358:
359: "List.cellRenderer",
360: new UIDefaults.ActiveValue() {
361: public Object createValue(UIDefaults table) {
362: return new MyListCellRenderer.UIResource(theme
363: .getListItemBorder(), theme
364: .getListFocusedItemBorder());
365: }
366: },
367:
368: "ToolTip.foreground",
369: theme.getTooltipForegroundColor(),
370: "ToolTip.background",
371: theme.getTooltipBackgroundColor(),
372:
373: "Viewport.background",
374: theme.getBackgroundColor(),
375:
376: "ScrollBar.background",
377: theme.getScrollBarBackgroundColor(),
378: "ScrollBar.shadow",
379: theme.getScrollBarBackgroundShadowColor(),
380: "ScrollBar.width",
381: new Integer(theme.getScrollBarWidth()),
382: // "ScrollBar.border", new BorderUIResource(new LineBorder(Color.GRAY, 1)),
383:
384: // "ScrollBar.thumb", new RelativeColor(thumbColor, 0.8).getColor(),
385: // "ScrollBar.thumbShadow", new RelativeColor(thumbColor, 0.7).getColor(),
386: // "ScrollBar.thumbHighlight", new RelativeColor(thumbColor, 1).getColor(),
387:
388: /* "ScrollBar.thumb", new ColorUIResource(255, 255, 255),
389: "ScrollBar.thumbShadow", new ColorUIResource(0, 255, 0),
390: "ScrollBar.thumbHighlight", new ColorUIResource(255, 255, 255),
391: */
392:
393: "Table.focusCellBackground",
394: new ColorUIResource(ColorUtil.mult(theme
395: .getSelectedMenuBackgroundColor(), 1.40f)),
396: "Table.focusCellForeground",
397: theme.getSelectedMenuForegroundColor(),
398:
399: "TableHeader.cellBorder",
400: theme.getTableHeaderCellBorder(),
401:
402: "InternalFrame.activeTitleBackground",
403: theme.getActiveInternalFrameTitleBackgroundColor(),
404: "InternalFrame.activeTitleForeground",
405: theme.getActiveInternalFrameTitleForegroundColor(),
406: "InternalFrame.activeTitleGradient",
407: theme.getActiveInternalFrameTitleGradientColor(), //ColorUtil.mult(theme.getActiveInternalFrameTitleBackgroundColor(), 1.2),
408: "InternalFrame.inactiveTitleBackground",
409: theme.getInactiveInternalFrameTitleBackgroundColor(),
410: "InternalFrame.inactiveTitleForeground",
411: theme.getInactiveInternalFrameTitleForegroundColor(),
412: "InternalFrame.inactiveTitleGradient",
413: theme.getInactiveInternalFrameTitleGradientColor(), //ColorUtil.mult(theme.getInactiveInternalFrameTitleBackgroundColor(), 1.2),
414: "InternalFrame.icon",
415: theme.getInternalFrameIcon(),
416: "InternalFrame.iconifyIcon",
417: theme.getInternalFrameIconifyIcon(),
418: "InternalFrame.minimizeIcon",
419: theme.getInternalFrameMinimizeIcon(),
420: "InternalFrame.maximizeIcon",
421: theme.getInternalFrameMaximizeIcon(),
422: "InternalFrame.closeIcon",
423: theme.getInternalFrameCloseIcon(),
424: "InternalFrame.border",
425: theme.getInternalFrameBorder(),
426: "InternalFrame.titleFont",
427: theme.getInternalFrameTitleFont(),
428:
429: "MenuBar.border",
430: theme.getMenuBarBorder(),
431:
432: "MenuItem.border",
433: menuItemBorder,
434: "Menu.border",
435: menuItemBorder,
436: // "CheckBoxMenuItem.border", menuItemBorder,
437: // "RadioButtonMenuItem.border", menuItemBorder,
438:
439: "Spinner.border",
440: theme.getTextFieldBorder(),
441: "Spinner.background",
442: new ColorUIResource(theme.getBackgroundColor()),
443:
444: "PopupMenu.border",
445: theme.getPopupMenuBorder(),
446:
447: "TextField.border",
448: theme.getTextFieldBorder(),
449: "FormattedTextField.border",
450: theme.getTextFieldBorder(),
451:
452: // "Button.border", new BorderUIResource(buttonBorder),
453: // "Button.disabledShadow", new ColorUIResource(Color.GREEN), //ColorUtil.blend(textColor, controlColor, 0.5f)),
454: "Button.textShiftOffset",
455: new Integer(2),
456: "Button.select",
457: theme.getControlLightShadowColor(),
458: // "Button.focus", focusColor,
459: "Button.margin",
460: theme.getButtonMargin(),
461: "Button.disabledText",
462: theme.getInactiveTextColor(),
463: //"Button.background", buttonBackground.getColor(),
464:
465: "ToggleButton.margin",
466: theme.getButtonMargin(),
467: "ToggleButton.select",
468: theme.getControlLightShadowColor(),
469: "ToggleButton.textShiftOffset",
470: new Integer(2),
471:
472: "Tree.openIcon",
473: theme.getTreeOpenIcon(),
474: "Tree.closedIcon",
475: theme.getTreeClosedIcon(),
476: "Tree.leafIcon",
477: theme.getTreeLeafIcon(),
478: "Tree.collapsedIcon",
479: new IconUIResource(new TreeIcon(TreeIcon.PLUS, 10, 10,
480: true, theme.getTextColor(), theme
481: .getTreeIconBackgroundColor())),
482: "Tree.expandedIcon",
483: new IconUIResource(new TreeIcon(TreeIcon.MINUS, 10, 10,
484: true, theme.getTextColor(), theme
485: .getTreeIconBackgroundColor())),
486: "Tree.leftChildIndent",
487: new Integer(5),
488: "Tree.rightChildIndent",
489: new Integer(11),
490: // "Tree.rowHeight", new Integer(12),
491:
492: "OptionPane.errorIcon",
493: LookAndFeel.makeIcon(iconClass, "icons/Error.gif"),
494: "OptionPane.informationIcon",
495: LookAndFeel.makeIcon(iconClass, "icons/Inform.gif"),
496: "OptionPane.warningIcon",
497: LookAndFeel.makeIcon(iconClass, "icons/Warn.gif"),
498: "OptionPane.questionIcon",
499: LookAndFeel.makeIcon(iconClass, "icons/Question.gif"),
500: "OptionPane.buttonFont",
501: theme.getOptionPaneButtonFont(), };
502:
503: table.putDefaults(defaults);
504: }
505:
506: /**
507: * Installs this look and feel with the {@link UIManager}, if it's not already installed.
508: */
509: public static void install() {
510: if (!ArrayUtil.contains(UIManager.getInstalledLookAndFeels(),
511: LOOK_AND_FEEL_INFO))
512: UIManager.installLookAndFeel(LOOK_AND_FEEL_INFO);
513: }
514:
515: }
|