PageRenderTime 59ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/GUIUtilities.java

#
Java | 1555 lines | 855 code | 165 blank | 535 comment | 169 complexity | 6e30854ef73f0c57f31f636477f8a55f MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * GUIUtilities.java - Various GUI utility functions
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2004 Slava Pestov
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package org.gjt.sp.jedit;
  23. //{{{ Imports
  24. import java.awt.Color;
  25. import java.awt.Component;
  26. import java.awt.Dimension;
  27. import java.awt.Font;
  28. import java.awt.Frame;
  29. import java.awt.GraphicsConfiguration;
  30. import java.awt.GraphicsDevice;
  31. import java.awt.GraphicsEnvironment;
  32. import java.awt.Image;
  33. import java.awt.Rectangle;
  34. import java.awt.Window;
  35. import java.awt.event.ComponentAdapter;
  36. import java.awt.event.ComponentEvent;
  37. import java.awt.event.MouseEvent;
  38. import java.awt.event.WindowAdapter;
  39. import java.awt.event.WindowEvent;
  40. import java.net.URL;
  41. import java.util.Hashtable;
  42. import java.util.Locale;
  43. import java.util.StringTokenizer;
  44. import javax.swing.*;
  45. import org.gjt.sp.jedit.browser.VFSFileChooserDialog;
  46. import org.gjt.sp.jedit.gui.EnhancedButton;
  47. import org.gjt.sp.jedit.gui.FloatingWindowContainer;
  48. import org.gjt.sp.jedit.gui.SplashScreen;
  49. import org.gjt.sp.jedit.gui.VariableGridLayout;
  50. import org.gjt.sp.jedit.menu.EnhancedCheckBoxMenuItem;
  51. import org.gjt.sp.jedit.menu.EnhancedMenu;
  52. import org.gjt.sp.jedit.menu.EnhancedMenuItem;
  53. import org.gjt.sp.jedit.syntax.SyntaxStyle;
  54. import org.gjt.sp.jedit.syntax.Token;
  55. import org.gjt.sp.util.Log;
  56. //}}}
  57. /**
  58. * Various GUI functions.<p>
  59. *
  60. * The most frequently used members of this class are:
  61. *
  62. * <ul>
  63. * <li>{@link #loadIcon(String)}</li>
  64. * <li>{@link #confirm(Component,String,Object[],int,int)}</li>
  65. * <li>{@link #error(Component,String,Object[])}</li>
  66. * <li>{@link #message(Component,String,Object[])}</li>
  67. * <li>{@link #showPopupMenu(JPopupMenu,Component,int,int)}</li>
  68. * <li>{@link #showVFSFileDialog(View,String,int,boolean)}</li>
  69. * <li>{@link #loadGeometry(Window,String)}</li>
  70. * <li>{@link #saveGeometry(Window,String)}</li>
  71. * </ul>
  72. *
  73. * @author Slava Pestov
  74. * @version $Id: GUIUtilities.java 5451 2006-06-20 13:19:47Z kpouer $
  75. */
  76. public class GUIUtilities
  77. {
  78. //{{{ Some predefined icons
  79. /**
  80. * @deprecated Use <code>GUIUtilities.loadIcon("new.gif");</code>
  81. * instead.
  82. */
  83. public static Icon NEW_BUFFER_ICON;
  84. /**
  85. * @deprecated Use <code>GUIUtilities.loadIcon("dirty.gif");</code>
  86. * instead.
  87. */
  88. public static Icon DIRTY_BUFFER_ICON;
  89. /**
  90. * @deprecated Use <code>GUIUtilities.loadIcon("readonly.gif");</code>
  91. * instead.
  92. */
  93. public static Icon READ_ONLY_BUFFER_ICON;
  94. /**
  95. * @deprecated Use <code>GUIUtilities.loadIcon("normal.gif");</code>
  96. * instead.
  97. */
  98. public static Icon NORMAL_BUFFER_ICON;
  99. /**
  100. * @deprecated Use <code>GUIUtilities.loadIcon("jedit-icon.gif");</code>
  101. * instead.
  102. */
  103. public static Icon WINDOW_ICON;
  104. //}}}
  105. //{{{ Icon methods
  106. //{{{ setIconPath() method
  107. /**
  108. * Sets the path where jEdit looks for icons.
  109. * @since jEdit 4.2pre5
  110. */
  111. public static void setIconPath(String iconPath)
  112. {
  113. GUIUtilities.iconPath = iconPath;
  114. if(icons != null)
  115. icons.clear();
  116. } //}}}
  117. //{{{ loadIcon() method
  118. /**
  119. * Loads an icon.
  120. * @param iconName The icon name
  121. * @since jEdit 2.6pre7
  122. */
  123. public static Icon loadIcon(String iconName)
  124. {
  125. if(icons == null)
  126. icons = new Hashtable();
  127. // check if there is a cached version first
  128. Icon icon = (Icon)icons.get(iconName);
  129. if(icon != null)
  130. return icon;
  131. URL url;
  132. try
  133. {
  134. // get the icon
  135. if(MiscUtilities.isURL(iconName))
  136. url = new URL(iconName);
  137. else
  138. url = new URL(iconPath + iconName);
  139. }
  140. catch(Exception e)
  141. {
  142. try
  143. {
  144. url = new URL(defaultIconPath + iconName);
  145. }
  146. catch(Exception ex)
  147. {
  148. Log.log(Log.ERROR,GUIUtilities.class,
  149. "Icon not found: " + iconName);
  150. Log.log(Log.ERROR,GUIUtilities.class,ex);
  151. return null;
  152. }
  153. }
  154. icon = new ImageIcon(url);
  155. icons.put(iconName,icon);
  156. return icon;
  157. } //}}}
  158. //{{{ getEditorIcon() method
  159. /**
  160. * Returns the default editor window image.
  161. */
  162. public static Image getEditorIcon()
  163. {
  164. return ((ImageIcon)loadIcon("jedit-icon.gif")).getImage();
  165. } //}}}
  166. //{{{ getPluginIcon() method
  167. /**
  168. * Returns the default plugin window image.
  169. */
  170. public static Image getPluginIcon()
  171. {
  172. return getEditorIcon();
  173. } //}}}
  174. //}}}
  175. //{{{ Menus, tool bars
  176. //{{{ loadMenuBar() method
  177. /**
  178. * Creates a menubar. Plugins should not need to call this method.
  179. * @param name The menu bar name
  180. * @since jEdit 3.2pre5
  181. */
  182. public static JMenuBar loadMenuBar(String name)
  183. {
  184. return loadMenuBar(jEdit.getActionContext(),name);
  185. } //}}}
  186. //{{{ loadMenuBar() method
  187. /**
  188. * Creates a menubar. Plugins should not need to call this method.
  189. * @param context An action context
  190. * @param name The menu bar name
  191. * @since jEdit 4.2pre1
  192. */
  193. public static JMenuBar loadMenuBar(ActionContext context, String name)
  194. {
  195. String menus = jEdit.getProperty(name);
  196. StringTokenizer st = new StringTokenizer(menus);
  197. JMenuBar mbar = new JMenuBar();
  198. while(st.hasMoreTokens())
  199. {
  200. mbar.add(loadMenu(context,st.nextToken()));
  201. }
  202. return mbar;
  203. } //}}}
  204. //{{{ loadMenu() method
  205. /**
  206. * Creates a menu. The menu label is set from the
  207. * <code><i>name</i>.label</code> property. The menu contents is taken
  208. * from the <code><i>name</i></code> property, which is a whitespace
  209. * separated list of action names. An action name of <code>-</code>
  210. * inserts a separator in the menu.
  211. * @param name The menu name
  212. * @see #loadMenuItem(String)
  213. * @since jEdit 2.6pre2
  214. */
  215. public static JMenu loadMenu(String name)
  216. {
  217. return loadMenu(jEdit.getActionContext(),name);
  218. } //}}}
  219. //{{{ loadMenu() method
  220. /**
  221. * Creates a menu. The menu label is set from the
  222. * <code><i>name</i>.label</code> property. The menu contents is taken
  223. * from the <code><i>name</i></code> property, which is a whitespace
  224. * separated list of action names. An action name of <code>-</code>
  225. * inserts a separator in the menu.
  226. * @param context An action context; either
  227. * <code>jEdit.getActionContext()</code> or
  228. * <code>VFSBrowser.getActionContext()</code>.
  229. * @param name The menu name
  230. * @see #loadMenuItem(String)
  231. * @since jEdit 4.2pre1
  232. */
  233. public static JMenu loadMenu(ActionContext context, String name)
  234. {
  235. return new EnhancedMenu(name,
  236. jEdit.getProperty(name.concat(".label")),
  237. context);
  238. } //}}}
  239. //{{{ loadPopupMenu() method
  240. /**
  241. * Creates a popup menu.
  242. * @param name The menu name
  243. * @since jEdit 2.6pre2
  244. */
  245. public static JPopupMenu loadPopupMenu(String name)
  246. {
  247. return loadPopupMenu(jEdit.getActionContext(),name);
  248. } //}}}
  249. //{{{ loadPopupMenu() method
  250. /**
  251. * Creates a popup menu.
  252. * @param context An action context; either
  253. * <code>jEdit.getActionContext()</code> or
  254. * <code>VFSBrowser.getActionContext()</code>.
  255. * @param name The menu name
  256. * @since jEdit 4.2pre1
  257. */
  258. public static JPopupMenu loadPopupMenu(ActionContext context, String name)
  259. {
  260. JPopupMenu menu = new JPopupMenu();
  261. String menuItems = jEdit.getProperty(name);
  262. if(menuItems != null)
  263. {
  264. StringTokenizer st = new StringTokenizer(menuItems);
  265. while(st.hasMoreTokens())
  266. {
  267. String menuItemName = st.nextToken();
  268. if(menuItemName.equals("-"))
  269. menu.addSeparator();
  270. else
  271. menu.add(loadMenuItem(context,menuItemName,false));
  272. }
  273. }
  274. return menu;
  275. } //}}}
  276. //{{{ loadMenuItem() method
  277. /**
  278. * Creates a menu item. The menu item is bound to the action named by
  279. * <code>name</code> with label taken from the return value of the
  280. * {@link EditAction#getLabel()} method.
  281. *
  282. * @param name The menu item name
  283. * @see #loadMenu(String)
  284. * @since jEdit 2.6pre1
  285. */
  286. public static JMenuItem loadMenuItem(String name)
  287. {
  288. return loadMenuItem(jEdit.getActionContext(),name,true);
  289. } //}}}
  290. //{{{ loadMenuItem() method
  291. /**
  292. * Creates a menu item.
  293. * @param name The menu item name
  294. * @param setMnemonic True if the menu item should have a mnemonic
  295. * @since jEdit 3.1pre1
  296. */
  297. public static JMenuItem loadMenuItem(String name, boolean setMnemonic)
  298. {
  299. return loadMenuItem(jEdit.getActionContext(),name,setMnemonic);
  300. } //}}}
  301. //{{{ loadMenuItem() method
  302. /**
  303. * Creates a menu item.
  304. * @param context An action context; either
  305. * <code>jEdit.getActionContext()</code> or
  306. * <code>VFSBrowser.getActionContext()</code>.
  307. * @param name The menu item name
  308. * @param setMnemonic True if the menu item should have a mnemonic
  309. * @since jEdit 4.2pre1
  310. */
  311. public static JMenuItem loadMenuItem(ActionContext context, String name,
  312. boolean setMnemonic)
  313. {
  314. if(name.startsWith("%"))
  315. return loadMenu(context,name.substring(1));
  316. String label = jEdit.getProperty(name + ".label");
  317. if(label == null)
  318. label = name;
  319. char mnemonic;
  320. int index = label.indexOf('$');
  321. if(index != -1 && label.length() - index > 1)
  322. {
  323. mnemonic = Character.toLowerCase(label.charAt(index + 1));
  324. label = label.substring(0,index).concat(label.substring(++index));
  325. }
  326. else
  327. mnemonic = '\0';
  328. JMenuItem mi;
  329. if(jEdit.getBooleanProperty(name + ".toggle"))
  330. mi = new EnhancedCheckBoxMenuItem(label,name,context);
  331. else
  332. mi = new EnhancedMenuItem(label,name,context);
  333. if(!OperatingSystem.isMacOS() && setMnemonic && mnemonic != '\0')
  334. mi.setMnemonic(mnemonic);
  335. return mi;
  336. } //}}}
  337. //{{{ loadToolBar() method
  338. /**
  339. * Creates a toolbar.
  340. * @param name The toolbar name
  341. * @since jEdit 4.2pre2
  342. */
  343. public static Box loadToolBar(String name)
  344. {
  345. return loadToolBar(jEdit.getActionContext(),name);
  346. } //}}}
  347. //{{{ loadToolBar() method
  348. /**
  349. * Creates a toolbar.
  350. * @param context An action context; either
  351. * <code>jEdit.getActionContext()</code> or
  352. * <code>VFSBrowser.getActionContext()</code>.
  353. * @param name The toolbar name
  354. * @since jEdit 4.2pre2
  355. */
  356. public static Box loadToolBar(ActionContext context, String name)
  357. {
  358. Box toolBar = new Box(BoxLayout.X_AXIS);
  359. String buttons = jEdit.getProperty(name);
  360. if(buttons != null)
  361. {
  362. StringTokenizer st = new StringTokenizer(buttons);
  363. while(st.hasMoreTokens())
  364. {
  365. String button = st.nextToken();
  366. if(button.equals("-"))
  367. toolBar.add(Box.createHorizontalStrut(12));
  368. else
  369. {
  370. JButton b = loadToolButton(context,button);
  371. if(b != null)
  372. toolBar.add(b);
  373. }
  374. }
  375. }
  376. toolBar.add(Box.createGlue());
  377. return toolBar;
  378. } //}}}
  379. //{{{ loadToolButton() method
  380. /**
  381. * Loads a tool bar button. The tooltip is constructed from
  382. * the <code><i>name</i>.label</code> and
  383. * <code><i>name</i>.shortcut</code> properties and the icon is loaded
  384. * from the resource named '/org/gjt/sp/jedit/icons/' suffixed
  385. * with the value of the <code><i>name</i>.icon</code> property.
  386. * @param name The name of the button
  387. */
  388. public static EnhancedButton loadToolButton(String name)
  389. {
  390. return loadToolButton(jEdit.getActionContext(),name);
  391. } //}}}
  392. //{{{ loadToolButton() method
  393. /**
  394. * Loads a tool bar button. The tooltip is constructed from
  395. * the <code><i>name</i>.label</code> and
  396. * <code><i>name</i>.shortcut</code> properties and the icon is loaded
  397. * from the resource named '/org/gjt/sp/jedit/icons/' suffixed
  398. * with the value of the <code><i>name</i>.icon</code> property.
  399. * @param context An action context; either
  400. * <code>jEdit.getActionContext()</code> or
  401. * <code>VFSBrowser.getActionContext()</code>.
  402. * @param name The name of the button
  403. * @since jEdit 4.2pre1
  404. */
  405. public static EnhancedButton loadToolButton(ActionContext context,
  406. String name)
  407. {
  408. String label = jEdit.getProperty(name + ".label");
  409. if(label == null)
  410. label = name;
  411. Icon icon;
  412. String iconName = jEdit.getProperty(name + ".icon");
  413. if(iconName == null)
  414. icon = loadIcon("BrokenImage.png");
  415. else
  416. {
  417. icon = loadIcon(iconName);
  418. if(icon == null)
  419. icon = loadIcon("BrokenImage.png");
  420. }
  421. String toolTip = prettifyMenuLabel(label);
  422. String shortcut1 = jEdit.getProperty(name + ".shortcut");
  423. String shortcut2 = jEdit.getProperty(name + ".shortcut2");
  424. if(shortcut1 != null || shortcut2 != null)
  425. {
  426. toolTip = toolTip + " ("
  427. + (shortcut1 != null
  428. ? shortcut1 : "")
  429. + ((shortcut1 != null && shortcut2 != null)
  430. ? " or " : "")
  431. + (shortcut2 != null
  432. ? shortcut2
  433. : "") + ")";
  434. }
  435. return new EnhancedButton(icon,toolTip,name,context);
  436. } //}}}
  437. //{{{ prettifyMenuLabel() method
  438. /**
  439. * `Prettifies' a menu item label by removing the `$' sign. This
  440. * can be used to process the contents of an <i>action</i>.label
  441. * property.
  442. */
  443. public static String prettifyMenuLabel(String label)
  444. {
  445. int index = label.indexOf('$');
  446. if(index != -1)
  447. {
  448. label = label.substring(0,index)
  449. .concat(label.substring(index + 1));
  450. }
  451. return label;
  452. } //}}}
  453. //}}}
  454. //{{{ Canned dialog boxes
  455. //{{{ message() method
  456. /**
  457. * Displays a dialog box.
  458. * The title of the dialog is fetched from
  459. * the <code><i>name</i>.title</code> property. The message is fetched
  460. * from the <code><i>name</i>.message</code> property. The message
  461. * is formatted by the property manager with <code>args</code> as
  462. * positional parameters.
  463. * @param comp The component to display the dialog for
  464. * @param name The name of the dialog
  465. * @param args Positional parameters to be substituted into the
  466. * message text
  467. */
  468. public static void message(Component comp, String name, Object[] args)
  469. {
  470. hideSplashScreen();
  471. JOptionPane.showMessageDialog(comp,
  472. jEdit.getProperty(name.concat(".message"),args),
  473. jEdit.getProperty(name.concat(".title"),args),
  474. JOptionPane.INFORMATION_MESSAGE);
  475. } //}}}
  476. //{{{ error() method
  477. /**
  478. * Displays an error dialog box.
  479. * The title of the dialog is fetched from
  480. * the <code><i>name</i>.title</code> property. The message is fetched
  481. * from the <code><i>name</i>.message</code> property. The message
  482. * is formatted by the property manager with <code>args</code> as
  483. * positional parameters.
  484. * @param comp The component to display the dialog for
  485. * @param name The name of the dialog
  486. * @param args Positional parameters to be substituted into the
  487. * message text
  488. */
  489. public static void error(Component comp, String name, Object[] args)
  490. {
  491. hideSplashScreen();
  492. JOptionPane.showMessageDialog(comp,
  493. jEdit.getProperty(name.concat(".message"),args),
  494. jEdit.getProperty(name.concat(".title"),args),
  495. JOptionPane.ERROR_MESSAGE);
  496. } //}}}
  497. //{{{ input() method
  498. /**
  499. * Displays an input dialog box and returns any text the user entered.
  500. * The title of the dialog is fetched from
  501. * the <code><i>name</i>.title</code> property. The message is fetched
  502. * from the <code><i>name</i>.message</code> property.
  503. * @param comp The component to display the dialog for
  504. * @param name The name of the dialog
  505. * @param def The text to display by default in the input field
  506. */
  507. public static String input(Component comp, String name, Object def)
  508. {
  509. return input(comp,name,null,def);
  510. } //}}}
  511. //{{{ inputProperty() method
  512. /**
  513. * Displays an input dialog box and returns any text the user entered.
  514. * The title of the dialog is fetched from
  515. * the <code><i>name</i>.title</code> property. The message is fetched
  516. * from the <code><i>name</i>.message</code> property.
  517. * @param comp The component to display the dialog for
  518. * @param name The name of the dialog
  519. * @param def The property whose text to display in the input field
  520. */
  521. public static String inputProperty(Component comp, String name,
  522. String def)
  523. {
  524. return inputProperty(comp,name,null,def);
  525. } //}}}
  526. //{{{ input() method
  527. /**
  528. * Displays an input dialog box and returns any text the user entered.
  529. * The title of the dialog is fetched from
  530. * the <code><i>name</i>.title</code> property. The message is fetched
  531. * from the <code><i>name</i>.message</code> property.
  532. * @param comp The component to display the dialog for
  533. * @param name The name of the dialog
  534. * @param def The text to display by default in the input field
  535. * @param args Positional parameters to be substituted into the
  536. * message text
  537. * @since jEdit 3.1pre3
  538. */
  539. public static String input(Component comp, String name,
  540. Object[] args, Object def)
  541. {
  542. hideSplashScreen();
  543. String retVal = (String)JOptionPane.showInputDialog(comp,
  544. jEdit.getProperty(name.concat(".message"),args),
  545. jEdit.getProperty(name.concat(".title")),
  546. JOptionPane.QUESTION_MESSAGE,null,null,def);
  547. return retVal;
  548. } //}}}
  549. //{{{ inputProperty() method
  550. /**
  551. * Displays an input dialog box and returns any text the user entered.
  552. * The title of the dialog is fetched from
  553. * the <code><i>name</i>.title</code> property. The message is fetched
  554. * from the <code><i>name</i>.message</code> property.
  555. * @param comp The component to display the dialog for
  556. * @param name The name of the dialog
  557. * @param args Positional parameters to be substituted into the
  558. * message text
  559. * @param def The property whose text to display in the input field
  560. * @since jEdit 3.1pre3
  561. */
  562. public static String inputProperty(Component comp, String name,
  563. Object[] args, String def)
  564. {
  565. hideSplashScreen();
  566. String retVal = (String)JOptionPane.showInputDialog(comp,
  567. jEdit.getProperty(name.concat(".message"),args),
  568. jEdit.getProperty(name.concat(".title")),
  569. JOptionPane.QUESTION_MESSAGE,
  570. null,null,jEdit.getProperty(def));
  571. if(retVal != null)
  572. jEdit.setProperty(def,retVal);
  573. return retVal;
  574. } //}}}
  575. //{{{ confirm() method
  576. /**
  577. * Displays a confirm dialog box and returns the button pushed by the
  578. * user. The title of the dialog is fetched from the
  579. * <code><i>name</i>.title</code> property. The message is fetched
  580. * from the <code><i>name</i>.message</code> property.
  581. * @param comp The component to display the dialog for
  582. * @param name The name of the dialog
  583. * @param args Positional parameters to be substituted into the
  584. * message text
  585. * @param buttons The buttons to display - for example,
  586. * JOptionPane.YES_NO_CANCEL_OPTION
  587. * @param type The dialog type - for example,
  588. * JOptionPane.WARNING_MESSAGE
  589. * @since jEdit 3.1pre3
  590. */
  591. public static int confirm(Component comp, String name,
  592. Object[] args, int buttons, int type)
  593. {
  594. hideSplashScreen();
  595. return JOptionPane.showConfirmDialog(comp,
  596. jEdit.getProperty(name + ".message",args),
  597. jEdit.getProperty(name + ".title"),buttons,type);
  598. } //}}}
  599. //{{{ listConfirm() method
  600. /**
  601. * Displays a confirm dialog box and returns the button pushed by the
  602. * user. The title of the dialog is fetched from the
  603. * <code><i>name</i>.title</code> property. The message is fetched
  604. * from the <code><i>name</i>.message</code> property. The dialog
  605. * also shows a list of entries given by the <code>listModel</code>
  606. * parameter.
  607. * @since jEdit 4.3pre1
  608. */
  609. public static int listConfirm(Component comp, String name, String[] args,
  610. Object[] listModel)
  611. {
  612. JList list = new JList(listModel);
  613. list.setVisibleRowCount(8);
  614. Object[] message = {
  615. jEdit.getProperty(name + ".message",args),
  616. new JScrollPane(list)
  617. };
  618. return JOptionPane.showConfirmDialog(comp,
  619. message,
  620. jEdit.getProperty(name + ".title"),
  621. JOptionPane.YES_NO_OPTION,
  622. JOptionPane.QUESTION_MESSAGE);
  623. } //}}}
  624. //{{{ showVFSFileDialog() method
  625. /**
  626. * Displays a VFS file selection dialog box.
  627. * @param view The view, should be non-null
  628. * @param path The initial directory to display. May be null
  629. * @param type The dialog type. One of
  630. * {@link org.gjt.sp.jedit.browser.VFSBrowser#OPEN_DIALOG},
  631. * {@link org.gjt.sp.jedit.browser.VFSBrowser#SAVE_DIALOG}, or
  632. * {@link org.gjt.sp.jedit.browser.VFSBrowser#CHOOSE_DIRECTORY_DIALOG}.
  633. * @param multipleSelection True if multiple selection should be allowed
  634. * @return The selected file(s)
  635. * @since jEdit 2.6pre2
  636. */
  637. public static String[] showVFSFileDialog(View view, String path,
  638. int type, boolean multipleSelection)
  639. {
  640. // the view should not be null, but some plugins might do this
  641. if(view == null)
  642. {
  643. Log.log(Log.WARNING,GUIUtilities.class,
  644. "showVFSFileDialog(): given null view, assuming jEdit.getActiveView()");
  645. view = jEdit.getActiveView();
  646. }
  647. hideSplashScreen();
  648. VFSFileChooserDialog fileChooser = new VFSFileChooserDialog(
  649. view,path,type,multipleSelection);
  650. String[] selectedFiles = fileChooser.getSelectedFiles();
  651. if(selectedFiles == null)
  652. return null;
  653. return selectedFiles;
  654. } //}}}
  655. //}}}
  656. //{{{ Colors and styles
  657. //{{{ parseColor() method
  658. /**
  659. * Converts a color name to a color object. The name must either be
  660. * a known string, such as `red', `green', etc (complete list is in
  661. * the <code>java.awt.Color</code> class) or a hex color value
  662. * prefixed with `#', for example `#ff0088'.
  663. * @param name The color name
  664. */
  665. public static Color parseColor(String name)
  666. {
  667. return parseColor(name, Color.black);
  668. } //}}}
  669. //{{{ parseColor() method
  670. public static Color parseColor(String name, Color defaultColor)
  671. {
  672. if(name == null)
  673. return defaultColor;
  674. else if(name.startsWith("#"))
  675. {
  676. try
  677. {
  678. return Color.decode(name);
  679. }
  680. catch(NumberFormatException nf)
  681. {
  682. return defaultColor;
  683. }
  684. }
  685. else if("red".equals(name))
  686. return Color.red;
  687. else if("green".equals(name))
  688. return Color.green;
  689. else if("blue".equals(name))
  690. return Color.blue;
  691. else if("yellow".equals(name))
  692. return Color.yellow;
  693. else if("orange".equals(name))
  694. return Color.orange;
  695. else if("white".equals(name))
  696. return Color.white;
  697. else if("lightGray".equals(name))
  698. return Color.lightGray;
  699. else if("gray".equals(name))
  700. return Color.gray;
  701. else if("darkGray".equals(name))
  702. return Color.darkGray;
  703. else if("black".equals(name))
  704. return Color.black;
  705. else if("cyan".equals(name))
  706. return Color.cyan;
  707. else if("magenta".equals(name))
  708. return Color.magenta;
  709. else if("pink".equals(name))
  710. return Color.pink;
  711. else
  712. return defaultColor;
  713. } //}}}
  714. //{{{ getColorHexString() method
  715. /**
  716. * Converts a color object to its hex value. The hex value
  717. * prefixed is with `#', for example `#ff0088'.
  718. * @param c The color object
  719. */
  720. public static String getColorHexString(Color c)
  721. {
  722. String colString = Integer.toHexString(c.getRGB() & 0xffffff);
  723. return "#000000".substring(0,7 - colString.length()).concat(colString);
  724. } //}}}
  725. //{{{ parseStyle() method
  726. /**
  727. * Converts a style string to a style object.
  728. * @param str The style string
  729. * @param family Style strings only specify font style, not font family
  730. * @param size Style strings only specify font style, not font family
  731. * @exception IllegalArgumentException if the style is invalid
  732. * @since jEdit 3.2pre6
  733. */
  734. public static SyntaxStyle parseStyle(String str, String family, int size)
  735. throws IllegalArgumentException
  736. {
  737. return parseStyle(str,family,size,true);
  738. } //}}}
  739. //{{{ parseStyle() method
  740. /**
  741. * Converts a style string to a style object.
  742. * @param str The style string
  743. * @param family Style strings only specify font style, not font family
  744. * @param size Style strings only specify font style, not font family
  745. * @param color If false, the styles will be monochrome
  746. * @exception IllegalArgumentException if the style is invalid
  747. * @since jEdit 4.0pre4
  748. */
  749. public static SyntaxStyle parseStyle(String str, String family, int size,
  750. boolean color)
  751. throws IllegalArgumentException
  752. {
  753. Color fgColor = Color.black;
  754. Color bgColor = null;
  755. boolean italic = false;
  756. boolean bold = false;
  757. StringTokenizer st = new StringTokenizer(str);
  758. while(st.hasMoreTokens())
  759. {
  760. String s = st.nextToken();
  761. if(s.startsWith("color:"))
  762. {
  763. if(color)
  764. fgColor = GUIUtilities.parseColor(s.substring(6), Color.black);
  765. }
  766. else if(s.startsWith("bgColor:"))
  767. {
  768. if(color)
  769. bgColor = GUIUtilities.parseColor(s.substring(8), null);
  770. }
  771. else if(s.startsWith("style:"))
  772. {
  773. for(int i = 6; i < s.length(); i++)
  774. {
  775. if(s.charAt(i) == 'i')
  776. italic = true;
  777. else if(s.charAt(i) == 'b')
  778. bold = true;
  779. else
  780. throw new IllegalArgumentException(
  781. "Invalid style: " + s);
  782. }
  783. }
  784. else
  785. throw new IllegalArgumentException(
  786. "Invalid directive: " + s);
  787. }
  788. return new SyntaxStyle(fgColor,bgColor,
  789. new Font(family,
  790. (italic ? Font.ITALIC : 0) | (bold ? Font.BOLD : 0),
  791. size));
  792. } //}}}
  793. //{{{ getStyleString() method
  794. /**
  795. * Converts a style into it's string representation.
  796. * @param style The style
  797. */
  798. public static String getStyleString(SyntaxStyle style)
  799. {
  800. StringBuffer buf = new StringBuffer();
  801. if(style.getForegroundColor() != null)
  802. {
  803. buf.append("color:").append(getColorHexString(style.getForegroundColor()));
  804. }
  805. if(style.getBackgroundColor() != null)
  806. {
  807. buf.append(" bgColor:").append(getColorHexString(style.getBackgroundColor()));
  808. }
  809. Font font = style.getFont();
  810. if(!font.isPlain())
  811. {
  812. buf.append(" style:");
  813. if (font.isItalic())
  814. buf.append('i');
  815. if (font.isBold())
  816. buf.append('b');
  817. }
  818. return buf.toString();
  819. } //}}}
  820. //{{{ loadStyles() method
  821. /**
  822. * Loads the syntax styles from the properties, giving them the specified
  823. * base font family and size.
  824. * @param family The font family
  825. * @param size The font size
  826. * @since jEdit 3.2pre6
  827. */
  828. public static SyntaxStyle[] loadStyles(String family, int size)
  829. {
  830. return loadStyles(family,size,true);
  831. } //}}}
  832. //{{{ loadStyles() method
  833. /**
  834. * Loads the syntax styles from the properties, giving them the specified
  835. * base font family and size.
  836. * @param family The font family
  837. * @param size The font size
  838. * @param color If false, the styles will be monochrome
  839. * @since jEdit 4.0pre4
  840. */
  841. public static SyntaxStyle[] loadStyles(String family, int size, boolean color)
  842. {
  843. SyntaxStyle[] styles = new SyntaxStyle[Token.ID_COUNT];
  844. // start at 1 not 0 to skip Token.NULL
  845. for(int i = 1; i < styles.length; i++)
  846. {
  847. try
  848. {
  849. String styleName = "view.style."
  850. + Token.tokenToString((byte)i)
  851. .toLowerCase(Locale.ENGLISH);
  852. styles[i] = GUIUtilities.parseStyle(
  853. jEdit.getProperty(styleName),
  854. family,size,color);
  855. }
  856. catch(Exception e)
  857. {
  858. Log.log(Log.ERROR,GUIUtilities.class,e);
  859. }
  860. }
  861. return styles;
  862. } //}}}
  863. //}}}
  864. //{{{ Loading, saving window geometry
  865. //{{{ loadGeometry() method
  866. /**
  867. * Loads a windows's geometry from the properties.
  868. * The geometry is loaded from the <code><i>name</i>.x</code>,
  869. * <code><i>name</i>.y</code>, <code><i>name</i>.width</code> and
  870. * <code><i>name</i>.height</code> properties.
  871. *
  872. * @param win The window
  873. * @param name The window name
  874. */
  875. public static void loadGeometry(Window win, String name)
  876. {
  877. int x, y, width, height;
  878. Dimension size = win.getSize();
  879. GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
  880. Rectangle gcbounds = gd.getDefaultConfiguration().getBounds();
  881. x = gcbounds.x;
  882. y = gcbounds.y;
  883. width = jEdit.getIntegerProperty(name + ".width",size.width);
  884. height = jEdit.getIntegerProperty(name + ".height",size.height);
  885. Component parent = win.getParent();
  886. if(parent == null)
  887. {
  888. x += (gcbounds.width - width) / 2;
  889. y += (gcbounds.height - height) / 2;
  890. }
  891. else
  892. {
  893. Rectangle bounds = parent.getBounds();
  894. x += bounds.x + (bounds.width - width) / 2;
  895. y += bounds.y + (bounds.height - height) / 2;
  896. }
  897. x = jEdit.getIntegerProperty(name + ".x",x);
  898. y = jEdit.getIntegerProperty(name + ".y",y);
  899. int extState = jEdit.getIntegerProperty(name + ".extendedState", 0);
  900. Rectangle desired = new Rectangle(x,y,width,height);
  901. try
  902. {
  903. if(!Debug.DISABLE_MULTIHEAD)
  904. adjustForScreenBounds(desired);
  905. }
  906. catch(Exception e)
  907. {
  908. /* Workaround for OS X bug. */
  909. Log.log(Log.ERROR,GUIUtilities.class,e);
  910. }
  911. if(OperatingSystem.isX11() && Debug.GEOMETRY_WORKAROUND)
  912. new UnixWorkaround(win,name,desired,extState);
  913. else
  914. {
  915. win.setBounds(desired);
  916. if(win instanceof Frame)
  917. ((Frame)win).setExtendedState(extState);
  918. }
  919. } //}}}
  920. //{{{ adjustForScreenBounds() method
  921. /**
  922. * Gives a rectangle the specified bounds, ensuring it is within the
  923. * screen bounds.
  924. * @since jEdit 4.2pre3
  925. */
  926. public static void adjustForScreenBounds(Rectangle desired)
  927. {
  928. // Make sure the window is displayed in visible region
  929. Rectangle osbounds = OperatingSystem.getScreenBounds(desired);
  930. if(desired.x < osbounds.x || desired.x+desired.width
  931. > desired.x + osbounds.width)
  932. {
  933. if (desired.width > osbounds.width)
  934. desired.width = osbounds.width;
  935. desired.x = (osbounds.width - desired.width) / 2;
  936. }
  937. if(desired.y < osbounds.y || desired.y+desired.height
  938. > osbounds.y + osbounds.height)
  939. {
  940. if (desired.height >= osbounds.height)
  941. desired.height = osbounds.height;
  942. desired.y = (osbounds.height - desired.height) / 2;
  943. }
  944. } //}}}
  945. //{{{ UnixWorkaround class
  946. static class UnixWorkaround
  947. {
  948. Window win;
  949. String name;
  950. Rectangle desired;
  951. Rectangle required;
  952. long start;
  953. boolean windowOpened;
  954. //{{{ UnixWorkaround constructor
  955. UnixWorkaround(Window win, String name, Rectangle desired,
  956. int extState)
  957. {
  958. this.win = win;
  959. this.name = name;
  960. this.desired = desired;
  961. int adjust_x, adjust_y, adjust_width, adjust_height;
  962. adjust_x = jEdit.getIntegerProperty(name + ".dx",0);
  963. adjust_y = jEdit.getIntegerProperty(name + ".dy",0);
  964. adjust_width = jEdit.getIntegerProperty(name + ".d-width",0);
  965. adjust_height = jEdit.getIntegerProperty(name + ".d-height",0);
  966. required = new Rectangle(
  967. desired.x - adjust_x,
  968. desired.y - adjust_y,
  969. desired.width - adjust_width,
  970. desired.height - adjust_height);
  971. Log.log(Log.DEBUG,GUIUtilities.class,"Window " + name
  972. + ": desired geometry is " + desired);
  973. Log.log(Log.DEBUG,GUIUtilities.class,"Window " + name
  974. + ": setting geometry to " + required);
  975. start = System.currentTimeMillis();
  976. win.setBounds(required);
  977. if(win instanceof Frame)
  978. ((Frame)win).setExtendedState(extState);
  979. win.addComponentListener(new ComponentHandler());
  980. win.addWindowListener(new WindowHandler());
  981. } //}}}
  982. //{{{ ComponentHandler class
  983. class ComponentHandler extends ComponentAdapter
  984. {
  985. //{{{ componentMoved() method
  986. public void componentMoved(ComponentEvent evt)
  987. {
  988. if(System.currentTimeMillis() - start < 1000)
  989. {
  990. Rectangle r = win.getBounds();
  991. if(!windowOpened && r.equals(required))
  992. return;
  993. if(!r.equals(desired))
  994. {
  995. Log.log(Log.DEBUG,GUIUtilities.class,
  996. "Window resize blocked: " + win.getBounds());
  997. win.setBounds(desired);
  998. }
  999. }
  1000. win.removeComponentListener(this);
  1001. } //}}}
  1002. //{{{ componentResized() method
  1003. public void componentResized(ComponentEvent evt)
  1004. {
  1005. if(System.currentTimeMillis() - start < 1000)
  1006. {
  1007. Rectangle r = win.getBounds();
  1008. if(!windowOpened && r.equals(required))
  1009. return;
  1010. if(!r.equals(desired))
  1011. {
  1012. Log.log(Log.DEBUG,GUIUtilities.class,
  1013. "Window resize blocked: " + win.getBounds());
  1014. win.setBounds(desired);
  1015. }
  1016. }
  1017. win.removeComponentListener(this);
  1018. } //}}}
  1019. } //}}}
  1020. //{{{ WindowHandler class
  1021. class WindowHandler extends WindowAdapter
  1022. {
  1023. //{{{ windowOpened() method
  1024. public void windowOpened(WindowEvent evt)
  1025. {
  1026. windowOpened = true;
  1027. Rectangle r = win.getBounds();
  1028. Log.log(Log.DEBUG,GUIUtilities.class,"Window "
  1029. + name + ": bounds after opening: " + r);
  1030. jEdit.setIntegerProperty(name + ".dx",
  1031. r.x - required.x);
  1032. jEdit.setIntegerProperty(name + ".dy",
  1033. r.y - required.y);
  1034. jEdit.setIntegerProperty(name + ".d-width",
  1035. r.width - required.width);
  1036. jEdit.setIntegerProperty(name + ".d-height",
  1037. r.height - required.height);
  1038. win.removeWindowListener(this);
  1039. } //}}}
  1040. } //}}}
  1041. } //}}}
  1042. //{{{ saveGeometry() method
  1043. /**
  1044. * Saves a window's geometry to the properties.
  1045. * The geometry is saved to the <code><i>name</i>.x</code>,
  1046. * <code><i>name</i>.y</code>, <code><i>name</i>.width</code> and
  1047. * <code><i>name</i>.height</code> properties.
  1048. * @param win The window
  1049. * @param name The window name
  1050. */
  1051. public static void saveGeometry(Window win, String name)
  1052. {
  1053. if(win instanceof Frame)
  1054. {
  1055. jEdit.setIntegerProperty(name + ".extendedState",
  1056. ((Frame)win).getExtendedState());
  1057. }
  1058. Rectangle bounds = win.getBounds();
  1059. jEdit.setIntegerProperty(name + ".x",bounds.x);
  1060. jEdit.setIntegerProperty(name + ".y",bounds.y);
  1061. jEdit.setIntegerProperty(name + ".width",bounds.width);
  1062. jEdit.setIntegerProperty(name + ".height",bounds.height);
  1063. } //}}}
  1064. //{{{ centerOnScreen() method
  1065. /**
  1066. * Centers the given window on the screen. This method is needed because
  1067. * JDK 1.3 does not have a <code>JWindow.setLocationRelativeTo()</code>
  1068. * method.
  1069. * @since jEdit 4.2pre3
  1070. */
  1071. public static void centerOnScreen(Window win)
  1072. {
  1073. GraphicsDevice gd = GraphicsEnvironment
  1074. .getLocalGraphicsEnvironment()
  1075. .getDefaultScreenDevice();
  1076. Rectangle gcbounds = gd.getDefaultConfiguration().getBounds();
  1077. int x = gcbounds.x + (gcbounds.width - win.getWidth()) / 2;
  1078. int y = gcbounds.y + (gcbounds.height - win.getHeight()) / 2;
  1079. win.setLocation(x,y);
  1080. } //}}}
  1081. //}}}
  1082. //{{{ hideSplashScreen() method
  1083. /**
  1084. * Ensures that the splash screen is not visible. This should be
  1085. * called before displaying any dialog boxes or windows at
  1086. * startup.
  1087. */
  1088. public static void hideSplashScreen()
  1089. {
  1090. if(splash != null)
  1091. {
  1092. splash.dispose();
  1093. splash = null;
  1094. }
  1095. } //}}}
  1096. //{{{ createMultilineLabel() method
  1097. /**
  1098. * Creates a component that displays a multiple line message. This
  1099. * is implemented by assembling a number of <code>JLabels</code> in
  1100. * a <code>JPanel</code>.
  1101. * @param str The string, with lines delimited by newline
  1102. * (<code>\n</code>) characters.
  1103. * @since jEdit 4.1pre3
  1104. */
  1105. public static JComponent createMultilineLabel(String str)
  1106. {
  1107. JPanel panel = new JPanel(new VariableGridLayout(
  1108. VariableGridLayout.FIXED_NUM_COLUMNS,1,1,1));
  1109. int lastOffset = 0;
  1110. for(;;)
  1111. {
  1112. int index = str.indexOf('\n',lastOffset);
  1113. if(index == -1)
  1114. break;
  1115. else
  1116. {
  1117. panel.add(new JLabel(str.substring(lastOffset,index)));
  1118. lastOffset = index + 1;
  1119. }
  1120. }
  1121. if(lastOffset != str.length())
  1122. panel.add(new JLabel(str.substring(lastOffset)));
  1123. return panel;
  1124. } //}}}
  1125. //{{{ requestFocus() method
  1126. /**
  1127. * Focuses on the specified component as soon as the window becomes
  1128. * active.
  1129. * @param win The window
  1130. * @param comp The component
  1131. */
  1132. public static void requestFocus(final Window win, final Component comp)
  1133. {
  1134. win.addWindowFocusListener(new WindowAdapter()
  1135. {
  1136. public void windowGainedFocus(WindowEvent evt)
  1137. {
  1138. comp.requestFocusInWindow();
  1139. win.removeWindowFocusListener(this);
  1140. }
  1141. });
  1142. } //}}}
  1143. //{{{ isPopupTrigger() method
  1144. /**
  1145. * Returns if the specified event is the popup trigger event.
  1146. * This implements precisely defined behavior, as opposed to
  1147. * MouseEvent.isPopupTrigger().
  1148. * @param evt The event
  1149. * @since jEdit 3.2pre8
  1150. */
  1151. public static boolean isPopupTrigger(MouseEvent evt)
  1152. {
  1153. return isRightButton(evt.getModifiers());
  1154. } //}}}
  1155. //{{{ isMiddleButton() method
  1156. /**
  1157. * @param modifiers The modifiers flag from a mouse event
  1158. * @since jEdit 4.1pre9
  1159. */
  1160. public static boolean isMiddleButton(int modifiers)
  1161. {
  1162. if (OperatingSystem.isMacOS())
  1163. {
  1164. if((modifiers & MouseEvent.BUTTON1_MASK) != 0)
  1165. return ((modifiers & MouseEvent.ALT_MASK) != 0);
  1166. else
  1167. return ((modifiers & MouseEvent.BUTTON2_MASK) != 0);
  1168. }
  1169. else
  1170. return ((modifiers & MouseEvent.BUTTON2_MASK) != 0);
  1171. } //}}}
  1172. //{{{ isRightButton() method
  1173. /**
  1174. * @param modifiers The modifiers flag from a mouse event
  1175. * @since jEdit 4.1pre9
  1176. */
  1177. public static boolean isRightButton(int modifiers)
  1178. {
  1179. if (OperatingSystem.isMacOS())
  1180. {
  1181. if((modifiers & MouseEvent.BUTTON1_MASK) != 0)
  1182. return ((modifiers & MouseEvent.CTRL_MASK) != 0);
  1183. else
  1184. return ((modifiers & MouseEvent.BUTTON3_MASK) != 0);
  1185. }
  1186. else
  1187. return ((modifiers & MouseEvent.BUTTON3_MASK) != 0);
  1188. } //}}}
  1189. //{{{ showPopupMenu() method
  1190. /**
  1191. * Shows the specified popup menu, ensuring it is displayed within
  1192. * the bounds of the screen.
  1193. * @param popup The popup menu
  1194. * @param comp The component to show it for
  1195. * @param x The x co-ordinate
  1196. * @param y The y co-ordinate
  1197. * @since jEdit 4.0pre1
  1198. */
  1199. public static void showPopupMenu(JPopupMenu popup, Component comp,
  1200. int x, int y)
  1201. {
  1202. showPopupMenu(popup,comp,x,y,true);
  1203. } //}}}
  1204. //{{{ showPopupMenu() method
  1205. /**
  1206. * Shows the specified popup menu, ensuring it is displayed within
  1207. * the bounds of the screen.
  1208. * @param popup The popup menu
  1209. * @param comp The component to show it for
  1210. * @param x The x co-ordinate
  1211. * @param y The y co-ordinate
  1212. * @param point If true, then the popup originates from a single point;
  1213. * otherwise it will originate from the component itself. This affects
  1214. * positioning in the case where the popup does not fit onscreen.
  1215. *
  1216. * @since jEdit 4.1pre1
  1217. */
  1218. public static void showPopupMenu(JPopupMenu popup, Component comp,
  1219. int x, int y, boolean point)
  1220. {
  1221. int offsetX = 0;
  1222. int offsetY = 0;
  1223. int extraOffset = (point ? 1 : 0);
  1224. Component win = comp;
  1225. while(!(win instanceof Window || win == null))
  1226. {
  1227. offsetX += win.getX();
  1228. offsetY += win.getY();
  1229. win = win.getParent();
  1230. }
  1231. if(win != null)
  1232. {
  1233. Dimension size = popup.getPreferredSize();
  1234. Rectangle screenSize = new Rectangle();
  1235. GraphicsEnvironment ge = GraphicsEnvironment
  1236. .getLocalGraphicsEnvironment();
  1237. GraphicsDevice[] devices = ge.getScreenDevices();
  1238. for (int j = 0; j < devices.length; j++)
  1239. {
  1240. GraphicsDevice device = devices[j];
  1241. GraphicsConfiguration[] gc =
  1242. device.getConfigurations();
  1243. for (int i=0; i < gc.length; i++)
  1244. {
  1245. screenSize =
  1246. screenSize.union(
  1247. gc[i].getBounds());
  1248. }
  1249. }
  1250. if(x + offsetX + size.width + win.getX() > screenSize.width
  1251. && x + offsetX + win.getX() >= size.width)
  1252. {
  1253. //System.err.println("x overflow");
  1254. if(point)
  1255. x -= (size.width + extraOffset);
  1256. else
  1257. x = (win.getWidth() - size.width - offsetX + extraOffset);
  1258. }
  1259. else
  1260. {
  1261. x += extraOffset;
  1262. }
  1263. //System.err.println("y=" + y + ",offsetY=" + offsetY
  1264. // + ",size.height=" + size.height
  1265. // + ",win.height=" + win.getHeight());
  1266. if(y + offsetY + size.height + win.getY() > screenSize.height
  1267. && y + offsetY + win.getY() >= size.height)
  1268. {
  1269. if(point)
  1270. y = (win.getHeight() - size.height - offsetY + extraOffset);
  1271. else
  1272. y = -size.height - 1;
  1273. }
  1274. else
  1275. {
  1276. y += extraOffset;
  1277. }
  1278. popup.show(comp,x,y);
  1279. }
  1280. else
  1281. popup.show(comp,x + extraOffset,y + extraOffset);
  1282. } //}}}
  1283. //{{{ isAncestorOf() method
  1284. /**
  1285. * Returns if the first component is an ancestor of the
  1286. * second by traversing up the component hierarchy.
  1287. *
  1288. * @param comp1 The ancestor
  1289. * @param comp2 The component to check
  1290. * @since jEdit 4.1pre5
  1291. */
  1292. public static boolean isAncestorOf(Component comp1, Component comp2)
  1293. {
  1294. while(comp2 != null)
  1295. {
  1296. if(comp1 == comp2)
  1297. return true;
  1298. else
  1299. comp2 = comp2.getParent();
  1300. }
  1301. return false;
  1302. } //}}}
  1303. //{{{ getParentDialog() method
  1304. /**
  1305. * Traverses the given component's parent tree looking for an
  1306. * instance of JDialog, and return it. If not found, return null.
  1307. * @param c The component
  1308. */
  1309. public static JDialog getParentDialog(Component c)
  1310. {
  1311. return (JDialog) SwingUtilities.getAncestorOfClass(JDialog.class, c);
  1312. } //}}}
  1313. //{{{ getComponentParent() method
  1314. /**
  1315. * Finds a parent of the specified component.
  1316. * @param comp The component
  1317. * @param clazz Looks for a parent with this class (exact match, not
  1318. * derived).
  1319. * @since jEdit 4.2pre1
  1320. */
  1321. public static Component getComponentParent(Component comp, Class clazz)
  1322. {
  1323. for(;;)
  1324. {
  1325. if(comp == null)
  1326. break;
  1327. if(comp instanceof JComponent)
  1328. {
  1329. Component real = (Component)((JComponent)comp)
  1330. .getClientProperty("KORTE_REAL_FRAME");
  1331. if(real != null)
  1332. comp = real;
  1333. }
  1334. if(comp.getClass().equals(clazz))
  1335. return comp;
  1336. else if(comp instanceof JPopupMenu)
  1337. comp = ((JPopupMenu)comp).getInvoker();
  1338. else if(comp instanceof FloatingWindowContainer)
  1339. {
  1340. comp = ((FloatingWindowContainer)comp)
  1341. .getDockableWindowManager();
  1342. }
  1343. else
  1344. comp = comp.getParent();
  1345. }
  1346. return null;
  1347. } //}}}
  1348. //{{{ getView() method
  1349. /**
  1350. * Finds the view parent of the specified component.
  1351. * @since jEdit 4.0pre2
  1352. */
  1353. public static View getView(Component comp)
  1354. {
  1355. return (View)getComponentParent(comp,View.class);
  1356. } //}}}
  1357. //{{{ Package-private members
  1358. //{{{ init() method
  1359. static void init()
  1360. {
  1361. // don't do this in static{} since we need jEdit.initMisc()
  1362. // run first so we have the jeditresource: protocol
  1363. NEW_BUFFER_ICON = loadIcon("new.gif");
  1364. DIRTY_BUFFER_ICON = loadIcon("dirty.gif");
  1365. READ_ONLY_BUFFER_ICON = loadIcon("readonly.gif");
  1366. NORMAL_BUFFER_ICON = loadIcon("normal.gif");
  1367. WINDOW_ICON = loadIcon("jedit-icon.gif");
  1368. } //}}}
  1369. //{{{ showSplashScreen() method
  1370. static void showSplashScreen()
  1371. {
  1372. splash = new SplashScreen();
  1373. } //}}}
  1374. //{{{ advanceSplashProgress() method
  1375. static void advanceSplashProgress()
  1376. {
  1377. if(splash != null)
  1378. splash.advance();
  1379. } //}}}
  1380. //}}}
  1381. //{{{ Private members
  1382. private static SplashScreen splash;
  1383. private static Hashtable icons;
  1384. private static String iconPath = "jeditresource:/org/gjt/sp/jedit/icons/";
  1385. private static String defaultIconPath = "jeditresource:/org/gjt/sp/jedit/icons/";
  1386. private GUIUtilities() {}
  1387. //}}}
  1388. }