/jEdit/tags/jedit-4-3-pre15/org/gjt/sp/jedit/EditPane.java
# · Java · 1377 lines · 939 code · 140 blank · 298 comment · 246 complexity · 5513febafd6e79cf1734d68199cc4ad3 MD5 · raw file
- /*
- * EditPane.java - Text area and buffer switcher
- * :tabSize=8:indentSize=8:noTabs=false:
- * :folding=explicit:collapseFolds=1:
- *
- * Copyright (C) 2000, 2005 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 java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.Dimension;
- import java.awt.FontMetrics;
- import java.awt.Graphics2D;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.util.HashMap;
- import java.util.Map;
- import javax.swing.JMenuItem;
- import javax.swing.JPanel;
- import javax.swing.JPopupMenu;
- import javax.swing.SwingUtilities;
- import org.gjt.sp.jedit.buffer.JEditBuffer;
- import org.gjt.sp.jedit.bufferset.BufferSet;
- import org.gjt.sp.jedit.bufferset.BufferSetListener;
- import org.gjt.sp.jedit.bufferset.BufferSetManager;
- import org.gjt.sp.jedit.gui.BufferSwitcher;
- import org.gjt.sp.jedit.gui.StatusBar;
- import org.gjt.sp.jedit.io.VFSManager;
- import org.gjt.sp.jedit.msg.BufferChanging;
- import org.gjt.sp.jedit.msg.BufferUpdate;
- import org.gjt.sp.jedit.msg.EditPaneUpdate;
- import org.gjt.sp.jedit.msg.PropertiesChanged;
- import org.gjt.sp.jedit.options.GlobalOptions;
- import org.gjt.sp.jedit.syntax.SyntaxStyle;
- import org.gjt.sp.jedit.textarea.AntiAlias;
- import org.gjt.sp.jedit.textarea.Gutter;
- import org.gjt.sp.jedit.textarea.JEditTextArea;
- import org.gjt.sp.jedit.textarea.MouseHandler;
- import org.gjt.sp.jedit.textarea.Selection;
- import org.gjt.sp.jedit.textarea.StatusListener;
- import org.gjt.sp.jedit.textarea.TextArea;
- import org.gjt.sp.jedit.textarea.TextAreaExtension;
- import org.gjt.sp.jedit.textarea.TextAreaPainter;
- import org.gjt.sp.jedit.textarea.TextAreaTransferHandler;
- import org.gjt.sp.util.SyntaxUtilities;
- //}}}
- /**
- * A panel containing a text area.<p>
- *
- * In a BeanShell script, you can obtain the current edit pane from the
- * <code>editPane</code> variable.<p>
- *
- *
- * Each View can have multiple editPanes, one is active at a time.
- * Each EditPane has a single JEditTextArea, and is operating on single buffer.
- * The EditPane also can switch buffers.
- *
- * This is the "controller" between a JEditTextArea (view) and a buffer (model).
- *
- * This class does not have a public constructor.
- * Edit panes can be created and destroyed using methods in the
- * {@link View} class.<p>
- *
- *
- * @see View#splitHorizontally()
- * @see View#splitVertically()
- * @see View#unsplitCurrent()
- * @see View#unsplit()
- * @see View#getEditPane()
- * @see View#getEditPanes()
- *
- * @author Slava Pestov
- * @version $Id: EditPane.java 13213 2008-08-06 13:56:09Z kpouer $
- */
- public class EditPane extends JPanel implements EBComponent, BufferSetListener
- {
- //{{{ getView() method
- /**
- * Returns the view containing this edit pane.
- * @return the view that contains this EditPane
- * @since jEdit 2.5pre2
- */
- public View getView()
- {
- return view;
- } //}}}
- //{{{ getBuffer() method
- /**
- * Returns the current buffer.
- * @return the current buffer
- * @since jEdit 2.5pre2
- */
- public Buffer getBuffer()
- {
- return buffer;
- } //}}}
- //{{{ setBuffer() methods
- /**
- * Sets the current buffer.
- * @param buffer The buffer to edit.
- * @since jEdit 2.5pre2
- */
- public void setBuffer(Buffer buffer)
- {
- setBuffer(buffer, true);
- }
- /**
- * Sets the current buffer.
- * @param buffer The buffer to edit.
- * @param requestFocus true if the textarea should request focus, false otherwise
- * @since jEdit 4.3pre6
- */
- public void setBuffer(final Buffer buffer, boolean requestFocus)
- {
- if(buffer == null)
- throw new NullPointerException();
- if(this.buffer == buffer)
- return;
- if (bufferSet.indexOf(buffer) == -1)
- {
- jEdit.getBufferSetManager().addBuffer(this, buffer);
- }
- //if(buffer.insideCompoundEdit())
- // buffer.endCompoundEdit();
- EditBus.send(new BufferChanging(this, buffer));
- if (bufferSet.indexOf(this.buffer) != -1)
- {
- // when closing the last buffer of a bufferSet, the current buffer will still be the closed
- // buffer until a new empty buffer is created.
- // So if the current buffer is not anymore in the bufferSet, do not set the recentBuffer
- recentBuffer = this.buffer;
- }
- if(recentBuffer != null)
- saveCaretInfo();
- this.buffer = buffer;
- textArea.setBuffer(buffer);
- if(!init)
- {
- view.updateTitle();
- if(bufferSwitcher != null)
- {
- if(bufferSwitcher.getSelectedItem() != buffer)
- bufferSwitcher.setSelectedItem(buffer);
- bufferSwitcher.setToolTipText(buffer.getPath());
- }
- EditBus.send(new EditPaneUpdate(this,EditPaneUpdate
- .BUFFER_CHANGED));
- }
- if (requestFocus)
- {
- SwingUtilities.invokeLater(new Runnable()
- {
- public void run()
- {
- // only do this if we are the current edit pane
- if(view.getEditPane() == EditPane.this
- && (bufferSwitcher == null
- || !bufferSwitcher.isPopupVisible()))
- {
- textArea.requestFocus();
- }
- }
- });
- }
- // Only do this after all I/O requests are complete
- Runnable runnable = new Runnable()
- {
- public void run()
- {
- // avoid a race condition
- // see bug #834338
- if(buffer == getBuffer())
- loadCaretInfo();
- }
- };
- if(buffer.isPerformingIO())
- VFSManager.runInAWTThread(runnable);
- else
- runnable.run();
- } //}}}
- //{{{ prevBuffer() method
- /**
- * Selects the previous buffer.
- * @since jEdit 2.7pre2
- */
- public void prevBuffer()
- {
- Buffer buffer = bufferSet.getPreviousBuffer(bufferSet.indexOf(this.buffer));
- setBuffer(buffer);
- } //}}}
- //{{{ nextBuffer() method
- /**
- * Selects the next buffer.
- * @since jEdit 2.7pre2
- */
- public void nextBuffer()
- {
- Buffer buffer = bufferSet.getNextBuffer(bufferSet.indexOf(this.buffer));
- setBuffer(buffer);
- } //}}}
- //{{{ recentBuffer() method
- /**
- * Selects the most recently edited buffer.
- * @since jEdit 2.7pre2
- */
- public void recentBuffer()
- {
- if(recentBuffer != null)
- setBuffer(recentBuffer);
- else
- getToolkit().beep();
- } //}}}
- //{{{ focusOnTextArea() method
- /**
- * Sets the focus onto the text area.
- * @since jEdit 2.5pre2
- */
- public void focusOnTextArea()
- {
- SwingUtilities.invokeLater(new Runnable()
- {
- public void run()
- {
- textArea.requestFocus();
- }
- });
- } //}}}
- //{{{ getTextArea() method
- /**
- * Returns the view's text area.
- * @return the text area of the edit pane
- * @since jEdit 2.5pre2
- */
- public JEditTextArea getTextArea()
- {
- return textArea;
- } //}}}
- //{{{ getBufferSwitcher() method
- /**
- * Returns the buffer switcher combo box instance.
- * @return the buffer switcher (it can be null)
- * @since jEdit 4.1pre8
- */
- public BufferSwitcher getBufferSwitcher()
- {
- return bufferSwitcher;
- } //}}}
- //{{{ showBufferSwitcher() method
- /**
- * Shows the buffer switcher combo box.
- * @since jEdit 4.1pre8
- */
- public void showBufferSwitcher()
- {
- if(bufferSwitcher == null)
- getToolkit().beep();
- else
- {
- bufferSwitcher.requestFocus();
- bufferSwitcher.showPopup();
- }
- } //}}}
- //{{{ saveCaretInfo() method
- /**
- * Saves the caret information to the current buffer.
- * @since jEdit 2.5pre2
- */
- public void saveCaretInfo()
- {
- if(!buffer.isLoaded())
- return;
- buffer.setIntegerProperty(Buffer.CARET,
- textArea.getCaretPosition());
- // save a map of buffer.getPath() -> CaretInfo, this is necessary for
- // when the same buffer is open in more than one EditPane and the user
- // is switching between buffers. We want to keep the caret in the
- // right position in each EditPane, which won't be the case if we
- // just use the buffer caret property.
- Map<String, CaretInfo> carets = (Map<String, CaretInfo>)getClientProperty(CARETS);
- if (carets == null)
- {
- carets = new HashMap<String, CaretInfo>();
- putClientProperty(CARETS, carets);
- }
- CaretInfo caretInfo = carets.get(buffer.getPath());
- if (caretInfo == null)
- {
- caretInfo = new CaretInfo();
- carets.put(buffer.getPath(), caretInfo);
- }
- caretInfo.caret = textArea.getCaretPosition();
- Selection[] selection = textArea.getSelection();
- for(int i = 0; i < selection.length; i++)
- selection[i] = (Selection)selection[i].clone();
- buffer.setProperty(Buffer.SELECTION,selection);
- caretInfo.selection = selection;
- caretInfo.rectangularSelection = textArea.isRectangularSelectionEnabled();
- caretInfo.multipleSelection = textArea.isMultipleSelectionEnabled();
- buffer.setIntegerProperty(Buffer.SCROLL_VERT,
- textArea.getFirstPhysicalLine());
- caretInfo.scrollVert = textArea.getFirstPhysicalLine();
- buffer.setIntegerProperty(Buffer.SCROLL_HORIZ,
- textArea.getHorizontalOffset());
- caretInfo.scrollHoriz = textArea.getHorizontalOffset();
- if (!buffer.isUntitled())
- {
- BufferHistory.setEntry(buffer.getPath(), textArea.getCaretPosition(),
- (Selection[])buffer.getProperty(Buffer.SELECTION),
- buffer.getStringProperty(JEditBuffer.ENCODING),
- buffer.getMode().getName());
- }
- } //}}}
- //{{{ loadCaretInfo() method
- /**
- * Loads the caret and selection information from this EditPane, fall
- * back to the information from the current buffer if none is already
- * in this EditPane.
- * @since jEdit 2.5pre2
- */
- public void loadCaretInfo()
- {
- // get our internal map of buffer -> CaretInfo since there might
- // be current info already
- Map<String, CaretInfo> carets = (Map<String, CaretInfo>) getClientProperty(CARETS);
- if (carets == null)
- {
- carets = new HashMap<String, CaretInfo>();
- putClientProperty(CARETS, carets);
- }
- CaretInfo caretInfo = carets.get(buffer.getPath());
- if (caretInfo == null)
- {
- caretInfo = new CaretInfo();
- }
- // set the position of the caret itself.
- // Caret position could be stored in the internal map already,
- // if so, use that one first. Otherwise, fall back to any
- // previously saved caret position that was stored in the
- // buffer properties.
- int caret = caretInfo.caret;
- if (caret == -1 || buffer.getBooleanProperty(Buffer.CARET_POSITIONED))
- {
- Integer i = (Integer) buffer.getProperty(Buffer.CARET);
- caret = i == null ? -1 : i;
- }
- buffer.unsetProperty(Buffer.CARET_POSITIONED);
- if(caret != -1)
- textArea.setCaretPosition(Math.min(caret,
- buffer.getLength()));
- // set any selections
- Selection[] selection = caretInfo.selection;
- if ( selection == null ) {
- selection = (Selection[])buffer.getProperty(Buffer.SELECTION);
- }
- if(selection != null)
- {
- for(int i = 0; i < selection.length; i++)
- {
- Selection s = selection[i];
- int max = buffer.getLength();
- if(s.getStart() > max || s.getEnd() > max)
- selection[i] = null;
- }
- }
- textArea.setSelection(selection);
- textArea.setRectangularSelectionEnabled(caretInfo.rectangularSelection);
- textArea.setMultipleSelectionEnabled(caretInfo.multipleSelection);
- // set firstLine value
- int firstLine = caretInfo.scrollVert;
- if ( firstLine == -1 )
- {
- Integer i = (Integer) buffer.getProperty(Buffer.SCROLL_VERT);
- firstLine = i == null ? -1 : i;
- }
- if(firstLine != -1)
- textArea.setFirstPhysicalLine(firstLine);
- // set horizontal offset
- int horizontalOffset = caretInfo.scrollHoriz;
- if (horizontalOffset == -1)
- {
- Integer i = (Integer) buffer.getProperty(Buffer.SCROLL_HORIZ);
- horizontalOffset = i == null ? -1 : i;
- }
- if(horizontalOffset != -1)
- textArea.setHorizontalOffset(horizontalOffset);
- /* Silly bug workaround #8694. If you look at the above code,
- * note that we restore the saved caret position first, then
- * scroll to the saved location. However, the caret changing
- * can itself result in scrolling to a different location than
- * what was saved; and since moveCaretPosition() calls
- * updateBracketHighlight(), the bracket highlight's out of
- * bounds calculation will rely on a different set of physical
- * first/last lines than what we will end up with eventually.
- * Instead of confusing the user with status messages that
- * appear at random when switching buffers, we simply hide the
- * message altogether. */
- view.getStatus().setMessage(null);
- } //}}}
- //{{{ bufferRenamed() method
- /**
- * This method should be called by the Buffer when the path is changing.
- * @param oldPath the old path of the buffer
- * @param newPath the new path of the buffer
- */
- void bufferRenamed(String oldPath, String newPath)
- {
- Map<String, CaretInfo> carets = (Map<String, CaretInfo>) getClientProperty(CARETS);
- if (carets == null)
- return;
- CaretInfo caretInfo = carets.remove(oldPath);
- if (caretInfo != null)
- carets.put(newPath, caretInfo);
- } //}}}
- //{{{ CaretInfo class
- /**
- * Need to track this info for each buffer that this EditPane might edit
- * since a buffer may be open in more than one EditPane at a time. That
- * means we need to track this info at the EditPane level rather than
- * the buffer level.
- */
- private static class CaretInfo
- {
- public int caret = -1;
- public Selection[] selection;
- public int scrollVert = -1;
- public int scrollHoriz = -1;
- public boolean rectangularSelection;
- public boolean multipleSelection;
- } //}}}
- //{{{ goToNextMarker() method
- /**
- * Moves the caret to the next marker.
- * @since jEdit 4.3pre3
- */
- public void goToNextMarker(boolean select)
- {
- java.util.List<Marker> markers = buffer.getMarkers();
- if(markers.isEmpty())
- {
- getToolkit().beep();
- return;
- }
- Marker marker = null;
- int caret = textArea.getCaretPosition();
- for(int i = 0; i < markers.size(); i++)
- {
- Marker _marker = markers.get(i);
- if(_marker.getPosition() > caret)
- {
- marker = _marker;
- break;
- }
- }
- // the markers list is not empty at this point
- if(marker == null)
- marker = markers.get(0);
- if(select)
- textArea.extendSelection(caret,marker.getPosition());
- else if(!textArea.isMultipleSelectionEnabled())
- textArea.selectNone();
- textArea.moveCaretPosition(marker.getPosition());
- } //}}}
- //{{{ goToPrevMarker() method
- /**
- * Moves the caret to the previous marker.
- * @since jEdit 2.7pre2
- */
- public void goToPrevMarker(boolean select)
- {
- java.util.List<Marker> markers = buffer.getMarkers();
- if(markers.isEmpty())
- {
- getToolkit().beep();
- return;
- }
- int caret = textArea.getCaretPosition();
- Marker marker = null;
- for(int i = markers.size() - 1; i >= 0; i--)
- {
- Marker _marker = markers.get(i);
- if(_marker.getPosition() < caret)
- {
- marker = _marker;
- break;
- }
- }
- if(marker == null)
- marker = markers.get(markers.size() - 1);
- if(select)
- textArea.extendSelection(caret,marker.getPosition());
- else if(!textArea.isMultipleSelectionEnabled())
- textArea.selectNone();
- textArea.moveCaretPosition(marker.getPosition());
- } //}}}
- //{{{ goToMarker() method
- /**
- * Moves the caret to the marker with the specified shortcut.
- * @param shortcut The shortcut
- * @param select True if the selection should be extended,
- * false otherwise
- * @since jEdit 3.2pre2
- */
- public void goToMarker(char shortcut, boolean select)
- {
- Marker marker = buffer.getMarker(shortcut);
- if(marker == null)
- {
- getToolkit().beep();
- return;
- }
- int pos = marker.getPosition();
- if(select)
- textArea.extendSelection(textArea.getCaretPosition(),pos);
- else if(!textArea.isMultipleSelectionEnabled())
- textArea.selectNone();
- textArea.moveCaretPosition(pos);
- } //}}}
- //{{{ addMarker() method
- /**
- * Adds a marker at the caret position.
- * @since jEdit 3.2pre1
- */
- public void addMarker()
- {
- int caretLine = textArea.getCaretLine();
- // always add markers on selected lines
- Selection[] selection = textArea.getSelection();
- for(int i = 0; i < selection.length; i++)
- {
- Selection s = selection[i];
- if(s.getStartLine() != s.getEndLine())
- {
- if(s.getStartLine() != caretLine)
- buffer.addMarker('\0',s.getStart());
- }
- if(s.getEndLine() != caretLine)
- buffer.addMarker('\0',s.getEnd());
- }
- // toggle marker on caret line
- buffer.addOrRemoveMarker('\0',textArea.getCaretPosition());
- } //}}}
- //{{{ swapMarkerAndCaret() method
- /**
- * Moves the caret to the marker with the specified shortcut,
- * then sets the marker position to the former caret position.
- * @param shortcut The shortcut
- * @since jEdit 3.2pre2
- */
- public void swapMarkerAndCaret(char shortcut)
- {
- Marker marker = buffer.getMarker(shortcut);
- if(marker == null)
- {
- getToolkit().beep();
- return;
- }
- int caret = textArea.getCaretPosition();
- textArea.setCaretPosition(marker.getPosition());
- buffer.addMarker(shortcut,caret);
- } //}}}
- //{{{ handleMessage() method
- public void handleMessage(EBMessage msg)
- {
- if(msg instanceof PropertiesChanged)
- {
- propertiesChanged();
- loadBufferSwitcher();
- }
- else if(msg instanceof BufferUpdate)
- handleBufferUpdate((BufferUpdate)msg);
- } //}}}
- //{{{ getMinimumSize() method
- /**
- * Returns 0,0 for split pane compatibility.
- */
- @Override
- public final Dimension getMinimumSize()
- {
- return new Dimension(0,0);
- } //}}}
- //{{{ getBufferSet() method
- public BufferSet getBufferSet()
- {
- return bufferSet;
- } //}}}
- //{{{ setBufferSet() methods
- /**
- * Set the default bufferSet.
- * from the editpane.bufferset.default property
- *
- * @since jEdit 4.3pre15
- */
- public void setBufferSet()
- {
- BufferSet.Scope mode = BufferSet.Scope.fromString(jEdit.getProperty("editpane.bufferset.default"));
- switch (mode)
- {
- case view:
- setBufferSet(jEdit.getBufferSetManager().getViewBufferSet(view));
- break;
- case editpane:
- setBufferSet(jEdit.getBufferSetManager().getEditPaneBufferSet(this));
- break;
- case global:
- setBufferSet(jEdit.getBufferSetManager().getGlobalBufferSet());
- break;
- }
- }
- /**
- * Set the new bufferSet of the EditPane.
- * @param bufferSet the new bufferSet
- * @since jEdit 4.3pre15
- */
- public void setBufferSet(BufferSet bufferSet)
- {
- if (this.bufferSet != bufferSet)
- {
- BufferSetManager bufferSetManager = jEdit.getBufferSetManager();
- String action = jEdit.getProperty("editpane.bufferset.new");
- BufferSetManager.NewBufferSetAction bufferSetAction = BufferSetManager.NewBufferSetAction.fromString(action);
- switch (bufferSetAction)
- {
- case copy:
- if (this.bufferSet == null)
- bufferSetManager.addAllBuffers(bufferSet);
- else
- bufferSetManager.mergeBufferSet(bufferSet, this.bufferSet);
- break;
- case empty:
- break;
- case currentbuffer:
- View activeView = jEdit.getActiveView();
- if (activeView == null)
- break;
- EditPane editPane = activeView.getEditPane();
- Buffer buffer = editPane.getBuffer();
- bufferSetManager.addBuffer(bufferSet,buffer);
- break;
- }
- if (this.bufferSet != null)
- {
- this.bufferSet.removeBufferSetListener(this);
- }
- if (buffer != null)
- bufferSetManager.addBuffer(bufferSet, buffer);
- if (bufferSet.size() == 0)
- {
- int untitledCount = jEdit.getNextUntitledBufferId();
- Buffer newEmptyBuffer = jEdit.openTemporary(jEdit.getActiveView(), null,
- "Untitled-" + untitledCount,true, null);
- jEdit.commitTemporary(newEmptyBuffer);
- bufferSetManager.addBuffer(bufferSet, newEmptyBuffer);
- }
- this.bufferSet = bufferSet;
- bufferSet.addBufferSetListener(this);
- if (bufferSwitcher != null)
- {
- bufferSwitcher.updateBufferList();
- }
- EditBus.send(new EditPaneUpdate(this, EditPaneUpdate.BUFFERSET_CHANGED));
- if (bufferSet.indexOf(recentBuffer) == -1)
- {
- // the recent buffer is not in the bufferSet
- recentBuffer = null;
- }
- if (bufferSet.size() != 0 && bufferSet.indexOf(buffer) == -1)
- {
- // the current buffer is not contained in the bufferSet, we must change the current buffer
- if (recentBuffer != null)
- setBuffer(recentBuffer);
- else
- {
- setBuffer(bufferSet.getBuffer(0));
- }
- }
- PerspectiveManager.setPerspectiveDirty(true);
- }
- } //}}}
- //{{{ bufferAdded() method
- /**
- * A buffer was added in the bufferSet.
- * @param buffer the added buffer
- * @param index the position where it was added
- * @since jEdit 4.3pre15
- */
- public void bufferAdded(Buffer buffer, int index)
- {
- if (bufferSwitcher != null)
- bufferSwitcher.updateBufferList();
- if (bufferSet.indexOf(this.buffer) == -1)
- {
- // it happens when having 1 untitled buffer if I open a file. The untitled buffer
- // is closed but the new buffer is not yet opened
- setBuffer(buffer);
- }
- } //}}}
- //{{{ bufferRemoved() method
- /**
- * A buffer was removed from the bufferSet.
- * @param buffer the removed buffer
- * @param index the position where it was before being removed
- * @since jEdit 4.3pre15
- */
- public void bufferRemoved(Buffer buffer, int index)
- {
- if (buffer.isUntitled())
- {
- // the buffer was a new file so I do not need to keep it's informations
- Map<String, CaretInfo> carets = (Map<String, CaretInfo>) getClientProperty(CARETS);
- if (carets != null)
- carets.remove(buffer.getPath());
- }
- if (buffer == this.buffer)
- {
- // The closed buffer is the current buffer
- Buffer newBuffer = recentBuffer != null ?
- recentBuffer : bufferSet.getPreviousBuffer(index);
- if(newBuffer != null && !newBuffer.isClosed())
- {
- setBuffer(newBuffer);
- if (bufferSet.size() > 1)
- {
- recentBuffer = bufferSet.getPreviousBuffer(index -1);
- }
- }
- else if(bufferSet.size() != 0)
- {
- setBuffer(bufferSet.getBuffer(0));
- recentBuffer = null;
- }
- }
- if(buffer == recentBuffer)
- recentBuffer = null;
- if (bufferSwitcher != null)
- bufferSwitcher.updateBufferList();
- } //}}}
- //{{{ bufferMoved() method
- /**
- * A buffer was moved in the BufferSet.
- * @param buffer the moved buffer
- * @param oldIndex the position it was before
- * @param newIndex the new position
- * @since jEdit 4.3pre15
- */
- public void bufferMoved(Buffer buffer, int oldIndex, int newIndex)
- {
- if (bufferSwitcher != null)
- bufferSwitcher.updateBufferList();
- } //}}}
- //{{{ bufferCleared() method
- /**
- * The bufferSet was cleared
- * @since jEdit 4.3pre15
- */
- public void bufferCleared()
- {
- int untitledCount = jEdit.getNextUntitledBufferId();
- Buffer newEmptyBuffer = jEdit.openTemporary(jEdit.getActiveView(), null,
- "Untitled-" + untitledCount,true, null);
- jEdit.commitTemporary(newEmptyBuffer);
- jEdit.getBufferSetManager().addBuffer(bufferSet, newEmptyBuffer);
- setBuffer(newEmptyBuffer);
- // if (bufferSwitcher != null)
- // bufferSwitcher.updateBufferList();
- } //}}}
- //{{{ toString() method
- @Override
- public String toString()
- {
- return getClass().getName() + '['
- + (view.getEditPane() == this
- ? "active" : "inactive")
- + ',' + bufferSet.getScope() + ']';
- } //}}}
- //{{{ Package-private members
- //{{{ EditPane constructor
- EditPane(View view, Buffer buffer)
- {
- super(new BorderLayout());
- init = true;
- this.view = view;
- textArea = new JEditTextArea(view);
- paneMap.put(textArea, this);
- textArea.getPainter().setAntiAlias(new AntiAlias(jEdit.getProperty("view.antiAlias")));
- textArea.setMouseHandler(new MouseHandler(textArea));
- textArea.setTransferHandler(new TextAreaTransferHandler());
- markerHighlight = new MarkerHighlight();
- textArea.getGutter().addExtension(markerHighlight);
- textArea.addStatusListener(new StatusHandler());
- add(BorderLayout.CENTER,textArea);
- propertiesChanged();
- this.buffer = buffer;
- setBufferSet();
- this.buffer = null;
- if(buffer == null)
- {
- Buffer b = bufferSet.getBuffer(0);
- if (b == null)
- setBuffer(jEdit.getFirstBuffer());
- else
- setBuffer(b);
- }
- else
- setBuffer(buffer);
- loadBufferSwitcher();
- init = false;
- EditBus.addToBus(this);
- } //}}}
- //{{{ close() method
- void close()
- {
- paneMap.remove(textArea);
- saveCaretInfo();
- EditBus.send(new EditPaneUpdate(this,EditPaneUpdate.DESTROYED));
- EditBus.removeFromBus(this);
- textArea.dispose();
- } //}}}
- public static EditPane get(TextArea ta)
- {
- return paneMap.get(ta);
- }
-
- //}}}
- //{{{ Private members
- //{{{ Instance variables
- private boolean init;
- /** The View where the edit pane is. */
- private final View view;
- private static final Map<TextArea, EditPane> paneMap = new HashMap<TextArea, EditPane>();
- private BufferSet bufferSet;
- /** The current buffer. */
- private Buffer buffer;
- private Buffer recentBuffer;
- private BufferSwitcher bufferSwitcher;
- /** The textArea inside the edit pane. */
- private final JEditTextArea textArea;
- private final MarkerHighlight markerHighlight;
- private static final String CARETS = "Buffer->caret";
- //}}}
- //{{{ propertiesChanged() method
- private void propertiesChanged()
- {
- TextAreaPainter painter = textArea.getPainter();
- initPainter(painter);
- Gutter gutter = textArea.getGutter();
- gutter.setExpanded(jEdit.getBooleanProperty(
- "view.gutter.lineNumbers"));
- int interval = jEdit.getIntegerProperty(
- "view.gutter.highlightInterval",5);
- gutter.setHighlightInterval(interval);
- gutter.setCurrentLineHighlightEnabled(jEdit.getBooleanProperty(
- "view.gutter.highlightCurrentLine"));
- gutter.setStructureHighlightEnabled(jEdit.getBooleanProperty(
- "view.gutter.structureHighlight"));
- gutter.setStructureHighlightColor(
- jEdit.getColorProperty("view.gutter.structureHighlightColor"));
- gutter.setBackground(
- jEdit.getColorProperty("view.gutter.bgColor"));
- gutter.setForeground(
- jEdit.getColorProperty("view.gutter.fgColor"));
- gutter.setHighlightedForeground(
- jEdit.getColorProperty("view.gutter.highlightColor"));
- gutter.setFoldColor(
- jEdit.getColorProperty("view.gutter.foldColor"));
- markerHighlight.setMarkerHighlightColor(
- jEdit.getColorProperty("view.gutter.markerColor"));
- markerHighlight.setMarkerHighlightEnabled(jEdit.getBooleanProperty(
- "view.gutter.markerHighlight"));
- gutter.setCurrentLineForeground(
- jEdit.getColorProperty("view.gutter.currentLineColor"));
- String alignment = jEdit.getProperty(
- "view.gutter.numberAlignment");
- if ("right".equals(alignment))
- {
- gutter.setLineNumberAlignment(Gutter.RIGHT);
- }
- else if ("center".equals(alignment))
- {
- gutter.setLineNumberAlignment(Gutter.CENTER);
- }
- else // left == default case
- {
- gutter.setLineNumberAlignment(Gutter.LEFT);
- }
- gutter.setFont(jEdit.getFontProperty("view.gutter.font"));
- int width = jEdit.getIntegerProperty(
- "view.gutter.borderWidth",3);
- gutter.setBorder(width,
- jEdit.getColorProperty("view.gutter.focusBorderColor"),
- jEdit.getColorProperty("view.gutter.noFocusBorderColor"),
- textArea.getPainter().getBackground());
- textArea.setCaretBlinkEnabled(jEdit.getBooleanProperty(
- "view.caretBlink"));
- textArea.setElectricScroll(jEdit.getIntegerProperty(
- "view.electricBorders",0));
- // Set up the right-click popup menu
- JPopupMenu popup = GUIUtilities.loadPopupMenu("view.context", getTextArea(), null);
-
- JMenuItem customize = new JMenuItem(jEdit.getProperty(
- "view.context.customize"));
- customize.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent evt)
- {
- new GlobalOptions(view,"context");
- }
- });
- popup.addSeparator();
- popup.add(customize);
- textArea.setRightClickPopup(popup);
- // use old property name for backwards compatibility
- textArea.setQuickCopyEnabled(jEdit.getBooleanProperty(
- "view.middleMousePaste"));
- textArea.setDragEnabled(jEdit.getBooleanProperty(
- "view.dragAndDrop"));
- textArea.setJoinNonWordChars(jEdit.getBooleanProperty(
- "view.joinNonWordChars"));
- textArea.setCtrlForRectangularSelection(jEdit.getBooleanProperty(
- "view.ctrlForRectangularSelection"));
- textArea.propertiesChanged();
- if (bufferSwitcher != null) {
- bufferSwitcher.setMaximumRowCount(jEdit.getIntegerProperty(
- "bufferSwitcher.maxRowCount",10));
- }
- } //}}}
- //{{{ initPainter() method
- /**
- * Init the painter of a textarea.
- *
- * @param painter the painter of a textarea
- * @since jEdit 4.3pre12
- */
- public static void initPainter(TextAreaPainter painter)
- {
- painter.setFont(jEdit.getFontProperty("view.font"));
- painter.setStructureHighlightEnabled(jEdit.getBooleanProperty(
- "view.structureHighlight"));
- painter.setStructureHighlightColor(
- jEdit.getColorProperty("view.structureHighlightColor"));
- painter.setEOLMarkersPainted(jEdit.getBooleanProperty(
- "view.eolMarkers"));
- painter.setEOLMarkerColor(
- jEdit.getColorProperty("view.eolMarkerColor"));
- painter.setWrapGuidePainted(jEdit.getBooleanProperty(
- "view.wrapGuide"));
- painter.setWrapGuideColor(
- jEdit.getColorProperty("view.wrapGuideColor"));
- painter.setCaretColor(
- jEdit.getColorProperty("view.caretColor"));
- painter.setSelectionColor(
- jEdit.getColorProperty("view.selectionColor"));
- painter.setMultipleSelectionColor(
- jEdit.getColorProperty("view.multipleSelectionColor"));
- painter.setBackground(
- jEdit.getColorProperty("view.bgColor"));
- painter.setForeground(
- jEdit.getColorProperty("view.fgColor"));
- painter.setBlockCaretEnabled(jEdit.getBooleanProperty(
- "view.blockCaret"));
- painter.setThickCaretEnabled(jEdit.getBooleanProperty(
- "view.thickCaret"));
- painter.setLineHighlightEnabled(jEdit.getBooleanProperty(
- "view.lineHighlight"));
- painter.setLineHighlightColor(
- jEdit.getColorProperty("view.lineHighlightColor"));
- painter.setAntiAlias(new AntiAlias(jEdit.getProperty("view.antiAlias")));
- painter.setFractionalFontMetricsEnabled(jEdit.getBooleanProperty(
- "view.fracFontMetrics"));
- String defaultFont = jEdit.getProperty("view.font");
- int defaultFontSize = jEdit.getIntegerProperty("view.fontsize",12);
- painter.setStyles(SyntaxUtilities.loadStyles(defaultFont,defaultFontSize));
- SyntaxStyle[] foldLineStyle = new SyntaxStyle[4];
- for(int i = 0; i <= 3; i++)
- {
- foldLineStyle[i] = GUIUtilities.parseStyle(
- jEdit.getProperty("view.style.foldLine." + i),
- defaultFont,defaultFontSize);
- }
- painter.setFoldLineStyle(foldLineStyle);
- } //}}}
- //{{{ loadBufferSwitcher() method
- private void loadBufferSwitcher()
- {
- if(jEdit.getBooleanProperty("view.showBufferSwitcher"))
- {
- if(bufferSwitcher == null)
- {
- bufferSwitcher = new BufferSwitcher(this);
- add(BorderLayout.NORTH,bufferSwitcher);
- bufferSwitcher.updateBufferList();
- revalidate();
- }
- }
- else if(bufferSwitcher != null)
- {
- remove(bufferSwitcher);
- revalidate();
- bufferSwitcher = null;
- }
- } //}}}
- //{{{ handleBufferUpdate() method
- private void handleBufferUpdate(BufferUpdate msg)
- {
- Buffer _buffer = msg.getBuffer();
- if(msg.getWhat() == BufferUpdate.CREATED)
- {
- if(bufferSwitcher != null)
- bufferSwitcher.updateBufferList();
- /* When closing the last buffer, the BufferUpdate.CLOSED
- * handler doesn't call setBuffer(), because null buffers
- * are not supported. Instead, it waits for the subsequent
- * 'Untitled' file creation. */
- if(buffer.isClosed())
- {
- // since recentBuffer will be set to the one that
- // was closed
- recentBuffer = null;
- }
- }
- else if(msg.getWhat() == BufferUpdate.CLOSED)
- {
- if(bufferSwitcher != null)
- bufferSwitcher.updateBufferList();
- if(_buffer == buffer)
- {
- // The closed buffer is the current buffer
- Buffer newBuffer = recentBuffer != null ?
- recentBuffer : _buffer.getPrev();
- if(newBuffer != null && !newBuffer.isClosed())
- {
- setBuffer(newBuffer);
- recentBuffer = newBuffer.getPrev();
- }
- }
- else if(_buffer == recentBuffer)
- recentBuffer = null;
- Buffer closedBuffer = msg.getBuffer();
- if (closedBuffer.isUntitled())
- {
- // the buffer was a new file so I do not need to keep it's informations
- Map<String, CaretInfo> carets = (Map<String, CaretInfo>) getClientProperty(CARETS);
- if (carets != null)
- carets.remove(closedBuffer.getPath());
- }
- }
- else if(msg.getWhat() == BufferUpdate.LOAD_STARTED)
- {
- if(_buffer == buffer)
- {
- textArea.setCaretPosition(0);
- textArea.getPainter().repaint();
- }
- }
- else if(msg.getWhat() == BufferUpdate.LOADED)
- {
- if(_buffer == buffer)
- {
- textArea.repaint();
- if(bufferSwitcher != null)
- bufferSwitcher.updateBufferList();
- if(view.getEditPane() == this)
- {
- StatusBar status = view.getStatus();
- status.updateCaretStatus();
- status.updateBufferStatus();
- status.updateMiscStatus();
- }
- loadCaretInfo();
- }
- }
- else if(msg.getWhat() == BufferUpdate.DIRTY_CHANGED)
- {
- if(_buffer == buffer)
- {
- if(bufferSwitcher != null)
- {
- if(buffer.isDirty())
- bufferSwitcher.repaint();
- else
- bufferSwitcher.updateBufferList();
- }
- }
- }
- else if(msg.getWhat() == BufferUpdate.MARKERS_CHANGED)
- {
- if(_buffer == buffer)
- textArea.getGutter().repaint();
- }
- else if(msg.getWhat() == BufferUpdate.PROPERTIES_CHANGED)
- {
- if(_buffer == buffer && buffer.isLoaded())
- {
- textArea.propertiesChanged();
- if(view.getEditPane() == this)
- view.getStatus().updateBufferStatus();
- }
- }
- else if(msg.getWhat() == BufferUpdate.SAVED)
- {
- if(_buffer == buffer)
- textArea.propertiesChanged();
- }
- } //}}}
- //}}}
- //{{{ StatusHandler class
- class StatusHandler implements StatusListener
- {
- public void statusChanged(org.gjt.sp.jedit.textarea.TextArea textArea, int flag, boolean value)
- {
- StatusBar status = view.getStatus();
- if(status == null)
- return;
- switch(flag)
- {
- case OVERWRITE_CHANGED:
- status.setMessageAndClear(
- jEdit.getProperty("view.status.overwrite-changed",
- new Integer[] { value ? 1 : 0 }));
- break;
- case MULTI_SELECT_CHANGED:
- status.setMessageAndClear(
- jEdit.getProperty("view.status.multi-changed",
- new Integer[] { value ? 1 : 0 }));
- break;
- case RECT_SELECT_CHANGED:
- status.setMessageAndClear(
- jEdit.getProperty("view.status.rect-select-changed",
- new Integer[] { value ? 1 : 0 }));
- break;
- }
- status.updateMiscStatus();
- }
- public void bracketSelected(org.gjt.sp.jedit.textarea.TextArea textArea, int line, String text)
- {
- StatusBar status = view.getStatus();
- if(status == null)
- return;
- status.setMessageAndClear(jEdit.getProperty(
- "view.status.bracket",new Object[] {
- line, text }));
- }
- public void narrowActive(org.gjt.sp.jedit.textarea.TextArea textArea)
- {
- StatusBar status = view.getStatus();
- if(status == null)
- return;
- status.setMessageAndClear(
- jEdit.getProperty("view.status.narrow"));
- }
- } //}}}
- //{{{ MarkerHighlight class
- class MarkerHighlight extends TextAreaExtension
- {
- private boolean markerHighlight;
- private Color markerHighlightColor;
- //{{{ getMarkerHighlightColor() method
- public Color getMarkerHighlightColor()
- {
- return markerHighlightColor;
- } //}}}
- //{{{ setMarkerHighlightColor() method
- public void setMarkerHighlightColor(Color markerHighlightColor)
- {
- this.markerHighlightColor = markerHighlightColor;
- } //}}}
- //{{{ isMarkerHighlightEnabled() method
- public boolean isMarkerHighlightEnabled()
- {
- return markerHighlight;
- } //}}}
- //{{{ isMarkerHighlightEnabled()
- public void setMarkerHighlightEnabled(boolean markerHighlight)
- {
- this.markerHighlight = markerHighlight;
- } //}}}
- //{{{ paintValidLine() method
- @Override
- public void paintValidLine(Graphics2D gfx, int screenLine,
- int physicalLine, int start, int end, int y)
- {
- if(isMarkerHighlightEnabled())
- {
- Buffer buffer = (Buffer)textArea.getBuffer();
- if(buffer.getMarkerInRange(start,end) != null)
- {
- gfx.setColor(getMarkerHighlightColor());
- FontMetrics fm = textArea.getPainter().getFontMetrics();
- gfx.fillRect(0,y,textArea.getGutter()
- .getWidth(),fm.getHeight());
- }
- }
- } //}}}
- //{{{ getToolTipText() method
- @Override
- public String getToolTipText(int x, int y)
- {
- if(isMarkerHighlightEnabled())
- {
- int lineHeight = textArea.getPainter().getFontMetrics().getHeight();
- if(lineHeight == 0)
- return null;
- int line = y / lineHeight;
- int start = textArea.getScreenLineStartOffset(line);
- int end = textArea.getScreenLineEndOffset(line);
- if(start == -1 || end == -1)
- return null;
- Buffer buffer = (Buffer)textArea.getBuffer();
- Marker marker = buffer.getMarkerInRange(start,end);
- if(marker != null)
- {
- char shortcut = marker.getShortcut();
- if(shortcut == '\0')
- return jEdit.getProperty("view.gutter.marker.no-name");
- else
- {
- String[] args = { String.valueOf(shortcut) };
- return jEdit.getProperty("view.gutter.marker",args);
- }
- }
- }
- return null;
- } //}}}
- } //}}}
- }