|
What this is
Other links
The source code/* * 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 javax.swing.*; import java.awt.*; import java.awt.event.*; import java.net.*; import java.util.*; import org.gjt.sp.jedit.browser.*; import org.gjt.sp.jedit.gui.*; import org.gjt.sp.jedit.menu.*; import org.gjt.sp.jedit.syntax.SyntaxStyle; import org.gjt.sp.jedit.syntax.Token; import org.gjt.sp.util.Log; //}}} /** * Various GUI functions.
GUIUtilities.loadIcon("new.gif");
* instead.
*/
public static Icon NEW_BUFFER_ICON;
/**
* @deprecated Use GUIUtilities.loadIcon("dirty.gif");
* instead.
*/
public static Icon DIRTY_BUFFER_ICON;
/**
* @deprecated Use GUIUtilities.loadIcon("readonly.gif");
* instead.
*/
public static Icon READ_ONLY_BUFFER_ICON;
/**
* @deprecated Use GUIUtilities.loadIcon("normal.gif");
* instead.
*/
public static Icon NORMAL_BUFFER_ICON;
/**
* @deprecated Use GUIUtilities.loadIcon("jedit-icon.gif");
* instead.
*/
public static Icon WINDOW_ICON;
//}}}
//{{{ Icon methods
//{{{ setIconPath() method
/**
* Sets the path where jEdit looks for icons.
* @since jEdit 4.2pre5
*/
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
*/
public static Icon loadIcon(String iconName)
{
if(icons == null)
icons = new Hashtable();
// check if there is a cached version first
Icon icon = (Icon)icons.get(iconName);
if(icon != null)
return icon;
// get the icon
if(MiscUtilities.isURL(iconName))
{
icon = new ImageIcon(iconName.substring(5));
}
else
{
try
{
URL url = new URL(iconPath + iconName);
icon = new ImageIcon(url);
}
catch(Exception e)
{
try
{
URL url = new URL(defaultIconPath + iconName);
icon = new ImageIcon(url);
}
catch(Exception ex)
{
Log.log(Log.ERROR,GUIUtilities.class,
"Icon not found: " + iconName);
Log.log(Log.ERROR,GUIUtilities.class,ex);
return null;
}
}
}
icons.put(iconName,icon);
return icon;
} //}}}
//{{{ getEditorIcon() method
/**
* Returns the default editor window image.
*/
public static Image getEditorIcon()
{
return ((ImageIcon)loadIcon("jedit-icon.gif")).getImage();
} //}}}
//{{{ getPluginIcon() method
/**
* Returns the default plugin window image.
*/
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
*/
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
*/
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())
{
mbar.add(loadMenu(context,st.nextToken()));
}
return mbar;
} //}}}
//{{{ loadMenu() method
/**
* Creates a menu. The menu label is set from the
* name.label property. The menu contents is taken
* from the name property, which is a whitespace
* separated list of action names. An action name of -
* inserts a separator in the menu.
* @param name The menu name
* @see #loadMenuItem(String)
* @since jEdit 2.6pre2
*/
public static JMenu loadMenu(String name)
{
return loadMenu(jEdit.getActionContext(),name);
} //}}}
//{{{ loadMenu() method
/**
* Creates a menu. The menu label is set from the
* name.label property. The menu contents is taken
* from the name property, which is a whitespace
* separated list of action names. An action name of -
* inserts a separator in the menu.
* @param context An action context; either
* jEdit.getActionContext() or
* VFSBrowser.getActionContext() .
* @param name The menu name
* @see #loadMenuItem(String)
* @since jEdit 4.2pre1
*/
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
*/
public static JPopupMenu loadPopupMenu(String name)
{
return loadPopupMenu(jEdit.getActionContext(),name);
} //}}}
//{{{ loadPopupMenu() method
/**
* Creates a popup menu.
* @param context An action context; either
* jEdit.getActionContext() or
* VFSBrowser.getActionContext() .
* @param name The menu name
* @since jEdit 4.2pre1
*/
public static JPopupMenu loadPopupMenu(ActionContext context, String name)
{
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));
}
}
return menu;
} //}}}
//{{{ loadMenuItem() method
/**
* Creates a menu item. The menu item is bound to the action named by
* name 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
*/
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
*/
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
* jEdit.getActionContext() or
* VFSBrowser.getActionContext() .
* @param name The menu item name
* @param setMnemonic True if the menu item should have a mnemonic
* @since jEdit 4.2pre1
*/
public static JMenuItem loadMenuItem(ActionContext context, String name,
boolean setMnemonic)
{
if(name.startsWith("%"))
return loadMenu(context,name.substring(1));
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);
return mi;
} //}}}
//{{{ loadToolBar() method
/**
* Creates a toolbar.
* @param name The toolbar name
* @since jEdit 4.2pre2
*/
public static Box loadToolBar(String name)
{
return loadToolBar(jEdit.getActionContext(),name);
} //}}}
//{{{ loadToolBar() method
/**
* Creates a toolbar.
* @param context An action context; either
* jEdit.getActionContext() or
* VFSBrowser.getActionContext() .
* @param name The toolbar name
* @since jEdit 4.2pre2
*/
public static Box loadToolBar(ActionContext context, String name)
{
Box toolBar = new Box(BoxLayout.X_AXIS);
String buttons = jEdit.getProperty(name);
if(buttons != null)
{
StringTokenizer st = new StringTokenizer(buttons);
while(st.hasMoreTokens())
{
String button = st.nextToken();
if(button.equals("-"))
toolBar.add(Box.createHorizontalStrut(12));
else
{
JButton b = loadToolButton(context,button);
if(b != null)
toolBar.add(b);
}
}
}
toolBar.add(Box.createGlue());
return toolBar;
} //}}}
//{{{ loadToolButton() method
/**
* Loads a tool bar button. The tooltip is constructed from
* the name.label and
* name.shortcut properties and the icon is loaded
* from the resource named '/org/gjt/sp/jedit/icons/' suffixed
* with the value of the name.icon property.
* @param name The name of the button
*/
public static EnhancedButton loadToolButton(String name)
{
return loadToolButton(jEdit.getActionContext(),name);
} //}}}
//{{{ loadToolButton() method
/**
* Loads a tool bar button. The tooltip is constructed from
* the name.label and
* name.shortcut properties and the icon is loaded
* from the resource named '/org/gjt/sp/jedit/icons/' suffixed
* with the value of the name.icon property.
* @param context An action context; either
* jEdit.getActionContext() or
* VFSBrowser.getActionContext() .
* @param name The name of the button
* @since jEdit 4.2pre1
*/
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("BrokenImage.png");
else
{
icon = loadIcon(iconName);
if(icon == null)
icon = loadIcon("BrokenImage.png");
}
String toolTip = prettifyMenuLabel(label);
String shortcut1 = jEdit.getProperty(name + ".shortcut");
String shortcut2 = jEdit.getProperty(name + ".shortcut2");
if(shortcut1 != null || shortcut2 != null)
{
toolTip = toolTip + " ("
+ (shortcut1 != null
? shortcut1 : "")
+ ((shortcut1 != null && shortcut2 != null)
? " or " : "")
+ (shortcut2 != null
? shortcut2
: "") + ")";
}
return new EnhancedButton(icon,toolTip,name,context);
} //}}}
//{{{ prettifyMenuLabel() method
/**
* `Prettifies' a menu item label by removing the `$' sign. This
* can be used to process the contents of an action.label
* property.
*/
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;
} //}}}
//}}}
//{{{ Canned dialog boxes
//{{{ message() method
/**
* Displays a dialog box.
* The title of the dialog is fetched from
* the name.title property. The message is fetched
* from the name.message property. The message
* is formatted by the property manager with args 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
*/
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 name.title property. The message is fetched
* from the name.message property. The message
* is formatted by the property manager with args 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
*/
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 name.title property. The message is fetched
* from the name.message 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
*/
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 name.title property. The message is fetched
* from the name.message 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
*/
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 name.title property. The message is fetched
* from the name.message 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
*/
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 name.title property. The message is fetched
* from the name.message 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
*/
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
* name.title property. The message is fetched
* from the name.message 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
*/
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);
} //}}}
//{{{ showVFSFileDialog() method
/**
* 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
*/
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);
String[] selectedFiles = fileChooser.getSelectedFiles();
if(selectedFiles == null)
return null;
return selectedFiles;
} //}}}
//}}}
//{{{ 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 java.awt.Color class) or a hex color value
* prefixed with `#', for example `#ff0088'.
* @param name The color name
*/
public static Color parseColor(String name)
{
return parseColor(name, Color.black);
} //}}}
//{{{ parseColor() method
public static Color parseColor(String name, Color defaultColor)
{
if(name == null)
return defaultColor;
else if(name.startsWith("#"))
{
try
{
return Color.decode(name);
}
catch(NumberFormatException nf)
{
return defaultColor;
}
}
else if("red".equals(name))
return Color.red;
else if("green".equals(name))
return Color.green;
else if("blue".equals(name))
return Color.blue;
else if("yellow".equals(name))
return Color.yellow;
else if("orange".equals(name))
return Color.orange;
else if("white".equals(name))
return Color.white;
else if("lightGray".equals(name))
return Color.lightGray;
else if("gray".equals(name))
return Color.gray;
else if("darkGray".equals(name))
return Color.darkGray;
else if("black".equals(name))
return Color.black;
else if("cyan".equals(name))
return Color.cyan;
else if("magenta".equals(name))
return Color.magenta;
else if("pink".equals(name))
return Color.pink;
else
return 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
*/
public static String getColorHexString(Color c)
{
String colString = Integer.toHexString(c.getRGB() & 0xffffff);
return "#000000".substring(0,7 - colString.length()).concat(colString);
} //}}}
//{{{ 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
*/
public static SyntaxStyle parseStyle(String str, String family, int size)
throws IllegalArgumentException
{
return 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
*/
public static SyntaxStyle parseStyle(String str, String family, int size,
boolean color)
throws IllegalArgumentException
{
Color fgColor = Color.black;
Color bgColor = null;
boolean italic = false;
boolean bold = false;
StringTokenizer st = new StringTokenizer(str);
while(st.hasMoreTokens())
{
String s = st.nextToken();
if(s.startsWith("color:"))
{
if(color)
fgColor = GUIUtilities.parseColor(s.substring(6), Color.black);
}
else if(s.startsWith("bgColor:"))
{
if(color)
bgColor = GUIUtilities.parseColor(s.substring(8), null);
}
else if(s.startsWith("style:"))
{
for(int i = 6; i < s.length(); i++)
{
if(s.charAt(i) == 'i')
italic = true;
else if(s.charAt(i) == 'b')
bold = true;
else
throw new IllegalArgumentException(
"Invalid style: " + s);
}
}
else
throw new IllegalArgumentException(
"Invalid directive: " + s);
}
return new SyntaxStyle(fgColor,bgColor,
new Font(family,
(italic ? Font.ITALIC : 0) | (bold ? Font.BOLD : 0),
size));
} //}}}
//{{{ getStyleString() method
/**
* Converts a style into it's string representation.
* @param style The style
*/
public static String getStyleString(SyntaxStyle style)
{
StringBuffer buf = new StringBuffer();
if(style.getForegroundColor() != null)
{
buf.append("color:" + getColorHexString(style.getForegroundColor()));
}
if(style.getBackgroundColor() != null)
{
buf.append(" bgColor:" + getColorHexString(style.getBackgroundColor()));
}
if(!style.getFont().isPlain())
{
buf.append(" style:" + (style.getFont().isItalic() ? "i" : "")
+ (style.getFont().isBold() ? "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
*/
public static SyntaxStyle[] loadStyles(String family, int size)
{
return loadStyles(family,size,true);
} //}}}
//{{{ 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
* @param color If false, the styles will be monochrome
* @since jEdit 4.0pre4
*/
public static SyntaxStyle[] loadStyles(String family, int size, boolean color)
{
SyntaxStyle[] styles = new SyntaxStyle[Token.ID_COUNT];
// start at 1 not 0 to skip Token.NULL
for(int i = 1; i < styles.length; i++)
{
try
{
String styleName = "view.style."
+ Token.tokenToString((byte)i)
.toLowerCase();
styles[i] = GUIUtilities.parseStyle(
jEdit.getProperty(styleName),
family,size,color);
}
catch(Exception e)
{
Log.log(Log.ERROR,GUIUtilities.class,e);
}
}
return styles;
} //}}}
//}}}
//{{{ Loading, saving window geometry
//{{{ loadGeometry() method
/**
* Loads a windows's geometry from the properties.
* The geometry is loaded from the name.x ,
* name.y , name.width and
* name.height properties.
*
* @param win The window
* @param name The window name
*/
public static void loadGeometry(Window win, String name)
{
int x, y, width, height;
Dimension size = win.getSize();
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
Rectangle gcbounds = gd.getDefaultConfiguration().getBounds();
x = gcbounds.x;
y = gcbounds.y;
width = jEdit.getIntegerProperty(name + ".width",size.width);
height = jEdit.getIntegerProperty(name + ".height",size.height);
Component parent = win.getParent();
if(parent == null)
{
x += (gcbounds.width - width) / 2;
y += (gcbounds.height - height) / 2;
}
else
{
Rectangle bounds = parent.getBounds();
x += bounds.x + (bounds.width - width) / 2;
y += bounds.y + (bounds.height - height) / 2;
}
x = jEdit.getIntegerProperty(name + ".x",x);
y = jEdit.getIntegerProperty(name + ".y",y);
int extState = jEdit.getIntegerProperty(name + ".extendedState", 0);
Rectangle desired = new Rectangle(x,y,width,height);
adjustForScreenBounds(desired);
if(OperatingSystem.isX11() && Debug.GEOMETRY_WORKAROUND)
new UnixWorkaround(win,name,desired,extState);
else
{
win.setBounds(desired);
if(win instanceof Frame)
setExtendedState((Frame)win,extState);
}
} //}}}
//{{{ adjustForScreenBounds() method
/**
* Gives a rectangle the specified bounds, ensuring it is within the
* screen bounds.
* @since jEdit 4.2pre3
*/
public static void adjustForScreenBounds(Rectangle desired)
{
// Make sure the window is displayed in visible region
Rectangle osbounds = OperatingSystem.getScreenBounds(desired);
if(desired.x < osbounds.x || desired.x+desired.width
> desired.x + osbounds.width)
{
if (desired.width > osbounds.width)
desired.width = osbounds.width;
desired.x = (osbounds.width - desired.width) / 2;
}
if(desired.y < osbounds.y || desired.y+desired.height
> osbounds.y + osbounds.height)
{
if (desired.height >= osbounds.height)
desired.height = osbounds.height;
desired.y = (osbounds.height - desired.height) / 2;
}
} //}}}
//{{{ UnixWorkaround class
static class UnixWorkaround
{
Window win;
String name;
Rectangle desired;
Rectangle required;
long start;
boolean windowOpened;
//{{{ UnixWorkaround constructor
UnixWorkaround(Window win, String name, Rectangle desired,
int extState)
{
this.win = win;
this.name = name;
this.desired = desired;
int adjust_x, adjust_y, adjust_width, adjust_height;
adjust_x = jEdit.getIntegerProperty(name + ".dx",0);
adjust_y = jEdit.getIntegerProperty(name + ".dy",0);
adjust_width = jEdit.getIntegerProperty(name + ".d-width",0);
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)
setExtendedState((Frame)win,extState);
win.addComponentListener(new ComponentHandler());
win.addWindowListener(new WindowHandler());
} //}}}
//{{{ ComponentHandler class
class ComponentHandler extends ComponentAdapter
{
//{{{ componentMoved() method
public void componentMoved(ComponentEvent evt)
{
if(System.currentTimeMillis() - start < 1000)
{
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
public void componentResized(ComponentEvent evt)
{
if(System.currentTimeMillis() - start < 1000)
{
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
class WindowHandler extends WindowAdapter
{
//{{{ windowOpened() method
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 name.x ,
* name.y , name.width and
* name.height properties.
* @param win The window
* @param name The window name
*/
public static void saveGeometry(Window win, String name)
{
if(win instanceof Frame)
{
jEdit.setIntegerProperty(name + ".extendedState",
getExtendedState((Frame)win));
}
Rectangle bounds = win.getBounds();
jEdit.setIntegerProperty(name + ".x",bounds.x);
jEdit.setIntegerProperty(name + ".y",bounds.y);
jEdit.setIntegerProperty(name + ".width",bounds.width);
jEdit.setIntegerProperty(name + ".height",bounds.height);
} //}}}
//{{{ getExtendedState() method
/**
* On Java 1.4, calls Frame.getExtendedState() .
* On Java 1.3, returns 0.
* @since jEdit 4.2pre1
*/
public static int getExtendedState(Frame frame)
{
if(OperatingSystem.hasJava14())
{
try
{
java.lang.reflect.Method meth =
Frame.class.getMethod("getExtendedState",
new Class[0]);
Integer extState = (Integer)meth.invoke(frame,
new Object[0]);
return extState.intValue();
}
catch(Exception e)
{
Log.log(Log.ERROR,GUIUtilities.class,e);
}
}
return 0;
} //}}}
//{{{ setExtendedState() method
/**
* On Java 1.4, calls Frame.setExtendedState() .
* On Java 1.3, does nothing.
* @since jEdit 4.2pre1
*/
public static void setExtendedState(Frame frame, int extState)
{
if(OperatingSystem.hasJava14())
{
try
{
java.lang.reflect.Method meth =
Frame.class.getMethod("setExtendedState",
new Class[] {int.class});
meth.invoke(frame, new Object[] {
new Integer(extState)});
}
catch(Exception e)
{
Log.log(Log.ERROR,GUIUtilities.class,e);
}
}
} //}}}
//{{{ centerOnScreen() method
/**
* Centers the given window on the screen. This method is needed because
* JDK 1.3 does not have a JWindow.setLocationRelativeTo()
* method.
* @since jEdit 4.2pre3
*/
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.
*/
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 JLabels in
* a JPanel .
* @param str The string, with lines delimited by newline
* (\n ) characters.
* @since jEdit 4.1pre3
*/
public static JComponent createMultilineLabel(String str)
{
JPanel panel = new JPanel(new VariableGridLayout(
VariableGridLayout.FIXED_NUM_COLUMNS,1,1,1));
int lastOffset = 0;
for(;;)
{
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
*/
public static void requestFocus(final Window win, final Component comp)
{
win.addWindowListener(new WindowAdapter()
{
public void windowActivated(WindowEvent evt)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
comp.requestFocus();
}
});
win.removeWindowListener(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
*/
public static boolean isPopupTrigger(MouseEvent evt)
{
return isRightButton(evt.getModifiers());
} //}}}
//{{{ isMiddleButton() method
/**
* @param modifiers The modifiers flag from a mouse event
* @since jEdit 4.1pre9
*/
public static boolean isMiddleButton(int modifiers)
{
if (OperatingSystem.isMacOS())
{
if((modifiers & MouseEvent.BUTTON1_MASK) != 0)
return ((modifiers & MouseEvent.ALT_MASK) != 0);
if(!OperatingSystem.hasJava14())
return ((modifiers & MouseEvent.BUTTON3_MASK) != 0);
else
return ((modifiers & MouseEvent.BUTTON2_MASK) != 0);
}
else
return ((modifiers & MouseEvent.BUTTON2_MASK) != 0);
} //}}}
//{{{ isRightButton() method
/**
* @param modifiers The modifiers flag from a mouse event
* @since jEdit 4.1pre9
*/
public static boolean isRightButton(int modifiers)
{
if (OperatingSystem.isMacOS())
{
if((modifiers & MouseEvent.BUTTON1_MASK) != 0)
return ((modifiers & MouseEvent.CTRL_MASK) != 0);
if(!OperatingSystem.hasJava14())
return ((modifiers & MouseEvent.BUTTON2_MASK) != 0);
else
return ((modifiers & MouseEvent.BUTTON3_MASK) != 0);
}
else
return ((modifiers & MouseEvent.BUTTON3_MASK) != 0);
} //}}}
//{{{ 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
*/
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
*/
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 = win.getGraphicsConfiguration()
.getBounds();
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
*/
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
*/
public static JDialog getParentDialog(Component c)
{
Component p = c.getParent();
while (p != null && !(p instanceof JDialog))
p = p.getParent();
return (p instanceof JDialog) ? (JDialog) p : null;
} //}}}
//{{{ 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
*/
public static Component getComponentParent(Component comp, Class clazz)
{
for(;;)
{
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;
} //}}}
//{{{ getView() method
/**
* Finds the view parent of the specified component.
* @since jEdit 4.0pre2
*/
public static View getView(Component comp)
{
return (View)getComponentParent(comp,View.class);
} //}}}
//{{{ Package-private members
//{{{ init() method
static void init()
{
// 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-icon.gif");
} //}}}
//{{{ showSplashScreen() method
static void showSplashScreen()
{
splash = new SplashScreen();
} //}}}
//{{{ advanceSplashProgress() method
static void advanceSplashProgress()
{
if(splash != null)
splash.advance();
} //}}}
//}}}
//{{{ Private members
private static SplashScreen splash;
private static Hashtable icons;
private static String iconPath = "jeditresource:/org/gjt/sp/jedit/icons/";
private static String defaultIconPath = "jeditresource:/org/gjt/sp/jedit/icons/";
private GUIUtilities() {}
//}}}
}
|
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.