PageRenderTime 61ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/View.java

#
Java | 1774 lines | 1271 code | 118 blank | 385 comment | 137 complexity | 963cb5b0336ee72bc48576f332010a1b 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, 2003 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 javax.swing.event.*;
  25. import javax.swing.text.*;
  26. import javax.swing.*;
  27. import java.awt.*;
  28. import java.awt.event.*;
  29. import java.io.IOException;
  30. import java.io.StreamTokenizer;
  31. import java.io.StringReader;
  32. import java.net.Socket;
  33. import java.util.*;
  34. import org.gjt.sp.jedit.msg.*;
  35. import org.gjt.sp.jedit.gui.*;
  36. import org.gjt.sp.jedit.search.*;
  37. import org.gjt.sp.jedit.textarea.*;
  38. import org.gjt.sp.util.Log;
  39. //}}}
  40. /**
  41. * A <code>View</code> is jEdit's top-level frame window.<p>
  42. *
  43. * In a BeanShell script, you can obtain the current view instance from the
  44. * <code>view</code> variable.<p>
  45. *
  46. * The largest component it contains is an {@link EditPane} that in turn
  47. * contains a {@link org.gjt.sp.jedit.textarea.JEditTextArea} that displays a
  48. * {@link Buffer}.
  49. * A view can have more than one edit pane in a split window configuration.
  50. * A view also contains a menu bar, an optional toolbar and other window
  51. * decorations, as well as docked windows.<p>
  52. *
  53. * The <b>View</b> class performs two important operations
  54. * dealing with plugins: creating plugin menu items, and managing dockable
  55. * windows.
  56. *
  57. * <ul>
  58. * <li>When a view is being created, its initialization routine
  59. * iterates through the collection of loaded plugins and constructs the
  60. * <b>Plugins</b> menu using the properties as specified in the
  61. * {@link EditPlugin} class.</li>
  62. * <li>The view also creates and initializes a
  63. * {@link org.gjt.sp.jedit.gui.DockableWindowManager}
  64. * object. This object is
  65. * responsible for creating, closing and managing dockable windows.</li>
  66. * </ul>
  67. *
  68. * This class does not have a public constructor.
  69. * Views can be opened and closed using methods in the <code>jEdit</code>
  70. * class.
  71. *
  72. * @see org.gjt.sp.jedit.jEdit#newView(View)
  73. * @see org.gjt.sp.jedit.jEdit#newView(View,Buffer)
  74. * @see org.gjt.sp.jedit.jEdit#newView(View,Buffer,boolean)
  75. * @see org.gjt.sp.jedit.jEdit#closeView(View)
  76. *
  77. * @author Slava Pestov
  78. * @author John Gellene (API documentation)
  79. * @version $Id: View.java 5037 2004-05-06 22:35:11Z spestov $
  80. */
  81. public class View extends JFrame implements EBComponent
  82. {
  83. //{{{ User interface
  84. //{{{ ToolBar-related constants
  85. //{{{ Groups
  86. /**
  87. * The group of tool bars above the DockableWindowManager
  88. * @see #addToolBar(int,int,java.awt.Component)
  89. * @since jEdit 4.0pre7
  90. */
  91. public static final int TOP_GROUP = 0;
  92. /**
  93. * The group of tool bars below the DockableWindowManager
  94. * @see #addToolBar(int,int,java.awt.Component)
  95. * @since jEdit 4.0pre7
  96. */
  97. public static final int BOTTOM_GROUP = 1;
  98. public static final int DEFAULT_GROUP = TOP_GROUP;
  99. //}}}
  100. //{{{ Layers
  101. // Common layers
  102. /**
  103. * The highest possible layer.
  104. * @see #addToolBar(int,int,java.awt.Component)
  105. * @since jEdit 4.0pre7
  106. */
  107. public static final int TOP_LAYER = Integer.MAX_VALUE;
  108. /**
  109. * The default layer for tool bars with no preference.
  110. * @see #addToolBar(int,int,java.awt.Component)
  111. * @since jEdit 4.0pre7
  112. */
  113. public static final int DEFAULT_LAYER = 0;
  114. /**
  115. * The lowest possible layer.
  116. * @see #addToolBar(int,int,java.awt.Component)
  117. * @since jEdit 4.0pre7
  118. */
  119. public static final int BOTTOM_LAYER = Integer.MIN_VALUE;
  120. // Layers for top group
  121. /**
  122. * Above system tool bar layer.
  123. * @see #addToolBar(int,int,java.awt.Component)
  124. * @since jEdit 4.0pre7
  125. */
  126. public static final int ABOVE_SYSTEM_BAR_LAYER = 150;
  127. /**
  128. * System tool bar layer.
  129. * jEdit uses this for the main tool bar.
  130. * @see #addToolBar(int,int,java.awt.Component)
  131. * @since jEdit 4.0pre7
  132. */
  133. public static final int SYSTEM_BAR_LAYER = 100;
  134. /**
  135. * Below system tool bar layer.
  136. * @see #addToolBar(int,int,java.awt.Component)
  137. * @since jEdit 4.0pre7
  138. */
  139. public static final int BELOW_SYSTEM_BAR_LAYER = 75;
  140. /**
  141. * Search bar layer.
  142. * @see #addToolBar(int,int,java.awt.Component)
  143. * @since jEdit 4.0pre7
  144. */
  145. public static final int SEARCH_BAR_LAYER = 75;
  146. /**
  147. * Below search bar layer.
  148. * @see #addToolBar(int,int,java.awt.Component)
  149. * @since jEdit 4.0pre7
  150. */
  151. public static final int BELOW_SEARCH_BAR_LAYER = 50;
  152. // Layers for bottom group
  153. /**
  154. * @deprecated Status bar no longer added as a tool bar.
  155. */
  156. public static final int ABOVE_ACTION_BAR_LAYER = -50;
  157. /**
  158. * Action bar layer.
  159. * @see #addToolBar(int,int,java.awt.Component)
  160. * @since jEdit 4.2pre1
  161. */
  162. public static final int ACTION_BAR_LAYER = -75;
  163. /**
  164. * Status bar layer.
  165. * @see #addToolBar(int,int,java.awt.Component)
  166. * @since jEdit 4.2pre1
  167. */
  168. public static final int STATUS_BAR_LAYER = -100;
  169. /**
  170. * Status bar layer.
  171. * @see #addToolBar(int,int,java.awt.Component)
  172. * @since jEdit 4.2pre1
  173. */
  174. public static final int BELOW_STATUS_BAR_LAYER = -150;
  175. //}}}
  176. //}}}
  177. //{{{ getDockableWindowManager() method
  178. /**
  179. * Returns the dockable window manager associated with this view.
  180. * @since jEdit 2.6pre3
  181. */
  182. public DockableWindowManager getDockableWindowManager()
  183. {
  184. return dockableWindowManager;
  185. } //}}}
  186. //{{{ getToolBar() method
  187. /**
  188. * Returns the view's tool bar.
  189. * @since jEdit 4.2pre1
  190. */
  191. public Box getToolBar()
  192. {
  193. return toolBar;
  194. } //}}}
  195. //{{{ addToolBar() method
  196. /**
  197. * Adds a tool bar to this view.
  198. * @param toolBar The tool bar
  199. */
  200. public void addToolBar(Component toolBar)
  201. {
  202. addToolBar(DEFAULT_GROUP, DEFAULT_LAYER, toolBar);
  203. } //}}}
  204. //{{{ addToolBar() method
  205. /**
  206. * Adds a tool bar to this view.
  207. * @param group The tool bar group to add to
  208. * @param toolBar The tool bar
  209. * @see org.gjt.sp.jedit.gui.ToolBarManager
  210. * @since jEdit 4.0pre7
  211. */
  212. public void addToolBar(int group, Component toolBar)
  213. {
  214. addToolBar(group, DEFAULT_LAYER, toolBar);
  215. } //}}}
  216. //{{{ addToolBar() method
  217. /**
  218. * Adds a tool bar to this view.
  219. * @param group The tool bar group to add to
  220. * @param layer The layer of the group to add to
  221. * @param toolBar The tool bar
  222. * @see org.gjt.sp.jedit.gui.ToolBarManager
  223. * @since jEdit 4.0pre7
  224. */
  225. public void addToolBar(int group, int layer, Component toolBar)
  226. {
  227. toolBarManager.addToolBar(group, layer, toolBar);
  228. getRootPane().revalidate();
  229. } //}}}
  230. //{{{ removeToolBar() method
  231. /**
  232. * Removes a tool bar from this view.
  233. * @param toolBar The tool bar
  234. */
  235. public void removeToolBar(Component toolBar)
  236. {
  237. toolBarManager.removeToolBar(toolBar);
  238. getRootPane().revalidate();
  239. } //}}}
  240. //{{{ showWaitCursor() method
  241. /**
  242. * Shows the wait cursor. This method and
  243. * {@link #hideWaitCursor()} are implemented using a reference
  244. * count of requests for wait cursors, so that nested calls work
  245. * correctly; however, you should be careful to use these methods in
  246. * tandem.<p>
  247. *
  248. * To ensure that {@link #hideWaitCursor()} is always called
  249. * after a {@link #showWaitCursor()}, use a
  250. * <code>try</code>/<code>finally</code> block, like this:
  251. * <pre>try
  252. *{
  253. * view.showWaitCursor();
  254. * // ...
  255. *}
  256. *finally
  257. *{
  258. * view.hideWaitCursor();
  259. *}</pre>
  260. */
  261. public synchronized void showWaitCursor()
  262. {
  263. if(waitCount++ == 0)
  264. {
  265. Cursor cursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
  266. setCursor(cursor);
  267. EditPane[] editPanes = getEditPanes();
  268. for(int i = 0; i < editPanes.length; i++)
  269. {
  270. EditPane editPane = editPanes[i];
  271. editPane.getTextArea().getPainter()
  272. .setCursor(cursor);
  273. }
  274. }
  275. } //}}}
  276. //{{{ hideWaitCursor() method
  277. /**
  278. * Hides the wait cursor.
  279. */
  280. public synchronized void hideWaitCursor()
  281. {
  282. if(waitCount > 0)
  283. waitCount--;
  284. if(waitCount == 0)
  285. {
  286. // still needed even though glass pane
  287. // has a wait cursor
  288. Cursor cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  289. setCursor(cursor);
  290. cursor = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
  291. EditPane[] editPanes = getEditPanes();
  292. for(int i = 0; i < editPanes.length; i++)
  293. {
  294. EditPane editPane = editPanes[i];
  295. editPane.getTextArea().getPainter()
  296. .setCursor(cursor);
  297. }
  298. }
  299. } //}}}
  300. //{{{ getSearchBar() method
  301. /**
  302. * Returns the search bar.
  303. * @since jEdit 2.4pre4
  304. */
  305. public final SearchBar getSearchBar()
  306. {
  307. return searchBar;
  308. } //}}}
  309. //{{{ getActionBar() method
  310. /**
  311. * Returns the action bar.
  312. * @since jEdit 4.2pre3
  313. */
  314. public final ActionBar getActionBar()
  315. {
  316. return actionBar;
  317. } //}}}
  318. //{{{ getStatus() method
  319. /**
  320. * Returns the status bar. The
  321. * {@link org.gjt.sp.jedit.gui.StatusBar#setMessage(String)} and
  322. * {@link org.gjt.sp.jedit.gui.StatusBar#setMessageAndClear(String)} methods can
  323. * be called on the return value of this method to display status
  324. * information to the user.
  325. * @since jEdit 3.2pre2
  326. */
  327. public StatusBar getStatus()
  328. {
  329. return status;
  330. } //}}}
  331. //{{{ quickIncrementalSearch() method
  332. /**
  333. * Quick search.
  334. * @since jEdit 4.0pre3
  335. */
  336. public void quickIncrementalSearch(boolean word)
  337. {
  338. if(searchBar == null)
  339. searchBar = new SearchBar(this,true);
  340. if(searchBar.getParent() == null)
  341. addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
  342. searchBar.setHyperSearch(false);
  343. JEditTextArea textArea = getTextArea();
  344. if(word)
  345. {
  346. String text = textArea.getSelectedText();
  347. if(text == null)
  348. {
  349. textArea.selectWord();
  350. text = textArea.getSelectedText();
  351. }
  352. else if(text.indexOf('\n') != -1)
  353. text = null;
  354. searchBar.getField().setText(text);
  355. }
  356. searchBar.getField().requestFocus();
  357. searchBar.getField().selectAll();
  358. } //}}}
  359. //{{{ quickHyperSearch() method
  360. /**
  361. * Quick HyperSearch.
  362. * @since jEdit 4.0pre3
  363. */
  364. public void quickHyperSearch(boolean word)
  365. {
  366. JEditTextArea textArea = getTextArea();
  367. if(word)
  368. {
  369. String text = textArea.getSelectedText();
  370. if(text == null)
  371. {
  372. textArea.selectWord();
  373. text = textArea.getSelectedText();
  374. }
  375. if(text != null && text.indexOf('\n') == -1)
  376. {
  377. HistoryModel.getModel("find").addItem(text);
  378. SearchAndReplace.setSearchString(text);
  379. SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
  380. SearchAndReplace.hyperSearch(this);
  381. return;
  382. }
  383. }
  384. if(searchBar == null)
  385. searchBar = new SearchBar(this,true);
  386. if(searchBar.getParent() == null)
  387. addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
  388. searchBar.setHyperSearch(true);
  389. searchBar.getField().setText(null);
  390. searchBar.getField().requestFocus();
  391. searchBar.getField().selectAll();
  392. } //}}}
  393. //{{{ actionBar() method
  394. /**
  395. * Shows the action bar if needed, and sends keyboard focus there.
  396. * @since jEdit 4.2pre1
  397. */
  398. public void actionBar()
  399. {
  400. if(actionBar == null)
  401. actionBar = new ActionBar(this,true);
  402. if(actionBar.getParent() == null)
  403. addToolBar(BOTTOM_GROUP,ACTION_BAR_LAYER,actionBar);
  404. actionBar.goToActionBar();
  405. } //}}}
  406. //}}}
  407. //{{{ Input handling
  408. //{{{ getKeyEventInterceptor() method
  409. /**
  410. * Returns the listener that will handle all key events in this
  411. * view, if any.
  412. */
  413. public KeyListener getKeyEventInterceptor()
  414. {
  415. return keyEventInterceptor;
  416. } //}}}
  417. //{{{ setKeyEventInterceptor() method
  418. /**
  419. * Sets the listener that will handle all key events in this
  420. * view. For example, the complete word command uses this so
  421. * that all key events are passed to the word list popup while
  422. * it is visible.
  423. * @param listener The key event interceptor.
  424. */
  425. public void setKeyEventInterceptor(KeyListener listener)
  426. {
  427. this.keyEventInterceptor = listener;
  428. } //}}}
  429. //{{{ getInputHandler() method
  430. /**
  431. * Returns the input handler.
  432. */
  433. public InputHandler getInputHandler()
  434. {
  435. return inputHandler;
  436. } //}}}
  437. //{{{ setInputHandler() method
  438. /**
  439. * Sets the input handler.
  440. * @param inputHandler The new input handler
  441. */
  442. public void setInputHandler(InputHandler inputHandler)
  443. {
  444. this.inputHandler = inputHandler;
  445. } //}}}
  446. //{{{ getMacroRecorder() method
  447. /**
  448. * Returns the macro recorder.
  449. */
  450. public Macros.Recorder getMacroRecorder()
  451. {
  452. return recorder;
  453. } //}}}
  454. //{{{ setMacroRecorder() method
  455. /**
  456. * Sets the macro recorder.
  457. * @param recorder The macro recorder
  458. */
  459. public void setMacroRecorder(Macros.Recorder recorder)
  460. {
  461. this.recorder = recorder;
  462. } //}}}
  463. //{{{ processKeyEvent() method
  464. /**
  465. * Forwards key events directly to the input handler.
  466. * This is slightly faster than using a KeyListener
  467. * because some Swing overhead is avoided.
  468. */
  469. public void processKeyEvent(KeyEvent evt)
  470. {
  471. processKeyEvent(evt,VIEW);
  472. } //}}}
  473. //{{{ processKeyEvent() method
  474. /**
  475. * Forwards key events directly to the input handler.
  476. * This is slightly faster than using a KeyListener
  477. * because some Swing overhead is avoided.
  478. */
  479. public void processKeyEvent(KeyEvent evt, boolean calledFromTextArea)
  480. {
  481. processKeyEvent(evt,calledFromTextArea
  482. ? TEXT_AREA
  483. : VIEW);
  484. } //}}}
  485. //{{{ processKeyEvent() method
  486. public static final int VIEW = 0;
  487. public static final int TEXT_AREA = 1;
  488. public static final int ACTION_BAR = 2;
  489. /**
  490. * Forwards key events directly to the input handler.
  491. * This is slightly faster than using a KeyListener
  492. * because some Swing overhead is avoided.
  493. */
  494. public void processKeyEvent(KeyEvent evt, int from)
  495. {
  496. if(Debug.DUMP_KEY_EVENTS && from != VIEW)
  497. {
  498. Log.log(Log.DEBUG,this,"Key event: "
  499. + GrabKeyDialog.toString(evt));
  500. }
  501. if(getTextArea().hasFocus() && from == VIEW)
  502. return;
  503. evt = _preprocessKeyEvent(evt);
  504. if(evt == null)
  505. return;
  506. if(Debug.DUMP_KEY_EVENTS && from != VIEW)
  507. {
  508. Log.log(Log.DEBUG,this,"Key event after workaround: "
  509. + GrabKeyDialog.toString(evt));
  510. }
  511. switch(evt.getID())
  512. {
  513. case KeyEvent.KEY_TYPED:
  514. boolean focusOnTextArea = false;
  515. // if the user pressed eg C+e n n in the
  516. // search bar we want focus to go back there
  517. // after the prefix is done
  518. if(prefixFocusOwner != null)
  519. {
  520. if(prefixFocusOwner.isShowing())
  521. {
  522. prefixFocusOwner.requestFocus();
  523. focusOnTextArea = true;
  524. }
  525. }
  526. if(keyEventInterceptor != null)
  527. keyEventInterceptor.keyTyped(evt);
  528. else if(from == ACTION_BAR
  529. || inputHandler.isPrefixActive()
  530. || getTextArea().hasFocus())
  531. {
  532. KeyEventTranslator.Key keyStroke
  533. = KeyEventTranslator
  534. .translateKeyEvent(evt);
  535. if(keyStroke != null)
  536. {
  537. if(Debug.DUMP_KEY_EVENTS
  538. && from != VIEW)
  539. {
  540. Log.log(Log.DEBUG,this,
  541. "Translated: "
  542. + keyStroke);
  543. }
  544. if(inputHandler.handleKey(keyStroke))
  545. evt.consume();
  546. }
  547. }
  548. // we might have been closed as a result of
  549. // the above
  550. if(isClosed())
  551. return;
  552. // this is a weird hack.
  553. // we don't want C+e a to insert 'a' in the
  554. // search bar if the search bar has focus...
  555. if(inputHandler.isPrefixActive())
  556. {
  557. if(getFocusOwner() instanceof JTextComponent)
  558. {
  559. prefixFocusOwner = getFocusOwner();
  560. getTextArea().requestFocus();
  561. }
  562. else if(focusOnTextArea)
  563. {
  564. getTextArea().requestFocus();
  565. }
  566. else
  567. {
  568. prefixFocusOwner = null;
  569. }
  570. }
  571. else
  572. {
  573. prefixFocusOwner = null;
  574. }
  575. break;
  576. case KeyEvent.KEY_PRESSED:
  577. if(keyEventInterceptor != null)
  578. keyEventInterceptor.keyPressed(evt);
  579. else
  580. {
  581. /* boolean */ focusOnTextArea = false;
  582. if(prefixFocusOwner != null)
  583. {
  584. if(prefixFocusOwner.isShowing())
  585. {
  586. prefixFocusOwner.requestFocus();
  587. focusOnTextArea = true;
  588. }
  589. prefixFocusOwner = null;
  590. }
  591. KeyEventTranslator.Key keyStroke
  592. = KeyEventTranslator
  593. .translateKeyEvent(evt);
  594. if(keyStroke != null)
  595. {
  596. if(Debug.DUMP_KEY_EVENTS
  597. && from != VIEW)
  598. {
  599. Log.log(Log.DEBUG,this,
  600. "Translated: "
  601. + keyStroke);
  602. }
  603. if(inputHandler.handleKey(keyStroke))
  604. evt.consume();
  605. }
  606. // we might have been closed as a result of
  607. // the above
  608. if(isClosed())
  609. return;
  610. // this is a weird hack.
  611. // we don't want C+e a to insert 'a' in the
  612. // search bar if the search bar has focus...
  613. if(inputHandler.isPrefixActive())
  614. {
  615. if(getFocusOwner() instanceof JTextComponent)
  616. {
  617. prefixFocusOwner = getFocusOwner();
  618. getTextArea().requestFocus();
  619. }
  620. else if(focusOnTextArea)
  621. {
  622. getTextArea().requestFocus();
  623. }
  624. else
  625. {
  626. prefixFocusOwner = null;
  627. }
  628. }
  629. else
  630. {
  631. prefixFocusOwner = null;
  632. }
  633. }
  634. break;
  635. case KeyEvent.KEY_RELEASED:
  636. if(keyEventInterceptor != null)
  637. keyEventInterceptor.keyReleased(evt);
  638. break;
  639. }
  640. if(!evt.isConsumed())
  641. super.processKeyEvent(evt);
  642. } //}}}
  643. //}}}
  644. //{{{ Buffers, edit panes, split panes
  645. //{{{ splitHorizontally() method
  646. /**
  647. * Splits the view horizontally.
  648. * @since jEdit 4.1pre2
  649. */
  650. public EditPane splitHorizontally()
  651. {
  652. return split(JSplitPane.VERTICAL_SPLIT);
  653. } //}}}
  654. //{{{ splitVertically() method
  655. /**
  656. * Splits the view vertically.
  657. * @since jEdit 4.1pre2
  658. */
  659. public EditPane splitVertically()
  660. {
  661. return split(JSplitPane.HORIZONTAL_SPLIT);
  662. } //}}}
  663. //{{{ split() method
  664. /**
  665. * Splits the view.
  666. * @since jEdit 4.1pre2
  667. */
  668. public EditPane split(int orientation)
  669. {
  670. PerspectiveManager.setPerspectiveDirty(true);
  671. editPane.saveCaretInfo();
  672. EditPane oldEditPane = editPane;
  673. setEditPane(createEditPane(oldEditPane.getBuffer()));
  674. editPane.loadCaretInfo();
  675. JComponent oldParent = (JComponent)oldEditPane.getParent();
  676. final JSplitPane newSplitPane = new JSplitPane(orientation);
  677. newSplitPane.setOneTouchExpandable(true);
  678. newSplitPane.setBorder(null);
  679. newSplitPane.setMinimumSize(new Dimension(0,0));
  680. int parentSize = (orientation == JSplitPane.VERTICAL_SPLIT
  681. ? oldEditPane.getHeight() : oldEditPane.getWidth());
  682. final int dividerPosition = (int)((double)(parentSize
  683. - newSplitPane.getDividerSize()) * 0.5);
  684. newSplitPane.setDividerLocation(dividerPosition);
  685. if(oldParent instanceof JSplitPane)
  686. {
  687. JSplitPane oldSplitPane = (JSplitPane)oldParent;
  688. int dividerPos = oldSplitPane.getDividerLocation();
  689. Component left = oldSplitPane.getLeftComponent();
  690. if(left == oldEditPane)
  691. oldSplitPane.setLeftComponent(newSplitPane);
  692. else
  693. oldSplitPane.setRightComponent(newSplitPane);
  694. newSplitPane.setLeftComponent(oldEditPane);
  695. newSplitPane.setRightComponent(editPane);
  696. oldSplitPane.setDividerLocation(dividerPos);
  697. }
  698. else
  699. {
  700. this.splitPane = newSplitPane;
  701. newSplitPane.setLeftComponent(oldEditPane);
  702. newSplitPane.setRightComponent(editPane);
  703. oldParent.add(newSplitPane,0);
  704. oldParent.revalidate();
  705. }
  706. SwingUtilities.invokeLater(new Runnable()
  707. {
  708. public void run()
  709. {
  710. newSplitPane.setDividerLocation(dividerPosition);
  711. }
  712. });
  713. editPane.focusOnTextArea();
  714. return editPane;
  715. } //}}}
  716. //{{{ unsplit() method
  717. /**
  718. * Unsplits the view.
  719. * @since jEdit 2.3pre2
  720. */
  721. public void unsplit()
  722. {
  723. if(splitPane != null)
  724. {
  725. PerspectiveManager.setPerspectiveDirty(true);
  726. EditPane[] editPanes = getEditPanes();
  727. for(int i = 0; i < editPanes.length; i++)
  728. {
  729. EditPane _editPane = editPanes[i];
  730. if(editPane != _editPane)
  731. _editPane.close();
  732. }
  733. JComponent parent = (JComponent)splitPane.getParent();
  734. parent.remove(splitPane);
  735. parent.add(editPane,0);
  736. parent.revalidate();
  737. splitPane = null;
  738. updateTitle();
  739. editPane.focusOnTextArea();
  740. }
  741. else
  742. getToolkit().beep();
  743. } //}}}
  744. //{{{ unsplitCurrent() method
  745. /**
  746. * Removes the current split.
  747. * @since jEdit 2.3pre2
  748. */
  749. public void unsplitCurrent()
  750. {
  751. if(splitPane != null)
  752. {
  753. PerspectiveManager.setPerspectiveDirty(true);
  754. // find first split pane parenting current edit pane
  755. Component comp = editPane;
  756. while(!(comp instanceof JSplitPane))
  757. {
  758. comp = comp.getParent();
  759. }
  760. // get rid of any edit pane that is a child
  761. // of the current edit pane's parent splitter
  762. EditPane[] editPanes = getEditPanes();
  763. for(int i = 0; i < editPanes.length; i++)
  764. {
  765. EditPane _editPane = editPanes[i];
  766. if(GUIUtilities.isAncestorOf(comp,_editPane)
  767. && _editPane != editPane)
  768. _editPane.close();
  769. }
  770. JComponent parent = (JComponent)comp.getParent();
  771. if(parent instanceof JSplitPane)
  772. {
  773. JSplitPane parentSplit = (JSplitPane)parent;
  774. int pos = parentSplit.getDividerLocation();
  775. if(parentSplit.getLeftComponent() == comp)
  776. parentSplit.setLeftComponent(editPane);
  777. else
  778. parentSplit.setRightComponent(editPane);
  779. parentSplit.setDividerLocation(pos);
  780. }
  781. else
  782. {
  783. parent.remove(comp);
  784. parent.add(editPane,0);
  785. splitPane = null;
  786. }
  787. parent.revalidate();
  788. updateTitle();
  789. editPane.focusOnTextArea();
  790. }
  791. else
  792. getToolkit().beep();
  793. } //}}}
  794. //{{{ nextTextArea() method
  795. /**
  796. * Moves keyboard focus to the next text area.
  797. * @since jEdit 2.7pre4
  798. */
  799. public void nextTextArea()
  800. {
  801. EditPane[] editPanes = getEditPanes();
  802. for(int i = 0; i < editPanes.length; i++)
  803. {
  804. if(editPane == editPanes[i])
  805. {
  806. if(i == editPanes.length - 1)
  807. editPanes[0].focusOnTextArea();
  808. else
  809. editPanes[i+1].focusOnTextArea();
  810. break;
  811. }
  812. }
  813. } //}}}
  814. //{{{ prevTextArea() method
  815. /**
  816. * Moves keyboard focus to the previous text area.
  817. * @since jEdit 2.7pre4
  818. */
  819. public void prevTextArea()
  820. {
  821. EditPane[] editPanes = getEditPanes();
  822. for(int i = 0; i < editPanes.length; i++)
  823. {
  824. if(editPane == editPanes[i])
  825. {
  826. if(i == 0)
  827. editPanes[editPanes.length - 1].focusOnTextArea();
  828. else
  829. editPanes[i-1].focusOnTextArea();
  830. break;
  831. }
  832. }
  833. } //}}}
  834. //{{{ getSplitPane() method
  835. /**
  836. * Returns the top-level split pane, if any.
  837. * @since jEdit 2.3pre2
  838. */
  839. public JSplitPane getSplitPane()
  840. {
  841. return splitPane;
  842. } //}}}
  843. //{{{ getBuffer() method
  844. /**
  845. * Returns the current edit pane's buffer.
  846. */
  847. public Buffer getBuffer()
  848. {
  849. if(editPane == null)
  850. return null;
  851. else
  852. return editPane.getBuffer();
  853. } //}}}
  854. //{{{ setBuffer() method
  855. /**
  856. * Sets the current edit pane's buffer.
  857. */
  858. public void setBuffer(Buffer buffer)
  859. {
  860. editPane.setBuffer(buffer);
  861. } //}}}
  862. //{{{ goToBuffer() method
  863. /**
  864. * If this buffer is open in one of the view's edit panes, sets focus
  865. * to that edit pane. Otherwise, opens the buffer in the currently
  866. * active edit pane.
  867. * @param buffer The buffer
  868. * @since jEdit 4.2pre1
  869. */
  870. public EditPane goToBuffer(Buffer buffer)
  871. {
  872. if(editPane.getBuffer() == buffer)
  873. {
  874. editPane.focusOnTextArea();
  875. return editPane;
  876. }
  877. EditPane[] editPanes = getEditPanes();
  878. for(int i = 0; i < editPanes.length; i++)
  879. {
  880. EditPane ep = editPanes[i];
  881. if(ep.getBuffer() == buffer
  882. /* ignore zero-height splits, etc */
  883. && ep.getTextArea().getVisibleLines() > 1)
  884. {
  885. setEditPane(ep);
  886. ep.focusOnTextArea();
  887. return ep;
  888. }
  889. }
  890. setBuffer(buffer);
  891. return editPane;
  892. } //}}}
  893. //{{{ getTextArea() method
  894. /**
  895. * Returns the current edit pane's text area.
  896. */
  897. public JEditTextArea getTextArea()
  898. {
  899. if(editPane == null)
  900. return null;
  901. else
  902. return editPane.getTextArea();
  903. } //}}}
  904. //{{{ getEditPane() method
  905. /**
  906. * Returns the current edit pane.
  907. * @since jEdit 2.5pre2
  908. */
  909. public EditPane getEditPane()
  910. {
  911. return editPane;
  912. } //}}}
  913. //{{{ getEditPanes() method
  914. /**
  915. * Returns all edit panes.
  916. * @since jEdit 2.5pre2
  917. */
  918. public EditPane[] getEditPanes()
  919. {
  920. if(splitPane == null)
  921. {
  922. EditPane[] ep = { editPane };
  923. return ep;
  924. }
  925. else
  926. {
  927. Vector vec = new Vector();
  928. getEditPanes(vec,splitPane);
  929. EditPane[] ep = new EditPane[vec.size()];
  930. vec.copyInto(ep);
  931. return ep;
  932. }
  933. } //}}}
  934. //{{{ getViewConfig() method
  935. /**
  936. * @since jEdit 4.2pre1
  937. */
  938. public ViewConfig getViewConfig()
  939. {
  940. StringBuffer splitConfig = new StringBuffer();
  941. if(splitPane != null)
  942. getSplitConfig(splitPane,splitConfig);
  943. else
  944. {
  945. splitConfig.append('"');
  946. splitConfig.append(MiscUtilities.charsToEscapes(
  947. getBuffer().getPath()));
  948. splitConfig.append("\" buffer");
  949. }
  950. ViewConfig config = new ViewConfig();
  951. config.plainView = isPlainView();
  952. config.splitConfig = splitConfig.toString();
  953. config.x = getX();
  954. config.y = getY();
  955. config.width = getWidth();
  956. config.height = getHeight();
  957. config.extState = GUIUtilities.getExtendedState(this);
  958. config.top = dockableWindowManager.getTopDockingArea().getCurrent();
  959. config.left = dockableWindowManager.getLeftDockingArea().getCurrent();
  960. config.bottom = dockableWindowManager.getBottomDockingArea().getCurrent();
  961. config.right = dockableWindowManager.getRightDockingArea().getCurrent();
  962. config.topPos = dockableWindowManager.getTopDockingArea().getDimension();
  963. config.leftPos = dockableWindowManager.getLeftDockingArea().getDimension();
  964. config.bottomPos = dockableWindowManager.getBottomDockingArea().getDimension();
  965. config.rightPos = dockableWindowManager.getRightDockingArea().getDimension();
  966. return config;
  967. } //}}}
  968. //}}}
  969. //{{{ isClosed() method
  970. /**
  971. * Returns true if this view has been closed with
  972. * {@link jEdit#closeView(View)}.
  973. */
  974. public boolean isClosed()
  975. {
  976. return closed;
  977. } //}}}
  978. //{{{ isPlainView() method
  979. /**
  980. * Returns true if this is an auxilliary view with no dockable windows.
  981. * @since jEdit 4.1pre2
  982. */
  983. public boolean isPlainView()
  984. {
  985. return plainView;
  986. } //}}}
  987. //{{{ getNext() method
  988. /**
  989. * Returns the next view in the list.
  990. */
  991. public View getNext()
  992. {
  993. return next;
  994. } //}}}
  995. //{{{ getPrev() method
  996. /**
  997. * Returns the previous view in the list.
  998. */
  999. public View getPrev()
  1000. {
  1001. return prev;
  1002. } //}}}
  1003. //{{{ handleMessage() method
  1004. public void handleMessage(EBMessage msg)
  1005. {
  1006. if(msg instanceof PropertiesChanged)
  1007. propertiesChanged();
  1008. else if(msg instanceof SearchSettingsChanged)
  1009. {
  1010. if(searchBar != null)
  1011. searchBar.update();
  1012. }
  1013. else if(msg instanceof BufferUpdate)
  1014. handleBufferUpdate((BufferUpdate)msg);
  1015. else if(msg instanceof EditPaneUpdate)
  1016. handleEditPaneUpdate((EditPaneUpdate)msg);
  1017. } //}}}
  1018. //{{{ getMinimumSize() method
  1019. public Dimension getMinimumSize()
  1020. {
  1021. return new Dimension(0,0);
  1022. } //}}}
  1023. //{{{ setWaitSocket() method
  1024. /**
  1025. * This socket is closed when the buffer is closed.
  1026. */
  1027. public void setWaitSocket(Socket waitSocket)
  1028. {
  1029. this.waitSocket = waitSocket;
  1030. } //}}}
  1031. //{{{ toString() method
  1032. public String toString()
  1033. {
  1034. return getClass().getName() + "["
  1035. + (jEdit.getActiveView() == this
  1036. ? "active" : "inactive")
  1037. + "]";
  1038. } //}}}
  1039. //{{{ Package-private members
  1040. View prev;
  1041. View next;
  1042. //{{{ View constructor
  1043. View(Buffer buffer, ViewConfig config)
  1044. {
  1045. this.plainView = config.plainView;
  1046. enableEvents(AWTEvent.KEY_EVENT_MASK);
  1047. setIconImage(GUIUtilities.getEditorIcon());
  1048. dockableWindowManager = new DockableWindowManager(this,config);
  1049. topToolBars = new JPanel(new VariableGridLayout(
  1050. VariableGridLayout.FIXED_NUM_COLUMNS,
  1051. 1));
  1052. bottomToolBars = new JPanel(new VariableGridLayout(
  1053. VariableGridLayout.FIXED_NUM_COLUMNS,
  1054. 1));
  1055. toolBarManager = new ToolBarManager(topToolBars, bottomToolBars);
  1056. status = new StatusBar(this);
  1057. inputHandler = new DefaultInputHandler(this,(DefaultInputHandler)
  1058. jEdit.getInputHandler());
  1059. try
  1060. {
  1061. Component comp = restoreSplitConfig(buffer,config.splitConfig);
  1062. dockableWindowManager.add(comp,0);
  1063. }
  1064. catch(IOException e)
  1065. {
  1066. // this should never throw an exception.
  1067. throw new InternalError();
  1068. }
  1069. getContentPane().add(BorderLayout.CENTER,dockableWindowManager);
  1070. dockableWindowManager.init();
  1071. // tool bar and status bar gets added in propertiesChanged()
  1072. // depending in the 'tool bar alternate layout' setting.
  1073. propertiesChanged();
  1074. setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
  1075. addWindowListener(new WindowHandler());
  1076. EditBus.addToBus(this);
  1077. SearchDialog.preloadSearchDialog(this);
  1078. } //}}}
  1079. //{{{ close() method
  1080. void close()
  1081. {
  1082. GUIUtilities.saveGeometry(this,plainView ? "plain-view" : "view");
  1083. closed = true;
  1084. // save dockable window geometry, and close 'em
  1085. dockableWindowManager.close();
  1086. EditBus.removeFromBus(this);
  1087. dispose();
  1088. EditPane[] editPanes = getEditPanes();
  1089. for(int i = 0; i < editPanes.length; i++)
  1090. editPanes[i].close();
  1091. // null some variables so that retaining references
  1092. // to closed views won't hurt as much.
  1093. toolBarManager = null;
  1094. toolBar = null;
  1095. searchBar = null;
  1096. splitPane = null;
  1097. inputHandler = null;
  1098. recorder = null;
  1099. getContentPane().removeAll();
  1100. // notify clients with -wait
  1101. if(waitSocket != null)
  1102. {
  1103. try
  1104. {
  1105. waitSocket.getOutputStream().write('\0');
  1106. waitSocket.getOutputStream().flush();
  1107. waitSocket.getInputStream().close();
  1108. waitSocket.getOutputStream().close();
  1109. waitSocket.close();
  1110. }
  1111. catch(IOException io)
  1112. {
  1113. //Log.log(Log.ERROR,this,io);
  1114. }
  1115. }
  1116. } //}}}
  1117. //{{{ updateTitle() method
  1118. /**
  1119. * Updates the title bar.
  1120. */
  1121. void updateTitle()
  1122. {
  1123. Vector buffers = new Vector();
  1124. EditPane[] editPanes = getEditPanes();
  1125. for(int i = 0; i < editPanes.length; i++)
  1126. {
  1127. Buffer buffer = editPanes[i].getBuffer();
  1128. if(buffers.indexOf(buffer) == -1)
  1129. buffers.addElement(buffer);
  1130. }
  1131. StringBuffer title = new StringBuffer(jEdit.getProperty("view.title"));
  1132. for(int i = 0; i < buffers.size(); i++)
  1133. {
  1134. if(i != 0)
  1135. title.append(", ");
  1136. Buffer buffer = (Buffer)buffers.elementAt(i);
  1137. title.append((showFullPath && !buffer.isNewFile())
  1138. ? buffer.getPath() : buffer.getName());
  1139. if(buffer.isDirty())
  1140. title.append(jEdit.getProperty("view.title.dirty"));
  1141. }
  1142. setTitle(title.toString());
  1143. } //}}}
  1144. //}}}
  1145. //{{{ Private members
  1146. //{{{ Instance variables
  1147. private boolean closed;
  1148. private DockableWindowManager dockableWindowManager;
  1149. private JPanel topToolBars;
  1150. private JPanel bottomToolBars;
  1151. private ToolBarManager toolBarManager;
  1152. private Box toolBar;
  1153. private SearchBar searchBar;
  1154. private ActionBar actionBar;
  1155. private EditPane editPane;
  1156. private JSplitPane splitPane;
  1157. private StatusBar status;
  1158. private KeyListener keyEventInterceptor;
  1159. private InputHandler inputHandler;
  1160. private Macros.Recorder recorder;
  1161. private Component prefixFocusOwner;
  1162. private int waitCount;
  1163. private boolean showFullPath;
  1164. private boolean plainView;
  1165. private Socket waitSocket;
  1166. //}}}
  1167. //{{{ getEditPanes() method
  1168. private void getEditPanes(Vector vec, Component comp)
  1169. {
  1170. if(comp instanceof EditPane)
  1171. vec.addElement(comp);
  1172. else if(comp instanceof JSplitPane)
  1173. {
  1174. JSplitPane split = (JSplitPane)comp;
  1175. getEditPanes(vec,split.getLeftComponent());
  1176. getEditPanes(vec,split.getRightComponent());
  1177. }
  1178. } //}}}
  1179. //{{{ getSplitConfig() method
  1180. /*
  1181. * The split config is recorded in a simple RPN "language".
  1182. */
  1183. private void getSplitConfig(JSplitPane splitPane,
  1184. StringBuffer splitConfig)
  1185. {
  1186. Component right = splitPane.getRightComponent();
  1187. if(right instanceof JSplitPane)
  1188. getSplitConfig((JSplitPane)right,splitConfig);
  1189. else
  1190. {
  1191. splitConfig.append('"');
  1192. splitConfig.append(MiscUtilities.charsToEscapes(
  1193. ((EditPane)right).getBuffer().getPath()));
  1194. splitConfig.append("\" buffer");
  1195. }
  1196. splitConfig.append(' ');
  1197. Component left = splitPane.getLeftComponent();
  1198. if(left instanceof JSplitPane)
  1199. getSplitConfig((JSplitPane)left,splitConfig);
  1200. else
  1201. {
  1202. splitConfig.append('"');
  1203. splitConfig.append(MiscUtilities.charsToEscapes(
  1204. ((EditPane)left).getBuffer().getPath()));
  1205. splitConfig.append("\" buffer");
  1206. }
  1207. splitConfig.append(' ');
  1208. splitConfig.append(splitPane.getDividerLocation());
  1209. splitConfig.append(' ');
  1210. splitConfig.append(splitPane.getOrientation()
  1211. == JSplitPane.VERTICAL_SPLIT ? "vertical" : "horizontal");
  1212. } //}}}
  1213. //{{{ restoreSplitConfig() method
  1214. private Component restoreSplitConfig(Buffer buffer, String splitConfig)
  1215. throws IOException
  1216. // this is where checked exceptions piss me off. this method only uses
  1217. // a StringReader which can never throw an exception...
  1218. {
  1219. if(buffer != null)
  1220. return (editPane = createEditPane(buffer));
  1221. else if(splitConfig == null)
  1222. return (editPane = createEditPane(jEdit.getFirstBuffer()));
  1223. Buffer[] buffers = jEdit.getBuffers();
  1224. Stack stack = new Stack();
  1225. // we create a stream tokenizer for parsing a simple
  1226. // stack-based language
  1227. StreamTokenizer st = new StreamTokenizer(new StringReader(
  1228. splitConfig));
  1229. st.whitespaceChars(0,' ');
  1230. /* all printable ASCII characters */
  1231. st.wordChars('#','~');
  1232. st.commentChar('!');
  1233. st.quoteChar('"');
  1234. st.eolIsSignificant(false);
  1235. loop: for(;;)
  1236. {
  1237. switch(st.nextToken())
  1238. {
  1239. case StreamTokenizer.TT_EOF:
  1240. break loop;
  1241. case StreamTokenizer.TT_WORD:
  1242. if(st.sval.equals("vertical") ||
  1243. st.sval.equals("horizontal"))
  1244. {
  1245. int orientation
  1246. = (st.sval.equals("vertical")
  1247. ? JSplitPane.VERTICAL_SPLIT
  1248. : JSplitPane.HORIZONTAL_SPLIT);
  1249. int divider = ((Integer)stack.pop())
  1250. .intValue();
  1251. stack.push(splitPane = new JSplitPane(
  1252. orientation,
  1253. (Component)stack.pop(),
  1254. (Component)stack.pop()));
  1255. splitPane.setOneTouchExpandable(true);
  1256. splitPane.setBorder(null);
  1257. splitPane.setMinimumSize(
  1258. new Dimension(0,0));
  1259. splitPane.setDividerLocation(divider);
  1260. }
  1261. else if(st.sval.equals("buffer"))
  1262. {
  1263. Object obj = stack.pop();
  1264. if(obj instanceof Integer)
  1265. {
  1266. int index = ((Integer)obj).intValue();
  1267. if(index >= 0 && index < buffers.length)
  1268. buffer = buffers[index];
  1269. }
  1270. else if(obj instanceof String)
  1271. {
  1272. String path = (String)obj;
  1273. buffer = jEdit.getBuffer(path);
  1274. }
  1275. if(buffer == null)
  1276. buffer = jEdit.getFirstBuffer();
  1277. stack.push(editPane = createEditPane(
  1278. buffer));
  1279. }
  1280. break;
  1281. case StreamTokenizer.TT_NUMBER:
  1282. stack.push(new Integer((int)st.nval));
  1283. break;
  1284. case '"':
  1285. stack.push(st.sval);
  1286. break;
  1287. }
  1288. }
  1289. updateGutterBorders();
  1290. return (Component)stack.peek();
  1291. } //}}}
  1292. //{{{ propertiesChanged() method
  1293. /**
  1294. * Reloads various settings from the properties.
  1295. */
  1296. private void propertiesChanged()
  1297. {
  1298. setJMenuBar(GUIUtilities.loadMenuBar("view.mbar"));
  1299. loadToolBars();
  1300. showFullPath = jEdit.getBooleanProperty("view.showFullPath");
  1301. updateTitle();
  1302. status.propertiesChanged();
  1303. removeToolBar(status);
  1304. getContentPane().remove(status);
  1305. if(jEdit.getBooleanProperty("view.toolbar.alternateLayout"))
  1306. {
  1307. getContentPane().add(BorderLayout.NORTH,topToolBars);
  1308. getContentPane().add(BorderLayout.SOUTH,bottomToolBars);
  1309. if(!plainView && jEdit.getBooleanProperty("view.status.visible"))
  1310. addToolBar(BOTTOM_GROUP,STATUS_BAR_LAYER,status);
  1311. }
  1312. else
  1313. {
  1314. dockableWindowManager.add(topToolBars,
  1315. DockableWindowManager.DockableLayout
  1316. .TOP_TOOLBARS,0);
  1317. dockableWindowManager.add(bottomToolBars,
  1318. DockableWindowManager.DockableLayout
  1319. .BOTTOM_TOOLBARS,0);
  1320. if(!plainView && jEdit.getBooleanProperty("view.status.visible"))
  1321. getContentPane().add(BorderLayout.SOUTH,status);
  1322. }
  1323. getRootPane().revalidate();
  1324. //SwingUtilities.updateComponentTreeUI(getRootPane());
  1325. } //}}}
  1326. //{{{ loadToolBars() method
  1327. private void loadToolBars()
  1328. {
  1329. if(jEdit.getBooleanProperty("view.showToolbar") && !plainView)
  1330. {
  1331. if(toolBar != null)
  1332. toolBarManager.removeToolBar(toolBar);
  1333. toolBar = GUIUtilities.loadToolBar("view.toolbar");
  1334. addToolBar(TOP_GROUP, SYSTEM_BAR_LAYER, toolBar);
  1335. }
  1336. else if(toolBar != null)
  1337. {
  1338. removeToolBar(toolBar);
  1339. toolBar = null;
  1340. }
  1341. if(searchBar != null)
  1342. removeToolBar(searchBar);
  1343. if(jEdit.getBooleanProperty("view.showSearchbar") && !plainView)
  1344. {
  1345. if(searchBar == null)
  1346. searchBar = new SearchBar(this,false);
  1347. searchBar.propertiesChanged();
  1348. addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar);
  1349. }
  1350. } //}}}
  1351. //{{{ createEditPane() method
  1352. private EditPane createEditPane(Buffer buffer)
  1353. {
  1354. EditPane editPane = new EditPane(this,buffer);
  1355. JEditTextArea textArea = editPane.getTextArea();
  1356. textArea.addFocusListener(new FocusHandler());
  1357. textArea.addCaretListener(new CaretHandler());
  1358. textArea.addScrollListener(new ScrollHandler());
  1359. EditBus.send(new EditPaneUpdate(editPane,EditPaneUpdate.CREATED));
  1360. return editPane;
  1361. } //}}}
  1362. //{{{ setEditPane() method
  1363. private void setEditPane(EditPane editPane)
  1364. {
  1365. this.editPane = editPane;
  1366. status.updateCaretStatus();
  1367. status.updateBufferStatus();
  1368. status.updateMiscStatus();
  1369. // repaint the gutter so that the border color
  1370. // reflects the focus state
  1371. updateGutterBorders();
  1372. EditBus.send(new ViewUpdate(this,ViewUpdate.EDIT_PANE_CHANGED));
  1373. } //}}}
  1374. //{{{ handleBufferUpdate() method
  1375. private void handleBufferUpdate(BufferUpdate msg)
  1376. {
  1377. Buffer buffer = msg.getBuffer();
  1378. if(msg.getWhat() == BufferUpdate.DIRTY_CHANGED
  1379. || msg.getWhat() == BufferUpdate.LOADED)
  1380. {
  1381. EditPane[] editPanes = getEditPanes();
  1382. for(int i = 0; i < editPanes.length; i++)
  1383. {
  1384. if(editPanes[i].getBuffer() == buffer)
  1385. {
  1386. updateTitle();
  1387. break;
  1388. }
  1389. }
  1390. }
  1391. } //}}}
  1392. //{{{ handleEditPaneUpdate() method
  1393. private void handleEditPaneUpdate(EditPaneUpdate msg)
  1394. {
  1395. EditPane editPane = msg.getEditPane();
  1396. if(editPane.getView() == this
  1397. && msg.getWhat() == EditPaneUpdate.BUFFER_CHANGED
  1398. && editPane.getBuffer().isLoaded())
  1399. {
  1400. status.updateCaretStatus();
  1401. status.updateBufferStatus();
  1402. status.updateMiscStatus();
  1403. }
  1404. } //}}}
  1405. //{{{ updateGutterBorders() method
  1406. /**
  1407. * Updates the borders of all gutters in this view to reflect the
  1408. * currently focused text area.
  1409. * @since jEdit 2.6final
  1410. */
  1411. private void updateGutterBorders()
  1412. {
  1413. EditPane[] editPanes = getEditPanes();
  1414. for(int i = 0; i < editPanes.length; i++)
  1415. editPanes[i].getTextArea().getGutter().updateBorder();
  1416. } //}}}
  1417. //{{{ _preprocessKeyEvent() method
  1418. private KeyEvent _preprocessKeyEvent(KeyEvent evt)
  1419. {
  1420. if(isClosed())
  1421. return null;
  1422. if(getFocusOwner() instanceof JComponent)
  1423. {
  1424. JComponent comp = (JComponent)getFocusOwner();
  1425. InputMap map = comp.getInputMap();
  1426. ActionMap am = comp.getActionMap();
  1427. if(map != null && am != null && comp.isEnabled())
  1428. {
  1429. Object binding = map.get(KeyStroke.getKeyStrokeForEvent(evt));
  1430. if(binding != null && am.get(binding) != null)
  1431. {
  1432. return null;
  1433. }
  1434. }
  1435. }
  1436. if(getFocusOwner() instanceof JTextComponent)
  1437. {
  1438. // fix for the bug where key events in JTextComponents
  1439. // inside views are also handled by the input handler
  1440. if(evt.getID() == KeyEvent.KEY_PRESSED)
  1441. {
  1442. switch(evt.getKeyCode())
  1443. {
  1444. case KeyEvent.VK_ENTER:
  1445. case KeyEvent.VK_TAB:
  1446. case KeyEvent.VK_BACK_SPACE:
  1447. case KeyEvent.VK_SPACE:
  1448. return null;
  1449. }
  1450. }
  1451. }
  1452. if(evt.isConsumed())
  1453. return null;
  1454. return KeyEventWorkaround.processKeyEvent(evt);
  1455. } //}}}
  1456. //}}}
  1457. //{{{ Inner classes
  1458. //{{{ CaretHandler class
  1459. class CaretHandler implements CaretListener
  1460. {
  1461. public void caretUpdate(CaretEvent evt)
  1462. {
  1463. if(evt.getSource() == getTextArea())
  1464. status.updateCaretStatus();
  1465. }
  1466. } //}}}
  1467. //{{{ FocusHandler class
  1468. class FocusHandler extends FocusAdapter
  1469. {
  1470. public void focusGained(FocusEvent evt)
  1471. {
  1472. // walk up hierarchy, looking for an EditPane
  1473. Component comp = (Component)evt.getSource();
  1474. while(!(comp instanceof EditPane))
  1475. {
  1476. if(comp == null)
  1477. return;
  1478. comp = comp.getParent();
  1479. }
  1480. if(comp != editPane)
  1481. setEditPane((EditPane)comp);
  1482. else
  1483. updateGutterBorders();
  1484. }
  1485. } //}}}
  1486. //{{{ ScrollHandler class
  1487. class ScrollHandler implements ScrollListener
  1488. {
  1489. public void scrolledVertically(JEditTextArea textArea)
  1490. {
  1491. if(getTextArea() == textArea)
  1492. status.updateCaretStatus();
  1493. }
  1494. public void scrolledHorizontally(JEditTextArea textArea) {}
  1495. } //}}}
  1496. //{{{ WindowHandler class
  1497. class WindowHandler extends WindowAdapter
  1498. {
  1499. public void windowActivated(WindowEvent evt)
  1500. {
  1501. jEdit.setActiveView(View.this);
  1502. // People have reported hangs with JDK 1.4; might be
  1503. // caused by modal dialogs being displayed from
  1504. // windowActivated()
  1505. SwingUtilities.invokeLater(new Runnable()
  1506. {
  1507. public void run()
  1508. {
  1509. jEdit.checkBufferStatus(View.this);
  1510. }
  1511. });
  1512. }
  1513. public void windowClosing(WindowEvent evt)
  1514. {
  1515. jEdit.closeView(View.this);
  1516. }
  1517. } //}}}
  1518. //{{{ ViewConfig class
  1519. public static class ViewConfig
  1520. {
  1521. public boolean plainView;
  1522. public String splitConfig;
  1523. public int x, y, width, height, extState;
  1524. // dockables
  1525. public String top, left, bottom, right;
  1526. public int topPos, leftPos, bottomPos, rightPos;
  1527. public ViewConfig()
  1528. {
  1529. }
  1530. public ViewConfig(boolean plainView)
  1531. {
  1532. this.plainView = plainView;
  1533. String prefix = (plainView ? "plain-view" : "view");
  1534. x = jEdit.getIntegerProperty(prefix + ".x",0);
  1535. y = jEdit.getIntegerProperty(prefix + ".y",0);
  1536. width = jEdit.getIntegerProperty(prefix + ".width",0);
  1537. height = jEdit.getIntegerProperty(prefix + ".height",0);
  1538. }
  1539. public ViewConfig(boolean plainView, String splitConfig,
  1540. int x, int y, int width, int height, int extState)
  1541. {
  1542. this.plainView = plainView;
  1543. this.splitConfig = splitConfig;
  1544. this.x = x;
  1545. this.y = y;
  1546. this.width = width;
  1547. this.height = height;
  1548. this.extState = extState;
  1549. }
  1550. } //}}}
  1551. //}}}
  1552. }