alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

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 View is jEdit's top-level frame window.

* * In a BeanShell script, you can obtain the current view instance from the * view variable.

* * The largest component it contains is an {@link EditPane} that in turn * contains a {@link org.gjt.sp.jedit.textarea.JEditTextArea} that displays a * {@link Buffer}. * A view can have more than one edit pane in a split window configuration. * A view also contains a menu bar, an optional toolbar and other window * decorations, as well as docked windows.

* * The View class performs two important operations * dealing with plugins: creating plugin menu items, and managing dockable * windows. * *

    *
  • When a view is being created, its initialization routine * iterates through the collection of loaded plugins and constructs the * Plugins menu using the properties as specified in the * {@link EditPlugin} class.
  • *
  • The view also creates and initializes a * {@link org.gjt.sp.jedit.gui.DockableWindowManager} * object. This object is * responsible for creating, closing and managing dockable windows.
  • *
* * This class does not have a public constructor. * Views can be opened and closed using methods in the 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/finally block, like this: *

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

 

new blog posts

 

Copyright 1998-2021 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.