PageRenderTime 49ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/View.java

#
Java | 2310 lines | 1581 code | 195 blank | 534 comment | 172 complexity | 00d5bed1be22ed29ebf8b54ae2f9a9af 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. * View.java - jEdit view
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1998, 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.*;
  25. import java.awt.event.FocusAdapter;
  26. import java.awt.event.FocusEvent;
  27. import java.awt.event.KeyEvent;
  28. import java.awt.event.KeyListener;
  29. import java.awt.event.WindowAdapter;
  30. import java.awt.event.WindowEvent;
  31. import java.io.IOException;
  32. import java.io.StreamTokenizer;
  33. import java.io.StringReader;
  34. import java.net.Socket;
  35. import java.util.ArrayList;
  36. import java.util.Arrays;
  37. import java.util.HashSet;
  38. import java.util.List;
  39. import java.util.Set;
  40. import java.util.Stack;
  41. import javax.swing.JComponent;
  42. import javax.swing.JFrame;
  43. import javax.swing.JMenu;
  44. import javax.swing.JMenuBar;
  45. import javax.swing.JMenuItem;
  46. import javax.swing.JOptionPane;
  47. import javax.swing.JPanel;
  48. import javax.swing.JSplitPane;
  49. import javax.swing.LayoutFocusTraversalPolicy;
  50. import javax.swing.MenuSelectionManager;
  51. import javax.swing.event.CaretEvent;
  52. import javax.swing.event.CaretListener;
  53. import org.gjt.sp.jedit.EditBus.EBHandler;
  54. import org.gjt.sp.jedit.bufferset.BufferSet;
  55. import org.gjt.sp.jedit.bufferset.BufferSetManager;
  56. import org.gjt.sp.jedit.gui.ActionBar;
  57. import org.gjt.sp.jedit.gui.CloseDialog;
  58. import org.gjt.sp.jedit.gui.DefaultInputHandler;
  59. import org.gjt.sp.jedit.gui.DockableWindowFactory;
  60. import org.gjt.sp.jedit.gui.DockableWindowManager;
  61. import org.gjt.sp.jedit.gui.HistoryModel;
  62. import org.gjt.sp.jedit.gui.DockingFrameworkProvider;
  63. import org.gjt.sp.jedit.gui.InputHandler;
  64. import org.gjt.sp.jedit.gui.StatusBar;
  65. import org.gjt.sp.jedit.gui.ToolBarManager;
  66. import org.gjt.sp.jedit.gui.VariableGridLayout;
  67. import org.gjt.sp.jedit.gui.DockableWindowManager.DockingLayout;
  68. import org.gjt.sp.jedit.input.InputHandlerProvider;
  69. import org.gjt.sp.jedit.msg.BufferUpdate;
  70. import org.gjt.sp.jedit.msg.EditPaneUpdate;
  71. import org.gjt.sp.jedit.msg.PropertiesChanged;
  72. import org.gjt.sp.jedit.msg.SearchSettingsChanged;
  73. import org.gjt.sp.jedit.msg.ViewUpdate;
  74. import org.gjt.sp.jedit.options.GeneralOptionPane;
  75. import org.gjt.sp.jedit.search.CurrentBufferSet;
  76. import org.gjt.sp.jedit.search.SearchAndReplace;
  77. import org.gjt.sp.jedit.search.SearchBar;
  78. import org.gjt.sp.jedit.textarea.JEditTextArea;
  79. import org.gjt.sp.jedit.textarea.ScrollListener;
  80. import org.gjt.sp.jedit.textarea.TextArea;
  81. import org.gjt.sp.jedit.visitors.JEditVisitor;
  82. import org.gjt.sp.jedit.visitors.JEditVisitorAdapter;
  83. import org.gjt.sp.util.Log;
  84. import org.gjt.sp.util.StandardUtilities;
  85. //}}}
  86. /**
  87. * A <code>View</code> is jEdit's top-level frame window.<p>
  88. *
  89. * In a BeanShell script, you can obtain the current view instance from the
  90. * <code>view</code> variable.<p>
  91. *
  92. * The largest component it contains is an {@link EditPane} that in turn
  93. * contains a {@link org.gjt.sp.jedit.textarea.JEditTextArea} that displays a
  94. * {@link Buffer}.
  95. * A view can have more than one edit pane in a split window configuration.
  96. * A view also contains a menu bar, an optional toolbar and other window
  97. * decorations, as well as docked windows.<p>
  98. *
  99. * The <b>View</b> class performs two important operations
  100. * dealing with plugins: creating plugin menu items, and managing dockable
  101. * windows.
  102. *
  103. * <ul>
  104. * <li>When a view is being created, its initialization routine
  105. * iterates through the collection of loaded plugins and constructs the
  106. * <b>Plugins</b> menu using the properties as specified in the
  107. * {@link EditPlugin} class.</li>
  108. * <li>The view also creates and initializes a
  109. * {@link org.gjt.sp.jedit.gui.DockableWindowManager}
  110. * object. This object is
  111. * responsible for creating, closing and managing dockable windows.</li>
  112. * </ul>
  113. *
  114. * This class does not have a public constructor.
  115. * Views can be opened and closed using methods in the <code>jEdit</code>
  116. * class.
  117. *
  118. * @see org.gjt.sp.jedit.jEdit#newView(View)
  119. * @see org.gjt.sp.jedit.jEdit#newView(View,Buffer)
  120. * @see org.gjt.sp.jedit.jEdit#newView(View,Buffer,boolean)
  121. * @see org.gjt.sp.jedit.jEdit#closeView(View)
  122. *
  123. * @author Slava Pestov
  124. * @author John Gellene (API documentation)
  125. * @version $Id: View.java 20108 2011-10-18 12:16:38Z evanpw $
  126. */
  127. public class View extends JFrame implements InputHandlerProvider
  128. {
  129. //{{{ User interface
  130. //{{{ ToolBar-related constants
  131. public static final String VIEW_DOCKING_FRAMEWORK_PROPERTY = "view.docking.framework";
  132. private static final String ORIGINAL_DOCKING_FRAMEWORK = "Original";
  133. public static final String DOCKING_FRAMEWORK_PROVIDER_SERVICE =
  134. "org.gjt.sp.jedit.gui.DockingFrameworkProvider";
  135. private static DockingFrameworkProvider dockingFrameworkProvider;
  136. //{{{ Groups
  137. /**
  138. * The group of tool bars above the DockableWindowManager
  139. * @see #addToolBar(int,int,java.awt.Component)
  140. * @since jEdit 4.0pre7
  141. */
  142. public static final int TOP_GROUP = 0;
  143. /**
  144. * The group of tool bars below the DockableWindowManager
  145. * @see #addToolBar(int,int,java.awt.Component)
  146. * @since jEdit 4.0pre7
  147. */
  148. public static final int BOTTOM_GROUP = 1;
  149. public static final int DEFAULT_GROUP = TOP_GROUP;
  150. //}}}
  151. //{{{ Layers
  152. // Common layers
  153. /**
  154. * The highest possible layer.
  155. * @see #addToolBar(int,int,java.awt.Component)
  156. * @since jEdit 4.0pre7
  157. */
  158. public static final int TOP_LAYER = Integer.MAX_VALUE;
  159. /**
  160. * The default layer for tool bars with no preference.
  161. * @see #addToolBar(int,int,java.awt.Component)
  162. * @since jEdit 4.0pre7
  163. */
  164. public static final int DEFAULT_LAYER = 0;
  165. /**
  166. * The lowest possible layer.
  167. * @see #addToolBar(int,int,java.awt.Component)
  168. * @since jEdit 4.0pre7
  169. */
  170. public static final int BOTTOM_LAYER = Integer.MIN_VALUE;
  171. // Layers for top group
  172. /**
  173. * Above system tool bar layer.
  174. * @see #addToolBar(int,int,java.awt.Component)
  175. * @since jEdit 4.0pre7
  176. */
  177. public static final int ABOVE_SYSTEM_BAR_LAYER = 150;
  178. /**
  179. * System tool bar layer.
  180. * jEdit uses this for the main tool bar.
  181. * @see #addToolBar(int,int,java.awt.Component)
  182. * @since jEdit 4.0pre7
  183. */
  184. public static final int SYSTEM_BAR_LAYER = 100;
  185. /**
  186. * Below system tool bar layer.
  187. * @see #addToolBar(int,int,java.awt.Component)
  188. * @since jEdit 4.0pre7
  189. */
  190. public static final int BELOW_SYSTEM_BAR_LAYER = 75;
  191. /**
  192. * Search bar layer.
  193. * @see #addToolBar(int,int,java.awt.Component)
  194. * @since jEdit 4.0pre7
  195. */
  196. public static final int SEARCH_BAR_LAYER = 75;
  197. /**
  198. * Below search bar layer.
  199. * @see #addToolBar(int,int,java.awt.Component)
  200. * @since jEdit 4.0pre7
  201. */
  202. public static final int BELOW_SEARCH_BAR_LAYER = 50;
  203. // Layers for bottom group
  204. /**
  205. * Action bar layer.
  206. * @see #addToolBar(int,int,java.awt.Component)
  207. * @since jEdit 4.2pre1
  208. */
  209. public static final int ACTION_BAR_LAYER = -75;
  210. /**
  211. * Status bar layer.
  212. * @see #addToolBar(int,int,java.awt.Component)
  213. * @since jEdit 4.2pre1
  214. */
  215. public static final int STATUS_BAR_LAYER = -100;
  216. /**
  217. * Status bar layer.
  218. * @see #addToolBar(int,int,java.awt.Component)
  219. * @since jEdit 4.2pre1
  220. */
  221. public static final int BELOW_STATUS_BAR_LAYER = -150;
  222. //}}}
  223. //}}}
  224. //{{{ getDockableWindowManager() method
  225. /**
  226. * Returns the dockable window manager associated with this view.
  227. * @since jEdit 2.6pre3
  228. */
  229. public DockableWindowManager getDockableWindowManager()
  230. {
  231. return dockableWindowManager;
  232. } //}}}
  233. //{{{ getDockingFrameworkName() method
  234. public static String getDockingFrameworkName()
  235. {
  236. String framework = jEdit.getProperty(
  237. VIEW_DOCKING_FRAMEWORK_PROPERTY, ORIGINAL_DOCKING_FRAMEWORK);
  238. return framework;
  239. } //}}}
  240. //{{{ getDockingFrameworkProvider() method
  241. public static DockingFrameworkProvider getDockingFrameworkProvider()
  242. {
  243. if (dockingFrameworkProvider == null)
  244. {
  245. String framework = getDockingFrameworkName();
  246. dockingFrameworkProvider = (DockingFrameworkProvider)
  247. ServiceManager.getService(
  248. DOCKING_FRAMEWORK_PROVIDER_SERVICE, framework);
  249. if (dockingFrameworkProvider == null)
  250. {
  251. Log.log(Log.ERROR, View.class, "No docking framework " + framework +
  252. " available, using the original one");
  253. dockingFrameworkProvider = (DockingFrameworkProvider)
  254. ServiceManager.getService(
  255. DOCKING_FRAMEWORK_PROVIDER_SERVICE, ORIGINAL_DOCKING_FRAMEWORK);
  256. }
  257. }
  258. return dockingFrameworkProvider;
  259. } //}}}
  260. //{{{ getToolBar() method
  261. /**
  262. * Returns the view's tool bar.
  263. * @since jEdit 4.2pre1
  264. */
  265. public Container getToolBar()
  266. {
  267. return toolBar;
  268. } //}}}
  269. //{{{ addToolBar() methods
  270. /**
  271. * Adds a tool bar to this view.
  272. * @param toolBar The tool bar
  273. */
  274. public void addToolBar(Component toolBar)
  275. {
  276. addToolBar(DEFAULT_GROUP, DEFAULT_LAYER, toolBar);
  277. }
  278. /**
  279. * Adds a tool bar to this view.
  280. * @param group The tool bar group to add to
  281. * @param toolBar The tool bar
  282. * @see org.gjt.sp.jedit.gui.ToolBarManager
  283. * @since jEdit 4.0pre7
  284. */
  285. public void addToolBar(int group, Component toolBar)
  286. {
  287. addToolBar(group, DEFAULT_LAYER, toolBar);
  288. }
  289. /**
  290. * Adds a tool bar to this view.
  291. * @param group The tool bar group to add to
  292. * @param layer The layer of the group to add to
  293. * @param toolBar The tool bar
  294. * @see org.gjt.sp.jedit.gui.ToolBarManager
  295. * @since jEdit 4.0pre7
  296. */
  297. public void addToolBar(int group, int layer, Component toolBar)
  298. {
  299. toolBarManager.addToolBar(group, layer, toolBar);
  300. getRootPane().revalidate();
  301. } //}}}
  302. //{{{ removeToolBar() method
  303. /**
  304. * Removes a tool bar from this view.
  305. * @param toolBar The tool bar
  306. */
  307. public void removeToolBar(Component toolBar)
  308. {
  309. if (toolBarManager == null) return;
  310. if (toolBar == null) return;
  311. toolBarManager.removeToolBar(toolBar);
  312. getRootPane().revalidate();
  313. } //}}}
  314. //{{{ showWaitCursor() method
  315. /**
  316. * Shows the wait cursor. This method and
  317. * {@link #hideWaitCursor()} are implemented using a reference
  318. * count of requests for wait cursors, so that nested calls work
  319. * correctly; however, you should be careful to use these methods in
  320. * tandem.<p>
  321. *
  322. * To ensure that {@link #hideWaitCursor()} is always called
  323. * after a {@link #showWaitCursor()}, use a
  324. * <code>try</code>/<code>finally</code> block, like this:
  325. * <pre>try
  326. *{
  327. * view.showWaitCursor();
  328. * // ...
  329. *}
  330. *finally
  331. *{
  332. * view.hideWaitCursor();
  333. *}</pre>
  334. */
  335. public synchronized void showWaitCursor()
  336. {
  337. if(waitCount++ == 0)
  338. {
  339. Cursor cursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
  340. setCursor(cursor);
  341. visit(new SetCursorVisitor(cursor));
  342. }
  343. } //}}}
  344. //{{{ hideWaitCursor() method
  345. /**
  346. * Hides the wait cursor.
  347. */
  348. public synchronized void hideWaitCursor()
  349. {
  350. if(waitCount > 0)
  351. waitCount--;
  352. if(waitCount == 0)
  353. {
  354. // still needed even though glass pane
  355. // has a wait cursor
  356. Cursor cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  357. setCursor(cursor);
  358. visit(new SetCursorVisitor(cursor));
  359. }
  360. } //}}}
  361. //{{{ getSearchBar() method
  362. /**
  363. * Returns the search bar.
  364. * @since jEdit 2.4pre4
  365. */
  366. public final SearchBar getSearchBar()
  367. {
  368. return searchBar;
  369. } //}}}
  370. //{{{ getActionBar() method
  371. /**
  372. * Returns the action bar.
  373. * @since jEdit 4.2pre3
  374. */
  375. public final ActionBar getActionBar()
  376. {
  377. return actionBar;
  378. } //}}}
  379. //{{{ getStatus() method
  380. /**
  381. * Returns the status bar. The
  382. * {@link org.gjt.sp.jedit.gui.StatusBar#setMessage(String)} and
  383. * {@link org.gjt.sp.jedit.gui.StatusBar#setMessageAndClear(String)} methods can
  384. * be called on the return value of this method to display status
  385. * information to the user.
  386. * @since jEdit 3.2pre2
  387. */
  388. public StatusBar getStatus()
  389. {
  390. return status;
  391. } //}}}
  392. //{{{ quickIncrementalSearch() method
  393. /**
  394. * Quick search.
  395. * @since jEdit 4.0pre3
  396. */
  397. public void quickIncrementalSearch(boolean word)
  398. {
  399. if(searchBar == null)
  400. searchBar = new SearchBar(this,true);
  401. if(searchBar.getParent() == null)
  402. addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
  403. searchBar.setHyperSearch(false);
  404. JEditTextArea textArea = getTextArea();
  405. if(word)
  406. {
  407. String text = textArea.getSelectedText();
  408. if(text == null)
  409. {
  410. textArea.selectWord();
  411. text = textArea.getSelectedText();
  412. }
  413. else if(text.indexOf('\n') != -1)
  414. text = null;
  415. if(text != null && SearchAndReplace.getRegexp())
  416. text = SearchAndReplace.escapeRegexp(text,false);
  417. searchBar.getField().setText(text);
  418. }
  419. searchBar.getField().requestFocus();
  420. searchBar.getField().selectAll();
  421. } //}}}
  422. //{{{ quickHyperSearch() method
  423. /**
  424. * Quick HyperSearch.
  425. * @since jEdit 4.0pre3
  426. */
  427. public void quickHyperSearch(boolean word)
  428. {
  429. JEditTextArea textArea = getTextArea();
  430. if(word)
  431. {
  432. String text = textArea.getSelectedText();
  433. if(text == null)
  434. {
  435. textArea.selectWord();
  436. text = textArea.getSelectedText();
  437. }
  438. if(text != null && text.indexOf('\n') == -1)
  439. {
  440. if(SearchAndReplace.getRegexp())
  441. {
  442. text = SearchAndReplace.escapeRegexp(
  443. text,false);
  444. }
  445. HistoryModel.getModel("find").addItem(text);
  446. SearchAndReplace.setSearchString(text);
  447. SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
  448. SearchAndReplace.hyperSearch(this);
  449. return;
  450. }
  451. }
  452. if(searchBar == null)
  453. searchBar = new SearchBar(this,true);
  454. if(searchBar.getParent() == null)
  455. addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
  456. searchBar.setHyperSearch(true);
  457. searchBar.getField().setText(null);
  458. searchBar.getField().requestFocus();
  459. searchBar.getField().selectAll();
  460. } //}}}
  461. //{{{ actionBar() method
  462. /**
  463. * Shows the action bar if needed, and sends keyboard focus there.
  464. * @since jEdit 4.2pre1
  465. */
  466. public void actionBar()
  467. {
  468. if(actionBar == null)
  469. actionBar = new ActionBar(this,true);
  470. if(actionBar.getParent() == null)
  471. addToolBar(BOTTOM_GROUP,ACTION_BAR_LAYER,actionBar);
  472. actionBar.goToActionBar();
  473. } //}}}
  474. //}}}
  475. //{{{ Input handling
  476. //{{{ getKeyEventInterceptor() method
  477. /**
  478. * Returns the listener that will handle all key events in this
  479. * view, if any.
  480. * @return the key event interceptor or null
  481. */
  482. public KeyListener getKeyEventInterceptor()
  483. {
  484. return inputHandler.getKeyEventInterceptor();
  485. } //}}}
  486. //{{{ setKeyEventInterceptor() method
  487. /**
  488. * Sets the listener that will handle all key events in this
  489. * view. For example, the complete word command uses this so
  490. * that all key events are passed to the word list popup while
  491. * it is visible.
  492. * @param listener The key event interceptor.
  493. */
  494. public void setKeyEventInterceptor(KeyListener listener)
  495. {
  496. inputHandler.setKeyEventInterceptor(listener);
  497. } //}}}
  498. //{{{ getInputHandler() method
  499. /**
  500. * Returns the input handler.
  501. */
  502. public InputHandler getInputHandler()
  503. {
  504. return inputHandler;
  505. } //}}}
  506. //{{{ setInputHandler() method
  507. /**
  508. * Sets the input handler.
  509. * @param inputHandler The new input handler
  510. */
  511. public void setInputHandler(InputHandler inputHandler)
  512. {
  513. this.inputHandler = inputHandler;
  514. } //}}}
  515. //{{{ getMacroRecorder() method
  516. /**
  517. * Returns the macro recorder.
  518. */
  519. public Macros.Recorder getMacroRecorder()
  520. {
  521. return recorder;
  522. } //}}}
  523. //{{{ setMacroRecorder() method
  524. /**
  525. * Sets the macro recorder.
  526. * @param recorder The macro recorder
  527. */
  528. public void setMacroRecorder(Macros.Recorder recorder)
  529. {
  530. this.recorder = recorder;
  531. } //}}}
  532. //{{{ processKeyEvent() method
  533. /**
  534. * Forwards key events directly to the input handler.
  535. * This is slightly faster than using a KeyListener
  536. * because some Swing overhead is avoided.
  537. */
  538. @Override
  539. public void processKeyEvent(KeyEvent evt)
  540. {
  541. inputHandler.processKeyEvent(evt,VIEW, false);
  542. if(!evt.isConsumed())
  543. super.processKeyEvent(evt);
  544. } //}}}
  545. //{{{ processKeyEvent() method
  546. /**
  547. * Forwards key events directly to the input handler.
  548. * This is slightly faster than using a KeyListener
  549. * because some Swing overhead is avoided.
  550. */
  551. public void processKeyEvent(KeyEvent evt, boolean calledFromTextArea)
  552. {
  553. processKeyEvent(evt,calledFromTextArea
  554. ? TEXT_AREA
  555. : VIEW);
  556. } //}}}
  557. //{{{ processKeyEvent() method
  558. public static final int VIEW = 0;
  559. public static final int TEXT_AREA = 1;
  560. public static final int ACTION_BAR = 2;
  561. /**
  562. * Forwards key events directly to the input handler.
  563. * This is slightly faster than using a KeyListener
  564. * because some Swing overhead is avoided.
  565. */
  566. public void processKeyEvent(KeyEvent evt, int from)
  567. {
  568. inputHandler.processKeyEvent(evt, from, false);
  569. if(!evt.isConsumed())
  570. super.processKeyEvent(evt);
  571. }
  572. //}}}
  573. //}}}
  574. //{{{ Buffers, edit panes, split panes
  575. //{{{ splitHorizontally() method
  576. /**
  577. * Splits the view horizontally.
  578. * @return the new editPane
  579. * @since jEdit 4.1pre2
  580. */
  581. public EditPane splitHorizontally()
  582. {
  583. return split(JSplitPane.VERTICAL_SPLIT);
  584. } //}}}
  585. //{{{ splitVertically() method
  586. /**
  587. * Splits the view vertically.
  588. * @return the new editPane
  589. * @since jEdit 4.1pre2
  590. */
  591. public EditPane splitVertically()
  592. {
  593. return split(JSplitPane.HORIZONTAL_SPLIT);
  594. } //}}}
  595. //{{{ split() method
  596. /**
  597. * Splits the view.
  598. * @param orientation the orientation {@link javax.swing.JSplitPane#HORIZONTAL_SPLIT} or
  599. * {@link javax.swing.JSplitPane#VERTICAL_SPLIT}
  600. * @return the new editPane
  601. * @since jEdit 4.1pre2
  602. */
  603. public EditPane split(int orientation)
  604. {
  605. PerspectiveManager.setPerspectiveDirty(true);
  606. editPane.saveCaretInfo();
  607. EditPane oldEditPane = editPane;
  608. EditPane newEditPane = createEditPane(oldEditPane);
  609. // setEditPane(newEditPane);
  610. newEditPane.loadCaretInfo();
  611. JComponent oldParent = (JComponent)oldEditPane.getParent();
  612. final JSplitPane newSplitPane = new JSplitPane(orientation,
  613. jEdit.getBooleanProperty("appearance.continuousLayout"));
  614. newSplitPane.setOneTouchExpandable(true);
  615. newSplitPane.setBorder(null);
  616. newSplitPane.setMinimumSize(new Dimension(0,0));
  617. newSplitPane.setResizeWeight(0.5);
  618. int parentSize = orientation == JSplitPane.VERTICAL_SPLIT
  619. ? oldEditPane.getHeight() : oldEditPane.getWidth();
  620. final int dividerPosition = (int)((parentSize
  621. - newSplitPane.getDividerSize()) * 0.5);
  622. newSplitPane.setDividerLocation(dividerPosition);
  623. if(oldParent instanceof JSplitPane)
  624. {
  625. JSplitPane oldSplitPane = (JSplitPane)oldParent;
  626. int dividerPos = oldSplitPane.getDividerLocation();
  627. Component left = oldSplitPane.getLeftComponent();
  628. if(left == oldEditPane)
  629. oldSplitPane.setLeftComponent(newSplitPane);
  630. else
  631. oldSplitPane.setRightComponent(newSplitPane);
  632. newSplitPane.setLeftComponent(oldEditPane);
  633. newSplitPane.setRightComponent(newEditPane);
  634. oldSplitPane.setDividerLocation(dividerPos);
  635. }
  636. else
  637. {
  638. splitPane = newSplitPane;
  639. newSplitPane.setLeftComponent(oldEditPane);
  640. newSplitPane.setRightComponent(newEditPane);
  641. setMainContent(newSplitPane);
  642. }
  643. EventQueue.invokeLater(new Runnable()
  644. {
  645. public void run()
  646. {
  647. newSplitPane.setDividerLocation(dividerPosition);
  648. }
  649. });
  650. newEditPane.focusOnTextArea();
  651. return newEditPane;
  652. } //}}}
  653. //{{{ unsplit() method
  654. /**
  655. * Unsplits the view.
  656. * @since jEdit 2.3pre2
  657. */
  658. public void unsplit()
  659. {
  660. if(splitPane != null)
  661. {
  662. lastSplitConfig = getSplitConfig();
  663. PerspectiveManager.setPerspectiveDirty(true);
  664. BufferSet.Scope scope = jEdit.getBufferSetManager().getScope();
  665. for(EditPane _editPane: getEditPanes())
  666. {
  667. if(editPane != _editPane)
  668. {
  669. if (scope == BufferSet.Scope.editpane)
  670. mergeBufferSets(editPane, _editPane);
  671. _editPane.close();
  672. }
  673. }
  674. setMainContent(editPane);
  675. splitPane = null;
  676. updateTitle();
  677. editPane.focusOnTextArea();
  678. }
  679. else
  680. getToolkit().beep();
  681. } //}}}
  682. //{{{ unsplitCurrent() method
  683. /**
  684. * Removes the current split.
  685. * @since jEdit 2.3pre2
  686. */
  687. public void unsplitCurrent()
  688. {
  689. if(splitPane != null)
  690. {
  691. lastSplitConfig = getSplitConfig();
  692. PerspectiveManager.setPerspectiveDirty(true);
  693. // find first split pane parenting current edit pane
  694. Component comp = editPane;
  695. while(!(comp instanceof JSplitPane) && comp != null)
  696. {
  697. comp = comp.getParent();
  698. }
  699. BufferSet.Scope scope = jEdit.getBufferSetManager().getScope();
  700. // get rid of any edit pane that is a child
  701. // of the current edit pane's parent splitter
  702. for(EditPane _editPane: getEditPanes())
  703. {
  704. if(GUIUtilities.isAncestorOf(comp,_editPane)
  705. && _editPane != editPane)
  706. {
  707. if (scope == BufferSet.Scope.editpane)
  708. mergeBufferSets(editPane, _editPane);
  709. _editPane.close();
  710. }
  711. }
  712. JComponent parent = comp == null ? null : (JComponent)comp.getParent();
  713. if(parent instanceof JSplitPane)
  714. {
  715. JSplitPane parentSplit = (JSplitPane)parent;
  716. int pos = parentSplit.getDividerLocation();
  717. if(parentSplit.getLeftComponent() == comp)
  718. parentSplit.setLeftComponent(editPane);
  719. else
  720. parentSplit.setRightComponent(editPane);
  721. parentSplit.setDividerLocation(pos);
  722. parent.revalidate();
  723. }
  724. else
  725. {
  726. setMainContent(editPane);
  727. splitPane = null;
  728. }
  729. updateTitle();
  730. editPane.focusOnTextArea();
  731. }
  732. else
  733. getToolkit().beep();
  734. } //}}}
  735. //{{{ resplit() method
  736. /**
  737. * Restore the split configuration as it was before unsplitting.
  738. *
  739. * @since jEdit 4.3pre1
  740. */
  741. public void resplit()
  742. {
  743. if(lastSplitConfig == null)
  744. getToolkit().beep();
  745. else
  746. setSplitConfig(null,lastSplitConfig);
  747. } //}}}
  748. //{{{ getSplitConfig() method
  749. /**
  750. * Split configurations are recorded in a simple RPN "language".
  751. * @return The split configuration, describing where splitpanes
  752. * are, which buffers are open in each EditPane, etc.
  753. *
  754. */
  755. public String getSplitConfig()
  756. {
  757. StringBuilder splitConfig = new StringBuilder();
  758. if(splitPane != null)
  759. getSplitConfig(splitPane,splitConfig);
  760. else
  761. {
  762. appendToSplitConfig(splitConfig, editPane);
  763. }
  764. return splitConfig.toString();
  765. } //}}}
  766. //{{{ setSplitConfig() method
  767. /**
  768. * sets the split configuration as per the splitConfig.
  769. *
  770. * @param buffer if null, checks all buffers to restore View's split config.
  771. * @param splitConfig the split config, as returned by getSplitConfig()
  772. */
  773. public void setSplitConfig(Buffer buffer, String splitConfig)
  774. {
  775. try
  776. {
  777. Component comp = restoreSplitConfig(buffer,splitConfig);
  778. setMainContent(comp);
  779. updateTitle();
  780. }
  781. catch(IOException e)
  782. {
  783. // this should never throw an exception.
  784. throw new InternalError();
  785. }
  786. } //}}}
  787. //{{{ nextTextArea() method
  788. /**
  789. * Moves keyboard focus to the next text area.
  790. * @since jEdit 2.7pre4
  791. */
  792. public void nextTextArea()
  793. {
  794. EditPane[] editPanes = getEditPanes();
  795. for(int i = 0; i < editPanes.length; i++)
  796. {
  797. if(editPane == editPanes[i])
  798. {
  799. if(i == editPanes.length - 1)
  800. editPanes[0].focusOnTextArea();
  801. else
  802. editPanes[i+1].focusOnTextArea();
  803. break;
  804. }
  805. }
  806. } //}}}
  807. //{{{ prevTextArea() method
  808. /**
  809. * Moves keyboard focus to the previous text area.
  810. * @since jEdit 2.7pre4
  811. */
  812. public void prevTextArea()
  813. {
  814. EditPane[] editPanes = getEditPanes();
  815. for(int i = 0; i < editPanes.length; i++)
  816. {
  817. if(editPane == editPanes[i])
  818. {
  819. if(i == 0)
  820. editPanes[editPanes.length - 1].focusOnTextArea();
  821. else
  822. editPanes[i-1].focusOnTextArea();
  823. break;
  824. }
  825. }
  826. } //}}}
  827. //{{{ getSplitPane() method
  828. /**
  829. * Returns the top-level split pane, if any.
  830. * @return the top JSplitPane if any.
  831. * @since jEdit 2.3pre2
  832. */
  833. public JSplitPane getSplitPane()
  834. {
  835. return splitPane;
  836. } //}}}
  837. //{{{ getBuffer() method
  838. /**
  839. * Returns the current edit pane's buffer.
  840. * @return the current edit pane's buffer, it can be null
  841. */
  842. public Buffer getBuffer()
  843. {
  844. if(editPane == null)
  845. return null;
  846. else
  847. return editPane.getBuffer();
  848. } //}}}
  849. //{{{ setBuffer() method
  850. /**
  851. * Sets the current edit pane's buffer.
  852. * @param buffer The buffer
  853. */
  854. public void setBuffer(Buffer buffer)
  855. {
  856. setBuffer(buffer,false);
  857. } //}}}
  858. //{{{ setBuffer() method
  859. /**
  860. * Sets the current edit pane's buffer.
  861. * @param buffer The buffer
  862. * @param disableFileStatusCheck Disables file status checking
  863. * regardless of the state of the checkFileStatus property
  864. */
  865. public void setBuffer(Buffer buffer, boolean disableFileStatusCheck)
  866. {
  867. setBuffer(buffer, disableFileStatusCheck, true);
  868. } //}}}
  869. //{{{ setBuffer() method
  870. /**
  871. * Sets the current edit pane's buffer.
  872. * @param buffer The buffer
  873. * @param disableFileStatusCheck Disables file status checking
  874. * regardless of the state of the checkFileStatus property
  875. * @param focus Whether the textarea should request focus
  876. * @since jEdit 4.3pre13
  877. */
  878. public void setBuffer(Buffer buffer, boolean disableFileStatusCheck, boolean focus)
  879. {
  880. editPane.setBuffer(buffer, focus);
  881. int check = jEdit.getIntegerProperty("checkFileStatus");
  882. if(!disableFileStatusCheck && (check == GeneralOptionPane.checkFileStatus_all ||
  883. check == GeneralOptionPane.checkFileStatus_operations ||
  884. check == GeneralOptionPane.checkFileStatus_focusBuffer))
  885. jEdit.checkBufferStatus(this, true);
  886. } //}}}
  887. //{{{ goToBuffer() method
  888. /**
  889. * If this buffer is open in one of the view's edit panes, sets focus
  890. * to that edit pane. Otherwise, opens the buffer in the currently
  891. * active edit pane.
  892. * @param buffer The buffer
  893. * @return the current edit pane
  894. * @since jEdit 4.2pre1
  895. */
  896. public EditPane goToBuffer(Buffer buffer)
  897. {
  898. return showBuffer(buffer, true);
  899. } //}}}
  900. //{{{ showBuffer() method
  901. /**
  902. * If this buffer is open in one of the view's edit panes, activates
  903. * that edit pane. Otherwise, opens the buffer in the currently
  904. * active edit pane. But the focus is not moved.
  905. * @param buffer The buffer to show
  906. * @return the current edit pane
  907. * @since jEdit 4.3pre13
  908. */
  909. public EditPane showBuffer(Buffer buffer)
  910. {
  911. return showBuffer(buffer, false);
  912. } //}}}
  913. //{{{ getTextArea() method
  914. /**
  915. * Returns the current edit pane's text area.
  916. * @return the current edit pane's text area, or <b>null</b> if there is no edit pane yet
  917. */
  918. public JEditTextArea getTextArea()
  919. {
  920. if(editPane == null)
  921. return null;
  922. else
  923. return editPane.getTextArea();
  924. } //}}}
  925. //{{{ getEditPane() method
  926. /**
  927. * Returns the current edit pane.
  928. * @return the current edit pane
  929. * @since jEdit 2.5pre2
  930. */
  931. public EditPane getEditPane()
  932. {
  933. return editPane;
  934. } //}}}
  935. //{{{ getEditPanes() method
  936. /**
  937. * Returns all edit panes.
  938. * @return an array of all edit panes in the view
  939. * @since jEdit 2.5pre2
  940. */
  941. public EditPane[] getEditPanes()
  942. {
  943. if(splitPane == null)
  944. {
  945. EditPane[] ep = { editPane };
  946. return ep;
  947. }
  948. else
  949. {
  950. List<EditPane> vec = new ArrayList<EditPane>();
  951. getEditPanes(vec,splitPane);
  952. EditPane[] ep = new EditPane[vec.size()];
  953. vec.toArray(ep);
  954. return ep;
  955. }
  956. } //}}}
  957. //{{{ getViewConfig() method
  958. /**
  959. * @return a ViewConfig instance for the current view
  960. * @since jEdit 4.2pre1
  961. */
  962. public ViewConfig getViewConfig()
  963. {
  964. ViewConfig config = new ViewConfig();
  965. config.plainView = isPlainView();
  966. config.splitConfig = getSplitConfig();
  967. config.extState = getExtendedState();
  968. config.docking = dockableWindowManager.getDockingLayout(config);
  969. config.title = userTitle;
  970. String prefix = config.plainView ? "plain-view" : "view";
  971. switch (config.extState)
  972. {
  973. case Frame.MAXIMIZED_BOTH:
  974. case Frame.ICONIFIED:
  975. config.x = jEdit.getIntegerProperty(prefix + ".x",getX());
  976. config.y = jEdit.getIntegerProperty(prefix + ".y",getY());
  977. config.width = jEdit.getIntegerProperty(prefix + ".width",getWidth());
  978. config.height = jEdit.getIntegerProperty(prefix + ".height",getHeight());
  979. break;
  980. case Frame.MAXIMIZED_VERT:
  981. config.x = getX();
  982. config.y = jEdit.getIntegerProperty(prefix + ".y",getY());
  983. config.width = getWidth();
  984. config.height = jEdit.getIntegerProperty(prefix + ".height",getHeight());
  985. break;
  986. case Frame.MAXIMIZED_HORIZ:
  987. config.x = jEdit.getIntegerProperty(prefix + ".x",getX());
  988. config.y = getY();
  989. config.width = jEdit.getIntegerProperty(prefix + ".width",getWidth());
  990. config.height = getHeight();
  991. break;
  992. case Frame.NORMAL:
  993. default:
  994. config.x = getX();
  995. config.y = getY();
  996. config.width = getWidth();
  997. config.height = getHeight();
  998. break;
  999. }
  1000. return config;
  1001. } //}}}
  1002. //}}}
  1003. //{{{ isClosed() method
  1004. /**
  1005. * Returns true if this view has been closed with
  1006. * {@link jEdit#closeView(View)}.
  1007. * @return true if the view is closed
  1008. */
  1009. public boolean isClosed()
  1010. {
  1011. return closed;
  1012. } //}}}
  1013. //{{{ isPlainView() method
  1014. /**
  1015. * Returns true if this is an auxilliary view with no dockable windows.
  1016. * @return true if the view is plain
  1017. * @since jEdit 4.1pre2
  1018. */
  1019. public boolean isPlainView()
  1020. {
  1021. return plainView;
  1022. } //}}}
  1023. //{{{ getNext() method
  1024. /**
  1025. * Returns the next view in the list.
  1026. * @return the next view
  1027. */
  1028. public View getNext()
  1029. {
  1030. return next;
  1031. } //}}}
  1032. //{{{ getPrev() method
  1033. /**
  1034. * Returns the previous view in the list.
  1035. * @return the preview view
  1036. */
  1037. public View getPrev()
  1038. {
  1039. return prev;
  1040. } //}}}
  1041. //{{{ handlePropertiesChanged()
  1042. @EBHandler
  1043. public void handlePropertiesChanged(PropertiesChanged msg)
  1044. {
  1045. propertiesChanged();
  1046. } //}}}
  1047. //{{{ handleSearchSettingsChanged() method
  1048. @EBHandler
  1049. public void handleSearchSettingsChanged(SearchSettingsChanged msg)
  1050. {
  1051. if(searchBar != null)
  1052. searchBar.update();
  1053. } //}}}
  1054. //{{{ getMinimumSize() method
  1055. @Override
  1056. public Dimension getMinimumSize()
  1057. {
  1058. return new Dimension(0,0);
  1059. } //}}}
  1060. //{{{ setWaitSocket() method
  1061. /**
  1062. * This socket is closed when the buffer is closed.
  1063. */
  1064. public void setWaitSocket(Socket waitSocket)
  1065. {
  1066. this.waitSocket = waitSocket;
  1067. } //}}}
  1068. //{{{ toString() method
  1069. @Override
  1070. public String toString()
  1071. {
  1072. return getClass().getName() + '['
  1073. + (jEdit.getActiveView() == this
  1074. ? "active" : "inactive")
  1075. + ']';
  1076. } //}}}
  1077. //{{{ updateTitle() method
  1078. /**
  1079. * Updates the title bar.
  1080. */
  1081. public void updateTitle()
  1082. {
  1083. List<Buffer> buffers = new ArrayList<Buffer>();
  1084. EditPane[] editPanes = getEditPanes();
  1085. for(int i = 0; i < editPanes.length; i++)
  1086. {
  1087. Buffer buffer = editPanes[i].getBuffer();
  1088. if(!buffers.contains(buffer))
  1089. buffers.add(buffer);
  1090. }
  1091. StringBuilder title = new StringBuilder();
  1092. /* On Mac OS X, apps are not supposed to show their name in the
  1093. title bar. */
  1094. if(!OperatingSystem.isMacOS())
  1095. {
  1096. if (userTitle != null)
  1097. title.append(userTitle);
  1098. else
  1099. title.append(jEdit.getProperty("view.title"));
  1100. }
  1101. for(int i = 0; i < buffers.size(); i++)
  1102. {
  1103. if(i != 0)
  1104. title.append(", ");
  1105. Buffer buffer = buffers.get(i);
  1106. title.append(showFullPath && !buffer.isNewFile()
  1107. ? buffer.getPath(true) : buffer.getName());
  1108. if(buffer.isDirty())
  1109. title.append(jEdit.getProperty("view.title.dirty"));
  1110. }
  1111. setTitle(title.toString());
  1112. } //}}}
  1113. //{{{ setUserTitle() method
  1114. /**
  1115. * Sets a user-defined title for this view instead of the "view.title" property.
  1116. */
  1117. public void setUserTitle(String title)
  1118. {
  1119. userTitle = title + " - ";
  1120. updateTitle();
  1121. } //}}}
  1122. //{{{ showUserTitleDialog() method
  1123. /**
  1124. * Shows a dialog for selecting a user-defined title for this view.
  1125. */
  1126. public void showUserTitleDialog()
  1127. {
  1128. String title = JOptionPane.showInputDialog(this, jEdit.getProperty(
  1129. "view.title.select"));
  1130. if (title == null)
  1131. return;
  1132. setUserTitle(title);
  1133. } //}}}
  1134. //{{{ getPrefixFocusOwner() method
  1135. public Component getPrefixFocusOwner()
  1136. {
  1137. return prefixFocusOwner;
  1138. } //}}}
  1139. //{{{ setPrefixFocusOwner() method
  1140. public void setPrefixFocusOwner(Component prefixFocusOwner)
  1141. {
  1142. this.prefixFocusOwner = prefixFocusOwner;
  1143. } //}}}
  1144. //{{{ visit() method
  1145. /**
  1146. * Visit the the editpanes and textareas of the view
  1147. * @param visitor the visitor
  1148. * @since jEdit 4.3pre13
  1149. */
  1150. public void visit(JEditVisitor visitor)
  1151. {
  1152. EditPane[] panes = getEditPanes();
  1153. for (int i = 0; i < panes.length; i++)
  1154. {
  1155. EditPane editPane = panes[i];
  1156. visitor.visit(editPane);
  1157. visitor.visit(editPane.getTextArea());
  1158. }
  1159. } //}}}
  1160. // {{{ closeAllMenus()
  1161. /** closes any popup menus that may have been opened
  1162. @since jEdit 4.4pre1
  1163. */
  1164. public void closeAllMenus()
  1165. {
  1166. MenuSelectionManager.defaultManager().clearSelectedPath();
  1167. KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
  1168. } // }}}
  1169. //{{{ Package-private members
  1170. View prev;
  1171. View next;
  1172. //{{{ View constructor
  1173. View(Buffer buffer, ViewConfig config)
  1174. {
  1175. fullScreenMode = false;
  1176. menuBar = null;
  1177. plainView = config.plainView;
  1178. enableEvents(AWTEvent.KEY_EVENT_MASK);
  1179. setIconImage(GUIUtilities.getEditorIcon());
  1180. mainPanel = new JPanel();
  1181. mainPanel.setLayout(new BorderLayout());
  1182. dockableWindowManager = getDockingFrameworkProvider().create(this,
  1183. DockableWindowFactory.getInstance(), config);
  1184. userTitle = config.title;
  1185. dockableWindowManager.setMainPanel(mainPanel);
  1186. topToolBars = new JPanel(new VariableGridLayout(
  1187. VariableGridLayout.FIXED_NUM_COLUMNS,
  1188. 1));
  1189. bottomToolBars = new JPanel(new VariableGridLayout(
  1190. VariableGridLayout.FIXED_NUM_COLUMNS,
  1191. 1));
  1192. toolBarManager = new ToolBarManager(topToolBars, bottomToolBars);
  1193. status = new StatusBar(this);
  1194. inputHandler = new DefaultInputHandler(this,(DefaultInputHandler)
  1195. jEdit.getInputHandler());
  1196. setSplitConfig(buffer,config.splitConfig);
  1197. getContentPane().add(BorderLayout.CENTER,dockableWindowManager);
  1198. dockableWindowManager.init();
  1199. // tool bar and status bar gets added in propertiesChanged()
  1200. // depending in the 'tool bar alternate layout' setting.
  1201. propertiesChanged();
  1202. setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
  1203. addWindowListener(new WindowHandler());
  1204. setFocusTraversalPolicy(new MyFocusTraversalPolicy());
  1205. EditBus.addToBus(this);
  1206. GUIUtilities.addSizeSaver(this, null, plainView ? "plain-view" : "view");
  1207. } //}}}
  1208. //{{{ updateFullScreenProps() method
  1209. public void updateFullScreenProps()
  1210. {
  1211. boolean alternateLayout = jEdit.getBooleanProperty(
  1212. "view.toolbar.alternateLayout");
  1213. boolean showMenu = jEdit.getBooleanProperty("fullScreenIncludesMenu");
  1214. boolean showToolbars = jEdit.getBooleanProperty("fullScreenIncludesToolbar");
  1215. boolean showStatus = jEdit.getBooleanProperty("fullScreenIncludesStatus");
  1216. if (! showMenu)
  1217. {
  1218. menuBar = getJMenuBar();
  1219. setJMenuBar(null);
  1220. }
  1221. else if (menuBar != null)
  1222. setJMenuBar(menuBar);
  1223. // Note: Bottom toolbar is the action bar, which is always enabled
  1224. loadToolBars();
  1225. if (alternateLayout)
  1226. {
  1227. if (! showStatus)
  1228. removeToolBar(status);
  1229. else
  1230. addToolBar(BOTTOM_GROUP,STATUS_BAR_LAYER,status);
  1231. }
  1232. else
  1233. {
  1234. if (! showStatus)
  1235. getContentPane().remove(status);
  1236. else
  1237. getContentPane().add(BorderLayout.SOUTH,status);
  1238. }
  1239. } //}}}
  1240. //{{{ toggleFullScreen() method
  1241. public void toggleFullScreen()
  1242. {
  1243. fullScreenMode = (! fullScreenMode);
  1244. GraphicsDevice sd = getGraphicsConfiguration().getDevice();
  1245. dispose();
  1246. if (fullScreenMode)
  1247. {
  1248. updateFullScreenProps();
  1249. windowedBounds = getBounds();
  1250. setUndecorated(true);
  1251. setBounds(sd.getDefaultConfiguration().getBounds());
  1252. validate();
  1253. }
  1254. else
  1255. {
  1256. boolean showStatus = plainView ? jEdit.getBooleanProperty("view.status.plainview.visible") :
  1257. jEdit.getBooleanProperty("view.status.visible");
  1258. if ((menuBar != null) && (getJMenuBar() != menuBar))
  1259. setJMenuBar(menuBar);
  1260. boolean alternateLayout = jEdit.getBooleanProperty(
  1261. "view.toolbar.alternateLayout");
  1262. loadToolBars();
  1263. if (showStatus)
  1264. {
  1265. if (alternateLayout)
  1266. addToolBar(BOTTOM_GROUP,STATUS_BAR_LAYER,status);
  1267. else
  1268. getContentPane().add(BorderLayout.SOUTH,status);
  1269. }
  1270. setUndecorated(false);
  1271. setBounds(windowedBounds);
  1272. }
  1273. setVisible(true);
  1274. toFront();
  1275. closeAllMenus();
  1276. // so you can keep typing in your editpane afterwards...
  1277. editPane.getTextArea().requestFocus();
  1278. } //}}}
  1279. //{{{ confirmToCloseDirty() methods
  1280. /**
  1281. * If the view contains dirty buffers which will be closed on
  1282. * closing the view, show the confirmation dialog for user.
  1283. * @return
  1284. * true if there are no such buffers or user select OK
  1285. * to close the view; false if user select Cancel
  1286. */
  1287. boolean confirmToCloseDirty()
  1288. {
  1289. Set<Buffer> checkingBuffers = getOpenBuffers();
  1290. for (View view: jEdit.getViews())
  1291. {
  1292. if (view != this)
  1293. {
  1294. checkingBuffers.removeAll(
  1295. view.getOpenBuffers());
  1296. }
  1297. }
  1298. for (Buffer buffer: checkingBuffers)
  1299. {
  1300. if (buffer.isDirty())
  1301. {
  1302. return new CloseDialog(this, checkingBuffers).isOK();
  1303. }
  1304. }
  1305. return true;
  1306. } //}}}
  1307. //{{{ close() method
  1308. void close()
  1309. {
  1310. EditBus.send(new ViewUpdate(this,ViewUpdate.CLOSED));
  1311. closed = true;
  1312. // save dockable window geometry, and close 'em
  1313. dockableWindowManager.close();
  1314. EditBus.removeFromBus(this);
  1315. dispose();
  1316. EditPane[] editPanes = getEditPanes();
  1317. for(int i = 0; i < editPanes.length; i++)
  1318. editPanes[i].close();
  1319. // null some variables so that retaining references
  1320. // to closed views won't hurt as much.
  1321. toolBarManager = null;
  1322. toolBar = null;
  1323. searchBar = null;
  1324. splitPane = null;
  1325. inputHandler = null;
  1326. recorder = null;
  1327. getContentPane().removeAll();
  1328. // notify clients with -wait
  1329. if(waitSocket != null)
  1330. {
  1331. try
  1332. {
  1333. waitSocket.getOutputStream().write('\0');
  1334. waitSocket.getOutputStream().flush();
  1335. waitSocket.getInputStream().close();
  1336. waitSocket.getOutputStream().close();
  1337. waitSocket.close();
  1338. }
  1339. catch(IOException io)
  1340. {
  1341. //Log.log(Log.ERROR,this,io);
  1342. }
  1343. }
  1344. } //}}}
  1345. //}}}
  1346. //{{{ Private members
  1347. //{{{ Instance variables
  1348. private boolean closed;
  1349. private DockableWindowManager dockableWindowManager;
  1350. private JPanel mainPanel;
  1351. private JPanel topToolBars;
  1352. private JPanel bottomToolBars;
  1353. private ToolBarManager toolBarManager;
  1354. private Container toolBar;
  1355. private SearchBar searchBar;
  1356. private ActionBar actionBar;
  1357. private EditPane editPane;
  1358. private JSplitPane splitPane;
  1359. private String lastSplitConfig;
  1360. private StatusBar status;
  1361. private InputHandler inputHandler;
  1362. private Macros.Recorder recorder;
  1363. private Component prefixFocusOwner;
  1364. private int waitCount;
  1365. private boolean showFullPath;
  1366. private boolean plainView;
  1367. private Socket waitSocket;
  1368. private Component mainContent;
  1369. private boolean fullScreenMode;
  1370. private Rectangle windowedBounds;
  1371. private JMenuBar menuBar;
  1372. private String userTitle;
  1373. //}}}
  1374. //{{{ setMainContent() method
  1375. private void setMainContent(Component c)
  1376. {
  1377. if (mainContent != null)
  1378. mainPanel.remove(mainContent);
  1379. mainContent = c;
  1380. mainPanel.add(mainContent, BorderLayout.CENTER);
  1381. if (c instanceof JSplitPane)
  1382. {
  1383. splitPane = (JSplitPane)c;
  1384. }
  1385. else
  1386. {
  1387. splitPane = null;
  1388. editPane = (EditPane)c;
  1389. }
  1390. mainPanel.revalidate();
  1391. mainPanel.repaint();
  1392. } //}}}
  1393. //{{{ getEditPanes() method
  1394. private static void getEditPanes(List<EditPane> vec, Component comp)
  1395. {
  1396. if(comp instanceof EditPane)
  1397. vec.add((EditPane) comp);
  1398. else if(comp instanceof JSplitPane)
  1399. {
  1400. JSplitPane split = (JSplitPane)comp;
  1401. getEditPanes(vec,split.getLeftComponent());
  1402. getEditPanes(vec,split.getRightComponent());
  1403. }
  1404. } //}}}
  1405. //{{{ showBuffer() method
  1406. private EditPane showBuffer(Buffer buffer, boolean focus)
  1407. {
  1408. if(editPane.getBuffer() == buffer
  1409. && editPane.getTextArea().getVisibleLines() > 1)
  1410. {
  1411. if (focus)
  1412. editPane.focusOnTextArea();
  1413. return editPane;
  1414. }
  1415. EditPane[] editPanes = getEditPanes();
  1416. for(int i = 0; i < editPanes.length; i++)
  1417. {
  1418. EditPane ep = editPanes[i];
  1419. if(ep.getBuffer() == buffer
  1420. /* ignore zero-height splits, etc */
  1421. && ep.getTextArea().getVisibleLines() > 1)
  1422. {
  1423. setEditPane(ep);
  1424. if (focus)
  1425. ep.focusOnTextArea();
  1426. return ep;
  1427. }
  1428. }
  1429. setBuffer(buffer,false, focus);
  1430. return editPane;
  1431. } //}}}
  1432. //{{{ getSplitConfig() method
  1433. /*
  1434. * The split config is recorded in a simple RPN "language".
  1435. */
  1436. private static void getSplitConfig(JSplitPane splitPane,
  1437. StringBuilder splitConfig)
  1438. {
  1439. Component right = splitPane.getRightComponent();
  1440. appendToSplitConfig(splitConfig, right);
  1441. splitConfig.append(' ');
  1442. Component left = splitPane.getLeftComponent();
  1443. appendToSplitConfig(splitConfig, left);
  1444. splitConfig.append(' ');
  1445. splitConfig.append(splitPane.getDividerLocation());
  1446. splitConfig.append(' ');
  1447. splitConfig.append(splitPane.getOrientation()
  1448. == JSplitPane.VERTICAL_SPLIT ? "vertical" : "horizontal");
  1449. } //}}}
  1450. //{{{ appendToSplitConfig() method
  1451. /**
  1452. * Append the Component to the split config.
  1453. * The component must be a JSplitPane or an EditPane
  1454. *
  1455. * @param splitConfig the split config
  1456. * @param component the component
  1457. */
  1458. private static void appendToSplitConfig(StringBuilder splitConfig, Component component)
  1459. {
  1460. if(component instanceof JSplitPane)
  1461. {
  1462. // the component is a JSplitPane
  1463. getSplitConfig((JSplitPane)component,splitConfig);
  1464. }
  1465. else
  1466. {
  1467. // the component is an editPane
  1468. EditPane editPane = (EditPane) component;
  1469. splitConfig.append('"');
  1470. splitConfig.append(StandardUtilities.charsToEscapes(
  1471. editPane.getBuffer().getPath()));
  1472. splitConfig.append("\" buffer");
  1473. BufferSet bufferSet = editPane.getBufferSet();
  1474. Buffer[] buffers = bufferSet.getAllBuffers();
  1475. for (Buffer buffer : buffers)
  1476. {
  1477. if (!buffer.isNewFile())
  1478. {
  1479. splitConfig.append(" \"");
  1480. splitConfig.append(StandardUtilities.charsToEscapes(
  1481. buffer.getPath()));
  1482. splitConfig.append("\" buff");
  1483. }
  1484. }
  1485. splitConfig.append(" \"");
  1486. splitConfig.append(jEdit.getBufferSetManager().getScope());
  1487. splitConfig.append("\" bufferset");
  1488. }
  1489. } //}}}
  1490. //{{{ restoreSplitConfig() method
  1491. private Component restoreSplitConfig(Buffer buffer, String splitConfig)
  1492. throws IOException
  1493. // this is where checked exceptions piss me off. this method only uses
  1494. // a StringReader which can never throw an exception...
  1495. {
  1496. if(buffer != null)
  1497. {
  1498. return editPane = createEditPane(buffer);
  1499. }
  1500. else if(splitConfig == null || splitConfig.trim().length() == 0)
  1501. {
  1502. Buffer buf = jEdit.getFirstBuffer();
  1503. if (buf == null)
  1504. {
  1505. buf = BufferSetManager.createUntitledBuffer();
  1506. }
  1507. return editPane = createEditPane(buf);
  1508. }
  1509. Buffer[] buffers = jEdit.getBuffers();
  1510. Stack<Object> stack = new Stack<Object>();
  1511. // we create a stream tokenizer for parsing a simple
  1512. // stack-based language
  1513. StreamTokenizer st = new StreamTokenizer(new StringReader(
  1514. splitConfig));
  1515. st.whitespaceChars(0,' ');
  1516. /* all printable ASCII characters */
  1517. st.wordChars('#','~');
  1518. st.commentChar('!');
  1519. st.quoteChar('"');
  1520. st.eolIsSignificant(false);
  1521. boolean continuousLayout = jEdit.getBooleanProperty("appearance.continuousLayout");
  1522. List<Buffer> editPaneBuffers = new ArrayList<Buffer>();
  1523. loop: while (true)
  1524. {
  1525. switch(st.nextToken())
  1526. {
  1527. case StreamTokenizer.TT_EOF:
  1528. break loop;
  1529. case StreamTokenizer.TT_WORD:
  1530. if(st.sval.equals("vertical") ||
  1531. st.sval.equals("horizontal"))
  1532. {
  1533. int orientation
  1534. = st.sval.equals("vertical")
  1535. ? JSplitPane.VERTICAL_SPLIT
  1536. : JSplitPane.HORIZONTAL_SPLIT;
  1537. int divider = ((Integer)stack.pop())
  1538. .intValue();
  1539. Object obj1 = stack.pop();
  1540. Object obj2 = stack.pop();
  1541. // Backward compatibility with pre-bufferset versions
  1542. if (obj1 instanceof Buffer)
  1543. {
  1544. Buffer b1 = buffer = (Buffer) obj1;
  1545. obj1 = editPane = createEditPane(b1);
  1546. }
  1547. if (obj2 instanceof Buffer)
  1548. {
  1549. Buffer b2 = (Buffer) obj2;
  1550. obj2 = createEditPane(b2);
  1551. }
  1552. stack.push(splitPane = new JSplitPane(
  1553. orientation,
  1554. continuousLayout,
  1555. (Component)obj1,
  1556. (Component)obj2));
  1557. splitPane.setOneTouchExpandable(true);
  1558. splitPane.setBorder(null);
  1559. splitPane.setMinimumSize(
  1560. new Dimension(0,0));
  1561. splitPane.setDividerLocation(divider);
  1562. }
  1563. else if(st.sval.equals("buffer"))
  1564. {
  1565. Object obj = stack.pop();
  1566. if(obj instanceof Integer)
  1567. {
  1568. int index = ((Integer)obj).intValue();
  1569. if(index >= 0 && index < buffers.length)
  1570. buffer = buffers[index];
  1571. }
  1572. else if(obj instanceof String)
  1573. {
  1574. String path = (String)obj;
  1575. buffer = jEdit.getBuffer(path);
  1576. if (buffer == null)
  1577. {
  1578. buffer = jEdit.openTemporary(jEdit.getActiveView(), null,
  1579. path, true, null);
  1580. jEdit.commitTemporary(buffer);
  1581. }
  1582. }
  1583. if(buffer == null)
  1584. buffer = jEdit.getFirstBuffer();
  1585. stack.push(buffer);
  1586. editPaneBuffers.add(buffer);
  1587. }
  1588. else if (st.sval.equals("buff"))
  1589. {
  1590. String path = (String)stack.pop();
  1591. buffer = jEdit.getBuffer(path);
  1592. if (buffer == null)
  1593. {
  1594. Log.log(Log.WARNING, this, "Buffer " + path + " doesn't exist");
  1595. }
  1596. else
  1597. {
  1598. editPaneBuffers.add(buffer);
  1599. }
  1600. }
  1601. else if (st.sval.equals("bufferset"))
  1602. {
  1603. // pop the bufferset scope. Not used anymore but still here for compatibility
  1604. // with old perspectives
  1605. stack.pop();
  1606. buffer = (Buffer) stack.pop();
  1607. editPane = createEditPane(buffer);
  1608. stack.push(editPane);
  1609. BufferSet bufferSet = editPane.getBufferSet();
  1610. int i = 0;
  1611. for (Buffer buff : editPaneBuffers)
  1612. {
  1613. bufferSet.addBufferAt(buff,i);
  1614. i++;
  1615. }
  1616. editPaneBuffers.clear();
  1617. }
  1618. break;
  1619. case StreamTokenizer.TT_NUMBER:
  1620. stack.push((int)st.nval);
  1621. break;
  1622. case '"':
  1623. stack.push(st.sval);
  1624. break;
  1625. }
  1626. }
  1627. // Backward compatibility with pre-bufferset versions
  1628. Object obj = stack.peek();
  1629. if (obj instanceof Buffer)
  1630. {
  1631. obj = editPane = createEditPane((Buffer)obj);
  1632. }
  1633. updateGutterBorders();
  1634. return (Component)obj;
  1635. } //}}}
  1636. //{{{ propertiesChanged() method
  1637. /**
  1638. * Reloads various settings from the properties.
  1639. */
  1640. private void propertiesChanged()
  1641. {
  1642. setJMenuBar(GUIUtilities.loadMenuBar("view.mbar"));
  1643. loadToolBars();
  1644. showFullPath = jEdit.getBooleanProperty("view.showFullPath");
  1645. updateTitle();
  1646. status.propertiesChanged();
  1647. removeToolBar(status);
  1648. getContentPane().remove(status);
  1649. boolean showStatus = plainView ? jEdit.getBooleanProperty("view.status.plainview.visible") :
  1650. jEdit.getBooleanProperty("view.status.visible");
  1651. if (jEdit.getBooleanProperty("view.toolbar.alternateLayout"))
  1652. {
  1653. getContentPane().add(BorderLayout.NORTH,topToolBars);
  1654. getContentPane().add(BorderLayout.SOUTH,bottomToolBars);
  1655. if (showStatus)
  1656. addToolBar(BOTTOM_GROUP,STATUS_BAR_LAYER,status);
  1657. }
  1658. else
  1659. {
  1660. mainPanel.add(topToolBars, BorderLayout.NORTH);
  1661. mainPanel.add(bottomToolBars, BorderLayout.SOUTH);
  1662. if (showStatus)
  1663. getContentPane().add(BorderLayout.SOUTH,status);
  1664. }
  1665. updateBufferSwitcherStates();
  1666. getRootPane().revalidate();
  1667. if (splitPane != null)
  1668. GUIUtilities.initContinuousLayout(splitPane);
  1669. //SwingUtilities.updateComponentTreeUI(getRootPane());
  1670. if (fullScreenMode)
  1671. updateFullScreenProps();
  1672. } //}}}
  1673. //{{{ updateBufferSwitcherStates() method
  1674. /**
  1675. * Enables or Disables the "Focus Buffer Switcher" menu item in the View menu
  1676. * depending on the visible state of the buffer switcher. The menu item
  1677. * is intended to have the same effect as clicking on the buffer switcher
  1678. * combo box, and it doesn't make sense to have this action available if
  1679. * the buffer switcher isn't visible.
  1680. * Also shows or hides the Buffer Switcher itself, since this can be invoked after
  1681. * the toggle buffer switcher action.
  1682. */
  1683. public void updateBufferSwitcherStates()
  1684. {
  1685. boolean show = jEdit.getBooleanProperty("view.showBufferSwitcher");
  1686. JMenuBar menubar = getJMenuBar();
  1687. if (menubar == null)
  1688. {
  1689. return;
  1690. }
  1691. String viewmenu_label = jEdit.getProperty("view.label");
  1692. viewmenu_label = viewmenu_label.replace("$", "");
  1693. String sbs_label = jEdit.getProperty("focus-buffer-switcher.label");
  1694. sbs_label = sbs_label.replace("$", "");
  1695. JMenu viewmenu = null;
  1696. for (int i = 0; i < menubar.getMenuCount(); i++)
  1697. {
  1698. JMenu menu = menubar.getMenu(i);
  1699. if (menu.getText().equals(viewmenu_label))
  1700. {
  1701. viewmenu = menu;
  1702. break;
  1703. }
  1704. }
  1705. if (viewmenu != null)
  1706. {
  1707. for (int i = 0; i < viewmenu.getMenuComponentCount(); i++)
  1708. {
  1709. Component item = viewmenu.getMenuComponent(i);
  1710. if (item instanceof JMenuItem && ((JMenuItem)item).getText().equals(sbs_label))
  1711. {
  1712. item.setEnabled(show);
  1713. // viewmenu.invalidate();
  1714. }
  1715. }
  1716. }
  1717. // Toggle the visibility of the BufferSwitcher itself
  1718. for (View v: jEdit.getViews())
  1719. for (EditPane ep: v.getEditPanes())
  1720. ep.loadBufferSwitcher();
  1721. } //}}}
  1722. //{{{ loadToolBars() method
  1723. private void loadToolBars()
  1724. {
  1725. if((! plainView) && (fullScreenMode ?
  1726. jEdit.getBooleanProperty("fullScreenIncludesToolbar") :
  1727. jEdit.getBooleanProperty("view.showToolbar")))
  1728. {
  1729. if(toolBar != null)
  1730. toolBarManager.removeToolBar(toolBar);
  1731. toolBar = GUIUtilities.loadToolBar("view.toolbar");
  1732. addToolBar(TOP_GROUP, SYSTEM_BAR_LAYER, toolBar);
  1733. }
  1734. else if(toolBar != null)
  1735. {
  1736. removeToolBar(toolBar);
  1737. toolBar = null;
  1738. }
  1739. if(searchBar != null)
  1740. {
  1741. searchBar.propertiesChanged();
  1742. removeToolBar(searchBar);
  1743. }
  1744. if(jEdit.getBooleanProperty("view.showSearchbar") && !plainView)
  1745. {
  1746. if(searchBar == null)
  1747. searchBar = new SearchBar(this,false);
  1748. addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
  1749. }
  1750. } //}}}
  1751. //{{{ createEditPane() methods
  1752. private EditPane createEditPane(Buffer buffer)
  1753. {
  1754. EditPane editPane = new EditPane(this, null, buffer);
  1755. JEditTextArea textArea = editPane.getTextArea();
  1756. textArea.addFocusListener(new FocusHandler());
  1757. textArea.addCaretListener(new CaretHandler());
  1758. textArea.addScrollListener(new ScrollHandler());
  1759. EditBus.send(new EditPaneUpdate(editPane,EditPaneUpdate.CREATED));
  1760. return editPane;
  1761. }
  1762. private EditPane createEditPane(EditPane oldEditPane)
  1763. {
  1764. EditPane editPane = new EditPane(this, oldEditPane.getBufferSet(), oldEditPane.getBuffer());
  1765. JEditTextArea textArea = editPane.getTextArea();
  1766. textArea.addFocusListener(new FocusHandler());
  1767. textArea.addCaretListener(new CaretHandler());
  1768. textArea.addScrollListener(new ScrollHandler());
  1769. EditBus.send(new EditPaneUpdate(editPane,EditPaneUpdate.CREATED));
  1770. return editPane;
  1771. } //}}}
  1772. //{{{ setEditPane() method
  1773. private void setEditPane(EditPane editPane)
  1774. {
  1775. this.editPane = editPane;
  1776. status.updateCaretStatus();
  1777. status.updateBufferStatus();
  1778. status.updateMiscStatus();
  1779. // repaint the gutter so that the border color
  1780. // reflects the focus state
  1781. updateGutterBorders();
  1782. EditBus.send(new ViewUpdate(this,ViewUpdate.EDIT_PANE_CHANGED));
  1783. } //}}}
  1784. //{{{ handleBufferUpdate() method
  1785. @EBHandler
  1786. public void handleBufferUpdate(BufferUpdate msg)
  1787. {
  1788. Buffer buffer = msg.getBuffer();
  1789. if(msg.getWhat() == BufferUpdate.DIRTY_CHANGED
  1790. || msg.getWhat() == BufferUpdate.LOADED)
  1791. {
  1792. EditPane[] editPanes = getEditPanes();
  1793. for(int i = 0; i < editPanes.length; i++)
  1794. {
  1795. if(editPanes[i].getBuffer() == buffer)
  1796. {
  1797. updateTitle();
  1798. break;
  1799. }
  1800. }
  1801. }
  1802. } //}}}
  1803. //{{{ handleEditPaneUpdate() method
  1804. @EBHandler
  1805. public void handleEditPaneUpdate(EditPaneUpdate msg)
  1806. {
  1807. EditPane editPane = msg.getEditPane();
  1808. if(editPane != null &&
  1809. editPane.getView() == this
  1810. && msg.getWhat() == EditPaneUpdate.BUFFER_CHANGED
  1811. && editPane.getBuffer().isLoaded())
  1812. {
  1813. closeDuplicateBuffers(msg);
  1814. status.updateCaretStatus();
  1815. status.updateBufferStatus();
  1816. status.updateMiscStatus();
  1817. }
  1818. } //}}}
  1819. //{{{ closeDuplicateBuffers() method
  1820. private void closeDuplicateBuffers(EditPaneUpdate epu)
  1821. {
  1822. if (!jEdit.getBooleanProperty("buffersets.exclusive"))
  1823. return;
  1824. final BufferSet.Scope scope = jEdit.getBufferSetManager().getScope();
  1825. if (scope == BufferSet.Scope.global)
  1826. return;
  1827. final EditPane ep = epu.getEditPane();
  1828. /* Only one view needs to handle this message, since
  1829. we iterate through all the other views */
  1830. final View view = ep.getView();
  1831. if (view != this)
  1832. return;
  1833. final Buffer b = ep.getBuffer();
  1834. jEdit.visit(new JEditVisitorAdapter()
  1835. {
  1836. @Override
  1837. public void visit(EditPane editPane)
  1838. {
  1839. if (editPane == ep ||
  1840. (scope == BufferSet.Scope.view && editPane.getView() == view))
  1841. return;
  1842. if (editPane.getBufferSet().indexOf(b) < 0)
  1843. return;
  1844. jEdit.getBufferSetManager().removeBuffer(editPane, b);
  1845. }
  1846. });
  1847. } //}}}
  1848. //{{{ updateGutterBorders() method
  1849. /**
  1850. * Updates the borders of all gutters in this view to reflect the
  1851. * currently focused text area.
  1852. * @since jEdit 2.6final
  1853. */
  1854. private void updateGutterBorders()
  1855. {
  1856. EditPane[] editPanes = getEditPanes();
  1857. for(int i = 0; i < editPanes.length; i++)
  1858. editPanes[i].getTextArea().getGutter().updateBorder();
  1859. } //}}}
  1860. //{{{ getOpenBuffers() method
  1861. private Set<Buffer> getOpenBuffers()
  1862. {
  1863. Set<Buffer> openBuffers = new HashSet<Buffer>();
  1864. for (EditPane editPane: getEditPanes())
  1865. {
  1866. openBuffers.addAll(Arrays.asList(
  1867. editPane.getBufferSet().getAllBuffers()));
  1868. }
  1869. return openBuffers;
  1870. } //}}}
  1871. //{{{ mergeBufferSets() method
  1872. /**
  1873. * Merge a EditPane's BufferSet into another one.
  1874. * This is used on unsplitting panes not to close buffers.
  1875. * @param target the target bufferSet where we will merge buffers from source
  1876. * @param source the source bufferSet
  1877. */
  1878. private static void mergeBufferSets(EditPane target, EditPane source)
  1879. {
  1880. BufferSetManager manager = jEdit.getBufferSetManager();
  1881. for (Buffer buffer: source.getBufferSet().getAllBuffers())
  1882. {
  1883. manager.addBuffer(target, buffer);
  1884. }
  1885. } //}}}
  1886. //}}}
  1887. //{{{ Inner classes
  1888. //{{{ CaretHandler class
  1889. private class CaretHandler implements CaretListener
  1890. {
  1891. public void caretUpdate(CaretEvent evt)
  1892. {
  1893. if(evt.getSource() == getTextArea())
  1894. status.updateCaretStatus();
  1895. }
  1896. } //}}}
  1897. //{{{ FocusHandler class
  1898. private class FocusHandler extends FocusAdapter
  1899. {
  1900. @Override
  1901. public void focusGained(FocusEvent evt)
  1902. {
  1903. // walk up hierarchy, looking for an EditPane
  1904. Component comp = (Component)evt.getSource();
  1905. while(!(comp instanceof EditPane))
  1906. {
  1907. if(comp == null)
  1908. return;
  1909. comp = comp.getParent();
  1910. }
  1911. if(comp != editPane)
  1912. setEditPane((EditPane)comp);
  1913. else
  1914. updateGutterBorders();
  1915. }
  1916. } //}}}
  1917. //{{{ ScrollHandler class
  1918. private class ScrollHandler implements ScrollListener
  1919. {
  1920. public void scrolledVertically(TextArea textArea)
  1921. {
  1922. if(getTextArea() == textArea)
  1923. status.updateCaretStatus();
  1924. }
  1925. public void scrolledHorizontally(TextArea textArea) {}
  1926. } //}}}
  1927. //{{{ WindowHandler class
  1928. private class WindowHandler extends WindowAdapter
  1929. {
  1930. @Override
  1931. public void windowActivated(WindowEvent evt)
  1932. {
  1933. boolean editPaneChanged =
  1934. jEdit.getActiveViewInternal() != View.this;
  1935. jEdit.setActiveView(View.this);
  1936. // People have reported hangs with JDK 1.4; might be
  1937. // caused by modal dialogs being displayed from
  1938. // windowActivated()
  1939. EventQueue.invokeLater(new Runnable()
  1940. {
  1941. public void run()
  1942. {
  1943. int check = jEdit.getIntegerProperty("checkFileStatus");
  1944. if(check == GeneralOptionPane.checkFileStatus_focus ||
  1945. check == GeneralOptionPane.checkFileStatus_all)
  1946. jEdit.checkBufferStatus(View.this,false);
  1947. else if(check == GeneralOptionPane.checkFileStatus_focusBuffer)
  1948. jEdit.checkBufferStatus(View.this,true);
  1949. }
  1950. });
  1951. if (editPaneChanged)
  1952. {
  1953. EditBus.send(new ViewUpdate(View.this,ViewUpdate
  1954. .ACTIVATED));
  1955. }
  1956. }
  1957. @Override
  1958. public void windowClosing(WindowEvent evt)
  1959. {
  1960. jEdit.closeView(View.this);
  1961. }
  1962. } //}}}
  1963. //{{{ ViewConfig class
  1964. public static class ViewConfig
  1965. {
  1966. public int x, y, width, height, extState;
  1967. public boolean plainView;
  1968. public String splitConfig;
  1969. public DockingLayout docking;
  1970. public String title;
  1971. public ViewConfig()
  1972. {
  1973. }
  1974. public ViewConfig(boolean plainView)
  1975. {
  1976. this.plainView = plainView;
  1977. String prefix = plainView ? "plain-view" : "view";
  1978. x = jEdit.getIntegerProperty(prefix + ".x",0);
  1979. y = jEdit.getIntegerProperty(prefix + ".y",0);
  1980. width = jEdit.getIntegerProperty(prefix + ".width",0);
  1981. height = jEdit.getIntegerProperty(prefix + ".height",0);
  1982. extState = jEdit.getIntegerProperty(prefix + ".extendedState", Frame.NORMAL);
  1983. }
  1984. public ViewConfig(boolean plainView, String splitConfig,
  1985. int x, int y, int width, int height, int extState)
  1986. {
  1987. this.plainView = plainView;
  1988. this.splitConfig = splitConfig;
  1989. this.x = x;
  1990. this.y = y;
  1991. this.width = width;
  1992. this.height = height;
  1993. this.extState = extState;
  1994. }
  1995. } //}}}
  1996. //{{{ isInsideScreen() method
  1997. private static boolean isInsideScreen(View parent, Rectangle r)
  1998. {
  1999. Rectangle bounds;
  2000. if (parent == null)
  2001. bounds = GUIUtilities.getScreenBounds();
  2002. else
  2003. bounds = parent.getGraphicsConfiguration().getBounds();
  2004. int minWidth = jEdit.getIntegerProperty("view.minStartupWidth");
  2005. int minHeight = jEdit.getIntegerProperty("view.minStartupHeight");
  2006. return r.x + r.width > bounds.x + minWidth && // right edge at minWidth pixels on the right of the left bound
  2007. r.x < bounds.x + bounds.width - minWidth && // left edge at minWidth pixels on the left of the right bound
  2008. r.y + r.height > bounds.y + minHeight && // bottom edge at minHeight pixels under the top bound
  2009. r.y < bounds.y + bounds.height - minHeight; // top edge at minHeight pixels on the top of the bottom bound
  2010. } //}}}
  2011. public void adjust(View parent, ViewConfig config)
  2012. {
  2013. if(config.width != 0 && config.height != 0)
  2014. {
  2015. Rectangle desired = new Rectangle(
  2016. config.x, config.y, config.width, config.height);
  2017. if (! isInsideScreen(parent, desired))
  2018. setLocationRelativeTo(parent);
  2019. else
  2020. {
  2021. if(OperatingSystem.isX11() && Debug.GEOMETRY_WORKAROUND)
  2022. new GUIUtilities.UnixWorkaround(this,"view",desired,config.extState);
  2023. else
  2024. {
  2025. setBounds(desired);
  2026. setExtendedState(config.extState);
  2027. }
  2028. }
  2029. }
  2030. else
  2031. setLocationRelativeTo(parent);
  2032. }
  2033. //{{{ MyFocusTraversalPolicy class
  2034. private static class MyFocusTraversalPolicy extends LayoutFocusTraversalPolicy
  2035. {
  2036. @Override
  2037. public Component getDefaultComponent(Container focusCycleRoot)
  2038. {
  2039. return GUIUtilities.getView(focusCycleRoot).getTextArea();
  2040. }
  2041. } //}}}
  2042. //{{{ SetCursorVisitor class
  2043. private static class SetCursorVisitor extends JEditVisitorAdapter
  2044. {
  2045. private final Cursor cursor;
  2046. SetCursorVisitor(Cursor cursor)
  2047. {
  2048. this.cursor = cursor;
  2049. }
  2050. @Override
  2051. public void visit(EditPane editPane)
  2052. {
  2053. editPane.setCursor(cursor);
  2054. }
  2055. }//}}}
  2056. //}}}
  2057. }