|
What this is
Other links
The source code/* * View.java - jEdit view * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 1998, 2003 Slava Pestov * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gjt.sp.jedit; //{{{ Imports import javax.swing.event.*; import javax.swing.text.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.IOException; import java.io.StreamTokenizer; import java.io.StringReader; import java.net.Socket; import java.util.*; import org.gjt.sp.jedit.msg.*; import org.gjt.sp.jedit.gui.*; import org.gjt.sp.jedit.search.*; import org.gjt.sp.jedit.textarea.*; import org.gjt.sp.util.Log; //}}} /** * A
jEdit
* class.
*
* @see org.gjt.sp.jedit.jEdit#newView(View)
* @see org.gjt.sp.jedit.jEdit#newView(View,Buffer)
* @see org.gjt.sp.jedit.jEdit#newView(View,Buffer,boolean)
* @see org.gjt.sp.jedit.jEdit#closeView(View)
*
* @author Slava Pestov
* @author John Gellene (API documentation)
* @version $Id: View.java,v 1.111 2004/05/06 22:35:11 spestov Exp $
*/
public class View extends JFrame implements EBComponent
{
//{{{ User interface
//{{{ ToolBar-related constants
//{{{ Groups
/**
* The group of tool bars above the DockableWindowManager
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int TOP_GROUP = 0;
/**
* The group of tool bars below the DockableWindowManager
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int BOTTOM_GROUP = 1;
public static final int DEFAULT_GROUP = TOP_GROUP;
//}}}
//{{{ Layers
// Common layers
/**
* The highest possible layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int TOP_LAYER = Integer.MAX_VALUE;
/**
* The default layer for tool bars with no preference.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int DEFAULT_LAYER = 0;
/**
* The lowest possible layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int BOTTOM_LAYER = Integer.MIN_VALUE;
// Layers for top group
/**
* Above system tool bar layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int ABOVE_SYSTEM_BAR_LAYER = 150;
/**
* System tool bar layer.
* jEdit uses this for the main tool bar.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int SYSTEM_BAR_LAYER = 100;
/**
* Below system tool bar layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int BELOW_SYSTEM_BAR_LAYER = 75;
/**
* Search bar layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int SEARCH_BAR_LAYER = 75;
/**
* Below search bar layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.0pre7
*/
public static final int BELOW_SEARCH_BAR_LAYER = 50;
// Layers for bottom group
/**
* @deprecated Status bar no longer added as a tool bar.
*/
public static final int ABOVE_ACTION_BAR_LAYER = -50;
/**
* Action bar layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.2pre1
*/
public static final int ACTION_BAR_LAYER = -75;
/**
* Status bar layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.2pre1
*/
public static final int STATUS_BAR_LAYER = -100;
/**
* Status bar layer.
* @see #addToolBar(int,int,java.awt.Component)
* @since jEdit 4.2pre1
*/
public static final int BELOW_STATUS_BAR_LAYER = -150;
//}}}
//}}}
//{{{ getDockableWindowManager() method
/**
* Returns the dockable window manager associated with this view.
* @since jEdit 2.6pre3
*/
public DockableWindowManager getDockableWindowManager()
{
return dockableWindowManager;
} //}}}
//{{{ getToolBar() method
/**
* Returns the view's tool bar.
* @since jEdit 4.2pre1
*/
public Box getToolBar()
{
return toolBar;
} //}}}
//{{{ addToolBar() method
/**
* Adds a tool bar to this view.
* @param toolBar The tool bar
*/
public void addToolBar(Component toolBar)
{
addToolBar(DEFAULT_GROUP, DEFAULT_LAYER, toolBar);
} //}}}
//{{{ addToolBar() method
/**
* Adds a tool bar to this view.
* @param group The tool bar group to add to
* @param toolBar The tool bar
* @see org.gjt.sp.jedit.gui.ToolBarManager
* @since jEdit 4.0pre7
*/
public void addToolBar(int group, Component toolBar)
{
addToolBar(group, DEFAULT_LAYER, toolBar);
} //}}}
//{{{ addToolBar() method
/**
* Adds a tool bar to this view.
* @param group The tool bar group to add to
* @param layer The layer of the group to add to
* @param toolBar The tool bar
* @see org.gjt.sp.jedit.gui.ToolBarManager
* @since jEdit 4.0pre7
*/
public void addToolBar(int group, int layer, Component toolBar)
{
toolBarManager.addToolBar(group, layer, toolBar);
getRootPane().revalidate();
} //}}}
//{{{ removeToolBar() method
/**
* Removes a tool bar from this view.
* @param toolBar The tool bar
*/
public void removeToolBar(Component toolBar)
{
toolBarManager.removeToolBar(toolBar);
getRootPane().revalidate();
} //}}}
//{{{ showWaitCursor() method
/**
* Shows the wait cursor. This method and
* {@link #hideWaitCursor()} are implemented using a reference
* count of requests for wait cursors, so that nested calls work
* correctly; however, you should be careful to use these methods in
* tandem.
*
* To ensure that {@link #hideWaitCursor()} is always called
* after a {@link #showWaitCursor()}, use a
* try *{ * view.showWaitCursor(); * // ... *} *finally *{ * view.hideWaitCursor(); *}*/ public synchronized void showWaitCursor() { if(waitCount++ == 0) { Cursor cursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); setCursor(cursor); EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { EditPane editPane = editPanes[i]; editPane.getTextArea().getPainter() .setCursor(cursor); } } } //}}} //{{{ hideWaitCursor() method /** * Hides the wait cursor. */ public synchronized void hideWaitCursor() { if(waitCount > 0) waitCount--; if(waitCount == 0) { // still needed even though glass pane // has a wait cursor Cursor cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); setCursor(cursor); cursor = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR); EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { EditPane editPane = editPanes[i]; editPane.getTextArea().getPainter() .setCursor(cursor); } } } //}}} //{{{ getSearchBar() method /** * Returns the search bar. * @since jEdit 2.4pre4 */ public final SearchBar getSearchBar() { return searchBar; } //}}} //{{{ getActionBar() method /** * Returns the action bar. * @since jEdit 4.2pre3 */ public final ActionBar getActionBar() { return actionBar; } //}}} //{{{ getStatus() method /** * Returns the status bar. The * {@link org.gjt.sp.jedit.gui.StatusBar#setMessage(String)} and * {@link org.gjt.sp.jedit.gui.StatusBar#setMessageAndClear(String)} methods can * be called on the return value of this method to display status * information to the user. * @since jEdit 3.2pre2 */ public StatusBar getStatus() { return status; } //}}} //{{{ quickIncrementalSearch() method /** * Quick search. * @since jEdit 4.0pre3 */ public void quickIncrementalSearch(boolean word) { if(searchBar == null) searchBar = new SearchBar(this,true); if(searchBar.getParent() == null) addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar); searchBar.setHyperSearch(false); JEditTextArea textArea = getTextArea(); if(word) { String text = textArea.getSelectedText(); if(text == null) { textArea.selectWord(); text = textArea.getSelectedText(); } else if(text.indexOf('\n') != -1) text = null; searchBar.getField().setText(text); } searchBar.getField().requestFocus(); searchBar.getField().selectAll(); } //}}} //{{{ quickHyperSearch() method /** * Quick HyperSearch. * @since jEdit 4.0pre3 */ public void quickHyperSearch(boolean word) { JEditTextArea textArea = getTextArea(); if(word) { String text = textArea.getSelectedText(); if(text == null) { textArea.selectWord(); text = textArea.getSelectedText(); } if(text != null && text.indexOf('\n') == -1) { HistoryModel.getModel("find").addItem(text); SearchAndReplace.setSearchString(text); SearchAndReplace.setSearchFileSet(new CurrentBufferSet()); SearchAndReplace.hyperSearch(this); return; } } if(searchBar == null) searchBar = new SearchBar(this,true); if(searchBar.getParent() == null) addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar); searchBar.setHyperSearch(true); searchBar.getField().setText(null); searchBar.getField().requestFocus(); searchBar.getField().selectAll(); } //}}} //{{{ actionBar() method /** * Shows the action bar if needed, and sends keyboard focus there. * @since jEdit 4.2pre1 */ public void actionBar() { if(actionBar == null) actionBar = new ActionBar(this,true); if(actionBar.getParent() == null) addToolBar(BOTTOM_GROUP,ACTION_BAR_LAYER,actionBar); actionBar.goToActionBar(); } //}}} //}}} //{{{ Input handling //{{{ getKeyEventInterceptor() method /** * Returns the listener that will handle all key events in this * view, if any. */ public KeyListener getKeyEventInterceptor() { return keyEventInterceptor; } //}}} //{{{ setKeyEventInterceptor() method /** * Sets the listener that will handle all key events in this * view. For example, the complete word command uses this so * that all key events are passed to the word list popup while * it is visible. * @param listener The key event interceptor. */ public void setKeyEventInterceptor(KeyListener listener) { this.keyEventInterceptor = listener; } //}}} //{{{ getInputHandler() method /** * Returns the input handler. */ public InputHandler getInputHandler() { return inputHandler; } //}}} //{{{ setInputHandler() method /** * Sets the input handler. * @param inputHandler The new input handler */ public void setInputHandler(InputHandler inputHandler) { this.inputHandler = inputHandler; } //}}} //{{{ getMacroRecorder() method /** * Returns the macro recorder. */ public Macros.Recorder getMacroRecorder() { return recorder; } //}}} //{{{ setMacroRecorder() method /** * Sets the macro recorder. * @param recorder The macro recorder */ public void setMacroRecorder(Macros.Recorder recorder) { this.recorder = recorder; } //}}} //{{{ processKeyEvent() method /** * Forwards key events directly to the input handler. * This is slightly faster than using a KeyListener * because some Swing overhead is avoided. */ public void processKeyEvent(KeyEvent evt) { processKeyEvent(evt,VIEW); } //}}} //{{{ processKeyEvent() method /** * Forwards key events directly to the input handler. * This is slightly faster than using a KeyListener * because some Swing overhead is avoided. */ public void processKeyEvent(KeyEvent evt, boolean calledFromTextArea) { processKeyEvent(evt,calledFromTextArea ? TEXT_AREA : VIEW); } //}}} //{{{ processKeyEvent() method public static final int VIEW = 0; public static final int TEXT_AREA = 1; public static final int ACTION_BAR = 2; /** * Forwards key events directly to the input handler. * This is slightly faster than using a KeyListener * because some Swing overhead is avoided. */ public void processKeyEvent(KeyEvent evt, int from) { if(Debug.DUMP_KEY_EVENTS && from != VIEW) { Log.log(Log.DEBUG,this,"Key event: " + GrabKeyDialog.toString(evt)); } if(getTextArea().hasFocus() && from == VIEW) return; evt = _preprocessKeyEvent(evt); if(evt == null) return; if(Debug.DUMP_KEY_EVENTS && from != VIEW) { Log.log(Log.DEBUG,this,"Key event after workaround: " + GrabKeyDialog.toString(evt)); } switch(evt.getID()) { case KeyEvent.KEY_TYPED: boolean focusOnTextArea = false; // if the user pressed eg C+e n n in the // search bar we want focus to go back there // after the prefix is done if(prefixFocusOwner != null) { if(prefixFocusOwner.isShowing()) { prefixFocusOwner.requestFocus(); focusOnTextArea = true; } } if(keyEventInterceptor != null) keyEventInterceptor.keyTyped(evt); else if(from == ACTION_BAR || inputHandler.isPrefixActive() || getTextArea().hasFocus()) { KeyEventTranslator.Key keyStroke = KeyEventTranslator .translateKeyEvent(evt); if(keyStroke != null) { if(Debug.DUMP_KEY_EVENTS && from != VIEW) { Log.log(Log.DEBUG,this, "Translated: " + keyStroke); } if(inputHandler.handleKey(keyStroke)) evt.consume(); } } // we might have been closed as a result of // the above if(isClosed()) return; // this is a weird hack. // we don't want C+e a to insert 'a' in the // search bar if the search bar has focus... if(inputHandler.isPrefixActive()) { if(getFocusOwner() instanceof JTextComponent) { prefixFocusOwner = getFocusOwner(); getTextArea().requestFocus(); } else if(focusOnTextArea) { getTextArea().requestFocus(); } else { prefixFocusOwner = null; } } else { prefixFocusOwner = null; } break; case KeyEvent.KEY_PRESSED: if(keyEventInterceptor != null) keyEventInterceptor.keyPressed(evt); else { /* boolean */ focusOnTextArea = false; if(prefixFocusOwner != null) { if(prefixFocusOwner.isShowing()) { prefixFocusOwner.requestFocus(); focusOnTextArea = true; } prefixFocusOwner = null; } KeyEventTranslator.Key keyStroke = KeyEventTranslator .translateKeyEvent(evt); if(keyStroke != null) { if(Debug.DUMP_KEY_EVENTS && from != VIEW) { Log.log(Log.DEBUG,this, "Translated: " + keyStroke); } if(inputHandler.handleKey(keyStroke)) evt.consume(); } // we might have been closed as a result of // the above if(isClosed()) return; // this is a weird hack. // we don't want C+e a to insert 'a' in the // search bar if the search bar has focus... if(inputHandler.isPrefixActive()) { if(getFocusOwner() instanceof JTextComponent) { prefixFocusOwner = getFocusOwner(); getTextArea().requestFocus(); } else if(focusOnTextArea) { getTextArea().requestFocus(); } else { prefixFocusOwner = null; } } else { prefixFocusOwner = null; } } break; case KeyEvent.KEY_RELEASED: if(keyEventInterceptor != null) keyEventInterceptor.keyReleased(evt); break; } if(!evt.isConsumed()) super.processKeyEvent(evt); } //}}} //}}} //{{{ Buffers, edit panes, split panes //{{{ splitHorizontally() method /** * Splits the view horizontally. * @since jEdit 4.1pre2 */ public EditPane splitHorizontally() { return split(JSplitPane.VERTICAL_SPLIT); } //}}} //{{{ splitVertically() method /** * Splits the view vertically. * @since jEdit 4.1pre2 */ public EditPane splitVertically() { return split(JSplitPane.HORIZONTAL_SPLIT); } //}}} //{{{ split() method /** * Splits the view. * @since jEdit 4.1pre2 */ public EditPane split(int orientation) { PerspectiveManager.setPerspectiveDirty(true); editPane.saveCaretInfo(); EditPane oldEditPane = editPane; setEditPane(createEditPane(oldEditPane.getBuffer())); editPane.loadCaretInfo(); JComponent oldParent = (JComponent)oldEditPane.getParent(); final JSplitPane newSplitPane = new JSplitPane(orientation); newSplitPane.setOneTouchExpandable(true); newSplitPane.setBorder(null); newSplitPane.setMinimumSize(new Dimension(0,0)); int parentSize = (orientation == JSplitPane.VERTICAL_SPLIT ? oldEditPane.getHeight() : oldEditPane.getWidth()); final int dividerPosition = (int)((double)(parentSize - newSplitPane.getDividerSize()) * 0.5); newSplitPane.setDividerLocation(dividerPosition); if(oldParent instanceof JSplitPane) { JSplitPane oldSplitPane = (JSplitPane)oldParent; int dividerPos = oldSplitPane.getDividerLocation(); Component left = oldSplitPane.getLeftComponent(); if(left == oldEditPane) oldSplitPane.setLeftComponent(newSplitPane); else oldSplitPane.setRightComponent(newSplitPane); newSplitPane.setLeftComponent(oldEditPane); newSplitPane.setRightComponent(editPane); oldSplitPane.setDividerLocation(dividerPos); } else { this.splitPane = newSplitPane; newSplitPane.setLeftComponent(oldEditPane); newSplitPane.setRightComponent(editPane); oldParent.add(newSplitPane,0); oldParent.revalidate(); } SwingUtilities.invokeLater(new Runnable() { public void run() { newSplitPane.setDividerLocation(dividerPosition); } }); editPane.focusOnTextArea(); return editPane; } //}}} //{{{ unsplit() method /** * Unsplits the view. * @since jEdit 2.3pre2 */ public void unsplit() { if(splitPane != null) { PerspectiveManager.setPerspectiveDirty(true); EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { EditPane _editPane = editPanes[i]; if(editPane != _editPane) _editPane.close(); } JComponent parent = (JComponent)splitPane.getParent(); parent.remove(splitPane); parent.add(editPane,0); parent.revalidate(); splitPane = null; updateTitle(); editPane.focusOnTextArea(); } else getToolkit().beep(); } //}}} //{{{ unsplitCurrent() method /** * Removes the current split. * @since jEdit 2.3pre2 */ public void unsplitCurrent() { if(splitPane != null) { PerspectiveManager.setPerspectiveDirty(true); // find first split pane parenting current edit pane Component comp = editPane; while(!(comp instanceof JSplitPane)) { comp = comp.getParent(); } // get rid of any edit pane that is a child // of the current edit pane's parent splitter EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { EditPane _editPane = editPanes[i]; if(GUIUtilities.isAncestorOf(comp,_editPane) && _editPane != editPane) _editPane.close(); } JComponent parent = (JComponent)comp.getParent(); if(parent instanceof JSplitPane) { JSplitPane parentSplit = (JSplitPane)parent; int pos = parentSplit.getDividerLocation(); if(parentSplit.getLeftComponent() == comp) parentSplit.setLeftComponent(editPane); else parentSplit.setRightComponent(editPane); parentSplit.setDividerLocation(pos); } else { parent.remove(comp); parent.add(editPane,0); splitPane = null; } parent.revalidate(); updateTitle(); editPane.focusOnTextArea(); } else getToolkit().beep(); } //}}} //{{{ nextTextArea() method /** * Moves keyboard focus to the next text area. * @since jEdit 2.7pre4 */ public void nextTextArea() { EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { if(editPane == editPanes[i]) { if(i == editPanes.length - 1) editPanes[0].focusOnTextArea(); else editPanes[i+1].focusOnTextArea(); break; } } } //}}} //{{{ prevTextArea() method /** * Moves keyboard focus to the previous text area. * @since jEdit 2.7pre4 */ public void prevTextArea() { EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { if(editPane == editPanes[i]) { if(i == 0) editPanes[editPanes.length - 1].focusOnTextArea(); else editPanes[i-1].focusOnTextArea(); break; } } } //}}} //{{{ getSplitPane() method /** * Returns the top-level split pane, if any. * @since jEdit 2.3pre2 */ public JSplitPane getSplitPane() { return splitPane; } //}}} //{{{ getBuffer() method /** * Returns the current edit pane's buffer. */ public Buffer getBuffer() { if(editPane == null) return null; else return editPane.getBuffer(); } //}}} //{{{ setBuffer() method /** * Sets the current edit pane's buffer. */ public void setBuffer(Buffer buffer) { editPane.setBuffer(buffer); } //}}} //{{{ goToBuffer() method /** * If this buffer is open in one of the view's edit panes, sets focus * to that edit pane. Otherwise, opens the buffer in the currently * active edit pane. * @param buffer The buffer * @since jEdit 4.2pre1 */ public EditPane goToBuffer(Buffer buffer) { if(editPane.getBuffer() == buffer) { editPane.focusOnTextArea(); return editPane; } EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { EditPane ep = editPanes[i]; if(ep.getBuffer() == buffer /* ignore zero-height splits, etc */ && ep.getTextArea().getVisibleLines() > 1) { setEditPane(ep); ep.focusOnTextArea(); return ep; } } setBuffer(buffer); return editPane; } //}}} //{{{ getTextArea() method /** * Returns the current edit pane's text area. */ public JEditTextArea getTextArea() { if(editPane == null) return null; else return editPane.getTextArea(); } //}}} //{{{ getEditPane() method /** * Returns the current edit pane. * @since jEdit 2.5pre2 */ public EditPane getEditPane() { return editPane; } //}}} //{{{ getEditPanes() method /** * Returns all edit panes. * @since jEdit 2.5pre2 */ public EditPane[] getEditPanes() { if(splitPane == null) { EditPane[] ep = { editPane }; return ep; } else { Vector vec = new Vector(); getEditPanes(vec,splitPane); EditPane[] ep = new EditPane[vec.size()]; vec.copyInto(ep); return ep; } } //}}} //{{{ getViewConfig() method /** * @since jEdit 4.2pre1 */ public ViewConfig getViewConfig() { StringBuffer splitConfig = new StringBuffer(); if(splitPane != null) getSplitConfig(splitPane,splitConfig); else { splitConfig.append('"'); splitConfig.append(MiscUtilities.charsToEscapes( getBuffer().getPath())); splitConfig.append("\" buffer"); } ViewConfig config = new ViewConfig(); config.plainView = isPlainView(); config.splitConfig = splitConfig.toString(); config.x = getX(); config.y = getY(); config.width = getWidth(); config.height = getHeight(); config.extState = GUIUtilities.getExtendedState(this); config.top = dockableWindowManager.getTopDockingArea().getCurrent(); config.left = dockableWindowManager.getLeftDockingArea().getCurrent(); config.bottom = dockableWindowManager.getBottomDockingArea().getCurrent(); config.right = dockableWindowManager.getRightDockingArea().getCurrent(); config.topPos = dockableWindowManager.getTopDockingArea().getDimension(); config.leftPos = dockableWindowManager.getLeftDockingArea().getDimension(); config.bottomPos = dockableWindowManager.getBottomDockingArea().getDimension(); config.rightPos = dockableWindowManager.getRightDockingArea().getDimension(); return config; } //}}} //}}} //{{{ isClosed() method /** * Returns true if this view has been closed with * {@link jEdit#closeView(View)}. */ public boolean isClosed() { return closed; } //}}} //{{{ isPlainView() method /** * Returns true if this is an auxilliary view with no dockable windows. * @since jEdit 4.1pre2 */ public boolean isPlainView() { return plainView; } //}}} //{{{ getNext() method /** * Returns the next view in the list. */ public View getNext() { return next; } //}}} //{{{ getPrev() method /** * Returns the previous view in the list. */ public View getPrev() { return prev; } //}}} //{{{ handleMessage() method public void handleMessage(EBMessage msg) { if(msg instanceof PropertiesChanged) propertiesChanged(); else if(msg instanceof SearchSettingsChanged) { if(searchBar != null) searchBar.update(); } else if(msg instanceof BufferUpdate) handleBufferUpdate((BufferUpdate)msg); else if(msg instanceof EditPaneUpdate) handleEditPaneUpdate((EditPaneUpdate)msg); } //}}} //{{{ getMinimumSize() method public Dimension getMinimumSize() { return new Dimension(0,0); } //}}} //{{{ setWaitSocket() method /** * This socket is closed when the buffer is closed. */ public void setWaitSocket(Socket waitSocket) { this.waitSocket = waitSocket; } //}}} //{{{ toString() method public String toString() { return getClass().getName() + "[" + (jEdit.getActiveView() == this ? "active" : "inactive") + "]"; } //}}} //{{{ Package-private members View prev; View next; //{{{ View constructor View(Buffer buffer, ViewConfig config) { this.plainView = config.plainView; enableEvents(AWTEvent.KEY_EVENT_MASK); setIconImage(GUIUtilities.getEditorIcon()); dockableWindowManager = new DockableWindowManager(this,config); topToolBars = new JPanel(new VariableGridLayout( VariableGridLayout.FIXED_NUM_COLUMNS, 1)); bottomToolBars = new JPanel(new VariableGridLayout( VariableGridLayout.FIXED_NUM_COLUMNS, 1)); toolBarManager = new ToolBarManager(topToolBars, bottomToolBars); status = new StatusBar(this); inputHandler = new DefaultInputHandler(this,(DefaultInputHandler) jEdit.getInputHandler()); try { Component comp = restoreSplitConfig(buffer,config.splitConfig); dockableWindowManager.add(comp,0); } catch(IOException e) { // this should never throw an exception. throw new InternalError(); } getContentPane().add(BorderLayout.CENTER,dockableWindowManager); dockableWindowManager.init(); // tool bar and status bar gets added in propertiesChanged() // depending in the 'tool bar alternate layout' setting. propertiesChanged(); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); addWindowListener(new WindowHandler()); EditBus.addToBus(this); SearchDialog.preloadSearchDialog(this); } //}}} //{{{ close() method void close() { GUIUtilities.saveGeometry(this,plainView ? "plain-view" : "view"); closed = true; // save dockable window geometry, and close 'em dockableWindowManager.close(); EditBus.removeFromBus(this); dispose(); EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) editPanes[i].close(); // null some variables so that retaining references // to closed views won't hurt as much. toolBarManager = null; toolBar = null; searchBar = null; splitPane = null; inputHandler = null; recorder = null; getContentPane().removeAll(); // notify clients with -wait if(waitSocket != null) { try { waitSocket.getOutputStream().write('\0'); waitSocket.getOutputStream().flush(); waitSocket.getInputStream().close(); waitSocket.getOutputStream().close(); waitSocket.close(); } catch(IOException io) { //Log.log(Log.ERROR,this,io); } } } //}}} //{{{ updateTitle() method /** * Updates the title bar. */ void updateTitle() { Vector buffers = new Vector(); EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { Buffer buffer = editPanes[i].getBuffer(); if(buffers.indexOf(buffer) == -1) buffers.addElement(buffer); } StringBuffer title = new StringBuffer(jEdit.getProperty("view.title")); for(int i = 0; i < buffers.size(); i++) { if(i != 0) title.append(", "); Buffer buffer = (Buffer)buffers.elementAt(i); title.append((showFullPath && !buffer.isNewFile()) ? buffer.getPath() : buffer.getName()); if(buffer.isDirty()) title.append(jEdit.getProperty("view.title.dirty")); } setTitle(title.toString()); } //}}} //}}} //{{{ Private members //{{{ Instance variables private boolean closed; private DockableWindowManager dockableWindowManager; private JPanel topToolBars; private JPanel bottomToolBars; private ToolBarManager toolBarManager; private Box toolBar; private SearchBar searchBar; private ActionBar actionBar; private EditPane editPane; private JSplitPane splitPane; private StatusBar status; private KeyListener keyEventInterceptor; private InputHandler inputHandler; private Macros.Recorder recorder; private Component prefixFocusOwner; private int waitCount; private boolean showFullPath; private boolean plainView; private Socket waitSocket; //}}} //{{{ getEditPanes() method private void getEditPanes(Vector vec, Component comp) { if(comp instanceof EditPane) vec.addElement(comp); else if(comp instanceof JSplitPane) { JSplitPane split = (JSplitPane)comp; getEditPanes(vec,split.getLeftComponent()); getEditPanes(vec,split.getRightComponent()); } } //}}} //{{{ getSplitConfig() method /* * The split config is recorded in a simple RPN "language". */ private void getSplitConfig(JSplitPane splitPane, StringBuffer splitConfig) { Component right = splitPane.getRightComponent(); if(right instanceof JSplitPane) getSplitConfig((JSplitPane)right,splitConfig); else { splitConfig.append('"'); splitConfig.append(MiscUtilities.charsToEscapes( ((EditPane)right).getBuffer().getPath())); splitConfig.append("\" buffer"); } splitConfig.append(' '); Component left = splitPane.getLeftComponent(); if(left instanceof JSplitPane) getSplitConfig((JSplitPane)left,splitConfig); else { splitConfig.append('"'); splitConfig.append(MiscUtilities.charsToEscapes( ((EditPane)left).getBuffer().getPath())); splitConfig.append("\" buffer"); } splitConfig.append(' '); splitConfig.append(splitPane.getDividerLocation()); splitConfig.append(' '); splitConfig.append(splitPane.getOrientation() == JSplitPane.VERTICAL_SPLIT ? "vertical" : "horizontal"); } //}}} //{{{ restoreSplitConfig() method private Component restoreSplitConfig(Buffer buffer, String splitConfig) throws IOException // this is where checked exceptions piss me off. this method only uses // a StringReader which can never throw an exception... { if(buffer != null) return (editPane = createEditPane(buffer)); else if(splitConfig == null) return (editPane = createEditPane(jEdit.getFirstBuffer())); Buffer[] buffers = jEdit.getBuffers(); Stack stack = new Stack(); // we create a stream tokenizer for parsing a simple // stack-based language StreamTokenizer st = new StreamTokenizer(new StringReader( splitConfig)); st.whitespaceChars(0,' '); /* all printable ASCII characters */ st.wordChars('#','~'); st.commentChar('!'); st.quoteChar('"'); st.eolIsSignificant(false); loop: for(;;) { switch(st.nextToken()) { case StreamTokenizer.TT_EOF: break loop; case StreamTokenizer.TT_WORD: if(st.sval.equals("vertical") || st.sval.equals("horizontal")) { int orientation = (st.sval.equals("vertical") ? JSplitPane.VERTICAL_SPLIT : JSplitPane.HORIZONTAL_SPLIT); int divider = ((Integer)stack.pop()) .intValue(); stack.push(splitPane = new JSplitPane( orientation, (Component)stack.pop(), (Component)stack.pop())); splitPane.setOneTouchExpandable(true); splitPane.setBorder(null); splitPane.setMinimumSize( new Dimension(0,0)); splitPane.setDividerLocation(divider); } else if(st.sval.equals("buffer")) { Object obj = stack.pop(); if(obj instanceof Integer) { int index = ((Integer)obj).intValue(); if(index >= 0 && index < buffers.length) buffer = buffers[index]; } else if(obj instanceof String) { String path = (String)obj; buffer = jEdit.getBuffer(path); } if(buffer == null) buffer = jEdit.getFirstBuffer(); stack.push(editPane = createEditPane( buffer)); } break; case StreamTokenizer.TT_NUMBER: stack.push(new Integer((int)st.nval)); break; case '"': stack.push(st.sval); break; } } updateGutterBorders(); return (Component)stack.peek(); } //}}} //{{{ propertiesChanged() method /** * Reloads various settings from the properties. */ private void propertiesChanged() { setJMenuBar(GUIUtilities.loadMenuBar("view.mbar")); loadToolBars(); showFullPath = jEdit.getBooleanProperty("view.showFullPath"); updateTitle(); status.propertiesChanged(); removeToolBar(status); getContentPane().remove(status); if(jEdit.getBooleanProperty("view.toolbar.alternateLayout")) { getContentPane().add(BorderLayout.NORTH,topToolBars); getContentPane().add(BorderLayout.SOUTH,bottomToolBars); if(!plainView && jEdit.getBooleanProperty("view.status.visible")) addToolBar(BOTTOM_GROUP,STATUS_BAR_LAYER,status); } else { dockableWindowManager.add(topToolBars, DockableWindowManager.DockableLayout .TOP_TOOLBARS,0); dockableWindowManager.add(bottomToolBars, DockableWindowManager.DockableLayout .BOTTOM_TOOLBARS,0); if(!plainView && jEdit.getBooleanProperty("view.status.visible")) getContentPane().add(BorderLayout.SOUTH,status); } getRootPane().revalidate(); //SwingUtilities.updateComponentTreeUI(getRootPane()); } //}}} //{{{ loadToolBars() method private void loadToolBars() { if(jEdit.getBooleanProperty("view.showToolbar") && !plainView) { if(toolBar != null) toolBarManager.removeToolBar(toolBar); toolBar = GUIUtilities.loadToolBar("view.toolbar"); addToolBar(TOP_GROUP, SYSTEM_BAR_LAYER, toolBar); } else if(toolBar != null) { removeToolBar(toolBar); toolBar = null; } if(searchBar != null) removeToolBar(searchBar); if(jEdit.getBooleanProperty("view.showSearchbar") && !plainView) { if(searchBar == null) searchBar = new SearchBar(this,false); searchBar.propertiesChanged(); addToolBar(TOP_GROUP,SEARCH_BAR_LAYER,searchBar); } } //}}} //{{{ createEditPane() method private EditPane createEditPane(Buffer buffer) { EditPane editPane = new EditPane(this,buffer); JEditTextArea textArea = editPane.getTextArea(); textArea.addFocusListener(new FocusHandler()); textArea.addCaretListener(new CaretHandler()); textArea.addScrollListener(new ScrollHandler()); EditBus.send(new EditPaneUpdate(editPane,EditPaneUpdate.CREATED)); return editPane; } //}}} //{{{ setEditPane() method private void setEditPane(EditPane editPane) { this.editPane = editPane; status.updateCaretStatus(); status.updateBufferStatus(); status.updateMiscStatus(); // repaint the gutter so that the border color // reflects the focus state updateGutterBorders(); EditBus.send(new ViewUpdate(this,ViewUpdate.EDIT_PANE_CHANGED)); } //}}} //{{{ handleBufferUpdate() method private void handleBufferUpdate(BufferUpdate msg) { Buffer buffer = msg.getBuffer(); if(msg.getWhat() == BufferUpdate.DIRTY_CHANGED || msg.getWhat() == BufferUpdate.LOADED) { EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) { if(editPanes[i].getBuffer() == buffer) { updateTitle(); break; } } } } //}}} //{{{ handleEditPaneUpdate() method private void handleEditPaneUpdate(EditPaneUpdate msg) { EditPane editPane = msg.getEditPane(); if(editPane.getView() == this && msg.getWhat() == EditPaneUpdate.BUFFER_CHANGED && editPane.getBuffer().isLoaded()) { status.updateCaretStatus(); status.updateBufferStatus(); status.updateMiscStatus(); } } //}}} //{{{ updateGutterBorders() method /** * Updates the borders of all gutters in this view to reflect the * currently focused text area. * @since jEdit 2.6final */ private void updateGutterBorders() { EditPane[] editPanes = getEditPanes(); for(int i = 0; i < editPanes.length; i++) editPanes[i].getTextArea().getGutter().updateBorder(); } //}}} //{{{ _preprocessKeyEvent() method private KeyEvent _preprocessKeyEvent(KeyEvent evt) { if(isClosed()) return null; if(getFocusOwner() instanceof JComponent) { JComponent comp = (JComponent)getFocusOwner(); InputMap map = comp.getInputMap(); ActionMap am = comp.getActionMap(); if(map != null && am != null && comp.isEnabled()) { Object binding = map.get(KeyStroke.getKeyStrokeForEvent(evt)); if(binding != null && am.get(binding) != null) { return null; } } } if(getFocusOwner() instanceof JTextComponent) { // fix for the bug where key events in JTextComponents // inside views are also handled by the input handler if(evt.getID() == KeyEvent.KEY_PRESSED) { switch(evt.getKeyCode()) { case KeyEvent.VK_ENTER: case KeyEvent.VK_TAB: case KeyEvent.VK_BACK_SPACE: case KeyEvent.VK_SPACE: return null; } } } if(evt.isConsumed()) return null; return KeyEventWorkaround.processKeyEvent(evt); } //}}} //}}} //{{{ Inner classes //{{{ CaretHandler class class CaretHandler implements CaretListener { public void caretUpdate(CaretEvent evt) { if(evt.getSource() == getTextArea()) status.updateCaretStatus(); } } //}}} //{{{ FocusHandler class class FocusHandler extends FocusAdapter { public void focusGained(FocusEvent evt) { // walk up hierarchy, looking for an EditPane Component comp = (Component)evt.getSource(); while(!(comp instanceof EditPane)) { if(comp == null) return; comp = comp.getParent(); } if(comp != editPane) setEditPane((EditPane)comp); else updateGutterBorders(); } } //}}} //{{{ ScrollHandler class class ScrollHandler implements ScrollListener { public void scrolledVertically(JEditTextArea textArea) { if(getTextArea() == textArea) status.updateCaretStatus(); } public void scrolledHorizontally(JEditTextArea textArea) {} } //}}} //{{{ WindowHandler class class WindowHandler extends WindowAdapter { public void windowActivated(WindowEvent evt) { jEdit.setActiveView(View.this); // People have reported hangs with JDK 1.4; might be // caused by modal dialogs being displayed from // windowActivated() SwingUtilities.invokeLater(new Runnable() { public void run() { jEdit.checkBufferStatus(View.this); } }); } public void windowClosing(WindowEvent evt) { jEdit.closeView(View.this); } } //}}} //{{{ ViewConfig class public static class ViewConfig { public boolean plainView; public String splitConfig; public int x, y, width, height, extState; // dockables public String top, left, bottom, right; public int topPos, leftPos, bottomPos, rightPos; public ViewConfig() { } public ViewConfig(boolean plainView) { this.plainView = plainView; String prefix = (plainView ? "plain-view" : "view"); x = jEdit.getIntegerProperty(prefix + ".x",0); y = jEdit.getIntegerProperty(prefix + ".y",0); width = jEdit.getIntegerProperty(prefix + ".width",0); height = jEdit.getIntegerProperty(prefix + ".height",0); } public ViewConfig(boolean plainView, String splitConfig, int x, int y, int width, int height, int extState) { this.plainView = plainView; this.splitConfig = splitConfig; this.x = x; this.y = y; this.width = width; this.height = height; this.extState = extState; } } //}}} //}}} } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.