001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.swing.plaf.gtk;
043:
044: import java.awt.Color;
045: import java.awt.Component;
046: import java.awt.Font;
047: import java.awt.Graphics;
048: import javax.swing.BorderFactory;
049: import javax.swing.Icon;
050: import javax.swing.JScrollPane;
051: import javax.swing.UIDefaults;
052: import javax.swing.UIManager;
053: import javax.swing.plaf.FontUIResource;
054: import org.netbeans.swing.plaf.LFCustoms;
055: import org.netbeans.swing.plaf.util.UIUtils;
056:
057: /** UI customizations for GTK look and feel
058: *
059: * @author Tim Boudreau
060: */
061: public class GtkLFCustoms extends LFCustoms {
062: private Object light = new ThemeValue(ThemeValue.REGION_PANEL,
063: ThemeValue.WHITE, Color.GRAY);
064: private static Object control = new ThemeValue(
065: ThemeValue.REGION_PANEL, ThemeValue.MID, Color.GRAY);
066: private Object controlFont = new ThemeValue(ThemeValue.REGION_TAB,
067: new FontUIResource("Dialog", Font.PLAIN, 11)); //NOI18N
068:
069: //Background colors for winsys tabs
070:
071: public Object[] createApplicationSpecificKeysAndValues() {
072: //Avoid using ThemeValue if it can't work - mainly due to testing issues when trying to run GTK UI customizations
073: //on the Mac, which doesn't have a GTKLookAndFeel
074:
075: Object selBg = ThemeValue.functioning() ? new ThemeValue(
076: ThemeValue.REGION_BUTTON, ThemeValue.DARK, Color.CYAN)
077: : (Object) Color.CYAN;
078: Object selFg = ThemeValue.functioning() ? new ThemeValue(
079: ThemeValue.REGION_BUTTON, ThemeValue.TEXT_FOREGROUND,
080: Color.BLACK) : (Object) Color.BLACK;
081:
082: Object fb = new Color(144, 144, 255);
083: Object tabBg = ThemeValue.functioning() ? new ThemeValue(
084: ThemeValue.REGION_INTFRAME, ThemeValue.DARK, fb)
085: : (Object) fb;
086:
087: if (!ThemeValue.functioning()) {
088: Integer i = (Integer) UIManager.get("customFontSize"); //NOI18N
089: int sz = 11;
090: if (i != null) {
091: sz = i.intValue();
092: }
093: controlFont = new Font("Dialog", Font.PLAIN, sz); //NOI18N
094: }
095:
096: Color borderColor = (Color) UIManager
097: .get("InternalFrame.borderShadow");
098: if (borderColor == null) {
099: borderColor = new Color(144, 150, 162);
100: }
101:
102: Object[] result = {
103: PROPSHEET_SELECTION_BACKGROUND,
104: selBg,
105: PROPSHEET_SELECTION_FOREGROUND,
106: selFg,
107: PROPSHEET_SELECTED_SET_BACKGROUND,
108: selBg,
109: PROPSHEET_SELECTED_SET_FOREGROUND,
110: selFg,
111: PROPSHEET_BUTTON_COLOR,
112: selFg,
113:
114: PROPSHEET_SET_BACKGROUND,
115: ThemeValue.functioning() ? (Object) control
116: : (Object) Color.CYAN,
117: PROPSHEET_DISABLED_FOREGROUND,
118: new Color(161, 161, 146),
119: "Table.selectionBackground",
120: selBg, //NOI18N
121: "Table.selectionForeground",
122: selFg, //NOI18N
123: PROPSHEET_BACKGROUND,
124: Color.WHITE,
125: "window",
126: light,
127:
128: VIEW_TAB_OUTER_BORDER,
129: BorderFactory.createEmptyBorder(),
130: VIEW_TAB_TABS_BORDER,
131: BorderFactory.createEmptyBorder(),
132: VIEW_TAB_CONTENT_BORDER,
133: BorderFactory
134: .createMatteBorder(0, 1, 1, 1, borderColor),
135: EDITOR_TAB_OUTER_BORDER,
136: BorderFactory.createEmptyBorder(),
137: EDITOR_TAB_CONTENT_BORDER,
138: BorderFactory
139: .createMatteBorder(0, 1, 1, 1, borderColor),
140: EDITOR_TAB_TABS_BORDER,
141: BorderFactory.createEmptyBorder(),
142:
143: EDITOR_STATUS_LEFT_BORDER,
144: new InsetBorder(false, true),
145: EDITOR_STATUS_RIGHT_BORDER,
146: new InsetBorder(false, false),
147: EDITOR_STATUS_ONLYONEBORDER,
148: new InsetBorder(false, false),
149: EDITOR_STATUS_INNER_BORDER,
150: new InsetBorder(false, true),
151:
152: OUTPUT_BACKGROUND,
153: control,
154: OUTPUT_HYPERLINK_FOREGROUND,
155: selFg,
156: OUTPUT_SELECTION_BACKGROUND,
157: selBg,
158:
159: "controlFont",
160: controlFont, //NOI18N
161:
162: //UI Delegates for the tab control
163: EDITOR_TAB_DISPLAYER_UI,
164: "org.netbeans.swing.tabcontrol.plaf.GtkEditorTabDisplayerUI", //NOI18N
165: VIEW_TAB_DISPLAYER_UI,
166: "org.netbeans.swing.tabcontrol.plaf.GtkViewTabDisplayerUI", //NOI18N
167: SLIDING_TAB_BUTTON_UI,
168: "org.netbeans.swing.tabcontrol.plaf.SlidingTabDisplayerButtonUI", //NOI18N
169: SLIDING_BUTTON_UI,
170: "org.netbeans.swing.tabcontrol.plaf.GtkSlidingButtonUI", //NOI18N
171:
172: DESKTOP_BACKGROUND,
173: ThemeValue.functioning() ? new ThemeValue(
174: ThemeValue.REGION_BUTTON, ThemeValue.LIGHT,
175: Color.GRAY) : (Object) Color.GRAY,
176: EXPLORER_MINISTATUSBAR_BORDER,
177: BorderFactory.createEmptyBorder(),
178:
179: //TOOLBAR_UI, "org.netbeans.swing.plaf.gtk.GtkToolbarUI", //NOI18N
180:
181: PROGRESS_CANCEL_BUTTON_ICON,
182: UIUtils
183: .loadImage("org/netbeans/swing/plaf/resources/cancel_task_linux_mac.png"),
184: "winclassic_tab_sel_gradient", tabBg,
185: SCROLLPANE_BORDER,
186: new JScrollPane().getViewportBorder(), };
187:
188: //#108517 - turn off ctrl+page_up and ctrl+page_down mapping
189: return UIUtils
190: .addInputMapsWithoutCtrlPageUpAndCtrlPageDown(result);
191: }
192:
193: public Object[] createLookAndFeelCustomizationKeysAndValues() {
194: if (ThemeValue.functioning()) {
195: return new Object[] {
196: //XXX once the JDK team has integrated support for standard
197: //UIManager keys into 1.5 (not there as of b47), these can
198: //probably be deleted, resulting in a performance improvement:
199: "control",
200: control,
201: "controlHighlight",
202: new ThemeValue(ThemeValue.REGION_PANEL,
203: ThemeValue.LIGHT, Color.LIGHT_GRAY), //NOI18N
204: "controlShadow",
205: new ThemeValue(ThemeValue.REGION_PANEL,
206: ThemeValue.DARK, Color.DARK_GRAY), //NOI18N
207: "controlDkShadow",
208: new ThemeValue(ThemeValue.REGION_PANEL,
209: ThemeValue.BLACK, Color.BLACK), //NOI18N
210: "controlLtHighlight",
211: new ThemeValue(ThemeValue.REGION_PANEL,
212: ThemeValue.WHITE, Color.WHITE), //NOI18N
213: "textText",
214: new ThemeValue(ThemeValue.REGION_PANEL,
215: ThemeValue.TEXT_FOREGROUND, Color.BLACK), //NOI18N
216: "text",
217: new ThemeValue(ThemeValue.REGION_PANEL,
218: ThemeValue.TEXT_BACKGROUND, Color.GRAY), //NOI18N
219:
220: "tab_unsel_fill",
221: control, //NOI18N
222:
223: "SplitPane.dividerSize",
224: new Integer(2), //NOI18N
225:
226: SYSTEMFONT,
227: controlFont, //NOI18N
228: USERFONT,
229: controlFont, //NOI18N
230: MENUFONT,
231: controlFont, //NOI18N
232: LISTFONT,
233: controlFont, //NOI18N
234: "Label.font",
235: controlFont, //NOI18N
236: "Panel.font",
237: controlFont, //NOI18N
238:
239: // workaround: GTKLookAndFeel FileChooser is unusable, cannot
240: // choose a dir and doesn't look native anyway. We force MetalFileChooserUI
241:
242: "FileChooserUI",
243: "javax.swing.plaf.metal.MetalFileChooserUI", // NOI18N
244: "FileView.computerIcon",
245: javax.swing.plaf.metal.MetalIconFactory
246: .getTreeComputerIcon(), // NOI18N
247: "FileView.hardDriveIcon",
248: javax.swing.plaf.metal.MetalIconFactory
249: .getTreeHardDriveIcon(), // NOI18N
250: "FileView.floppyDriveIcon",
251: javax.swing.plaf.metal.MetalIconFactory
252: .getTreeFloppyDriveIcon(), // NOI18N
253: "FileChooser.newFolderIcon",
254: javax.swing.plaf.metal.MetalIconFactory
255: .getFileChooserNewFolderIcon(), // NOI18N
256: "FileChooser.upFolderIcon",
257: javax.swing.plaf.metal.MetalIconFactory
258: .getFileChooserUpFolderIcon(), // NOI18N
259: "FileChooser.homeFolderIcon",
260: javax.swing.plaf.metal.MetalIconFactory
261: .getFileChooserHomeFolderIcon(), // NOI18N
262: "FileChooser.detailsViewIcon",
263: javax.swing.plaf.metal.MetalIconFactory
264: .getFileChooserDetailViewIcon(), // NOI18N
265: "FileChooser.listViewIcon",
266: javax.swing.plaf.metal.MetalIconFactory
267: .getFileChooserListViewIcon(), // NOI18N
268: "FileChooser.usesSingleFilePane",
269: Boolean.TRUE, // NOI18N
270: "FileChooser.ancestorInputMap", // NOI18N
271: new UIDefaults.LazyInputMap(new Object[] {
272: "ESCAPE", "cancelSelection", // NOI18N
273: "F2", "editFileName", // NOI18N
274: "F5", "refresh", // NOI18N
275: "BACK_SPACE", "Go Up", // NOI18N
276: "ENTER", "approveSelection" // NOI18N
277: }),
278: // special tree icons - only for property sheet
279: "Tree.gtk_expandedIcon", new GTKExpandedIcon(),
280: "Tree.gtk_collapsedIcon", new GTKCollapsedIcon(), };
281: } else {
282: Object[] result = new Object[] {
283: TOOLBAR_UI,
284: new UIDefaults.ProxyLazyValue(
285: "org.netbeans.swing.plaf.gtk.GtkToolbarUI"), //NOI18N
286: // special tree icons - only for property sheet
287: "Tree.gtk_expandedIcon", new GTKExpandedIcon(),
288: "Tree.gtk_collapsedIcon", new GTKCollapsedIcon(), };
289: return result;
290: }
291: }
292:
293: /** Temporary workaround for GTK L&F */
294: private static abstract class GTKIcon implements Icon {
295: private static final int SIZE = 11;
296:
297: public int getIconWidth() {
298: return GTKIcon.SIZE;
299: }
300:
301: public int getIconHeight() {
302: return GTKIcon.SIZE;
303: }
304: }
305:
306: /**
307: * Temporary workaround for GTK L&F - they provide an icon which does not
308: * know its width or height until it has been painted. So for it to work
309: * correctly, we have this silliness.
310: */
311: private static final class GTKCollapsedIcon extends GTKIcon {
312: public void paintIcon(Component c, Graphics g, int x, int y) {
313: g.translate(x, y);
314: int mid, height, thick, i, j, up, down;
315: int size = Math.min(getIconWidth(), getIconHeight());
316: mid = (size / 2);
317: height = size / 2 + 1;
318: thick = Math.max(1, size / 7);
319:
320: i = size / 2 - height / 2 - 1;
321:
322: // Fill in the background of the expander icon.
323: g.setColor((Color) UIManager.get("Button.background"));
324: for (j = height - 1; j > 0; j--) {
325: g.drawLine(i, mid - j + 1, i, mid + j - 1);
326: i++;
327: }
328:
329: g.setColor((Color) UIManager.get("Button.foreground"));
330: i = size / 2 - height / 2 - 1;
331: down = thick - 1;
332: // Draw the base of the triangle.
333: for (up = 0; up < thick; up++) {
334: g.drawLine(i + up, 0 - down, i + up, size + down);
335: down--;
336: }
337: i++;
338:
339: // Paint sides of triangle.
340: for (j = height - 1; j > 0; j--) {
341: for (up = 0; up < thick; up++) {
342: g
343: .drawLine(i, mid - j + 1 - up, i, mid - j
344: + 1 - up);
345: g
346: .drawLine(i, mid + j - 1 + up, i, mid + j
347: - 1 + up);
348: }
349: i++;
350: }
351:
352: // Paint remainder of tip if necessary.
353: if (thick > 1) {
354: for (up = thick - 2; up >= 0; up--) {
355: g.drawLine(i, mid - up, i, mid + up);
356: i++;
357: }
358: }
359:
360: g.translate(-x, -y);
361: }
362: }
363:
364: /**
365: * Temporary workaround for GTK L&F - they provide an icon which does not
366: * know its width or height until it has been painted. So for it to work
367: * correctly, we have this silliness.
368: */
369: private static final class GTKExpandedIcon extends GTKIcon {
370: public void paintIcon(Component c, Graphics g, int x, int y) {
371: g.translate(x, y);
372: int mid, height, thick, i, j, up, down;
373: int size = Math.min(getIconWidth(), getIconHeight());
374: mid = (size / 2);
375: height = size / 2 + 1;
376: thick = Math.max(1, size / 7);
377:
378: j = size / 2 - height / 2 - 1;
379: // Fill in the background of the expander icon.
380: g.setColor((Color) UIManager.get("Button.background"));
381: for (i = height - 1; i > 0; i--) {
382: g.drawLine(mid - i + 1, j, mid + i - 1, j);
383: j++;
384: }
385:
386: g.setColor((Color) UIManager.get("Button.foreground"));
387: j = size / 2 - height / 2 - 1;
388: down = thick - 1;
389: // Draw the base of the triangle.
390: for (up = 0; up < thick; up++) {
391: g.drawLine(0 - down, j + up, size + down, j + up);
392: down--;
393: }
394: j++;
395:
396: // Paint sides of triangle.
397: for (i = height - 1; i > 0; i--) {
398: for (up = 0; up < thick; up++) {
399: g
400: .drawLine(mid - i + 1 - up, j, mid - i + 1
401: - up, j);
402: g
403: .drawLine(mid + i - 1 + up, j, mid + i - 1
404: + up, j);
405: }
406: j++;
407: }
408:
409: // Paint remainder of tip if necessary.
410: if (thick > 1) {
411: for (up = thick - 2; up >= 0; up--) {
412: g.drawLine(mid - up, j, mid + up, j);
413: j++;
414: }
415: }
416:
417: g.translate(-x, -y);
418: }
419: }
420:
421: }
|