Logo Search packages:      
Sourcecode: jedit version File versions  Download package

GUIUtilities.java

/*
 * GUIUtilities.java - Various GUI utility functions
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 1999, 2004 Slava Pestov
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package org.gjt.sp.jedit;

//{{{ Imports
import org.gjt.sp.jedit.browser.VFSFileChooserDialog;
import org.gjt.sp.jedit.gui.DynamicContextMenuService;
import org.gjt.sp.jedit.gui.EnhancedButton;
import org.gjt.sp.jedit.gui.FloatingWindowContainer;
import org.gjt.sp.jedit.gui.SplashScreen;
import org.gjt.sp.jedit.gui.VariableGridLayout;
import org.gjt.sp.jedit.menu.EnhancedCheckBoxMenuItem;
import org.gjt.sp.jedit.menu.EnhancedMenu;
import org.gjt.sp.jedit.menu.EnhancedMenuItem;
import org.gjt.sp.jedit.syntax.SyntaxStyle;
import org.gjt.sp.jedit.textarea.JEditTextArea;
import org.gjt.sp.jedit.textarea.TextAreaMouseHandler;
import org.gjt.sp.util.Log;
import org.gjt.sp.util.SyntaxUtilities;


import java.net.URL;
import java.util.*;
import java.util.List;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;


import java.awt.*;
import java.awt.event.*;
//}}}

/**
 * Various GUI functions.<p>
 *
 * The most frequently used members of this class are:
 *
 * <ul>
 * <li>{@link #loadIcon(String)}</li>
 * <li>{@link #confirm(Component,String,Object[],int,int)}</li>
 * <li>{@link #error(Component,String,Object[])}</li>
 * <li>{@link #message(Component,String,Object[])}</li>

 * <li>{@link #showVFSFileDialog(View,String,int,boolean)}</li>
 * <li>{@link #loadGeometry(Window,String)}</li>
 * <li>{@link #saveGeometry(Window,String)}</li>
 * <li>{@link #showPopupMenu(JPopupMenu,Component,int,int)}</li>
 * </ul>
 *
 * @author Slava Pestov
 * @version $Id: GUIUtilities.java 16406 2009-10-22 20:42:36Z shlomy $
 */
00090 public class GUIUtilities
{
      //{{{ Some predefined icons
      /**
       * @deprecated Use <code>GUIUtilities.loadIcon("new.gif");</code>
       * instead.
       */
      @Deprecated
00098       public static Icon NEW_BUFFER_ICON;

      /**
       * @deprecated Use <code>GUIUtilities.loadIcon("dirty.gif");</code>
       * instead.
       */
      @Deprecated
00105       public static Icon DIRTY_BUFFER_ICON;

      /**
       * @deprecated Use <code>GUIUtilities.loadIcon("readonly.gif");</code>
       * instead.
       */
      @Deprecated
00112       public static Icon READ_ONLY_BUFFER_ICON;

      /**
       * @deprecated Use <code>GUIUtilities.loadIcon("normal.gif");</code>
       * instead.
       */
      @Deprecated
00119       public static Icon NORMAL_BUFFER_ICON;

      /**
       * @deprecated Use <code>GUIUtilities.loadIcon("jedit-icon.gif");</code>
       * instead.
       */
      @Deprecated
00126       public static Icon WINDOW_ICON;
      //}}}

      //{{{ Icon methods

      //{{{ setIconPath() method
      /**
       * Sets the path where jEdit looks for icons.
       * @since jEdit 4.2pre5
       */
00136       public static void setIconPath(String iconPath)
      {
            GUIUtilities.iconPath = iconPath;
            if(icons != null)
                  icons.clear();
      } //}}}

      //{{{ loadIcon() method
      /**
       * Loads an icon.
       * @param iconName The icon name
       * @since jEdit 2.6pre7
       */
00149       public static Icon loadIcon(String iconName)
      {
            if(iconName == null)
                  return null;

            // * Enable old icon naming scheme support
            if(deprecatedIcons != null && deprecatedIcons.containsKey(iconName))
                  iconName = deprecatedIcons.get(iconName);

            if(icons == null)
                  icons = new Hashtable<String, Icon>();

            // check if there is a cached version first
            Icon icon = icons.get(iconName);
            if(icon != null)
                  return icon;

            URL url;

            try
            {
                  // get the icon
                  if(MiscUtilities.isURL(iconName))
                        url = new URL(iconName);
                  else
                        url = new URL(iconPath + iconName);
            }
            catch(Exception e)
            {
                  try
                  {
                        url = new URL(defaultIconPath + iconName);
                  }
                  catch(Exception ex)
                  {
                        Log.log(Log.ERROR,GUIUtilities.class,
                              "Icon not found: " + iconName);
                        Log.log(Log.ERROR,GUIUtilities.class,ex);
                        return null;
                  }
            }

            icon = new ImageIcon(url);

            icons.put(iconName,icon);
            return icon;
      } //}}}

      //{{{ getEditorIcon() method
      /**
       * Returns the default editor window image.
       */
00201       public static Image getEditorIcon()
      {
            return ((ImageIcon)loadIcon(jEdit.getProperty("logo.icon.medium"))).getImage();
      } //}}}

      //{{{ getPluginIcon() method
      /**
       * Returns the default plugin window image.
       */
00210       public static Image getPluginIcon()
      {
            return getEditorIcon();
      } //}}}

      //}}}

      //{{{ Menus, tool bars

      //{{{ loadMenuBar() method
      /**
       * Creates a menubar. Plugins should not need to call this method.
       * @param name The menu bar name
       * @since jEdit 3.2pre5
       */
00225       public static JMenuBar loadMenuBar(String name)
      {
            return loadMenuBar(jEdit.getActionContext(),name);
      } //}}}

      //{{{ loadMenuBar() method
      /**
       * Creates a menubar. Plugins should not need to call this method.
       * @param context An action context
       * @param name The menu bar name
       * @since jEdit 4.2pre1
       */
00237       public static JMenuBar loadMenuBar(ActionContext context, String name)
      {
            String menus = jEdit.getProperty(name);
            StringTokenizer st = new StringTokenizer(menus);

            JMenuBar mbar = new JMenuBar();

            while(st.hasMoreTokens())
            {
                  String menuName = st.nextToken();
                  mbar.add(loadMenu(context, menuName));
            }

            return mbar;
      } //}}}

      //{{{ loadMenu() method
      /**
       * Creates a menu. The menu label is set from the
       * <code><i>name</i>.label</code> property. The menu contents is taken
       * from the <code><i>name</i></code> property, which is a whitespace
       * separated list of action names. An action name of <code>-</code>
       * inserts a separator in the menu.
       * @param name The menu name
       * @see #loadMenuItem(String)
       * @since jEdit 2.6pre2
       */
00264       public static JMenu loadMenu(String name)
      {
            return loadMenu(jEdit.getActionContext(),name);
      } //}}}

      //{{{ loadMenu() method
      /**
       * Creates a menu. The menu label is set from the
       * <code><i>name</i>.label</code> property. The menu contents is taken
       * from the <code><i>name</i></code> property, which is a whitespace
       * separated list of action names. An action name of <code>-</code>
       * inserts a separator in the menu.
       * @param context An action context; either
       * <code>jEdit.getActionContext()</code> or
       * <code>VFSBrowser.getActionContext()</code>.
       * @param name The menu name
       * @see #loadMenuItem(String)
       * @since jEdit 4.2pre1
       */
00283       public static JMenu loadMenu(ActionContext context, String name)
      {
            return new EnhancedMenu(name,
                  jEdit.getProperty(name.concat(".label")),
                  context);
      } //}}}

      //{{{ loadPopupMenu() method
      /**
       * Creates a popup menu.
       * @param name The menu name
       * @since jEdit 2.6pre2
       */
00296       public static JPopupMenu loadPopupMenu(String name, JEditTextArea textArea, MouseEvent evt)
      {
            return loadPopupMenu(jEdit.getActionContext(), name, textArea, evt);
      } //}}}

      //{{{ loadPopupMenu() method
      /**
       * Creates a popup menu.

       * @param name The menu name
       * @since jEdit 2.6pre2
       */
00308       public static JPopupMenu loadPopupMenu(String name)
      {
            return loadPopupMenu(jEdit.getActionContext(),name);
      } //}}}

      //{{{ loadPopupMenu() method
      /**
       * Creates a popup menu.

       * @param context An action context; either
       * <code>jEdit.getActionContext()</code> or
       * <code>VFSBrowser.getActionContext()</code>.
       * @param name The menu name
       * @since jEdit 4.2pre1
       */
00323       public static JPopupMenu loadPopupMenu(ActionContext context, String name)
      {
            return loadPopupMenu(context, name, null, null);
      }

      //{{{ loadPopupMenu() method
      /**
       * Creates a popup menu.
       * @param context An action context; either
       * <code>jEdit.getActionContext()</code> or
       * <code>VFSBrowser.getActionContext()</code>.
       * @param name The menu name
       * @param textArea the textArea wanting to show the popup.
       *    If not null, include context menu items defined by services.
       * @param evt additional context info about where the mouse was when menu was requested
       * @since jEdit 4.3pre15
       */
00340       public static JPopupMenu loadPopupMenu(ActionContext context, String name, JEditTextArea textArea, MouseEvent evt)
      {
            JPopupMenu menu = new JPopupMenu();

            String menuItems = jEdit.getProperty(name);
            if(menuItems != null)
            {
                  StringTokenizer st = new StringTokenizer(menuItems);
                  while(st.hasMoreTokens())
                  {
                        String menuItemName = st.nextToken();
                        if(menuItemName.equals("-"))
                              menu.addSeparator();
                        else
                              menu.add(loadMenuItem(context,menuItemName,false));
                  }
            }
            // load menu items defined by services
            if (textArea != null)
            {
                  List<JMenuItem> list = GUIUtilities.getServiceContextMenuItems(textArea, evt);
                  if (!list.isEmpty())
                  {
                        menu.addSeparator();
                  }
                  for (JMenuItem mi : list)
                  {
                        menu.add(mi);
                  }
            }

            return menu;
      } //}}}
      //{{{ addServiceContextMenuItems() method
      /**
       * @return a list of menu items defined by services.
       *
       * @param textArea the TextArea desiring to display these menu items
       * @since jEdit 4.3pre15
       */
00380       public static List<JMenuItem> getServiceContextMenuItems(JEditTextArea textArea, MouseEvent evt)
      {
            List<JMenuItem> list = new ArrayList<JMenuItem>();
            String serviceClassName =  DynamicContextMenuService.class.getName();
            String[] menuServiceList = ServiceManager.getServiceNames(serviceClassName);
            for (String menuServiceName : menuServiceList)
            {
                  if (menuServiceName != null && menuServiceName.trim().length() > 0)
                  {
                        DynamicContextMenuService dcms = (DynamicContextMenuService)
                                    ServiceManager.getService(serviceClassName, menuServiceName);
                        if (dcms != null)
                        {
                              JMenuItem[] items = dcms.createMenu(textArea, evt);
                              if (items != null)
                              {
                                    list.addAll(Arrays.asList(items));
                              }
                        }
                  }
            }
            return list;
      } //}}}

      //{{{ loadMenuItem() method
      /**
       * Creates a menu item. The menu item is bound to the action named by
       * <code>name</code> with label taken from the return value of the
       * {@link EditAction#getLabel()} method.
       *
       * @param name The menu item name
       * @see #loadMenu(String)
       * @since jEdit 2.6pre1
       */
00414       public static JMenuItem loadMenuItem(String name)
      {
            return loadMenuItem(jEdit.getActionContext(),name,true);
      } //}}}

      //{{{ loadMenuItem() method
      /**
       * Creates a menu item.
       * @param name The menu item name
       * @param setMnemonic True if the menu item should have a mnemonic
       * @since jEdit 3.1pre1
       */
00426       public static JMenuItem loadMenuItem(String name, boolean setMnemonic)
      {
            return loadMenuItem(jEdit.getActionContext(),name,setMnemonic);
      } //}}}

      //{{{ loadMenuItem() method
      /**
       * Creates a menu item.
       * @param context An action context; either
       * <code>jEdit.getActionContext()</code> or
       * <code>VFSBrowser.getActionContext()</code>.
       * @param name The menu item name
       * @param setMnemonic True if the menu item should have a mnemonic
       * @since jEdit 4.2pre1
       */
00441       public static JMenuItem loadMenuItem(ActionContext context, String name,
            boolean setMnemonic)
      {
            if(name.charAt(0) == '%')
                  return loadMenu(context,name.substring(1));

            return _loadMenuItem(name, context, setMnemonic);
      } //}}}

      //{{{ loadMenuItem(EditAction, boolean)
      public static JMenuItem loadMenuItem(EditAction editAction,
            boolean setMnemonic)
      {
            String name = editAction.getName();
            ActionContext context = jEdit.getActionContext();

            return _loadMenuItem(name, context, setMnemonic);
      } //}}}

      //{{{ loadToolBar() method
      /**
       * Creates a toolbar.
       * @param name The toolbar name
       * @since jEdit 4.2pre2
       */
00466       public static Container loadToolBar(String name)
      {
            return loadToolBar(jEdit.getActionContext(),name);
      } //}}}

      //{{{ loadToolBar() method
      /**
       * Creates a toolbar.
       * @param context An action context; either
       * <code>jEdit.getActionContext()</code> or
       * <code>VFSBrowser.getActionContext()</code>.
       * @param name The toolbar name
       * @since jEdit 4.2pre2
       */
00480       public static Container loadToolBar(ActionContext context, String name)
      {
            JPanel toolBar = new JPanel(new BorderLayout());
            JToolBar toolB = new JToolBar();
            toolB.setFloatable(false);
            toolB.setMargin(new Insets(0,0,0,0));

            String buttons = jEdit.getProperty(name);
            if(buttons != null)
            {
                  StringTokenizer st = new StringTokenizer(buttons);
                  while(st.hasMoreTokens())
                  {
                        String button = st.nextToken();
                        if(button.equals("-"))
                        {
                              toolB.addSeparator(new Dimension(12,12));
                        }
                        else
                        {
                              JButton b = loadToolButton(context,button);
                              if(b != null)
                                    toolB.add(b);
                        }
                  }
            }

            toolBar.add(toolB);
            return toolBar;
      } //}}}

      //{{{ loadToolButton() method
      /**
       * Loads a tool bar button. The tooltip is constructed from
       * the <code><i>name</i>.label</code> and
       * <code><i>name</i>.shortcut</code> properties and the icon is loaded
       * from the resource named '/org/gjt/sp/jedit/icons/' suffixed
       * with the value of the <code><i>name</i>.icon</code> property.
       * @param name The name of the button
       */
00520       public static EnhancedButton loadToolButton(String name)
      {
            return loadToolButton(jEdit.getActionContext(),name);
      } //}}}

      //{{{ loadToolButton() method
      /**
       * Loads a tool bar button. The tooltip is constructed from
       * the <code><i>name</i>.label</code> and
       * <code><i>name</i>.shortcut</code> properties and the icon is loaded
       * from the resource named '/org/gjt/sp/jedit/icons/' suffixed
       * with the value of the <code><i>name</i>.icon</code> property.
       * @param context An action context; either
       * <code>jEdit.getActionContext()</code> or
       * <code>VFSBrowser.getActionContext()</code>.
       * @param name The name of the button
       * @since jEdit 4.2pre1
       */
00538       public static EnhancedButton loadToolButton(ActionContext context,
            String name)
      {
            String label = jEdit.getProperty(name + ".label");

            if(label == null)
                  label = name;

            Icon icon;
            String iconName = jEdit.getProperty(name + ".icon");
            if(iconName == null)
                  icon = loadIcon(jEdit.getProperty("broken-image.icon"));
            else
            {
                  icon = loadIcon(iconName);
                  if(icon == null)
                        icon = loadIcon(jEdit.getProperty("broken-image.icon"));
            }

            String toolTip = prettifyMenuLabel(label);
            String shortcutLabel = getShortcutLabel(name);
            if(shortcutLabel != null)
            {
                  toolTip = toolTip + " (" + shortcutLabel + ')';
            }

            EnhancedButton b = new EnhancedButton(icon,toolTip,name,context);
            b.setPreferredSize(new Dimension(32,32));
            return b;
      } //}}}

      //{{{ prettifyMenuLabel() method
      /**
       * `Prettifies' a menu item label by removing the `$' sign. This
       * can be used to process the contents of an <i>action</i>.label
       * property.
       */
00575       public static String prettifyMenuLabel(String label)
      {
            int index = label.indexOf('$');
            if(index != -1)
            {
                  label = label.substring(0,index)
                        .concat(label.substring(index + 1));
            }
            return label;
      } //}}}

      //{{{ getShortcutLabel() method
      /**
       * Returns a label string to show users what shortcut are
       * assigned to the action.
       */
00591       public static String getShortcutLabel(String action)
      {
            if(action == null)
                  return null;
            else
            {
                  String shortcut1 = jEdit.getProperty(action + ".shortcut");
                  String shortcut2 = jEdit.getProperty(action + ".shortcut2");

                  if(shortcut1 == null || shortcut1.length() == 0)
                  {
                        if(shortcut2 == null || shortcut2.length() == 0)
                              return null;
                        else
                              return shortcut2;
                  }
                  else
                  {
                        if(shortcut2 == null || shortcut2.length() == 0)
                              return shortcut1;
                        else
                              return shortcut1 + " or " + shortcut2;
                  }
            }
      } //}}}

      //}}}

      //}}}

      //{{{ Canned dialog boxes

      //{{{ message() method
      /**
       * Displays a dialog box.
       * The title of the dialog is fetched from
       * the <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property. The message
       * is formatted by the property manager with <code>args</code> as
       * positional parameters.
       * @param comp The component to display the dialog for
       * @param name The name of the dialog
       * @param args Positional parameters to be substituted into the
       * message text
       */
00636       public static void message(Component comp, String name, Object[] args)
      {
            hideSplashScreen();

            JOptionPane.showMessageDialog(comp,
                  jEdit.getProperty(name.concat(".message"),args),
                  jEdit.getProperty(name.concat(".title"),args),
                  JOptionPane.INFORMATION_MESSAGE);
      } //}}}

      //{{{ error() method
      /**
       * Displays an error dialog box.
       * The title of the dialog is fetched from
       * the <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property. The message
       * is formatted by the property manager with <code>args</code> as
       * positional parameters.
       * @param comp The component to display the dialog for
       * @param name The name of the dialog
       * @param args Positional parameters to be substituted into the
       * message text
       */
00659       public static void error(Component comp, String name, Object[] args)
      {
            hideSplashScreen();

            JOptionPane.showMessageDialog(comp,
                  jEdit.getProperty(name.concat(".message"),args),
                  jEdit.getProperty(name.concat(".title"),args),
                  JOptionPane.ERROR_MESSAGE);
      } //}}}

      //{{{ input() method
      /**
       * Displays an input dialog box and returns any text the user entered.
       * The title of the dialog is fetched from
       * the <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property.
       * @param comp The component to display the dialog for
       * @param name The name of the dialog
       * @param def The text to display by default in the input field
       */
00679       public static String input(Component comp, String name, Object def)
      {
            return input(comp,name,null,def);
      } //}}}

      //{{{ inputProperty() method
      /**
       * Displays an input dialog box and returns any text the user entered.
       * The title of the dialog is fetched from
       * the <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property.
       * @param comp The component to display the dialog for
       * @param name The name of the dialog
       * @param def The property whose text to display in the input field
       */
00694       public static String inputProperty(Component comp, String name,
            String def)
      {
            return inputProperty(comp,name,null,def);
      } //}}}

      //{{{ input() method
      /**
       * Displays an input dialog box and returns any text the user entered.
       * The title of the dialog is fetched from
       * the <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property.
       * @param comp The component to display the dialog for
       * @param name The name of the dialog
       * @param def The text to display by default in the input field
       * @param args Positional parameters to be substituted into the
       * message text
       * @since jEdit 3.1pre3
       */
00713       public static String input(Component comp, String name,
            Object[] args, Object def)
      {
            hideSplashScreen();

            String retVal = (String)JOptionPane.showInputDialog(comp,
                  jEdit.getProperty(name.concat(".message"),args),
                  jEdit.getProperty(name.concat(".title")),
                  JOptionPane.QUESTION_MESSAGE,null,null,def);
            return retVal;
      } //}}}

      //{{{ inputProperty() method
      /**
       * Displays an input dialog box and returns any text the user entered.
       * The title of the dialog is fetched from
       * the <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property.
       * @param comp The component to display the dialog for
       * @param name The name of the dialog
       * @param args Positional parameters to be substituted into the
       * message text
       * @param def The property whose text to display in the input field
       * @since jEdit 3.1pre3
       */
00738       public static String inputProperty(Component comp, String name,
            Object[] args, String def)
      {
            hideSplashScreen();

            String retVal = (String)JOptionPane.showInputDialog(comp,
                  jEdit.getProperty(name.concat(".message"),args),
                  jEdit.getProperty(name.concat(".title")),
                  JOptionPane.QUESTION_MESSAGE,
                  null,null,jEdit.getProperty(def));
            if(retVal != null)
                  jEdit.setProperty(def,retVal);
            return retVal;
      } //}}}

      //{{{ confirm() method
      /**
       * Displays a confirm dialog box and returns the button pushed by the
       * user. The title of the dialog is fetched from the
       * <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property.
       * @param comp The component to display the dialog for
       * @param name The name of the dialog
       * @param args Positional parameters to be substituted into the
       * message text
       * @param buttons The buttons to display - for example,
       * JOptionPane.YES_NO_CANCEL_OPTION
       * @param type The dialog type - for example,
       * JOptionPane.WARNING_MESSAGE
       * @since jEdit 3.1pre3
       */
00769       public static int confirm(Component comp, String name,
            Object[] args, int buttons, int type)
      {
            hideSplashScreen();

            return JOptionPane.showConfirmDialog(comp,
                  jEdit.getProperty(name + ".message",args),
                  jEdit.getProperty(name + ".title"),buttons,type);
      } //}}}

      //{{{ listConfirm() method
      /**
       * Displays a confirm dialog box and returns the button pushed by the
       * user. The title of the dialog is fetched from the
       * <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property. The dialog
       * also shows a list of entries given by the <code>listModel</code>
       * parameter.
       * @param comp the parent component
       * @param name the name of the confirm dialog
       * @param args the for the message
       * @param listModel the items in the list
       * @return an integer indicating the option selected by the user
       * @since jEdit 4.3pre1
       */
00794       public static int listConfirm(Component comp, String name, String[] args,
            Object[] listModel)
      {
            JList list = new JList(listModel);
            list.setVisibleRowCount(8);

            Object[] message = {
                  jEdit.getProperty(name + ".message",args),
                  new JScrollPane(list)
            };

            return JOptionPane.showConfirmDialog(comp,
                  message,
                  jEdit.getProperty(name + ".title"),
                  JOptionPane.YES_NO_OPTION,
                  JOptionPane.QUESTION_MESSAGE);
      } //}}}

      //{{{ listConfirm() method
      /**
       * Displays a confirm dialog box and returns the button pushed by the
       * user. The title of the dialog is fetched from the
       * <code><i>name</i>.title</code> property. The message is fetched
       * from the <code><i>name</i>.message</code> property. The dialog
       * also shows a list of entries given by the <code>listModel</code>
       * parameter.
       * @param comp the parent component
       * @param name the name of the confirm dialog
       * @param args the for the message
       * @param listModel the items in the list
       * @param selectedItems give an empty list, it will contains in return the selected items
       * @return an integer indicating the option selected by the user
       * @since jEdit 4.3pre12
       */
00828       public static int listConfirm(Component comp, String name, String[] args,
            Object[] listModel, List selectedItems)
      {
            JList list = new JList(listModel);
            list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
            list.setVisibleRowCount(8);
            list.addSelectionInterval(0,listModel.length - 1);

            Object[] message = {
                  jEdit.getProperty(name + ".message",args),
                  new JScrollPane(list)
            };

            int ret = JOptionPane.showConfirmDialog(comp,
                                          message,
                                          jEdit.getProperty(name + ".title"),
                                          JOptionPane.YES_NO_OPTION,
                                          JOptionPane.QUESTION_MESSAGE);
            Object[] selectedValues = list.getSelectedValues();
            selectedItems.addAll(Arrays.asList(selectedValues));
            return ret;
      } //}}}

      //{{{ showVFSFileDialog() methods
      /**
       * Displays a VFS file selection dialog box.
       * @param view The view, should be non-null
       * @param path The initial directory to display. May be null
       * @param type The dialog type. One of
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#OPEN_DIALOG},
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#SAVE_DIALOG}, or
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#CHOOSE_DIRECTORY_DIALOG}.
       * @param multipleSelection True if multiple selection should be allowed
       * @return The selected file(s)
       * @since jEdit 2.6pre2
       */
00864       public static String[] showVFSFileDialog(View view, String path,
            int type, boolean multipleSelection)
      {
            // the view should not be null, but some plugins might do this
            if(view == null)
            {
                  Log.log(Log.WARNING,GUIUtilities.class,
                  "showVFSFileDialog(): given null view, assuming jEdit.getActiveView()");
                  view = jEdit.getActiveView();
            }

            hideSplashScreen();

            VFSFileChooserDialog fileChooser = new VFSFileChooserDialog(
                  view,path,type,multipleSelection);
            return fileChooser.getSelectedFiles();
      }

      /**
       * Displays a VFS file selection dialog box.
       * This version can specify a dialog as the parent instead
       * of the view.
       * @param view The view, should be non-null
       * @param path The initial directory to display. May be null
       * @param type The dialog type. One of
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#OPEN_DIALOG},
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#SAVE_DIALOG}, or
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#CHOOSE_DIRECTORY_DIALOG}.
       * @param multipleSelection True if multiple selection should be allowed
       * @return The selected file(s)
       * @since jEdit 4.3pre10
       */
00896       public static String[] showVFSFileDialog(Dialog parent, View view,
            String path, int type, boolean multipleSelection)
      {
            hideSplashScreen();

            VFSFileChooserDialog fileChooser = new VFSFileChooserDialog(
                  parent, view, path, type, multipleSelection, true);
            return fileChooser.getSelectedFiles();
      }

      /**
       * Displays a VFS file selection dialog box.
       * This version can specify a frame as the parent instead
       * of the view.
       * @param parent The parent frame
       * @param view The view, should be non-null
       * @param path The initial directory to display. May be null
       * @param type The dialog type. One of
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#OPEN_DIALOG},
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#SAVE_DIALOG}, or
       * {@link org.gjt.sp.jedit.browser.VFSBrowser#CHOOSE_DIRECTORY_DIALOG}.
       * @param multipleSelection True if multiple selection should be allowed
       * @return The selected file(s)
       * @since jEdit 4.3pre10
       */
00921       public static String[] showVFSFileDialog(Frame parent, View view,
            String path, int type, boolean multipleSelection)
      {
            hideSplashScreen();
            VFSFileChooserDialog fileChooser = new VFSFileChooserDialog(
                  parent, view, path, type, multipleSelection, true);
            return fileChooser.getSelectedFiles();
      } //}}}

      //}}}

      //{{{ Colors and styles

      //{{{ parseColor() method
      /**
       * Converts a color name to a color object. The name must either be
       * a known string, such as `red', `green', etc (complete list is in
       * the <code>java.awt.Color</code> class) or a hex color value
       * prefixed with `#', for example `#ff0088'.
       * @param name The color name
       */
00942       public static Color parseColor(String name)
      {
            return SyntaxUtilities.parseColor(name, Color.black);
      } //}}}

      //{{{ parseColor() method
      /**
       * @deprecated use {@link SyntaxUtilities#parseColor(String,Color)}
       */
      @Deprecated
00952       public static Color parseColor(String name, Color defaultColor)
      {
            return SyntaxUtilities.parseColor(name, defaultColor);
      } //}}}

      //{{{ getColorHexString() method
      /**
       * Converts a color object to its hex value. The hex value
       * prefixed is with `#', for example `#ff0088'.
       * @param c The color object
       * @deprecated use {@link SyntaxUtilities#parseStyle(String,String,int,boolean)}
       */
      @Deprecated
00965       public static String getColorHexString(Color c)
      {
            return SyntaxUtilities.getColorHexString(c);
      } //}}}

      //{{{ parseStyle() method
      /**
       * Converts a style string to a style object.
       * @param str The style string
       * @param family Style strings only specify font style, not font family
       * @param size Style strings only specify font style, not font family
       * @exception IllegalArgumentException if the style is invalid
       * @since jEdit 3.2pre6
       */
00979       public static SyntaxStyle parseStyle(String str, String family, int size)
            throws IllegalArgumentException
      {
            return SyntaxUtilities.parseStyle(str,family,size,true);
      } //}}}

      //{{{ parseStyle() method
      /**
       * Converts a style string to a style object.
       * @param str The style string
       * @param family Style strings only specify font style, not font family
       * @param size Style strings only specify font style, not font family
       * @param color If false, the styles will be monochrome
       * @exception IllegalArgumentException if the style is invalid
       * @since jEdit 4.0pre4
       * @deprecated use {@link SyntaxUtilities#parseStyle(String,String,int,boolean)}
       */
      @Deprecated
00997       public static SyntaxStyle parseStyle(String str, String family, int size,
            boolean color)
            throws IllegalArgumentException
      {
            return SyntaxUtilities.parseStyle(str,family,size,color);
      } //}}}

      //{{{ getStyleString() method
      /**
       * Converts a style into it's string representation.
       * @param style The style
       */
01009       public static String getStyleString(SyntaxStyle style)
      {
            StringBuilder buf = new StringBuilder();

            if (style.getForegroundColor() != null)
            {
                  buf.append("color:").append(SyntaxUtilities.getColorHexString(style.getForegroundColor()));
            }

            if (style.getBackgroundColor() != null)
            {
                  buf.append(" bgColor:").append(SyntaxUtilities.getColorHexString(style.getBackgroundColor()));
            }

            Font font = style.getFont();
            if (!font.isPlain())
            {
                  buf.append(" style:");
                  if (font.isItalic())
                        buf.append('i');
                  if (font.isBold())
                        buf.append('b');
            }

            return buf.toString();
      } //}}}

      //{{{ loadStyles() method
      /**
       * Loads the syntax styles from the properties, giving them the specified
       * base font family and size.
       * @param family The font family
       * @param size The font size
       * @since jEdit 3.2pre6
       * @deprecated use {@link SyntaxUtilities#loadStyles(String,int)}
       */
      @Deprecated
01046       public static SyntaxStyle[] loadStyles(String family, int size)
      {
            return SyntaxUtilities.loadStyles(family,size,true);
      }

      /**
       * Loads the syntax styles from the properties, giving them the specified
       * base font family and size.
       * @param family The font family
       * @param size The font size
       * @param color If false, the styles will be monochrome
       * @since jEdit 4.0pre4
       * @deprecated use {@link SyntaxUtilities#loadStyles(String,int,boolean)}
       */
      @Deprecated
01061       public static SyntaxStyle[] loadStyles(String family, int size, boolean color)
      {
            return SyntaxUtilities.loadStyles(family, size, color);
      } //}}}

      //}}}

      //{{{ Loading, saving window geometry

      //{{{ loadGeometry() method
      /**
       * Loads a windows's geometry from the properties.
       * The geometry is loaded from the <code><i>name</i>.x</code>,
       * <code><i>name</i>.y</code>, <code><i>name</i>.width</code> and
       * <code><i>name</i>.height</code> properties.
       *
       * @param win The window to load geometry from
       * @param parent The parent frame to be relative to.
       * @param name The name of the window
       */
01081       public static void loadGeometry(Window win, Container parent, String name )
      {
            Dimension size = win.getSize();
            int width = jEdit.getIntegerProperty(name + ".width", size.width);
            int height = jEdit.getIntegerProperty(name + ".height", size.height);
            int x = jEdit.getIntegerProperty(name + ".x",50);
            int y = jEdit.getIntegerProperty(name + ".y",50);
            if(parent != null)
            {
                  Point location = parent.getLocation();
                  x = location.x + x;
                  y = location.y + y;
            }

            int extState = jEdit.getIntegerProperty(name + ".extendedState", Frame.NORMAL);

            Rectangle desired = new Rectangle(x,y,width,height);
            try
            {
                  if(!Debug.DISABLE_MULTIHEAD)
                        adjustForScreenBounds(desired);
            }
            catch(Exception e)
            {
                  /* Workaround for OS X bug. */
                  Log.log(Log.ERROR,GUIUtilities.class,e);
            }

            if(OperatingSystem.isX11() && Debug.GEOMETRY_WORKAROUND)
                  new UnixWorkaround(win,name,desired,extState);
            else
            {
                  win.setBounds(desired);
                  if(win instanceof Frame)
                        ((Frame)win).setExtendedState(extState);
            }

      } //}}}

      //{{{ loadGeometry() method
      /**
       * Loads a windows's geometry from the properties.
       * The geometry is loaded from the <code><i>name</i>.x</code>,
       * <code><i>name</i>.y</code>, <code><i>name</i>.width</code> and
       * <code><i>name</i>.height</code> properties.
       *
       * @param win The window to load geometry from
       * @param name The name of the window
       */
01130       public static void loadGeometry(Window win, String name)
      {
            loadGeometry(win, win.getParent(), name);
      } //}}}

      //{{{ adjustForScreenBounds() method
      /**
       * Gives a rectangle the specified bounds, ensuring it is within the
       * screen bounds.
       * @since jEdit 4.2pre3
       */
01141       public static void adjustForScreenBounds(Rectangle desired)
      {
            // Make sure the window is displayed in visible region
            Rectangle osbounds = OperatingSystem.getScreenBounds(desired);

            if (desired.width > osbounds.width)
            {
                  desired.width = osbounds.width;
            }
            if (desired.x < osbounds.x)
            {
                  desired.x = osbounds.x;
            }
            if (desired.x + desired.width > osbounds.x + osbounds.width)
            {
                  desired.x = osbounds.x + osbounds.width - desired.width;
            }
            if (desired.height > osbounds.height)
            {
                  desired.height = osbounds.height;
            }
            if (desired.y < osbounds.y)
            {
                  desired.y = osbounds.y;
            }
            if (desired.y + desired.height > osbounds.y + osbounds.height)
            {
                  desired.y = osbounds.y + osbounds.height - desired.height;
            }
      } //}}}

      //{{{ UnixWorkaround class
      public static class UnixWorkaround
      {
            Window win;
            String name;
            Rectangle desired;
            Rectangle required;
            long start;
            boolean windowOpened;

            //{{{ UnixWorkaround constructor
            public UnixWorkaround(Window win, String name, Rectangle desired,
                  int extState)
            {
                  this.win = win;
                  this.name = name;
                  this.desired = desired;

                  int adjust_x = jEdit.getIntegerProperty(name + ".dx",0);
                  int adjust_y = jEdit.getIntegerProperty(name + ".dy",0);
                  int adjust_width = jEdit.getIntegerProperty(name + ".d-width",0);
                  int adjust_height = jEdit.getIntegerProperty(name + ".d-height",0);

                  required = new Rectangle(
                        desired.x - adjust_x,
                        desired.y - adjust_y,
                        desired.width - adjust_width,
                        desired.height - adjust_height);

                  Log.log(Log.DEBUG,GUIUtilities.class,"Window " + name
                        + ": desired geometry is " + desired);
                  Log.log(Log.DEBUG,GUIUtilities.class,"Window " + name
                        + ": setting geometry to " + required);

                  start = System.currentTimeMillis();

                  win.setBounds(required);
                  if(win instanceof Frame)
                        ((Frame)win).setExtendedState(extState);

                  win.addComponentListener(new ComponentHandler());
                  win.addWindowListener(new WindowHandler());
            } //}}}

            //{{{ ComponentHandler class
            private class ComponentHandler extends ComponentAdapter
            {
                  //{{{ componentMoved() method
                  @Override
                  public void componentMoved(ComponentEvent evt)
                  {
                        if(System.currentTimeMillis() - start < 1000L)
                        {
                              Rectangle r = win.getBounds();
                              if(!windowOpened && r.equals(required))
                                    return;

                              if(!r.equals(desired))
                              {
                                    Log.log(Log.DEBUG,GUIUtilities.class,
                                          "Window resize blocked: " + win.getBounds());
                                    win.setBounds(desired);
                              }
                        }

                        win.removeComponentListener(this);
                  } //}}}

                  //{{{ componentResized() method
                  @Override
                  public void componentResized(ComponentEvent evt)
                  {
                        if(System.currentTimeMillis() - start < 1000L)
                        {
                              Rectangle r = win.getBounds();
                              if(!windowOpened && r.equals(required))
                                    return;

                              if(!r.equals(desired))
                              {
                                    Log.log(Log.DEBUG,GUIUtilities.class,
                                          "Window resize blocked: " + win.getBounds());
                                    win.setBounds(desired);
                              }
                        }

                        win.removeComponentListener(this);
                  } //}}}
            } //}}}

            //{{{ WindowHandler class
            private class WindowHandler extends WindowAdapter
            {
                  //{{{ windowOpened() method
                  @Override
                  public void windowOpened(WindowEvent evt)
                  {
                        windowOpened = true;

                        Rectangle r = win.getBounds();
                        Log.log(Log.DEBUG,GUIUtilities.class,"Window "
                              + name + ": bounds after opening: " + r);

                        jEdit.setIntegerProperty(name + ".dx",
                              r.x - required.x);
                        jEdit.setIntegerProperty(name + ".dy",
                              r.y - required.y);
                        jEdit.setIntegerProperty(name + ".d-width",
                              r.width - required.width);
                        jEdit.setIntegerProperty(name + ".d-height",
                              r.height - required.height);

                        win.removeWindowListener(this);
                  } //}}}
            } //}}}
      } //}}}

      //{{{ saveGeometry() method
      /**
       * Saves a window's geometry to the properties.
       * The geometry is saved to the <code><i>name</i>.x</code>,
       * <code><i>name</i>.y</code>, <code><i>name</i>.width</code> and
       * <code><i>name</i>.height</code> properties.<br />
       * For Frame's and descendents use {@link #addSizeSaver(Frame,String)} to save the sizes
       * correct even if the Frame is in maximized or iconified state.
       * @param win The window to load geometry from
       * @param name The name of the window
       * @see #addSizeSaver(Frame,String)
       */
01301       public static void saveGeometry(Window win, String name)
      {
            saveGeometry (win, win.getParent(), name);
      } //}}}

      //{{{ saveGeometry() method
      /**
       * Saves a window's geometry to the properties.
       * The geometry is saved to the <code><i>name</i>.x</code>,
       * <code><i>name</i>.y</code>, <code><i>name</i>.width</code> and
       * <code><i>name</i>.height</code> properties.<br />
       * For Frame's and descendents use {@link #addSizeSaver(Frame,Container,String)} to save the sizes
       * correct even if the Frame is in maximized or iconified state.
       * @param win The window to load geometry from
       * @param parent The parent frame to be relative to.
       * @param name The name of the window
       * @see #addSizeSaver(Frame,Container,String)
       */
01319       public static void saveGeometry(Window win, Container parent, String name)
      {
            if(win instanceof Frame)
            {
                  jEdit.setIntegerProperty(name + ".extendedState",
                        ((Frame)win).getExtendedState());
            }

            Rectangle bounds = win.getBounds();
            int x = bounds.x;
            int y = bounds.y;
            if (parent != null)
            {
                  Rectangle parentBounds = parent.getBounds();
                  x -= parentBounds.x;
                  y -= parentBounds.y;
            }
            jEdit.setIntegerProperty(name + ".x",x);
            jEdit.setIntegerProperty(name + ".y",y);
            jEdit.setIntegerProperty(name + ".width", bounds.width);
            jEdit.setIntegerProperty(name + ".height", bounds.height);
      } //}}}

      //{{{ centerOnScreen() method
      /**
       * Centers the given window on the screen. This method is needed because
       * JDK 1.3 does not have a <code>JWindow.setLocationRelativeTo()</code>
       * method.
       * @since jEdit 4.2pre3
       * @deprecated use {@link javax.swing.JWindow#setLocationRelativeTo(java.awt.Component)}
       */
      @Deprecated
01351       public static void centerOnScreen(Window win)
      {
            GraphicsDevice gd = GraphicsEnvironment
                  .getLocalGraphicsEnvironment()
                  .getDefaultScreenDevice();
            Rectangle gcbounds = gd.getDefaultConfiguration().getBounds();
            int x = gcbounds.x + (gcbounds.width - win.getWidth()) / 2;
            int y = gcbounds.y + (gcbounds.height - win.getHeight()) / 2;
            win.setLocation(x,y);
      } //}}}

      //}}}

      //{{{ hideSplashScreen() method
      /**
       * Ensures that the splash screen is not visible. This should be
       * called before displaying any dialog boxes or windows at
       * startup.
       */
01370       public static void hideSplashScreen()
      {
            if(splash != null)
            {
                  splash.dispose();
                  splash = null;
            }
      } //}}}

      //{{{ createMultilineLabel() method
      /**
       * Creates a component that displays a multiple line message. This
       * is implemented by assembling a number of <code>JLabels</code> in
       * a <code>JPanel</code>.
       * @param str The string, with lines delimited by newline
       * (<code>\n</code>) characters.
       * @since jEdit 4.1pre3
       */
01388       public static JComponent createMultilineLabel(String str)
      {
            JPanel panel = new JPanel(new VariableGridLayout(
                  VariableGridLayout.FIXED_NUM_COLUMNS,1,1,1));
            int lastOffset = 0;
            while(true)
            {
                  int index = str.indexOf('\n',lastOffset);
                  if(index == -1)
                        break;
                  else
                  {
                        panel.add(new JLabel(str.substring(lastOffset,index)));
                        lastOffset = index + 1;
                  }
            }

            if(lastOffset != str.length())
                  panel.add(new JLabel(str.substring(lastOffset)));

            return panel;
      } //}}}

      //{{{ requestFocus() method
      /**
       * Focuses on the specified component as soon as the window becomes
       * active.
       * @param win The window
       * @param comp The component
       */
01418       public static void requestFocus(final Window win, final Component comp)
      {
            win.addWindowFocusListener(new WindowAdapter()
            {
                  @Override
                  public void windowGainedFocus(WindowEvent evt)
                  {
                        SwingUtilities.invokeLater(new Runnable()
                        {
                                    public void run()
                                    {
                                          comp.requestFocusInWindow();
                                    }
                        });
                        win.removeWindowFocusListener(this);
                  }
            });
      } //}}}

      //{{{ isPopupTrigger() method
      /**
       * Returns if the specified event is the popup trigger event.
       * This implements precisely defined behavior, as opposed to
       * MouseEvent.isPopupTrigger().
       * @param evt The event
       * @since jEdit 3.2pre8
       */
01445       public static boolean isPopupTrigger(MouseEvent evt)
      {
            return TextAreaMouseHandler.isRightButton(evt.getModifiers());
      } //}}}

      //{{{ isMiddleButton() method
      /**
       * @param modifiers The modifiers flag from a mouse event
       * @since jEdit 4.1pre9
       */
01455       public static boolean isMiddleButton(int modifiers)
      {
            return TextAreaMouseHandler.isMiddleButton(modifiers);
      } //}}}

      //{{{ isRightButton() method
      /**
       * @param modifiers The modifiers flag from a mouse event
       * @since jEdit 4.1pre9
       */
01465       public static boolean isRightButton(int modifiers)
      {
            return TextAreaMouseHandler.isRightButton(modifiers);
      } //}}}

      //{{{ getScreenBounds() method
      /**
       * Returns the screen bounds, taking into account multi-screen
       * environments.
       * @since jEdit 4.3pre18
       */
01476       public static Rectangle getScreenBounds()
      {
            Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().
                  getMaximumWindowBounds();
            GraphicsDevice [] devices = GraphicsEnvironment.
                  getLocalGraphicsEnvironment().getScreenDevices();
            if (devices.length > 1)
            {
                  for (GraphicsDevice device: devices)
                  {
                        for (GraphicsConfiguration config: device.getConfigurations())
                              bounds = bounds.union(config.getBounds());
                  }
            }
            return bounds;
      }

      //{{{ showPopupMenu() method
      /**
       * Shows the specified popup menu, ensuring it is displayed within
       * the bounds of the screen.
       * @param popup The popup menu
       * @param comp The component to show it for
       * @param x The x co-ordinate
       * @param y The y co-ordinate
       * @since jEdit 4.0pre1
       * @see javax.swing.JComponent#setComponentPopupMenu(javax.swing.JPopupMenu) setComponentPopupMenu
       * which works better and is simpler to use: you don't have to write the code to
       * show/hide popups in response to mouse events anymore.
       */
01506       public static void showPopupMenu(JPopupMenu popup, Component comp,
            int x, int y)
      {
            showPopupMenu(popup,comp,x,y,true);
      } //}}}

      //{{{ showPopupMenu() method
      /**
       * Shows the specified popup menu, ensuring it is displayed within
       * the bounds of the screen.
       * @param popup The popup menu
       * @param comp The component to show it for
       * @param x The x co-ordinate
       * @param y The y co-ordinate
       * @param point If true, then the popup originates from a single point;
       * otherwise it will originate from the component itself. This affects
       * positioning in the case where the popup does not fit onscreen.
       *
       * @since jEdit 4.1pre1
       */
01526       public static void showPopupMenu(JPopupMenu popup, Component comp,
            int x, int y, boolean point)
      {
            int offsetX = 0;
            int offsetY = 0;

            int extraOffset = point ? 1 : 0;

            Component win = comp;
            while(!(win instanceof Window || win == null))
            {
                  offsetX += win.getX();
                  offsetY += win.getY();
                  win = win.getParent();
            }

            if(win != null)
            {
                  Dimension size = popup.getPreferredSize();

                  Rectangle screenSize = getScreenBounds();

                  if(x + offsetX + size.width + win.getX() > screenSize.width
                        && x + offsetX + win.getX() >= size.width)
                  {
                        //System.err.println("x overflow");
                        if(point)
                              x -= size.width + extraOffset;
                        else
                              x = win.getWidth() - size.width - offsetX + extraOffset;
                  }
                  else
                  {
                        x += extraOffset;
                  }

                  //System.err.println("y=" + y + ",offsetY=" + offsetY
                  //    + ",size.height=" + size.height
                  //    + ",win.height=" + win.getHeight());
                  if(y + offsetY + size.height + win.getY() > screenSize.height
                        && y + offsetY + win.getY() >= size.height)
                  {
                        if(point)
                              y = win.getHeight() - size.height - offsetY + extraOffset;
                        else
                              y = -size.height - 1;
                  }
                  else
                  {
                        y += extraOffset;
                  }

                  popup.show(comp,x,y);
            }
            else
                  popup.show(comp,x + extraOffset,y + extraOffset);

      } //}}}

      //{{{ isAncestorOf() method
      /**
       * Returns if the first component is an ancestor of the
       * second by traversing up the component hierarchy.
       *
       * @param comp1 The ancestor
       * @param comp2 The component to check
       * @since jEdit 4.1pre5
       */
01594       public static boolean isAncestorOf(Component comp1, Component comp2)
      {
            while(comp2 != null)
            {
                  if(comp1 == comp2)
                        return true;
                  else
                        comp2 = comp2.getParent();
            }

            return false;
      } //}}}

      //{{{ getParentDialog() method
      /**
       * Traverses the given component's parent tree looking for an
       * instance of JDialog, and return it. If not found, return null.
       * @param c The component
       */
01613       public static JDialog getParentDialog(Component c)
      {
            return (JDialog) SwingUtilities.getAncestorOfClass(JDialog.class, c);
      } //}}}

      //{{{ getComponentParent() method
      /**
       * Finds a parent of the specified component.
       * @param comp The component
       * @param clazz Looks for a parent with this class (exact match, not
       * derived).
       * @since jEdit 4.2pre1
       */
01626       public static Component getComponentParent(Component comp, Class clazz)
      {
            while(true)
            {
                  if(comp == null)
                        break;

                  if(comp instanceof JComponent)
                  {
                        Component real = (Component)((JComponent)comp)
                              .getClientProperty("KORTE_REAL_FRAME");
                        if(real != null)
                              comp = real;
                  }

                  if(comp.getClass().equals(clazz))
                        return comp;
                  else if(comp instanceof JPopupMenu)
                        comp = ((JPopupMenu)comp).getInvoker();
                  else if(comp instanceof FloatingWindowContainer)
                  {
                        comp = ((FloatingWindowContainer)comp)
                              .getDockableWindowManager();
                  }
                  else
                        comp = comp.getParent();
            }
            return null;
      } //}}}

      //{{{ setEnabledRecursively() method
      /**
       * Call setEnabled() recursively on the container and its descendants.
       * @param c The container
       * @param enabled The enabled state to set
       * @since jEdit 4.3pre17
       */
01663       public static void setEnabledRecursively(Container c, boolean enabled)
      {
            for (Component child: c.getComponents())
            {
                  if (child instanceof Container)
                        setEnabledRecursively((Container)child, enabled);
                  else
                        child.setEnabled(enabled);
            }
            c.setEnabled(enabled);
      } //}}}

      //{{{ getView() method
      /**
       * Finds the view parent of the specified component.
       * @since jEdit 4.0pre2
       */
01680       public static View getView(Component comp)
      {
            return (View)getComponentParent(comp,View.class);
      } //}}}

      //{{{ addSizeSaver() method
      /**
      * Adds a SizeSaver to the specified Frame. For non-Frame's use {@link #saveGeometry(Window,String)}
       *
       * @param frame The Frame for which to save the size
       * @param name The prefix for the settings
       * @since jEdit 4.3pre6
       * @see #saveGeometry(Window,String)
       */
01694       public static void addSizeSaver(Frame frame, String name)
      {
            addSizeSaver(frame,frame.getParent(),name);
      } //}}}

      //{{{ addSizeSaver() method
      /**
       * Adds a SizeSaver to the specified Frame. For non-Frame's use {@link #saveGeometry(Window,Container,String)}
       *
       * @param frame The Frame for which to save the size
       * @param parent The parent to be relative to
       * @param name The prefix for the settings
       * @since jEdit 4.3pre7
       * @see #saveGeometry(Window,Container,String)
       */
01709       public static void addSizeSaver(Frame frame, Container parent, String name)
      {
            SizeSaver ss = new SizeSaver(frame,parent,name);
            frame.addWindowStateListener(ss);
            frame.addComponentListener(ss);
      } //}}}

      //{{{ initContinuousLayout() method
      /**
       * Init the continuous layout flag using the jEdit's property
       * appearance.continuousLayout
       *
       * @param split the split. It must never be null
       * @since jEdit 4.3pre9
       */
01724       public static void initContinuousLayout(JSplitPane split)
      {
            boolean continuousLayout = split.isContinuousLayout();
            if (continuousLayout != jEdit.getBooleanProperty("appearance.continuousLayout"))
                  split.setContinuousLayout(!continuousLayout);
      } //}}}

      //{{{ Package-private members

      //{{{ initializeDeprecatedIcons() method
      /**
       * Initializes a list of mappings between old icon names and new names
       */
01737       private static void initializeDeprecatedIcons()
      {
            deprecatedIcons.put("File.png",       "16x16/mimetypes/text-x-generic.png");
            deprecatedIcons.put("Folder.png",     "16x16/places/folder.png");
            deprecatedIcons.put("OpenFolder.png", "16x16/status/folder-open.png");
            deprecatedIcons.put("OpenFile.png",   "16x16/actions/edit-select-all.png");
            deprecatedIcons.put("ReloadSmall.png","16x16/actions/view-refresh.png");
            deprecatedIcons.put("DriveSmall.png", "16x16/devices/drive-harddisk.png");
            deprecatedIcons.put("New.png",        "22x22/actions/document-new.png");
            deprecatedIcons.put("NewDir.png",     "22x22/actions/folder-new.png");
            deprecatedIcons.put("Reload.png",     "22x22/actions/view-refresh.png");
            deprecatedIcons.put("Load.png",       "22x22/places/plugins.png");
            deprecatedIcons.put("Save.png",       "22x22/actions/document-save.png");
            deprecatedIcons.put("SaveAs.png",     "22x22/actions/document-save-as.png");
            deprecatedIcons.put("SaveAll.png",    "22x22/actions/document-save-all.png");
            deprecatedIcons.put("Open.png",       "22x22/actions/document-open.png");
            deprecatedIcons.put("Print.png",      "22x22/actions/document-print.png");
            deprecatedIcons.put("Drive.png",      "22x22/devices/drive-harddisk.png");
            deprecatedIcons.put("Clear.png",      "22x22/actions/edit-clear.png");
            deprecatedIcons.put("Run.png",        "22x22/actions/application-run.png");
            deprecatedIcons.put("RunAgain.png",   "22x22/actions/application-run-again.png");
            deprecatedIcons.put("RunToBuffer.png",  "22x22/actions/run-to-buffer.png");
            deprecatedIcons.put("CopyToBuffer.png", "22x22/actions/copy-to-buffer.png");
            deprecatedIcons.put("Plus.png",       "22x22/actions/list-add.png");
            deprecatedIcons.put("Minus.png",      "22x22/actions/list-remove.png");
            deprecatedIcons.put("Find.png",       "22x22/actions/edit-find.png");
            deprecatedIcons.put("FindAgain.png",  "22x22/actions/edit-find-next.png");
            deprecatedIcons.put("FindInDir.png",  "22x22/actions/edit-find-in-folder.png");
            deprecatedIcons.put("Parse.png",      "22x22/actions/document-reload2.png");
            deprecatedIcons.put("Delete.png",     "22x22/actions/edit-delete.png");
            deprecatedIcons.put("Paste.png",      "22x22/actions/edit-paste.png");
            deprecatedIcons.put("Cut.png",        "22x22/actions/edit-cut.png");
            deprecatedIcons.put("Copy.png",       "22x22/actions/edit-copy.png");
            deprecatedIcons.put("Undo.png",       "22x22/actions/edit-undo.png");
            deprecatedIcons.put("Redo.png",       "22x22/actions/edit-redo.png");
            deprecatedIcons.put("CurrentDir.png", "22x22/status/folder-visiting.png");
            deprecatedIcons.put("ParentDir.png",  "22x22/actions/go-parent.png");
            deprecatedIcons.put("PageSetup.png",  "22x22/actions/printer-setup.png");
            deprecatedIcons.put("Plugins.png",    "22x22/apps/system-installer.png");
            deprecatedIcons.put("Floppy.png",     "22x22/devices/media-floppy.png");
            deprecatedIcons.put("Stop.png",       "22x22/actions/process-stop.png");
            deprecatedIcons.put("Cancel.png",     "22x22/actions/process-stop.png");
            deprecatedIcons.put("Home.png",       "22x22/actions/go-home.png");
            deprecatedIcons.put("Help.png",       "22x22/apps/help-browser.png");
            deprecatedIcons.put("Properties.png", "22x22/actions/document-properties.png");
            deprecatedIcons.put("Preferences.png","22x22/categories/preferences-system.png");
            deprecatedIcons.put("ZoomIn.png",     "22x22/actions/zoom-in.png");
            deprecatedIcons.put("ZoomOut.png",    "22x22/actions/zoom-out.png");
            deprecatedIcons.put("BrokenImage.png","22x22/status/image-missing.png");
            deprecatedIcons.put("AdjustWidth.png","22x22/actions/resize-horisontal.png");
            deprecatedIcons.put("ToolbarMenu.gif","ToolbarMenu.gif");

            deprecatedIcons.put("Play.png","22x22/actions/media-playback-start.png");
            deprecatedIcons.put("Pause.png","22x22/actions/media-playback-pause.png");

            deprecatedIcons.put("MultipleResults.png", "22x22/actions/edit-find-multiple.png");
            deprecatedIcons.put("SingleResult.png",    "22x22/actions/edit-find-single.png");

            deprecatedIcons.put("NextFile.png",    "22x22/go-last.png");
            deprecatedIcons.put("PreviousFile.png","22x22/go-first.png");

            deprecatedIcons.put("closebox.gif",   "10x10/actions/close.png");
            deprecatedIcons.put("normal.gif",   "10x10/status/document-unmodified.png");
            deprecatedIcons.put("readonly.gif",   "10x10/emblem/emblem-readonly.png");
            deprecatedIcons.put("dirty.gif",    "10x10/status/document-modified.png");
            deprecatedIcons.put("new.gif",    "10x10/status/document-new.png");

            deprecatedIcons.put("ArrowU.png", "22x22/actions/go-up.png");
            deprecatedIcons.put("ArrowR.png", "22x22/actions/go-next.png");
            deprecatedIcons.put("ArrowD.png", "22x22/actions/go-down.png");
            deprecatedIcons.put("ArrowL.png", "22x22/actions/go-previous.png");
            deprecatedIcons.put("arrow1.png", "16x16/actions/group-expand.png");
            deprecatedIcons.put("arrow2.png", "16x16/actions/group-collapse.png");

            deprecatedIcons.put("NewView.png", "22x22/actions/window-new.png");
            deprecatedIcons.put("UnSplit.png", "22x22/actions/window-unsplit.png");
            deprecatedIcons.put("SplitVertical.png", "22x22/actions/window-split-vertical.png");
            deprecatedIcons.put("SplitHorizontal.png", "22x22/actions/window-split-horizontal.png");

            deprecatedIcons.put("ButtonProperties.png", "22x22/actions/document-properties.png");

      }
      //}}}

      //{{{ init() method
      static void init()
      {
            initializeDeprecatedIcons();

            // Load the icon theme but fallback on the old icons
            String theme = jEdit.getProperty("icon-theme", "tango");
            Log.log(Log.DEBUG, GUIUtilities.class, "Icon theme set to: "+theme);
            setIconPath("jeditresource:/org/gjt/sp/jedit/icons/themes/" + theme + '/');
            Log.log(Log.DEBUG, GUIUtilities.class, "Loading icon theme from: "+iconPath);

            // don't do this in static{} since we need jEdit.initMisc()
            // run first so we have the jeditresource: protocol
            NEW_BUFFER_ICON = loadIcon("new.gif");
            DIRTY_BUFFER_ICON = loadIcon("dirty.gif");
            READ_ONLY_BUFFER_ICON = loadIcon("readonly.gif");
            NORMAL_BUFFER_ICON = loadIcon("normal.gif");
            WINDOW_ICON = loadIcon(jEdit.getProperty("logo.icon.medium"));
      } //}}}

      //{{{ showSplashScreen() method
      static void showSplashScreen()
      {
            splash = new SplashScreen();
      } //}}}

      //{{{ advanceSplashProgress() method
      static void advanceSplashProgress()
      {
            if(splash != null)
                  splash.advance();
      } //}}}

      //{{{ advanceSplashProgress() method
      static void advanceSplashProgress(String label)
      {
            if(splash != null)
                  splash.advance(label);
      } //}}}

      //}}}

      //{{{ Private members
      private static SplashScreen splash;
      private static Map<String, Icon> icons;
      private static String iconPath = "jeditresource:/org/gjt/sp/jedit/icons/themes/";
      private static final String defaultIconPath = "jeditresource:/org/gjt/sp/jedit/icons/themes/";
      private static final HashMap<String, String> deprecatedIcons = new HashMap<String, String>();

      //{{{ _loadMenuItem() method
      private static JMenuItem _loadMenuItem(String name, ActionContext context, boolean setMnemonic)
      {

            String label = jEdit.getProperty(name + ".label");
            if (label == null)
            {
                  label = name;
            }
            char mnemonic;
            int index = label.indexOf('$');
            if (index != -1 && label.length() - index > 1)
            {
                  mnemonic = Character.toLowerCase(label.charAt(index + 1));
                  label = label.substring(0, index).concat(label.substring(++index));
            }
            else
            {
                  mnemonic = '\0';
            }
            JMenuItem mi;
            if (jEdit.getBooleanProperty(name + ".toggle"))
            {
                  mi = new EnhancedCheckBoxMenuItem(label, name, context);
            }
            else
            {
                  mi = new EnhancedMenuItem(label, name, context);
            }
            if (!OperatingSystem.isMacOS() && setMnemonic && mnemonic != '\0')
            {
                  mi.setMnemonic(mnemonic);
            }
            Icon itemIcon = loadIcon(jEdit.getProperty(name + ".icon.small"));
            if(itemIcon != null)
            {
                  mi.setIcon(itemIcon);
            }

            return mi;
      } //}}}

      private GUIUtilities() {}
      //}}}

      //{{{ Inner classes

      //{{{ SizeSaver class
      /**
       * A combined ComponentListener and WindowStateListener to continually save a Frames size.<br />
       * For non-Frame's use {@link GUIUtilities#saveGeometry(Window,String)}
       *
       * @author Björn Kautler
       * @version $Id: GUIUtilities.java 16406 2009-10-22 20:42:36Z shlomy $
       * @since jEdit 4.3pre6
       * @see GUIUtilities#saveGeometry(Window,Container,String)
       */
01927       private static class SizeSaver extends ComponentAdapter implements WindowStateListener
      {
            private Frame frame;
            private Container parent;
            private String name;

            //{{{ SizeSaver constructors
            /**
             * Constructs a new SizeSaver.
             *
             * @param frame The Frame for which to save the size
             * @param parent The parent to be relative to.
             * @param name The prefix for the settings
             */
01941             SizeSaver(Frame frame, Container parent, String name)
            {
                  if (frame == null || name == null)
                  {
                        throw new NullPointerException();
                  }
                  this.frame = frame;
                  this.parent = parent;
                  this.name = name;
            } //}}}

            //{{{ windowStateChanged() method
            public void windowStateChanged(WindowEvent wse)
            {
                  int extendedState = wse.getNewState();
                  jEdit.setIntegerProperty(name + ".extendedState",extendedState);
                  Rectangle bounds = frame.getBounds();
                  save(extendedState, bounds);
            } //}}}

            //{{{ save() method
            private void save(int extendedState, Rectangle bounds)
            {
                  switch (extendedState)
                  {
                        case Frame.MAXIMIZED_VERT:
                              jEdit.setIntegerProperty(name + ".x",bounds.x);
                              jEdit.setIntegerProperty(name + ".width",bounds.width);
                              break;

                        case Frame.MAXIMIZED_HORIZ:
                              jEdit.setIntegerProperty(name + ".y",bounds.y);
                              jEdit.setIntegerProperty(name + ".height",bounds.height);
                              break;

                        case Frame.NORMAL:
                              saveGeometry(frame,parent,name );
                              break;
                  }
            } //}}}

            //{{{ componentResized() method
            @Override
            public void componentResized(ComponentEvent ce)
            {
                  componentMoved(ce);
            } //}}}

            //{{{ componentMoved() method
            @Override
            public void componentMoved(ComponentEvent ce)
            {
                  final Rectangle bounds = frame.getBounds();
                  final Runnable sizeSaver = new Runnable()
                  {
                        public void run()
                        {
                              int extendedState = frame.getExtendedState();
                              save(extendedState, bounds);
                        }
                  };
                  new Thread("Sizesavingdelay")
                  {
                        @Override
                        public void run()
                        {
                              try
                              {
                                    Thread.sleep(500L);
                              }
                              catch (InterruptedException ie)
                              {
                              }
                              SwingUtilities.invokeLater(sizeSaver);
                        }
                  }.start();
            } //}}}
      } //}}}

      //}}}
}

Generated by  Doxygen 1.6.0   Back to index