2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.ide.ui;
18 import com.intellij.CommonBundle;
19 import com.intellij.ide.IdeBundle;
20 import com.intellij.idea.StartupUtil;
21 import com.intellij.openapi.components.*;
22 import com.intellij.openapi.diagnostic.Logger;
23 import com.intellij.openapi.ui.Messages;
24 import com.intellij.openapi.util.Comparing;
25 import com.intellij.openapi.util.IconLoader;
26 import com.intellij.openapi.util.SystemInfo;
27 import com.intellij.ui.ColoredSideBorder;
28 import com.intellij.ui.IdeaBlueMetalTheme;
29 import com.intellij.ui.ScreenUtil;
30 import com.intellij.ui.mac.MacPopupMenuUI;
31 import com.intellij.ui.plaf.beg.*;
32 import com.intellij.util.ui.UIUtil;
33 import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
34 import org.jdom.Element;
35 import org.jetbrains.annotations.NonNls;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
40 import javax.swing.border.Border;
41 import javax.swing.event.EventListenerList;
42 import javax.swing.plaf.ColorUIResource;
43 import javax.swing.plaf.FontUIResource;
44 import javax.swing.plaf.metal.DefaultMetalTheme;
45 import javax.swing.plaf.metal.MetalLookAndFeel;
46 import javax.swing.text.DefaultEditorKit;
48 import java.awt.event.KeyEvent;
49 import java.lang.reflect.InvocationTargetException;
50 import java.lang.reflect.Method;
51 import java.util.Arrays;
52 import java.util.Comparator;
53 import java.util.HashMap;
56 * @author Eugene Belyaev
57 * @author Vladimir Kondratyev
61 roamingType = RoamingType.PER_PLATFORM,
64 file = "$APP_CONFIG$/options.xml")})
65 public final class LafManagerImpl extends LafManager implements ApplicationComponent, PersistentStateComponent<Element> {
66 private static final Logger LOG=Logger.getInstance("#com.intellij.ide.ui.LafManager");
68 @NonNls private static final String IDEA_LAF_CLASSNAME = "idea.laf.classname";
71 * One of the possible values of -Didea.popup.weight property. Heavy weight means
72 * that all popups are shown inside the window. Under UNIXes it's possible to configure
73 * window manager "Focus follows mouse with Auto Raise". In this case popup window will
74 * be immediately closed after showing.
76 @NonNls private static final String HEAVY_WEIGHT_POPUP="heavy";
78 * One of the possible values of -Didea.popup.weight property. Medium weight means
79 * that popup will be shouw inside the paren't JLayeredPane if it can be fit to it.
80 * Otherwise popup will be shown in the window. This mode is defaut for the Swing but
81 * it's very slow (much slower then heavy weight popups).
83 @NonNls private static final String MEDIUM_WEIGHT_POPUP="medium";
85 private final EventListenerList myListenerList;
86 private final UIManager.LookAndFeelInfo[] myLafs;
87 private UIManager.LookAndFeelInfo myCurrentLaf;
89 @NonNls private static final String[] ourPatcheableFontResources = new String[]{
90 "Button.font", "ToggleButton.font", "RadioButton.font", "CheckBox.font", "ColorChooser.font", "ComboBox.font",
91 "Label.font", "List.font", "MenuBar.font", "MenuItem.font", "MenuItem.acceleratorFont", "RadioButtonMenuItem.font",
92 "CheckBoxMenuItem.font", "Menu.font", "PopupMenu.font", "OptionPane.font", "Panel.font", "ProgressBar.font",
93 "ScrollPane.font", "Viewport.font", "TabbedPane.font", "Table.font", "TableHeader.font", "TextField.font",
94 "PasswordField.font", "TextArea.font", "TextPane.font", "EditorPane.font", "TitledBorder.font", "ToolBar.font",
95 "ToolTip.font", "Tree.font"
97 @NonNls private static final String[] ourFileChooserTextKeys = new String[] {
98 "FileChooser.viewMenuLabelText", "FileChooser.newFolderActionLabelText", "FileChooser.listViewActionLabelText",
99 "FileChooser.detailsViewActionLabelText", "FileChooser.refreshActionLabelText"
102 private final HashMap<UIManager.LookAndFeelInfo, HashMap<String, Object>> myStoredDefaults = new HashMap<UIManager.LookAndFeelInfo, HashMap<String, Object>>();
103 private final UISettings myUiSettings;
105 @NonNls private static final String ELEMENT_LAF = "laf";
106 @NonNls private static final String ATTRIBUTE_CLASS_NAME = "class-name";
108 /** invoked by reflection
109 * @param uiSettings */
110 LafManagerImpl(UISettings uiSettings){
111 myUiSettings = uiSettings;
112 myListenerList=new EventListenerList();
114 IdeaLookAndFeelInfo ideaLaf=new IdeaLookAndFeelInfo();
115 UIManager.LookAndFeelInfo[] installedLafs=UIManager.getInstalledLookAndFeels();
117 // Get all installed LAFs
118 myLafs=new UIManager.LookAndFeelInfo[1+installedLafs.length];
120 System.arraycopy(installedLafs,0,myLafs,1,installedLafs.length);
121 Arrays.sort(myLafs,new MyComparator());
123 // Setup current LAF. Unfortunately it's system depended.
124 myCurrentLaf=getDefaultLaf();
128 * Adds specified listener
130 public void addLafManagerListener(@NotNull final LafManagerListener l){
131 myListenerList.add(LafManagerListener.class, l);
135 * Removes specified listener
137 public void removeLafManagerListener(@NotNull final LafManagerListener l){
138 myListenerList.remove(LafManagerListener.class, l);
141 private void fireLookAndFeelChanged(){
142 LafManagerListener[] listeners = myListenerList.getListeners(LafManagerListener.class);
143 for (LafManagerListener listener : listeners) {
144 listener.lookAndFeelChanged(this);
149 public String getComponentName(){
153 public void initComponent() {
154 setCurrentLookAndFeel(findLaf(myCurrentLaf.getClassName())); // setup default LAF or one specfied by readExternal.
158 public void disposeComponent(){}
160 public void loadState(final Element element) {
161 String className=null;
162 for (final Object o : element.getChildren()) {
163 Element child = (Element)o;
164 if (ELEMENT_LAF.equals(child.getName())) {
165 className = child.getAttributeValue(ATTRIBUTE_CLASS_NAME);
170 UIManager.LookAndFeelInfo laf=findLaf(className);
171 // If LAF is undefined (wrong class name or something else) we have set default LAF anyway.
176 if (myCurrentLaf != null && !laf.getClassName().equals(myCurrentLaf.getClassName())) {
177 setCurrentLookAndFeel(laf);
184 public Element getState() {
185 Element element = new Element("state");
186 if(myCurrentLaf.getClassName()!=null){
187 Element child=new Element(ELEMENT_LAF);
188 child.setAttribute(ATTRIBUTE_CLASS_NAME,myCurrentLaf.getClassName());
189 element.addContent(child);
194 public UIManager.LookAndFeelInfo[] getInstalledLookAndFeels(){
195 return myLafs.clone();
198 public UIManager.LookAndFeelInfo getCurrentLookAndFeel(){
202 public boolean isUnderAquaLookAndFeel() {
203 //noinspection HardCodedStringLiteral
204 return "Mac OS X".equals(getCurrentLookAndFeel().getName());
207 public boolean isUnderQuaquaLookAndFeel() {
208 //noinspection HardCodedStringLiteral
209 return "Quaqua".equals(getCurrentLookAndFeel().getName());
213 * @return default LookAndFeelInfo for the running OS. For Win32 and
214 * Linux the method returns Alloy LAF or IDEA LAF if first not found, for Mac OS X it returns Aqua
216 private UIManager.LookAndFeelInfo getDefaultLaf(){
217 if(SystemInfo.isMac) {
218 UIManager.LookAndFeelInfo laf=findLaf(UIManager.getSystemLookAndFeelClassName());
219 LOG.assertTrue(laf!=null);
223 String defaultLafName = StartupUtil.getDefaultLAF();
224 if (defaultLafName != null) {
225 UIManager.LookAndFeelInfo defaultLaf = findLaf(defaultLafName);
226 if (defaultLaf != null) {
230 return findLaf(IDEA_LAF_CLASSNAME);
235 * Finds LAF by its class name.
238 private UIManager.LookAndFeelInfo findLaf(String className){
239 for (UIManager.LookAndFeelInfo laf : myLafs) {
240 if (Comparing.equal(laf.getClassName(), className)) {
248 * Sets current LAF. The method doesn't update component hierarchy.
250 public void setCurrentLookAndFeel(UIManager.LookAndFeelInfo lookAndFeelInfo){
251 if(findLaf(lookAndFeelInfo.getClassName())==null){
252 LOG.error("unknown LookAndFeel : "+lookAndFeelInfo);
258 if(IDEA_LAF_CLASSNAME.equals(lookAndFeelInfo.getClassName())){ // that is IDEA default LAF
259 IdeaLaf laf=new IdeaLaf();
260 IdeaLaf.setCurrentTheme(new IdeaBlueMetalTheme());
262 UIManager.setLookAndFeel(laf);
263 } catch (Exception exc) {
264 Messages.showMessageDialog(
265 IdeBundle.message("error.cannot.set.look.and.feel", lookAndFeelInfo.getName()),
266 CommonBundle.getErrorTitle(),
267 Messages.getErrorIcon()
271 }else{ // non default LAF
273 LookAndFeel laf=((LookAndFeel)Class.forName(lookAndFeelInfo.getClassName()).newInstance());
274 if(laf instanceof MetalLookAndFeel){
275 MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
277 UIManager.setLookAndFeel(laf);
278 } catch(Exception exc) {
279 Messages.showMessageDialog(
280 IdeBundle.message("error.cannot.set.look.and.feel", lookAndFeelInfo.getName()),
281 CommonBundle.getErrorTitle(),
282 Messages.getErrorIcon()
287 myCurrentLaf=lookAndFeelInfo;
289 // The following code is a trick! By default Swing uses lightweight and "medium" weight
290 // popups to show JPopupMenu. The code below force the creation of real heavyweight menus.
291 // It dramatically increases speed of popups.
293 //noinspection HardCodedStringLiteral
294 String popupWeight=System.getProperty("idea.popup.weight");
295 if(popupWeight==null){ // use defaults if popup weight isn't specified
296 if(SystemInfo.isWindows){
297 popupWeight=HEAVY_WEIGHT_POPUP;
298 }else{ // UNIXes (Linux and MAC) go here
299 popupWeight=MEDIUM_WEIGHT_POPUP;
301 } else if (HEAVY_WEIGHT_POPUP.equals(popupWeight) && !MEDIUM_WEIGHT_POPUP.equals(popupWeight)) {
302 throw new IllegalStateException("unknown value of property -Didea.popup.weight: " + popupWeight);
305 if (SystemInfo.isMacOSLeopard) {
306 // Force heavy weight popups under Leopard, otherwise they don't have shadow or any kind of border.
307 popupWeight = HEAVY_WEIGHT_POPUP;
310 popupWeight = popupWeight.trim();
311 final boolean heavyWeighPopup = HEAVY_WEIGHT_POPUP.equals(popupWeight);
313 PopupFactory popupFactory;
315 final PopupFactory oldFactory = PopupFactory.getSharedInstance();
316 if (!(oldFactory instanceof OurPopupFactory)) {
317 popupFactory = new OurPopupFactory() {
318 public Popup getPopup(
323 ) throws IllegalArgumentException {
324 final Point point = fixPopupLocation(contents, x, y);
326 final Method method = PopupFactory.class.getDeclaredMethod("setPopupType", int.class);
327 method.setAccessible(true);
328 method.invoke(oldFactory, heavyWeighPopup ? 2 : 1);
331 catch (Throwable e) {
335 return oldFactory.getPopup(owner, contents, point.x, point.y);
339 PopupFactory.setSharedInstance(popupFactory);
342 // update ui for popup menu to get round corners
343 if (UIUtil.isUnderAquaLookAndFeel()) {
344 final UIDefaults uiDefaults = UIManager.getLookAndFeelDefaults();
345 uiDefaults.put("PopupMenuUI", MacPopupMenuUI.class.getCanonicalName());
346 final Icon icon = getAquaMenuInvertedIcon();
348 uiDefaults.put("Menu.invertedArrowIcon", icon);
354 private static Icon getAquaMenuInvertedIcon() {
355 if (!UIUtil.isUnderAquaLookAndFeel()) return null;
356 final Icon arrow = (Icon) UIManager.get("Menu.arrowIcon");
357 if (arrow == null) return null;
360 final Method method = arrow.getClass().getMethod("getInvertedIcon");
361 if (method != null) {
362 method.setAccessible(true);
363 return (Icon) method.invoke(arrow);
368 catch (NoSuchMethodException e1) {
371 catch (InvocationTargetException e1) {
374 catch (IllegalAccessException e1) {
379 private Point fixPopupLocation(final Component contents, final int x, final int y) {
380 if (!(contents instanceof JToolTip)) return new Point(x, y);
382 final PointerInfo info;
384 info = MouseInfo.getPointerInfo();
386 catch (InternalError e) {
387 // http://www.jetbrains.net/jira/browse/IDEADEV-21390
388 // may happen under Mac OSX 10.5
389 return new Point(x, y);
394 final Point mouse = info.getLocation();
395 deltaY = mouse.y - y;
398 final Dimension size = contents.getPreferredSize();
399 final Rectangle rec = new Rectangle(new Point(x, y), size);
400 ScreenUtil.moveRectangleToFitTheScreen(rec);
406 return rec.getLocation();
411 * Updates LAF of all windows. The method also updates font of components
412 * as it's configured in <code>UISettings</code>.
414 public void updateUI(){
415 UIDefaults lookAndFeelDefaults=UIManager.getLookAndFeelDefaults();
416 initInputMapDefaults(lookAndFeelDefaults);
417 patchFileChooserStrings(lookAndFeelDefaults);
418 if (shouldPatchLAFFonts()) {
419 storeOriginalFontDefaults(lookAndFeelDefaults);
420 initFontDefaults(lookAndFeelDefaults);
423 restoreOriginalFontDefaults(lookAndFeelDefaults);
426 Frame[] frames=Frame.getFrames();
427 for (Frame frame : frames) {
430 fireLookAndFeelChanged();
433 private void patchFileChooserStrings(final UIDefaults defaults) {
434 if (!defaults.containsKey(ourFileChooserTextKeys [0])) {
435 // Alloy L&F does not define strings for names of context menu actions, so we have to patch them in here
436 for (String key : ourFileChooserTextKeys) {
437 defaults.put(key, IdeBundle.message(key));
442 private void restoreOriginalFontDefaults(UIDefaults defaults) {
443 UIManager.LookAndFeelInfo lf = getCurrentLookAndFeel();
444 HashMap<String, Object> lfDefaults = myStoredDefaults.get(lf);
445 if (lfDefaults != null) {
446 for (String resource : ourPatcheableFontResources) {
447 defaults.put(resource, lfDefaults.get(resource));
452 private void storeOriginalFontDefaults(UIDefaults defaults) {
453 UIManager.LookAndFeelInfo lf = getCurrentLookAndFeel();
454 HashMap<String, Object> lfDefaults = myStoredDefaults.get(lf);
455 if (lfDefaults == null) {
456 lfDefaults = new HashMap<String, Object>();
457 for (String resource : ourPatcheableFontResources) {
458 lfDefaults.put(resource, defaults.get(resource));
460 myStoredDefaults.put(lf, lfDefaults);
464 private boolean shouldPatchLAFFonts() {
465 //noinspection HardCodedStringLiteral
466 return getCurrentLookAndFeel().getName().startsWith("IDEA") || UISettings.getInstance().OVERRIDE_NONIDEA_LAF_FONTS;
469 private static void updateUI(Window window){
470 if(!window.isDisplayable()){
473 SwingUtilities.updateComponentTreeUI(window);
474 Window[] children=window.getOwnedWindows();
475 for (Window aChildren : children) {
481 * Repaints all displayable window.
483 public void repaintUI(){
484 Frame[] frames=Frame.getFrames();
485 for (Frame frame : frames) {
490 private static void repaintUI(Window window){
491 if(!window.isDisplayable()){
495 Window[] children=window.getOwnedWindows();
496 for (Window aChildren : children) {
497 repaintUI(aChildren);
501 private static void installCutCopyPasteShortcuts(InputMap inputMap, boolean useSimpleActionKeys){
502 String copyActionKey = useSimpleActionKeys ? "copy" : DefaultEditorKit.copyAction;
503 String pasteActionKey = useSimpleActionKeys ? "paste" : DefaultEditorKit.pasteAction;
504 String cutActionKey = useSimpleActionKeys ? "cut" : DefaultEditorKit.cutAction;
505 // Ctrl+Ins, Shift+Ins, Shift+Del
506 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT,KeyEvent.CTRL_MASK|KeyEvent.CTRL_DOWN_MASK),copyActionKey);
507 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT,KeyEvent.SHIFT_MASK|KeyEvent.SHIFT_DOWN_MASK),pasteActionKey);
508 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,KeyEvent.SHIFT_MASK|KeyEvent.SHIFT_DOWN_MASK),cutActionKey);
509 // Ctrl+C, Ctrl+V, Ctrl+X
510 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_C,KeyEvent.CTRL_MASK|KeyEvent.CTRL_DOWN_MASK),copyActionKey);
511 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,KeyEvent.CTRL_MASK|KeyEvent.CTRL_DOWN_MASK),pasteActionKey);
512 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_X,KeyEvent.CTRL_MASK|KeyEvent.CTRL_DOWN_MASK),DefaultEditorKit.cutAction);
515 @SuppressWarnings({"HardCodedStringLiteral"})
516 private static void initInputMapDefaults(UIDefaults defaults){
517 // Make ENTER work in JTrees
518 InputMap treeInputMap = (InputMap)defaults.get("Tree.focusInputMap");
519 if(treeInputMap!=null){ // it's really possible. For examle, GTK+ doesn't have such map
520 treeInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),"toggle");
522 // Cut/Copy/Paste in JTextAreas
523 InputMap textAreaInputMap=(InputMap)defaults.get("TextArea.focusInputMap");
524 if(textAreaInputMap!=null){ // It really can be null, for example when LAF isn't properly initialized (Alloy license problem)
525 installCutCopyPasteShortcuts(textAreaInputMap, false);
527 // Cut/Copy/Paste in JTextFields
528 InputMap textFieldInputMap=(InputMap)defaults.get("TextField.focusInputMap");
529 if(textFieldInputMap!=null){ // It really can be null, for example when LAF isn't properly initialized (Alloy license problem)
530 installCutCopyPasteShortcuts(textFieldInputMap, false);
532 // Cut/Copy/Paste in JPAsswordField
533 InputMap passwordFieldInputMap=(InputMap)defaults.get("PasswordField.focusInputMap");
534 if(passwordFieldInputMap!=null){ // It really can be null, for example when LAF isn't properly initialized (Alloy license problem)
535 installCutCopyPasteShortcuts(passwordFieldInputMap, false);
537 // Cut/Copy/Paste in JTables
538 InputMap tableInputMap=(InputMap)defaults.get("Table.ancestorInputMap");
539 if(tableInputMap!=null){ // It really can be null, for example when LAF isn't properly initialized (Alloy license problem)
540 installCutCopyPasteShortcuts(tableInputMap, true);
544 @SuppressWarnings({"HardCodedStringLiteral"})
545 private void initFontDefaults(UIDefaults defaults) {
546 defaults.put("Tree.ancestorInputMap", null);
547 int uiFontSize = myUiSettings.FONT_SIZE;
548 String uiFontFace = myUiSettings.FONT_FACE;
549 FontUIResource font = new FontUIResource(uiFontFace, Font.PLAIN, uiFontSize);
550 FontUIResource font1 = new FontUIResource("Serif", Font.PLAIN, uiFontSize);
551 FontUIResource font3 = new FontUIResource("Monospaced", Font.PLAIN, uiFontSize);
553 for (String fontResource : ourPatcheableFontResources) {
554 defaults.put(fontResource, font);
557 defaults.put("PasswordField.font", font3);
558 defaults.put("TextArea.font", font3);
559 defaults.put("TextPane.font", font1);
560 defaults.put("EditorPane.font", font1);
561 defaults.put("TitledBorder.font", font);
564 private static final class IdeaLookAndFeelInfo extends UIManager.LookAndFeelInfo{
565 public IdeaLookAndFeelInfo(){
566 super(IdeBundle.message("idea.default.look.and.feel"), IDEA_LAF_CLASSNAME);
569 public boolean equals(Object obj){
570 return (obj instanceof IdeaLookAndFeelInfo);
573 public int hashCode(){
574 return getName().hashCode();
578 private static final class MyComparator implements Comparator{
579 public int compare(Object obj1,Object obj2){
580 String name1=((UIManager.LookAndFeelInfo)obj1).getName();
581 String name2=((UIManager.LookAndFeelInfo)obj2).getName();
582 return name1.compareToIgnoreCase(name2);
586 private static final class IdeaLaf extends MetalLookAndFeel{
587 protected void initComponentDefaults(UIDefaults table) {
588 super.initComponentDefaults(table);
589 initInputMapDefaults(table);
590 initIdeaDefaults(table);
593 protected void initSystemColorDefaults(UIDefaults table) {
594 super.initSystemColorDefaults(table);
596 table.put("control", new ColorUIResource(236, 233, 216));
597 table.put("controlHighlight", new ColorUIResource(255, 255, 255));
598 table.put("controlShadow", new ColorUIResource(172, 167, 153));
602 @SuppressWarnings({"HardCodedStringLiteral"})
603 private static void initIdeaDefaults(UIDefaults defaults) {
604 defaults.put("Menu.maxGutterIconWidth", 18);
605 defaults.put("MenuItem.maxGutterIconWidth", 18);
606 // TODO[vova,anton] REMOVE!!! INVESTIGATE??? Borland???
607 defaults.put("MenuItem.acceleratorDelimiter", "-");
609 defaults.put("TitledBorder.titleColor",IdeaBlueMetalTheme.primary1);
610 ColorUIResource col = new ColorUIResource(230, 230, 230);
611 defaults.put("ScrollBar.background", col);
612 defaults.put("ScrollBar.track", col);
614 // Border scrollPaneBorder = new BorderUIResource(new BegBorders.ScrollPaneBorder());
615 // defaults.put("ScrollPane.border", scrollPaneBorder);
616 defaults.put("TextField.border", BegBorders.getTextFieldBorder());
617 defaults.put("PasswordField.border", BegBorders.getTextFieldBorder());
618 Border popupMenuBorder = new BegPopupMenuBorder();
619 defaults.put("PopupMenu.border", popupMenuBorder);
620 defaults.put("ScrollPane.border", BegBorders.getScrollPaneBorder());
622 defaults.put("ButtonUI", BegButtonUI.class.getName());
623 defaults.put("ComboBoxUI", BegComboBoxUI.class.getName());
624 defaults.put("RadioButtonUI", BegRadioButtonUI.class.getName());
625 defaults.put("CheckBoxUI", BegCheckBoxUI.class.getName());
626 defaults.put("TabbedPaneUI", BegTabbedPaneUI.class.getName());
627 defaults.put("TableUI", BegTableUI.class.getName());
628 defaults.put("TreeUI", BegTreeUI.class.getName());
629 // defaults.put("ScrollPaneUI", BegScrollPaneUI.class.getName());
631 defaults.put("TabbedPane.tabInsets", new Insets(0, 4, 0, 4));
632 defaults.put("ToolTip.background", new ColorUIResource(255, 255, 231));
633 defaults.put("ToolTip.border", new ColoredSideBorder(Color.gray, Color.gray, Color.black, Color.black, 1));
634 defaults.put("Tree.ancestorInputMap", null);
635 defaults.put("FileView.directoryIcon", IconLoader.getIcon("/nodes/folder.png"));
636 defaults.put("FileChooser.upFolderIcon", IconLoader.getIcon("/nodes/upFolder.png"));
637 defaults.put("FileChooser.newFolderIcon", IconLoader.getIcon("/nodes/newFolder.png"));
638 defaults.put("FileChooser.homeFolderIcon", IconLoader.getIcon("/nodes/homeFolder.png"));
639 defaults.put("OptionPane.errorIcon", IconLoader.getIcon("/general/errorDialog.png"));
640 defaults.put("OptionPane.informationIcon", IconLoader.getIcon("/general/informationDialog.png"));
641 defaults.put("OptionPane.warningIcon", IconLoader.getIcon("/general/warningDialog.png"));
642 defaults.put("OptionPane.questionIcon", IconLoader.getIcon("/general/questionDialog.png"));
643 defaults.put("Tree.openIcon", LookAndFeel.makeIcon(WindowsLookAndFeel.class, "icons/TreeOpen.gif"));
644 defaults.put("Tree.closedIcon", LookAndFeel.makeIcon(WindowsLookAndFeel.class, "icons/TreeClosed.gif"));
645 defaults.put("Tree.leafIcon", LookAndFeel.makeIcon(WindowsLookAndFeel.class, "icons/TreeLeaf.gif"));
646 defaults.put("Tree.expandedIcon", com.sun.java.swing.plaf.windows.WindowsTreeUI.ExpandedIcon.createExpandedIcon());
647 defaults.put("Tree.collapsedIcon", com.sun.java.swing.plaf.windows.WindowsTreeUI.CollapsedIcon.createCollapsedIcon());
648 defaults.put("Table.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
655 "control INSERT", "copy",
656 "shift INSERT", "paste",
657 "shift DELETE", "cut",
658 "RIGHT", "selectNextColumn",
659 "KP_RIGHT", "selectNextColumn",
660 "LEFT", "selectPreviousColumn",
661 "KP_LEFT", "selectPreviousColumn",
662 "DOWN", "selectNextRow",
663 "KP_DOWN", "selectNextRow",
664 "UP", "selectPreviousRow",
665 "KP_UP", "selectPreviousRow",
666 "shift RIGHT", "selectNextColumnExtendSelection",
667 "shift KP_RIGHT", "selectNextColumnExtendSelection",
668 "shift LEFT", "selectPreviousColumnExtendSelection",
669 "shift KP_LEFT", "selectPreviousColumnExtendSelection",
670 "shift DOWN", "selectNextRowExtendSelection",
671 "shift KP_DOWN", "selectNextRowExtendSelection",
672 "shift UP", "selectPreviousRowExtendSelection",
673 "shift KP_UP", "selectPreviousRowExtendSelection",
674 "PAGE_UP", "scrollUpChangeSelection",
675 "PAGE_DOWN", "scrollDownChangeSelection",
676 "HOME", "selectFirstColumn",
677 "END", "selectLastColumn",
678 "shift PAGE_UP", "scrollUpExtendSelection",
679 "shift PAGE_DOWN", "scrollDownExtendSelection",
680 "shift HOME", "selectFirstColumnExtendSelection",
681 "shift END", "selectLastColumnExtendSelection",
682 "ctrl PAGE_UP", "scrollLeftChangeSelection",
683 "ctrl PAGE_DOWN", "scrollRightChangeSelection",
684 "ctrl HOME", "selectFirstRow",
685 "ctrl END", "selectLastRow",
686 "ctrl shift PAGE_UP", "scrollRightExtendSelection",
687 "ctrl shift PAGE_DOWN", "scrollLeftExtendSelection",
688 "ctrl shift HOME", "selectFirstRowExtendSelection",
689 "ctrl shift END", "selectLastRowExtendSelection",
690 "TAB", "selectNextColumnCell",
691 "shift TAB", "selectPreviousColumnCell",
692 //"ENTER", "selectNextRowCell",
693 "shift ENTER", "selectPreviousRowCell",
694 "ctrl A", "selectAll",
695 //"ESCAPE", "cancel",
701 private static class OurPopupFactory extends PopupFactory {}