org.gjt.sp.jedit.textarea.TextArea Maven / Gradle / Ivy
/*
* TextArea.java - Handles services.xml files in plugins
* :tabSize=8:indentSize=8:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 1999, 2005 Slava Pestov
* Portions copyright (C) 2000 Ollie Rutherfurd
* Portions copyright (C) 2006 Matthieu Casanova
*
* 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.textarea;
//{{{ Imports
import java.io.IOException;
import org.gjt.sp.jedit.Debug;
import org.gjt.sp.jedit.Mode;
import org.gjt.sp.jedit.buffer.*;
import org.gjt.sp.jedit.input.AbstractInputHandler;
import org.gjt.sp.jedit.input.InputHandlerProvider;
import org.gjt.sp.jedit.syntax.TokenMarker;
import org.gjt.sp.jedit.syntax.ParserRuleSet;
import org.gjt.sp.jedit.syntax.ModeProvider;
import org.gjt.sp.util.Log;
import org.gjt.sp.util.StandardUtilities;
import org.gjt.sp.util.SyntaxUtilities;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.event.MouseInputAdapter;
import javax.swing.text.Segment;
import java.awt.*;
import java.awt.event.*;
import java.io.InputStream;
import java.util.Properties;
import org.gjt.sp.jedit.IPropertyManager;
import org.gjt.sp.util.IOUtilities;
//}}}
/**
* jEdit's text component.
*
* Unlike most other text editors, the selection API permits selection and
* concurrent manipulation of multiple, non-contiguous regions of text.
* Methods in this class that deal with selecting text rely upon classes derived
* the {@link Selection} class.
*
* @author Slava Pestov
* @author John Gellene (API documentation)
* @version $Id: JEditTextArea.java 7148 2006-09-29 23:09:06 +0200 (ven., 29 sept. 2006) kpouer $
*/
public class TextArea extends JComponent
{
//{{{ TextArea constructor
/**
* Instantiate a TextArea.
* @param propertyManager the property manager that contains informations like shortcut bindings
* @param insideJEdit must be set to true if the textarea is embedded in jEdit
*/
public TextArea(IPropertyManager propertyManager, boolean insideJEdit)
{
this(propertyManager, null);
//{{{ init Style property manager
if (SyntaxUtilities.propertyManager == null)
{
final Properties props = new Properties();
InputStream in = TextArea.class.getResourceAsStream("/org/gjt/sp/jedit/jedit.props");
try
{
props.load(in);
}
catch (IOException e)
{
Log.log(Log.ERROR, TextArea.class, e);
}
finally
{
IOUtilities.closeQuietly(in);
}
SyntaxUtilities.propertyManager = new IPropertyManager()
{
public String getProperty(String name)
{
return props.getProperty(name);
}
};
}
//}}}
String defaultFont = SyntaxUtilities.propertyManager.getProperty("view.font");
int defaultFontSize;
try
{
defaultFontSize = Integer.parseInt(SyntaxUtilities.propertyManager.getProperty("view.fontsize"));
}
catch (NumberFormatException e)
{
defaultFontSize = 12;
}
/*Font font1 = new Font("Monospaced", Font.PLAIN, 12);
painter.setFont(font1);
SyntaxStyle[] styles = new SyntaxStyle[1];
styles[0] = new SyntaxStyle(Color.black, Color.white, font1);*/
//painter.setStyles(styles);
String name = SyntaxUtilities.propertyManager.getProperty("view.font");
String family = SyntaxUtilities.propertyManager.getProperty(name);
String sizeString = SyntaxUtilities.propertyManager.getProperty(name + "size");
String styleString = SyntaxUtilities.propertyManager.getProperty(name + "style");
//{{{ get font, copy of jEdit.getFontPropert()
Font font;
if(family == null || sizeString == null || styleString == null)
font = new Font("Monospaced", Font.PLAIN, 12);
else
{
int size, style;
try
{
size = Integer.parseInt(sizeString);
}
catch(NumberFormatException nf)
{
size = 12;
}
try
{
style = Integer.parseInt(styleString);
}
catch(NumberFormatException nf)
{
style = Font.PLAIN;
}
font = new Font(family,style,size);
} //}}}
setCaretBlinkEnabled(true);
setElectricScroll(3);
JEditBuffer buffer = new JEditBuffer();
TokenMarker tokenMarker = new TokenMarker();
tokenMarker.addRuleSet(new ParserRuleSet("text","MAIN"));
buffer.setTokenMarker(tokenMarker);
setBuffer(buffer);
Mode mode = new Mode("text");
mode.setTokenMarker(tokenMarker);
ModeProvider.instance.addMode(mode);
KillRing.setInstance(new KillRing());
KillRing.getInstance().propertiesChanged(100);
} //}}}
//{{{ TextArea constructor
/**
* Creates a new JEditTextArea.
* @param propertyManager the property manager that contains informations like shortcut bindings
* @param inputHandlerProvider the inputHandlerProvider
*/
public TextArea(IPropertyManager propertyManager, InputHandlerProvider inputHandlerProvider)
{
} //}}}
//{{{ setMouseHandler() method
public void setMouseHandler(MouseInputAdapter mouseInputAdapter)
{
mouseHandler = mouseInputAdapter;
} //}}}
//{{{ setTransferHandler() method
@Override
public void setTransferHandler(TransferHandler newHandler)
{
super.setTransferHandler(newHandler);
} //}}}
//{{{ toString() method
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("caret: ").append(caret).append('\n');
builder.append("caretLine: ").append(caretLine).append('\n');
builder.append("caretScreenLine: ").append(caretScreenLine).append('\n');
builder.append("electricScroll: ").append(electricScroll).append('\n');
builder.append("horizontalOffset: ").append(horizontalOffset).append('\n');
builder.append("magicCaret: ").append(magicCaret).append('\n');
builder.append("offsetXY").append(offsetXY.toString()).append('\n');
builder.append("oldCaretLine: ").append(oldCaretLine).append('\n');
builder.append("screenLastLine: ").append(screenLastLine).append('\n');
builder.append("visibleLines: ").append(visibleLines).append('\n');
builder.append("physLastLine: ").append(physLastLine).append('\n');
return builder.toString();
} //}}}
//{{{ dispose() method
/**
* Plugins and macros should not call this method.
* @since jEdit 4.2pre1
*/
public void dispose()
{
} //}}}
//{{{ getInputHandler() method
/**
* @since jEdit 4.3pre1
*/
public AbstractInputHandler getInputHandler()
{
return inputHandlerProvider.getInputHandler();
} //}}}
//{{{ isCaretBlinkEnabled() method
/**
* @return true if the caret is blinking, false otherwise.
*/
public final boolean isCaretBlinkEnabled()
{
return caretBlinks;
} //}}}
//{{{ setCaretBlinkEnabled() method
/**
* Toggles caret blinking.
* @param caretBlinks True if the caret should blink, false otherwise
*/
public void setCaretBlinkEnabled(boolean caretBlinks)
{
this.caretBlinks = caretBlinks;
if(!caretBlinks)
blink = false;
if(buffer != null)
invalidateLine(caretLine);
} //}}}
//{{{ getElectricScroll() method
/**
* @return the minimum distance (in number of lines)
* from the caret to the nearest edge of the screen
* (top or bottom edge).
*/
public final int getElectricScroll()
{
return electricScroll;
} //}}}
//{{{ setElectricScroll() method
/**
* Sets the number of lines from the top and bottom of the text
* area that are always visible
* @param electricScroll The number of lines always visible from
* the top or bottom
*/
public final void setElectricScroll(int electricScroll)
{
this.electricScroll = electricScroll;
} //}}}
//{{{ isQuickCopyEnabled() method
/**
* Returns if clicking the middle mouse button pastes the most
* recent selection (% register), and if Control-dragging inserts
* the selection at the caret.
*/
public final boolean isQuickCopyEnabled()
{
return quickCopy;
} //}}}
//{{{ setQuickCopyEnabled() method
/**
* Sets if clicking the middle mouse button pastes the most
* recent selection (% register), and if Control-dragging inserts
* the selection at the caret.
* @param quickCopy A boolean flag
*/
public final void setQuickCopyEnabled(boolean quickCopy)
{
this.quickCopy = quickCopy;
} //}}}
//{{{ getBuffer() method
/**
* Returns the buffer this text area is editing.
* @since jedit 4.3pre3
*
* Prior to 4.3pre3, this function returned a "Buffer" type.
* If this causes your code to break, try calling view.getBuffer() instead of
* view.getTextArea().getBuffer().
*
*/
public final JEditBuffer getBuffer()
{
return buffer;
} //}}}
//{{{ setBuffer() method
/**
* Sets the buffer this text area is editing.
* If you don't run a standalone textarea in jEdit please do not call this method -
* use {@link org.gjt.sp.jedit.EditPane#setBuffer(org.gjt.sp.jedit.Buffer)} instead.
* @param buffer The buffer
*/
public void setBuffer(JEditBuffer buffer)
{
if(this.buffer == buffer)
return;
try
{
bufferChanging = true;
if(this.buffer != null)
{
// dubious?
//setFirstLine(0);
caretLine = caret = caretScreenLine = 0;
}
boolean inCompoundEdit = false;
if (this.buffer != null)
inCompoundEdit = this.buffer.insideCompoundEdit();
if (inCompoundEdit)
this.buffer.endCompoundEdit();
this.buffer = buffer;
if (inCompoundEdit)
this.buffer.beginCompoundEdit();
}
finally
{
bufferChanging = false;
}
} //}}}
//{{{ isEditable() method
/**
* Returns true if this text area is editable, false otherwise.
*/
public final boolean isEditable()
{
return buffer.isEditable();
} //}}}
//{{{ isDragInProgress() method
/**
* Drag and drop of text in jEdit is implementing using jEdit 1.4 APIs,
* however since jEdit must run with Java 1.3, this class only has the
* necessary support to call a hook method via reflection. This method
* is called by the org.gjt.sp.jedit.Java14 class to signal that
* a drag is in progress.
* @since jEdit 4.2pre5
* @deprecated the org.gjt.jedit.Java14 class no longer exists.
*/
@Deprecated
public boolean isDragInProgress()
{
return dndInProgress;
} //}}}
//{{{ setDragInProgress() method
/**
* Drag and drop of text in jEdit is implementing using jEdit 1.4 APIs,
* however since jEdit must run with Java 1.3, this class only has the
* necessary support to call a hook method via reflection. This method
* is called by the org.gjt.sp.jedit.Java14 class to signal that
* a drag is in progress.
* @since jEdit 4.2pre5
* @deprecated the org.gjt.jedit.Java14 class no longer exists.
*/
@Deprecated
public void setDragInProgress(boolean dndInProgress)
{
this.dndInProgress = dndInProgress;
} //}}}
//{{{ isDragEnabled() method
/**
* Returns if drag and drop of text is enabled.
* @since jEdit 4.2pre5
*/
public boolean isDragEnabled()
{
return dndEnabled;
} //}}}
//{{{ setDragEnabled() method
/**
* Sets if drag and drop of text is enabled.
* @since jEdit 4.2pre5
*/
public void setDragEnabled(boolean dndEnabled)
{
this.dndEnabled = dndEnabled;
} //}}}
//{{{ getJoinNonWordChars() method
/**
* If set, double clicking will join non-word characters to form one "word".
* @since jEdit 4.3pre2
*/
public boolean getJoinNonWordChars()
{
return joinNonWordChars;
} //}}}
//{{{ setJoinNonWordChars() method
/**
* If set, double clicking will join non-word characters to form one "word".
* @since jEdit 4.3pre2
*/
public void setJoinNonWordChars(boolean joinNonWordChars)
{
this.joinNonWordChars = joinNonWordChars;
} //}}}
//{{{ getCtrlForRectangularSelection() method
/**
* If set, CTRL enables rectangular selection mode while pressed.
* @since jEdit 4.3pre10
*/
public boolean isCtrlForRectangularSelection()
{
return ctrlForRectangularSelection;
} //}}}
//{{{ setCtrlForRectangularSelection() method
/**
* If set, CTRL enables rectangular selection mode while pressed.
* @since jEdit 4.3pre10
*/
public void setCtrlForRectangularSelection(boolean ctrlForRectangularSelection)
{
this.ctrlForRectangularSelection = ctrlForRectangularSelection;
} //}}}
//{{{ setFirstLine() method
/**
* Sets the vertical scroll bar position
*
* @param firstLine The scroll bar position
*/
public void setFirstLine(int firstLine)
{
} //}}}
//{{{ setFirstPhysicalLine() method
/**
* Sets the vertical scroll bar position.
* @param physFirstLine The first physical line to display
* @since jEdit 4.2pre1
*/
public void setFirstPhysicalLine(int physFirstLine)
{
setFirstPhysicalLine(physFirstLine,0);
} //}}}
//{{{ setFirstPhysicalLine() method
/**
* Sets the vertical scroll bar position.
* @param physFirstLine The first physical line to display
* @param skew A local screen line delta
* @since jEdit 4.2pre1
*/
public void setFirstPhysicalLine(int physFirstLine, int skew)
{
} //}}}
//{{{ getLastPhysicalLine() method
/**
* Returns the last visible physical line index.
* @since jEdit 4.0pre4
*/
public final int getLastPhysicalLine()
{
return physLastLine;
} //}}}
//{{{ getLastScreenLine() method
/**
* Returns the last screen line index, it is different from
* {@link #getVisibleLines()} because the buffer can have less lines than
* the visible lines
* @return the last screen line index.
* @since jEdit 4.3pre1
*/
public int getLastScreenLine()
{
return screenLastLine;
} //}}}
//{{{ getVisibleLines() method
/**
* Returns the number of lines visible in this text area.
* @return the number of visible lines in the textarea
*/
public final int getVisibleLines()
{
return visibleLines;
} //}}}
//{{{ getHorizontalOffset() method
/**
* Returns the horizontal offset of drawn lines.
*/
public final int getHorizontalOffset()
{
return horizontalOffset;
} //}}}
//{{{ setHorizontalOffset() method
/**
* Sets the horizontal offset of drawn lines. This can be used to
* implement horizontal scrolling.
* @param horizontalOffset offset The new horizontal offset
*/
public void setHorizontalOffset(int horizontalOffset)
{
if(horizontalOffset > 0)
horizontalOffset = 0;
if(horizontalOffset == this.horizontalOffset)
return;
this.horizontalOffset = horizontalOffset;
} //}}}
//{{{ scrollUpLine() method
/**
* Scrolls up by one line.
* @since jEdit 2.7pre2
*/
public void scrollUpLine()
{
} //}}}
//{{{ scrollUpPage() method
/**
* Scrolls up by one page.
* @since jEdit 2.7pre2
*/
public void scrollUpPage()
{
} //}}}
//{{{ scrollDownLine() method
/**
* Scrolls down by one line.
* @since jEdit 2.7pre2
*/
public void scrollDownLine()
{
} //}}}
//{{{ scrollDownPage() method
/**
* Scrolls down by one page.
* @since jEdit 2.7pre2
*/
public void scrollDownPage()
{
} //}}}
//{{{ scrollToCaret() method
/**
* Ensures that the caret is visible by scrolling the text area if
* necessary.
* @param doElectricScroll If true, electric scrolling will be performed
*/
public void scrollToCaret(boolean doElectricScroll)
{
scrollTo(caretLine,caret - buffer.getLineStartOffset(caretLine),
doElectricScroll);
} //}}}
//{{{ scrollTo() method
/**
* Ensures that the specified location in the buffer is visible.
* @param offset The offset from the start of the buffer
* @param doElectricScroll If true, electric scrolling will be performed
* @since jEdit 4.2pre3
*/
public void scrollTo(int offset, boolean doElectricScroll)
{
int line = buffer.getLineOfOffset(offset);
scrollTo(line,offset - buffer.getLineStartOffset(line),
doElectricScroll);
} //}}}
//{{{ scrollTo() method
/**
* Ensures that the specified location in the buffer is visible.
* @param line The line number
* @param offset The offset from the start of the line
* @param doElectricScroll If true, electric scrolling will be performed
* @since jEdit 4.0pre6
*/
public void scrollTo(int line, int offset, boolean doElectricScroll)
{
} //}}}
//{{{ offsetToXY() method
//}}}
/**
* Marks a range of screen lines as needing a repaint.
* @param start The first line
* @param end The last line
* @since jEdit 4.0pre4
*/
public void invalidateScreenLineRange(int start, int end)
{
if(buffer.isLoading())
return;
if(start > end)
{
int tmp = end;
end = start;
start = tmp;
}
} //}}}
//{{{ invalidateLine() method
/**
* Marks a line as needing a repaint.
* @param line The physical line to invalidate
*/
public void invalidateLine(int line)
{
} //}}}
//{{{ invalidateLineRange() method
/**
* Marks a range of physical lines as needing a repaint.
* @param start The first line to invalidate
* @param end The last line to invalidate
*/
public void invalidateLineRange(int start, int end)
{
} //}}}
//}}}
//{{{ Convenience methods
//{{{ getBufferLength() method
/**
* Returns the length of the buffer.
*/
public final int getBufferLength()
{
return buffer.getLength();
} //}}}
//{{{ getLineCount() method
/**
* Returns the number of physical lines in the buffer.
*/
public final int getLineCount()
{
return buffer.getLineCount();
} //}}}
//{{{ getLineOfOffset() method
/**
* Returns the line containing the specified offset.
* @param offset The offset
*/
public final int getLineOfOffset(int offset)
{
return buffer.getLineOfOffset(offset);
} //}}}
//{{{ getLineStartOffset() method
/**
* Returns the start offset of the specified line.
* @param line The line (physical line)
* @return The start offset of the specified line, or -1 if the line is
* invalid
*/
public int getLineStartOffset(int line)
{
return buffer.getLineStartOffset(line);
} //}}}
//{{{ getLineEndOffset() method
/**
* Returns the end offset of the specified line.
* @param line The line (physical line)
* @return The end offset of the specified line, or -1 if the line is
* invalid.
*/
public int getLineEndOffset(int line)
{
return buffer.getLineEndOffset(line);
} //}}}
//{{{ getLineLength() method
/**
* Returns the length of the specified line.
* @param line The line
*/
public int getLineLength(int line)
{
return buffer.getLineLength(line);
} //}}}
//{{{ getText() method
/**
* Returns the specified substring of the buffer.
* @param start The start offset
* @param len The length of the substring
* @return The substring
*/
public final String getText(int start, int len)
{
return buffer.getText(start,len);
} //}}}
//{{{ getText() method
/**
* Copies the specified substring of the buffer into a segment.
* @param start The start offset
* @param len The length of the substring
* @param segment The segment
*/
public final void getText(int start, int len, Segment segment)
{
buffer.getText(start,len,segment);
} //}}}
//{{{ getLineText() method
/**
* Returns the text on the specified line.
* @param lineIndex the line number
* @return The text, or null if the lineIndex is invalid
*/
public final String getLineText(int lineIndex)
{
return buffer.getLineText(lineIndex);
} //}}}
//{{{ getLineText() method
/**
* Copies the text on the specified line into a Segment. If lineIndex
* is invalid, the segment will contain a null string.
* @param lineIndex The line number (physical line)
* @param segment the segment into which the data will be stored.
*/
public final void getLineText(int lineIndex, Segment segment)
{
buffer.getLineText(lineIndex,segment);
} //}}}
//{{{ getText() method
/**
* Returns the entire text of this text area.
*/
public String getText()
{
return buffer.getText(0,buffer.getLength());
} //}}}
//{{{ setText() method
/**
* Sets the entire text of this text area.
* @param text the new content of the buffer
*/
public void setText(String text)
{
try
{
buffer.beginCompoundEdit();
buffer.remove(0,buffer.getLength());
buffer.insert(0,text);
}
finally
{
buffer.endCompoundEdit();
}
} //}}}
//}}}
//{{{ Selection
//{{{ selectAll() method
/**
* Selects all text in the buffer. Preserves the scroll position.
*/
public final void selectAll()
{
} //}}}
//{{{ moveCaretPosition() method
public static final int NO_SCROLL = 0;
public static final int NORMAL_SCROLL = 1;
public static final int ELECTRIC_SCROLL = 2;
/**
* Sets the caret position without deactivating the selection.
* @param newCaret The caret position
* @param scrollMode The scroll mode (NO_SCROLL, NORMAL_SCROLL, or
* ELECTRIC_SCROLL).
* @since jEdit 4.2pre1
*/
public void moveCaretPosition(int newCaret, int scrollMode)
{
if(newCaret < 0 || newCaret > buffer.getLength())
{
throw new IllegalArgumentException("caret out of bounds: "
+ newCaret);
}
int oldCaretLine = caretLine;
if(caret == newCaret)
finishCaretUpdate(oldCaretLine,scrollMode,false);
else
{
caret = newCaret;
caretLine = getLineOfOffset(newCaret);
magicCaret = -1;
finishCaretUpdate(oldCaretLine,scrollMode,true);
}
} //}}}
//{{{ getCaretPosition() method
/**
* Returns a zero-based index of the caret position.
*/
public int getCaretPosition()
{
return caret;
} //}}}
//{{{ getCaretLine() method
/**
* Returns the line number containing the caret.
*/
public int getCaretLine()
{
return caretLine;
} //}}}
//{{{ goToPrevBracket() method
/**
* Moves the caret to the previous bracket.
* @param select true if you want to extend selection
* @since jEdit 2.7pre2
*/
public void goToPrevBracket(boolean select)
{
String text = getText(0,caret);
int newCaret = -1;
loop: for(int i = getCaretPosition() - 1; i >= 0; i--)
{
switch(text.charAt(i))
{
case '(': case '[': case '{':
newCaret = i;
break loop;
}
}
} //}}}
static TextArea focusedComponent;
//{{{ Instance variables
final Segment lineSegment = new Segment();
MouseInputAdapter mouseHandler;
boolean bufferChanging;
int maxHorizontalScrollWidth;
String wrap;
boolean hardWrap;
boolean softWrap;
boolean wrapToWidth;
int maxLineLen;
int wrapMargin;
float tabSize;
int charWidth;
boolean scrollBarsInitialized;
/**
* Cursor location, measured as an offset (in pixels) from upper left corner
* of the TextArea.
*/
Point offsetXY;
boolean lastLinePartial;
boolean blink;
//}}}
//{{{ isCaretVisible() method
/**
* Returns true if the caret is visible, false otherwise.
*/
final boolean isCaretVisible()
{
return blink && hasFocus();
} //}}}
//{{{ Instance variables
protected Cursor hiddenCursor;
private boolean caretBlinks;
private InputHandlerProvider inputHandlerProvider;
/** The last visible physical line index. */
private int physLastLine;
/**
* The last screen line index.
*/
private int screenLastLine;
/** The visible lines count. */
private int visibleLines;
private int electricScroll;
private int horizontalOffset;
private boolean quickCopy;
protected JEditBuffer buffer;
protected int caret;
protected int caretLine;
private int caretScreenLine;
private int magicCaret;
/** Flag that tells if multiple selection is on. */
protected boolean multi;
private boolean dndEnabled;
private boolean dndInProgress;
// see finishCaretUpdate() & _finishCaretUpdate()
private boolean queuedCaretUpdate;
private int queuedScrollMode;
private boolean queuedFireCaretEvent;
private int oldCaretLine;
private boolean joinNonWordChars;
private boolean ctrlForRectangularSelection;
//}}}
//{{{ invalidateSelectedLines() method
/**
* Repaints the lines containing the selection.
*/
private void invalidateSelectedLines()
{
// to hide line highlight if selections are being added later on
invalidateLine(caretLine);
} //}}}
//{{{ finishCaretUpdate() method
/**
* the collapsing of scrolling/event firing inside compound edits
* greatly speeds up replace-all.
*/
private void finishCaretUpdate(int oldCaretLine,
int scrollMode, boolean fireCaretEvent)
{
queuedFireCaretEvent |= fireCaretEvent;
queuedScrollMode = Math.max(scrollMode,queuedScrollMode);
if(queuedCaretUpdate)
return;
this.oldCaretLine = oldCaretLine;
queuedCaretUpdate = true;
} //}}}
//{{{ addExplicitFold() method
/**
* Add an explicit fold.
* You should call this method inside a compoundEdit in the buffer.
* You must also check if the buffer fold mode is explicit before
* calling this method.
*
* @param caretStart the starting offset
* @param caretEnd the end offset
* @param lineStart the start line
* @param lineEnd the end line
* @since jEdit 4.3pre3
*/
protected int addExplicitFold(int caretStart, int caretEnd, int lineStart, int lineEnd)
{
// need to "fix" the caret position so that we get the right rule.
// taking the start offset one char ahead and the end offset one char
// behing makes sure we get the right rule for the text being
// wrapped (tricky around mode boundaries, e.g., php code embedded
// in HTML code)
int startCaret = caretStart < buffer.getLength() ? caretStart + 1 : caretStart;
int endCaret = caretEnd > 0 ? caretEnd - 1 : caretEnd;
String startLineComment = buffer.getContextSensitiveProperty(startCaret,"lineComment");
String startCommentStart = buffer.getContextSensitiveProperty(startCaret,"commentStart");
String startCommentEnd = buffer.getContextSensitiveProperty(startCaret,"commentEnd");
String endLineComment = buffer.getContextSensitiveProperty(endCaret,"lineComment");
String endCommentStart = buffer.getContextSensitiveProperty(endCaret,"commentStart");
String endCommentEnd = buffer.getContextSensitiveProperty(endCaret,"commentEnd");
String start;
int caretBack = 1;
if(startLineComment != null)
start = startLineComment + "{{{ ";
else if(startCommentStart != null && startCommentEnd != null)
{
start = startCommentStart + "{{{ " + startCommentEnd;
caretBack = 1 + startCommentStart.length();
}
else
start = "{{{ ";
if (startLineComment != null) {
// add a new line if there's text after the comment
// we're inserting
if (buffer.getLineLength(lineStart) != caretStart)
{
start += '\n';
}
}
else
{
// always insert a new line if there's no comment character.
start += "\n";
}
String end;
if(endLineComment != null)
end = endLineComment + "}}}";
else if(endCommentStart != null && endCommentEnd != null)
end = endCommentStart + "}}}" + endCommentEnd;
else
end = "}}}";
String line = buffer.getLineText(lineStart);
String whitespace = line.substring(0,
StandardUtilities.getLeadingWhiteSpace(line));
if (endLineComment != null)
{
// if we're inserting a line comment into a non-empty
// line, we'll need to add a line break so we don't
// comment out existing code.
if (buffer.getLineLength(lineEnd) != caretEnd)
{
end += '\n';
}
}
else
{
// always insert a new line if there's no comment character.
end += "\n";
}
if(caretEnd == buffer.getLineStartOffset(lineEnd))
buffer.insert(caretEnd,end);
else
{
CharSequence lineText = buffer.getSegment(caretEnd - 1, 1);
if (Character.isWhitespace(lineText.charAt(0)))
buffer.insert(caretEnd, end);
else
buffer.insert(caretEnd,' ' + end);
}
buffer.insert(caretStart,start + whitespace);
return caretBack;
} //}}}
//{{{ rangeLineComment() method
/**
* This method will surround each selected line with a range comment.
* This is used when calling line comment if the edit mode doesn't have
* a line comment property
* @since jEdit 4.3pre10
*/
private void rangeLineComment()
{
String commentStart = buffer.getContextSensitiveProperty(caret,"commentStart");
String commentEnd = buffer.getContextSensitiveProperty(caret,"commentEnd");
if(!buffer.isEditable() || commentStart == null || commentEnd == null
|| commentStart.length() == 0 || commentEnd.length() == 0)
{
getToolkit().beep();
return;
}
commentStart += ' ';
commentEnd = ' ' + commentEnd;
} //}}}
//{{{ joinLine() method
/**
* Join a line with the next line.
* If you use this method you have to lock the buffer in compound edit mode.
* @param line the line number that will be joined with the next line
*/
private void joinLineAt(int line)
{
if (line >= buffer.getLineCount() - 1)
return;
int end = getLineEndOffset(line);
CharSequence nextLineText = buffer.getLineSegment(line + 1);
buffer.remove(end - 1,StandardUtilities.getLeadingWhiteSpace(
nextLineText) + 1);
if (nextLineText.length() != 0)
buffer.insert(end - 1, " ");
} //}}}
//}}}
//{{{ Inner classes
//{{{ AdjustHandler class
private class AdjustHandler implements AdjustmentListener
{
//{{{ adjustmentValueChanged() method
public void adjustmentValueChanged(AdjustmentEvent evt)
{
} //}}}
} //}}}
//{{{ _createTextArea() method
/**
* Create a standalone textArea.
* @param insidejEdit true if we are in jEdit, false otherwise
* @param iPropertyManager the property manager that will provide properties
* @return the new textarea
*/
public static TextArea _createTextArea(boolean insidejEdit, final IPropertyManager iPropertyManager)
{
final TextArea textArea = new TextArea(iPropertyManager, insidejEdit);
return textArea;
} //}}}
//{{{ createTextArea() method
/**
* Create a standalone TextArea.
* If you want to use it in jEdit, please use {@link org.gjt.sp.jedit.jEdit#createTextArea()}
*
* @param iPropertyManager the properties where key bindings are stored
* @return a textarea
* @since 4.3pre13
*/
public static TextArea createTextArea(IPropertyManager iPropertyManager)
{
TextArea textArea = _createTextArea(false, iPropertyManager);
return textArea;
} // }}}
//{{{ createTextArea() method
/**
* Create a standalone TextArea.
* If you want to use it in jEdit, please use {@link org.gjt.sp.jedit.jEdit#createTextArea()}
*
* @return a textarea
* @since 4.3pre13
*/
public static TextArea createTextArea()
{
final Properties props = new Properties();
InputStream in = TextArea.class.getResourceAsStream("/org/gjt/sp/jedit/jedit_keys.props");
try
{
props.load(in);
}
catch (IOException e)
{
Log.log(Log.ERROR, TextArea.class, e);
}
finally
{
IOUtilities.closeQuietly(in);
}
TextArea textArea = _createTextArea(false, new IPropertyManager()
{
public String getProperty(String name)
{
return props.getProperty(name);
}
});
textArea.getBuffer().setProperty("folding", "explicit");
return textArea;
} // }}}
}