Source Code Cross Referenced for JavaMoveLinesAction.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » ui » javaeditor » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.internal.ui.javaeditor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2000, 2006 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.jdt.internal.ui.javaeditor;
011:
012:        import java.util.ResourceBundle;
013:
014:        import org.eclipse.core.runtime.Assert;
015:
016:        import org.eclipse.swt.custom.StyledText;
017:        import org.eclipse.swt.graphics.Point;
018:        import org.eclipse.swt.widgets.Event;
019:
020:        import org.eclipse.jface.text.BadLocationException;
021:        import org.eclipse.jface.text.IDocument;
022:        import org.eclipse.jface.text.IRegion;
023:        import org.eclipse.jface.text.IRewriteTarget;
024:        import org.eclipse.jface.text.ITextSelection;
025:        import org.eclipse.jface.text.ITextViewer;
026:        import org.eclipse.jface.text.ITextViewerExtension5;
027:        import org.eclipse.jface.text.Region;
028:        import org.eclipse.jface.text.TextSelection;
029:        import org.eclipse.jface.text.TextUtilities;
030:        import org.eclipse.jface.text.source.ILineRange;
031:        import org.eclipse.jface.text.source.ISourceViewer;
032:        import org.eclipse.jface.text.source.LineRange;
033:
034:        import org.eclipse.ui.IEditorInput;
035:        import org.eclipse.ui.texteditor.IEditorStatusLine;
036:        import org.eclipse.ui.texteditor.ITextEditor;
037:        import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
038:        import org.eclipse.ui.texteditor.TextEditorAction;
039:
040:        import org.eclipse.jdt.core.ICompilationUnit;
041:        import org.eclipse.jdt.core.IJavaProject;
042:
043:        import org.eclipse.jdt.internal.ui.JavaPlugin;
044:        import org.eclipse.jdt.internal.ui.javaeditor.IndentUtil.IndentResult;
045:
046:        /**
047:         * Action for moving selected lines in a Java editor.
048:         * @since 3.1
049:         */
050:        public class JavaMoveLinesAction extends TextEditorAction {
051:
052:            /**
053:             * State shared by the Move / Copy lines action quadruple.
054:             * @since 3.1
055:             */
056:            private static final class SharedState {
057:                /** The compilation unit editor that all four actions operate on. */
058:                public CompilationUnitEditor fEditor;
059:                /**
060:                 * The indent token shared by all four actions.
061:                 */
062:                public IndentResult fResult = null;
063:                /**
064:                 * Set to true before modifying the document, to false after.
065:                 */
066:                boolean fIsChanging = false;
067:
068:                /** <code>true</code> if a compound move / copy is going on. */
069:                private boolean fEditInProgress = false;
070:                /** The exit strategy that will detect the ending of a compound edit */
071:                private final CompoundEditExitStrategy fExitStrategy;
072:
073:                public SharedState(CompilationUnitEditor editor) {
074:                    fEditor = editor;
075:                    fExitStrategy = new CompoundEditExitStrategy(new String[] {
076:                            ITextEditorActionDefinitionIds.MOVE_LINES_UP,
077:                            ITextEditorActionDefinitionIds.MOVE_LINES_DOWN,
078:                            ITextEditorActionDefinitionIds.COPY_LINES_UP,
079:                            ITextEditorActionDefinitionIds.COPY_LINES_DOWN });
080:                    fExitStrategy
081:                            .addCompoundListener(new ICompoundEditListener() {
082:                                public void endCompoundEdit() {
083:                                    SharedState.this .endCompoundEdit();
084:                                }
085:                            });
086:                }
087:
088:                /**
089:                 * Ends the compound change.
090:                 */
091:                public void beginCompoundEdit() {
092:                    if (fEditInProgress || fEditor == null)
093:                        return;
094:
095:                    fEditInProgress = true;
096:
097:                    fExitStrategy.arm(fEditor.getViewer());
098:
099:                    IRewriteTarget target = (IRewriteTarget) fEditor
100:                            .getAdapter(IRewriteTarget.class);
101:                    if (target != null) {
102:                        target.beginCompoundChange();
103:                    }
104:                }
105:
106:                /**
107:                 * Ends the compound change.
108:                 */
109:                public void endCompoundEdit() {
110:                    if (!fEditInProgress || fEditor == null)
111:                        return;
112:
113:                    fExitStrategy.disarm();
114:
115:                    IRewriteTarget target = (IRewriteTarget) fEditor
116:                            .getAdapter(IRewriteTarget.class);
117:                    if (target != null) {
118:                        target.endCompoundChange();
119:                    }
120:
121:                    fResult = null;
122:                    fEditInProgress = false;
123:                }
124:            }
125:
126:            /* keys */
127:
128:            /** Key for status message upon illegal move. <p>Value {@value}</p> */
129:
130:            /* state variables - define what this action does */
131:
132:            /** <code>true</code> if lines are shifted upwards, <code>false</code> otherwise. */
133:            private final boolean fUpwards;
134:            /** <code>true</code> if lines are to be copied instead of moved. */
135:            private final boolean fCopy;
136:            /** The shared state of the move/copy action quadruple. */
137:            private final SharedState fSharedState;
138:
139:            /**
140:             * Creates the quadruple of move and copy actions. The returned array contains
141:             * the actions in the following order:
142:             * [0] move up
143:             * [1] move down
144:             * [2] copy up (duplicate)
145:             * [3] copy down (duplicate & select)
146:             * @param bundle the resource bundle
147:             * @param editor the editor
148:             * @return the quadruple of actions
149:             */
150:            public static JavaMoveLinesAction[] createMoveCopyActionSet(
151:                    ResourceBundle bundle, CompilationUnitEditor editor) {
152:                SharedState state = new SharedState(editor);
153:                JavaMoveLinesAction[] actions = new JavaMoveLinesAction[4];
154:                actions[0] = new JavaMoveLinesAction(bundle,
155:                        "Editor.MoveLinesUp.", true, false, state); //$NON-NLS-1$
156:                actions[1] = new JavaMoveLinesAction(bundle,
157:                        "Editor.MoveLinesDown.", false, false, state); //$NON-NLS-1$
158:                actions[2] = new JavaMoveLinesAction(bundle,
159:                        "Editor.CopyLineUp.", true, true, state); //$NON-NLS-1$
160:                actions[3] = new JavaMoveLinesAction(bundle,
161:                        "Editor.CopyLineDown.", false, true, state); //$NON-NLS-1$
162:                return actions;
163:            }
164:
165:            /*
166:             * @see org.eclipse.ui.texteditor.TextEditorAction#setEditor(org.eclipse.ui.texteditor.ITextEditor)
167:             */
168:            public void setEditor(ITextEditor editor) {
169:                Assert.isTrue(editor instanceof  CompilationUnitEditor);
170:                super .setEditor(editor);
171:                if (fSharedState != null)
172:                    fSharedState.fEditor = (CompilationUnitEditor) editor;
173:            }
174:
175:            /**
176:             * Creates and initializes the action for the given text editor.
177:             * The action configures its visual representation from the given resource
178:             * bundle.
179:             *
180:             * @param bundle the resource bundle
181:             * @param prefix a prefix to be prepended to the various resource keys
182:             *   (described in <code>ResourceAction</code> constructor), or  <code>null</code> if none
183:             * @param upwards <code>true</code>if the selected lines should be moved upwards,
184:             * <code>false</code> if downwards
185:             * @param copy if <code>true</code>, the action will copy lines instead of moving them
186:             * @param state the shared state
187:             * @see TextEditorAction#TextEditorAction(ResourceBundle, String, ITextEditor)
188:             */
189:            private JavaMoveLinesAction(ResourceBundle bundle, String prefix,
190:                    boolean upwards, boolean copy, SharedState state) {
191:                super (bundle, prefix, state.fEditor);
192:                fUpwards = upwards;
193:                fCopy = copy;
194:                fSharedState = state;
195:                update();
196:            }
197:
198:            /**
199:             * Checks if <code>selection</code> is contained by the visible region of <code>viewer</code>.
200:             * As a special case, a selection is considered contained even if it extends over the visible
201:             * region, but the extension stays on a partially contained line and contains only white space.
202:             *
203:             * @param selection the selection to be checked
204:             * @param viewer the viewer displaying a visible region of <code>selection</code>'s document.
205:             * @return <code>true</code>, if <code>selection</code> is contained, <code>false</code> otherwise.
206:             */
207:            private boolean containedByVisibleRegion(ITextSelection selection,
208:                    ISourceViewer viewer) {
209:                int min = selection.getOffset();
210:                int max = min + selection.getLength();
211:                IDocument document = viewer.getDocument();
212:
213:                IRegion visible;
214:                if (viewer instanceof  ITextViewerExtension5)
215:                    visible = ((ITextViewerExtension5) viewer)
216:                            .getModelCoverage();
217:                else
218:                    visible = viewer.getVisibleRegion();
219:
220:                int visOffset = visible.getOffset();
221:                try {
222:                    if (visOffset > min) {
223:                        if (document.getLineOfOffset(visOffset) != selection
224:                                .getStartLine())
225:                            return false;
226:                        if (!isWhitespace(document.get(min, visOffset - min))) {
227:                            showStatus();
228:                            return false;
229:                        }
230:                    }
231:                    int visEnd = visOffset + visible.getLength();
232:                    if (visEnd < max) {
233:                        if (document.getLineOfOffset(visEnd) != selection
234:                                .getEndLine())
235:                            return false;
236:                        if (!isWhitespace(document.get(visEnd, max - visEnd))) {
237:                            showStatus();
238:                            return false;
239:                        }
240:                    }
241:                    return true;
242:                } catch (BadLocationException e) {
243:                }
244:                return false;
245:            }
246:
247:            /**
248:             * Given a selection on a document, computes the lines fully or partially covered by
249:             * <code>selection</code>. A line in the document is considered covered if
250:             * <code>selection</code> comprises any characters on it, including the terminating delimiter.
251:             * <p>Note that the last line in a selection is not considered covered if the selection only
252:             * comprises the line delimiter at its beginning (that is considered part of the second last
253:             * line).
254:             * As a special case, if the selection is empty, a line is considered covered if the caret is
255:             * at any position in the line, including between the delimiter and the start of the line. The
256:             * line containing the delimiter is not considered covered in that case.
257:             * </p>
258:             *
259:             * @param document the document <code>selection</code> refers to
260:             * @param selection a selection on <code>document</code>
261:             * @param viewer the <code>ISourceViewer</code> displaying <code>document</code>
262:             * @return a selection describing the range of lines (partially) covered by
263:             * <code>selection</code>, without any terminating line delimiters
264:             * @throws BadLocationException if the selection is out of bounds (when the underlying document has changed during the call)
265:             */
266:            private ITextSelection getMovingSelection(IDocument document,
267:                    ITextSelection selection, ISourceViewer viewer)
268:                    throws BadLocationException {
269:                int low = document.getLineOffset(selection.getStartLine());
270:                int endLine = selection.getEndLine();
271:                int high = document.getLineOffset(endLine)
272:                        + document.getLineLength(endLine);
273:
274:                // get everything up to last line without its delimiter
275:                String delim = document.getLineDelimiter(endLine);
276:                if (delim != null)
277:                    high -= delim.length();
278:
279:                return new TextSelection(document, low, high - low);
280:            }
281:
282:            /**
283:             * Computes the region of the skipped line given the text block to be moved. If
284:             * <code>fUpwards</code> is <code>true</code>, the line above <code>selection</code>
285:             * is selected, otherwise the line below.
286:             *
287:             * @param document the document <code>selection</code> refers to
288:             * @param selection the selection on <code>document</code> that will be moved.
289:             * @return the region comprising the line that <code>selection</code> will be moved over, without its terminating delimiter.
290:             */
291:            private ITextSelection getSkippedLine(IDocument document,
292:                    ITextSelection selection) {
293:                int skippedLineN = (fUpwards ? selection.getStartLine() - 1
294:                        : selection.getEndLine() + 1);
295:                if (skippedLineN > document.getNumberOfLines()
296:                        || (!fCopy && (skippedLineN < 0 || skippedLineN == document
297:                                .getNumberOfLines())))
298:                    return null;
299:                try {
300:                    if (fCopy && skippedLineN == -1)
301:                        skippedLineN = 0;
302:                    IRegion line = document.getLineInformation(skippedLineN);
303:                    return new TextSelection(document, line.getOffset(), line
304:                            .getLength());
305:                } catch (BadLocationException e) {
306:                    // only happens on concurrent modifications
307:                    return null;
308:                }
309:            }
310:
311:            /**
312:             * Checks for white space in a string.
313:             *
314:             * @param string the string to be checked or <code>null</code>
315:             * @return <code>true</code> if <code>string</code> contains only white space or is
316:             * <code>null</code>, <code>false</code> otherwise
317:             */
318:            private boolean isWhitespace(String string) {
319:                return string == null ? true : string.trim().length() == 0;
320:            }
321:
322:            /*
323:             * @see org.eclipse.jface.action.IAction#run()
324:             */
325:            public void runWithEvent(Event event) {
326:
327:                // get involved objects
328:                if (fSharedState.fEditor == null)
329:                    return;
330:
331:                if (!validateEditorInputState())
332:                    return;
333:
334:                ISourceViewer viewer = fSharedState.fEditor.getViewer();
335:                if (viewer == null)
336:                    return;
337:
338:                IDocument document = viewer.getDocument();
339:                if (document == null)
340:                    return;
341:
342:                StyledText widget = viewer.getTextWidget();
343:                if (widget == null)
344:                    return;
345:
346:                // get selection
347:                Point p = viewer.getSelectedRange();
348:                if (p == null)
349:                    return;
350:
351:                ITextSelection sel = new TextSelection(document, p.x, p.y);
352:
353:                ITextSelection skippedLine = getSkippedLine(document, sel);
354:                if (skippedLine == null)
355:                    return;
356:
357:                try {
358:
359:                    ITextSelection movingArea = getMovingSelection(document,
360:                            sel, viewer);
361:
362:                    // if either the skipped line or the moving lines are outside the widget's
363:                    // visible area, bail out
364:                    if (!containedByVisibleRegion(movingArea, viewer)
365:                            || !containedByVisibleRegion(skippedLine, viewer))
366:                        return;
367:
368:                    // get the content to be moved around: the moving (selected) area and the skipped line
369:                    String moving = movingArea.getText();
370:                    String skipped = skippedLine.getText();
371:                    if (moving == null || skipped == null
372:                            || document.getLength() == 0)
373:                        return;
374:
375:                    String delim;
376:                    String insertion;
377:                    int offset;
378:                    if (fUpwards) {
379:                        delim = document.getLineDelimiter(skippedLine
380:                                .getEndLine());
381:                        if (fCopy) {
382:                            delim = TextUtilities
383:                                    .getDefaultLineDelimiter(document);
384:                            insertion = moving + delim;
385:                            offset = movingArea.getOffset();
386:                        } else {
387:                            Assert.isNotNull(delim);
388:                            insertion = moving + delim + skipped;
389:                            offset = skippedLine.getOffset();
390:                        }
391:                    } else {
392:                        delim = document.getLineDelimiter(movingArea
393:                                .getEndLine());
394:                        if (fCopy) {
395:                            if (delim == null) {
396:                                delim = TextUtilities
397:                                        .getDefaultLineDelimiter(document);
398:                                insertion = delim + moving;
399:                            } else
400:                                insertion = moving + delim;
401:                            offset = skippedLine.getOffset();
402:                        } else {
403:                            Assert.isNotNull(delim);
404:                            insertion = skipped + delim + moving;
405:                            offset = movingArea.getOffset();
406:                        }
407:                    }
408:                    int lenght = fCopy ? 0 : insertion.length();
409:
410:                    // modify the document
411:                    ILineRange selectionBefore = getLineRange(document,
412:                            movingArea);
413:
414:                    if (fCopy)
415:                        fSharedState.endCompoundEdit();
416:                    fSharedState.beginCompoundEdit();
417:                    fSharedState.fIsChanging = true;
418:
419:                    document.replace(offset, lenght, insertion);
420:
421:                    ILineRange selectionAfter;
422:                    if (fUpwards && fCopy)
423:                        selectionAfter = selectionBefore;
424:                    else if (fUpwards)
425:                        selectionAfter = new LineRange(selectionBefore
426:                                .getStartLine() - 1, selectionBefore
427:                                .getNumberOfLines());
428:                    else if (fCopy)
429:                        selectionAfter = new LineRange(selectionBefore
430:                                .getStartLine()
431:                                + selectionBefore.getNumberOfLines(),
432:                                selectionBefore.getNumberOfLines());
433:                    else
434:                        selectionAfter = new LineRange(selectionBefore
435:                                .getStartLine() + 1, selectionBefore
436:                                .getNumberOfLines());
437:
438:                    fSharedState.fResult = IndentUtil.indentLines(document,
439:                            selectionAfter, getProject(), fSharedState.fResult);
440:
441:                    // move the selection along
442:                    IRegion region = getRegion(document, selectionAfter);
443:                    selectAndReveal(viewer, region.getOffset(), region
444:                            .getLength());
445:
446:                } catch (BadLocationException x) {
447:                    // won't happen without concurrent modification - bail out
448:                    return;
449:                } finally {
450:                    fSharedState.fIsChanging = false;
451:                    if (fCopy)
452:                        fSharedState.endCompoundEdit();
453:                }
454:            }
455:
456:            private IJavaProject getProject() {
457:                IEditorInput editorInput = fSharedState.fEditor
458:                        .getEditorInput();
459:                ICompilationUnit unit = JavaPlugin.getDefault()
460:                        .getWorkingCopyManager().getWorkingCopy(editorInput);
461:                if (unit != null)
462:                    return unit.getJavaProject();
463:                return null;
464:            }
465:
466:            private ILineRange getLineRange(IDocument document,
467:                    ITextSelection selection) throws BadLocationException {
468:                final int offset = selection.getOffset();
469:                int startLine = document.getLineOfOffset(offset);
470:                int endOffset = offset + selection.getLength();
471:                int endLine = document.getLineOfOffset(endOffset);
472:                final int nLines = endLine - startLine + 1;
473:                return new LineRange(startLine, nLines);
474:            }
475:
476:            private IRegion getRegion(IDocument document, ILineRange lineRange)
477:                    throws BadLocationException {
478:                final int startLine = lineRange.getStartLine();
479:                int offset = document.getLineOffset(startLine);
480:                final int numberOfLines = lineRange.getNumberOfLines();
481:                if (numberOfLines < 1)
482:                    return new Region(offset, 0);
483:                int endLine = startLine + numberOfLines - 1;
484:                int endOffset = document.getLineOffset(endLine)
485:                        + document.getLineLength(endLine);
486:                return new Region(offset, endOffset - offset);
487:            }
488:
489:            /**
490:             * Performs similar to AbstractTextEditor.selectAndReveal, but does not update
491:             * the viewers highlight area.
492:             *
493:             * @param viewer the viewer that we want to select on
494:             * @param offset the offset of the selection
495:             * @param length the length of the selection
496:             */
497:            private void selectAndReveal(ITextViewer viewer, int offset,
498:                    int length) {
499:                // invert selection to avoid jumping to the end of the selection in st.showSelection()
500:                viewer.setSelectedRange(offset + length, -length);
501:                //viewer.revealRange(offset, length); // will trigger jumping
502:                StyledText st = viewer.getTextWidget();
503:                if (st != null)
504:                    st.showSelection(); // only minimal scrolling
505:            }
506:
507:            /**
508:             * Displays information in the status line why a line move is not possible
509:             */
510:            private void showStatus() {
511:                IEditorStatusLine status = (IEditorStatusLine) fSharedState.fEditor
512:                        .getAdapter(IEditorStatusLine.class);
513:                if (status == null)
514:                    return;
515:                status.setMessage(false,
516:                        JavaEditorMessages.Editor_MoveLines_IllegalMove_status,
517:                        null);
518:            }
519:
520:            /*
521:             * @see org.eclipse.ui.texteditor.IUpdate#update()
522:             */
523:            public void update() {
524:                super.update();
525:
526:                if (isEnabled())
527:                    setEnabled(canModifyEditor());
528:
529:            }
530:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.