### Eclipse Workspace Patch 1.0
#P org.eclipse.ui.workbench.texteditor
Index: src/org/eclipse/ui/texteditor/AbstractTextEditor.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java,v
retrieving revision 1.293
diff -u -r1.293 AbstractTextEditor.java
--- src/org/eclipse/ui/texteditor/AbstractTextEditor.java 27 Nov 2008 14:43:32 -0000 1.293
+++ src/org/eclipse/ui/texteditor/AbstractTextEditor.java 23 Dec 2008 14:39:49 -0000
@@ -12,6 +12,7 @@
* Genady Beryozkin, me@genady.org - https://bugs.eclipse.org/bugs/show_bug.cgi?id=11668
* Benjamin Muskalla
"ColumnMode"
+ * @since 3.5
+ */
+ String BLOCK_MODE = "ColumnMode"; //$NON-NLS-1$
}
Index: src/org/eclipse/ui/texteditor/CaseAction.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/CaseAction.java,v
retrieving revision 1.12
diff -u -r1.12 CaseAction.java
--- src/org/eclipse/ui/texteditor/CaseAction.java 16 Jul 2008 12:03:42 -0000 1.12
+++ src/org/eclipse/ui/texteditor/CaseAction.java 23 Dec 2008 14:39:49 -0000
@@ -8,16 +8,21 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sebastian Davids "column_mode_context_action_context"
+ * @since 3.5
+ */
+ String COLUMN_MODE_ACTION=PREFIX + "column_mode" + ACTION_POSTFIX; //$NON-NLS-1$
}
Index: src/org/eclipse/ui/texteditor/DeleteLineAction.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/DeleteLineAction.java,v
retrieving revision 1.16
diff -u -r1.16 DeleteLineAction.java
--- src/org/eclipse/ui/texteditor/DeleteLineAction.java 22 Oct 2008 12:39:59 -0000 1.16
+++ src/org/eclipse/ui/texteditor/DeleteLineAction.java 23 Dec 2008 14:39:49 -0000
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.ui.texteditor;
@@ -189,7 +190,10 @@
return;
try {
- fTarget.deleteLine(document, selection.getOffset(), selection.getLength(), fType, fCopyToClipboard);
+ if (fTarget instanceof TextViewerDeleteLineTarget)
+ ((TextViewerDeleteLineTarget) fTarget).deleteLine(document, selection, fType, fCopyToClipboard);
+ else
+ fTarget.deleteLine(document, selection.getOffset(), selection.getLength(), fType, fCopyToClipboard);
} catch (BadLocationException e) {
// should not happen
}
Index: src/org/eclipse/ui/texteditor/TextViewerDeleteLineTarget.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/TextViewerDeleteLineTarget.java,v
retrieving revision 1.3
diff -u -r1.3 TextViewerDeleteLineTarget.java
--- src/org/eclipse/ui/texteditor/TextViewerDeleteLineTarget.java 11 Sep 2008 11:58:02 -0000 1.3
+++ src/org/eclipse/ui/texteditor/TextViewerDeleteLineTarget.java 23 Dec 2008 14:39:50 -0000
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.ui.texteditor;
@@ -34,10 +35,12 @@
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextListener;
+import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextEvent;
+import org.eclipse.jface.text.TextSelection;
import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
@@ -255,32 +258,28 @@
}
/**
- * Returns the document's delete region specified by position and type.
+ * Returns the document's delete region according to selection
and type
.
*
* @param document the document
- * @param offset the offset
- * @param length the length
+ * @param selection the selection
* @param type the line deletion type, must be one of WHOLE_LINE
,
* TO_BEGINNING
or TO_END
* @return the document's delete region
* @throws BadLocationException if the document is accessed with invalid offset or line
*/
- private IRegion getDeleteRegion(IDocument document, int offset, int length, int type) throws BadLocationException {
+ private IRegion getDeleteRegion(IDocument document, ITextSelection selection, int type) throws BadLocationException {
- int line= document.getLineOfOffset(offset);
+ int offset= selection.getOffset();
+ int line= selection.getStartLine();
int resultOffset= 0;
int resultLength= 0;
switch (type) {
- case DeleteLineAction.WHOLE:
- resultOffset= document.getLineOffset(line);
- int endOffset= offset + length;
- IRegion endLineInfo= document.getLineInformationOfOffset(endOffset);
- int endLine= document.getLineOfOffset(endLineInfo.getOffset());
- if (endLineInfo.getOffset() == endOffset && endLine > 0 && length > 0)
- endLine= endLine - 1;
- resultLength= document.getLineOffset(endLine) + document.getLineLength(endLine) - resultOffset;
- break;
+ case DeleteLineAction.WHOLE:
+ resultOffset= document.getLineOffset(line);
+ int endLine= selection.getEndLine();
+ resultLength= document.getLineOffset(endLine) + document.getLineLength(endLine) - resultOffset;
+ break;
case DeleteLineAction.TO_BEGINNING:
resultOffset= document.getLineOffset(line);
@@ -338,8 +337,22 @@
* @since 3.4
*/
public void deleteLine(IDocument document, int offset, int length, int type, boolean copyToClipboard) throws BadLocationException {
+ deleteLine(document, new TextSelection(offset, length), type, copyToClipboard);
+ }
- IRegion deleteRegion= getDeleteRegion(document, offset, length, type);
+ /**
+ * Deletes the lines that intersect with the given selection
.
+ *
+ * @param document the document
+ * @param selection the selection to use to determine the document range to delete
+ * @param type the line deletion type, must be one of
+ * WHOLE_LINE
, TO_BEGINNING
or TO_END
+ * @param copyToClipboard true
if the deleted line should be copied to the clipboard
+ * @throws BadLocationException if position is not valid in the given document
+ * @since 3.5
+ */
+ public void deleteLine(IDocument document, ITextSelection selection, int type, boolean copyToClipboard) throws BadLocationException {
+ IRegion deleteRegion= getDeleteRegion(document, selection, type);
int deleteOffset= deleteRegion.getOffset();
int deleteLength= deleteRegion.getLength();
Index: src/org/eclipse/ui/texteditor/MoveLinesAction.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/MoveLinesAction.java,v
retrieving revision 1.21
diff -u -r1.21 MoveLinesAction.java
--- src/org/eclipse/ui/texteditor/MoveLinesAction.java 11 Sep 2008 11:58:02 -0000 1.21
+++ src/org/eclipse/ui/texteditor/MoveLinesAction.java 23 Dec 2008 14:39:50 -0000
@@ -7,13 +7,13 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.ui.texteditor;
import java.util.ResourceBundle;
import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Event;
import org.eclipse.core.runtime.Assert;
@@ -291,12 +291,10 @@
return;
// get selection
- Point p= fTextViewer.getSelectedRange();
- if (p == null)
+ ITextSelection sel= (ITextSelection) fTextViewer.getSelectionProvider().getSelection();
+ if (sel.isEmpty())
return;
- ITextSelection sel= new TextSelection(document, p.x, p.y);
-
ITextSelection skippedLine= getSkippedLine(document, sel);
if (skippedLine == null)
return;
Index: src/org/eclipse/ui/texteditor/ConstructedEditorMessages.properties
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/ConstructedEditorMessages.properties,v
retrieving revision 1.13
diff -u -r1.13 ConstructedEditorMessages.properties
--- src/org/eclipse/ui/texteditor/ConstructedEditorMessages.properties 24 Nov 2008 16:15:52 -0000 1.13
+++ src/org/eclipse/ui/texteditor/ConstructedEditorMessages.properties 23 Dec 2008 14:39:49 -0000
@@ -7,6 +7,7 @@
#
# Contributors:
# IBM Corporation - initial API and implementation
+# Tom Eicher (Avaloq Evolution AG) - block selection mode
###############################################################################
Editor.Undo.label=&Undo
@@ -238,3 +239,8 @@
Editor.ShowInformation.tooltip= Shows the Tooltip Description
Editor.ShowInformation.image=
Editor.ShowInformation.description= Displays information for the current caret location in a sticky hover
+
+Editor.ToggleColumnMode.label= Toggle Column Mode
+Editor.ToggleColumnMode.description= Enable rectangular / column selection in the current text editor
+Editor.ToggleColumnMode.image=
+Editor.ToggleColumnMode.tooltip= Toggle Column Selection Mode
Index: src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java,v
retrieving revision 1.37
diff -u -r1.37 ITextEditorActionDefinitionIds.java
--- src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java 24 Nov 2008 10:28:59 -0000 1.37
+++ src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java 23 Dec 2008 14:39:50 -0000
@@ -10,6 +10,7 @@
* Chris.Dennis@invidi.com - http://bugs.eclipse.org/bugs/show_bug.cgi?id=29027
* Genady Beryozkin, me@genady.org - https://bugs.eclipse.org/bugs/show_bug.cgi?id=11668
* Benjamin Muskalla "org.eclipse.ui.edit.text.toggleColumnMode"
).
+ * @since 3.5
+ */
+ String BLOCK_MODE = "org.eclipse.ui.edit.text.toggleColumnMode"; //$NON-NLS-1$
}
Index: plugin.properties
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/plugin.properties,v
retrieving revision 1.47
diff -u -r1.47 plugin.properties
--- plugin.properties 15 Mar 2007 10:25:00 -0000 1.47
+++ plugin.properties 23 Dec 2008 14:39:44 -0000
@@ -7,6 +7,7 @@
#
# Contributors:
# IBM Corporation - initial API and implementation
+# Tom Eicher (Avaloq Evolution AG) - block selection mode
###############################################################################
pluginName= Text Editor Framework
providerName= Eclipse.org
@@ -32,6 +33,10 @@
showInformation.name= Show Tooltip Description
showInformation.description= Displays information for the current caret location in a sticky hover
+toggleColumnMode.label= Enable Block Selection
+toggleColumnMode.tooltip= Enables block selection mode
+toggleColumnMode.description= Enable block / column selection in the current text editor
+
smartEnter.label= Insert Line Below Current Line
smartEnter.description= Adds a new line below the current line
smartEnterInverse.label= Insert Line Above Current Line
@@ -169,3 +174,5 @@
SpellingEngine= Spelling Engine
+columnModeFont.label= Text Editor Block Selection Font
+columnModeFont.description= The block selection mode font is used by text editors in block (column) mode. A monospace font should be used.
Index: plugin.xml
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/plugin.xml,v
retrieving revision 1.91
diff -u -r1.91 plugin.xml
--- plugin.xml 2 May 2007 20:23:35 -0000 1.91
+++ plugin.xml 23 Dec 2008 14:39:45 -0000
@@ -399,6 +399,12 @@
categoryId="org.eclipse.ui.category.window"
id="org.eclipse.ui.edit.text.toggleShowSelectedElementOnly">
+ + * This interface may be implemented by clients. + *
+ * + * @since 3.5 + */ +public interface ITextEditorExtension5 { + /** + * Returnstrue
if the receiver is in block (aka rectangular or column) selection
+ * mode, false
otherwise.
+ *
+ * @return the receiver's block selection state
+ */
+ boolean isBlockSelectionEnabled();
+
+ /**
+ * Sets the block selection mode state of the receiver to enable
. Nothing happens
+ * if the receiver already is in the requested state.
+ *
+ * @param enable the new block selection state
+ */
+ void setBlockSelectionMode(boolean enable);
+}
Index: src/org/eclipse/ui/texteditor/BlockModeToggleAction.java
===================================================================
RCS file: src/org/eclipse/ui/texteditor/BlockModeToggleAction.java
diff -N src/org/eclipse/ui/texteditor/BlockModeToggleAction.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/ui/texteditor/BlockModeToggleAction.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Avaloq Evolution AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tom Eicher (Avaloq Evolution AG) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ui.texteditor;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.action.IAction;
+
+
+/**
+ * This action toggles the block (aka rectangular) selection mode.
+ * + * This API is provisional and may change any time before the 3.5 API freeze. + *
+ * + * @since 3.5 + */ +final class BlockModeToggleAction extends TextEditorAction { + + /** + * Construct the action and initialize its state. + * + * @param resourceBundle the resource bundle to construct label and tooltip from + * @param prefix the prefix to use for constructing resource bundle keys + * @param editor the editor this action is associated with + */ + public BlockModeToggleAction(ResourceBundle resourceBundle, String prefix, ITextEditor editor) { + super(resourceBundle, prefix, editor, IAction.AS_CHECK_BOX); + } + + /* + * @see org.eclipse.jface.action.Action#run() + */ + public void run() { + ITextEditor editor= getTextEditor(); + if (editor instanceof ITextEditorExtension5) { + ITextEditorExtension5 ext5= (ITextEditorExtension5) editor; + ext5.setBlockSelectionMode(!ext5.isBlockSelectionEnabled()); + } + update(); // update in case anyone else has directly accessed the widget + } + + /* + * @see org.eclipse.ui.texteditor.TextEditorAction#update() + */ + public void update() { + ITextEditor editor= getTextEditor(); + if (editor instanceof ITextEditorExtension5) { + ITextEditorExtension5 ext5= (ITextEditorExtension5) editor; + setEnabled(true); + setChecked(ext5.isBlockSelectionEnabled()); + return; + } + setEnabled(false); + setChecked(false); + } +} #P org.eclipse.jdt.ui Index: ui/org/eclipse/jdt/ui/text/JavaSourceViewerConfiguration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/JavaSourceViewerConfiguration.java,v retrieving revision 1.159 diff -u -r1.159 JavaSourceViewerConfiguration.java --- ui/org/eclipse/jdt/ui/text/JavaSourceViewerConfiguration.java 15 Sep 2008 14:16:47 -0000 1.159 +++ ui/org/eclipse/jdt/ui/text/JavaSourceViewerConfiguration.java 23 Dec 2008 14:39:56 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Tom Eicher (Avaloq Evolution AG) - block selection mode *******************************************************************************/ package org.eclipse.jdt.ui.text; @@ -459,9 +460,9 @@ else if (IJavaPartitions.JAVA_STRING.equals(contentType)) return new IAutoEditStrategy[] { new SmartSemicolonAutoEditStrategy(partitioning), new JavaStringAutoIndentStrategy(partitioning) }; else if (IJavaPartitions.JAVA_CHARACTER.equals(contentType) || IDocument.DEFAULT_CONTENT_TYPE.equals(contentType)) - return new IAutoEditStrategy[] { new SmartSemicolonAutoEditStrategy(partitioning), new JavaAutoIndentStrategy(partitioning, getProject()) }; + return new IAutoEditStrategy[] { new SmartSemicolonAutoEditStrategy(partitioning), new JavaAutoIndentStrategy(partitioning, getProject(), sourceViewer) }; else - return new IAutoEditStrategy[] { new JavaAutoIndentStrategy(partitioning, getProject()) }; + return new IAutoEditStrategy[] { new JavaAutoIndentStrategy(partitioning, getProject(), sourceViewer) }; } /* Index: ui/org/eclipse/jdt/internal/ui/javaeditor/JavaMoveLinesAction.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/JavaMoveLinesAction.java,v retrieving revision 1.12 diff -u -r1.12 JavaMoveLinesAction.java --- ui/org/eclipse/jdt/internal/ui/javaeditor/JavaMoveLinesAction.java 11 Sep 2008 11:59:24 -0000 1.12 +++ ui/org/eclipse/jdt/internal/ui/javaeditor/JavaMoveLinesAction.java 23 Dec 2008 14:39:55 -0000 @@ -7,13 +7,13 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Tom Eicher (Avaloq Evolution AG) - block selection mode *******************************************************************************/ package org.eclipse.jdt.internal.ui.javaeditor; import java.util.ResourceBundle; import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Event; import org.eclipse.core.runtime.Assert; @@ -320,12 +320,10 @@ return; // get selection - Point p= viewer.getSelectedRange(); - if (p == null) + ITextSelection sel= (ITextSelection) viewer.getSelectionProvider().getSelection(); + if (sel.isEmpty()) return; - ITextSelection sel= new TextSelection(document, p.x, p.y); - ITextSelection skippedLine= getSkippedLine(document, sel); if (skippedLine == null) return; @@ -436,7 +434,14 @@ if (numberOfLines < 1) return new Region(offset, 0); int endLine= startLine + numberOfLines - 1; - int endOffset= document.getLineOffset(endLine) + document.getLineLength(endLine); + int endOffset; + if (fSharedState.fEditor.isBlockSelectionEnabled()) { + // in column mode, don't select the last delimiter as we count an empty selected line + IRegion endLineInfo= document.getLineInformation(endLine); + endOffset= endLineInfo.getOffset() + endLineInfo.getLength(); + } else { + endOffset= document.getLineOffset(endLine) + document.getLineLength(endLine); + } return new Region(offset, endOffset - offset); } Index: ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java,v retrieving revision 1.471 diff -u -r1.471 JavaEditor.java --- ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java 17 Nov 2008 16:49:35 -0000 1.471 +++ ui/org/eclipse/jdt/internal/ui/javaeditor/JavaEditor.java 23 Dec 2008 14:39:54 -0000 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Tom EicherrestoreSelection()
.
*
@@ -724,7 +742,7 @@
*/
protected Point rememberSelection() {
- final Point selection= getSelectedRange();
+ final ITextSelection selection= (ITextSelection) getSelection();
final IDocument document= getDocument();
if (fSelections.isEmpty()) {
@@ -735,8 +753,11 @@
}
try {
-
- final Position position= new Position(selection.x, selection.y);
+ final Position position;
+ if (selection instanceof IBlockTextSelection)
+ position= new ColumnPosition(selection.getOffset(), selection.getLength(), ((IBlockTextSelection) selection).getStartColumn(), ((IBlockTextSelection) selection).getEndColumn());
+ else
+ position= new Position(selection.getOffset(), selection.getLength());
document.addPosition(fSelectionCategory, position);
fSelections.push(position);
@@ -746,7 +767,7 @@
// Should not happen
}
- return selection;
+ return new Point(selection.getOffset(), selection.getLength());
}
/**
@@ -766,13 +787,20 @@
try {
document.removePosition(fSelectionCategory, position);
Point currentSelection= getSelectedRange();
- if (currentSelection == null || currentSelection.x != position.getOffset() || currentSelection.y != position.getLength())
- setSelectedRange(position.getOffset(), position.getLength());
+ if (currentSelection == null || currentSelection.x != position.getOffset() || currentSelection.y != position.getLength()) {
+ if (position instanceof ColumnPosition && getTextWidget().getBlockSelection()) {
+ setSelection(new BlockTextSelection(document, document.getLineOfOffset(position.getOffset()), ((ColumnPosition) position).fStartColumn, document.getLineOfOffset(position.getOffset() + position.getLength()), ((ColumnPosition) position).fEndColumn, getTextWidget().getTabs()));
+ } else {
+ setSelectedRange(position.getOffset(), position.getLength());
+ }
+ }
if (fSelections.isEmpty())
clearRememberedSelection();
} catch (BadPositionCategoryException exception) {
// Should not happen
+ } catch (BadLocationException x) {
+ // Should not happen
}
}
}
Index: src/org/eclipse/jface/text/TextViewer.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewer.java,v
retrieving revision 1.204
diff -u -r1.204 TextViewer.java
--- src/org/eclipse/jface/text/TextViewer.java 19 Dec 2008 09:45:36 -0000 1.204
+++ src/org/eclipse/jface/text/TextViewer.java 23 Dec 2008 14:40:01 -0000
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.jface.text;
@@ -2415,6 +2416,16 @@
* @see Viewer#setSelection(ISelection)
*/
public void setSelection(ISelection selection, boolean reveal) {
+// // FIXME ViewerState should also support column selections
+// if (selection instanceof IColumnTextSelection && getTextWidget().getBlockSelection()) {
+// IColumnTextSelection s= (IColumnTextSelection) selection;
+// StyledText styledText= getTextWidget();
+// int startLine= modelLine2WidgetLine(s.getStartLine());
+// int endLine= modelLine2WidgetLine(s.getEndLine());
+// styledText.setBlColumnSelection(s.getStartColumn(), startLine, s.getEndColumn(), endLine);
+// if (reveal)
+// revealRange(s.getOffset(), s.getLength());
+// } else if (selection instanceof ITextSelection) {
if (selection instanceof ITextSelection) {
ITextSelection s= (ITextSelection) selection;
setSelectedRange(s.getOffset(), s.getLength());
@@ -2427,6 +2438,28 @@
* @see Viewer#getSelection()
*/
public ISelection getSelection() {
+ if (redraws() && fTextWidget != null && fTextWidget.getBlockSelection()) {
+ int[] ranges= fTextWidget.getSelectionRanges();
+ int startOffset= ranges[0];
+ int endOffset= ranges[ranges.length - 2] + ranges[ranges.length - 1];
+
+ IDocument document= getDocument();
+ startOffset= widgetOffset2ModelOffset(startOffset);
+ endOffset= widgetOffset2ModelOffset(endOffset);
+ try {
+ int startLine= document.getLineOfOffset(startOffset);
+ int endLine= document.getLineOfOffset(endOffset);
+
+ int startColumn= startOffset - document.getLineOffset(startLine);
+ int endColumn= endOffset - document.getLineOffset(endLine);
+ if (startLine == -1 || endLine == -1)
+ return TextSelection.emptySelection();
+ return new BlockTextSelection(document, startLine, startColumn, endLine, endColumn, fTextWidget.getTabs());
+ } catch (BadLocationException e) {
+ return TextSelection.emptySelection();
+ }
+ }
+
Point p= getSelectedRange();
if (p.x == -1 || p.y == -1)
return TextSelection.emptySelection();
@@ -3965,13 +3998,15 @@
* @return the region describing the text block comprising the given selection
* @since 2.0
*/
- private IRegion getTextBlockFromSelection(Point selection) {
+ private IRegion getTextBlockFromSelection(ITextSelection selection) {
try {
IDocument document= getDocument();
- IRegion line= document.getLineInformationOfOffset(selection.x);
- int length= selection.y == 0 ? line.getLength() : selection.y + (selection.x - line.getOffset());
- return new Region(line.getOffset(), length);
+ int start= document.getLineOffset(selection.getStartLine());
+ int endLine= selection.getEndLine();
+ IRegion endLineInfo= document.getLineInformation(endLine);
+ int end= endLineInfo.getOffset() + endLineInfo.getLength();
+ return new Region(start, end - start);
} catch (BadLocationException x) {
}
@@ -4010,7 +4045,7 @@
Map partitioners= null;
DocumentRewriteSession rewriteSession= null;
try {
- Point selection= getSelectedRange();
+ ITextSelection selection= (ITextSelection) getSelection();
IRegion block= getTextBlockFromSelection(selection);
ITypedRegion[] regions= TextUtilities.computePartitioning(d, getDocumentPartitioning(), block.getOffset(), block.getLength(), false);
Index: src/org/eclipse/jface/text/TextSelection.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/TextSelection.java,v
retrieving revision 1.13
diff -u -r1.13 TextSelection.java
--- src/org/eclipse/jface/text/TextSelection.java 12 Sep 2008 14:44:18 -0000 1.13
+++ src/org/eclipse/jface/text/TextSelection.java 23 Dec 2008 14:39:59 -0000
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.jface.text;
@@ -17,7 +18,7 @@
/**
* Standard implementation of {@link org.eclipse.jface.text.ITextSelection}.
* - * Makes advantage of the weak contract of correctness of its interface. If + * Takes advantage of the weak contract of correctness of its interface. If * generated from a selection provider, it only remembers its offset and length * and computes the remaining information on request.
*/ @@ -42,8 +43,8 @@ return NULL; } - /** Document which delivers the data of the selection */ - private IDocument fDocument; + /** Document which delivers the data of the selection, possiblynull
. */
+ protected final IDocument fDocument;
/** Offset of the selection */
private int fOffset;
/** Length of the selection */
@@ -56,6 +57,7 @@
private TextSelection() {
fOffset= -1;
fLength= -1;
+ fDocument= null;
}
/**
Index: src/org/eclipse/jface/text/CursorLinePainter.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/CursorLinePainter.java,v
retrieving revision 1.21
diff -u -r1.21 CursorLinePainter.java
--- src/org/eclipse/jface/text/CursorLinePainter.java 11 Sep 2008 11:58:23 -0000 1.21
+++ src/org/eclipse/jface/text/CursorLinePainter.java 23 Dec 2008 14:39:59 -0000
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.jface.text;
@@ -77,7 +78,7 @@
int caret= textWidget.getCaretOffset();
int length= event.lineText.length();
- if (event.lineOffset <= caret && caret <= event.lineOffset + length)
+ if (event.lineOffset <= caret && caret <= event.lineOffset + length && !hasMultiLineSelection(textWidget))
event.lineBackground= fHighlightColor;
else
event.lineBackground= textWidget.getBackground();
@@ -223,10 +224,7 @@
StyledText textWidget= fViewer.getTextWidget();
// check selection
- Point selection= textWidget.getSelection();
- int startLine= textWidget.getLineAtOffset(selection.x);
- int endLine= textWidget.getLineAtOffset(selection.y);
- if (startLine != endLine) {
+ if (hasMultiLineSelection(textWidget)) {
deactivate(true);
return;
}
@@ -247,6 +245,22 @@
}
}
+ /**
+ * Returns true
if the widget has a selection spanning multiple lines,
+ * false
otherwise.
+ *
+ * @param textWidget the text widget to check
+ * @return true
if textWidget
has a multiline selection,
+ * false
otherwise
+ * @since 3.5
+ */
+ private boolean hasMultiLineSelection(StyledText textWidget) {
+ Point selection= textWidget.getSelection();
+ int startLine= textWidget.getLineAtOffset(selection.x);
+ int endLine= textWidget.getLineAtOffset(selection.y);
+ return startLine != endLine;
+ }
+
/*
* @see IPainter#setPositionManager(IPaintPositionManager)
*/
Index: src/org/eclipse/jface/text/WhitespaceCharacterPainter.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/WhitespaceCharacterPainter.java,v
retrieving revision 1.11
diff -u -r1.11 WhitespaceCharacterPainter.java
--- src/org/eclipse/jface/text/WhitespaceCharacterPainter.java 11 Sep 2008 11:58:23 -0000 1.11
+++ src/org/eclipse/jface/text/WhitespaceCharacterPainter.java 23 Dec 2008 14:40:01 -0000
@@ -9,6 +9,7 @@
* Anton Leherbauer (Wind River Systems) - initial API and implementation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=22712
* Anton Leherbauer (Wind River Systems) - [painting] Long lines take too long to display when "Show Whitespace Characters" is enabled - https://bugs.eclipse.org/bugs/show_bug.cgi?id=196116
* Anton Leherbauer (Wind River Systems) - [painting] Whitespace characters not drawn when scrolling to right slowly - https://bugs.eclipse.org/bugs/show_bug.cgi?id=206633
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.jface.text;
@@ -229,7 +230,6 @@
String text= content.getTextRange(startOffset, length);
StyleRange styleRange= null;
Color fg= null;
- Point selection= fTextWidget.getSelection();
StringBuffer visibleChar= new StringBuffer(10);
for (int textOffset= 0; textOffset <= length; ++textOffset) {
int delta= 0;
@@ -270,7 +270,7 @@
if (visibleChar.length() > 0) {
int widgetOffset= startOffset + textOffset - visibleChar.length() + delta;
if (!eol || !isFoldedLine(content.getLineAtOffset(widgetOffset))) {
- if (widgetOffset >= selection.x && widgetOffset < selection.y) {
+ if (isOffsetSelected(fTextWidget, widgetOffset)) {
fg= fTextWidget.getSelectionForeground();
} else if (styleRange == null || styleRange.start + styleRange.length <= widgetOffset) {
styleRange= fTextWidget.getStyleRangeAtOffset(widgetOffset);
@@ -286,6 +286,23 @@
}
}
}
+
+ /**
+ * Returns true
if offset
is selection in widget
,
+ * false
otherwise.
+ *
+ * @param widget the widget
+ * @param offset the offset
+ * @return true
if offset
is selection, false
otherwise
+ * @since 3.5
+ */
+ private static final boolean isOffsetSelected(StyledText widget, int offset) {
+ int[] ranges= widget.getSelectionRanges();
+ for (int i= 0; i < ranges.length; i+= 2)
+ if (ranges[i] <= offset && offset <= ranges[i + 1])
+ return true;
+ return false;
+ }
/**
* Check if the given widget line is a folded line.
Index: src/org/eclipse/jface/text/JFaceTextUtil.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/JFaceTextUtil.java,v
retrieving revision 1.8
diff -u -r1.8 JFaceTextUtil.java
--- src/org/eclipse/jface/text/JFaceTextUtil.java 27 Nov 2008 14:43:08 -0000 1.8
+++ src/org/eclipse/jface/text/JFaceTextUtil.java 23 Dec 2008 14:39:59 -0000
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.jface.text;
@@ -16,6 +17,8 @@
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.jface.internal.text.SelectionProcessor;
+
import org.eclipse.jface.text.source.ILineRange;
import org.eclipse.jface.text.source.LineRange;
@@ -353,4 +356,33 @@
return increment;
}
+ /**
+ * Returns true
if the text covered by selection
does not contain any
+ * characters in the given viewer. Note the difference to {@link ITextSelection#isEmpty()},
+ * which returns true
only for invalid selections.
+ *
+ * @param viewer the viewer
+ * @param selection the selection
+ * @return true
if selection
does not contain any text,
+ * false
otherwise
+ * @throws BadLocationException if accessing the document failed
+ * @since 3.5
+ */
+ public static boolean isEmpty(ITextViewer viewer, ITextSelection selection) throws BadLocationException {
+ return new SelectionProcessor(viewer).isEmpty(selection);
+ }
+
+ /**
+ * Returns the text regions covered by the given selection in the given viewer.
+ *
+ * @param viewer the viewer
+ * @param selection the selection
+ * @return the text regions corresponding to selection
+ * @throws BadLocationException if accessing the document failed
+ * @since 3.5
+ */
+ public static IRegion[] getCoveredRanges(ITextViewer viewer, ITextSelection selection) throws BadLocationException {
+ return new SelectionProcessor(viewer).getRanges(selection);
+ }
+
}
Index: projection/org/eclipse/jface/text/source/projection/ProjectionViewer.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface.text/projection/org/eclipse/jface/text/source/projection/ProjectionViewer.java,v
retrieving revision 1.103
diff -u -r1.103 ProjectionViewer.java
--- projection/org/eclipse/jface/text/source/projection/ProjectionViewer.java 2 Oct 2008 15:40:41 -0000 1.103
+++ projection/org/eclipse/jface/text/source/projection/ProjectionViewer.java 23 Dec 2008 14:39:58 -0000
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tom Eicher (Avaloq Evolution AG) - block selection mode
*******************************************************************************/
package org.eclipse.jface.text.source.projection;
@@ -28,6 +29,8 @@
import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.internal.text.SelectionProcessor;
+
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
@@ -36,9 +39,11 @@
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ISlaveDocumentManager;
+import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.projection.ProjectionDocument;
import org.eclipse.jface.text.projection.ProjectionDocumentEvent;
@@ -1443,34 +1448,31 @@
if (textWidget == null)
return;
- Point selection= null;
+ ITextSelection selection= null;
switch (operation) {
case CUT:
if (redraws()) {
- selection= getSelectedRange();
- if (exposeModelRange(new Region(selection.x, selection.y)))
- return;
-
- if (selection.y == 0)
+ selection= (ITextSelection) getSelection();
+ if (selection.getLength() == 0)
copyMarkedRegion(true);
else
- copyToClipboard(selection.x, selection.y, true, textWidget);
+ copyToClipboard(selection, true, textWidget);
- selection= textWidget.getSelectionRange();
- fireSelectionChanged(selection.x, selection.y);
+ Point range= textWidget.getSelectionRange();
+ fireSelectionChanged(range.x, range.y);
}
break;
case COPY:
if (redraws()) {
- selection= getSelectedRange();
- if (selection.y == 0)
+ selection= (ITextSelection) getSelection();
+ if (selection.getLength() == 0)
copyMarkedRegion(false);
else
- copyToClipboard(selection.x, selection.y, false, textWidget);
+ copyToClipboard(selection, false, textWidget);
}
break;
@@ -1478,15 +1480,15 @@
if (redraws()) {
try {
- selection= getSelectedRange();
+ selection= (ITextSelection) getSelection();
Point widgetSelection= textWidget.getSelectionRange();
- if (selection.y == 0 || selection.y == widgetSelection.y)
+ if (selection.getLength() == widgetSelection.y)
getTextWidget().invokeAction(ST.DELETE_NEXT);
else
- deleteTextRange(selection.x, selection.y, textWidget);
+ deleteSelection(selection, textWidget);
- selection= textWidget.getSelectionRange();
- fireSelectionChanged(selection.x, selection.y);
+ Point range= textWidget.getSelectionRange();
+ fireSelectionChanged(range.x, range.y);
} catch (BadLocationException x) {
// ignore
@@ -1567,21 +1569,14 @@
protected void copyMarkedRegion(boolean delete) {
IRegion markedRegion= getMarkedRegion();
if (markedRegion != null)
- copyToClipboard(markedRegion.getOffset(), markedRegion.getLength(), delete, getTextWidget());
+ copyToClipboard(new TextSelection(getDocument(), markedRegion.getOffset(), markedRegion.getLength()), delete, getTextWidget());
}
- private void copyToClipboard(int offset, int length, boolean delete, StyledText textWidget) {
+ private void copyToClipboard(ITextSelection selection, boolean delete, StyledText textWidget) {
- String copyText= null;
-
- try {
- IDocument document= getDocument();
- copyText= document.get(offset, length);
- } catch (BadLocationException ex) {
- // XXX: should log here, but JFace Text has no Log
- // As a fallback solution let the widget handle this
+ String copyText= selection.getText();
+ if (copyText == null) // selection.getText failed - backup using widget
textWidget.copy();
- }
if (copyText != null && copyText.equals(textWidget.getSelectionText())) {
/*
@@ -1616,18 +1611,23 @@
if (delete) {
try {
- deleteTextRange(offset, length, textWidget);
+ deleteSelection(selection, textWidget);
} catch (BadLocationException x) {
// XXX: should log here, but JFace Text has no Log
}
}
}
- private void deleteTextRange(int offset, int length, StyledText textWidget) throws BadLocationException {
- getDocument().replace(offset, length, ""); //$NON-NLS-1$
- int widgetCaret= modelOffset2WidgetOffset(offset);
- if (widgetCaret > -1)
- textWidget.setSelection(widgetCaret);
+ /**
+ * Deletes the selection and sets the caret before the deleted range.
+ *
+ * @param selection the selection to delete
+ * @param textWidget the widget
+ * @throws BadLocationException on document access failure
+ * @since 3.5
+ */
+ private void deleteSelection(ITextSelection selection, StyledText textWidget) throws BadLocationException {
+ new SelectionProcessor(this).doDelete(selection);
}
/**
Index: src/org/eclipse/jface/internal/text/SelectionProcessor.java
===================================================================
RCS file: src/org/eclipse/jface/internal/text/SelectionProcessor.java
diff -N src/org/eclipse/jface/internal/text/SelectionProcessor.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/internal/text/SelectionProcessor.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,540 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Avaloq Evolution AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tom Eicher (Avaloq Evolution AG) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.internal.text;
+
+import java.util.Arrays;
+
+import org.eclipse.core.runtime.Assert;
+
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BlockTextSelection;
+import org.eclipse.jface.text.IBlockTextSelection;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.IRewriteTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.text.TextUtilities;
+
+/**
+ * Processes {@link ITextSelection}s.
+ *
+ * @since 3.5
+ */
+public final class SelectionProcessor {
+ private static class Implementation {
+ TextEdit replace(ISelection selection, String replacement) throws BadLocationException {
+ return new MultiTextEdit();
+ }
+
+ String getText(ISelection selection) throws BadLocationException {
+ return ""; //$NON-NLS-1$
+ }
+
+ boolean isEmpty(ISelection selection) throws BadLocationException {
+ return selection.isEmpty();
+ }
+
+ boolean isMultiline(ISelection selection) {
+ return false;
+ }
+
+ TextEdit delete(ISelection selection) throws BadLocationException {
+ return replace(selection, ""); //$NON-NLS-1$
+ }
+
+ TextEdit backspace(ISelection selection) throws BadLocationException {
+ return replace(selection, ""); //$NON-NLS-1$
+ }
+
+ ISelection makeEmpty(ISelection selection) throws BadLocationException {
+ return selection;
+ }
+
+ IRegion[] getRanges(ISelection selection) throws BadLocationException {
+ return new IRegion[0];
+ }
+ }
+
+ private final Implementation NULL_IMPLEMENTATION= new Implementation();
+
+ private final Implementation RANGE_IMPLEMENTATION= new Implementation() {
+ TextEdit replace(ISelection selection, String replacement) {
+ ITextSelection ts= (ITextSelection)selection;
+ return new ReplaceEdit(ts.getOffset(), ts.getLength(), replacement);
+ }
+
+ String getText(ISelection selection) {
+ ITextSelection ts= (ITextSelection)selection;
+ return ts.getText();
+ }
+
+ boolean isEmpty(ISelection selection) {
+ ITextSelection ts= (ITextSelection)selection;
+ return ts.getLength() == 0;
+ }
+
+ boolean isMultiline(ISelection selection) {
+ ITextSelection ts= (ITextSelection)selection;
+ return ts.getEndLine() > ts.getStartLine();
+ }
+
+ TextEdit delete(ISelection selection) {
+ ITextSelection ts= (ITextSelection)selection;
+ if (isEmpty(selection))
+ return new DeleteEdit(ts.getOffset(), 1);
+ return new DeleteEdit(ts.getOffset(), ts.getLength());
+ }
+
+ TextEdit backspace(ISelection selection) throws BadLocationException {
+ ITextSelection ts= (ITextSelection)selection;
+ if (isEmpty(selection))
+ return new DeleteEdit(ts.getOffset() - 1, 1);
+ return new DeleteEdit(ts.getOffset(), ts.getLength());
+ }
+
+ ISelection makeEmpty(ISelection selection) {
+ ITextSelection ts= (ITextSelection)selection;
+ return new TextSelection(fDocument, ts.getOffset(), 0);
+ }
+
+ IRegion[] getRanges(ISelection selection) {
+ ITextSelection ts= (ITextSelection)selection;
+ return new IRegion[] { new Region(ts.getOffset(), ts.getLength()) };
+ }
+ };
+
+ private final Implementation COLUMN_IMPLEMENTATION= new Implementation() {
+ TextEdit replace(ISelection selection, String replacement) throws BadLocationException {
+ try {
+ MultiTextEdit root;
+ IBlockTextSelection cts= (IBlockTextSelection)selection;
+ int startLine= cts.getStartLine();
+ int endLine= cts.getEndLine();
+ int startColumn= cts.getStartColumn();
+ int endColumn= cts.getEndColumn();
+ int visualStartColumn= computeVisualColumn(startLine, startColumn);
+ int visualEndColumn= computeVisualColumn(endLine, endColumn);
+ root= new MultiTextEdit();
+ String[] delimiters= fDocument.getLegalLineDelimiters();
+
+ int lastDelim= 0;
+ for (int line= startLine; line <= endLine; line++) {
+ String string;
+ if (lastDelim == -1) {
+ string= ""; //$NON-NLS-1$
+ } else {
+ int[] index= TextUtilities.indexOf(delimiters, replacement, lastDelim);
+ if (index[0] == -1) {
+ string= replacement.substring(lastDelim);
+ lastDelim= -1;
+ } else {
+ string= replacement.substring(lastDelim, index[0]);
+ lastDelim= index[0] + delimiters[index[1]].length();
+ }
+ }
+ TextEdit replace= createReplaceEdit(cts, line, visualStartColumn, visualEndColumn, string);
+ root.addChild(replace);
+ }
+ while (lastDelim != -1) {
+ // more stuff to insert
+ String string;
+ int[] index= TextUtilities.indexOf(delimiters, replacement, lastDelim);
+ if (index[0] == -1) {
+ string= replacement.substring(lastDelim);
+ lastDelim= -1;
+ } else {
+ string= replacement.substring(lastDelim, index[0]);
+ lastDelim= index[0] + delimiters[index[1]].length();
+ }
+ endLine++;
+ TextEdit edit;
+ if (endLine < fDocument.getNumberOfLines()) {
+ edit= createReplaceEdit(cts, endLine, visualStartColumn, visualEndColumn, string);
+ } else {
+ // insertion reaches beyond the last line
+ int insertLocation= root.getExclusiveEnd();
+ int spaces= visualStartColumn;
+ char[] array= new char[spaces];
+ Arrays.fill(array, ' ');
+ string= fDocument.getLegalLineDelimiters()[0] + String.valueOf(array) + string;
+ edit= new InsertEdit(insertLocation, string);
+ insertLocation+= string.length();
+ }
+ root.addChild(edit);
+ }
+ return root;
+ } catch (MalformedTreeException x) {
+ Assert.isTrue(false);
+ return null;
+ }
+ }
+
+ String getText(ISelection selection) throws BadLocationException {
+ IBlockTextSelection cts= (IBlockTextSelection)selection;
+ StringBuffer buf= new StringBuffer(cts.getLength());
+ int startLine= cts.getStartLine();
+ int endLine= cts.getEndLine();
+ int startColumn= cts.getStartColumn();
+ int endColumn= cts.getEndColumn();
+ int visualStartColumn= computeVisualColumn(startLine, startColumn);
+ int visualEndColumn= computeVisualColumn(endLine, endColumn);
+
+ for (int line= startLine; line <= endLine; line++) {
+ appendColumnRange(buf, line, visualStartColumn, visualEndColumn);
+ if (line != endLine)
+ buf.append(fDocument.getLineDelimiter(line));
+ }
+
+ return buf.toString();
+ }
+
+ boolean isEmpty(ISelection selection) throws BadLocationException {
+ IBlockTextSelection cts= (IBlockTextSelection)selection;
+ int startLine= cts.getStartLine();
+ int endLine= cts.getEndLine();
+ int startColumn= cts.getStartColumn();
+ int endColumn= cts.getEndColumn();
+ int visualStartColumn= computeVisualColumn(startLine, startColumn);
+ int visualEndColumn= computeVisualColumn(endLine, endColumn);
+ return visualEndColumn == visualStartColumn;
+ }
+
+ boolean isMultiline(ISelection selection) {
+ ITextSelection ts= (ITextSelection)selection;
+ return ts.getEndLine() > ts.getStartLine();
+ }
+
+ TextEdit delete(ISelection selection) throws BadLocationException {
+ if (isEmpty(selection)) {
+ IBlockTextSelection cts= (IBlockTextSelection)selection;
+ selection= new BlockTextSelection(fDocument, cts.getStartLine(), cts.getStartColumn(), cts.getEndLine(), cts.getEndColumn() + 1, fTabWidth);
+ }
+ return replace(selection, ""); //$NON-NLS-1$
+ }
+
+ TextEdit backspace(ISelection selection) throws BadLocationException {
+ IBlockTextSelection cts= (IBlockTextSelection)selection;
+ if (isEmpty(selection) && cts.getStartColumn() > 0) {
+ selection= new BlockTextSelection(fDocument, cts.getStartLine(), cts.getStartColumn() - 1, cts.getEndLine(), cts.getEndColumn(), fTabWidth);
+ }
+ return replace(selection, ""); //$NON-NLS-1$
+ }
+
+ ISelection makeEmpty(ISelection selection) throws BadLocationException {
+ IBlockTextSelection cts= (IBlockTextSelection)selection;
+ int startLine= cts.getStartLine();
+ int startColumn= cts.getStartColumn();
+ int endLine= cts.getEndLine();
+ int endColumn= computeCharacterColumn(cts.getEndLine(), computeVisualColumn(startLine, startColumn));
+ return new BlockTextSelection(fDocument, startLine, startColumn, endLine, endColumn, fTabWidth);
+ }
+
+ IRegion[] getRanges(ISelection selection) throws BadLocationException {
+ IBlockTextSelection cts= (IBlockTextSelection)selection;
+ final int startLine= cts.getStartLine();
+ final int endLine= cts.getEndLine();
+ int visualStartColumn= computeVisualColumn(startLine, cts.getStartColumn());
+ int visualEndColumn= computeVisualColumn(endLine, cts.getEndColumn());
+ IRegion[] ranges= new IRegion[endLine - startLine + 1];
+
+ for (int line= startLine; line <= endLine; line++) {
+ int startColumn= computeCharacterColumn(line, visualStartColumn);
+ int endColumn= computeCharacterColumn(line, visualEndColumn);
+ IRegion lineInfo= fDocument.getLineInformation(line);
+ int lineEnd= lineInfo.getLength();
+ startColumn= Math.min(startColumn, lineEnd);
+ endColumn= Math.min(endColumn, lineEnd);
+ ranges[line - startLine]= new Region(lineInfo.getOffset() + startColumn, endColumn - startColumn);
+ }
+
+ return ranges;
+ }
+
+ private TextEdit createReplaceEdit(IBlockTextSelection cts, int line, int visualStartColumn, int visualEndColumn, String replacement) throws BadLocationException {
+ IRegion info= fDocument.getLineInformation(line);
+ int lineLength= info.getLength();
+ String content= fDocument.get(info.getOffset(), lineLength);
+ int startColumn= -1;
+ int endColumn= -1;
+ int visual= 0;
+ for (int offset= 0; offset < lineLength; offset++) {
+ if (startColumn == -1 && visual >= visualStartColumn)
+ startColumn= offset;
+ if (visual == visualEndColumn) {
+ endColumn= offset;
+ break;
+ }
+ if (content.charAt(offset) == '\t')
+ visual+= fTabWidth - visual % fTabWidth;
+ else
+ visual++;
+ }
+ if (startColumn == -1) {
+ boolean materializeVirtualSpace= replacement.length() != 0;
+ if (materializeVirtualSpace) {
+ int spaces= visualStartColumn - visual;
+ char[] array= new char[spaces];
+ Arrays.fill(array, ' ');
+ return new InsertEdit(info.getOffset() + lineLength, String.valueOf(array) + replacement);
+ }
+ return new MultiTextEdit();
+ }
+ if (endColumn == -1)
+ endColumn= lineLength;
+ return new ReplaceEdit(info.getOffset() + startColumn, endColumn - startColumn, replacement);
+ }
+
+ private void appendColumnRange(StringBuffer buf, int line, int visualStartColumn, int visualEndColumn) throws BadLocationException {
+ IRegion info= fDocument.getLineInformation(line);
+ int lineLength= info.getLength();
+ String content= fDocument.get(info.getOffset(), lineLength);
+ int startColumn= -1;
+ int endColumn= -1;
+ int visual= 0;
+ for (int offset= 0; offset < lineLength; offset++) {
+ if (startColumn == -1 && visual >= visualStartColumn)
+ startColumn= offset;
+ if (visual == visualEndColumn) {
+ endColumn= offset;
+ break;
+ }
+ if (content.charAt(offset) == '\t')
+ visual+= fTabWidth - visual % fTabWidth;
+ else
+ visual++;
+ }
+ if (startColumn != -1)
+ buf.append(content.substring(startColumn, endColumn == -1 ? lineLength : endColumn));
+ if (endColumn == -1) {
+ int spaces= visualEndColumn - Math.max(visual, visualStartColumn);
+ for (int i= 0; i < spaces; i++)
+ buf.append(' ');
+ }
+ }
+
+ private int computeVisualColumn(final int line, final int column) throws BadLocationException {
+ int visualColumn= 0;
+ IRegion info= fDocument.getLineInformation(line);
+ int lineEnd= info.getLength();
+ int to= Math.min(lineEnd, column);
+ String content= fDocument.get(info.getOffset(), info.getLength());
+ for (int offset= 0; offset < to; offset++) {
+ if (content.charAt(offset) == '\t')
+ visualColumn+= fTabWidth - visualColumn % fTabWidth;
+ else
+ visualColumn++;
+ }
+ if (column > lineEnd) {
+ visualColumn+= column - lineEnd; // virtual spaces
+ }
+ return visualColumn;
+ }
+
+ private int computeCharacterColumn(int line, int visualColumn) throws BadLocationException {
+ IRegion info= fDocument.getLineInformation(line);
+ int lineLength= info.getLength();
+ String content= fDocument.get(info.getOffset(), lineLength);
+ int column= -1;
+ int visual= 0;
+ for (int offset= 0; offset < lineLength; offset++) {
+ if (column == -1 && visual >= visualColumn)
+ return offset;
+ if (content.charAt(offset) == '\t')
+ visual+= fTabWidth - visual % fTabWidth;
+ else
+ visual++;
+ }
+ return lineLength + visualColumn - visual;
+ }
+ };
+
+ private final IDocument fDocument;
+
+ private final int fTabWidth;
+
+ private IRewriteTarget fRewriteTarget;
+
+ private ISelectionProvider fSelectionProvider;
+
+ /**
+ * Creates a new processor on the given viewer.
+ *
+ * @param viewer the viewer
+ */
+ public SelectionProcessor(ITextViewer viewer) {
+ this(viewer.getDocument(), viewer.getTextWidget().getTabs());
+ if (viewer instanceof ITextViewerExtension) {
+ ITextViewerExtension ext= (ITextViewerExtension)viewer;
+ fRewriteTarget= ext.getRewriteTarget();
+ }
+ fSelectionProvider= viewer.getSelectionProvider();
+ }
+
+ /**
+ * Creates a new processor on the given document and using the given tab width.
+ *
+ * @param document the document
+ * @param tabWidth the tabulator width in space equivalents
+ */
+ public SelectionProcessor(IDocument document, int tabWidth) {
+ Assert.isNotNull(document);
+ Assert.isTrue(tabWidth > 0);
+ fDocument= document;
+ fTabWidth= tabWidth;
+ }
+
+ /**
+ * Returns a text edit describing the text modification that would be executed if the delete key
+ * was pressed on the given selection.
+ *
+ * @param selection the selection to delete
+ * @return a text edit describing the operation needed to delete selection
+ * @throws BadLocationException if computing the edit failed
+ */
+ public TextEdit delete(ISelection selection) throws BadLocationException {
+ return getImplementation(selection).delete(selection);
+ }
+
+ /**
+ * Returns a text edit describing the text modification that would be executed if the backspace
+ * key was pressed on the given selection.
+ *
+ * @param selection the selection to delete
+ * @return a text edit describing the operation needed to delete selection
+ * @throws BadLocationException if computing the edit failed
+ */
+ public TextEdit backspace(ISelection selection) throws BadLocationException {
+ return getImplementation(selection).backspace(selection);
+ }
+
+ /**
+ * Returns a text edit describing the text modification that would be executed if the given
+ * selection was replaced by replacement
.
+ *
+ * @param selection the selection to replace
+ * @param replacement the replacement text
+ * @return a text edit describing the operation needed to replace selection
+ * @throws BadLocationException if computing the edit failed
+ */
+ public TextEdit replace(ISelection selection, String replacement) throws BadLocationException {
+ return getImplementation(selection).replace(selection, replacement);
+ }
+
+ /**
+ * Returns the text covered by selection
+ *
+ * @param selection the selection
+ * @return the text covered by selection
+ * @throws BadLocationException if computing the edit failed
+ */
+ public String getText(ISelection selection) throws BadLocationException {
+ return getImplementation(selection).getText(selection);
+ }
+
+ /**
+ * Returns true
if the text covered by selection
does not contain any
+ * characters. Note the difference to {@link ITextSelection#isEmpty()}, which returns
+ * true
only for invalid selections.
+ *
+ * @param selection the selection
+ * @return true
if selection
does not contain any text,
+ * false
otherwise
+ * @throws BadLocationException if accessing the document failed
+ */
+ public boolean isEmpty(ISelection selection) throws BadLocationException {
+ return getImplementation(selection).isEmpty(selection);
+ }
+
+ /**
+ * Returns true
if selection
covers text on two or more lines,
+ * false
otherwise.
+ *
+ * @param selection the selection
+ * @return true
if selection
covers text on two or more lines,
+ * false
otherwise
+ */
+ public boolean isMultiline(ISelection selection) {
+ return getImplementation(selection).isMultiline(selection);
+ }
+
+ /**
+ * Returns a selection similar to selection
but {@linkplain #isEmpty(ISelection)
+ * empty}. Typically, the selection is reduced to its left-most offset.
+ *
+ * @param selection the selection
+ * @return an empty variant of selection
+ * @throws BadLocationException if accessing the document failed
+ */
+ public ISelection makeEmpty(ISelection selection) throws BadLocationException {
+ return getImplementation(selection).makeEmpty(selection);
+ }
+
+ /**
+ * Convenience method that applies the edit returned from {@link #delete(ISelection)} to the
+ * underlying document.
+ *
+ * @param selection the selection to delete
+ * @throws BadLocationException if accessing the document failed
+ */
+ public void doDelete(ISelection selection) throws BadLocationException {
+ TextEdit edit= delete(selection);
+ ISelection empty= makeEmpty(selection);
+ boolean complex= edit.hasChildren();
+ if (complex && fRewriteTarget != null)
+ fRewriteTarget.beginCompoundChange();
+ edit.apply(fDocument, TextEdit.UPDATE_REGIONS);
+ if (fSelectionProvider != null)
+ fSelectionProvider.setSelection(empty);
+ if (complex && fRewriteTarget != null)
+ fRewriteTarget.endCompoundChange();
+
+ }
+
+ /**
+ * Returns the text regions covered by the given selection.
+ *
+ * @param selection the selection
+ * @return the text regions corresponding to selection
+ * @throws BadLocationException if accessing the document failed
+ */
+ public IRegion[] getRanges(ISelection selection) throws BadLocationException {
+ return getImplementation(selection).getRanges(selection);
+ }
+
+ /**
+ * Returns the implementation.
+ *
+ * @param selection the selection
+ * @return the corresponding processor implementation
+ */
+ private Implementation getImplementation(ISelection selection) {
+ if (selection instanceof IBlockTextSelection)
+ return COLUMN_IMPLEMENTATION;
+ else if (selection instanceof ITextSelection)
+ return RANGE_IMPLEMENTATION;
+ else
+ return NULL_IMPLEMENTATION;
+ }
+}
Index: src/org/eclipse/jface/text/BlockTextSelection.java
===================================================================
RCS file: src/org/eclipse/jface/text/BlockTextSelection.java
diff -N src/org/eclipse/jface/text/BlockTextSelection.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/text/BlockTextSelection.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Avaloq Evolution AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tom Eicher (Avaloq Evolution AG) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.text;
+
+import org.eclipse.core.runtime.Assert;
+
+import org.eclipse.jface.internal.text.SelectionProcessor;
+
+
+/**
+ * Standard implementation of {@link org.eclipse.jface.text.IBlockTextSelection}.
+ *
+ * @since 3.5
+ */
+public class BlockTextSelection extends TextSelection implements IBlockTextSelection {
+
+ /** The start line. */
+ private final int fStartLine;
+ /** The start column. */
+ private final int fStartColumn;
+ /** The end line. */
+ private final int fEndLine;
+ /** The end column. */
+ private final int fEndColumn;
+ /** The tabulator width used to compute visual columns from character offsets. */
+ private final int fTabWidth;
+
+ /**
+ * Creates a column selection for the given lines and columns.
+ *
+ * @param document the document that this selection refers to
+ * @param startLine the start line
+ * @param startColumn the possibly virtual start column, measured in characters from the start
+ * of startLine
+ * @param endLine the inclusive end line
+ * @param endColumn the exclusive and possibly virtual end column, measured in characters from
+ * the start of endLine
+ * @param tabWidth the tabulator width used to compute the visual offsets from character offsets
+ */
+ public BlockTextSelection(IDocument document, int startLine, int startColumn, int endLine, int endColumn, int tabWidth) {
+ super(document, computeOffset(document, startLine, startColumn), computeOffset(document, endLine, endColumn) - computeOffset(document, startLine, startColumn));
+ Assert.isLegal(startLine >= 0);
+ Assert.isLegal(startColumn >= 0);
+ Assert.isLegal(endLine >= startLine);
+ Assert.isLegal(endColumn >= 0);
+ Assert.isLegal(tabWidth >= 0);
+ fStartLine= startLine;
+ fStartColumn= startColumn;
+ fEndLine= endLine;
+ fEndColumn= endColumn;
+ fTabWidth= tabWidth > 0 ? tabWidth : 8; // seems to be the default when StyledText.getTabs returns 0
+ }
+
+ /**
+ * Returns the document offset for a given tuple of line and column count. If the column count
+ * points beyond the end of the line, the end of the line is returned (virtual location). If the
+ * line points beyond the number of lines, the end of the document is returned; if the line is
+ * < zero, 0 is returned.
+ *
+ * @param document the document to get line information from
+ * @param line the line in the document, may be greater than the line count
+ * @param column the offset in the given line, may be greater than the line length
+ * @return the document offset corresponding to the line and column counts
+ */
+ private static int computeOffset(IDocument document, int line, int column) {
+ try {
+ IRegion lineInfo= document.getLineInformation(line);
+ int offsetInLine= Math.min(column, lineInfo.getLength());
+ return lineInfo.getOffset() + offsetInLine;
+ } catch (BadLocationException x) {
+ if (line < 0)
+ return 0;
+ return document.getLength();
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.TextSelection#getStartLine()
+ */
+ public int getStartLine() {
+ return fStartLine;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IColumnTextSelection#getStartColumn()
+ */
+ public int getStartColumn() {
+ return fStartColumn;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.TextSelection#getEndLine()
+ */
+ public int getEndLine() {
+ return fEndLine;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IColumnTextSelection#getEndColumn()
+ */
+ public int getEndColumn() {
+ return fEndColumn;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.TextSelection#getText()
+ */
+ public String getText() {
+ try {
+ return new SelectionProcessor(fDocument, fTabWidth).getText(this);
+ } catch (BadLocationException x) {
+ return super.getText();
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.TextSelection#hashCode()
+ */
+ public int hashCode() {
+ final int prime= 31;
+ int result= super.hashCode();
+ result= prime * result + fEndColumn;
+ result= prime * result + fEndLine;
+ result= prime * result + fStartColumn;
+ result= prime * result + fStartLine;
+ return result;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.TextSelection#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ final BlockTextSelection other= (BlockTextSelection) obj;
+ if (fEndColumn != other.fEndColumn)
+ return false;
+ if (fEndLine != other.fEndLine)
+ return false;
+ if (fStartColumn != other.fStartColumn)
+ return false;
+ if (fStartLine != other.fStartLine)
+ return false;
+ return true;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IColumnTextSelection#getRegions()
+ */
+ public IRegion[] getRegions() {
+ try {
+ return new SelectionProcessor(fDocument, fTabWidth).getRanges(this);
+ } catch (BadLocationException x) {
+ return new IRegion[] {new Region(getOffset(), getLength())};
+ }
+ }
+}
Index: src/org/eclipse/jface/text/IBlockTextSelection.java
===================================================================
RCS file: src/org/eclipse/jface/text/IBlockTextSelection.java
diff -N src/org/eclipse/jface/text/IBlockTextSelection.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/text/IBlockTextSelection.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Avaloq Evolution AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tom Eicher (Avaloq Evolution AG) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.text;
+
+/**
+ * A rectangular selection in a text document. A column selection spans the visually identical range
+ * of columns on a contiguous range of lines. The character count of the same visually perceived
+ * column may not be equal for two different lines, therefore computing the set of disjunct
+ * character ranges covered by a column selection is influenced by the used font and tabulator
+ * width. Using column selections with proportional fonts may render unexpected results.
+ * + * The {@linkplain ITextSelection#getOffset() offset} and + * {@linkplain ITextSelection#getLength() length} of an {@link IBlockTextSelection} refer to the + * smallest non-virtual range that comprises the entire rectangular selection. + *
+ *+ * Clients may implement this interface or use the default implementation provided by + * {@link org.eclipse.jface.text.BlockTextSelection}. + *
+ * + * @see org.eclipse.jface.text.BlockTextSelection + * @since 3.5 + */ +public interface IBlockTextSelection extends ITextSelection { + /** + * Returns the column on the {@linkplain ITextSelection#getStartLine() start line} at which the + * selection starts. The returned column is a character count measured from the start of the + * line. It may be larger than the length of the line, in which case it is a virtual offset. + * + * @return the start column measured from the line start + */ + int getStartColumn(); + /** + * Returns the exclusive column on the {@linkplain ITextSelection#getEndLine() end line} at which the + * selection ends. The returned column is a character count measured from the start of the + * line. It may be larger than the length of the line, in which case it is a virtual offset. + * + * @return the end column measured from the line start + */ + int getEndColumn(); + /** + * {@inheritDoc} + *+ * The returned text does not necessarily correspond to the total + * {@linkplain ITextSelection#getOffset() offset} and {@link ITextSelection#getLength() length}, + * as only the text within the selected columns is returned. + *
+ * Any virtual spaces beyond the end of the selected lines are + * materialized and returned as text. + *
+ * + * @see org.eclipse.jface.text.ITextSelection#getText() + */ + String getText(); + /** + * Returns a non-empty array containing the selected text range for each line covered by the + * selection. + * + * @return an array containing a the covered text range for each line covered by the receiver + */ + IRegion[] getRegions(); +}