0001: /*
0002: * View.java - jEdit view
0003: * :tabSize=8:indentSize=8:noTabs=false:
0004: * :folding=explicit:collapseFolds=1:
0005: *
0006: * Copyright (C) 1998, 2004 Slava Pestov
0007: *
0008: * This program is free software; you can redistribute it and/or
0009: * modify it under the terms of the GNU General Public License
0010: * as published by the Free Software Foundation; either version 2
0011: * of the License, or any later version.
0012: *
0013: * This program is distributed in the hope that it will be useful,
0014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0016: * GNU General Public License for more details.
0017: *
0018: * You should have received a copy of the GNU General Public License
0019: * along with this program; if not, write to the Free Software
0020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0021: */
0022:
0023: package org.gjt.sp.jedit;
0024:
0025: //{{{ Imports
0026: import javax.swing.event.*;
0027: import javax.swing.*;
0028: import java.awt.*;
0029: import java.awt.event.*;
0030: import java.io.IOException;
0031: import java.io.StreamTokenizer;
0032: import java.io.StringReader;
0033: import java.net.Socket;
0034: import java.util.*;
0035: import java.util.List;
0036:
0037: import org.gjt.sp.jedit.msg.*;
0038: import org.gjt.sp.jedit.gui.*;
0039: import org.gjt.sp.jedit.gui.InputHandler;
0040: import org.gjt.sp.jedit.gui.DefaultInputHandler;
0041: import org.gjt.sp.jedit.search.*;
0042: import org.gjt.sp.jedit.textarea.*;
0043: import org.gjt.sp.jedit.textarea.TextArea;
0044: import org.gjt.sp.jedit.input.InputHandlerProvider;
0045:
0046: //}}}
0047:
0048: /**
0049: * A <code>View</code> is jEdit's top-level frame window.<p>
0050: *
0051: * In a BeanShell script, you can obtain the current view instance from the
0052: * <code>view</code> variable.<p>
0053: *
0054: * The largest component it contains is an {@link EditPane} that in turn
0055: * contains a {@link org.gjt.sp.jedit.textarea.JEditTextArea} that displays a
0056: * {@link Buffer}.
0057: * A view can have more than one edit pane in a split window configuration.
0058: * A view also contains a menu bar, an optional toolbar and other window
0059: * decorations, as well as docked windows.<p>
0060: *
0061: * The <b>View</b> class performs two important operations
0062: * dealing with plugins: creating plugin menu items, and managing dockable
0063: * windows.
0064: *
0065: * <ul>
0066: * <li>When a view is being created, its initialization routine
0067: * iterates through the collection of loaded plugins and constructs the
0068: * <b>Plugins</b> menu using the properties as specified in the
0069: * {@link EditPlugin} class.</li>
0070: * <li>The view also creates and initializes a
0071: * {@link org.gjt.sp.jedit.gui.DockableWindowManager}
0072: * object. This object is
0073: * responsible for creating, closing and managing dockable windows.</li>
0074: * </ul>
0075: *
0076: * This class does not have a public constructor.
0077: * Views can be opened and closed using methods in the <code>jEdit</code>
0078: * class.
0079: *
0080: * @see org.gjt.sp.jedit.jEdit#newView(View)
0081: * @see org.gjt.sp.jedit.jEdit#newView(View,Buffer)
0082: * @see org.gjt.sp.jedit.jEdit#newView(View,Buffer,boolean)
0083: * @see org.gjt.sp.jedit.jEdit#closeView(View)
0084: *
0085: * @author Slava Pestov
0086: * @author John Gellene (API documentation)
0087: * @version $Id: View.java 10894 2007-10-15 16:11:39Z mediumnet $
0088: */
0089: public class View extends JFrame implements EBComponent,
0090: InputHandlerProvider {
0091: //{{{ User interface
0092:
0093: //{{{ ToolBar-related constants
0094:
0095: //{{{ Groups
0096: /**
0097: * The group of tool bars above the DockableWindowManager
0098: * @see #addToolBar(int,int,java.awt.Component)
0099: * @since jEdit 4.0pre7
0100: */
0101: public static final int TOP_GROUP = 0;
0102:
0103: /**
0104: * The group of tool bars below the DockableWindowManager
0105: * @see #addToolBar(int,int,java.awt.Component)
0106: * @since jEdit 4.0pre7
0107: */
0108: public static final int BOTTOM_GROUP = 1;
0109: public static final int DEFAULT_GROUP = TOP_GROUP;
0110: //}}}
0111:
0112: //{{{ Layers
0113:
0114: // Common layers
0115: /**
0116: * The highest possible layer.
0117: * @see #addToolBar(int,int,java.awt.Component)
0118: * @since jEdit 4.0pre7
0119: */
0120: public static final int TOP_LAYER = Integer.MAX_VALUE;
0121:
0122: /**
0123: * The default layer for tool bars with no preference.
0124: * @see #addToolBar(int,int,java.awt.Component)
0125: * @since jEdit 4.0pre7
0126: */
0127: public static final int DEFAULT_LAYER = 0;
0128:
0129: /**
0130: * The lowest possible layer.
0131: * @see #addToolBar(int,int,java.awt.Component)
0132: * @since jEdit 4.0pre7
0133: */
0134: public static final int BOTTOM_LAYER = Integer.MIN_VALUE;
0135:
0136: // Layers for top group
0137: /**
0138: * Above system tool bar layer.
0139: * @see #addToolBar(int,int,java.awt.Component)
0140: * @since jEdit 4.0pre7
0141: */
0142: public static final int ABOVE_SYSTEM_BAR_LAYER = 150;
0143:
0144: /**
0145: * System tool bar layer.
0146: * jEdit uses this for the main tool bar.
0147: * @see #addToolBar(int,int,java.awt.Component)
0148: * @since jEdit 4.0pre7
0149: */
0150: public static final int SYSTEM_BAR_LAYER = 100;
0151:
0152: /**
0153: * Below system tool bar layer.
0154: * @see #addToolBar(int,int,java.awt.Component)
0155: * @since jEdit 4.0pre7
0156: */
0157: public static final int BELOW_SYSTEM_BAR_LAYER = 75;
0158:
0159: /**
0160: * Search bar layer.
0161: * @see #addToolBar(int,int,java.awt.Component)
0162: * @since jEdit 4.0pre7
0163: */
0164: public static final int SEARCH_BAR_LAYER = 75;
0165:
0166: /**
0167: * Below search bar layer.
0168: * @see #addToolBar(int,int,java.awt.Component)
0169: * @since jEdit 4.0pre7
0170: */
0171: public static final int BELOW_SEARCH_BAR_LAYER = 50;
0172:
0173: // Layers for bottom group
0174: /**
0175: * @deprecated Status bar no longer added as a tool bar.
0176: */
0177: public static final int ABOVE_ACTION_BAR_LAYER = -50;
0178:
0179: /**
0180: * Action bar layer.
0181: * @see #addToolBar(int,int,java.awt.Component)
0182: * @since jEdit 4.2pre1
0183: */
0184: public static final int ACTION_BAR_LAYER = -75;
0185:
0186: /**
0187: * Status bar layer.
0188: * @see #addToolBar(int,int,java.awt.Component)
0189: * @since jEdit 4.2pre1
0190: */
0191: public static final int STATUS_BAR_LAYER = -100;
0192:
0193: /**
0194: * Status bar layer.
0195: * @see #addToolBar(int,int,java.awt.Component)
0196: * @since jEdit 4.2pre1
0197: */
0198: public static final int BELOW_STATUS_BAR_LAYER = -150;
0199:
0200: //}}}
0201:
0202: //}}}
0203:
0204: //{{{ getDockableWindowManager() method
0205: /**
0206: * Returns the dockable window manager associated with this view.
0207: * @since jEdit 2.6pre3
0208: */
0209: public DockableWindowManager getDockableWindowManager() {
0210: return dockableWindowManager;
0211: } //}}}
0212:
0213: //{{{ getToolBar() method
0214: /**
0215: * Returns the view's tool bar.
0216: * @since jEdit 4.2pre1
0217: */
0218: public Box getToolBar() {
0219: return toolBar;
0220: } //}}}
0221:
0222: //{{{ addToolBar() method
0223: /**
0224: * Adds a tool bar to this view.
0225: * @param toolBar The tool bar
0226: */
0227: public void addToolBar(Component toolBar) {
0228: addToolBar(DEFAULT_GROUP, DEFAULT_LAYER, toolBar);
0229: } //}}}
0230:
0231: //{{{ addToolBar() method
0232: /**
0233: * Adds a tool bar to this view.
0234: * @param group The tool bar group to add to
0235: * @param toolBar The tool bar
0236: * @see org.gjt.sp.jedit.gui.ToolBarManager
0237: * @since jEdit 4.0pre7
0238: */
0239: public void addToolBar(int group, Component toolBar) {
0240: addToolBar(group, DEFAULT_LAYER, toolBar);
0241: } //}}}
0242:
0243: //{{{ addToolBar() method
0244: /**
0245: * Adds a tool bar to this view.
0246: * @param group The tool bar group to add to
0247: * @param layer The layer of the group to add to
0248: * @param toolBar The tool bar
0249: * @see org.gjt.sp.jedit.gui.ToolBarManager
0250: * @since jEdit 4.0pre7
0251: */
0252: public void addToolBar(int group, int layer, Component toolBar) {
0253: toolBarManager.addToolBar(group, layer, toolBar);
0254: getRootPane().revalidate();
0255: } //}}}
0256:
0257: //{{{ removeToolBar() method
0258: /**
0259: * Removes a tool bar from this view.
0260: * @param toolBar The tool bar
0261: */
0262: public void removeToolBar(Component toolBar) {
0263: if (toolBarManager == null)
0264: return;
0265: if (toolBar == null)
0266: return;
0267: toolBarManager.removeToolBar(toolBar);
0268: getRootPane().revalidate();
0269: } //}}}
0270:
0271: //{{{ showWaitCursor() method
0272: /**
0273: * Shows the wait cursor. This method and
0274: * {@link #hideWaitCursor()} are implemented using a reference
0275: * count of requests for wait cursors, so that nested calls work
0276: * correctly; however, you should be careful to use these methods in
0277: * tandem.<p>
0278: *
0279: * To ensure that {@link #hideWaitCursor()} is always called
0280: * after a {@link #showWaitCursor()}, use a
0281: * <code>try</code>/<code>finally</code> block, like this:
0282: * <pre>try
0283: *{
0284: * view.showWaitCursor();
0285: * // ...
0286: *}
0287: *finally
0288: *{
0289: * view.hideWaitCursor();
0290: *}</pre>
0291: */
0292: public synchronized void showWaitCursor() {
0293: if (waitCount++ == 0) {
0294: Cursor cursor = Cursor
0295: .getPredefinedCursor(Cursor.WAIT_CURSOR);
0296: setCursor(cursor);
0297: EditPane[] editPanes = getEditPanes();
0298: for (int i = 0; i < editPanes.length; i++) {
0299: EditPane editPane = editPanes[i];
0300: editPane.getTextArea().getPainter().setCursor(cursor);
0301: }
0302: }
0303: } //}}}
0304:
0305: //{{{ hideWaitCursor() method
0306: /**
0307: * Hides the wait cursor.
0308: */
0309: public synchronized void hideWaitCursor() {
0310: if (waitCount > 0)
0311: waitCount--;
0312:
0313: if (waitCount == 0) {
0314: // still needed even though glass pane
0315: // has a wait cursor
0316: Cursor cursor = Cursor
0317: .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
0318: setCursor(cursor);
0319: cursor = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
0320: EditPane[] editPanes = getEditPanes();
0321: for (int i = 0; i < editPanes.length; i++) {
0322: EditPane editPane = editPanes[i];
0323: editPane.getTextArea().getPainter().setCursor(cursor);
0324: }
0325: }
0326: } //}}}
0327:
0328: //{{{ getSearchBar() method
0329: /**
0330: * Returns the search bar.
0331: * @since jEdit 2.4pre4
0332: */
0333: public final SearchBar getSearchBar() {
0334: return searchBar;
0335: } //}}}
0336:
0337: //{{{ getActionBar() method
0338: /**
0339: * Returns the action bar.
0340: * @since jEdit 4.2pre3
0341: */
0342: public final ActionBar getActionBar() {
0343: return actionBar;
0344: } //}}}
0345:
0346: //{{{ getStatus() method
0347: /**
0348: * Returns the status bar. The
0349: * {@link org.gjt.sp.jedit.gui.StatusBar#setMessage(String)} and
0350: * {@link org.gjt.sp.jedit.gui.StatusBar#setMessageAndClear(String)} methods can
0351: * be called on the return value of this method to display status
0352: * information to the user.
0353: * @since jEdit 3.2pre2
0354: */
0355: public StatusBar getStatus() {
0356: return status;
0357: } //}}}
0358:
0359: //{{{ quickIncrementalSearch() method
0360: /**
0361: * Quick search.
0362: * @since jEdit 4.0pre3
0363: */
0364: public void quickIncrementalSearch(boolean word) {
0365: if (searchBar == null)
0366: searchBar = new SearchBar(this , true);
0367: if (searchBar.getParent() == null)
0368: addToolBar(TOP_GROUP, SEARCH_BAR_LAYER, searchBar);
0369:
0370: searchBar.setHyperSearch(false);
0371:
0372: JEditTextArea textArea = getTextArea();
0373:
0374: if (word) {
0375: String text = textArea.getSelectedText();
0376: if (text == null) {
0377: textArea.selectWord();
0378: text = textArea.getSelectedText();
0379: } else if (text.indexOf('\n') != -1)
0380: text = null;
0381:
0382: if (text != null && SearchAndReplace.getRegexp())
0383: text = SearchAndReplace.escapeRegexp(text, false);
0384:
0385: searchBar.getField().setText(text);
0386: }
0387:
0388: searchBar.getField().requestFocus();
0389: searchBar.getField().selectAll();
0390: } //}}}
0391:
0392: //{{{ quickHyperSearch() method
0393: /**
0394: * Quick HyperSearch.
0395: * @since jEdit 4.0pre3
0396: */
0397: public void quickHyperSearch(boolean word) {
0398: JEditTextArea textArea = getTextArea();
0399:
0400: if (word) {
0401: String text = textArea.getSelectedText();
0402: if (text == null) {
0403: textArea.selectWord();
0404: text = textArea.getSelectedText();
0405: }
0406:
0407: if (text != null && text.indexOf('\n') == -1) {
0408: if (SearchAndReplace.getRegexp()) {
0409: text = SearchAndReplace.escapeRegexp(text, false);
0410: }
0411:
0412: HistoryModel.getModel("find").addItem(text);
0413: SearchAndReplace.setSearchString(text);
0414: SearchAndReplace
0415: .setSearchFileSet(new CurrentBufferSet());
0416: SearchAndReplace.hyperSearch(this );
0417:
0418: return;
0419: }
0420: }
0421:
0422: if (searchBar == null)
0423: searchBar = new SearchBar(this , true);
0424: if (searchBar.getParent() == null)
0425: addToolBar(TOP_GROUP, SEARCH_BAR_LAYER, searchBar);
0426:
0427: searchBar.setHyperSearch(true);
0428: searchBar.getField().setText(null);
0429: searchBar.getField().requestFocus();
0430: searchBar.getField().selectAll();
0431: } //}}}
0432:
0433: //{{{ actionBar() method
0434: /**
0435: * Shows the action bar if needed, and sends keyboard focus there.
0436: * @since jEdit 4.2pre1
0437: */
0438: public void actionBar() {
0439: if (actionBar == null)
0440: actionBar = new ActionBar(this , true);
0441: if (actionBar.getParent() == null)
0442: addToolBar(BOTTOM_GROUP, ACTION_BAR_LAYER, actionBar);
0443:
0444: actionBar.goToActionBar();
0445: } //}}}
0446:
0447: //}}}
0448:
0449: //{{{ Input handling
0450:
0451: //{{{ getKeyEventInterceptor() method
0452: /**
0453: * Returns the listener that will handle all key events in this
0454: * view, if any.
0455: * @return the key event interceptor or null
0456: */
0457: public KeyListener getKeyEventInterceptor() {
0458: return inputHandler.getKeyEventInterceptor();
0459: } //}}}
0460:
0461: //{{{ setKeyEventInterceptor() method
0462: /**
0463: * Sets the listener that will handle all key events in this
0464: * view. For example, the complete word command uses this so
0465: * that all key events are passed to the word list popup while
0466: * it is visible.
0467: * @param listener The key event interceptor.
0468: */
0469: public void setKeyEventInterceptor(KeyListener listener) {
0470: inputHandler.setKeyEventInterceptor(listener);
0471: } //}}}
0472:
0473: //{{{ getInputHandler() method
0474: /**
0475: * Returns the input handler.
0476: */
0477: public InputHandler getInputHandler() {
0478: return inputHandler;
0479: } //}}}
0480:
0481: //{{{ setInputHandler() method
0482: /**
0483: * Sets the input handler.
0484: * @param inputHandler The new input handler
0485: */
0486: public void setInputHandler(InputHandler inputHandler) {
0487: this .inputHandler = inputHandler;
0488: } //}}}
0489:
0490: //{{{ getMacroRecorder() method
0491: /**
0492: * Returns the macro recorder.
0493: */
0494: public Macros.Recorder getMacroRecorder() {
0495: return recorder;
0496: } //}}}
0497:
0498: //{{{ setMacroRecorder() method
0499: /**
0500: * Sets the macro recorder.
0501: * @param recorder The macro recorder
0502: */
0503: public void setMacroRecorder(Macros.Recorder recorder) {
0504: this .recorder = recorder;
0505: } //}}}
0506:
0507: //{{{ processKeyEvent() method
0508: /**
0509: * Forwards key events directly to the input handler.
0510: * This is slightly faster than using a KeyListener
0511: * because some Swing overhead is avoided.
0512: */
0513: public void processKeyEvent(KeyEvent evt) {
0514: inputHandler.processKeyEvent(evt, VIEW, false);
0515: if (!evt.isConsumed())
0516: super .processKeyEvent(evt);
0517: } //}}}
0518:
0519: //{{{ processKeyEvent() method
0520: /**
0521: * Forwards key events directly to the input handler.
0522: * This is slightly faster than using a KeyListener
0523: * because some Swing overhead is avoided.
0524: */
0525: public void processKeyEvent(KeyEvent evt, boolean calledFromTextArea) {
0526: processKeyEvent(evt, calledFromTextArea ? TEXT_AREA : VIEW);
0527: } //}}}
0528:
0529: //{{{ processKeyEvent() method
0530: public static final int VIEW = 0;
0531: public static final int TEXT_AREA = 1;
0532: public static final int ACTION_BAR = 2;
0533:
0534: /**
0535: * Forwards key events directly to the input handler.
0536: * This is slightly faster than using a KeyListener
0537: * because some Swing overhead is avoided.
0538: */
0539: public void processKeyEvent(KeyEvent evt, int from) {
0540: processKeyEvent(evt, from, false);
0541: }
0542:
0543: /**
0544: * Forwards key events directly to the input handler.
0545: * This is slightly faster than using a KeyListener
0546: * because some Swing overhead is avoided.
0547: * @deprecated do not use, try {@link org.gjt.sp.jedit.gui.InputHandler#processKeyEvent(java.awt.event.KeyEvent, int, boolean)}
0548: */
0549: public void processKeyEvent(KeyEvent evt, int from, boolean global) {
0550: inputHandler.processKeyEvent(evt, from, global);
0551: if (!evt.isConsumed())
0552: super .processKeyEvent(evt);
0553: } //}}}
0554:
0555: //}}}
0556:
0557: //{{{ Buffers, edit panes, split panes
0558:
0559: //{{{ splitHorizontally() method
0560: /**
0561: * Splits the view horizontally.
0562: * @since jEdit 4.1pre2
0563: */
0564: public EditPane splitHorizontally() {
0565: return split(JSplitPane.VERTICAL_SPLIT);
0566: } //}}}
0567:
0568: //{{{ splitVertically() method
0569: /**
0570: * Splits the view vertically.
0571: * @since jEdit 4.1pre2
0572: */
0573: public EditPane splitVertically() {
0574: return split(JSplitPane.HORIZONTAL_SPLIT);
0575: } //}}}
0576:
0577: //{{{ split() method
0578: /**
0579: * Splits the view.
0580: * @since jEdit 4.1pre2
0581: */
0582: public EditPane split(int orientation) {
0583: PerspectiveManager.setPerspectiveDirty(true);
0584:
0585: editPane.saveCaretInfo();
0586: EditPane oldEditPane = editPane;
0587: setEditPane(createEditPane(oldEditPane.getBuffer()));
0588: editPane.loadCaretInfo();
0589:
0590: JComponent oldParent = (JComponent) oldEditPane.getParent();
0591:
0592: final JSplitPane newSplitPane = new JSplitPane(orientation,
0593: jEdit.getBooleanProperty("appearance.continuousLayout"));
0594: newSplitPane.setOneTouchExpandable(true);
0595: newSplitPane.setBorder(null);
0596: newSplitPane.setMinimumSize(new Dimension(0, 0));
0597: newSplitPane.setResizeWeight(0.5);
0598:
0599: int parentSize = orientation == JSplitPane.VERTICAL_SPLIT ? oldEditPane
0600: .getHeight()
0601: : oldEditPane.getWidth();
0602: final int dividerPosition = (int) ((parentSize - newSplitPane
0603: .getDividerSize()) * 0.5);
0604: newSplitPane.setDividerLocation(dividerPosition);
0605:
0606: if (oldParent instanceof JSplitPane) {
0607: JSplitPane oldSplitPane = (JSplitPane) oldParent;
0608: int dividerPos = oldSplitPane.getDividerLocation();
0609:
0610: Component left = oldSplitPane.getLeftComponent();
0611:
0612: if (left == oldEditPane)
0613: oldSplitPane.setLeftComponent(newSplitPane);
0614: else
0615: oldSplitPane.setRightComponent(newSplitPane);
0616:
0617: newSplitPane.setLeftComponent(oldEditPane);
0618: newSplitPane.setRightComponent(editPane);
0619:
0620: oldSplitPane.setDividerLocation(dividerPos);
0621: } else {
0622: splitPane = newSplitPane;
0623:
0624: newSplitPane.setLeftComponent(oldEditPane);
0625: newSplitPane.setRightComponent(editPane);
0626:
0627: oldParent.add(newSplitPane, 0);
0628: oldParent.revalidate();
0629: }
0630:
0631: SwingUtilities.invokeLater(new Runnable() {
0632: public void run() {
0633: newSplitPane.setDividerLocation(dividerPosition);
0634: }
0635: });
0636:
0637: editPane.focusOnTextArea();
0638:
0639: return editPane;
0640: } //}}}
0641:
0642: //{{{ unsplit() method
0643: /**
0644: * Unsplits the view.
0645: * @since jEdit 2.3pre2
0646: */
0647: public void unsplit() {
0648: if (splitPane != null) {
0649: lastSplitConfig = getSplitConfig();
0650:
0651: PerspectiveManager.setPerspectiveDirty(true);
0652:
0653: EditPane[] editPanes = getEditPanes();
0654: for (int i = 0; i < editPanes.length; i++) {
0655: EditPane _editPane = editPanes[i];
0656: if (editPane != _editPane)
0657: _editPane.close();
0658: }
0659:
0660: JComponent parent = (JComponent) splitPane.getParent();
0661:
0662: parent.remove(splitPane);
0663: parent.add(editPane, 0);
0664: parent.revalidate();
0665:
0666: splitPane = null;
0667: updateTitle();
0668:
0669: editPane.focusOnTextArea();
0670: } else
0671: getToolkit().beep();
0672: } //}}}
0673:
0674: //{{{ unsplitCurrent() method
0675: /**
0676: * Removes the current split.
0677: * @since jEdit 2.3pre2
0678: */
0679: public void unsplitCurrent() {
0680: if (splitPane != null) {
0681: lastSplitConfig = getSplitConfig();
0682:
0683: PerspectiveManager.setPerspectiveDirty(true);
0684:
0685: // find first split pane parenting current edit pane
0686: Component comp = editPane;
0687: while (!(comp instanceof JSplitPane)) {
0688: comp = comp.getParent();
0689: }
0690:
0691: // get rid of any edit pane that is a child
0692: // of the current edit pane's parent splitter
0693: EditPane[] editPanes = getEditPanes();
0694: for (int i = 0; i < editPanes.length; i++) {
0695: EditPane _editPane = editPanes[i];
0696: if (GUIUtilities.isAncestorOf(comp, _editPane)
0697: && _editPane != editPane)
0698: _editPane.close();
0699: }
0700:
0701: JComponent parent = (JComponent) comp.getParent();
0702:
0703: if (parent instanceof JSplitPane) {
0704: JSplitPane parentSplit = (JSplitPane) parent;
0705: int pos = parentSplit.getDividerLocation();
0706: if (parentSplit.getLeftComponent() == comp)
0707: parentSplit.setLeftComponent(editPane);
0708: else
0709: parentSplit.setRightComponent(editPane);
0710: parentSplit.setDividerLocation(pos);
0711: } else {
0712: parent.remove(comp);
0713: parent.add(editPane, 0);
0714: splitPane = null;
0715: }
0716:
0717: parent.revalidate();
0718:
0719: updateTitle();
0720:
0721: editPane.focusOnTextArea();
0722: } else
0723: getToolkit().beep();
0724: } //}}}
0725:
0726: //{{{ resplit() method
0727: /**
0728: * Restore the split configuration as it was before unsplitting.
0729: *
0730: * @since jEdit 4.3pre1
0731: */
0732: public void resplit() {
0733: if (lastSplitConfig == null)
0734: getToolkit().beep();
0735: else
0736: setSplitConfig(null, lastSplitConfig);
0737: } //}}}
0738:
0739: //{{{ nextTextArea() method
0740: /**
0741: * Moves keyboard focus to the next text area.
0742: * @since jEdit 2.7pre4
0743: */
0744: public void nextTextArea() {
0745: EditPane[] editPanes = getEditPanes();
0746: for (int i = 0; i < editPanes.length; i++) {
0747: if (editPane == editPanes[i]) {
0748: if (i == editPanes.length - 1)
0749: editPanes[0].focusOnTextArea();
0750: else
0751: editPanes[i + 1].focusOnTextArea();
0752: break;
0753: }
0754: }
0755: } //}}}
0756:
0757: //{{{ prevTextArea() method
0758: /**
0759: * Moves keyboard focus to the previous text area.
0760: * @since jEdit 2.7pre4
0761: */
0762: public void prevTextArea() {
0763: EditPane[] editPanes = getEditPanes();
0764: for (int i = 0; i < editPanes.length; i++) {
0765: if (editPane == editPanes[i]) {
0766: if (i == 0)
0767: editPanes[editPanes.length - 1].focusOnTextArea();
0768: else
0769: editPanes[i - 1].focusOnTextArea();
0770: break;
0771: }
0772: }
0773: } //}}}
0774:
0775: //{{{ getSplitPane() method
0776: /**
0777: * Returns the top-level split pane, if any.
0778: * @since jEdit 2.3pre2
0779: */
0780: public JSplitPane getSplitPane() {
0781: return splitPane;
0782: } //}}}
0783:
0784: //{{{ getBuffer() method
0785: /**
0786: * Returns the current edit pane's buffer.
0787: */
0788: public Buffer getBuffer() {
0789: if (editPane == null)
0790: return null;
0791: else
0792: return editPane.getBuffer();
0793: } //}}}
0794:
0795: //{{{ setBuffer() method
0796: /**
0797: * Sets the current edit pane's buffer.
0798: * @param buffer The buffer
0799: */
0800: public void setBuffer(Buffer buffer) {
0801: setBuffer(buffer, false);
0802: } //}}}
0803:
0804: //{{{ setBuffer() method
0805: /**
0806: * Sets the current edit pane's buffer.
0807: * @param buffer The buffer
0808: * @param disableFileStatusCheck Disables file status checking
0809: * regardless of the state of the checkFileStatus property
0810: */
0811: public void setBuffer(Buffer buffer, boolean disableFileStatusCheck) {
0812: editPane.setBuffer(buffer);
0813:
0814: int check = jEdit.getIntegerProperty("checkFileStatus");
0815: if ((!disableFileStatusCheck)
0816: && (check == 1 || check == 2 || check == 3))
0817: jEdit.checkBufferStatus(this , true);
0818: } //}}}
0819:
0820: //{{{ goToBuffer() method
0821: /**
0822: * If this buffer is open in one of the view's edit panes, sets focus
0823: * to that edit pane. Otherwise, opens the buffer in the currently
0824: * active edit pane.
0825: * @param buffer The buffer
0826: * @since jEdit 4.2pre1
0827: */
0828: public EditPane goToBuffer(Buffer buffer) {
0829: if (editPane.getBuffer() == buffer
0830: && editPane.getTextArea().getVisibleLines() > 1) {
0831: editPane.focusOnTextArea();
0832: return editPane;
0833: }
0834:
0835: EditPane[] editPanes = getEditPanes();
0836: for (int i = 0; i < editPanes.length; i++) {
0837: EditPane ep = editPanes[i];
0838: if (ep.getBuffer() == buffer
0839: /* ignore zero-height splits, etc */
0840: && ep.getTextArea().getVisibleLines() > 1) {
0841: setEditPane(ep);
0842: ep.focusOnTextArea();
0843: return ep;
0844: }
0845: }
0846:
0847: setBuffer(buffer, false);
0848: return editPane;
0849: } //}}}
0850:
0851: //{{{ getTextArea() method
0852: /**
0853: * Returns the current edit pane's text area.
0854: */
0855: public JEditTextArea getTextArea() {
0856: if (editPane == null)
0857: return null;
0858: else
0859: return editPane.getTextArea();
0860: } //}}}
0861:
0862: //{{{ getEditPane() method
0863: /**
0864: * Returns the current edit pane.
0865: * @since jEdit 2.5pre2
0866: */
0867: public EditPane getEditPane() {
0868: return editPane;
0869: } //}}}
0870:
0871: //{{{ getEditPanes() method
0872: /**
0873: * Returns all edit panes.
0874: * @since jEdit 2.5pre2
0875: */
0876: public EditPane[] getEditPanes() {
0877: if (splitPane == null) {
0878: EditPane[] ep = { editPane };
0879: return ep;
0880: } else {
0881: List<EditPane> vec = new ArrayList<EditPane>();
0882: getEditPanes(vec, splitPane);
0883: EditPane[] ep = new EditPane[vec.size()];
0884: vec.toArray(ep);
0885: return ep;
0886: }
0887: } //}}}
0888:
0889: //{{{ getViewConfig() method
0890: /**
0891: * @since jEdit 4.2pre1
0892: */
0893: public ViewConfig getViewConfig() {
0894: ViewConfig config = new ViewConfig();
0895: config.plainView = isPlainView();
0896: config.splitConfig = getSplitConfig();
0897: config.extState = getExtendedState();
0898: String prefix = config.plainView ? "plain-view" : "view";
0899: switch (config.extState) {
0900: case Frame.MAXIMIZED_BOTH:
0901: case Frame.ICONIFIED:
0902: config.x = jEdit.getIntegerProperty(prefix + ".x", getX());
0903: config.y = jEdit.getIntegerProperty(prefix + ".y", getY());
0904: config.width = jEdit.getIntegerProperty(prefix + ".width",
0905: getWidth());
0906: config.height = jEdit.getIntegerProperty(
0907: prefix + ".height", getHeight());
0908: break;
0909:
0910: case Frame.MAXIMIZED_VERT:
0911: config.x = getX();
0912: config.y = jEdit.getIntegerProperty(prefix + ".y", getY());
0913: config.width = getWidth();
0914: config.height = jEdit.getIntegerProperty(
0915: prefix + ".height", getHeight());
0916: break;
0917:
0918: case Frame.MAXIMIZED_HORIZ:
0919: config.x = jEdit.getIntegerProperty(prefix + ".x", getX());
0920: config.y = getY();
0921: config.width = jEdit.getIntegerProperty(prefix + ".width",
0922: getWidth());
0923: config.height = getHeight();
0924: break;
0925:
0926: case Frame.NORMAL:
0927: default:
0928: config.x = getX();
0929: config.y = getY();
0930: config.width = getWidth();
0931: config.height = getHeight();
0932: break;
0933: }
0934:
0935: config.top = dockableWindowManager.getTopDockingArea()
0936: .getCurrent();
0937: config.left = dockableWindowManager.getLeftDockingArea()
0938: .getCurrent();
0939: config.bottom = dockableWindowManager.getBottomDockingArea()
0940: .getCurrent();
0941: config.right = dockableWindowManager.getRightDockingArea()
0942: .getCurrent();
0943:
0944: config.topPos = dockableWindowManager.getTopDockingArea()
0945: .getDimension();
0946: config.leftPos = dockableWindowManager.getLeftDockingArea()
0947: .getDimension();
0948: config.bottomPos = dockableWindowManager.getBottomDockingArea()
0949: .getDimension();
0950: config.rightPos = dockableWindowManager.getRightDockingArea()
0951: .getDimension();
0952:
0953: return config;
0954: } //}}}
0955:
0956: //}}}
0957:
0958: //{{{ isClosed() method
0959: /**
0960: * Returns true if this view has been closed with
0961: * {@link jEdit#closeView(View)}.
0962: */
0963: public boolean isClosed() {
0964: return closed;
0965: } //}}}
0966:
0967: //{{{ isPlainView() method
0968: /**
0969: * Returns true if this is an auxilliary view with no dockable windows.
0970: * @since jEdit 4.1pre2
0971: */
0972: public boolean isPlainView() {
0973: return plainView;
0974: } //}}}
0975:
0976: //{{{ getNext() method
0977: /**
0978: * Returns the next view in the list.
0979: */
0980: public View getNext() {
0981: return next;
0982: } //}}}
0983:
0984: //{{{ getPrev() method
0985: /**
0986: * Returns the previous view in the list.
0987: */
0988: public View getPrev() {
0989: return prev;
0990: } //}}}
0991:
0992: //{{{ handleMessage() method
0993: public void handleMessage(EBMessage msg) {
0994: if (msg instanceof PropertiesChanged)
0995: propertiesChanged();
0996: else if (msg instanceof SearchSettingsChanged) {
0997: if (searchBar != null)
0998: searchBar.update();
0999: } else if (msg instanceof BufferUpdate)
1000: handleBufferUpdate((BufferUpdate) msg);
1001: else if (msg instanceof EditPaneUpdate)
1002: handleEditPaneUpdate((EditPaneUpdate) msg);
1003: } //}}}
1004:
1005: //{{{ getMinimumSize() method
1006: public Dimension getMinimumSize() {
1007: return new Dimension(0, 0);
1008: } //}}}
1009:
1010: //{{{ setWaitSocket() method
1011: /**
1012: * This socket is closed when the buffer is closed.
1013: */
1014: public void setWaitSocket(Socket waitSocket) {
1015: this .waitSocket = waitSocket;
1016: } //}}}
1017:
1018: //{{{ toString() method
1019: public String toString() {
1020: return getClass().getName()
1021: + '['
1022: + (jEdit.getActiveView() == this ? "active"
1023: : "inactive") + ']';
1024: } //}}}
1025:
1026: //{{{ updateTitle() method
1027: /**
1028: * Updates the title bar.
1029: */
1030: public void updateTitle() {
1031: List<Buffer> buffers = new ArrayList<Buffer>();
1032: EditPane[] editPanes = getEditPanes();
1033: for (int i = 0; i < editPanes.length; i++) {
1034: Buffer buffer = editPanes[i].getBuffer();
1035: if (buffers.indexOf(buffer) == -1)
1036: buffers.add(buffer);
1037: }
1038:
1039: StringBuilder title = new StringBuilder();
1040:
1041: /* On Mac OS X, apps are not supposed to show their name in the
1042: title bar. */
1043: if (!OperatingSystem.isMacOS())
1044: title.append(jEdit.getProperty("view.title"));
1045:
1046: boolean unsavedChanges = false;
1047:
1048: for (int i = 0; i < buffers.size(); i++) {
1049: if (i != 0)
1050: title.append(", ");
1051:
1052: Buffer buffer = buffers.get(i);
1053: title.append((showFullPath && !buffer.isNewFile()) ? buffer
1054: .getPath() : buffer.getName());
1055: if (buffer.isDirty()) {
1056: unsavedChanges = true;
1057: title.append(jEdit.getProperty("view.title.dirty"));
1058: }
1059: }
1060:
1061: setTitle(title.toString());
1062:
1063: /* On MacOS X, the close box is shown in a different color if
1064: an app has unsaved changes. For details, see
1065: http://developer.apple.com/qa/qa2001/qa1146.html */
1066: final String WINDOW_MODIFIED = "windowModified";
1067: getRootPane()
1068: .putClientProperty(WINDOW_MODIFIED, unsavedChanges);
1069: } //}}}
1070:
1071: public Component getPrefixFocusOwner() {
1072: return prefixFocusOwner;
1073: }
1074:
1075: public void setPrefixFocusOwner(Component prefixFocusOwner) {
1076: this .prefixFocusOwner = prefixFocusOwner;
1077: }
1078:
1079: //{{{ Package-private members
1080: View prev;
1081: View next;
1082:
1083: //{{{ View constructor
1084: View(Buffer buffer, ViewConfig config) {
1085: plainView = config.plainView;
1086:
1087: enableEvents(AWTEvent.KEY_EVENT_MASK);
1088:
1089: setIconImage(GUIUtilities.getEditorIcon());
1090:
1091: dockableWindowManager = new DockableWindowManager(this ,
1092: DockableWindowFactory.getInstance(), config);
1093:
1094: topToolBars = new JPanel(new VariableGridLayout(
1095: VariableGridLayout.FIXED_NUM_COLUMNS, 1));
1096: bottomToolBars = new JPanel(new VariableGridLayout(
1097: VariableGridLayout.FIXED_NUM_COLUMNS, 1));
1098:
1099: toolBarManager = new ToolBarManager(topToolBars, bottomToolBars);
1100:
1101: status = new StatusBar(this );
1102:
1103: inputHandler = new DefaultInputHandler(this ,
1104: (DefaultInputHandler) jEdit.getInputHandler());
1105:
1106: setSplitConfig(buffer, config.splitConfig);
1107:
1108: getContentPane()
1109: .add(BorderLayout.CENTER, dockableWindowManager);
1110:
1111: dockableWindowManager.init();
1112:
1113: // tool bar and status bar gets added in propertiesChanged()
1114: // depending in the 'tool bar alternate layout' setting.
1115: propertiesChanged();
1116:
1117: setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
1118: addWindowListener(new WindowHandler());
1119:
1120: setFocusTraversalPolicy(new MyFocusTraversalPolicy());
1121:
1122: EditBus.addToBus(this );
1123:
1124: GUIUtilities.addSizeSaver(this , null, plainView ? "plain-view"
1125: : "view");
1126: } //}}}
1127:
1128: //{{{ close() method
1129: void close() {
1130: EditBus.send(new ViewUpdate(this , ViewUpdate.CLOSED));
1131: closed = true;
1132:
1133: // save dockable window geometry, and close 'em
1134: dockableWindowManager.close();
1135:
1136: EditBus.removeFromBus(this );
1137: dispose();
1138:
1139: EditPane[] editPanes = getEditPanes();
1140: for (int i = 0; i < editPanes.length; i++)
1141: editPanes[i].close();
1142:
1143: // null some variables so that retaining references
1144: // to closed views won't hurt as much.
1145: toolBarManager = null;
1146: toolBar = null;
1147: searchBar = null;
1148: splitPane = null;
1149: inputHandler = null;
1150: recorder = null;
1151:
1152: getContentPane().removeAll();
1153:
1154: // notify clients with -wait
1155: if (waitSocket != null) {
1156: try {
1157: waitSocket.getOutputStream().write('\0');
1158: waitSocket.getOutputStream().flush();
1159: waitSocket.getInputStream().close();
1160: waitSocket.getOutputStream().close();
1161: waitSocket.close();
1162: } catch (IOException io) {
1163: //Log.log(Log.ERROR,this,io);
1164: }
1165: }
1166: } //}}}
1167:
1168: //}}}
1169:
1170: //{{{ Private members
1171:
1172: //{{{ Instance variables
1173: private boolean closed;
1174:
1175: private DockableWindowManager dockableWindowManager;
1176:
1177: private JPanel topToolBars;
1178: private JPanel bottomToolBars;
1179: private ToolBarManager toolBarManager;
1180:
1181: private Box toolBar;
1182: private SearchBar searchBar;
1183: private ActionBar actionBar;
1184:
1185: private EditPane editPane;
1186: private JSplitPane splitPane;
1187: private String lastSplitConfig;
1188:
1189: private StatusBar status;
1190:
1191: private InputHandler inputHandler;
1192: private Macros.Recorder recorder;
1193: private Component prefixFocusOwner;
1194:
1195: private int waitCount;
1196:
1197: private boolean showFullPath;
1198:
1199: private boolean plainView;
1200:
1201: private Socket waitSocket;
1202:
1203: //}}}
1204:
1205: //{{{ getEditPanes() method
1206: private static void getEditPanes(List<EditPane> vec, Component comp) {
1207: if (comp instanceof EditPane)
1208: vec.add((EditPane) comp);
1209: else if (comp instanceof JSplitPane) {
1210: JSplitPane split = (JSplitPane) comp;
1211: getEditPanes(vec, split.getLeftComponent());
1212: getEditPanes(vec, split.getRightComponent());
1213: }
1214: } //}}}
1215:
1216: //{{{ getSplitConfig() method
1217: private String getSplitConfig() {
1218: StringBuilder splitConfig = new StringBuilder();
1219:
1220: if (splitPane != null)
1221: getSplitConfig(splitPane, splitConfig);
1222: else {
1223: splitConfig.append('"');
1224: splitConfig.append(MiscUtilities.charsToEscapes(getBuffer()
1225: .getPath()));
1226: splitConfig.append("\" buffer");
1227: }
1228:
1229: return splitConfig.toString();
1230: } //}}}
1231:
1232: //{{{ getSplitConfig() method
1233: /*
1234: * The split config is recorded in a simple RPN "language".
1235: */
1236: private static void getSplitConfig(JSplitPane splitPane,
1237: StringBuilder splitConfig) {
1238: Component right = splitPane.getRightComponent();
1239: if (right instanceof JSplitPane)
1240: getSplitConfig((JSplitPane) right, splitConfig);
1241: else {
1242: splitConfig.append('"');
1243: splitConfig.append(MiscUtilities
1244: .charsToEscapes(((EditPane) right).getBuffer()
1245: .getPath()));
1246: splitConfig.append("\" buffer");
1247: }
1248:
1249: splitConfig.append(' ');
1250:
1251: Component left = splitPane.getLeftComponent();
1252: if (left instanceof JSplitPane)
1253: getSplitConfig((JSplitPane) left, splitConfig);
1254: else {
1255: splitConfig.append('"');
1256: splitConfig.append(MiscUtilities
1257: .charsToEscapes(((EditPane) left).getBuffer()
1258: .getPath()));
1259: splitConfig.append("\" buffer");
1260: }
1261:
1262: splitConfig.append(' ');
1263: splitConfig.append(splitPane.getDividerLocation());
1264: splitConfig.append(' ');
1265: splitConfig
1266: .append(splitPane.getOrientation() == JSplitPane.VERTICAL_SPLIT ? "vertical"
1267: : "horizontal");
1268: } //}}}
1269:
1270: //{{{ setSplitConfig() method
1271: private void setSplitConfig(Buffer buffer, String splitConfig) {
1272: if (editPane != null)
1273: dockableWindowManager.remove(editPane);
1274:
1275: if (splitPane != null)
1276: dockableWindowManager.remove(splitPane);
1277:
1278: try {
1279: Component comp = restoreSplitConfig(buffer, splitConfig);
1280: dockableWindowManager.add(comp, 0);
1281: } catch (IOException e) {
1282: // this should never throw an exception.
1283: throw new InternalError();
1284: }
1285:
1286: dockableWindowManager.revalidate();
1287: dockableWindowManager.repaint();
1288: } //}}}
1289:
1290: //{{{ restoreSplitConfig() method
1291: private Component restoreSplitConfig(Buffer buffer,
1292: String splitConfig) throws IOException
1293: // this is where checked exceptions piss me off. this method only uses
1294: // a StringReader which can never throw an exception...
1295: {
1296: if (buffer != null)
1297: return editPane = createEditPane(buffer);
1298: else if (splitConfig == null)
1299: return editPane = createEditPane(jEdit.getFirstBuffer());
1300:
1301: Buffer[] buffers = jEdit.getBuffers();
1302:
1303: Stack stack = new Stack();
1304:
1305: // we create a stream tokenizer for parsing a simple
1306: // stack-based language
1307: StreamTokenizer st = new StreamTokenizer(new StringReader(
1308: splitConfig));
1309: st.whitespaceChars(0, ' ');
1310: /* all printable ASCII characters */
1311: st.wordChars('#', '~');
1312: st.commentChar('!');
1313: st.quoteChar('"');
1314: st.eolIsSignificant(false);
1315: boolean continuousLayout = jEdit
1316: .getBooleanProperty("appearance.continuousLayout");
1317: loop: while (true) {
1318: switch (st.nextToken()) {
1319: case StreamTokenizer.TT_EOF:
1320: break loop;
1321: case StreamTokenizer.TT_WORD:
1322: if (st.sval.equals("vertical")
1323: || st.sval.equals("horizontal")) {
1324: int orientation = (st.sval.equals("vertical") ? JSplitPane.VERTICAL_SPLIT
1325: : JSplitPane.HORIZONTAL_SPLIT);
1326: int divider = ((Integer) stack.pop()).intValue();
1327: stack.push(splitPane = new JSplitPane(orientation,
1328: continuousLayout, (Component) stack.pop(),
1329: (Component) stack.pop()));
1330: splitPane.setOneTouchExpandable(true);
1331: splitPane.setBorder(null);
1332: splitPane.setMinimumSize(new Dimension(0, 0));
1333: splitPane.setDividerLocation(divider);
1334: } else if (st.sval.equals("buffer")) {
1335: Object obj = stack.pop();
1336: if (obj instanceof Integer) {
1337: int index = ((Integer) obj).intValue();
1338: if (index >= 0 && index < buffers.length)
1339: buffer = buffers[index];
1340: } else if (obj instanceof String) {
1341: String path = (String) obj;
1342: buffer = jEdit.getBuffer(path);
1343: }
1344:
1345: if (buffer == null)
1346: buffer = jEdit.getFirstBuffer();
1347:
1348: stack.push(editPane = createEditPane(buffer));
1349: }
1350: break;
1351: case StreamTokenizer.TT_NUMBER:
1352: stack.push((int) st.nval);
1353: break;
1354: case '"':
1355: stack.push(st.sval);
1356: break;
1357: }
1358: }
1359:
1360: updateGutterBorders();
1361:
1362: return (Component) stack.peek();
1363: } //}}}
1364:
1365: //{{{ propertiesChanged() method
1366: /**
1367: * Reloads various settings from the properties.
1368: */
1369: private void propertiesChanged() {
1370: setJMenuBar(GUIUtilities.loadMenuBar("view.mbar"));
1371:
1372: loadToolBars();
1373:
1374: showFullPath = jEdit.getBooleanProperty("view.showFullPath");
1375: updateTitle();
1376:
1377: status.propertiesChanged();
1378:
1379: removeToolBar(status);
1380: getContentPane().remove(status);
1381:
1382: if (jEdit.getBooleanProperty("view.toolbar.alternateLayout")) {
1383: getContentPane().add(BorderLayout.NORTH, topToolBars);
1384: getContentPane().add(BorderLayout.SOUTH, bottomToolBars);
1385: if (!plainView
1386: && jEdit.getBooleanProperty("view.status.visible"))
1387: addToolBar(BOTTOM_GROUP, STATUS_BAR_LAYER, status);
1388: } else {
1389: dockableWindowManager.add(topToolBars,
1390: DockableLayout.TOP_TOOLBARS, 0);
1391: dockableWindowManager.add(bottomToolBars,
1392: DockableLayout.BOTTOM_TOOLBARS, 0);
1393: if (!plainView
1394: && jEdit.getBooleanProperty("view.status.visible"))
1395: getContentPane().add(BorderLayout.SOUTH, status);
1396: }
1397:
1398: getRootPane().revalidate();
1399:
1400: if (splitPane != null)
1401: GUIUtilities.initContinuousLayout(splitPane);
1402: //SwingUtilities.updateComponentTreeUI(getRootPane());
1403: } //}}}
1404:
1405: //{{{ loadToolBars() method
1406: private void loadToolBars() {
1407: if (jEdit.getBooleanProperty("view.showToolbar") && !plainView) {
1408: if (toolBar != null)
1409: toolBarManager.removeToolBar(toolBar);
1410:
1411: toolBar = GUIUtilities.loadToolBar("view.toolbar");
1412:
1413: addToolBar(TOP_GROUP, SYSTEM_BAR_LAYER, toolBar);
1414: } else if (toolBar != null) {
1415: removeToolBar(toolBar);
1416: toolBar = null;
1417: }
1418:
1419: if (searchBar != null)
1420: removeToolBar(searchBar);
1421:
1422: if (jEdit.getBooleanProperty("view.showSearchbar")
1423: && !plainView) {
1424: if (searchBar == null)
1425: searchBar = new SearchBar(this , false);
1426: searchBar.propertiesChanged();
1427: addToolBar(TOP_GROUP, SEARCH_BAR_LAYER, searchBar);
1428: }
1429: } //}}}
1430:
1431: //{{{ createEditPane() method
1432: private EditPane createEditPane(Buffer buffer) {
1433: EditPane editPane = new EditPane(this , buffer);
1434: JEditTextArea textArea = editPane.getTextArea();
1435: textArea.addFocusListener(new FocusHandler());
1436: textArea.addCaretListener(new CaretHandler());
1437: textArea.addScrollListener(new ScrollHandler());
1438: EditBus.send(new EditPaneUpdate(editPane,
1439: EditPaneUpdate.CREATED));
1440: return editPane;
1441: } //}}}
1442:
1443: //{{{ setEditPane() method
1444: private void setEditPane(EditPane editPane) {
1445: this .editPane = editPane;
1446: status.updateCaretStatus();
1447: status.updateBufferStatus();
1448: status.updateMiscStatus();
1449:
1450: // repaint the gutter so that the border color
1451: // reflects the focus state
1452: updateGutterBorders();
1453:
1454: EditBus
1455: .send(new ViewUpdate(this , ViewUpdate.EDIT_PANE_CHANGED));
1456: } //}}}
1457:
1458: //{{{ handleBufferUpdate() method
1459: private void handleBufferUpdate(BufferUpdate msg) {
1460: Buffer buffer = msg.getBuffer();
1461: if (msg.getWhat() == BufferUpdate.DIRTY_CHANGED
1462: || msg.getWhat() == BufferUpdate.LOADED) {
1463: EditPane[] editPanes = getEditPanes();
1464: for (int i = 0; i < editPanes.length; i++) {
1465: if (editPanes[i].getBuffer() == buffer) {
1466: updateTitle();
1467: break;
1468: }
1469: }
1470: }
1471: } //}}}
1472:
1473: //{{{ handleEditPaneUpdate() method
1474: private void handleEditPaneUpdate(EditPaneUpdate msg) {
1475: EditPane editPane = msg.getEditPane();
1476: if (editPane.getView() == this
1477: && msg.getWhat() == EditPaneUpdate.BUFFER_CHANGED
1478: && editPane.getBuffer().isLoaded()) {
1479: status.updateCaretStatus();
1480: status.updateBufferStatus();
1481: status.updateMiscStatus();
1482: }
1483: } //}}}
1484:
1485: //{{{ updateGutterBorders() method
1486: /**
1487: * Updates the borders of all gutters in this view to reflect the
1488: * currently focused text area.
1489: * @since jEdit 2.6final
1490: */
1491: private void updateGutterBorders() {
1492: EditPane[] editPanes = getEditPanes();
1493: for (int i = 0; i < editPanes.length; i++)
1494: editPanes[i].getTextArea().getGutter().updateBorder();
1495: } //}}}
1496:
1497: //}}}
1498:
1499: //{{{ Inner classes
1500:
1501: //{{{ CaretHandler class
1502: class CaretHandler implements CaretListener {
1503: public void caretUpdate(CaretEvent evt) {
1504: if (evt.getSource() == getTextArea())
1505: status.updateCaretStatus();
1506: }
1507: } //}}}
1508:
1509: //{{{ FocusHandler class
1510: class FocusHandler extends FocusAdapter {
1511: public void focusGained(FocusEvent evt) {
1512: // walk up hierarchy, looking for an EditPane
1513: Component comp = (Component) evt.getSource();
1514: while (!(comp instanceof EditPane)) {
1515: if (comp == null)
1516: return;
1517:
1518: comp = comp.getParent();
1519: }
1520:
1521: if (comp != editPane)
1522: setEditPane((EditPane) comp);
1523: else
1524: updateGutterBorders();
1525: }
1526: } //}}}
1527:
1528: //{{{ ScrollHandler class
1529: class ScrollHandler implements ScrollListener {
1530: public void scrolledVertically(TextArea textArea) {
1531: if (getTextArea() == textArea)
1532: status.updateCaretStatus();
1533: }
1534:
1535: public void scrolledHorizontally(TextArea textArea) {
1536: }
1537: } //}}}
1538:
1539: //{{{ WindowHandler class
1540: class WindowHandler extends WindowAdapter {
1541: public void windowActivated(WindowEvent evt) {
1542: boolean editPaneChanged = jEdit.getActiveViewInternal() != View.this ;
1543: jEdit.setActiveView(View.this );
1544:
1545: // People have reported hangs with JDK 1.4; might be
1546: // caused by modal dialogs being displayed from
1547: // windowActivated()
1548: SwingUtilities.invokeLater(new Runnable() {
1549: public void run() {
1550: int check = jEdit
1551: .getIntegerProperty("checkFileStatus");
1552: if (check == 0 || check == 1)
1553: jEdit.checkBufferStatus(View.this , false);
1554: else if (check == 3)
1555: jEdit.checkBufferStatus(View.this , true);
1556: }
1557: });
1558:
1559: if (editPaneChanged) {
1560: EditBus.send(new ViewUpdate(View.this ,
1561: ViewUpdate.ACTIVATED));
1562: }
1563: }
1564:
1565: public void windowClosing(WindowEvent evt) {
1566: jEdit.closeView(View.this );
1567: }
1568: } //}}}
1569:
1570: //{{{ ViewConfig class
1571: public static class ViewConfig {
1572: public boolean plainView;
1573: public String splitConfig;
1574: public int x, y, width, height, extState;
1575:
1576: // dockables
1577: public String top, left, bottom, right;
1578: public int topPos, leftPos, bottomPos, rightPos;
1579:
1580: public ViewConfig() {
1581: }
1582:
1583: public ViewConfig(boolean plainView) {
1584: this .plainView = plainView;
1585: String prefix = plainView ? "plain-view" : "view";
1586: x = jEdit.getIntegerProperty(prefix + ".x", 0);
1587: y = jEdit.getIntegerProperty(prefix + ".y", 0);
1588: width = jEdit.getIntegerProperty(prefix + ".width", 0);
1589: height = jEdit.getIntegerProperty(prefix + ".height", 0);
1590: extState = jEdit.getIntegerProperty(prefix
1591: + ".extendedState", NORMAL);
1592: }
1593:
1594: public ViewConfig(boolean plainView, String splitConfig, int x,
1595: int y, int width, int height, int extState) {
1596: this .plainView = plainView;
1597: this .splitConfig = splitConfig;
1598: this .x = x;
1599: this .y = y;
1600: this .width = width;
1601: this .height = height;
1602: this .extState = extState;
1603: }
1604: } //}}}
1605:
1606: //{{{ MyFocusTraversalPolicy class
1607: static class MyFocusTraversalPolicy extends
1608: LayoutFocusTraversalPolicy {
1609: public Component getDefaultComponent(Container focusCycleRoot) {
1610: return GUIUtilities.getView(focusCycleRoot).getTextArea();
1611: }
1612: } //}}}
1613:
1614: //}}}
1615: }
|