1 11 package org.eclipse.ui.texteditor; 12 13 import java.util.ResourceBundle ; 14 15 import org.eclipse.swt.custom.StyledText; 16 import org.eclipse.swt.graphics.Point; 17 import org.eclipse.swt.widgets.Event; 18 19 import org.eclipse.core.runtime.Assert; 20 21 import org.eclipse.jface.text.BadLocationException; 22 import org.eclipse.jface.text.IDocument; 23 import org.eclipse.jface.text.IRegion; 24 import org.eclipse.jface.text.IRewriteTarget; 25 import org.eclipse.jface.text.ITextSelection; 26 import org.eclipse.jface.text.ITextViewer; 27 import org.eclipse.jface.text.ITextViewerExtension5; 28 import org.eclipse.jface.text.TextSelection; 29 import org.eclipse.jface.text.TextUtilities; 30 import org.eclipse.jface.text.source.ISourceViewer; 31 32 import org.eclipse.ui.internal.texteditor.CompoundEditExitStrategy; 33 import org.eclipse.ui.internal.texteditor.ICompoundEditListener; 34 35 39 public class MoveLinesAction extends TextEditorAction { 40 41 42 43 44 private final boolean fUpwards; 45 46 private final boolean fCopy; 47 48 private final AbstractTextEditor fEditor; 49 50 51 52 56 private final CompoundEditExitStrategy fStrategy; 57 58 59 60 64 private boolean fAddDelimiter; 65 66 private boolean fEditInProgress= false; 67 68 82 public MoveLinesAction(ResourceBundle bundle, String prefix, AbstractTextEditor editor, boolean upwards, boolean copy) { 83 super(bundle, prefix, editor); 84 fEditor= editor; 85 fUpwards= upwards; 86 fCopy= copy; 87 String [] commandIds= copy ? new String [] {ITextEditorActionDefinitionIds.COPY_LINES_UP, ITextEditorActionDefinitionIds.COPY_LINES_DOWN } : new String [] {ITextEditorActionDefinitionIds.MOVE_LINES_UP, ITextEditorActionDefinitionIds.MOVE_LINES_DOWN }; 88 fStrategy= new CompoundEditExitStrategy(commandIds); 89 fStrategy.addCompoundListener(new ICompoundEditListener() { 90 public void endCompoundEdit() { 91 MoveLinesAction.this.endCompoundEdit(); 92 } 93 }); 94 update(); 95 } 96 97 100 private void beginCompoundEdit() { 101 if (fEditInProgress || fEditor == null) 102 return; 103 104 fEditInProgress= true; 105 106 fStrategy.arm(fEditor.getSourceViewer()); 107 108 IRewriteTarget target= (IRewriteTarget)fEditor.getAdapter(IRewriteTarget.class); 109 if (target != null) { 110 target.beginCompoundChange(); 111 } 112 } 113 114 123 private boolean containedByVisibleRegion(ITextSelection selection, ISourceViewer viewer) { 124 int min= selection.getOffset(); 125 int max= min + selection.getLength(); 126 IDocument document= viewer.getDocument(); 127 128 IRegion visible; 129 if (viewer instanceof ITextViewerExtension5) 130 visible= ((ITextViewerExtension5) viewer).getModelCoverage(); 131 else 132 visible= viewer.getVisibleRegion(); 133 134 int visOffset= visible.getOffset(); 135 try { 136 if (visOffset > min) { 137 if (document.getLineOfOffset(visOffset) != selection.getStartLine()) 138 return false; 139 if (!isWhitespace(document.get(min, visOffset - min))) { 140 showStatus(); 141 return false; 142 } 143 } 144 int visEnd= visOffset + visible.getLength(); 145 if (visEnd < max) { 146 if (document.getLineOfOffset(visEnd) != selection.getEndLine()) 147 return false; 148 if (!isWhitespace(document.get(visEnd, max - visEnd))) { 149 showStatus(); 150 return false; 151 } 152 } 153 return true; 154 } catch (BadLocationException e) { 155 } 156 return false; 157 } 158 159 162 private void endCompoundEdit() { 163 if (!fEditInProgress || fEditor == null) 164 return; 165 166 IRewriteTarget target= (IRewriteTarget)fEditor.getAdapter(IRewriteTarget.class); 167 if (target != null) { 168 target.endCompoundChange(); 169 } 170 171 fEditInProgress= false; 172 } 173 174 193 private ITextSelection getMovingSelection(IDocument document, ITextSelection selection, ISourceViewer viewer) throws BadLocationException { 194 int low= document.getLineOffset(selection.getStartLine()); 195 int endLine= selection.getEndLine(); 196 int high= document.getLineOffset(endLine) + document.getLineLength(endLine); 197 198 String delim= document.getLineDelimiter(endLine); 200 if (delim != null) 201 high -= delim.length(); 202 203 if (delim != null && document.getLineLength(endLine) == delim.length()) 207 fAddDelimiter= true; 208 else 209 fAddDelimiter= false; 210 211 return new TextSelection(document, low, high - low); 212 } 213 214 223 private ITextSelection getSkippedLine(IDocument document, ITextSelection selection) { 224 int skippedLineN= (fUpwards ? selection.getStartLine() - 1 : selection.getEndLine() + 1); 225 if (skippedLineN > document.getNumberOfLines() || (!fCopy && (skippedLineN < 0 || skippedLineN == document.getNumberOfLines()))) 226 return null; 227 try { 228 if (fCopy && skippedLineN == -1) 229 skippedLineN= 0; 230 IRegion line= document.getLineInformation(skippedLineN); 231 return new TextSelection(document, line.getOffset(), line.getLength()); 232 } catch (BadLocationException e) { 233 return null; 235 } 236 } 237 238 245 private boolean isWhitespace(String string) { 246 return string == null ? true : string.trim().length() == 0; 247 } 248 249 252 public void runWithEvent(Event event) { 253 254 if (fEditor == null) 256 return; 257 258 if (!validateEditorInputState()) 259 return; 260 261 ISourceViewer viewer= fEditor.getSourceViewer(); 262 if (viewer == null) 263 return; 264 265 IDocument document= viewer.getDocument(); 266 if (document == null) 267 return; 268 269 StyledText widget= viewer.getTextWidget(); 270 if (widget == null) 271 return; 272 273 Point p= viewer.getSelectedRange(); 275 if (p == null) 276 return; 277 278 ITextSelection sel= new TextSelection(document, p.x, p.y); 279 280 ITextSelection skippedLine= getSkippedLine(document, sel); 281 if (skippedLine == null) 282 return; 283 284 try { 285 286 ITextSelection movingArea= getMovingSelection(document, sel, viewer); 287 288 if (!containedByVisibleRegion(movingArea, viewer) || !containedByVisibleRegion(skippedLine, viewer)) 291 return; 292 293 String moving= movingArea.getText(); 295 String skipped= skippedLine.getText(); 296 if (moving == null || skipped == null || document.getLength() == 0) 297 return; 298 299 String delim; 300 String insertion; 301 int offset, deviation; 302 if (fUpwards) { 303 delim= document.getLineDelimiter(skippedLine.getEndLine()); 304 if (fCopy) { 305 delim= TextUtilities.getDefaultLineDelimiter(document); 306 insertion= moving + delim; 307 offset= movingArea.getOffset(); 308 deviation= 0; 309 } else { 310 Assert.isNotNull(delim); 311 insertion= moving + delim + skipped; 312 offset= skippedLine.getOffset(); 313 deviation= -skippedLine.getLength() - delim.length(); 314 } 315 } else { 316 delim= document.getLineDelimiter(movingArea.getEndLine()); 317 if (fCopy) { 318 if (delim == null) { 319 delim= TextUtilities.getDefaultLineDelimiter(document); 320 insertion= delim + moving; 321 } else { 322 insertion= moving + delim; 323 } 324 offset= skippedLine.getOffset(); 325 deviation= movingArea.getLength() + delim.length(); 326 } else { 327 Assert.isNotNull(delim); 328 insertion= skipped + delim + moving; 329 offset= movingArea.getOffset(); 330 deviation= skipped.length() + delim.length(); 331 } 332 } 333 334 beginCompoundEdit(); 336 if (fCopy) { 337 document.replace(offset, 0, insertion); 339 } else { 340 document.replace(offset, insertion.length(), insertion); 342 } 343 344 int selOffset= movingArea.getOffset() + deviation; 346 int selLength= movingArea.getLength() + (fAddDelimiter ? delim.length() : 0); 347 if (! (viewer instanceof ITextViewerExtension5)) 348 selLength= Math.min(selLength, viewer.getVisibleRegion().getOffset() + viewer.getVisibleRegion().getLength() - selOffset); 349 else { 350 } 352 selectAndReveal(viewer, selOffset, selLength); 353 } catch (BadLocationException x) { 354 return; 356 } 357 } 358 359 367 private void selectAndReveal(ITextViewer viewer, int offset, int length) { 368 viewer.setSelectedRange(offset + length, -length); 370 StyledText st= viewer.getTextWidget(); 372 if (st != null) 373 st.showSelection(); } 375 376 379 private void showStatus() { 380 IEditorStatusLine status= (IEditorStatusLine) fEditor.getAdapter(IEditorStatusLine.class); 381 if (status == null) 382 return; 383 status.setMessage(false, EditorMessages.Editor_MoveLines_IllegalMove_status, null); 384 } 385 386 389 public void update() { 390 super.update(); 391 392 if (isEnabled()) 393 setEnabled(canModifyEditor()); 394 395 } 396 } 397 | Popular Tags |