Source Code Cross Referenced for AbstractTextEditor.java in  » IDE-Eclipse » ui-workbench » org » eclipse » ui » texteditor » 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 » ui workbench » org.eclipse.ui.texteditor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *     Chris.Dennis@invidi.com - http://bugs.eclipse.org/bugs/show_bug.cgi?id=29027
0011:         *     Michel Ishizuka (cqw10305@nifty.com) - http://bugs.eclipse.org/bugs/show_bug.cgi?id=68963
0012:         *     Genady Beryozkin, me@genady.org - https://bugs.eclipse.org/bugs/show_bug.cgi?id=11668
0013:         *     Benjamin Muskalla <b.muskalla@gmx.net> - https://bugs.eclipse.org/bugs/show_bug.cgi?id=41573
0014:         *******************************************************************************/package org.eclipse.ui.texteditor;
0015:
0016:        import java.lang.reflect.InvocationTargetException;
0017:        import java.util.ArrayList;
0018:        import java.util.HashMap;
0019:        import java.util.Iterator;
0020:        import java.util.List;
0021:        import java.util.Map;
0022:        import java.util.ResourceBundle;
0023:
0024:        import org.osgi.framework.Bundle;
0025:
0026:        import org.eclipse.swt.SWT;
0027:        import org.eclipse.swt.custom.BusyIndicator;
0028:        import org.eclipse.swt.custom.ST;
0029:        import org.eclipse.swt.custom.StyledText;
0030:        import org.eclipse.swt.custom.VerifyKeyListener;
0031:        import org.eclipse.swt.dnd.DND;
0032:        import org.eclipse.swt.dnd.DragSource;
0033:        import org.eclipse.swt.dnd.DragSourceAdapter;
0034:        import org.eclipse.swt.dnd.DragSourceEvent;
0035:        import org.eclipse.swt.dnd.DropTargetAdapter;
0036:        import org.eclipse.swt.dnd.DropTargetEvent;
0037:        import org.eclipse.swt.dnd.DropTargetListener;
0038:        import org.eclipse.swt.dnd.TextTransfer;
0039:        import org.eclipse.swt.dnd.Transfer;
0040:        import org.eclipse.swt.events.KeyEvent;
0041:        import org.eclipse.swt.events.KeyListener;
0042:        import org.eclipse.swt.events.MouseEvent;
0043:        import org.eclipse.swt.events.MouseListener;
0044:        import org.eclipse.swt.events.VerifyEvent;
0045:        import org.eclipse.swt.events.VerifyListener;
0046:        import org.eclipse.swt.graphics.Color;
0047:        import org.eclipse.swt.graphics.Font;
0048:        import org.eclipse.swt.graphics.FontData;
0049:        import org.eclipse.swt.graphics.GC;
0050:        import org.eclipse.swt.graphics.Image;
0051:        import org.eclipse.swt.graphics.ImageData;
0052:        import org.eclipse.swt.graphics.PaletteData;
0053:        import org.eclipse.swt.graphics.Point;
0054:        import org.eclipse.swt.graphics.RGB;
0055:        import org.eclipse.swt.widgets.Caret;
0056:        import org.eclipse.swt.widgets.Composite;
0057:        import org.eclipse.swt.widgets.Control;
0058:        import org.eclipse.swt.widgets.Display;
0059:        import org.eclipse.swt.widgets.Menu;
0060:        import org.eclipse.swt.widgets.Shell;
0061:
0062:        import org.eclipse.core.commands.operations.IOperationApprover;
0063:        import org.eclipse.core.commands.operations.IOperationHistory;
0064:        import org.eclipse.core.commands.operations.IUndoContext;
0065:        import org.eclipse.core.commands.operations.OperationHistoryFactory;
0066:
0067:        import org.eclipse.core.runtime.Assert;
0068:        import org.eclipse.core.runtime.CoreException;
0069:        import org.eclipse.core.runtime.IConfigurationElement;
0070:        import org.eclipse.core.runtime.ILog;
0071:        import org.eclipse.core.runtime.IProgressMonitor;
0072:        import org.eclipse.core.runtime.IStatus;
0073:        import org.eclipse.core.runtime.NullProgressMonitor;
0074:        import org.eclipse.core.runtime.Platform;
0075:        import org.eclipse.core.runtime.SafeRunner;
0076:        import org.eclipse.core.runtime.Status;
0077:
0078:        import org.eclipse.text.undo.DocumentUndoManagerRegistry;
0079:        import org.eclipse.text.undo.IDocumentUndoManager;
0080:
0081:        import org.eclipse.jface.action.Action;
0082:        import org.eclipse.jface.action.GroupMarker;
0083:        import org.eclipse.jface.action.IAction;
0084:        import org.eclipse.jface.action.IMenuListener;
0085:        import org.eclipse.jface.action.IMenuManager;
0086:        import org.eclipse.jface.action.IStatusLineManager;
0087:        import org.eclipse.jface.action.MenuManager;
0088:        import org.eclipse.jface.action.Separator;
0089:        import org.eclipse.jface.dialogs.ErrorDialog;
0090:        import org.eclipse.jface.dialogs.MessageDialog;
0091:        import org.eclipse.jface.internal.text.html.HTMLTextPresenter;
0092:        import org.eclipse.jface.operation.IRunnableWithProgress;
0093:        import org.eclipse.jface.preference.IPreferenceStore;
0094:        import org.eclipse.jface.preference.PreferenceConverter;
0095:        import org.eclipse.jface.resource.ImageDescriptor;
0096:        import org.eclipse.jface.resource.JFaceResources;
0097:        import org.eclipse.jface.util.IPropertyChangeListener;
0098:        import org.eclipse.jface.util.PropertyChangeEvent;
0099:        import org.eclipse.jface.util.SafeRunnable;
0100:        import org.eclipse.jface.viewers.IPostSelectionProvider;
0101:        import org.eclipse.jface.viewers.ISelection;
0102:        import org.eclipse.jface.viewers.ISelectionChangedListener;
0103:        import org.eclipse.jface.viewers.ISelectionProvider;
0104:        import org.eclipse.jface.viewers.SelectionChangedEvent;
0105:        import org.eclipse.jface.viewers.StructuredSelection;
0106:        import org.eclipse.jface.window.IShellProvider;
0107:
0108:        import org.eclipse.jface.text.AbstractInformationControlManager;
0109:        import org.eclipse.jface.text.BadLocationException;
0110:        import org.eclipse.jface.text.DefaultInformationControl;
0111:        import org.eclipse.jface.text.DefaultLineTracker;
0112:        import org.eclipse.jface.text.DocumentEvent;
0113:        import org.eclipse.jface.text.IDocument;
0114:        import org.eclipse.jface.text.IDocumentListener;
0115:        import org.eclipse.jface.text.IFindReplaceTarget;
0116:        import org.eclipse.jface.text.IFindReplaceTargetExtension;
0117:        import org.eclipse.jface.text.IInformationControl;
0118:        import org.eclipse.jface.text.IInformationControlCreator;
0119:        import org.eclipse.jface.text.IMarkRegionTarget;
0120:        import org.eclipse.jface.text.IRegion;
0121:        import org.eclipse.jface.text.IRewriteTarget;
0122:        import org.eclipse.jface.text.ISelectionValidator;
0123:        import org.eclipse.jface.text.ITextHover;
0124:        import org.eclipse.jface.text.ITextInputListener;
0125:        import org.eclipse.jface.text.ITextListener;
0126:        import org.eclipse.jface.text.ITextOperationTarget;
0127:        import org.eclipse.jface.text.ITextSelection;
0128:        import org.eclipse.jface.text.ITextViewer;
0129:        import org.eclipse.jface.text.ITextViewerExtension;
0130:        import org.eclipse.jface.text.ITextViewerExtension2;
0131:        import org.eclipse.jface.text.ITextViewerExtension4;
0132:        import org.eclipse.jface.text.ITextViewerExtension5;
0133:        import org.eclipse.jface.text.ITextViewerExtension6;
0134:        import org.eclipse.jface.text.ITextViewerExtension7;
0135:        import org.eclipse.jface.text.IUndoManager;
0136:        import org.eclipse.jface.text.IUndoManagerExtension;
0137:        import org.eclipse.jface.text.Position;
0138:        import org.eclipse.jface.text.Region;
0139:        import org.eclipse.jface.text.TabsToSpacesConverter;
0140:        import org.eclipse.jface.text.TextEvent;
0141:        import org.eclipse.jface.text.TextSelection;
0142:        import org.eclipse.jface.text.TextUtilities;
0143:        import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
0144:        import org.eclipse.jface.text.information.IInformationProvider;
0145:        import org.eclipse.jface.text.information.IInformationProviderExtension;
0146:        import org.eclipse.jface.text.information.IInformationProviderExtension2;
0147:        import org.eclipse.jface.text.information.InformationPresenter;
0148:        import org.eclipse.jface.text.link.LinkedModeModel;
0149:        import org.eclipse.jface.text.link.LinkedPosition;
0150:        import org.eclipse.jface.text.revisions.RevisionInformation;
0151:        import org.eclipse.jface.text.source.Annotation;
0152:        import org.eclipse.jface.text.source.CompositeRuler;
0153:        import org.eclipse.jface.text.source.IAnnotationHover;
0154:        import org.eclipse.jface.text.source.IAnnotationHoverExtension;
0155:        import org.eclipse.jface.text.source.IAnnotationModel;
0156:        import org.eclipse.jface.text.source.ILineRange;
0157:        import org.eclipse.jface.text.source.ISourceViewer;
0158:        import org.eclipse.jface.text.source.ISourceViewerExtension3;
0159:        import org.eclipse.jface.text.source.IVerticalRuler;
0160:        import org.eclipse.jface.text.source.IVerticalRulerColumn;
0161:        import org.eclipse.jface.text.source.IVerticalRulerExtension;
0162:        import org.eclipse.jface.text.source.IVerticalRulerInfo;
0163:        import org.eclipse.jface.text.source.SourceViewer;
0164:        import org.eclipse.jface.text.source.SourceViewerConfiguration;
0165:        import org.eclipse.jface.text.source.VerticalRuler;
0166:
0167:        import org.eclipse.ui.IActionBars;
0168:        import org.eclipse.ui.IEditorDescriptor;
0169:        import org.eclipse.ui.IEditorInput;
0170:        import org.eclipse.ui.IEditorPart;
0171:        import org.eclipse.ui.IEditorRegistry;
0172:        import org.eclipse.ui.IEditorSite;
0173:        import org.eclipse.ui.IKeyBindingService;
0174:        import org.eclipse.ui.IMemento;
0175:        import org.eclipse.ui.INavigationLocation;
0176:        import org.eclipse.ui.INavigationLocationProvider;
0177:        import org.eclipse.ui.IPartListener;
0178:        import org.eclipse.ui.IPartService;
0179:        import org.eclipse.ui.IPersistableEditor;
0180:        import org.eclipse.ui.IReusableEditor;
0181:        import org.eclipse.ui.ISaveablesLifecycleListener;
0182:        import org.eclipse.ui.ISaveablesSource;
0183:        import org.eclipse.ui.IWindowListener;
0184:        import org.eclipse.ui.IWorkbenchActionConstants;
0185:        import org.eclipse.ui.IWorkbenchPart;
0186:        import org.eclipse.ui.IWorkbenchWindow;
0187:        import org.eclipse.ui.PartInitException;
0188:        import org.eclipse.ui.PlatformUI;
0189:        import org.eclipse.ui.Saveable;
0190:        import org.eclipse.ui.SaveablesLifecycleEvent;
0191:        import org.eclipse.ui.actions.CommandNotMappedException;
0192:        import org.eclipse.ui.actions.ContributedAction;
0193:        import org.eclipse.ui.dialogs.PropertyDialogAction;
0194:        import org.eclipse.ui.dnd.IDragAndDropService;
0195:        import org.eclipse.ui.internal.texteditor.EditPosition;
0196:        import org.eclipse.ui.internal.texteditor.NLSUtility;
0197:        import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
0198:        import org.eclipse.ui.internal.texteditor.rulers.StringSetSerializer;
0199:        import org.eclipse.ui.operations.LinearUndoViolationUserApprover;
0200:        import org.eclipse.ui.operations.NonLocalUndoUserApprover;
0201:        import org.eclipse.ui.operations.OperationHistoryActionHandler;
0202:        import org.eclipse.ui.operations.RedoActionHandler;
0203:        import org.eclipse.ui.operations.UndoActionHandler;
0204:        import org.eclipse.ui.part.EditorPart;
0205:        import org.eclipse.ui.texteditor.rulers.IColumnSupport;
0206:        import org.eclipse.ui.texteditor.rulers.IContributedRulerColumn;
0207:        import org.eclipse.ui.texteditor.rulers.RulerColumnDescriptor;
0208:        import org.eclipse.ui.texteditor.rulers.RulerColumnPreferenceAdapter;
0209:        import org.eclipse.ui.texteditor.rulers.RulerColumnRegistry;
0210:
0211:        /**
0212:         * Abstract base implementation of a text editor.
0213:         * <p>
0214:         * Subclasses are responsible for configuring the editor appropriately.
0215:         * The standard text editor, <code>TextEditor</code>, is one such example.</p>
0216:         * <p>
0217:         * If a subclass calls {@linkplain #setEditorContextMenuId(String) setEditorContextMenuId} the argument is
0218:         * used as the id under which the editor's context menu is registered for extensions.
0219:         * If no id is set, the context menu is registered under <b>[editor_id].EditorContext</b>
0220:         * whereby [editor_id] is replaced with the editor's part id.  If the editor is instructed to
0221:         * run in version 1.0 context menu registration compatibility mode, the latter form of the
0222:         * registration even happens if a context menu id has been set via {@linkplain #setEditorContextMenuId(String) setEditorContextMenuId}.
0223:         * If no id is set while in compatibility mode, the menu is registered under
0224:         * {@link #DEFAULT_EDITOR_CONTEXT_MENU_ID}.</p>
0225:         * <p>
0226:         * If a subclass calls {@linkplain #setRulerContextMenuId(String) setRulerContextMenuId} the argument is
0227:         * used as the id under which the ruler's context menu is registered for extensions.
0228:         * If no id is set, the context menu is registered under <b>[editor_id].RulerContext</b>
0229:         * whereby [editor_id] is replaced with the editor's part id.  If the editor is instructed to
0230:         * run in version 1.0 context menu registration compatibility mode, the latter form of the
0231:         * registration even happens if a context menu id has been set via {@linkplain #setRulerContextMenuId(String) setRulerContextMenuId}.
0232:         * If no id is set while in compatibility mode, the menu is registered under
0233:         * {@link #DEFAULT_RULER_CONTEXT_MENU_ID}.</p>
0234:         */
0235:        public abstract class AbstractTextEditor extends EditorPart implements 
0236:                ITextEditor, IReusableEditor, ITextEditorExtension,
0237:                ITextEditorExtension2, ITextEditorExtension3,
0238:                ITextEditorExtension4, INavigationLocationProvider,
0239:                ISaveablesSource, IPersistableEditor {
0240:
0241:            /**
0242:             * Tag used in xml configuration files to specify editor action contributions.
0243:             * Current value: <code>editorContribution</code>
0244:             * @since 2.0
0245:             */
0246:            private static final String TAG_CONTRIBUTION_TYPE = "editorContribution"; //$NON-NLS-1$
0247:
0248:            /**
0249:             * Tags used in the {@link IMemento} when saving and
0250:             * restoring editor state.
0251:             * 
0252:             * @see #saveState(IMemento)
0253:             * @see #restoreState(IMemento)
0254:             * @since 3.3
0255:             */
0256:            protected static final String TAG_SELECTION_OFFSET = "selectionOffset"; //$NON-NLS-1$
0257:            protected static final String TAG_SELECTION_LENGTH = "selectionLength"; //$NON-NLS-1$
0258:            // XXX: workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=168524
0259:            private static final String TAG_SELECTION_HPIXEL = "selectionHPixel"; //$NON-NLS-1$
0260:
0261:            /**
0262:             * The caret width for the wide (double) caret.
0263:             * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=21715.
0264:             * Value: {@value}
0265:             * @since 3.0
0266:             */
0267:            private static final int WIDE_CARET_WIDTH = 2;
0268:
0269:            /**
0270:             * The caret width for the narrow (single) caret.
0271:             * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=21715.
0272:             * Value: {@value}
0273:             * @since 3.0
0274:             */
0275:            private static final int SINGLE_CARET_WIDTH = 1;
0276:
0277:            /**
0278:             * The text input listener.
0279:             *
0280:             * @see ITextInputListener
0281:             * @since 2.1
0282:             */
0283:            private static class TextInputListener implements 
0284:                    ITextInputListener {
0285:                /** Indicates whether the editor input changed during the process of state validation. */
0286:                public boolean inputChanged;
0287:
0288:                /* Detectors for editor input changes during the process of state validation. */
0289:                public void inputDocumentAboutToBeChanged(IDocument oldInput,
0290:                        IDocument newInput) {
0291:                }
0292:
0293:                public void inputDocumentChanged(IDocument oldInput,
0294:                        IDocument newInput) {
0295:                    inputChanged = true;
0296:                }
0297:            }
0298:
0299:            /**
0300:             * Internal element state listener.
0301:             */
0302:            class ElementStateListener implements  IElementStateListener,
0303:                    IElementStateListenerExtension {
0304:
0305:                /**
0306:                 * Internal <code>VerifyListener</code> for performing the state validation of the
0307:                 * editor input in case of the first attempted manipulation via typing on the keyboard.
0308:                 * @since 2.0
0309:                 */
0310:                class Validator implements  VerifyListener {
0311:                    /*
0312:                     * @see VerifyListener#verifyText(org.eclipse.swt.events.VerifyEvent)
0313:                     */
0314:                    public void verifyText(VerifyEvent e) {
0315:                        IDocument document = getDocumentProvider().getDocument(
0316:                                getEditorInput());
0317:                        final boolean[] documentChanged = new boolean[1];
0318:                        IDocumentListener listener = new IDocumentListener() {
0319:                            public void documentAboutToBeChanged(
0320:                                    DocumentEvent event) {
0321:                            }
0322:
0323:                            public void documentChanged(DocumentEvent event) {
0324:                                documentChanged[0] = true;
0325:                            }
0326:                        };
0327:                        try {
0328:                            if (document != null)
0329:                                document.addDocumentListener(listener);
0330:                            if (!validateEditorInputState()
0331:                                    || documentChanged[0])
0332:                                e.doit = false;
0333:                        } finally {
0334:                            if (document != null)
0335:                                document.removeDocumentListener(listener);
0336:                        }
0337:                    }
0338:                }
0339:
0340:                /**
0341:                 * The listener's validator.
0342:                 * @since 2.0
0343:                 */
0344:                private Validator fValidator;
0345:                /**
0346:                 * The display used for posting runnable into the UI thread.
0347:                 * @since 3.0
0348:                 */
0349:                private Display fDisplay;
0350:
0351:                /*
0352:                 * @see IElementStateListenerExtension#elementStateValidationChanged(Object, boolean)
0353:                 * @since 2.0
0354:                 */
0355:                public void elementStateValidationChanged(final Object element,
0356:                        final boolean isStateValidated) {
0357:                    if (element != null && element.equals(getEditorInput())) {
0358:                        Runnable r = new Runnable() {
0359:                            public void run() {
0360:                                enableSanityChecking(true);
0361:                                if (isStateValidated && fValidator != null) {
0362:                                    ISourceViewer viewer = fSourceViewer;
0363:                                    if (viewer != null) {
0364:                                        StyledText textWidget = viewer
0365:                                                .getTextWidget();
0366:                                        if (textWidget != null
0367:                                                && !textWidget.isDisposed())
0368:                                            textWidget
0369:                                                    .removeVerifyListener(fValidator);
0370:                                        fValidator = null;
0371:                                        enableStateValidation(false);
0372:                                    }
0373:                                } else if (!isStateValidated
0374:                                        && fValidator == null) {
0375:                                    ISourceViewer viewer = fSourceViewer;
0376:                                    if (viewer != null) {
0377:                                        StyledText textWidget = viewer
0378:                                                .getTextWidget();
0379:                                        if (textWidget != null
0380:                                                && !textWidget.isDisposed()) {
0381:                                            fValidator = new Validator();
0382:                                            enableStateValidation(true);
0383:                                            textWidget
0384:                                                    .addVerifyListener(fValidator);
0385:                                        }
0386:                                    }
0387:                                }
0388:                            }
0389:                        };
0390:                        execute(r, false);
0391:                    }
0392:                }
0393:
0394:                /*
0395:                 * @see IElementStateListener#elementDirtyStateChanged(Object, boolean)
0396:                 */
0397:                public void elementDirtyStateChanged(Object element,
0398:                        boolean isDirty) {
0399:                    if (element != null && element.equals(getEditorInput())) {
0400:                        Runnable r = new Runnable() {
0401:                            public void run() {
0402:                                enableSanityChecking(true);
0403:                                firePropertyChange(PROP_DIRTY);
0404:                            }
0405:                        };
0406:                        execute(r, false);
0407:                    }
0408:                }
0409:
0410:                /*
0411:                 * @see IElementStateListener#elementContentAboutToBeReplaced(Object)
0412:                 */
0413:                public void elementContentAboutToBeReplaced(Object element) {
0414:                    if (element != null && element.equals(getEditorInput())) {
0415:                        Runnable r = new Runnable() {
0416:                            public void run() {
0417:                                enableSanityChecking(true);
0418:                                rememberSelection();
0419:                                resetHighlightRange();
0420:                            }
0421:                        };
0422:                        execute(r, false);
0423:                    }
0424:                }
0425:
0426:                /*
0427:                 * @see IElementStateListener#elementContentReplaced(Object)
0428:                 */
0429:                public void elementContentReplaced(Object element) {
0430:                    if (element != null && element.equals(getEditorInput())) {
0431:                        Runnable r = new Runnable() {
0432:                            public void run() {
0433:                                enableSanityChecking(true);
0434:                                firePropertyChange(PROP_DIRTY);
0435:                                restoreSelection();
0436:                                handleElementContentReplaced();
0437:                            }
0438:                        };
0439:                        execute(r, false);
0440:                    }
0441:                }
0442:
0443:                /*
0444:                 * @see IElementStateListener#elementDeleted(Object)
0445:                 */
0446:                public void elementDeleted(Object deletedElement) {
0447:                    if (deletedElement != null
0448:                            && deletedElement.equals(getEditorInput())) {
0449:                        Runnable r = new Runnable() {
0450:                            public void run() {
0451:                                enableSanityChecking(true);
0452:                                close(false);
0453:                            }
0454:                        };
0455:                        execute(r, false);
0456:                    }
0457:                }
0458:
0459:                /*
0460:                 * @see IElementStateListener#elementMoved(Object, Object)
0461:                 */
0462:                public void elementMoved(final Object originalElement,
0463:                        final Object movedElement) {
0464:                    if (originalElement != null
0465:                            && originalElement.equals(getEditorInput())) {
0466:                        final boolean doValidationAsync = Display.getCurrent() != null;
0467:                        Runnable r = new Runnable() {
0468:                            public void run() {
0469:                                enableSanityChecking(true);
0470:
0471:                                if (fSourceViewer == null)
0472:                                    return;
0473:
0474:                                if (!canHandleMove(
0475:                                        (IEditorInput) originalElement,
0476:                                        (IEditorInput) movedElement)) {
0477:                                    close(true);
0478:                                    return;
0479:                                }
0480:
0481:                                if (movedElement == null
0482:                                        || movedElement instanceof  IEditorInput) {
0483:                                    rememberSelection();
0484:
0485:                                    final IDocumentProvider d = getDocumentProvider();
0486:                                    final String previousContent;
0487:                                    IDocumentUndoManager previousUndoManager = null;
0488:                                    IDocument changed = null;
0489:                                    boolean wasDirty = isDirty();
0490:                                    changed = d.getDocument(getEditorInput());
0491:                                    if (changed != null) {
0492:                                        if (wasDirty)
0493:                                            previousContent = changed.get();
0494:                                        else
0495:                                            previousContent = null;
0496:
0497:                                        previousUndoManager = DocumentUndoManagerRegistry
0498:                                                .getDocumentUndoManager(changed);
0499:                                        if (previousUndoManager != null)
0500:                                            previousUndoManager.connect(this );
0501:                                    } else
0502:                                        previousContent = null;
0503:
0504:                                    setInput((IEditorInput) movedElement);
0505:
0506:                                    // The undo manager needs to be replaced with one for the new document.
0507:                                    // Transfer the undo history and then disconnect from the old undo manager.
0508:                                    if (previousUndoManager != null) {
0509:                                        IDocument newDocument = getDocumentProvider()
0510:                                                .getDocument(movedElement);
0511:                                        if (newDocument != null) {
0512:                                            IDocumentUndoManager newUndoManager = DocumentUndoManagerRegistry
0513:                                                    .getDocumentUndoManager(newDocument);
0514:                                            if (newUndoManager != null)
0515:                                                newUndoManager
0516:                                                        .transferUndoHistory(previousUndoManager);
0517:                                        }
0518:                                        previousUndoManager.disconnect(this );
0519:                                    }
0520:
0521:                                    if (wasDirty && changed != null) {
0522:                                        Runnable r2 = new Runnable() {
0523:                                            public void run() {
0524:                                                validateState(getEditorInput());
0525:                                                d.getDocument(getEditorInput())
0526:                                                        .set(previousContent);
0527:                                                updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE);
0528:                                                restoreSelection();
0529:                                            }
0530:                                        };
0531:                                        execute(r2, doValidationAsync);
0532:                                    } else
0533:                                        restoreSelection();
0534:
0535:                                }
0536:                            }
0537:                        };
0538:                        execute(r, false);
0539:                    }
0540:                }
0541:
0542:                /*
0543:                 * @see IElementStateListenerExtension#elementStateChanging(Object)
0544:                 * @since 2.0
0545:                 */
0546:                public void elementStateChanging(Object element) {
0547:                    if (element != null && element.equals(getEditorInput()))
0548:                        enableSanityChecking(false);
0549:                }
0550:
0551:                /*
0552:                 * @see IElementStateListenerExtension#elementStateChangeFailed(Object)
0553:                 * @since 2.0
0554:                 */
0555:                public void elementStateChangeFailed(Object element) {
0556:                    if (element != null && element.equals(getEditorInput()))
0557:                        enableSanityChecking(true);
0558:                }
0559:
0560:                /**
0561:                 * Executes the given runnable in the UI thread.
0562:                 * <p>
0563:                 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=76765 for details
0564:                 * about why the parameter <code>postAsync</code> has been
0565:                 * introduced in the course of 3.1.
0566:                 *
0567:                 * @param runnable runnable to be executed
0568:                 * @param postAsync <code>true</code> if the runnable must be posted asynchronous, <code>false</code> otherwise
0569:                 * @since 3.0
0570:                 */
0571:                private void execute(Runnable runnable, boolean postAsync) {
0572:                    if (postAsync || Display.getCurrent() == null) {
0573:                        if (fDisplay == null)
0574:                            fDisplay = getSite().getShell().getDisplay();
0575:                        fDisplay.asyncExec(runnable);
0576:                    } else
0577:                        runnable.run();
0578:                }
0579:            }
0580:
0581:            /**
0582:             * Internal text listener for updating all content dependent
0583:             * actions. The updating is done asynchronously.
0584:             */
0585:            class TextListener implements  ITextListener, ITextInputListener {
0586:
0587:                /** The posted updater code. */
0588:                private Runnable fRunnable = new Runnable() {
0589:                    public void run() {
0590:                        fIsRunnablePosted = false;
0591:
0592:                        if (fSourceViewer != null) {
0593:                            updateContentDependentActions();
0594:
0595:                            // remember the last edit position
0596:                            if (isDirty() && fUpdateLastEditPosition) {
0597:                                fUpdateLastEditPosition = false;
0598:                                ISelection sel = getSelectionProvider()
0599:                                        .getSelection();
0600:                                IEditorInput input = getEditorInput();
0601:                                IDocument document = getDocumentProvider()
0602:                                        .getDocument(input);
0603:
0604:                                if (fLocalLastEditPosition != null) {
0605:                                    document
0606:                                            .removePosition(fLocalLastEditPosition);
0607:                                    fLocalLastEditPosition = null;
0608:                                }
0609:
0610:                                if (sel instanceof  ITextSelection
0611:                                        && !sel.isEmpty()) {
0612:                                    ITextSelection s = (ITextSelection) sel;
0613:                                    fLocalLastEditPosition = new Position(s
0614:                                            .getOffset(), s.getLength());
0615:                                    try {
0616:                                        document
0617:                                                .addPosition(fLocalLastEditPosition);
0618:                                    } catch (BadLocationException ex) {
0619:                                        fLocalLastEditPosition = null;
0620:                                    }
0621:                                }
0622:                                TextEditorPlugin
0623:                                        .getDefault()
0624:                                        .setLastEditPosition(
0625:                                                new EditPosition(
0626:                                                        input,
0627:                                                        getEditorSite().getId(),
0628:                                                        fLocalLastEditPosition));
0629:                            }
0630:                        }
0631:                    }
0632:                };
0633:
0634:                /** Display used for posting the updater code. */
0635:                private Display fDisplay;
0636:                /**
0637:                 * The editor's last edit position
0638:                 * @since 3.0
0639:                 */
0640:                private Position fLocalLastEditPosition;
0641:                /**
0642:                 * Has the runnable been posted?
0643:                 * @since 3.0
0644:                 */
0645:                private boolean fIsRunnablePosted = false;
0646:                /**
0647:                 * Should the last edit position be updated?
0648:                 * @since 3.0
0649:                 */
0650:                private boolean fUpdateLastEditPosition = false;
0651:
0652:                /*
0653:                 * @see ITextListener#textChanged(TextEvent)
0654:                 */
0655:                public void textChanged(TextEvent event) {
0656:
0657:                    /*
0658:                     * Also works for text events which do not base on a DocumentEvent.
0659:                     * This way, if the visible document of the viewer changes, all content
0660:                     * dependent actions are updated as well.
0661:                     */
0662:
0663:                    if (fDisplay == null)
0664:                        fDisplay = getSite().getShell().getDisplay();
0665:
0666:                    if (event.getDocumentEvent() != null)
0667:                        fUpdateLastEditPosition = true;
0668:
0669:                    if (!fIsRunnablePosted) {
0670:                        fIsRunnablePosted = true;
0671:                        fDisplay.asyncExec(fRunnable);
0672:                    }
0673:                }
0674:
0675:                /*
0676:                 * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
0677:                 */
0678:                public void inputDocumentAboutToBeChanged(IDocument oldInput,
0679:                        IDocument newInput) {
0680:                    if (oldInput != null && fLocalLastEditPosition != null) {
0681:                        oldInput.removePosition(fLocalLastEditPosition);
0682:                        fLocalLastEditPosition = null;
0683:                    }
0684:                }
0685:
0686:                /*
0687:                 * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
0688:                 */
0689:                public void inputDocumentChanged(IDocument oldInput,
0690:                        IDocument newInput) {
0691:                }
0692:            }
0693:
0694:            /**
0695:             * Internal property change listener for handling changes in the editor's preferences.
0696:             */
0697:            class PropertyChangeListener implements  IPropertyChangeListener {
0698:                /*
0699:                 * @see IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
0700:                 */
0701:                public void propertyChange(PropertyChangeEvent event) {
0702:                    handlePreferenceStoreChanged(event);
0703:                }
0704:            }
0705:
0706:            /**
0707:             * Internal property change listener for handling workbench font changes.
0708:             * @since 2.1
0709:             */
0710:            class FontPropertyChangeListener implements  IPropertyChangeListener {
0711:                /*
0712:                 * @see IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
0713:                 */
0714:                public void propertyChange(PropertyChangeEvent event) {
0715:                    if (fSourceViewer == null)
0716:                        return;
0717:
0718:                    String property = event.getProperty();
0719:
0720:                    if (getFontPropertyPreferenceKey().equals(property)) {
0721:                        initializeViewerFont(fSourceViewer);
0722:                        updateCaret();
0723:                    }
0724:                }
0725:            }
0726:
0727:            /**
0728:             * Internal key verify listener for triggering action activation codes.
0729:             */
0730:            class ActivationCodeTrigger implements  VerifyKeyListener {
0731:
0732:                /** Indicates whether this trigger has been installed. */
0733:                private boolean fIsInstalled = false;
0734:                /**
0735:                 * The key binding service to use.
0736:                 * @since 2.0
0737:                 */
0738:                private IKeyBindingService fKeyBindingService;
0739:
0740:                /*
0741:                 * @see VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
0742:                 */
0743:                public void verifyKey(VerifyEvent event) {
0744:
0745:                    ActionActivationCode code = null;
0746:                    int size = fActivationCodes.size();
0747:                    for (int i = 0; i < size; i++) {
0748:                        code = (ActionActivationCode) fActivationCodes.get(i);
0749:                        if (code.matches(event)) {
0750:                            IAction action = getAction(code.fActionId);
0751:                            if (action != null) {
0752:
0753:                                if (action instanceof  IUpdate)
0754:                                    ((IUpdate) action).update();
0755:
0756:                                if (!action.isEnabled()
0757:                                        && action instanceof  IReadOnlyDependent) {
0758:                                    IReadOnlyDependent dependent = (IReadOnlyDependent) action;
0759:                                    boolean writable = dependent
0760:                                            .isEnabled(true);
0761:                                    if (writable) {
0762:                                        event.doit = false;
0763:                                        return;
0764:                                    }
0765:                                } else if (action.isEnabled()) {
0766:                                    event.doit = false;
0767:                                    action.run();
0768:                                    return;
0769:                                }
0770:                            }
0771:                        }
0772:                    }
0773:                }
0774:
0775:                /**
0776:                 * Installs this trigger on the editor's text widget.
0777:                 * @since 2.0
0778:                 */
0779:                public void install() {
0780:                    if (!fIsInstalled) {
0781:
0782:                        if (fSourceViewer instanceof  ITextViewerExtension) {
0783:                            ITextViewerExtension e = (ITextViewerExtension) fSourceViewer;
0784:                            e.prependVerifyKeyListener(this );
0785:                        } else {
0786:                            StyledText text = fSourceViewer.getTextWidget();
0787:                            text.addVerifyKeyListener(this );
0788:                        }
0789:
0790:                        fKeyBindingService = getEditorSite()
0791:                                .getKeyBindingService();
0792:                        fIsInstalled = true;
0793:                    }
0794:                }
0795:
0796:                /**
0797:                 * Uninstalls this trigger from the editor's text widget.
0798:                 * @since 2.0
0799:                 */
0800:                public void uninstall() {
0801:                    if (fIsInstalled) {
0802:
0803:                        if (fSourceViewer instanceof  ITextViewerExtension) {
0804:                            ITextViewerExtension e = (ITextViewerExtension) fSourceViewer;
0805:                            e.removeVerifyKeyListener(this );
0806:                        } else if (fSourceViewer != null) {
0807:                            StyledText text = fSourceViewer.getTextWidget();
0808:                            if (text != null && !text.isDisposed())
0809:                                text
0810:                                        .removeVerifyKeyListener(fActivationCodeTrigger);
0811:                        }
0812:
0813:                        fIsInstalled = false;
0814:                        fKeyBindingService = null;
0815:                    }
0816:                }
0817:
0818:                /**
0819:                 * Registers the given action for key activation.
0820:                 * @param action the action to be registered
0821:                 * @since 2.0
0822:                 */
0823:                public void registerActionForKeyActivation(IAction action) {
0824:                    if (action.getActionDefinitionId() != null)
0825:                        fKeyBindingService.registerAction(action);
0826:                }
0827:
0828:                /**
0829:                 * The given action is no longer available for key activation
0830:                 * @param action the action to be unregistered
0831:                 * @since 2.0
0832:                 */
0833:                public void unregisterActionFromKeyActivation(IAction action) {
0834:                    if (action.getActionDefinitionId() != null)
0835:                        fKeyBindingService.unregisterAction(action);
0836:                }
0837:
0838:                /**
0839:                 * Sets the key binding scopes for this editor.
0840:                 * @param keyBindingScopes the key binding scopes
0841:                 * @since 2.1
0842:                 */
0843:                public void setScopes(String[] keyBindingScopes) {
0844:                    if (keyBindingScopes != null && keyBindingScopes.length > 0)
0845:                        fKeyBindingService.setScopes(keyBindingScopes);
0846:                }
0847:            }
0848:
0849:            /**
0850:             * Representation of action activation codes.
0851:             */
0852:            static class ActionActivationCode {
0853:
0854:                /** The action id. */
0855:                public String fActionId;
0856:                /** The character. */
0857:                public char fCharacter;
0858:                /** The key code. */
0859:                public int fKeyCode = -1;
0860:                /** The state mask. */
0861:                public int fStateMask = SWT.DEFAULT;
0862:
0863:                /**
0864:                 * Creates a new action activation code for the given action id.
0865:                 * @param actionId the action id
0866:                 */
0867:                public ActionActivationCode(String actionId) {
0868:                    fActionId = actionId;
0869:                }
0870:
0871:                /**
0872:                 * Returns <code>true</code> if this activation code matches the given verify event.
0873:                 * @param event the event to test for matching
0874:                 * @return whether this activation code matches <code>event</code>
0875:                 */
0876:                public boolean matches(VerifyEvent event) {
0877:                    return (event.character == fCharacter
0878:                            && (fKeyCode == -1 || event.keyCode == fKeyCode) && (fStateMask == SWT.DEFAULT || event.stateMask == fStateMask));
0879:                }
0880:            }
0881:
0882:            /**
0883:             * Internal part and shell activation listener for triggering state validation.
0884:             * @since 2.0
0885:             */
0886:            class ActivationListener implements  IPartListener, IWindowListener {
0887:
0888:                /** Cache of the active workbench part. */
0889:                private IWorkbenchPart fActivePart;
0890:                /** Indicates whether activation handling is currently be done. */
0891:                private boolean fIsHandlingActivation = false;
0892:                /**
0893:                 * The part service.
0894:                 * @since 3.1
0895:                 */
0896:                private IPartService fPartService;
0897:
0898:                /**
0899:                 * Creates this activation listener.
0900:                 *
0901:                 * @param partService the part service on which to add the part listener
0902:                 * @since 3.1
0903:                 */
0904:                public ActivationListener(IPartService partService) {
0905:                    fPartService = partService;
0906:                    fPartService.addPartListener(this );
0907:                    PlatformUI.getWorkbench().addWindowListener(this );
0908:                }
0909:
0910:                /**
0911:                 * Disposes this activation listener.
0912:                 *
0913:                 * @since 3.1
0914:                 */
0915:                public void dispose() {
0916:                    fPartService.removePartListener(this );
0917:                    PlatformUI.getWorkbench().removeWindowListener(this );
0918:                    fPartService = null;
0919:                }
0920:
0921:                /*
0922:                 * @see IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
0923:                 */
0924:                public void partActivated(IWorkbenchPart part) {
0925:                    fActivePart = part;
0926:                    handleActivation();
0927:                }
0928:
0929:                /*
0930:                 * @see IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
0931:                 */
0932:                public void partBroughtToTop(IWorkbenchPart part) {
0933:                }
0934:
0935:                /*
0936:                 * @see IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
0937:                 */
0938:                public void partClosed(IWorkbenchPart part) {
0939:                }
0940:
0941:                /*
0942:                 * @see IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
0943:                 */
0944:                public void partDeactivated(IWorkbenchPart part) {
0945:                    fActivePart = null;
0946:                }
0947:
0948:                /*
0949:                 * @see IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
0950:                 */
0951:                public void partOpened(IWorkbenchPart part) {
0952:                    // Restore the saved state if any
0953:                    if (part == AbstractTextEditor.this 
0954:                            && fMementoToRestore != null
0955:                            && containsSavedState(fMementoToRestore))
0956:                        doRestoreState(fMementoToRestore);
0957:                    fMementoToRestore = null;
0958:                }
0959:
0960:                /**
0961:                 * Handles the activation triggering a element state check in the editor.
0962:                 */
0963:                private void handleActivation() {
0964:                    if (fIsHandlingActivation)
0965:                        return;
0966:
0967:                    if (fActivePart == AbstractTextEditor.this ) {
0968:                        fIsHandlingActivation = true;
0969:                        try {
0970:                            safelySanityCheckState(getEditorInput());
0971:                        } finally {
0972:                            fIsHandlingActivation = false;
0973:                        }
0974:                    }
0975:                }
0976:
0977:                /*
0978:                 * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
0979:                 * @since 3.1
0980:                 */
0981:                public void windowActivated(IWorkbenchWindow window) {
0982:                    if (window == getEditorSite().getWorkbenchWindow()) {
0983:                        /*
0984:                         * Workaround for problem described in
0985:                         * http://dev.eclipse.org/bugs/show_bug.cgi?id=11731
0986:                         * Will be removed when SWT has solved the problem.
0987:                         */
0988:                        window.getShell().getDisplay().asyncExec(
0989:                                new Runnable() {
0990:                                    public void run() {
0991:                                        handleActivation();
0992:                                    }
0993:                                });
0994:                    }
0995:                }
0996:
0997:                /*
0998:                 * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
0999:                 * @since 3.1
1000:                 */
1001:                public void windowDeactivated(IWorkbenchWindow window) {
1002:                }
1003:
1004:                /*
1005:                 * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
1006:                 * @since 3.1
1007:                 */
1008:                public void windowClosed(IWorkbenchWindow window) {
1009:                }
1010:
1011:                /*
1012:                 * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
1013:                 * @since 3.1
1014:                 */
1015:                public void windowOpened(IWorkbenchWindow window) {
1016:                }
1017:            }
1018:
1019:            /**
1020:             * Internal interface for a cursor listener. I.e. aggregation
1021:             * of mouse and key listener.
1022:             * @since 2.0
1023:             */
1024:            interface ICursorListener extends MouseListener, KeyListener {
1025:            }
1026:
1027:            /**
1028:             * Maps an action definition id to an StyledText action.
1029:             * @since 2.0
1030:             */
1031:            protected static final class IdMapEntry {
1032:
1033:                /** The action id. */
1034:                private String fActionId;
1035:                /** The StyledText action. */
1036:                private int fAction;
1037:
1038:                /**
1039:                 * Creates a new mapping.
1040:                 * @param actionId the action id
1041:                 * @param action the StyledText action
1042:                 */
1043:                public IdMapEntry(String actionId, int action) {
1044:                    fActionId = actionId;
1045:                    fAction = action;
1046:                }
1047:
1048:                /**
1049:                 * Returns the action id.
1050:                 * @return the action id
1051:                 */
1052:                public String getActionId() {
1053:                    return fActionId;
1054:                }
1055:
1056:                /**
1057:                 * Returns the action.
1058:                 * @return the action
1059:                 */
1060:                public int getAction() {
1061:                    return fAction;
1062:                }
1063:            }
1064:
1065:            /**
1066:             * Internal action to scroll the editor's viewer by a specified number of lines.
1067:             * @since 2.0
1068:             */
1069:            class ScrollLinesAction extends Action {
1070:
1071:                /** Number of lines to scroll. */
1072:                private int fScrollIncrement;
1073:
1074:                /**
1075:                 * Creates a new scroll action that scroll the given number of lines. If the
1076:                 * increment is &lt; 0, it's scrolling up, if &gt; 0 it's scrolling down.
1077:                 * @param scrollIncrement the number of lines to scroll
1078:                 */
1079:                public ScrollLinesAction(int scrollIncrement) {
1080:                    fScrollIncrement = scrollIncrement;
1081:                }
1082:
1083:                /*
1084:                 * @see IAction#run()
1085:                 */
1086:                public void run() {
1087:                    if (fSourceViewer instanceof  ITextViewerExtension5) {
1088:                        ITextViewerExtension5 extension = (ITextViewerExtension5) fSourceViewer;
1089:                        StyledText textWidget = fSourceViewer.getTextWidget();
1090:                        int topIndex = textWidget.getTopIndex();
1091:                        int newTopIndex = Math.max(0, topIndex
1092:                                + fScrollIncrement);
1093:                        fSourceViewer.setTopIndex(extension
1094:                                .widgetLine2ModelLine(newTopIndex));
1095:                    } else {
1096:                        int topIndex = fSourceViewer.getTopIndex();
1097:                        int newTopIndex = Math.max(0, topIndex
1098:                                + fScrollIncrement);
1099:                        fSourceViewer.setTopIndex(newTopIndex);
1100:                    }
1101:                }
1102:            }
1103:
1104:            /**
1105:             * Action to toggle the insert mode. The action is checked if smart mode is
1106:             * turned on.
1107:             *
1108:             * @since 2.1
1109:             */
1110:            class ToggleInsertModeAction extends ResourceAction {
1111:
1112:                public ToggleInsertModeAction(ResourceBundle bundle,
1113:                        String prefix) {
1114:                    super (bundle, prefix, IAction.AS_CHECK_BOX);
1115:                }
1116:
1117:                /*
1118:                 * @see org.eclipse.jface.action.IAction#run()
1119:                 */
1120:                public void run() {
1121:                    switchToNextInsertMode();
1122:                }
1123:
1124:                /*
1125:                 * @see org.eclipse.jface.action.IAction#isChecked()
1126:                 * @since 3.0
1127:                 */
1128:                public boolean isChecked() {
1129:                    return fInsertMode == SMART_INSERT;
1130:                }
1131:            }
1132:
1133:            /**
1134:             * Action to toggle the overwrite mode.
1135:             *
1136:             * @since 3.0
1137:             */
1138:            class ToggleOverwriteModeAction extends ResourceAction {
1139:
1140:                public ToggleOverwriteModeAction(ResourceBundle bundle,
1141:                        String prefix) {
1142:                    super (bundle, prefix);
1143:                }
1144:
1145:                /*
1146:                 * @see org.eclipse.jface.action.IAction#run()
1147:                 */
1148:                public void run() {
1149:                    toggleOverwriteMode();
1150:                }
1151:            }
1152:
1153:            /**
1154:             * This action implements smart end.
1155:             * Instead of going to the end of a line it does the following:
1156:             * - if smart home/end is enabled and the caret is before the line's last non-whitespace and then the caret is moved directly after it
1157:             * - if the caret is after last non-whitespace the caret is moved at the end of the line
1158:             * - if the caret is at the end of the line the caret is moved directly after the line's last non-whitespace character
1159:             * @since 2.1 (in 3.3 the access modifier changed from package visibility to protected)
1160:             */
1161:            protected class LineEndAction extends TextNavigationAction {
1162:
1163:                /** boolean flag which tells if the text up to the line end should be selected. */
1164:                private boolean fDoSelect;
1165:
1166:                /**
1167:                 * Create a new line end action.
1168:                 *
1169:                 * @param textWidget the styled text widget
1170:                 * @param doSelect a boolean flag which tells if the text up to the line end should be selected
1171:                 */
1172:                public LineEndAction(StyledText textWidget, boolean doSelect) {
1173:                    super (textWidget, ST.LINE_END);
1174:                    fDoSelect = doSelect;
1175:                }
1176:
1177:                /**
1178:                 * Computes the offset of the line end position.
1179:                 *
1180:                 * @param document the document where to compute the line end position
1181:                 * @param line the line to determine the end position of
1182:                 * @param length the length of the line
1183:                 * @param offset the caret position in the document
1184:                 * @return the offset of the line end
1185:                 * @since 3.3, protected since 3.4
1186:                 */
1187:                protected int getLineEndPosition(final IDocument document,
1188:                        final String line, final int length, final int offset) {
1189:                    int index = length - 1;
1190:                    while (index > -1
1191:                            && Character.isWhitespace(line.charAt(index)))
1192:                        index--;
1193:                    index++;
1194:
1195:                    LinkedModeModel model = LinkedModeModel.getModel(document,
1196:                            offset);
1197:                    if (model != null) {
1198:                        LinkedPosition linkedPosition = model
1199:                                .findPosition(new LinkedPosition(document,
1200:                                        offset, 0));
1201:                        if (linkedPosition != null) {
1202:                            int linkedPositionEnd = linkedPosition.getOffset()
1203:                                    + linkedPosition.getLength();
1204:                            int lineOffset;
1205:                            try {
1206:                                lineOffset = document
1207:                                        .getLineInformationOfOffset(offset)
1208:                                        .getOffset();
1209:                                if (offset != linkedPositionEnd
1210:                                        && linkedPositionEnd - lineOffset < index)
1211:                                    index = linkedPositionEnd - lineOffset;
1212:                            } catch (BadLocationException e) {
1213:                                //should not happen
1214:                            }
1215:                        }
1216:                    }
1217:                    return index;
1218:                }
1219:
1220:                /*
1221:                 * @see org.eclipse.jface.action.IAction#run()
1222:                 */
1223:                public void run() {
1224:                    boolean isSmartHomeEndEnabled = false;
1225:                    IPreferenceStore store = getPreferenceStore();
1226:                    if (store != null)
1227:                        isSmartHomeEndEnabled = store
1228:                                .getBoolean(AbstractTextEditor.PREFERENCE_NAVIGATION_SMART_HOME_END);
1229:
1230:                    StyledText st = fSourceViewer.getTextWidget();
1231:                    if (st == null || st.isDisposed())
1232:                        return;
1233:                    int caretOffset = st.getCaretOffset();
1234:                    int lineNumber = st.getLineAtOffset(caretOffset);
1235:                    int lineOffset = st.getOffsetAtLine(lineNumber);
1236:
1237:                    int lineLength;
1238:                    int caretOffsetInDocument;
1239:                    final IDocument document = fSourceViewer.getDocument();
1240:
1241:                    try {
1242:                        caretOffsetInDocument = widgetOffset2ModelOffset(
1243:                                fSourceViewer, caretOffset);
1244:                        lineLength = document.getLineInformationOfOffset(
1245:                                caretOffsetInDocument).getLength();
1246:                    } catch (BadLocationException ex) {
1247:                        return;
1248:                    }
1249:                    int lineEndOffset = lineOffset + lineLength;
1250:
1251:                    int delta = lineEndOffset - st.getCharCount();
1252:                    if (delta > 0) {
1253:                        lineEndOffset -= delta;
1254:                        lineLength -= delta;
1255:                    }
1256:
1257:                    String line = ""; //$NON-NLS-1$
1258:                    if (lineLength > 0)
1259:                        line = st.getText(lineOffset, lineEndOffset - 1);
1260:
1261:                    // Remember current selection
1262:                    Point oldSelection = st.getSelection();
1263:
1264:                    // The new caret position
1265:                    int newCaretOffset = -1;
1266:
1267:                    if (isSmartHomeEndEnabled) {
1268:                        // Compute the line end offset
1269:                        int i = getLineEndPosition(document, line, lineLength,
1270:                                caretOffsetInDocument);
1271:
1272:                        if (caretOffset - lineOffset == i)
1273:                            // to end of line
1274:                            newCaretOffset = lineEndOffset;
1275:                        else
1276:                            // to end of text
1277:                            newCaretOffset = lineOffset + i;
1278:
1279:                    } else {
1280:
1281:                        if (caretOffset < lineEndOffset)
1282:                            // to end of line
1283:                            newCaretOffset = lineEndOffset;
1284:
1285:                    }
1286:
1287:                    if (newCaretOffset == -1)
1288:                        newCaretOffset = caretOffset;
1289:                    else
1290:                        st.setCaretOffset(newCaretOffset);
1291:
1292:                    st.setCaretOffset(newCaretOffset);
1293:                    if (fDoSelect) {
1294:                        if (caretOffset < oldSelection.y)
1295:                            st.setSelection(oldSelection.y, newCaretOffset);
1296:                        else
1297:                            st.setSelection(oldSelection.x, newCaretOffset);
1298:                    } else
1299:                        st.setSelection(newCaretOffset);
1300:
1301:                    fireSelectionChanged(oldSelection);
1302:                }
1303:            }
1304:
1305:            /**
1306:             * This action implements smart home.
1307:             * Instead of going to the start of a line it does the following:
1308:             * - if smart home/end is enabled and the caret is after the line's first non-whitespace then the caret is moved directly before it
1309:             * - if the caret is before the line's first non-whitespace the caret is moved to the beginning of the line
1310:             * - if the caret is at the beginning of the line the caret is moved directly before the line's first non-whitespace character
1311:             * @since 2.1
1312:             */
1313:            protected class LineStartAction extends TextNavigationAction {
1314:
1315:                /** boolean flag which tells if the text up to the beginning of the line should be selected. */
1316:                private final boolean fDoSelect;
1317:
1318:                /**
1319:                 * Creates a new line start action.
1320:                 *
1321:                 * @param textWidget the styled text widget
1322:                 * @param doSelect a boolean flag which tells if the text up to the beginning of the line should be selected
1323:                 */
1324:                public LineStartAction(final StyledText textWidget,
1325:                        final boolean doSelect) {
1326:                    super (textWidget, ST.LINE_START);
1327:                    fDoSelect = doSelect;
1328:                }
1329:
1330:                /**
1331:                 * Computes the offset of the line start position.
1332:                 *
1333:                 * @param document the document where to compute the line start position
1334:                 * @param line the line to determine the start position of
1335:                 * @param length the length of the line
1336:                 * @param offset the caret position in the document
1337:                 * @return the offset of the line start
1338:                 * @since 3.0
1339:                 */
1340:                protected int getLineStartPosition(final IDocument document,
1341:                        final String line, final int length, final int offset) {
1342:                    int index = 0;
1343:                    while (index < length
1344:                            && Character.isWhitespace(line.charAt(index)))
1345:                        index++;
1346:
1347:                    LinkedModeModel model = LinkedModeModel.getModel(document,
1348:                            offset);
1349:                    if (model != null) {
1350:                        LinkedPosition linkedPosition = model
1351:                                .findPosition(new LinkedPosition(document,
1352:                                        offset, 0));
1353:                        if (linkedPosition != null) {
1354:                            int linkedPositionOffset = linkedPosition
1355:                                    .getOffset();
1356:                            int lineOffset;
1357:                            try {
1358:                                lineOffset = document
1359:                                        .getLineInformationOfOffset(offset)
1360:                                        .getOffset();
1361:                                if (offset != linkedPositionOffset
1362:                                        && index < linkedPositionOffset
1363:                                                - lineOffset)
1364:                                    index = linkedPositionOffset - lineOffset;
1365:                            } catch (BadLocationException e) {
1366:                                //should not happen
1367:                            }
1368:                        }
1369:                    }
1370:                    return index;
1371:                }
1372:
1373:                /*
1374:                 * @see org.eclipse.jface.action.IAction#run()
1375:                 */
1376:                public void run() {
1377:                    boolean isSmartHomeEndEnabled = false;
1378:                    IPreferenceStore store = getPreferenceStore();
1379:                    if (store != null)
1380:                        isSmartHomeEndEnabled = store
1381:                                .getBoolean(AbstractTextEditor.PREFERENCE_NAVIGATION_SMART_HOME_END);
1382:
1383:                    StyledText st = fSourceViewer.getTextWidget();
1384:                    if (st == null || st.isDisposed())
1385:                        return;
1386:
1387:                    int caretOffset = st.getCaretOffset();
1388:                    int lineNumber = st.getLineAtOffset(caretOffset);
1389:                    int lineOffset = st.getOffsetAtLine(lineNumber);
1390:
1391:                    int lineLength;
1392:                    int caretOffsetInDocument;
1393:                    final IDocument document = fSourceViewer.getDocument();
1394:
1395:                    try {
1396:                        caretOffsetInDocument = widgetOffset2ModelOffset(
1397:                                fSourceViewer, caretOffset);
1398:                        lineLength = document.getLineInformationOfOffset(
1399:                                caretOffsetInDocument).getLength();
1400:                    } catch (BadLocationException ex) {
1401:                        return;
1402:                    }
1403:
1404:                    String line = ""; //$NON-NLS-1$
1405:                    if (lineLength > 0) {
1406:                        int end = lineOffset + lineLength - 1;
1407:                        end = Math.min(end, st.getCharCount() - 1);
1408:                        line = st.getText(lineOffset, end);
1409:                    }
1410:
1411:                    // Remember current selection
1412:                    Point oldSelection = st.getSelection();
1413:
1414:                    // The new caret position
1415:                    int newCaretOffset = -1;
1416:
1417:                    if (isSmartHomeEndEnabled) {
1418:
1419:                        // Compute the line start offset
1420:                        int index = getLineStartPosition(document, line,
1421:                                lineLength, caretOffsetInDocument);
1422:
1423:                        if (caretOffset - lineOffset == index)
1424:                            // to beginning of line
1425:                            newCaretOffset = lineOffset;
1426:                        else
1427:                            // to beginning of text
1428:                            newCaretOffset = lineOffset + index;
1429:
1430:                    } else {
1431:
1432:                        if (caretOffset > lineOffset)
1433:                            // to beginning of line
1434:                            newCaretOffset = lineOffset;
1435:                    }
1436:
1437:                    if (newCaretOffset == -1)
1438:                        newCaretOffset = caretOffset;
1439:                    else
1440:                        st.setCaretOffset(newCaretOffset);
1441:
1442:                    if (fDoSelect) {
1443:                        if (caretOffset < oldSelection.y)
1444:                            st.setSelection(oldSelection.y, newCaretOffset);
1445:                        else
1446:                            st.setSelection(oldSelection.x, newCaretOffset);
1447:                    } else
1448:                        st.setSelection(newCaretOffset);
1449:
1450:                    fireSelectionChanged(oldSelection);
1451:                }
1452:
1453:            }
1454:
1455:            /**
1456:             * Internal action to show the editor's ruler context menu (accessibility).
1457:             * @since 2.0
1458:             */
1459:            class ShowRulerContextMenuAction extends Action {
1460:                /*
1461:                 * @see IAction#run()
1462:                 */
1463:                public void run() {
1464:                    if (fSourceViewer == null)
1465:                        return;
1466:
1467:                    StyledText text = fSourceViewer.getTextWidget();
1468:                    if (text == null || text.isDisposed())
1469:                        return;
1470:
1471:                    Point location = text.getLocationAtOffset(text
1472:                            .getCaretOffset());
1473:                    location.x = 0;
1474:
1475:                    if (fVerticalRuler instanceof  IVerticalRulerExtension)
1476:                        ((IVerticalRulerExtension) fVerticalRuler)
1477:                                .setLocationOfLastMouseButtonActivity(
1478:                                        location.x, location.y);
1479:
1480:                    location = text.toDisplay(location);
1481:                    fRulerContextMenu.setLocation(location.x, location.y);
1482:                    fRulerContextMenu.setVisible(true);
1483:                }
1484:            }
1485:
1486:            /**
1487:             * Editor specific selection provider which wraps the source viewer's selection provider.
1488:             * @since 2.1
1489:             */
1490:            class SelectionProvider implements  IPostSelectionProvider,
1491:                    ISelectionValidator {
1492:
1493:                /*
1494:                 * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(ISelectionChangedListener)
1495:                 */
1496:                public void addSelectionChangedListener(
1497:                        ISelectionChangedListener listener) {
1498:                    if (fSourceViewer != null)
1499:                        fSourceViewer.getSelectionProvider()
1500:                                .addSelectionChangedListener(listener);
1501:                }
1502:
1503:                /*
1504:                 * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
1505:                 */
1506:                public ISelection getSelection() {
1507:                    return doGetSelection();
1508:                }
1509:
1510:                /*
1511:                 * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(ISelectionChangedListener)
1512:                 */
1513:                public void removeSelectionChangedListener(
1514:                        ISelectionChangedListener listener) {
1515:                    if (fSourceViewer != null)
1516:                        fSourceViewer.getSelectionProvider()
1517:                                .removeSelectionChangedListener(listener);
1518:                }
1519:
1520:                /*
1521:                 * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(ISelection)
1522:                 */
1523:                public void setSelection(ISelection selection) {
1524:                    doSetSelection(selection);
1525:                }
1526:
1527:                /*
1528:                 * @see org.eclipse.jface.text.IPostSelectionProvider#addPostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
1529:                 * @since 3.0
1530:                 */
1531:                public void addPostSelectionChangedListener(
1532:                        ISelectionChangedListener listener) {
1533:                    if (fSourceViewer != null) {
1534:                        if (fSourceViewer.getSelectionProvider() instanceof  IPostSelectionProvider) {
1535:                            IPostSelectionProvider provider = (IPostSelectionProvider) fSourceViewer
1536:                                    .getSelectionProvider();
1537:                            provider.addPostSelectionChangedListener(listener);
1538:                        }
1539:                    }
1540:                }
1541:
1542:                /*
1543:                 * @see org.eclipse.jface.text.IPostSelectionProvider#removePostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
1544:                 * @since 3.0
1545:                 */
1546:                public void removePostSelectionChangedListener(
1547:                        ISelectionChangedListener listener) {
1548:                    if (fSourceViewer != null) {
1549:                        if (fSourceViewer.getSelectionProvider() instanceof  IPostSelectionProvider) {
1550:                            IPostSelectionProvider provider = (IPostSelectionProvider) fSourceViewer
1551:                                    .getSelectionProvider();
1552:                            provider
1553:                                    .removePostSelectionChangedListener(listener);
1554:                        }
1555:                    }
1556:                }
1557:
1558:                /*
1559:                 * @see org.eclipse.jface.text.IPostSelectionValidator#isValid()
1560:                 * @since 3.0
1561:                 */
1562:                public boolean isValid(ISelection postSelection) {
1563:                    return fSelectionListener != null
1564:                            && fSelectionListener.isValid(postSelection);
1565:                }
1566:            }
1567:
1568:            /**
1569:             * Internal implementation class for a change listener.
1570:             * @since 3.0
1571:             */
1572:            protected abstract class AbstractSelectionChangedListener implements 
1573:                    ISelectionChangedListener {
1574:
1575:                /**
1576:                 * Installs this selection changed listener with the given selection provider. If
1577:                 * the selection provider is a post selection provider, post selection changed
1578:                 * events are the preferred choice, otherwise normal selection changed events
1579:                 * are requested.
1580:                 *
1581:                 * @param selectionProvider
1582:                 */
1583:                public void install(ISelectionProvider selectionProvider) {
1584:                    if (selectionProvider == null)
1585:                        return;
1586:
1587:                    if (selectionProvider instanceof  IPostSelectionProvider) {
1588:                        IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
1589:                        provider.addPostSelectionChangedListener(this );
1590:                    } else {
1591:                        selectionProvider.addSelectionChangedListener(this );
1592:                    }
1593:                }
1594:
1595:                /**
1596:                 * Removes this selection changed listener from the given selection provider.
1597:                 *
1598:                 * @param selectionProvider the selection provider
1599:                 */
1600:                public void uninstall(ISelectionProvider selectionProvider) {
1601:                    if (selectionProvider == null)
1602:                        return;
1603:
1604:                    if (selectionProvider instanceof  IPostSelectionProvider) {
1605:                        IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
1606:                        provider.removePostSelectionChangedListener(this );
1607:                    } else {
1608:                        selectionProvider.removeSelectionChangedListener(this );
1609:                    }
1610:                }
1611:            }
1612:
1613:            /**
1614:             * This selection listener allows the SelectionProvider to implement {@link ISelectionValidator}.
1615:             *
1616:             * @since 3.0
1617:             */
1618:            private class SelectionListener extends
1619:                    AbstractSelectionChangedListener implements 
1620:                    IDocumentListener {
1621:
1622:                private IDocument fDocument;
1623:                private final Object INVALID_SELECTION = new Object();
1624:                private Object fPostSelection = INVALID_SELECTION;
1625:
1626:                /*
1627:                 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
1628:                 */
1629:                public synchronized void selectionChanged(
1630:                        SelectionChangedEvent event) {
1631:                    fPostSelection = event.getSelection();
1632:                }
1633:
1634:                /*
1635:                 * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
1636:                 * @since 3.0
1637:                 */
1638:                public synchronized void documentAboutToBeChanged(
1639:                        DocumentEvent event) {
1640:                    fPostSelection = INVALID_SELECTION;
1641:                }
1642:
1643:                /*
1644:                 * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
1645:                 * @since 3.0
1646:                 */
1647:                public void documentChanged(DocumentEvent event) {
1648:                }
1649:
1650:                public synchronized boolean isValid(ISelection selection) {
1651:                    return fPostSelection != INVALID_SELECTION
1652:                            && fPostSelection == selection;
1653:                }
1654:
1655:                public void setDocument(IDocument document) {
1656:                    if (fDocument != null)
1657:                        fDocument.removeDocumentListener(this );
1658:
1659:                    fDocument = document;
1660:                    if (fDocument != null)
1661:                        fDocument.addDocumentListener(this );
1662:                }
1663:
1664:                /*
1665:                 * @see org.eclipse.ui.texteditor.AbstractTextEditor.AbstractSelectionChangedListener#install(org.eclipse.jface.viewers.ISelectionProvider)
1666:                 * @since 3.0
1667:                 */
1668:                public void install(ISelectionProvider selectionProvider) {
1669:                    super .install(selectionProvider);
1670:
1671:                    if (selectionProvider != null)
1672:                        selectionProvider.addSelectionChangedListener(this );
1673:                }
1674:
1675:                /*
1676:                 * @see org.eclipse.ui.texteditor.AbstractTextEditor.AbstractSelectionChangedListener#uninstall(org.eclipse.jface.viewers.ISelectionProvider)
1677:                 * @since 3.0
1678:                 */
1679:                public void uninstall(ISelectionProvider selectionProvider) {
1680:                    if (selectionProvider != null)
1681:                        selectionProvider.removeSelectionChangedListener(this );
1682:
1683:                    if (fDocument != null) {
1684:                        fDocument.removeDocumentListener(this );
1685:                        fDocument = null;
1686:                    }
1687:                    super .uninstall(selectionProvider);
1688:                }
1689:            }
1690:
1691:            /**
1692:             * Implements the ruler column support of for the given editor.
1693:             * <p>
1694:             * This is currently only used to support vertical ruler columns.
1695:             * </p>
1696:             * 
1697:             * @since 3.3
1698:             */
1699:            protected static class ColumnSupport implements  IColumnSupport {
1700:                private final AbstractTextEditor fEditor;
1701:                private final RulerColumnRegistry fRegistry;
1702:                private final List fColumns;
1703:
1704:                /**
1705:                 * Creates a new column support for the given editor. Only the editor itself should normally
1706:                 * create such an instance.
1707:                 * 
1708:                 * @param editor the editor
1709:                 * @param registry the contribution registry to refer to
1710:                 */
1711:                public ColumnSupport(AbstractTextEditor editor,
1712:                        RulerColumnRegistry registry) {
1713:                    Assert.isLegal(editor != null);
1714:                    Assert.isLegal(registry != null);
1715:                    fEditor = editor;
1716:                    fRegistry = registry;
1717:                    fColumns = new ArrayList();
1718:                }
1719:
1720:                /*
1721:                 * @see org.eclipse.ui.texteditor.IColumnSupport#setColumnVisible(java.lang.String, boolean)
1722:                 */
1723:                public final void setColumnVisible(
1724:                        RulerColumnDescriptor descriptor, boolean visible) {
1725:                    Assert.isLegal(descriptor != null);
1726:
1727:                    final CompositeRuler ruler = getRuler();
1728:                    if (ruler == null)
1729:                        return;
1730:
1731:                    if (!isColumnSupported(descriptor))
1732:                        visible = false;
1733:
1734:                    if (isColumnVisible(descriptor)) {
1735:                        if (!visible)
1736:                            removeColumn(ruler, descriptor);
1737:                    } else {
1738:                        if (visible)
1739:                            addColumn(ruler, descriptor);
1740:                    }
1741:                }
1742:
1743:                private void addColumn(final CompositeRuler ruler,
1744:                        final RulerColumnDescriptor descriptor) {
1745:
1746:                    final int idx = computeIndex(ruler, descriptor);
1747:
1748:                    SafeRunnable runnable = new SafeRunnable() {
1749:                        public void run() throws Exception {
1750:                            IContributedRulerColumn column = descriptor
1751:                                    .createColumn(fEditor);
1752:                            fColumns.add(column);
1753:                            initializeColumn(column);
1754:                            ruler.addDecorator(idx, column);
1755:                        }
1756:                    };
1757:                    SafeRunner.run(runnable);
1758:                }
1759:
1760:                /**
1761:                 * Hook to let subclasses initialize a newly created column.
1762:                 * <p>
1763:                 * Subclasses may extend this method.</p>
1764:                 * 
1765:                 * @param column the created column
1766:                 */
1767:                protected void initializeColumn(IContributedRulerColumn column) {
1768:                }
1769:
1770:                private void removeColumn(final CompositeRuler ruler,
1771:                        final RulerColumnDescriptor descriptor) {
1772:                    removeColumn(ruler, getVisibleColumn(ruler, descriptor));
1773:                }
1774:
1775:                private void removeColumn(final CompositeRuler ruler,
1776:                        final IContributedRulerColumn rulerColumn) {
1777:                    if (rulerColumn != null) {
1778:                        SafeRunnable runnable = new SafeRunnable() {
1779:                            public void run() throws Exception {
1780:                                if (ruler != null)
1781:                                    ruler.removeDecorator(rulerColumn);
1782:                                rulerColumn.columnRemoved();
1783:                            }
1784:                        };
1785:                        SafeRunner.run(runnable);
1786:                    }
1787:                }
1788:
1789:                /**
1790:                 * Returns the currently visible column matching <code>id</code>, <code>null</code> if
1791:                 * none.
1792:                 * 
1793:                 * @param ruler the composite ruler to scan
1794:                 * @param descriptor the descriptor of the column of interest
1795:                 * @return the matching column or <code>null</code>
1796:                 */
1797:                private IContributedRulerColumn getVisibleColumn(
1798:                        CompositeRuler ruler, RulerColumnDescriptor descriptor) {
1799:                    for (Iterator it = ruler.getDecoratorIterator(); it
1800:                            .hasNext();) {
1801:                        IVerticalRulerColumn column = (IVerticalRulerColumn) it
1802:                                .next();
1803:                        if (column instanceof  IContributedRulerColumn) {
1804:                            IContributedRulerColumn rulerColumn = (IContributedRulerColumn) column;
1805:                            RulerColumnDescriptor rcd = rulerColumn
1806:                                    .getDescriptor();
1807:                            if (descriptor.equals(rcd))
1808:                                return rulerColumn;
1809:                        }
1810:                    }
1811:                    return null;
1812:                }
1813:
1814:                /**
1815:                 * Computes the insertion index for a column contribution into the currently visible columns.
1816:                 * 
1817:                 * @param ruler the composite ruler into which to insert the column
1818:                 * @param descriptor the descriptor to compute the index for
1819:                 * @return the insertion index for a new column
1820:                 */
1821:                private int computeIndex(CompositeRuler ruler,
1822:                        RulerColumnDescriptor descriptor) {
1823:                    int index = 0;
1824:                    List all = fRegistry.getColumnDescriptors();
1825:                    int newPos = all.indexOf(descriptor);
1826:                    for (Iterator it = ruler.getDecoratorIterator(); it
1827:                            .hasNext();) {
1828:                        IVerticalRulerColumn column = (IVerticalRulerColumn) it
1829:                                .next();
1830:                        if (column instanceof  IContributedRulerColumn) {
1831:                            RulerColumnDescriptor rcd = ((IContributedRulerColumn) column)
1832:                                    .getDescriptor();
1833:                            if (rcd != null && all.indexOf(rcd) > newPos)
1834:                                break;
1835:                        } else if ("org.eclipse.jface.text.source.projection.ProjectionRulerColumn".equals(column.getClass().getName())) { //$NON-NLS-1$
1836:                            // projection column is always the rightmost column
1837:                            break;
1838:                        }
1839:                        index++;
1840:                    }
1841:                    return index;
1842:                }
1843:
1844:                /*
1845:                 * @see org.eclipse.ui.texteditor.IColumnSupport#isColumnVisible(java.lang.String)
1846:                 */
1847:                public final boolean isColumnVisible(
1848:                        RulerColumnDescriptor descriptor) {
1849:                    Assert.isLegal(descriptor != null);
1850:                    CompositeRuler ruler = getRuler();
1851:                    return ruler != null
1852:                            && getVisibleColumn(ruler, descriptor) != null;
1853:                }
1854:
1855:                /*
1856:                 * @see org.eclipse.ui.texteditor.IColumnSupport#isColumnSupported(java.lang.String)
1857:                 */
1858:                public final boolean isColumnSupported(
1859:                        RulerColumnDescriptor descriptor) {
1860:                    Assert.isLegal(descriptor != null);
1861:                    if (getRuler() == null)
1862:                        return false;
1863:
1864:                    if (descriptor == null)
1865:                        return false;
1866:
1867:                    return descriptor.matchesEditor(fEditor);
1868:                }
1869:
1870:                /**
1871:                 * Returns the editor's vertical ruler, if it is a {@link CompositeRuler}, <code>null</code>
1872:                 * otherwise.
1873:                 * 
1874:                 * @return the editor's {@link CompositeRuler} or <code>null</code>
1875:                 */
1876:                private CompositeRuler getRuler() {
1877:                    Object ruler = fEditor.getAdapter(IVerticalRulerInfo.class);
1878:                    if (ruler instanceof  CompositeRuler)
1879:                        return (CompositeRuler) ruler;
1880:                    return null;
1881:                }
1882:
1883:                /**
1884:                 * {@inheritDoc}
1885:                 * <p>
1886:                 * Subclasses may extend this method.</p>
1887:                 * 
1888:                 */
1889:                public void dispose() {
1890:                    for (Iterator iter = new ArrayList(fColumns).iterator(); iter
1891:                            .hasNext();)
1892:                        removeColumn(getRuler(), (IContributedRulerColumn) iter
1893:                                .next());
1894:                    fColumns.clear();
1895:                }
1896:            }
1897:
1898:            /**
1899:             * Information provider used to present focusable information shells.
1900:             *
1901:             * @since 3.3
1902:             */
1903:            private static final class InformationProvider implements 
1904:                    IInformationProvider, IInformationProviderExtension,
1905:                    IInformationProviderExtension2 {
1906:
1907:                private IRegion fHoverRegion;
1908:                private Object fHoverInfo;
1909:                private IInformationControlCreator fControlCreator;
1910:
1911:                InformationProvider(IRegion hoverRegion, Object hoverInfo,
1912:                        IInformationControlCreator controlCreator) {
1913:                    fHoverRegion = hoverRegion;
1914:                    fHoverInfo = hoverInfo;
1915:                    fControlCreator = controlCreator;
1916:                }
1917:
1918:                /*
1919:                 * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer, int)
1920:                 */
1921:                public IRegion getSubject(ITextViewer textViewer,
1922:                        int invocationOffset) {
1923:                    return fHoverRegion;
1924:                }
1925:
1926:                /*
1927:                 * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
1928:                 */
1929:                public String getInformation(ITextViewer textViewer,
1930:                        IRegion subject) {
1931:                    return fHoverInfo.toString();
1932:                }
1933:
1934:                /*
1935:                 * @see org.eclipse.jface.text.information.IInformationProviderExtension#getInformation2(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
1936:                 * @since 3.2
1937:                 */
1938:                public Object getInformation2(ITextViewer textViewer,
1939:                        IRegion subject) {
1940:                    return fHoverInfo;
1941:                }
1942:
1943:                /*
1944:                 * @see org.eclipse.jface.text.information.IInformationProviderExtension2#getInformationPresenterControlCreator()
1945:                 */
1946:                public IInformationControlCreator getInformationPresenterControlCreator() {
1947:                    return fControlCreator;
1948:                }
1949:            }
1950:
1951:            /**
1952:             * This action behaves in two different ways: If there is no current text
1953:             * hover, the javadoc is displayed using information presenter. If there is
1954:             * a current text hover, it is converted into a information presenter in
1955:             * order to make it sticky.
1956:             * 
1957:             * @since 3.3
1958:             */
1959:            private final class InformationDispatchAction extends
1960:                    TextEditorAction {
1961:
1962:                /** The wrapped text operation action. */
1963:                private final TextOperationAction fTextOperationAction;
1964:
1965:                /**
1966:                 * Creates a dispatch action.
1967:                 *
1968:                 * @param resourceBundle the resource bundle
1969:                 * @param prefix the prefix
1970:                 * @param textOperationAction the text operation action
1971:                 */
1972:                public InformationDispatchAction(ResourceBundle resourceBundle,
1973:                        String prefix,
1974:                        final TextOperationAction textOperationAction) {
1975:                    super (resourceBundle, prefix, AbstractTextEditor.this );
1976:                    if (textOperationAction == null)
1977:                        throw new IllegalArgumentException();
1978:                    fTextOperationAction = textOperationAction;
1979:                }
1980:
1981:                /*
1982:                 * @see org.eclipse.jface.action.IAction#run()
1983:                 */
1984:                public void run() {
1985:
1986:                    ISourceViewer sourceViewer = getSourceViewer();
1987:                    if (sourceViewer == null) {
1988:                        if (fTextOperationAction.isEnabled())
1989:                            fTextOperationAction.run();
1990:                        return;
1991:                    }
1992:
1993:                    if (sourceViewer instanceof  ITextViewerExtension4) {
1994:                        ITextViewerExtension4 extension4 = (ITextViewerExtension4) sourceViewer;
1995:                        if (extension4.moveFocusToWidgetToken())
1996:                            return;
1997:                    }
1998:
1999:                    if (sourceViewer instanceof  ITextViewerExtension2) {
2000:                        // does a text hover exist?
2001:                        ITextHover textHover = ((ITextViewerExtension2) sourceViewer)
2002:                                .getCurrentTextHover();
2003:                        if (textHover != null
2004:                                && makeTextHoverFocusable(sourceViewer,
2005:                                        textHover))
2006:                            return;
2007:                    }
2008:
2009:                    if (sourceViewer instanceof  ISourceViewerExtension3) {
2010:                        // does an annotation hover exist?
2011:                        IAnnotationHover annotationHover = ((ISourceViewerExtension3) sourceViewer)
2012:                                .getCurrentAnnotationHover();
2013:                        if (annotationHover != null
2014:                                && makeAnnotationHoverFocusable(sourceViewer,
2015:                                        annotationHover))
2016:                            return;
2017:                    }
2018:
2019:                    // otherwise, just run the action
2020:                    if (fTextOperationAction.isEnabled())
2021:                        fTextOperationAction.run();
2022:                }
2023:
2024:                /**
2025:                 * Tries to make a text hover focusable (or "sticky").
2026:                 * 
2027:                 * @param sourceViewer the source viewer to display the hover over
2028:                 * @param textHover the hover to make focusable
2029:                 * @return <code>true</code> if successful, <code>false</code> otherwise
2030:                 */
2031:                private boolean makeTextHoverFocusable(
2032:                        ISourceViewer sourceViewer, ITextHover textHover) {
2033:                    Point hoverEventLocation = ((ITextViewerExtension2) sourceViewer)
2034:                            .getHoverEventLocation();
2035:                    int offset = computeOffsetAtLocation(sourceViewer,
2036:                            hoverEventLocation.x, hoverEventLocation.y);
2037:                    if (offset == -1)
2038:                        return false;
2039:
2040:                    try {
2041:                        IRegion hoverRegion = textHover.getHoverRegion(
2042:                                sourceViewer, offset);
2043:                        if (hoverRegion == null)
2044:                            return false;
2045:
2046:                        String hoverInfo = textHover.getHoverInfo(sourceViewer,
2047:                                hoverRegion);
2048:
2049:                        IInformationControlCreator controlCreator = null;
2050:                        if (textHover instanceof  IInformationProviderExtension2)
2051:                            controlCreator = ((IInformationProviderExtension2) textHover)
2052:                                    .getInformationPresenterControlCreator();
2053:
2054:                        IInformationProvider informationProvider = new InformationProvider(
2055:                                hoverRegion, hoverInfo, controlCreator);
2056:
2057:                        fInformationPresenter.setOffset(offset);
2058:                        fInformationPresenter
2059:                                .setAnchor(AbstractInformationControlManager.ANCHOR_BOTTOM);
2060:                        fInformationPresenter.setMargins(6, 6); // default values from AbstractInformationControlManager
2061:                        String contentType = TextUtilities.getContentType(
2062:                                sourceViewer.getDocument(),
2063:                                getSourceViewerConfiguration()
2064:                                        .getConfiguredDocumentPartitioning(
2065:                                                getSourceViewer()), offset,
2066:                                true);
2067:                        fInformationPresenter.setInformationProvider(
2068:                                informationProvider, contentType);
2069:                        fInformationPresenter.showInformation();
2070:
2071:                        return true;
2072:
2073:                    } catch (BadLocationException e) {
2074:                        return false;
2075:                    }
2076:                }
2077:
2078:                /**
2079:                 * Tries to make an annotation hover focusable (or "sticky").
2080:                 * 
2081:                 * @param sourceViewer the source viewer to display the hover over
2082:                 * @param annotationHover the hover to make focusable
2083:                 * @return <code>true</code> if successful, <code>false</code> otherwise
2084:                 */
2085:                private boolean makeAnnotationHoverFocusable(
2086:                        ISourceViewer sourceViewer,
2087:                        IAnnotationHover annotationHover) {
2088:                    IVerticalRulerInfo info = getVerticalRuler();
2089:                    int line = info.getLineOfLastMouseButtonActivity();
2090:                    if (line == -1)
2091:                        return false;
2092:
2093:                    try {
2094:
2095:                        // compute the hover information
2096:                        Object hoverInfo;
2097:                        if (annotationHover instanceof  IAnnotationHoverExtension) {
2098:                            IAnnotationHoverExtension extension = (IAnnotationHoverExtension) annotationHover;
2099:                            ILineRange hoverLineRange = extension
2100:                                    .getHoverLineRange(sourceViewer, line);
2101:                            if (hoverLineRange == null)
2102:                                return false;
2103:                            final int maxVisibleLines = Integer.MAX_VALUE; // allow any number of lines being displayed, as we support scrolling
2104:                            hoverInfo = extension.getHoverInfo(sourceViewer,
2105:                                    hoverLineRange, maxVisibleLines);
2106:                        } else {
2107:                            hoverInfo = annotationHover.getHoverInfo(
2108:                                    sourceViewer, line);
2109:                        }
2110:
2111:                        // hover region: the beginning of the concerned line to place the control right over the line
2112:                        IDocument document = sourceViewer.getDocument();
2113:                        int offset = document.getLineOffset(line);
2114:                        String contentType = TextUtilities.getContentType(
2115:                                document, getSourceViewerConfiguration()
2116:                                        .getConfiguredDocumentPartitioning(
2117:                                                getSourceViewer()), offset,
2118:                                true);
2119:
2120:                        IInformationControlCreator controlCreator = null;
2121:                        if (annotationHover instanceof  IInformationProviderExtension2)
2122:                            controlCreator = ((IInformationProviderExtension2) annotationHover)
2123:                                    .getInformationPresenterControlCreator();
2124:                        else if (annotationHover instanceof  IAnnotationHoverExtension)
2125:                            controlCreator = ((IAnnotationHoverExtension) annotationHover)
2126:                                    .getHoverControlCreator();
2127:
2128:                        IInformationProvider informationProvider = new InformationProvider(
2129:                                new Region(offset, 0), hoverInfo,
2130:                                controlCreator);
2131:
2132:                        fInformationPresenter.setOffset(offset);
2133:                        fInformationPresenter
2134:                                .setAnchor(AbstractInformationControlManager.ANCHOR_RIGHT);
2135:                        fInformationPresenter.setMargins(4, 0); // AnnotationBarHoverManager sets (5,0), minus SourceViewer.GAP_SIZE_1
2136:                        fInformationPresenter.setInformationProvider(
2137:                                informationProvider, contentType);
2138:                        fInformationPresenter.showInformation();
2139:
2140:                        return true;
2141:
2142:                    } catch (BadLocationException e) {
2143:                        return false;
2144:                    }
2145:                }
2146:
2147:                // modified version from TextViewer
2148:                private int computeOffsetAtLocation(ITextViewer textViewer,
2149:                        int x, int y) {
2150:
2151:                    StyledText styledText = textViewer.getTextWidget();
2152:                    IDocument document = textViewer.getDocument();
2153:
2154:                    if (document == null)
2155:                        return -1;
2156:
2157:                    try {
2158:                        int widgetOffset = styledText
2159:                                .getOffsetAtLocation(new Point(x, y));
2160:                        Point p = styledText.getLocationAtOffset(widgetOffset);
2161:                        if (p.x > x)
2162:                            widgetOffset--;
2163:
2164:                        if (textViewer instanceof  ITextViewerExtension5) {
2165:                            ITextViewerExtension5 extension = (ITextViewerExtension5) textViewer;
2166:                            return extension
2167:                                    .widgetOffset2ModelOffset(widgetOffset);
2168:                        }
2169:                        IRegion visibleRegion = textViewer.getVisibleRegion();
2170:                        return widgetOffset + visibleRegion.getOffset();
2171:                    } catch (IllegalArgumentException e) {
2172:                        return -1;
2173:                    }
2174:
2175:                }
2176:            }
2177:
2178:            /**
2179:             * Key used to look up font preference.
2180:             * Value: <code>"org.eclipse.jface.textfont"</code>
2181:             *
2182:             * @deprecated As of 2.1, replaced by {@link JFaceResources#TEXT_FONT}
2183:             */
2184:            public final static String PREFERENCE_FONT = JFaceResources.TEXT_FONT;
2185:            /**
2186:             * Key used to look up foreground color preference.
2187:             * Value: <code>AbstractTextEditor.Color.Foreground</code>
2188:             * @since 2.0
2189:             */
2190:            public final static String PREFERENCE_COLOR_FOREGROUND = "AbstractTextEditor.Color.Foreground"; //$NON-NLS-1$
2191:            /**
2192:             * Key used to look up background color preference.
2193:             * Value: <code>AbstractTextEditor.Color.Background</code>
2194:             * @since 2.0
2195:             */
2196:            public final static String PREFERENCE_COLOR_BACKGROUND = "AbstractTextEditor.Color.Background"; //$NON-NLS-1$
2197:            /**
2198:             * Key used to look up foreground color system default preference.
2199:             * Value: <code>AbstractTextEditor.Color.Foreground.SystemDefault</code>
2200:             * @since 2.0
2201:             */
2202:            public final static String PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT = "AbstractTextEditor.Color.Foreground.SystemDefault"; //$NON-NLS-1$
2203:            /**
2204:             * Key used to look up background color system default preference.
2205:             * Value: <code>AbstractTextEditor.Color.Background.SystemDefault</code>
2206:             * @since 2.0
2207:             */
2208:            public final static String PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT = "AbstractTextEditor.Color.Background.SystemDefault"; //$NON-NLS-1$
2209:            /**
2210:             * Key used to look up selection foreground color preference.
2211:             * Value: <code>AbstractTextEditor.Color.SelectionForeground</code>
2212:             * @since 3.0
2213:             */
2214:            public final static String PREFERENCE_COLOR_SELECTION_FOREGROUND = "AbstractTextEditor.Color.SelectionForeground"; //$NON-NLS-1$
2215:            /**
2216:             * Key used to look up selection background color preference.
2217:             * Value: <code>AbstractTextEditor.Color.SelectionBackground</code>
2218:             * @since 3.0
2219:             */
2220:            public final static String PREFERENCE_COLOR_SELECTION_BACKGROUND = "AbstractTextEditor.Color.SelectionBackground"; //$NON-NLS-1$
2221:            /**
2222:             * Key used to look up selection foreground color system default preference.
2223:             * Value: <code>AbstractTextEditor.Color.SelectionForeground.SystemDefault</code>
2224:             * @since 3.0
2225:             */
2226:            public final static String PREFERENCE_COLOR_SELECTION_FOREGROUND_SYSTEM_DEFAULT = "AbstractTextEditor.Color.SelectionForeground.SystemDefault"; //$NON-NLS-1$
2227:            /**
2228:             * Key used to look up selection background color system default preference.
2229:             * Value: <code>AbstractTextEditor.Color.SelectionBackground.SystemDefault</code>
2230:             * @since 3.0
2231:             */
2232:            public final static String PREFERENCE_COLOR_SELECTION_BACKGROUND_SYSTEM_DEFAULT = "AbstractTextEditor.Color.SelectionBackground.SystemDefault"; //$NON-NLS-1$
2233:            /**
2234:             * Key used to look up find scope background color preference.
2235:             * Value: <code>AbstractTextEditor.Color.FindScope</code>
2236:             * @since 2.0
2237:             */
2238:            public final static String PREFERENCE_COLOR_FIND_SCOPE = "AbstractTextEditor.Color.FindScope"; //$NON-NLS-1$
2239:            /**
2240:             * Key used to look up smart home/end preference.
2241:             * Value: <code>AbstractTextEditor.Navigation.SmartHomeEnd</code>
2242:             * @since 2.1
2243:             */
2244:            public final static String PREFERENCE_NAVIGATION_SMART_HOME_END = "AbstractTextEditor.Navigation.SmartHomeEnd"; //$NON-NLS-1$
2245:            /**
2246:             * Key used to look up the custom caret preference.
2247:             * Value: {@value}
2248:             * @since 3.0
2249:             */
2250:            public final static String PREFERENCE_USE_CUSTOM_CARETS = "AbstractTextEditor.Accessibility.UseCustomCarets"; //$NON-NLS-1$
2251:            /**
2252:             * Key used to look up the caret width preference.
2253:             * Value: {@value}
2254:             * @since 3.0
2255:             */
2256:            public final static String PREFERENCE_WIDE_CARET = "AbstractTextEditor.Accessibility.WideCaret"; //$NON-NLS-1$
2257:            /**
2258:             * A named preference that controls if hyperlinks are turned on or off.
2259:             * <p>
2260:             * Value is of type <code>Boolean</code>.
2261:             * </p>
2262:             *
2263:             * @since 3.1
2264:             */
2265:            public static final String PREFERENCE_HYPERLINKS_ENABLED = "hyperlinksEnabled"; //$NON-NLS-1$
2266:
2267:            /**
2268:             * A named preference that controls the key modifier for hyperlinks.
2269:             * <p>
2270:             * Value is of type <code>String</code>.
2271:             * </p>
2272:             *
2273:             * @since 3.1
2274:             */
2275:            public static final String PREFERENCE_HYPERLINK_KEY_MODIFIER = "hyperlinkKeyModifier"; //$NON-NLS-1$
2276:            /**
2277:             * A named preference that controls the key modifier mask for hyperlinks.
2278:             * The value is only used if the value of <code>PREFERENCE_HYPERLINK_KEY_MODIFIER</code>
2279:             * cannot be resolved to valid SWT modifier bits.
2280:             * <p>
2281:             * Value is of type <code>String</code>.
2282:             * </p>
2283:             *
2284:             * @see #PREFERENCE_HYPERLINK_KEY_MODIFIER
2285:             * @since 3.1
2286:             */
2287:            public static final String PREFERENCE_HYPERLINK_KEY_MODIFIER_MASK = "hyperlinkKeyModifierMask"; //$NON-NLS-1$
2288:            /**
2289:             * A named preference that controls the visible ruler column contributions.
2290:             * <p>
2291:             * Value is of type <code>String</code> and should be read using a {@link RulerColumnPreferenceAdapter}.
2292:             * </p>
2293:             *
2294:             * @since 3.3
2295:             */
2296:            public static final String PREFERENCE_RULER_CONTRIBUTIONS = "rulerContributions"; //$NON-NLS-1$
2297:            /**
2298:             * A named preference that controls the display of whitespace characters.
2299:             * <p>
2300:             * Value is of type <code>Boolean</code>.
2301:             * </p>
2302:             *
2303:             * @since 3.3
2304:             */
2305:            public static final String PREFERENCE_SHOW_WHITESPACE_CHARACTERS = "showWhitespaceCharacters"; //$NON-NLS-1$
2306:            /**
2307:             * A named preference that controls whether text drag and drop is enabled.
2308:             * <p>
2309:             * Value is of type <code>Boolean</code>.
2310:             * </p>
2311:             *
2312:             * @since 3.3
2313:             */
2314:            public static final String PREFERENCE_TEXT_DRAG_AND_DROP_ENABLED = "textDragAndDropEnabled"; //$NON-NLS-1$
2315:
2316:            /** Menu id for the editor context menu. */
2317:            public final static String DEFAULT_EDITOR_CONTEXT_MENU_ID = "#EditorContext"; //$NON-NLS-1$
2318:            /** Menu id for the ruler context menu. */
2319:            public final static String DEFAULT_RULER_CONTEXT_MENU_ID = "#RulerContext"; //$NON-NLS-1$
2320:
2321:            /** The width of the vertical ruler. */
2322:            protected final static int VERTICAL_RULER_WIDTH = 12;
2323:
2324:            /**
2325:             * The complete mapping between action definition IDs used by eclipse and StyledText actions.
2326:             *
2327:             * @since 2.0
2328:             */
2329:            protected final static IdMapEntry[] ACTION_MAP = new IdMapEntry[] {
2330:                    // navigation
2331:                    new IdMapEntry(ITextEditorActionDefinitionIds.LINE_UP,
2332:                            ST.LINE_UP),
2333:                    new IdMapEntry(ITextEditorActionDefinitionIds.LINE_DOWN,
2334:                            ST.LINE_DOWN),
2335:                    new IdMapEntry(ITextEditorActionDefinitionIds.LINE_START,
2336:                            ST.LINE_START),
2337:                    new IdMapEntry(ITextEditorActionDefinitionIds.LINE_END,
2338:                            ST.LINE_END),
2339:                    new IdMapEntry(
2340:                            ITextEditorActionDefinitionIds.COLUMN_PREVIOUS,
2341:                            ST.COLUMN_PREVIOUS),
2342:                    new IdMapEntry(ITextEditorActionDefinitionIds.COLUMN_NEXT,
2343:                            ST.COLUMN_NEXT),
2344:                    new IdMapEntry(ITextEditorActionDefinitionIds.PAGE_UP,
2345:                            ST.PAGE_UP),
2346:                    new IdMapEntry(ITextEditorActionDefinitionIds.PAGE_DOWN,
2347:                            ST.PAGE_DOWN),
2348:                    new IdMapEntry(
2349:                            ITextEditorActionDefinitionIds.WORD_PREVIOUS,
2350:                            ST.WORD_PREVIOUS),
2351:                    new IdMapEntry(ITextEditorActionDefinitionIds.WORD_NEXT,
2352:                            ST.WORD_NEXT),
2353:                    new IdMapEntry(ITextEditorActionDefinitionIds.TEXT_START,
2354:                            ST.TEXT_START),
2355:                    new IdMapEntry(ITextEditorActionDefinitionIds.TEXT_END,
2356:                            ST.TEXT_END),
2357:                    new IdMapEntry(ITextEditorActionDefinitionIds.WINDOW_START,
2358:                            ST.WINDOW_START),
2359:                    new IdMapEntry(ITextEditorActionDefinitionIds.WINDOW_END,
2360:                            ST.WINDOW_END),
2361:                    // selection
2362:                    new IdMapEntry(
2363:                            ITextEditorActionDefinitionIds.SELECT_LINE_UP,
2364:                            ST.SELECT_LINE_UP),
2365:                    new IdMapEntry(
2366:                            ITextEditorActionDefinitionIds.SELECT_LINE_DOWN,
2367:                            ST.SELECT_LINE_DOWN),
2368:                    new IdMapEntry(
2369:                            ITextEditorActionDefinitionIds.SELECT_LINE_START,
2370:                            ST.SELECT_LINE_START),
2371:                    new IdMapEntry(
2372:                            ITextEditorActionDefinitionIds.SELECT_LINE_END,
2373:                            ST.SELECT_LINE_END),
2374:                    new IdMapEntry(
2375:                            ITextEditorActionDefinitionIds.SELECT_COLUMN_PREVIOUS,
2376:                            ST.SELECT_COLUMN_PREVIOUS),
2377:                    new IdMapEntry(
2378:                            ITextEditorActionDefinitionIds.SELECT_COLUMN_NEXT,
2379:                            ST.SELECT_COLUMN_NEXT),
2380:                    new IdMapEntry(
2381:                            ITextEditorActionDefinitionIds.SELECT_PAGE_UP,
2382:                            ST.SELECT_PAGE_UP),
2383:                    new IdMapEntry(
2384:                            ITextEditorActionDefinitionIds.SELECT_PAGE_DOWN,
2385:                            ST.SELECT_PAGE_DOWN),
2386:                    new IdMapEntry(
2387:                            ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS,
2388:                            ST.SELECT_WORD_PREVIOUS),
2389:                    new IdMapEntry(
2390:                            ITextEditorActionDefinitionIds.SELECT_WORD_NEXT,
2391:                            ST.SELECT_WORD_NEXT),
2392:                    new IdMapEntry(
2393:                            ITextEditorActionDefinitionIds.SELECT_TEXT_START,
2394:                            ST.SELECT_TEXT_START),
2395:                    new IdMapEntry(
2396:                            ITextEditorActionDefinitionIds.SELECT_TEXT_END,
2397:                            ST.SELECT_TEXT_END),
2398:                    new IdMapEntry(
2399:                            ITextEditorActionDefinitionIds.SELECT_WINDOW_START,
2400:                            ST.SELECT_WINDOW_START),
2401:                    new IdMapEntry(
2402:                            ITextEditorActionDefinitionIds.SELECT_WINDOW_END,
2403:                            ST.SELECT_WINDOW_END),
2404:                    // modification
2405:                    new IdMapEntry(IWorkbenchActionDefinitionIds.CUT, ST.CUT),
2406:                    new IdMapEntry(IWorkbenchActionDefinitionIds.COPY, ST.COPY),
2407:                    new IdMapEntry(IWorkbenchActionDefinitionIds.PASTE,
2408:                            ST.PASTE),
2409:                    new IdMapEntry(
2410:                            ITextEditorActionDefinitionIds.DELETE_PREVIOUS,
2411:                            ST.DELETE_PREVIOUS),
2412:                    new IdMapEntry(ITextEditorActionDefinitionIds.DELETE_NEXT,
2413:                            ST.DELETE_NEXT),
2414:                    new IdMapEntry(
2415:                            ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD,
2416:                            ST.DELETE_WORD_PREVIOUS),
2417:                    new IdMapEntry(
2418:                            ITextEditorActionDefinitionIds.DELETE_NEXT_WORD,
2419:                            ST.DELETE_WORD_NEXT),
2420:                    // miscellaneous
2421:                    new IdMapEntry(
2422:                            ITextEditorActionDefinitionIds.TOGGLE_OVERWRITE,
2423:                            ST.TOGGLE_OVERWRITE) };
2424:
2425:            private final String fReadOnlyLabel = EditorMessages.Editor_statusline_state_readonly_label;
2426:            private final String fWritableLabel = EditorMessages.Editor_statusline_state_writable_label;
2427:            private final String fInsertModeLabel = EditorMessages.Editor_statusline_mode_insert_label;
2428:            private final String fOverwriteModeLabel = EditorMessages.Editor_statusline_mode_overwrite_label;
2429:            private final String fSmartInsertModeLabel = EditorMessages.Editor_statusline_mode_smartinsert_label;
2430:
2431:            /** The error message shown in the status line in case of failed information look up. */
2432:            protected final String fErrorLabel = EditorMessages.Editor_statusline_error_label;
2433:
2434:            /**
2435:             * Data structure for the position label value.
2436:             */
2437:            private static class PositionLabelValue {
2438:
2439:                public int fValue;
2440:
2441:                public String toString() {
2442:                    return String.valueOf(fValue);
2443:                }
2444:            }
2445:
2446:            /** The pattern used to show the position label in the status line. */
2447:            private final String fPositionLabelPattern = EditorMessages.Editor_statusline_position_pattern;
2448:            /** The position label value of the current line. */
2449:            private final PositionLabelValue fLineLabel = new PositionLabelValue();
2450:            /** The position label value of the current column. */
2451:            private final PositionLabelValue fColumnLabel = new PositionLabelValue();
2452:            /** The arguments for the position label pattern. */
2453:            private final Object[] fPositionLabelPatternArguments = new Object[] {
2454:                    fLineLabel, fColumnLabel };
2455:            /**
2456:             * The column support of this editor.
2457:             * @since 3.3
2458:             */
2459:            private IColumnSupport fColumnSupport;
2460:
2461:            /** The editor's explicit document provider. */
2462:            private IDocumentProvider fExplicitDocumentProvider;
2463:            /** The editor's preference store. */
2464:            private IPreferenceStore fPreferenceStore;
2465:            /** The editor's range indicator. */
2466:            private Annotation fRangeIndicator;
2467:            /** The editor's source viewer configuration. */
2468:            private SourceViewerConfiguration fConfiguration;
2469:            /** The editor's source viewer. */
2470:            private ISourceViewer fSourceViewer;
2471:            /**
2472:             * The editor's selection provider.
2473:             * @since 2.1
2474:             */
2475:            private SelectionProvider fSelectionProvider = new SelectionProvider();
2476:            /**
2477:             * The editor's selection listener.
2478:             * @since 3.0
2479:             */
2480:            private SelectionListener fSelectionListener;
2481:            /** The editor's font. */
2482:            private Font fFont;
2483:            /**
2484:             * The editor's foreground color.
2485:             * @since 2.0
2486:             */
2487:            private Color fForegroundColor;
2488:            /**
2489:             * The editor's background color.
2490:             * @since 2.0
2491:             */
2492:            private Color fBackgroundColor;
2493:            /**
2494:             * The editor's selection foreground color.
2495:             * @since 3.0
2496:             */
2497:            private Color fSelectionForegroundColor;
2498:            /**
2499:             * The editor's selection background color.
2500:             * @since 3.0
2501:             */
2502:            private Color fSelectionBackgroundColor;
2503:            /**
2504:             * The find scope's highlight color.
2505:             * @since 2.0
2506:             */
2507:            private Color fFindScopeHighlightColor;
2508:
2509:            /**
2510:             * The editor's status line.
2511:             * @since 2.1
2512:             */
2513:            private IEditorStatusLine fEditorStatusLine;
2514:            /** The editor's vertical ruler. */
2515:            private IVerticalRuler fVerticalRuler;
2516:            /** The editor's context menu id. */
2517:            private String fEditorContextMenuId;
2518:            /** The ruler's context menu id. */
2519:            private String fRulerContextMenuId;
2520:            /** The editor's help context id. */
2521:            private String fHelpContextId;
2522:            /** The editor's presentation mode. */
2523:            private boolean fShowHighlightRangeOnly;
2524:            /** The actions registered with the editor. */
2525:            private Map fActions = new HashMap(10);
2526:            /** The actions marked as selection dependent. */
2527:            private List fSelectionActions = new ArrayList(5);
2528:            /** The actions marked as content dependent. */
2529:            private List fContentActions = new ArrayList(5);
2530:            /**
2531:             * The actions marked as property dependent.
2532:             * @since 2.0
2533:             */
2534:            private List fPropertyActions = new ArrayList(5);
2535:            /**
2536:             * The actions marked as state dependent.
2537:             * @since 2.0
2538:             */
2539:            private List fStateActions = new ArrayList(5);
2540:            /** The editor's action activation codes. */
2541:            private List fActivationCodes = new ArrayList(2);
2542:            /** The verify key listener for activation code triggering. */
2543:            private ActivationCodeTrigger fActivationCodeTrigger = new ActivationCodeTrigger();
2544:            /** Context menu listener. */
2545:            private IMenuListener fMenuListener;
2546:            /** Vertical ruler mouse listener. */
2547:            private MouseListener fMouseListener;
2548:            /** Selection changed listener. */
2549:            private ISelectionChangedListener fSelectionChangedListener;
2550:            /** Title image to be disposed. */
2551:            private Image fTitleImage;
2552:            /** The text context menu to be disposed. */
2553:            private Menu fTextContextMenu;
2554:            /** The ruler context menu to be disposed. */
2555:            private Menu fRulerContextMenu;
2556:            /** The editor's element state listener. */
2557:            private IElementStateListener fElementStateListener = new ElementStateListener();
2558:            /**
2559:             * The editor's text input listener.
2560:             * @since 2.1
2561:             */
2562:            private TextInputListener fTextInputListener = new TextInputListener();
2563:            /** The editor's text listener. */
2564:            private TextListener fTextListener = new TextListener();
2565:            /** The editor's property change listener. */
2566:            private IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
2567:            /**
2568:             * The editor's font properties change listener.
2569:             * @since 2.1
2570:             */
2571:            private IPropertyChangeListener fFontPropertyChangeListener = new FontPropertyChangeListener();
2572:
2573:            /**
2574:             * The editor's activation listener.
2575:             * @since 2.0
2576:             */
2577:            private ActivationListener fActivationListener;
2578:            /**
2579:             * The map of the editor's status fields.
2580:             * @since 2.0
2581:             */
2582:            private Map fStatusFields;
2583:            /**
2584:             * The editor's cursor listener.
2585:             * @since 2.0
2586:             */
2587:            private ICursorListener fCursorListener;
2588:            /**
2589:             * The editor's remembered text selection.
2590:             * @since 2.0
2591:             */
2592:            private ISelection fRememberedSelection;
2593:            /**
2594:             * Indicates whether the editor runs in 1.0 context menu registration compatibility mode.
2595:             * @since 2.0
2596:             */
2597:            private boolean fCompatibilityMode = true;
2598:            /**
2599:             * The number of re-entrances into error correction code while saving.
2600:             * @since 2.0
2601:             */
2602:            private int fErrorCorrectionOnSave;
2603:            /**
2604:             * The delete line target.
2605:             * @since 2.1
2606:             */
2607:            private DeleteLineTarget fDeleteLineTarget;
2608:            /**
2609:             * The incremental find target.
2610:             * @since 2.0
2611:             */
2612:            private IncrementalFindTarget fIncrementalFindTarget;
2613:            /**
2614:             * The mark region target.
2615:             * @since 2.0
2616:             */
2617:            private IMarkRegionTarget fMarkRegionTarget;
2618:            /**
2619:             * Cached modification stamp of the editor's input.
2620:             * @since 2.0
2621:             */
2622:            private long fModificationStamp = -1;
2623:            /**
2624:             * Ruler context menu listeners.
2625:             * @since 2.0
2626:             */
2627:            private List fRulerContextMenuListeners = new ArrayList();
2628:            /**
2629:             * Indicates whether sanity checking in enabled.
2630:             * @since 2.0
2631:             */
2632:            private boolean fIsSanityCheckEnabled = true;
2633:            /**
2634:             * The find replace target.
2635:             * @since 2.1
2636:             */
2637:            private FindReplaceTarget fFindReplaceTarget;
2638:            /**
2639:             * Indicates whether state validation is enabled.
2640:             * @since 2.1
2641:             */
2642:            private boolean fIsStateValidationEnabled = true;
2643:            /**
2644:             * The key binding scopes of this editor.
2645:             * @since 2.1
2646:             */
2647:            private String[] fKeyBindingScopes;
2648:            /**
2649:             * Whether the overwrite mode can be turned on.
2650:             * @since 3.0
2651:             */
2652:            private boolean fIsOverwriteModeEnabled = true;
2653:            /**
2654:             * Whether the overwrite mode is currently on.
2655:             * @since 3.0
2656:             */
2657:            private boolean fIsOverwriting = false;
2658:            /**
2659:             * The editor's insert mode.
2660:             * @since 3.0
2661:             */
2662:            private InsertMode fInsertMode = SMART_INSERT;
2663:            /**
2664:             * The sequence of legal editor insert modes.
2665:             * @since 3.0
2666:             */
2667:            private List fLegalInsertModes = null;
2668:            /**
2669:             * The non-default caret.
2670:             * @since 3.0
2671:             */
2672:            private Caret fNonDefaultCaret;
2673:            /**
2674:             * The image used in non-default caret.
2675:             * @since 3.0
2676:             */
2677:            private Image fNonDefaultCaretImage;
2678:            /**
2679:             * The styled text's initial caret.
2680:             * @since 3.0
2681:             */
2682:            private Caret fInitialCaret;
2683:            /**
2684:             * The operation approver used to warn on undoing of non-local operations.
2685:             * @since 3.1
2686:             */
2687:            private IOperationApprover fNonLocalOperationApprover;
2688:            /**
2689:             * The operation approver used to warn of linear undo violations.
2690:             * @since 3.1
2691:             */
2692:            private IOperationApprover fLinearUndoViolationApprover;
2693:            /**
2694:             * This editor's memento holding data for restoring it after restart.
2695:             * @since 3.3
2696:             */
2697:            private IMemento fMementoToRestore;
2698:            /**
2699:             * This editor's savable.
2700:             * @since 3.3
2701:             */
2702:            private TextEditorSavable fSavable;
2703:            /**
2704:             * Tells whether text drag and drop is enabled.
2705:             * @since 3.3
2706:             */
2707:            private boolean fIsTextDragAndDropEnabled = false;
2708:            /**
2709:             * Tells whether text drag and drop has been installed on the control.
2710:             * @since 3.3
2711:             */
2712:            private boolean fIsTextDragAndDropInstalled = false;
2713:            /**
2714:             * Helper token to decide whether drag and
2715:             * drop happens inside the same editor.
2716:             * @since 3.3
2717:             */
2718:            private Object fTextDragAndDropToken;
2719:            /**
2720:             * The information presenter.
2721:             * @since 3.3
2722:             */
2723:            private InformationPresenter fInformationPresenter;
2724:
2725:            /**
2726:             * Creates a new text editor. If not explicitly set, this editor uses
2727:             * a <code>SourceViewerConfiguration</code> to configure its
2728:             * source viewer. This viewer does not have a range indicator installed,
2729:             * nor any menu id set. By default, the created editor runs in 1.0 context
2730:             * menu registration compatibility mode.
2731:             */
2732:            protected AbstractTextEditor() {
2733:                super ();
2734:                fEditorContextMenuId = null;
2735:                fRulerContextMenuId = null;
2736:                fHelpContextId = null;
2737:            }
2738:
2739:            /*
2740:             * @see ITextEditor#getDocumentProvider()
2741:             */
2742:            public IDocumentProvider getDocumentProvider() {
2743:                return fExplicitDocumentProvider;
2744:            }
2745:
2746:            /**
2747:             * Returns the editor's range indicator. May return <code>null</code> if no
2748:             * range indicator is installed.
2749:             *
2750:             * @return the editor's range indicator which may be <code>null</code>
2751:             */
2752:            protected final Annotation getRangeIndicator() {
2753:                return fRangeIndicator;
2754:            }
2755:
2756:            /**
2757:             * Returns the editor's source viewer configuration. May return <code>null</code>
2758:             * before the editor's part has been created and after disposal.
2759:             *
2760:             * @return the editor's source viewer configuration which may be <code>null</code>
2761:             */
2762:            protected final SourceViewerConfiguration getSourceViewerConfiguration() {
2763:                return fConfiguration;
2764:            }
2765:
2766:            /**
2767:             * Returns the editor's source viewer. May return <code>null</code> before
2768:             * the editor's part has been created and after disposal.
2769:             *
2770:             * @return the editor's source viewer which may be <code>null</code>
2771:             */
2772:            protected final ISourceViewer getSourceViewer() {
2773:                return fSourceViewer;
2774:            }
2775:
2776:            /**
2777:             * Returns the editor's vertical ruler. May return <code>null</code> before
2778:             * the editor's part has been created and after disposal.
2779:             *
2780:             * @return the editor's vertical ruler which may be <code>null</code>
2781:             */
2782:            protected final IVerticalRuler getVerticalRuler() {
2783:                return fVerticalRuler;
2784:            }
2785:
2786:            /**
2787:             * Returns the editor's context menu id. May return <code>null</code> before
2788:             * the editor's part has been created.
2789:             *
2790:             * @return the editor's context menu id which may be <code>null</code>
2791:             */
2792:            protected final String getEditorContextMenuId() {
2793:                return fEditorContextMenuId;
2794:            }
2795:
2796:            /**
2797:             * Returns the ruler's context menu id. May return <code>null</code> before
2798:             * the editor's part has been created.
2799:             *
2800:             * @return the ruler's context menu id which may be <code>null</code>
2801:             */
2802:            protected final String getRulerContextMenuId() {
2803:                return fRulerContextMenuId;
2804:            }
2805:
2806:            /**
2807:             * Returns the editor's help context id or <code>null</code> if none has
2808:             * been set.
2809:             *
2810:             * @return the editor's help context id which may be <code>null</code>
2811:             */
2812:            protected final String getHelpContextId() {
2813:                return fHelpContextId;
2814:            }
2815:
2816:            /**
2817:             * Returns this editor's preference store or <code>null</code> if none has
2818:             * been set.
2819:             *
2820:             * @return this editor's preference store which may be <code>null</code>
2821:             */
2822:            protected final IPreferenceStore getPreferenceStore() {
2823:                return fPreferenceStore;
2824:            }
2825:
2826:            /**
2827:             * Sets this editor's document provider. This method must be
2828:             * called before the editor's control is created.
2829:             *
2830:             * @param provider the document provider
2831:             */
2832:            protected void setDocumentProvider(IDocumentProvider provider) {
2833:                fExplicitDocumentProvider = provider;
2834:            }
2835:
2836:            /**
2837:             * Sets this editor's source viewer configuration used to configure its
2838:             * internal source viewer. This method must be called before the editor's
2839:             * control is created. If not, this editor uses a <code>SourceViewerConfiguration</code>.
2840:             *
2841:             * @param configuration the source viewer configuration object
2842:             */
2843:            protected void setSourceViewerConfiguration(
2844:                    SourceViewerConfiguration configuration) {
2845:                Assert.isNotNull(configuration);
2846:                fConfiguration = configuration;
2847:            }
2848:
2849:            /**
2850:             * Sets the annotation which this editor uses to represent the highlight
2851:             * range if the editor is configured to show the entire document. If the
2852:             * range indicator is not set, this editor will not show a range indication.
2853:             *
2854:             * @param rangeIndicator the annotation
2855:             */
2856:            protected void setRangeIndicator(Annotation rangeIndicator) {
2857:                Assert.isNotNull(rangeIndicator);
2858:                fRangeIndicator = rangeIndicator;
2859:            }
2860:
2861:            /**
2862:             * Sets this editor's context menu id.
2863:             *
2864:             * @param contextMenuId the context menu id
2865:             */
2866:            protected void setEditorContextMenuId(String contextMenuId) {
2867:                Assert.isNotNull(contextMenuId);
2868:                fEditorContextMenuId = contextMenuId;
2869:            }
2870:
2871:            /**
2872:             * Sets the ruler's context menu id.
2873:             *
2874:             * @param contextMenuId the context menu id
2875:             */
2876:            protected void setRulerContextMenuId(String contextMenuId) {
2877:                Assert.isNotNull(contextMenuId);
2878:                fRulerContextMenuId = contextMenuId;
2879:            }
2880:
2881:            /**
2882:             * Sets the context menu registration 1.0 compatibility mode. (See class
2883:             * description for more details.)
2884:             *
2885:             * @param compatible <code>true</code> if compatibility mode is enabled
2886:             * @since 2.0
2887:             */
2888:            protected final void setCompatibilityMode(boolean compatible) {
2889:                fCompatibilityMode = compatible;
2890:            }
2891:
2892:            /**
2893:             * Sets the editor's help context id.
2894:             *
2895:             * @param helpContextId the help context id
2896:             */
2897:            protected void setHelpContextId(String helpContextId) {
2898:                Assert.isNotNull(helpContextId);
2899:                fHelpContextId = helpContextId;
2900:            }
2901:
2902:            /**
2903:             * Sets the key binding scopes for this editor.
2904:             *
2905:             * @param scopes a non-empty array of key binding scope identifiers
2906:             * @since 2.1
2907:             */
2908:            protected void setKeyBindingScopes(String[] scopes) {
2909:                Assert.isTrue(scopes != null && scopes.length > 0);
2910:                fKeyBindingScopes = scopes;
2911:            }
2912:
2913:            /**
2914:             * Sets this editor's preference store. This method must be
2915:             * called before the editor's control is created.
2916:             *
2917:             * @param store the preference store or <code>null</code> to remove the
2918:             * 		  preference store
2919:             */
2920:            protected void setPreferenceStore(IPreferenceStore store) {
2921:                if (fPreferenceStore != null)
2922:                    fPreferenceStore
2923:                            .removePropertyChangeListener(fPropertyChangeListener);
2924:
2925:                fPreferenceStore = store;
2926:
2927:                if (fPreferenceStore != null)
2928:                    fPreferenceStore
2929:                            .addPropertyChangeListener(fPropertyChangeListener);
2930:            }
2931:
2932:            /*
2933:             * @see ITextEditor#isEditable()
2934:             */
2935:            public boolean isEditable() {
2936:                IDocumentProvider provider = getDocumentProvider();
2937:                if (provider instanceof  IDocumentProviderExtension) {
2938:                    IDocumentProviderExtension extension = (IDocumentProviderExtension) provider;
2939:                    return extension.isModifiable(getEditorInput());
2940:                }
2941:                return false;
2942:            }
2943:
2944:            /**
2945:             * {@inheritDoc}
2946:             * <p>
2947:             * Returns <code>null</code> after disposal.
2948:             * </p>
2949:             *
2950:             * @return the selection provider or <code>null</code> if the editor has
2951:             *         been disposed
2952:             */
2953:            public ISelectionProvider getSelectionProvider() {
2954:                return fSelectionProvider;
2955:            }
2956:
2957:            /**
2958:             * Remembers the current selection of this editor. This method is called when, e.g.,
2959:             * the content of the editor is about to be reverted to the saved state. This method
2960:             * remembers the selection in a semantic format, i.e., in a format which allows to
2961:             * restore the selection even if the originally selected text is no longer part of the
2962:             * editor's content.
2963:             * <p>
2964:             * Subclasses should implement this method including all necessary state. This
2965:             * default implementation remembers the textual range only and is thus purely
2966:             * syntactic.</p>
2967:             *
2968:             * @see #restoreSelection()
2969:             * @since 2.0
2970:             */
2971:            protected void rememberSelection() {
2972:                fRememberedSelection = doGetSelection();
2973:            }
2974:
2975:            /**
2976:             * Returns the current selection.
2977:             * @return ISelection
2978:             * @since 2.1
2979:             */
2980:            protected ISelection doGetSelection() {
2981:                ISelectionProvider sp = null;
2982:                if (fSourceViewer != null)
2983:                    sp = fSourceViewer.getSelectionProvider();
2984:                return (sp == null ? null : sp.getSelection());
2985:            }
2986:
2987:            /**
2988:             * Restores a selection previously remembered by <code>rememberSelection</code>.
2989:             * Subclasses may reimplement this method and thereby semantically adapt the
2990:             * remembered selection. This default implementation just selects the
2991:             * remembered textual range.
2992:             *
2993:             * @see #rememberSelection()
2994:             * @since 2.0
2995:             */
2996:            protected void restoreSelection() {
2997:                if (fRememberedSelection instanceof  ITextSelection) {
2998:                    ITextSelection textSelection = (ITextSelection) fRememberedSelection;
2999:                    if (isValidSelection(textSelection.getOffset(),
3000:                            textSelection.getLength()))
3001:                        doSetSelection(fRememberedSelection);
3002:                }
3003:                fRememberedSelection = null;
3004:            }
3005:
3006:            /**
3007:             * Tells whether the given selection is valid.
3008:             *
3009:             * @param offset the offset of the selection
3010:             * @param length the length of the selection
3011:             * @return <code>true</code> if the selection is valid
3012:             * @since 2.1
3013:             */
3014:            private boolean isValidSelection(int offset, int length) {
3015:                IDocumentProvider provider = getDocumentProvider();
3016:                if (provider != null) {
3017:                    IDocument document = provider.getDocument(getEditorInput());
3018:                    if (document != null) {
3019:                        int end = offset + length;
3020:                        int documentLength = document.getLength();
3021:                        return 0 <= offset && offset <= documentLength
3022:                                && 0 <= end && end <= documentLength
3023:                                && length >= 0;
3024:                    }
3025:                }
3026:                return false;
3027:            }
3028:
3029:            /**
3030:             * Sets the given selection.
3031:             * @param selection
3032:             * @since 2.1
3033:             */
3034:            protected void doSetSelection(ISelection selection) {
3035:                if (selection instanceof  ITextSelection) {
3036:                    ITextSelection textSelection = (ITextSelection) selection;
3037:                    selectAndReveal(textSelection.getOffset(), textSelection
3038:                            .getLength());
3039:                }
3040:            }
3041:
3042:            /**
3043:             * Creates and returns the listener on this editor's context menus.
3044:             *
3045:             * @return the menu listener
3046:             */
3047:            protected final IMenuListener getContextMenuListener() {
3048:                if (fMenuListener == null) {
3049:                    fMenuListener = new IMenuListener() {
3050:
3051:                        public void menuAboutToShow(IMenuManager menu) {
3052:                            String id = menu.getId();
3053:                            if (getRulerContextMenuId().equals(id)) {
3054:                                setFocus();
3055:                                rulerContextMenuAboutToShow(menu);
3056:                            } else if (getEditorContextMenuId().equals(id)) {
3057:                                setFocus();
3058:                                editorContextMenuAboutToShow(menu);
3059:                            }
3060:                        }
3061:                    };
3062:                }
3063:                return fMenuListener;
3064:            }
3065:
3066:            /**
3067:             * Creates and returns the listener on this editor's vertical ruler.
3068:             *
3069:             * @return the mouse listener
3070:             */
3071:            protected final MouseListener getRulerMouseListener() {
3072:                if (fMouseListener == null) {
3073:                    fMouseListener = new MouseListener() {
3074:
3075:                        private boolean fDoubleClicked = false;
3076:                        private final int fDoubleClickTime = Display
3077:                                .getDefault().getDoubleClickTime();
3078:                        private long fMouseUpDelta = 0;
3079:
3080:                        private void triggerAction(String actionID) {
3081:                            IAction action = getAction(actionID);
3082:                            if (action != null) {
3083:                                if (action instanceof  IUpdate)
3084:                                    ((IUpdate) action).update();
3085:                                if (action.isEnabled())
3086:                                    action.run();
3087:                            }
3088:                        }
3089:
3090:                        public void mouseUp(final MouseEvent e) {
3091:                            setFocus();
3092:                            final int delay = fDoubleClickTime
3093:                                    - (int) (System.currentTimeMillis() - fMouseUpDelta);
3094:                            if (1 != e.button)
3095:                                return;
3096:
3097:                            Runnable runnable = new Runnable() {
3098:                                public void run() {
3099:                                    if (!fDoubleClicked)
3100:                                        triggerAction(ITextEditorActionConstants.RULER_CLICK);
3101:                                }
3102:                            };
3103:                            if (delay <= 0)
3104:                                runnable.run();
3105:                            else
3106:                                Display.getDefault().timerExec(delay, runnable);
3107:                        }
3108:
3109:                        public void mouseDoubleClick(MouseEvent e) {
3110:                            if (1 == e.button) {
3111:                                fDoubleClicked = true;
3112:                                triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
3113:                            }
3114:                        }
3115:
3116:                        public void mouseDown(MouseEvent e) {
3117:                            fMouseUpDelta = System.currentTimeMillis();
3118:                            fDoubleClicked = false;
3119:                            StyledText text = fSourceViewer.getTextWidget();
3120:                            if (text != null && !text.isDisposed()) {
3121:                                Display display = text.getDisplay();
3122:                                Point location = display.getCursorLocation();
3123:                                fRulerContextMenu.setLocation(location.x,
3124:                                        location.y);
3125:                            }
3126:                        }
3127:                    };
3128:                }
3129:                return fMouseListener;
3130:            }
3131:
3132:            /**
3133:             * Returns this editor's selection changed listener to be installed
3134:             * on the editor's source viewer.
3135:             *
3136:             * @return the listener
3137:             */
3138:            protected final ISelectionChangedListener getSelectionChangedListener() {
3139:                if (fSelectionChangedListener == null) {
3140:                    fSelectionChangedListener = new ISelectionChangedListener() {
3141:
3142:                        private Runnable fRunnable = new Runnable() {
3143:                            public void run() {
3144:                                // check whether editor has not been disposed yet
3145:                                if (fSourceViewer != null
3146:                                        && fSourceViewer.getDocument() != null) {
3147:                                    updateSelectionDependentActions();
3148:                                }
3149:                            }
3150:                        };
3151:
3152:                        private Display fDisplay;
3153:
3154:                        public void selectionChanged(SelectionChangedEvent event) {
3155:                            if (fDisplay == null)
3156:                                fDisplay = getSite().getShell().getDisplay();
3157:                            fDisplay.asyncExec(fRunnable);
3158:                            handleCursorPositionChanged();
3159:                        }
3160:                    };
3161:                }
3162:
3163:                return fSelectionChangedListener;
3164:            }
3165:
3166:            /**
3167:             * Returns this editor's "cursor" listener to be installed on the editor's
3168:             * source viewer. This listener is listening to key and mouse button events.
3169:             * It triggers the updating of the status line by calling
3170:             * <code>handleCursorPositionChanged()</code>.
3171:             *
3172:             * @return the listener
3173:             * @since 2.0
3174:             */
3175:            protected final ICursorListener getCursorListener() {
3176:                if (fCursorListener == null) {
3177:                    fCursorListener = new ICursorListener() {
3178:
3179:                        public void keyPressed(KeyEvent e) {
3180:                            handleCursorPositionChanged();
3181:                        }
3182:
3183:                        public void keyReleased(KeyEvent e) {
3184:                        }
3185:
3186:                        public void mouseDoubleClick(MouseEvent e) {
3187:                        }
3188:
3189:                        public void mouseDown(MouseEvent e) {
3190:                        }
3191:
3192:                        public void mouseUp(MouseEvent e) {
3193:                            handleCursorPositionChanged();
3194:                        }
3195:                    };
3196:                }
3197:                return fCursorListener;
3198:            }
3199:
3200:            /**
3201:             * Implements the <code>init</code> method of <code>IEditorPart</code>.
3202:             * Subclasses replacing <code>init</code> may choose to call this method in
3203:             * their implementation.
3204:             *
3205:             * @param window the workbench window
3206:             * @param site the editor's site
3207:             * @param input the editor input for the editor being created
3208:             * @throws PartInitException if {@link #doSetInput(IEditorInput)} fails or gets canceled
3209:             *
3210:             * @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
3211:             * @since 2.1
3212:             */
3213:            protected final void internalInit(IWorkbenchWindow window,
3214:                    final IEditorSite site, final IEditorInput input)
3215:                    throws PartInitException {
3216:
3217:                IRunnableWithProgress runnable = new IRunnableWithProgress() {
3218:                    public void run(IProgressMonitor monitor)
3219:                            throws InvocationTargetException,
3220:                            InterruptedException {
3221:                        try {
3222:
3223:                            if (getDocumentProvider() instanceof  IDocumentProviderExtension2) {
3224:                                IDocumentProviderExtension2 extension = (IDocumentProviderExtension2) getDocumentProvider();
3225:                                extension.setProgressMonitor(monitor);
3226:                            }
3227:
3228:                            doSetInput(input);
3229:
3230:                        } catch (CoreException x) {
3231:                            throw new InvocationTargetException(x);
3232:                        } finally {
3233:                            if (getDocumentProvider() instanceof  IDocumentProviderExtension2) {
3234:                                IDocumentProviderExtension2 extension = (IDocumentProviderExtension2) getDocumentProvider();
3235:                                extension.setProgressMonitor(null);
3236:                            }
3237:                        }
3238:                    }
3239:                };
3240:
3241:                try {
3242:                    //			When using the progress service always a modal dialog pops up. The site should be asked for a runnable context
3243:                    //			which could be the workbench window or the progress service, depending on what the site represents.
3244:                    //			getSite().getWorkbenchWindow().getWorkbench().getProgressService().run(false, true, runnable);
3245:
3246:                    getSite().getWorkbenchWindow().run(false, true, runnable);
3247:
3248:                } catch (InterruptedException x) {
3249:                } catch (InvocationTargetException x) {
3250:                    Throwable t = x.getTargetException();
3251:                    if (t instanceof  CoreException) {
3252:                        /*
3253:                        /* XXX: Remove unpacking of CoreException once the following bug is
3254:                         *		fixed: https://bugs.eclipse.org/bugs/show_bug.cgi?id=81640
3255:                         */
3256:                        CoreException e = (CoreException) t;
3257:                        IStatus status = e.getStatus();
3258:                        if (status.getException() != null)
3259:                            throw new PartInitException(status);
3260:                        throw new PartInitException(new Status(status
3261:                                .getSeverity(), status.getPlugin(), status
3262:                                .getCode(), status.getMessage(), t));
3263:                    }
3264:                    throw new PartInitException(new Status(IStatus.ERROR,
3265:                            TextEditorPlugin.PLUGIN_ID, IStatus.OK,
3266:                            EditorMessages.Editor_error_init, t));
3267:                }
3268:            }
3269:
3270:            /*
3271:             * @see IEditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
3272:             */
3273:            public void init(final IEditorSite site, final IEditorInput input)
3274:                    throws PartInitException {
3275:
3276:                setSite(site);
3277:
3278:                internalInit(site.getWorkbenchWindow(), site, input);
3279:                fActivationListener = new ActivationListener(site
3280:                        .getWorkbenchWindow().getPartService());
3281:            }
3282:
3283:            /**
3284:             * Creates the vertical ruler to be used by this editor.
3285:             * Subclasses may re-implement this method.
3286:             *
3287:             * @return the vertical ruler
3288:             */
3289:            protected IVerticalRuler createVerticalRuler() {
3290:                return new VerticalRuler(VERTICAL_RULER_WIDTH);
3291:            }
3292:
3293:            /**
3294:             * Adds enabled ruler contributions to the vertical ruler.
3295:             * <p>
3296:             * Clients may extend or replace.</p>
3297:             * 
3298:             * @param ruler the composite ruler to add contributions to
3299:             * @since 3.3
3300:             */
3301:            protected void updateContributedRulerColumns(CompositeRuler ruler) {
3302:                IColumnSupport support = (IColumnSupport) getAdapter(IColumnSupport.class);
3303:                if (support == null)
3304:                    return;
3305:
3306:                RulerColumnPreferenceAdapter adapter = null;
3307:                if (fPreferenceStore != null)
3308:                    adapter = new RulerColumnPreferenceAdapter(
3309:                            getPreferenceStore(),
3310:                            PREFERENCE_RULER_CONTRIBUTIONS);
3311:
3312:                RulerColumnRegistry registry = RulerColumnRegistry.getDefault();
3313:                List descriptors = registry.getColumnDescriptors();
3314:                for (Iterator it = descriptors.iterator(); it.hasNext();) {
3315:                    final RulerColumnDescriptor descriptor = (RulerColumnDescriptor) it
3316:                            .next();
3317:                    support.setColumnVisible(descriptor, adapter == null
3318:                            || adapter.isEnabled(descriptor));
3319:                }
3320:            }
3321:
3322:            /**
3323:             * Creates the column support to be used by this editor to manage the
3324:             * contributed ruler columns.
3325:             * Subclasses may re-implement this method using the {@link ColumnSupport},
3326:             * e.g. by returning <code>new ColumnSupport(this, RulerColumnRegistry.getDefault());</code>.
3327:             * <p>
3328:             * <strong>Note:</strong> If you override this method to provide column support you will
3329:             * also need to override {@link #createVerticalRuler()} to return a {@link CompositeRuler}.</p>
3330:             * <p>
3331:             * Out of the box this class does not install this support and hence this
3332:             * implementation always returns <code>null</code>.</p>
3333:             *
3334:             * @return the column support or <code>null</code> if none
3335:             * @since 3.3
3336:             */
3337:            protected IColumnSupport createColumnSupport() {
3338:                return null;
3339:            }
3340:
3341:            /**
3342:             * Creates the source viewer to be used by this editor.
3343:             * Subclasses may re-implement this method.
3344:             *
3345:             * @param parent the parent control
3346:             * @param ruler the vertical ruler
3347:             * @param styles style bits, <code>SWT.WRAP</code> is currently not supported
3348:             * @return the source viewer
3349:             */
3350:            protected ISourceViewer createSourceViewer(Composite parent,
3351:                    IVerticalRuler ruler, int styles) {
3352:                return new SourceViewer(parent, ruler, styles);
3353:            }
3354:
3355:            /**
3356:             * Initializes the drag and drop support for the given viewer based on
3357:             * provided editor adapter for drop target listeners.
3358:             *
3359:             * @param viewer the viewer
3360:             * @since 3.0
3361:             */
3362:            protected void initializeDragAndDrop(ISourceViewer viewer) {
3363:                IDragAndDropService dndService = (IDragAndDropService) getSite()
3364:                        .getService(IDragAndDropService.class);
3365:                if (dndService == null)
3366:                    return;
3367:
3368:                ITextEditorDropTargetListener listener = (ITextEditorDropTargetListener) getAdapter(ITextEditorDropTargetListener.class);
3369:
3370:                if (listener == null) {
3371:                    Object object = Platform
3372:                            .getAdapterManager()
3373:                            .loadAdapter(this ,
3374:                                    "org.eclipse.ui.texteditor.ITextEditorDropTargetListener"); //$NON-NLS-1$
3375:                    if (object instanceof  ITextEditorDropTargetListener)
3376:                        listener = (ITextEditorDropTargetListener) object;
3377:                }
3378:
3379:                if (listener != null)
3380:                    dndService.addMergedDropTarget(viewer.getTextWidget(),
3381:                            DND.DROP_MOVE | DND.DROP_COPY, listener
3382:                                    .getTransfers(), listener);
3383:
3384:                IPreferenceStore store = getPreferenceStore();
3385:                if (store != null
3386:                        && store
3387:                                .getBoolean(PREFERENCE_TEXT_DRAG_AND_DROP_ENABLED))
3388:                    installTextDragAndDrop(viewer);
3389:
3390:            }
3391:
3392:            /**
3393:             * The <code>AbstractTextEditor</code> implementation of this
3394:             * <code>IWorkbenchPart</code> method creates the vertical ruler and
3395:             * source viewer.
3396:             * <p>
3397:             * Subclasses may extend this method. Besides extending this method, the
3398:             * behavior of <code>createPartControl</code> may be customized by
3399:             * calling, extending or replacing the following methods: <br>
3400:             * Subclasses may supply customized implementations for some members using
3401:             * the following methods before <code>createPartControl</code> is invoked:
3402:             * <ul>
3403:             * <li>
3404:             * {@linkplain #setSourceViewerConfiguration(SourceViewerConfiguration) setSourceViewerConfiguration}
3405:             * to supply a custom source viewer configuration,</li>
3406:             * <li>{@linkplain #setRangeIndicator(Annotation) setRangeIndicator} to
3407:             * provide a range indicator,</li>
3408:             * <li>{@linkplain #setHelpContextId(String) setHelpContextId} to provide a
3409:             * help context id,</li>
3410:             * <li>{@linkplain #setEditorContextMenuId(String) setEditorContextMenuId}
3411:             * to set a custom context menu id,</li>
3412:             * <li>{@linkplain #setRulerContextMenuId(String) setRulerContextMenuId} to
3413:             * set a custom ruler context menu id.</li>
3414:             * </ul>
3415:             * <br>
3416:             * Subclasses may replace the following methods called from within
3417:             * <code>createPartControl</code>:
3418:             * <ul>
3419:             * <li>{@linkplain #createVerticalRuler() createVerticalRuler} to supply a
3420:             * custom vertical ruler,</li>
3421:             * <li>{@linkplain #createSourceViewer(Composite, IVerticalRuler, int) createSourceViewer}
3422:             * to supply a custom source viewer,</li>
3423:             * <li>{@linkplain #getSelectionProvider() getSelectionProvider} to supply
3424:             * a custom selection provider.</li>
3425:             * </ul>
3426:             * <br>
3427:             * Subclasses may extend the following methods called from within
3428:             * <code>createPartControl</code>:
3429:             * <ul>
3430:             * <li>
3431:             * {@linkplain #initializeViewerColors(ISourceViewer) initializeViewerColors}
3432:             * to customize the viewer color scheme (may also be replaced),</li>
3433:             * <li>
3434:             * {@linkplain #initializeDragAndDrop(ISourceViewer) initializeDragAndDrop}
3435:             * to customize drag and drop (may also be replaced),</li>
3436:             * <li>{@linkplain #createNavigationActions() createNavigationActions} to
3437:             * add navigation actions,</li>
3438:             * <li>{@linkplain #createActions() createActions} to add text editor
3439:             * actions.</li>
3440:             * </ul>
3441:             * </p>
3442:             *
3443:             * @param parent the parent composite
3444:             */
3445:            public void createPartControl(Composite parent) {
3446:
3447:                fVerticalRuler = createVerticalRuler();
3448:
3449:                int styles = SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI
3450:                        | SWT.BORDER | SWT.FULL_SELECTION;
3451:                fSourceViewer = createSourceViewer(parent, fVerticalRuler,
3452:                        styles);
3453:
3454:                if (fConfiguration == null)
3455:                    fConfiguration = new SourceViewerConfiguration();
3456:                fSourceViewer.configure(fConfiguration);
3457:
3458:                if (fRangeIndicator != null)
3459:                    fSourceViewer.setRangeIndicator(fRangeIndicator);
3460:
3461:                fSourceViewer.addTextListener(fTextListener);
3462:                fSourceViewer.addTextInputListener(fTextListener);
3463:                getSelectionProvider().addSelectionChangedListener(
3464:                        getSelectionChangedListener());
3465:
3466:                initializeViewerFont(fSourceViewer);
3467:                initializeViewerColors(fSourceViewer);
3468:                initializeFindScopeColor(fSourceViewer);
3469:                initializeDragAndDrop(fSourceViewer);
3470:
3471:                StyledText styledText = fSourceViewer.getTextWidget();
3472:
3473:                /* gestures commented out until proper solution (i.e. preference page) can be found
3474:                 * for bug # 28417:
3475:                 *
3476:                final Map gestureMap= new HashMap();
3477:
3478:                gestureMap.put("E", "org.eclipse.ui.navigate.forwardHistory");
3479:                gestureMap.put("N", "org.eclipse.ui.file.save");
3480:                gestureMap.put("NW", "org.eclipse.ui.file.saveAll");
3481:                gestureMap.put("S", "org.eclipse.ui.file.close");
3482:                gestureMap.put("SW", "org.eclipse.ui.file.closeAll");
3483:                gestureMap.put("W", "org.eclipse.ui.navigate.backwardHistory");
3484:                gestureMap.put("EN", "org.eclipse.ui.edit.copy");
3485:                gestureMap.put("ES", "org.eclipse.ui.edit.paste");
3486:                gestureMap.put("EW", "org.eclipse.ui.edit.cut");
3487:
3488:                Capture capture= Capture.create();
3489:                capture.setControl(styledText);
3490:
3491:                capture.addCaptureListener(new CaptureListener() {
3492:                	public void gesture(Gesture gesture) {
3493:                		if (gesture.getPen() == 3) {
3494:                			String actionId= (String) gestureMap.get(Util.recognize(gesture.getPoints(), 20));
3495:
3496:                			if (actionId != null) {
3497:                				IKeyBindingService keyBindingService= getEditorSite().getKeyBindingService();
3498:
3499:                				if (keyBindingService instanceof KeyBindingService) {
3500:                					IAction action= ((KeyBindingService) keyBindingService).getAction(actionId);
3501:
3502:                					if (action != null) {
3503:                						if (action instanceof IUpdate)
3504:                							((IUpdate) action).update();
3505:
3506:                						if (action.isEnabled())
3507:                							action.run();
3508:                					}
3509:                				}
3510:
3511:                				return;
3512:                			}
3513:
3514:                			fTextContextMenu.setVisible(true);
3515:                		}
3516:                	};
3517:                });
3518:                 */
3519:
3520:                styledText.addMouseListener(getCursorListener());
3521:                styledText.addKeyListener(getCursorListener());
3522:
3523:                if (getHelpContextId() != null)
3524:                    PlatformUI.getWorkbench().getHelpSystem().setHelp(
3525:                            styledText, getHelpContextId());
3526:
3527:                String id = fEditorContextMenuId != null ? fEditorContextMenuId
3528:                        : DEFAULT_EDITOR_CONTEXT_MENU_ID;
3529:
3530:                MenuManager manager = new MenuManager(id, id);
3531:                manager.setRemoveAllWhenShown(true);
3532:                manager.addMenuListener(getContextMenuListener());
3533:                fTextContextMenu = manager.createContextMenu(styledText);
3534:
3535:                // comment this line if using gestures, above.
3536:                styledText.setMenu(fTextContextMenu);
3537:
3538:                if (fEditorContextMenuId != null)
3539:                    getEditorSite().registerContextMenu(fEditorContextMenuId,
3540:                            manager, getSelectionProvider(),
3541:                            isEditorInputIncludedInContextMenu());
3542:                else if (fCompatibilityMode)
3543:                    getEditorSite().registerContextMenu(
3544:                            DEFAULT_EDITOR_CONTEXT_MENU_ID, manager,
3545:                            getSelectionProvider(),
3546:                            isEditorInputIncludedInContextMenu());
3547:
3548:                if ((fEditorContextMenuId != null && fCompatibilityMode)
3549:                        || fEditorContextMenuId == null) {
3550:                    String partId = getEditorSite().getId();
3551:                    if (partId != null)
3552:                        getEditorSite()
3553:                                .registerContextMenu(
3554:                                        partId + ".EditorContext", manager, getSelectionProvider(), isEditorInputIncludedInContextMenu()); //$NON-NLS-1$
3555:                }
3556:
3557:                if (fEditorContextMenuId == null)
3558:                    fEditorContextMenuId = DEFAULT_EDITOR_CONTEXT_MENU_ID;
3559:
3560:                id = fRulerContextMenuId != null ? fRulerContextMenuId
3561:                        : DEFAULT_RULER_CONTEXT_MENU_ID;
3562:                manager = new MenuManager(id, id);
3563:                manager.setRemoveAllWhenShown(true);
3564:                manager.addMenuListener(getContextMenuListener());
3565:
3566:                Control rulerControl = fVerticalRuler.getControl();
3567:                fRulerContextMenu = manager.createContextMenu(rulerControl);
3568:                rulerControl.setMenu(fRulerContextMenu);
3569:                rulerControl.addMouseListener(getRulerMouseListener());
3570:
3571:                if (fRulerContextMenuId != null)
3572:                    getEditorSite().registerContextMenu(fRulerContextMenuId,
3573:                            manager, getSelectionProvider(), false);
3574:                else if (fCompatibilityMode)
3575:                    getEditorSite().registerContextMenu(
3576:                            DEFAULT_RULER_CONTEXT_MENU_ID, manager,
3577:                            getSelectionProvider(), false);
3578:
3579:                if ((fRulerContextMenuId != null && fCompatibilityMode)
3580:                        || fRulerContextMenuId == null) {
3581:                    String partId = getSite().getId();
3582:                    if (partId != null)
3583:                        getEditorSite()
3584:                                .registerContextMenu(
3585:                                        partId + ".RulerContext", manager, getSelectionProvider(), false); //$NON-NLS-1$
3586:                }
3587:
3588:                if (fRulerContextMenuId == null)
3589:                    fRulerContextMenuId = DEFAULT_RULER_CONTEXT_MENU_ID;
3590:
3591:                getSite().setSelectionProvider(getSelectionProvider());
3592:
3593:                fSelectionListener = new SelectionListener();
3594:                fSelectionListener.install(getSelectionProvider());
3595:                fSelectionListener.setDocument(getDocumentProvider()
3596:                        .getDocument(getEditorInput()));
3597:
3598:                initializeActivationCodeTrigger();
3599:
3600:                createNavigationActions();
3601:                createAccessibilityActions();
3602:                createActions();
3603:
3604:                initializeSourceViewer(getEditorInput());
3605:
3606:                /* since 3.2 - undo redo actions should be created after 
3607:                 * the source viewer is initialized, so that the undo manager
3608:                 * can obtain its undo context from its document.
3609:                 */
3610:                createUndoRedoActions();
3611:
3612:                JFaceResources.getFontRegistry().addListener(
3613:                        fFontPropertyChangeListener);
3614:
3615:                IVerticalRuler ruler = getVerticalRuler();
3616:                if (ruler instanceof  CompositeRuler)
3617:                    updateContributedRulerColumns((CompositeRuler) ruler);
3618:
3619:                IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
3620:                    public IInformationControl createInformationControl(
3621:                            Shell shell) {
3622:                        boolean cutDown = false;
3623:                        int style = cutDown ? SWT.NONE
3624:                                : (SWT.V_SCROLL | SWT.H_SCROLL);
3625:                        return new DefaultInformationControl(shell, SWT.RESIZE
3626:                                | SWT.TOOL, style, new HTMLTextPresenter(
3627:                                cutDown));
3628:                    }
3629:                };
3630:
3631:                fInformationPresenter = new InformationPresenter(
3632:                        informationControlCreator);
3633:                fInformationPresenter.setSizeConstraints(60, 10, true, true);
3634:                fInformationPresenter.install(getSourceViewer());
3635:                fInformationPresenter
3636:                        .setDocumentPartitioning(getSourceViewerConfiguration()
3637:                                .getConfiguredDocumentPartitioning(
3638:                                        getSourceViewer()));
3639:
3640:            }
3641:
3642:            /**
3643:             * Installs text drag and drop on the given source viewer.
3644:             * 
3645:             * @param viewer the viewer
3646:             * @since 3.3
3647:             */
3648:            protected void installTextDragAndDrop(final ISourceViewer viewer) {
3649:                if (fIsTextDragAndDropEnabled || viewer == null)
3650:                    return;
3651:
3652:                if (fIsTextDragAndDropInstalled) {
3653:                    fIsTextDragAndDropEnabled = true;
3654:                    return;
3655:                }
3656:
3657:                final IDragAndDropService dndService = (IDragAndDropService) getSite()
3658:                        .getService(IDragAndDropService.class);
3659:                if (dndService == null)
3660:                    return;
3661:
3662:                fIsTextDragAndDropEnabled = true;
3663:
3664:                final StyledText st = viewer.getTextWidget();
3665:
3666:                // Install drag source
3667:                final ISelectionProvider selectionProvider = viewer
3668:                        .getSelectionProvider();
3669:                final DragSource source = new DragSource(st, DND.DROP_COPY
3670:                        | DND.DROP_MOVE);
3671:                source
3672:                        .setTransfer(new Transfer[] { TextTransfer
3673:                                .getInstance() });
3674:                source.addDragListener(new DragSourceAdapter() {
3675:                    String fSelectedText;
3676:                    Point fSelection;
3677:
3678:                    public void dragStart(DragSourceEvent event) {
3679:                        fTextDragAndDropToken = null;
3680:
3681:                        // XXX: This is only a workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=162192
3682:                        if (!fIsTextDragAndDropEnabled) {
3683:                            event.doit = false;
3684:                            event.image = null;
3685:                            return;
3686:                        }
3687:
3688:                        try {
3689:                            fSelection = st.getSelection();
3690:                            int offset = st.getOffsetAtLocation(new Point(
3691:                                    event.x, event.y));
3692:                            Point p = st.getLocationAtOffset(offset);
3693:                            if (p.x > event.x)
3694:                                offset--;
3695:                            event.doit = offset > fSelection.x
3696:                                    && offset < fSelection.y;
3697:
3698:                            ISelection selection = selectionProvider
3699:                                    .getSelection();
3700:                            if (selection instanceof  ITextSelection)
3701:                                fSelectedText = ((ITextSelection) selection)
3702:                                        .getText();
3703:                            else
3704:                                // fallback to widget
3705:                                fSelectedText = st.getSelectionText();
3706:                        } catch (IllegalArgumentException ex) {
3707:                            event.doit = false;
3708:                        }
3709:                    }
3710:
3711:                    public void dragSetData(DragSourceEvent event) {
3712:                        event.data = fSelectedText;
3713:                        fTextDragAndDropToken = this ; // Can be any non-null object
3714:                    }
3715:
3716:                    public void dragFinished(DragSourceEvent event) {
3717:                        try {
3718:                            if (event.detail == DND.DROP_MOVE
3719:                                    && validateEditorInputState()) {
3720:                                Point newSelection = st.getSelection();
3721:                                int length = fSelection.y - fSelection.x;
3722:                                int delta = 0;
3723:                                if (newSelection.x < fSelection.x)
3724:                                    delta = length;
3725:                                st.replaceTextRange(fSelection.x + delta,
3726:                                        length, ""); //$NON-NLS-1$
3727:
3728:                                if (fTextDragAndDropToken == null) {
3729:                                    // Move in same editor - end compound change
3730:                                    IRewriteTarget target = (IRewriteTarget) getAdapter(IRewriteTarget.class);
3731:                                    if (target != null)
3732:                                        target.endCompoundChange();
3733:                                }
3734:
3735:                            }
3736:                        } finally {
3737:                            fTextDragAndDropToken = null;
3738:                        }
3739:                    }
3740:                });
3741:
3742:                // Install drag target
3743:                DropTargetListener dropTargetListener = new DropTargetAdapter() {
3744:
3745:                    private Point fSelection;
3746:
3747:                    public void dragEnter(DropTargetEvent event) {
3748:                        fTextDragAndDropToken = null;
3749:                        fSelection = st.getSelection();
3750:
3751:                        // XXX: This is only a workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=162192
3752:                        if (!fIsTextDragAndDropEnabled) {
3753:                            event.detail = DND.DROP_NONE;
3754:                            event.feedback = DND.FEEDBACK_NONE;
3755:                            return;
3756:                        }
3757:
3758:                        if (event.detail == DND.DROP_DEFAULT)
3759:                            event.detail = DND.DROP_MOVE;
3760:                    }
3761:
3762:                    public void dragOperationChanged(DropTargetEvent event) {
3763:                        if (!fIsTextDragAndDropEnabled) {
3764:                            event.detail = DND.DROP_NONE;
3765:                            event.feedback = DND.FEEDBACK_NONE;
3766:                            return;
3767:                        }
3768:
3769:                        if (event.detail == DND.DROP_DEFAULT)
3770:                            event.detail = DND.DROP_MOVE;
3771:                    }
3772:
3773:                    public void dragOver(DropTargetEvent event) {
3774:
3775:                        // XXX: This is only a workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=162192
3776:                        if (!fIsTextDragAndDropEnabled) {
3777:                            event.feedback = DND.FEEDBACK_NONE;
3778:                            return;
3779:                        }
3780:
3781:                        event.feedback |= DND.FEEDBACK_SCROLL;
3782:                    }
3783:
3784:                    public void drop(DropTargetEvent event) {
3785:                        try {
3786:                            if (!fIsTextDragAndDropEnabled)
3787:                                return;
3788:
3789:                            if (fTextDragAndDropToken != null
3790:                                    && event.detail == DND.DROP_MOVE) {
3791:                                // Move in same editor
3792:                                int caretOffset = st.getCaretOffset();
3793:                                if (fSelection.x <= caretOffset
3794:                                        && caretOffset <= fSelection.y) {
3795:                                    event.detail = DND.DROP_NONE;
3796:                                    return;
3797:                                }
3798:
3799:                                // Start compound change
3800:                                IRewriteTarget target = (IRewriteTarget) getAdapter(IRewriteTarget.class);
3801:                                if (target != null)
3802:                                    target.beginCompoundChange();
3803:                            }
3804:
3805:                            if (!validateEditorInputState()) {
3806:                                event.detail = DND.DROP_NONE;
3807:                                return;
3808:                            }
3809:
3810:                            String text = (String) event.data;
3811:                            Point newSelection = st.getSelection();
3812:                            try {
3813:                                int modelOffset = widgetOffset2ModelOffset(
3814:                                        viewer, newSelection.x);
3815:                                viewer.getDocument().replace(modelOffset, 0,
3816:                                        text);
3817:                            } catch (BadLocationException e) {
3818:                                return;
3819:                            }
3820:                            st.setSelectionRange(newSelection.x, text.length());
3821:                        } finally {
3822:                            fTextDragAndDropToken = null;
3823:                        }
3824:                    }
3825:                };
3826:                dndService.addMergedDropTarget(st, DND.DROP_MOVE
3827:                        | DND.DROP_COPY, new Transfer[] { TextTransfer
3828:                        .getInstance() }, dropTargetListener);
3829:
3830:                fIsTextDragAndDropInstalled = true;
3831:                fIsTextDragAndDropEnabled = true;
3832:            }
3833:
3834:            /**
3835:             * Uninstalls text drag and drop from the given source viewer.
3836:             * 
3837:             * @param viewer the viewer
3838:             * @since 3.3
3839:             */
3840:            protected void uninstallTextDragAndDrop(ISourceViewer viewer) {
3841:                fIsTextDragAndDropEnabled = false;
3842:            }
3843:
3844:            /**
3845:             * Tells whether the editor input should be included when adding object
3846:             * contributions to this editor's context menu.
3847:             * <p>
3848:             * This implementation always returns <code>true</code>.
3849:             * </p>
3850:             * 
3851:             * @return <code>true</code> if the editor input should be considered
3852:             * @since 3.2
3853:             */
3854:            protected boolean isEditorInputIncludedInContextMenu() {
3855:                return true;
3856:            }
3857:
3858:            /**
3859:             * Initializes the activation code trigger.
3860:             *
3861:             * @since 2.1
3862:             */
3863:            private void initializeActivationCodeTrigger() {
3864:                fActivationCodeTrigger.install();
3865:                fActivationCodeTrigger.setScopes(fKeyBindingScopes);
3866:            }
3867:
3868:            /**
3869:             * Initializes the given viewer's font.
3870:             *
3871:             * @param viewer the viewer
3872:             * @since 2.0
3873:             */
3874:            private void initializeViewerFont(ISourceViewer viewer) {
3875:
3876:                boolean isSharedFont = true;
3877:                Font font = null;
3878:                String symbolicFontName = getSymbolicFontName();
3879:
3880:                if (symbolicFontName != null)
3881:                    font = JFaceResources.getFont(symbolicFontName);
3882:                else if (fPreferenceStore != null) {
3883:                    // Backward compatibility
3884:                    if (fPreferenceStore.contains(JFaceResources.TEXT_FONT)
3885:                            && !fPreferenceStore
3886:                                    .isDefault(JFaceResources.TEXT_FONT)) {
3887:                        FontData data = PreferenceConverter.getFontData(
3888:                                fPreferenceStore, JFaceResources.TEXT_FONT);
3889:
3890:                        if (data != null) {
3891:                            isSharedFont = false;
3892:                            font = new Font(
3893:                                    viewer.getTextWidget().getDisplay(), data);
3894:                        }
3895:                    }
3896:                }
3897:                if (font == null)
3898:                    font = JFaceResources.getTextFont();
3899:
3900:                setFont(viewer, font);
3901:
3902:                if (fFont != null) {
3903:                    fFont.dispose();
3904:                    fFont = null;
3905:                }
3906:
3907:                if (!isSharedFont)
3908:                    fFont = font;
3909:            }
3910:
3911:            /**
3912:             * Sets the font for the given viewer sustaining selection and scroll position.
3913:             *
3914:             * @param sourceViewer the source viewer
3915:             * @param font the font
3916:             * @since 2.0
3917:             */
3918:            private void setFont(ISourceViewer sourceViewer, Font font) {
3919:                if (sourceViewer.getDocument() != null) {
3920:
3921:                    Point selection = sourceViewer.getSelectedRange();
3922:                    int topIndex = sourceViewer.getTopIndex();
3923:
3924:                    StyledText styledText = sourceViewer.getTextWidget();
3925:                    Control parent = styledText;
3926:                    if (sourceViewer instanceof  ITextViewerExtension) {
3927:                        ITextViewerExtension extension = (ITextViewerExtension) sourceViewer;
3928:                        parent = extension.getControl();
3929:                    }
3930:
3931:                    parent.setRedraw(false);
3932:
3933:                    styledText.setFont(font);
3934:
3935:                    if (fVerticalRuler instanceof  IVerticalRulerExtension) {
3936:                        IVerticalRulerExtension e = (IVerticalRulerExtension) fVerticalRuler;
3937:                        e.setFont(font);
3938:                    }
3939:
3940:                    sourceViewer.setSelectedRange(selection.x, selection.y);
3941:                    sourceViewer.setTopIndex(topIndex);
3942:
3943:                    if (parent instanceof  Composite) {
3944:                        Composite composite = (Composite) parent;
3945:                        composite.layout(true);
3946:                    }
3947:
3948:                    parent.setRedraw(true);
3949:
3950:                } else {
3951:
3952:                    StyledText styledText = sourceViewer.getTextWidget();
3953:                    styledText.setFont(font);
3954:
3955:                    if (fVerticalRuler instanceof  IVerticalRulerExtension) {
3956:                        IVerticalRulerExtension e = (IVerticalRulerExtension) fVerticalRuler;
3957:                        e.setFont(font);
3958:                    }
3959:                }
3960:            }
3961:
3962:            /**
3963:             * Creates a color from the information stored in the given preference store.
3964:             * Returns <code>null</code> if there is no such information available.
3965:             *
3966:             * @param store the store to read from
3967:             * @param key the key used for the lookup in the preference store
3968:             * @param display the display used create the color
3969:             * @return the created color according to the specification in the preference store
3970:             * @since 2.0
3971:             */
3972:            private Color createColor(IPreferenceStore store, String key,
3973:                    Display display) {
3974:
3975:                RGB rgb = null;
3976:
3977:                if (store.contains(key)) {
3978:
3979:                    if (store.isDefault(key))
3980:                        rgb = PreferenceConverter.getDefaultColor(store, key);
3981:                    else
3982:                        rgb = PreferenceConverter.getColor(store, key);
3983:
3984:                    if (rgb != null)
3985:                        return new Color(display, rgb);
3986:                }
3987:
3988:                return null;
3989:            }
3990:
3991:            /**
3992:             * Initializes the fore- and background colors of the given viewer for both
3993:             * normal and selected text.
3994:             *
3995:             * @param viewer the viewer to be initialized
3996:             * @since 2.0
3997:             */
3998:            protected void initializeViewerColors(ISourceViewer viewer) {
3999:
4000:                IPreferenceStore store = getPreferenceStore();
4001:                if (store != null) {
4002:
4003:                    StyledText styledText = viewer.getTextWidget();
4004:
4005:                    // ----------- foreground color --------------------
4006:                    Color color = store
4007:                            .getBoolean(PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT) ? null
4008:                            : createColor(store, PREFERENCE_COLOR_FOREGROUND,
4009:                                    styledText.getDisplay());
4010:                    styledText.setForeground(color);
4011:
4012:                    if (fForegroundColor != null)
4013:                        fForegroundColor.dispose();
4014:
4015:                    fForegroundColor = color;
4016:
4017:                    // ---------- background color ----------------------
4018:                    color = store
4019:                            .getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT) ? null
4020:                            : createColor(store, PREFERENCE_COLOR_BACKGROUND,
4021:                                    styledText.getDisplay());
4022:                    styledText.setBackground(color);
4023:
4024:                    if (fBackgroundColor != null)
4025:                        fBackgroundColor.dispose();
4026:
4027:                    fBackgroundColor = color;
4028:
4029:                    // ----------- selection foreground color --------------------
4030:                    color = store
4031:                            .getBoolean(PREFERENCE_COLOR_SELECTION_FOREGROUND_SYSTEM_DEFAULT) ? null
4032:                            : createColor(store,
4033:                                    PREFERENCE_COLOR_SELECTION_FOREGROUND,
4034:                                    styledText.getDisplay());
4035:                    styledText.setSelectionForeground(color);
4036:
4037:                    if (fSelectionForegroundColor != null)
4038:                        fSelectionForegroundColor.dispose();
4039:
4040:                    fSelectionForegroundColor = color;
4041:
4042:                    // ---------- selection background color ----------------------
4043:                    color = store
4044:                            .getBoolean(PREFERENCE_COLOR_SELECTION_BACKGROUND_SYSTEM_DEFAULT) ? null
4045:                            : createColor(store,
4046:                                    PREFERENCE_COLOR_SELECTION_BACKGROUND,
4047:                                    styledText.getDisplay());
4048:                    styledText.setSelectionBackground(color);
4049:
4050:                    if (fSelectionBackgroundColor != null)
4051:                        fSelectionBackgroundColor.dispose();
4052:
4053:                    fSelectionBackgroundColor = color;
4054:                }
4055:            }
4056:
4057:            /**
4058:             * Initializes the background color used for highlighting the document ranges
4059:             * defining search scopes.
4060:             *
4061:             * @param viewer the viewer to initialize
4062:             * @since 2.0
4063:             */
4064:            private void initializeFindScopeColor(ISourceViewer viewer) {
4065:
4066:                IPreferenceStore store = getPreferenceStore();
4067:                if (store != null) {
4068:
4069:                    StyledText styledText = viewer.getTextWidget();
4070:
4071:                    Color color = createColor(store,
4072:                            PREFERENCE_COLOR_FIND_SCOPE, styledText
4073:                                    .getDisplay());
4074:
4075:                    IFindReplaceTarget target = viewer.getFindReplaceTarget();
4076:                    if (target != null
4077:                            && target instanceof  IFindReplaceTargetExtension)
4078:                        ((IFindReplaceTargetExtension) target)
4079:                                .setScopeHighlightColor(color);
4080:
4081:                    if (fFindScopeHighlightColor != null)
4082:                        fFindScopeHighlightColor.dispose();
4083:
4084:                    fFindScopeHighlightColor = color;
4085:                }
4086:            }
4087:
4088:            /**
4089:             * Initializes the editor's source viewer based on the given editor input.
4090:             *
4091:             * @param input the editor input to be used to initialize the source viewer
4092:             */
4093:            private void initializeSourceViewer(IEditorInput input) {
4094:
4095:                IAnnotationModel model = getDocumentProvider()
4096:                        .getAnnotationModel(input);
4097:                IDocument document = getDocumentProvider().getDocument(input);
4098:
4099:                if (document != null) {
4100:                    fSourceViewer.setDocument(document, model);
4101:                    fSourceViewer.setEditable(isEditable());
4102:                    fSourceViewer.showAnnotations(model != null);
4103:                }
4104:
4105:                if (fElementStateListener instanceof  IElementStateListenerExtension) {
4106:                    IElementStateListenerExtension extension = (IElementStateListenerExtension) fElementStateListener;
4107:                    extension.elementStateValidationChanged(input, false);
4108:                }
4109:
4110:                if (fInitialCaret == null)
4111:                    fInitialCaret = fSourceViewer.getTextWidget().getCaret();
4112:
4113:                if (fIsOverwriting)
4114:                    fSourceViewer.getTextWidget().invokeAction(
4115:                            ST.TOGGLE_OVERWRITE);
4116:                handleInsertModeChanged();
4117:
4118:                if (isTabsToSpacesConversionEnabled())
4119:                    installTabsToSpacesConverter();
4120:
4121:            }
4122:
4123:            /**
4124:             * Initializes the editor's title based on the given editor input.
4125:             * <p>
4126:             * <strong>Note:</strong> We use the editor's image instead of the image from the
4127:             * editor input to distinguish situations where the same editor input is
4128:             * opened in different kinds of editors.
4129:             * </p>
4130:             *
4131:             * @param input the editor input to be used
4132:             */
4133:            private void initializeTitle(IEditorInput input) {
4134:
4135:                Image oldImage = fTitleImage;
4136:                fTitleImage = null;
4137:                String title = ""; //$NON-NLS-1$
4138:
4139:                if (input != null) {
4140:                    IEditorRegistry editorRegistry = PlatformUI.getWorkbench()
4141:                            .getEditorRegistry();
4142:                    IEditorDescriptor editorDesc = editorRegistry
4143:                            .findEditor(getSite().getId());
4144:                    ImageDescriptor imageDesc = editorDesc != null ? editorDesc
4145:                            .getImageDescriptor() : null;
4146:
4147:                    fTitleImage = imageDesc != null ? imageDesc.createImage()
4148:                            : null;
4149:                    title = input.getName();
4150:                }
4151:
4152:                setTitleImage(fTitleImage);
4153:                setPartName(title);
4154:
4155:                firePropertyChange(PROP_DIRTY);
4156:
4157:                if (oldImage != null && !oldImage.isDisposed())
4158:                    oldImage.dispose();
4159:            }
4160:
4161:            /**
4162:             * Hook method for setting the document provider for the given input.
4163:             * This default implementation does nothing. Clients may
4164:             * reimplement.
4165:             *
4166:             * @param input the input of this editor.
4167:             * @since 3.0
4168:             */
4169:            protected void setDocumentProvider(IEditorInput input) {
4170:            }
4171:
4172:            /**
4173:             * If there is no explicit document provider set, the implicit one is
4174:             * re-initialized based on the given editor input.
4175:             *
4176:             * @param input the editor input.
4177:             */
4178:            private void updateDocumentProvider(IEditorInput input) {
4179:
4180:                IProgressMonitor rememberedProgressMonitor = null;
4181:
4182:                IDocumentProvider provider = getDocumentProvider();
4183:                if (provider != null) {
4184:                    provider.removeElementStateListener(fElementStateListener);
4185:                    if (provider instanceof  IDocumentProviderExtension2) {
4186:                        IDocumentProviderExtension2 extension = (IDocumentProviderExtension2) provider;
4187:                        rememberedProgressMonitor = extension
4188:                                .getProgressMonitor();
4189:                        extension.setProgressMonitor(null);
4190:                    }
4191:                }
4192:
4193:                setDocumentProvider(input);
4194:
4195:                provider = getDocumentProvider();
4196:                if (provider != null) {
4197:                    provider.addElementStateListener(fElementStateListener);
4198:                    if (provider instanceof  IDocumentProviderExtension2) {
4199:                        IDocumentProviderExtension2 extension = (IDocumentProviderExtension2) provider;
4200:                        extension.setProgressMonitor(rememberedProgressMonitor);
4201:                    }
4202:                }
4203:            }
4204:
4205:            /**
4206:             * Called directly from <code>setInput</code> and from within a workspace
4207:             * runnable from <code>init</code>, this method does the actual setting
4208:             * of the editor input. Closes the editor if <code>input</code> is
4209:             * <code>null</code>. Disconnects from any previous editor input and its
4210:             * document provider and connects to the new one.
4211:             * <p>
4212:             * Subclasses may extend.
4213:             * </p>
4214:             *
4215:             * @param input the input to be set
4216:             * @exception CoreException if input cannot be connected to the document
4217:             *            provider
4218:             */
4219:            protected void doSetInput(IEditorInput input) throws CoreException {
4220:                ISaveablesLifecycleListener listener = (ISaveablesLifecycleListener) getSite()
4221:                        .getService(ISaveablesLifecycleListener.class);
4222:                if (listener == null)
4223:                    fSavable = null;
4224:
4225:                if (input == null) {
4226:                    close(isSaveOnCloseNeeded());
4227:
4228:                    if (fSavable != null) {
4229:                        listener
4230:                                .handleLifecycleEvent(new SaveablesLifecycleEvent(
4231:                                        this ,
4232:                                        SaveablesLifecycleEvent.POST_CLOSE,
4233:                                        getSaveables(), false));
4234:                        fSavable.disconnectEditor();
4235:                        fSavable = null;
4236:                    }
4237:
4238:                } else {
4239:                    boolean mustSendLifeCycleEvent = false;
4240:                    if (fSavable != null) {
4241:                        listener
4242:                                .handleLifecycleEvent(new SaveablesLifecycleEvent(
4243:                                        this ,
4244:                                        SaveablesLifecycleEvent.POST_CLOSE,
4245:                                        getSaveables(), false));
4246:                        fSavable.disconnectEditor();
4247:                        fSavable = null;
4248:                        mustSendLifeCycleEvent = true;
4249:                    }
4250:
4251:                    IEditorInput oldInput = getEditorInput();
4252:                    if (oldInput != null)
4253:                        getDocumentProvider().disconnect(oldInput);
4254:
4255:                    super .setInput(input);
4256:
4257:                    updateDocumentProvider(input);
4258:
4259:                    IDocumentProvider provider = getDocumentProvider();
4260:                    if (provider == null) {
4261:                        IStatus s = new Status(IStatus.ERROR,
4262:                                PlatformUI.PLUGIN_ID, IStatus.OK,
4263:                                EditorMessages.Editor_error_no_provider, null);
4264:                        throw new CoreException(s);
4265:                    }
4266:
4267:                    provider.connect(input);
4268:
4269:                    initializeTitle(input);
4270:
4271:                    if (fSourceViewer != null) {
4272:                        initializeSourceViewer(input);
4273:
4274:                        // Reset the undo context for the undo and redo action handlers
4275:                        IAction undoAction = getAction(ITextEditorActionConstants.UNDO);
4276:                        IAction redoAction = getAction(ITextEditorActionConstants.REDO);
4277:                        boolean areOperationActionHandlersInstalled = undoAction instanceof  OperationHistoryActionHandler
4278:                                && redoAction instanceof  OperationHistoryActionHandler;
4279:                        IUndoContext undoContext = getUndoContext();
4280:                        if (undoContext != null
4281:                                && areOperationActionHandlersInstalled) {
4282:                            ((OperationHistoryActionHandler) undoAction)
4283:                                    .setContext(undoContext);
4284:                            ((OperationHistoryActionHandler) redoAction)
4285:                                    .setContext(undoContext);
4286:                        } else {
4287:                            createUndoRedoActions();
4288:                        }
4289:                    }
4290:
4291:                    if (fIsOverwriting)
4292:                        toggleOverwriteMode();
4293:                    setInsertMode((InsertMode) getLegalInsertModes().get(0));
4294:                    updateCaret();
4295:
4296:                    updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE);
4297:
4298:                    if (fSelectionListener != null)
4299:                        fSelectionListener.setDocument(getDocumentProvider()
4300:                                .getDocument(input));
4301:
4302:                    IVerticalRuler ruler = getVerticalRuler();
4303:                    if (ruler instanceof  CompositeRuler)
4304:                        updateContributedRulerColumns((CompositeRuler) ruler);
4305:
4306:                    // Send savable life-cycle if needed.
4307:                    if (mustSendLifeCycleEvent && listener != null)
4308:                        listener
4309:                                .handleLifecycleEvent(new SaveablesLifecycleEvent(
4310:                                        this ,
4311:                                        SaveablesLifecycleEvent.POST_OPEN,
4312:                                        getSaveables(), false));
4313:
4314:                }
4315:
4316:            }
4317:
4318:            /**
4319:             * Returns this editor's viewer's undo manager undo context.
4320:             *
4321:             * @return the undo context or <code>null</code> if not available
4322:             * @since 3.1
4323:             */
4324:            private IUndoContext getUndoContext() {
4325:                if (fSourceViewer instanceof  ITextViewerExtension6) {
4326:                    IUndoManager undoManager = ((ITextViewerExtension6) fSourceViewer)
4327:                            .getUndoManager();
4328:                    if (undoManager instanceof  IUndoManagerExtension)
4329:                        return ((IUndoManagerExtension) undoManager)
4330:                                .getUndoContext();
4331:                }
4332:                return null;
4333:            }
4334:
4335:            /*
4336:             * @see org.eclipse.ui.part.EditorPart#setInputWithNotify(org.eclipse.ui.IEditorInput)
4337:             * @since 3.2
4338:             */
4339:            protected final void setInputWithNotify(IEditorInput input) {
4340:                try {
4341:
4342:                    doSetInput(input);
4343:
4344:                    /*
4345:                     * The following bugs explain why we fire this property change:
4346:                     * 	https://bugs.eclipse.org/bugs/show_bug.cgi?id=90283
4347:                     * 	https://bugs.eclipse.org/bugs/show_bug.cgi?id=92049
4348:                     * 	https://bugs.eclipse.org/bugs/show_bug.cgi?id=92286
4349:                     */
4350:                    firePropertyChange(IEditorPart.PROP_INPUT);
4351:
4352:                } catch (CoreException x) {
4353:                    String title = EditorMessages.Editor_error_setinput_title;
4354:                    String msg = EditorMessages.Editor_error_setinput_message;
4355:                    Shell shell = getSite().getShell();
4356:                    ErrorDialog.openError(shell, title, msg, x.getStatus());
4357:                }
4358:            }
4359:
4360:            /*
4361:             * @see EditorPart#setInput(org.eclipse.ui.IEditorInput)
4362:             */
4363:            public final void setInput(IEditorInput input) {
4364:                setInputWithNotify(input);
4365:            }
4366:
4367:            /*
4368:             * @see ITextEditor#close
4369:             */
4370:            public void close(final boolean save) {
4371:
4372:                enableSanityChecking(false);
4373:
4374:                Display display = getSite().getShell().getDisplay();
4375:                display.asyncExec(new Runnable() {
4376:                    public void run() {
4377:                        if (fSourceViewer != null)
4378:                            getSite().getPage().closeEditor(
4379:                                    AbstractTextEditor.this , save);
4380:                    }
4381:                });
4382:            }
4383:
4384:            /**
4385:             * The <code>AbstractTextEditor</code> implementation of this
4386:             * <code>IWorkbenchPart</code> method may be extended by subclasses.
4387:             * Subclasses must call <code>super.dispose()</code>.
4388:             * <p>
4389:             * Note that many methods may return <code>null</code> after the editor is
4390:             * disposed.
4391:             * </p>
4392:             */
4393:            public void dispose() {
4394:
4395:                if (fActivationListener != null) {
4396:                    fActivationListener.dispose();
4397:                    fActivationListener = null;
4398:                }
4399:
4400:                if (fTitleImage != null) {
4401:                    fTitleImage.dispose();
4402:                    fTitleImage = null;
4403:                }
4404:
4405:                if (fFont != null) {
4406:                    fFont.dispose();
4407:                    fFont = null;
4408:                }
4409:
4410:                disposeNonDefaultCaret();
4411:                fInitialCaret = null;
4412:
4413:                if (fForegroundColor != null) {
4414:                    fForegroundColor.dispose();
4415:                    fForegroundColor = null;
4416:                }
4417:
4418:                if (fBackgroundColor != null) {
4419:                    fBackgroundColor.dispose();
4420:                    fBackgroundColor = null;
4421:                }
4422:
4423:                if (fSelectionForegroundColor != null) {
4424:                    fSelectionForegroundColor.dispose();
4425:                    fSelectionForegroundColor = null;
4426:                }
4427:
4428:                if (fSelectionBackgroundColor != null) {
4429:                    fSelectionBackgroundColor.dispose();
4430:                    fSelectionBackgroundColor = null;
4431:                }
4432:
4433:                if (fFindScopeHighlightColor != null) {
4434:                    fFindScopeHighlightColor.dispose();
4435:                    fFindScopeHighlightColor = null;
4436:                }
4437:
4438:                if (fFontPropertyChangeListener != null) {
4439:                    JFaceResources.getFontRegistry().removeListener(
4440:                            fFontPropertyChangeListener);
4441:                    fFontPropertyChangeListener = null;
4442:                }
4443:
4444:                if (fPropertyChangeListener != null) {
4445:                    if (fPreferenceStore != null) {
4446:                        fPreferenceStore
4447:                                .removePropertyChangeListener(fPropertyChangeListener);
4448:                        fPreferenceStore = null;
4449:                    }
4450:                    fPropertyChangeListener = null;
4451:                }
4452:
4453:                if (fActivationCodeTrigger != null) {
4454:                    fActivationCodeTrigger.uninstall();
4455:                    fActivationCodeTrigger = null;
4456:                }
4457:
4458:                if (fSelectionListener != null) {
4459:                    fSelectionListener.uninstall(getSelectionProvider());
4460:                    fSelectionListener = null;
4461:                }
4462:
4463:                if (fSavable != null) {
4464:                    fSavable.disconnectEditor();
4465:                    fSavable = null;
4466:                }
4467:
4468:                disposeDocumentProvider();
4469:
4470:                if (fSourceViewer != null) {
4471:
4472:                    if (fTextListener != null) {
4473:                        fSourceViewer.removeTextListener(fTextListener);
4474:                        fSourceViewer.removeTextInputListener(fTextListener);
4475:                        fTextListener = null;
4476:                    }
4477:
4478:                    uninstallTabsToSpacesConverter();
4479:
4480:                    fTextInputListener = null;
4481:                    fSelectionProvider = null;
4482:                    fSourceViewer = null;
4483:                }
4484:
4485:                if (fTextContextMenu != null) {
4486:                    fTextContextMenu.dispose();
4487:                    fTextContextMenu = null;
4488:                }
4489:
4490:                if (fRulerContextMenu != null) {
4491:                    fRulerContextMenu.dispose();
4492:                    fRulerContextMenu = null;
4493:                }
4494:
4495:                if (fActions != null) {
4496:                    fActions.clear();
4497:                    fActions = null;
4498:                }
4499:
4500:                if (fSelectionActions != null) {
4501:                    fSelectionActions.clear();
4502:                    fSelectionActions = null;
4503:                }
4504:
4505:                if (fContentActions != null) {
4506:                    fContentActions.clear();
4507:                    fContentActions = null;
4508:                }
4509:
4510:                if (fPropertyActions != null) {
4511:                    fPropertyActions.clear();
4512:                    fPropertyActions = null;
4513:                }
4514:
4515:                if (fStateActions != null) {
4516:                    fStateActions.clear();
4517:                    fStateActions = null;
4518:                }
4519:
4520:                if (fActivationCodes != null) {
4521:                    fActivationCodes.clear();
4522:                    fActivationCodes = null;
4523:                }
4524:
4525:                if (fEditorStatusLine != null)
4526:                    fEditorStatusLine = null;
4527:
4528:                if (fConfiguration != null)
4529:                    fConfiguration = null;
4530:
4531:                if (fColumnSupport != null) {
4532:                    fColumnSupport.dispose();
4533:                    fColumnSupport = null;
4534:                }
4535:
4536:                if (fVerticalRuler != null)
4537:                    fVerticalRuler = null;
4538:
4539:                IOperationHistory history = OperationHistoryFactory
4540:                        .getOperationHistory();
4541:                if (history != null) {
4542:                    if (fNonLocalOperationApprover != null)
4543:                        history
4544:                                .removeOperationApprover(fNonLocalOperationApprover);
4545:                    if (fLinearUndoViolationApprover != null)
4546:                        history
4547:                                .removeOperationApprover(fLinearUndoViolationApprover);
4548:                }
4549:                fNonLocalOperationApprover = null;
4550:                fLinearUndoViolationApprover = null;
4551:
4552:                super .dispose();
4553:            }
4554:
4555:            /**
4556:             * Disposes of the connection with the document provider. Subclasses
4557:             * may extend.
4558:             *
4559:             * @since 3.0
4560:             */
4561:            protected void disposeDocumentProvider() {
4562:                IDocumentProvider provider = getDocumentProvider();
4563:                if (provider != null) {
4564:
4565:                    IEditorInput input = getEditorInput();
4566:                    if (input != null)
4567:                        provider.disconnect(input);
4568:
4569:                    if (fElementStateListener != null) {
4570:                        provider
4571:                                .removeElementStateListener(fElementStateListener);
4572:                        fElementStateListener = null;
4573:                    }
4574:
4575:                }
4576:                fExplicitDocumentProvider = null;
4577:            }
4578:
4579:            /**
4580:             * Determines whether the given preference change affects the editor's
4581:             * presentation. This implementation always returns <code>false</code>.
4582:             * May be reimplemented by subclasses.
4583:             *
4584:             * @param event the event which should be investigated
4585:             * @return <code>true</code> if the event describes a preference change affecting the editor's presentation
4586:             * @since 2.0
4587:             */
4588:            protected boolean affectsTextPresentation(PropertyChangeEvent event) {
4589:                return false;
4590:            }
4591:
4592:            /**
4593:             * Returns the symbolic font name for this editor as defined in XML.
4594:             *
4595:             * @return a String with the symbolic font name or <code>null</code> if
4596:             *         none is defined
4597:             * @since 2.1
4598:             */
4599:            private String getSymbolicFontName() {
4600:                if (getConfigurationElement() != null)
4601:                    return getConfigurationElement().getAttribute(
4602:                            "symbolicFontName"); //$NON-NLS-1$
4603:                return null;
4604:            }
4605:
4606:            /**
4607:             * Returns the property preference key for the editor font. Subclasses may
4608:             * replace this method.
4609:             *
4610:             * @return a String with the key
4611:             * @since 2.1
4612:             */
4613:            protected final String getFontPropertyPreferenceKey() {
4614:                String symbolicFontName = getSymbolicFontName();
4615:                if (symbolicFontName != null)
4616:                    return symbolicFontName;
4617:                return JFaceResources.TEXT_FONT;
4618:            }
4619:
4620:            /**
4621:             * Handles a property change event describing a change of the editor's
4622:             * preference store and updates the preference related editor properties.
4623:             * <p>
4624:             * Subclasses may extend.
4625:             * </p>
4626:             *
4627:             * @param event the property change event
4628:             */
4629:            protected void handlePreferenceStoreChanged(
4630:                    PropertyChangeEvent event) {
4631:
4632:                if (fSourceViewer == null)
4633:                    return;
4634:
4635:                String property = event.getProperty();
4636:
4637:                if (getFontPropertyPreferenceKey().equals(property))
4638:                    // There is a separate handler for font preference changes
4639:                    return;
4640:
4641:                if (PREFERENCE_COLOR_FOREGROUND.equals(property)
4642:                        || PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT
4643:                                .equals(property)
4644:                        || PREFERENCE_COLOR_BACKGROUND.equals(property)
4645:                        || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT
4646:                                .equals(property)
4647:                        || PREFERENCE_COLOR_SELECTION_FOREGROUND
4648:                                .equals(property)
4649:                        || PREFERENCE_COLOR_SELECTION_FOREGROUND_SYSTEM_DEFAULT
4650:                                .equals(property)
4651:                        || PREFERENCE_COLOR_SELECTION_BACKGROUND
4652:                                .equals(property)
4653:                        || PREFERENCE_COLOR_SELECTION_BACKGROUND_SYSTEM_DEFAULT
4654:                                .equals(property)) {
4655:                    initializeViewerColors(fSourceViewer);
4656:                } else if (PREFERENCE_COLOR_FIND_SCOPE.equals(property)) {
4657:                    initializeFindScopeColor(fSourceViewer);
4658:                } else if (PREFERENCE_USE_CUSTOM_CARETS.equals(property)) {
4659:                    updateCaret();
4660:                } else if (PREFERENCE_WIDE_CARET.equals(property)) {
4661:                    updateCaret();
4662:                }
4663:
4664:                if (affectsTextPresentation(event))
4665:                    fSourceViewer.invalidateTextPresentation();
4666:
4667:                if (PREFERENCE_HYPERLINKS_ENABLED.equals(property)) {
4668:                    if (fSourceViewer instanceof  ITextViewerExtension6) {
4669:                        IHyperlinkDetector[] detectors = getSourceViewerConfiguration()
4670:                                .getHyperlinkDetectors(fSourceViewer);
4671:                        int stateMask = getSourceViewerConfiguration()
4672:                                .getHyperlinkStateMask(fSourceViewer);
4673:                        ITextViewerExtension6 textViewer6 = (ITextViewerExtension6) fSourceViewer;
4674:                        textViewer6.setHyperlinkDetectors(detectors, stateMask);
4675:                    }
4676:                    return;
4677:                }
4678:
4679:                if (PREFERENCE_HYPERLINK_KEY_MODIFIER.equals(property)) {
4680:                    if (fSourceViewer instanceof  ITextViewerExtension6) {
4681:                        ITextViewerExtension6 textViewer6 = (ITextViewerExtension6) fSourceViewer;
4682:                        IHyperlinkDetector[] detectors = getSourceViewerConfiguration()
4683:                                .getHyperlinkDetectors(fSourceViewer);
4684:                        int stateMask = getSourceViewerConfiguration()
4685:                                .getHyperlinkStateMask(fSourceViewer);
4686:                        textViewer6.setHyperlinkDetectors(detectors, stateMask);
4687:                    }
4688:                    return;
4689:                }
4690:
4691:                if (PREFERENCE_RULER_CONTRIBUTIONS.equals(property)) {
4692:                    String[] difference = StringSetSerializer.getDifference(
4693:                            (String) event.getOldValue(), (String) event
4694:                                    .getNewValue());
4695:                    IColumnSupport support = (IColumnSupport) getAdapter(IColumnSupport.class);
4696:                    for (int i = 0; i < difference.length; i++) {
4697:                        RulerColumnDescriptor desc = RulerColumnRegistry
4698:                                .getDefault()
4699:                                .getColumnDescriptor(difference[i]);
4700:                        if (desc != null && support.isColumnSupported(desc)) {
4701:                            boolean newState = !support.isColumnVisible(desc);
4702:                            support.setColumnVisible(desc, newState);
4703:                        }
4704:                    }
4705:                    return;
4706:                }
4707:
4708:                if (PREFERENCE_SHOW_WHITESPACE_CHARACTERS.equals(property)) {
4709:                    IAction action = getAction(ITextEditorActionConstants.SHOW_WHITESPACE_CHARACTERS);
4710:                    if (action instanceof  IUpdate)
4711:                        ((IUpdate) action).update();
4712:                    return;
4713:                }
4714:
4715:                if (PREFERENCE_TEXT_DRAG_AND_DROP_ENABLED.equals(property)) {
4716:                    IPreferenceStore store = getPreferenceStore();
4717:                    if (store != null
4718:                            && store
4719:                                    .getBoolean(PREFERENCE_TEXT_DRAG_AND_DROP_ENABLED))
4720:                        installTextDragAndDrop(getSourceViewer());
4721:                    else
4722:                        uninstallTextDragAndDrop(getSourceViewer());
4723:                    return;
4724:                }
4725:
4726:            }
4727:
4728:            /**
4729:             * Returns the progress monitor related to this editor. It should not be
4730:             * necessary to extend this method.
4731:             *
4732:             * @return the progress monitor related to this editor
4733:             * @since 2.1
4734:             */
4735:            protected IProgressMonitor getProgressMonitor() {
4736:
4737:                IProgressMonitor pm = null;
4738:
4739:                IStatusLineManager manager = getStatusLineManager();
4740:                if (manager != null)
4741:                    pm = manager.getProgressMonitor();
4742:
4743:                return pm != null ? pm : new NullProgressMonitor();
4744:            }
4745:
4746:            /**
4747:             * Handles an external change of the editor's input element. Subclasses may
4748:             * extend.
4749:             */
4750:            protected void handleEditorInputChanged() {
4751:
4752:                String title;
4753:                String msg;
4754:                Shell shell = getSite().getShell();
4755:
4756:                final IDocumentProvider provider = getDocumentProvider();
4757:                if (provider == null) {
4758:                    // fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=15066
4759:                    close(false);
4760:                    return;
4761:                }
4762:
4763:                final IEditorInput input = getEditorInput();
4764:                if (provider.isDeleted(input)) {
4765:
4766:                    if (isSaveAsAllowed()) {
4767:
4768:                        title = EditorMessages.Editor_error_activated_deleted_save_title;
4769:                        msg = EditorMessages.Editor_error_activated_deleted_save_message;
4770:
4771:                        String[] buttons = {
4772:                                EditorMessages.Editor_error_activated_deleted_save_button_save,
4773:                                EditorMessages.Editor_error_activated_deleted_save_button_close, };
4774:
4775:                        MessageDialog dialog = new MessageDialog(shell, title,
4776:                                null, msg, MessageDialog.QUESTION, buttons, 0);
4777:
4778:                        if (dialog.open() == 0) {
4779:                            IProgressMonitor pm = getProgressMonitor();
4780:                            performSaveAs(pm);
4781:                            if (pm.isCanceled())
4782:                                handleEditorInputChanged();
4783:                        } else {
4784:                            close(false);
4785:                        }
4786:
4787:                    } else {
4788:
4789:                        title = EditorMessages.Editor_error_activated_deleted_close_title;
4790:                        msg = EditorMessages.Editor_error_activated_deleted_close_message;
4791:                        if (MessageDialog.openConfirm(shell, title, msg))
4792:                            close(false);
4793:                    }
4794:
4795:                } else {
4796:
4797:                    title = EditorMessages.Editor_error_activated_outofsync_title;
4798:                    msg = EditorMessages.Editor_error_activated_outofsync_message;
4799:
4800:                    if (MessageDialog.openQuestion(shell, title, msg)) {
4801:
4802:                        try {
4803:                            if (provider instanceof  IDocumentProviderExtension) {
4804:                                IDocumentProviderExtension extension = (IDocumentProviderExtension) provider;
4805:                                extension.synchronize(input);
4806:                            } else {
4807:                                doSetInput(input);
4808:                            }
4809:                        } catch (CoreException x) {
4810:                            IStatus status = x.getStatus();
4811:                            if (status == null
4812:                                    || status.getSeverity() != IStatus.CANCEL) {
4813:                                title = EditorMessages.Editor_error_refresh_outofsync_title;
4814:                                msg = EditorMessages.Editor_error_refresh_outofsync_message;
4815:                                ErrorDialog.openError(shell, title, msg, x
4816:                                        .getStatus());
4817:                            }
4818:                        }
4819:                    }
4820:                }
4821:            }
4822:
4823:            /**
4824:             * The <code>AbstractTextEditor</code> implementation of this
4825:             * <code>IEditorPart</code> method calls <code>performSaveAs</code>.
4826:             * Subclasses may reimplement.
4827:             */
4828:            public void doSaveAs() {
4829:                /*
4830:                 * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors.
4831:                 * Changed Behavior to make sure that if called inside a regular save (because
4832:                 * of deletion of input element) there is a way to report back to the caller.
4833:                 */
4834:                performSaveAs(getProgressMonitor());
4835:            }
4836:
4837:            /**
4838:             * Performs a save as and reports the result state back to the
4839:             * given progress monitor. This default implementation does nothing.
4840:             * Subclasses may reimplement.
4841:             *
4842:             * @param progressMonitor the progress monitor for communicating result state or <code>null</code>
4843:             */
4844:            protected void performSaveAs(IProgressMonitor progressMonitor) {
4845:            }
4846:
4847:            /**
4848:             * The <code>AbstractTextEditor</code> implementation of this
4849:             * <code>IEditorPart</code> method may be extended by subclasses.
4850:             *
4851:             * @param progressMonitor the progress monitor for communicating result state or <code>null</code>
4852:             */
4853:            public void doSave(IProgressMonitor progressMonitor) {
4854:
4855:                IDocumentProvider p = getDocumentProvider();
4856:                if (p == null)
4857:                    return;
4858:
4859:                if (p.isDeleted(getEditorInput())) {
4860:
4861:                    if (isSaveAsAllowed()) {
4862:
4863:                        /*
4864:                         * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors.
4865:                         * Changed Behavior to make sure that if called inside a regular save (because
4866:                         * of deletion of input element) there is a way to report back to the caller.
4867:                         */
4868:                        performSaveAs(progressMonitor);
4869:
4870:                    } else {
4871:
4872:                        Shell shell = getSite().getShell();
4873:                        String title = EditorMessages.Editor_error_save_deleted_title;
4874:                        String msg = EditorMessages.Editor_error_save_deleted_message;
4875:                        MessageDialog.openError(shell, title, msg);
4876:                    }
4877:
4878:                } else {
4879:                    updateState(getEditorInput());
4880:                    validateState(getEditorInput());
4881:                    performSave(false, progressMonitor);
4882:                }
4883:            }
4884:
4885:            /**
4886:             * Enables/disables sanity checking.
4887:             * @param enable <code>true</code> if sanity checking should be enabled, <code>false</code> otherwise
4888:             * @since 2.0
4889:             */
4890:            protected void enableSanityChecking(boolean enable) {
4891:                synchronized (this ) {
4892:                    fIsSanityCheckEnabled = enable;
4893:                }
4894:            }
4895:
4896:            /**
4897:             * Checks the state of the given editor input if sanity checking is enabled.
4898:             * @param input the editor input whose state is to be checked
4899:             * @since 2.0
4900:             */
4901:            protected void safelySanityCheckState(IEditorInput input) {
4902:                boolean enabled = false;
4903:
4904:                synchronized (this ) {
4905:                    enabled = fIsSanityCheckEnabled;
4906:                }
4907:
4908:                if (enabled)
4909:                    sanityCheckState(input);
4910:            }
4911:
4912:            /**
4913:             * Checks the state of the given editor input.
4914:             * @param input the editor input whose state is to be checked
4915:             * @since 2.0
4916:             */
4917:            protected void sanityCheckState(IEditorInput input) {
4918:
4919:                IDocumentProvider p = getDocumentProvider();
4920:                if (p == null)
4921:                    return;
4922:
4923:                if (p instanceof  IDocumentProviderExtension3) {
4924:
4925:                    IDocumentProviderExtension3 p3 = (IDocumentProviderExtension3) p;
4926:
4927:                    long stamp = p.getModificationStamp(input);
4928:                    if (stamp != fModificationStamp) {
4929:                        fModificationStamp = stamp;
4930:                        if (!p3.isSynchronized(input))
4931:                            handleEditorInputChanged();
4932:                    }
4933:
4934:                } else {
4935:
4936:                    if (fModificationStamp == -1)
4937:                        fModificationStamp = p.getSynchronizationStamp(input);
4938:
4939:                    long stamp = p.getModificationStamp(input);
4940:                    if (stamp != fModificationStamp) {
4941:                        fModificationStamp = stamp;
4942:                        if (stamp != p.getSynchronizationStamp(input))
4943:                            handleEditorInputChanged();
4944:                    }
4945:                }
4946:
4947:                updateState(getEditorInput());
4948:                updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE);
4949:            }
4950:
4951:            /**
4952:             * Enables/disables state validation.
4953:             * @param enable <code>true</code> if state validation should be enabled, <code>false</code> otherwise
4954:             * @since 2.1
4955:             */
4956:            protected void enableStateValidation(boolean enable) {
4957:                synchronized (this ) {
4958:                    fIsStateValidationEnabled = enable;
4959:                }
4960:            }
4961:
4962:            /**
4963:             * Validates the state of the given editor input. The predominate intent
4964:             * of this method is to take any action probably necessary to ensure that
4965:             * the input can persistently be changed.
4966:             *
4967:             * @param input the input to be validated
4968:             * @since 2.0
4969:             */
4970:            protected void validateState(IEditorInput input) {
4971:
4972:                IDocumentProvider provider = getDocumentProvider();
4973:                if (!(provider instanceof  IDocumentProviderExtension))
4974:                    return;
4975:
4976:                IDocumentProviderExtension extension = (IDocumentProviderExtension) provider;
4977:
4978:                try {
4979:
4980:                    extension.validateState(input, getSite().getShell());
4981:
4982:                } catch (CoreException x) {
4983:                    IStatus status = x.getStatus();
4984:                    if (status == null
4985:                            || status.getSeverity() != IStatus.CANCEL) {
4986:                        Bundle bundle = Platform
4987:                                .getBundle(PlatformUI.PLUGIN_ID);
4988:                        ILog log = Platform.getLog(bundle);
4989:                        log.log(x.getStatus());
4990:
4991:                        Shell shell = getSite().getShell();
4992:                        String title = EditorMessages.Editor_error_validateEdit_title;
4993:                        String msg = EditorMessages.Editor_error_validateEdit_message;
4994:                        ErrorDialog.openError(shell, title, msg, x.getStatus());
4995:                    }
4996:                    return;
4997:                }
4998:
4999:                if (fSourceViewer != null)
5000:                    fSourceViewer.setEditable(isEditable());
5001:
5002:                updateStateDependentActions();
5003:            }
5004:
5005:            /*
5006:             * @see org.eclipse.ui.texteditor.ITextEditorExtension2#validateEditorInputState()
5007:             * @since 2.1
5008:             */
5009:            public boolean validateEditorInputState() {
5010:
5011:                boolean enabled = false;
5012:
5013:                synchronized (this ) {
5014:                    enabled = fIsStateValidationEnabled;
5015:                }
5016:
5017:                if (enabled) {
5018:
5019:                    ISourceViewer viewer = fSourceViewer;
5020:                    if (viewer == null)
5021:                        return false;
5022:
5023:                    fTextInputListener.inputChanged = false;
5024:                    viewer.addTextInputListener(fTextInputListener);
5025:
5026:                    try {
5027:                        final IEditorInput input = getEditorInput();
5028:                        BusyIndicator.showWhile(getSite().getShell()
5029:                                .getDisplay(), new Runnable() {
5030:                            /*
5031:                             * @see java.lang.Runnable#run()
5032:                             */
5033:                            public void run() {
5034:                                validateState(input);
5035:                            }
5036:                        });
5037:                        sanityCheckState(input);
5038:                        return !isEditorInputReadOnly()
5039:                                && !fTextInputListener.inputChanged;
5040:
5041:                    } finally {
5042:                        viewer.removeTextInputListener(fTextInputListener);
5043:                    }
5044:
5045:                }
5046:
5047:                return !isEditorInputReadOnly();
5048:            }
5049:
5050:            /**
5051:             * Updates the state of the given editor input such as read-only flag.
5052:             *
5053:             * @param input the input to be validated
5054:             * @since 2.0
5055:             */
5056:            protected void updateState(IEditorInput input) {
5057:                IDocumentProvider provider = getDocumentProvider();
5058:                if (provider instanceof  IDocumentProviderExtension) {
5059:                    IDocumentProviderExtension extension = (IDocumentProviderExtension) provider;
5060:                    try {
5061:
5062:                        boolean wasReadOnly = isEditorInputReadOnly();
5063:                        extension.updateStateCache(input);
5064:
5065:                        if (fSourceViewer != null)
5066:                            fSourceViewer.setEditable(isEditable());
5067:
5068:                        if (wasReadOnly != isEditorInputReadOnly())
5069:                            updateStateDependentActions();
5070:
5071:                    } catch (CoreException x) {
5072:                        Bundle bundle = Platform
5073:                                .getBundle(PlatformUI.PLUGIN_ID);
5074:                        ILog log = Platform.getLog(bundle);
5075:                        log.log(x.getStatus());
5076:                    }
5077:                }
5078:            }
5079:
5080:            /**
5081:             * Performs the save and handles errors appropriately.
5082:             *
5083:             * @param overwrite indicates whether or not overwriting is allowed
5084:             * @param progressMonitor the monitor in which to run the operation
5085:             * @since 3.0
5086:             */
5087:            protected void performSave(boolean overwrite,
5088:                    IProgressMonitor progressMonitor) {
5089:
5090:                IDocumentProvider provider = getDocumentProvider();
5091:                if (provider == null)
5092:                    return;
5093:
5094:                try {
5095:
5096:                    provider.aboutToChange(getEditorInput());
5097:                    IEditorInput input = getEditorInput();
5098:                    provider
5099:                            .saveDocument(progressMonitor, input,
5100:                                    getDocumentProvider().getDocument(input),
5101:                                    overwrite);
5102:                    editorSaved();
5103:
5104:                } catch (CoreException x) {
5105:                    IStatus status = x.getStatus();
5106:                    if (status == null
5107:                            || status.getSeverity() != IStatus.CANCEL)
5108:                        handleExceptionOnSave(x, progressMonitor);
5109:                } finally {
5110:                    provider.changed(getEditorInput());
5111:                }
5112:            }
5113:
5114:            /**
5115:             * Handles the given exception. If the exception reports an out-of-sync
5116:             * situation, this is reported to the user. Otherwise, the exception
5117:             * is generically reported.
5118:             *
5119:             * @param exception the exception to handle
5120:             * @param progressMonitor the progress monitor
5121:             */
5122:            protected void handleExceptionOnSave(CoreException exception,
5123:                    IProgressMonitor progressMonitor) {
5124:
5125:                try {
5126:                    ++fErrorCorrectionOnSave;
5127:
5128:                    boolean isSynchronized = false;
5129:                    IDocumentProvider p = getDocumentProvider();
5130:
5131:                    if (p instanceof  IDocumentProviderExtension3) {
5132:                        IDocumentProviderExtension3 p3 = (IDocumentProviderExtension3) p;
5133:                        isSynchronized = p3.isSynchronized(getEditorInput());
5134:                    } else {
5135:                        long modifiedStamp = p
5136:                                .getModificationStamp(getEditorInput());
5137:                        long synchStamp = p
5138:                                .getSynchronizationStamp(getEditorInput());
5139:                        isSynchronized = (modifiedStamp == synchStamp);
5140:                    }
5141:
5142:                    if (isNotSynchronizedException(exception)
5143:                            && fErrorCorrectionOnSave == 1 && !isSynchronized) {
5144:                        String title = EditorMessages.Editor_error_save_outofsync_title;
5145:                        String msg = NLSUtility
5146:                                .format(
5147:                                        EditorMessages.Editor_error_save_outofsync_message,
5148:                                        getEditorInput().getToolTipText());
5149:
5150:                        if (MessageDialog.openQuestion(getSite().getShell(),
5151:                                title, msg))
5152:                            performSave(true, progressMonitor);
5153:                        else {
5154:                            /*
5155:                             * 1GEUPKR: ITPJUI:ALL - Loosing work with simultaneous edits
5156:                             * Set progress monitor to canceled in order to report back
5157:                             * to enclosing operations.
5158:                             */
5159:                            if (progressMonitor != null)
5160:                                progressMonitor.setCanceled(true);
5161:                        }
5162:                    } else {
5163:                        String title = EditorMessages.Editor_error_save_title;
5164:                        String msg = EditorMessages.Editor_error_save_message;
5165:                        openSaveErrorDialog(title, msg, exception);
5166:
5167:                        /*
5168:                         * 1GEUPKR: ITPJUI:ALL - Loosing work with simultaneous edits
5169:                         * Set progress monitor to canceled in order to report back
5170:                         * to enclosing operations.
5171:                         */
5172:                        if (progressMonitor != null)
5173:                            progressMonitor.setCanceled(true);
5174:                    }
5175:                } finally {
5176:                    --fErrorCorrectionOnSave;
5177:                }
5178:            }
5179:
5180:            /**
5181:             * Presents an error dialog to the user when a problem
5182:             * happens during save.
5183:             * <p>
5184:             * Subclasses can decide to override the given title and message.
5185:             * </p>
5186:             * 
5187:             * @param title	the dialog title
5188:             * @param message the message to display
5189:             * @param exception the exception to handle
5190:             * @since 3.3
5191:             */
5192:            protected void openSaveErrorDialog(String title, String message,
5193:                    CoreException exception) {
5194:                ErrorDialog.openError(getSite().getShell(), title, message,
5195:                        exception.getStatus());
5196:            }
5197:
5198:            /**
5199:             * Tells whether the given core exception is exactly the
5200:             * exception which is thrown for a non-synchronized element.
5201:             * 
5202:             * @param ex the core exception
5203:             * @return <code>true</code> iff the given core exception is exactly the
5204:             *			exception which is thrown for a non-synchronized element
5205:             * @since 3.1
5206:             */
5207:            private boolean isNotSynchronizedException(CoreException ex) {
5208:                IDocumentProvider provider = getDocumentProvider();
5209:                if (provider instanceof  IDocumentProviderExtension5)
5210:                    return ((IDocumentProviderExtension5) provider)
5211:                            .isNotSynchronizedException(getEditorInput(), ex);
5212:                return false;
5213:            }
5214:
5215:            /**
5216:             * The <code>AbstractTextEditor</code> implementation of this
5217:             * <code>IEditorPart</code> method returns <code>false</code>.
5218:             * Subclasses may override.
5219:             *
5220:             * @return <code>false</code>
5221:             */
5222:            public boolean isSaveAsAllowed() {
5223:                return false;
5224:            }
5225:
5226:            /*
5227:             * @see EditorPart#isDirty()
5228:             */
5229:            public boolean isDirty() {
5230:                IDocumentProvider p = getDocumentProvider();
5231:                return p == null ? false : p.canSaveDocument(getEditorInput());
5232:            }
5233:
5234:            /**
5235:             * The <code>AbstractTextEditor</code> implementation of this
5236:             * <code>ITextEditor</code> method may be extended by subclasses.
5237:             */
5238:            public void doRevertToSaved() {
5239:                IDocumentProvider p = getDocumentProvider();
5240:                if (p == null)
5241:                    return;
5242:
5243:                performRevert();
5244:            }
5245:
5246:            /**
5247:             * Performs revert and handles errors appropriately.
5248:             * <p>
5249:             * Subclasses may extend.
5250:             * </p>
5251:             *
5252:             * @since 3.0
5253:             */
5254:            protected void performRevert() {
5255:
5256:                IDocumentProvider provider = getDocumentProvider();
5257:                if (provider == null)
5258:                    return;
5259:
5260:                try {
5261:
5262:                    provider.aboutToChange(getEditorInput());
5263:                    provider.resetDocument(getEditorInput());
5264:                    editorSaved();
5265:
5266:                } catch (CoreException x) {
5267:                    IStatus status = x.getStatus();
5268:                    if (status == null
5269:                            || status.getSeverity() != IStatus.CANCEL) {
5270:                        Shell shell = getSite().getShell();
5271:                        String title = EditorMessages.Editor_error_revert_title;
5272:                        String msg = EditorMessages.Editor_error_revert_message;
5273:                        ErrorDialog.openError(shell, title, msg, x.getStatus());
5274:                    }
5275:                } finally {
5276:                    provider.changed(getEditorInput());
5277:                }
5278:            }
5279:
5280:            /**
5281:             * Performs any additional action necessary to perform after the input
5282:             * document's content has been replaced.
5283:             * <p>
5284:             * Clients may extended this method.
5285:             *
5286:             * @since 3.0
5287:             */
5288:            protected void handleElementContentReplaced() {
5289:            }
5290:
5291:            /*
5292:             * @see ITextEditor#setAction(String, IAction)
5293:             */
5294:            public void setAction(String actionID, IAction action) {
5295:                Assert.isNotNull(actionID);
5296:                if (action == null) {
5297:                    action = (IAction) fActions.remove(actionID);
5298:                    if (action != null)
5299:                        fActivationCodeTrigger
5300:                                .unregisterActionFromKeyActivation(action);
5301:                } else {
5302:                    fActions.put(actionID, action);
5303:                    fActivationCodeTrigger
5304:                            .registerActionForKeyActivation(action);
5305:                }
5306:            }
5307:
5308:            /*
5309:             * @see ITextEditor#setActionActivationCode(String, char, int, int)
5310:             */
5311:            public void setActionActivationCode(String actionID,
5312:                    char activationCharacter, int activationKeyCode,
5313:                    int activationStateMask) {
5314:
5315:                Assert.isNotNull(actionID);
5316:
5317:                ActionActivationCode found = findActionActivationCode(actionID);
5318:                if (found == null) {
5319:                    found = new ActionActivationCode(actionID);
5320:                    fActivationCodes.add(found);
5321:                }
5322:
5323:                found.fCharacter = activationCharacter;
5324:                found.fKeyCode = activationKeyCode;
5325:                found.fStateMask = activationStateMask;
5326:            }
5327:
5328:            /**
5329:             * Returns the activation code registered for the specified action.
5330:             *
5331:             * @param actionID the action id
5332:             * @return the registered activation code or <code>null</code> if no code has been installed
5333:             */
5334:            private ActionActivationCode findActionActivationCode(
5335:                    String actionID) {
5336:                int size = fActivationCodes.size();
5337:                for (int i = 0; i < size; i++) {
5338:                    ActionActivationCode code = (ActionActivationCode) fActivationCodes
5339:                            .get(i);
5340:                    if (actionID.equals(code.fActionId))
5341:                        return code;
5342:                }
5343:                return null;
5344:            }
5345:
5346:            /*
5347:             * @see ITextEditor#removeActionActivationCode(String)
5348:             */
5349:            public void removeActionActivationCode(String actionID) {
5350:                Assert.isNotNull(actionID);
5351:                ActionActivationCode code = findActionActivationCode(actionID);
5352:                if (code != null)
5353:                    fActivationCodes.remove(code);
5354:            }
5355:
5356:            /*
5357:             * @see ITextEditor#getAction(String)
5358:             */
5359:            public IAction getAction(String actionID) {
5360:                Assert.isNotNull(actionID);
5361:                IAction action = (IAction) fActions.get(actionID);
5362:
5363:                if (action == null) {
5364:                    action = findContributedAction(actionID);
5365:                    if (action != null)
5366:                        setAction(actionID, action);
5367:                }
5368:
5369:                return action;
5370:            }
5371:
5372:            /**
5373:             * Returns the action with the given action id that has been contributed via XML to this editor.
5374:             * The lookup honors the dependencies of plug-ins.
5375:             *
5376:             * @param actionID the action id to look up
5377:             * @return the action that has been contributed
5378:             * @since 2.0
5379:             */
5380:            private IAction findContributedAction(String actionID) {
5381:                List actions = new ArrayList();
5382:                IConfigurationElement[] elements = Platform
5383:                        .getExtensionRegistry().getConfigurationElementsFor(
5384:                                PlatformUI.PLUGIN_ID, "editorActions"); //$NON-NLS-1$
5385:                for (int i = 0; i < elements.length; i++) {
5386:                    IConfigurationElement element = elements[i];
5387:                    if (TAG_CONTRIBUTION_TYPE.equals(element.getName())) {
5388:                        if (!getSite().getId().equals(
5389:                                element.getAttribute("targetID"))) //$NON-NLS-1$
5390:                            continue;
5391:
5392:                        IConfigurationElement[] children = element
5393:                                .getChildren("action"); //$NON-NLS-1$
5394:                        for (int j = 0; j < children.length; j++) {
5395:                            IConfigurationElement child = children[j];
5396:                            if (actionID.equals(child.getAttribute("actionID"))) //$NON-NLS-1$
5397:                                actions.add(child);
5398:                        }
5399:                    }
5400:                }
5401:                int actionSize = actions.size();
5402:                if (actionSize > 0) {
5403:                    IConfigurationElement element;
5404:                    if (actionSize > 1) {
5405:                        IConfigurationElement[] actionArray = (IConfigurationElement[]) actions
5406:                                .toArray(new IConfigurationElement[actionSize]);
5407:                        ConfigurationElementSorter sorter = new ConfigurationElementSorter() {
5408:                            /*
5409:                             * @see org.eclipse.ui.texteditor.ConfigurationElementSorter#getConfigurationElement(java.lang.Object)
5410:                             */
5411:                            public IConfigurationElement getConfigurationElement(
5412:                                    Object object) {
5413:                                return (IConfigurationElement) object;
5414:                            }
5415:                        };
5416:                        sorter.sort(actionArray);
5417:                        element = actionArray[0];
5418:                    } else
5419:                        element = (IConfigurationElement) actions.get(0);
5420:
5421:                    try {
5422:                        return new ContributedAction(getSite(), element);
5423:                    } catch (CommandNotMappedException e) {
5424:                        // out of luck, no command action mapping
5425:                    }
5426:                }
5427:
5428:                return null;
5429:            }
5430:
5431:            /**
5432:             * Updates the specified action by calling <code>IUpdate.update</code>
5433:             * if applicable.
5434:             *
5435:             * @param actionId the action id
5436:             */
5437:            private void updateAction(String actionId) {
5438:                Assert.isNotNull(actionId);
5439:                if (fActions != null) {
5440:                    IAction action = (IAction) fActions.get(actionId);
5441:                    if (action instanceof  IUpdate)
5442:                        ((IUpdate) action).update();
5443:                }
5444:            }
5445:
5446:            /**
5447:             * Marks or unmarks the given action to be updated on text selection changes.
5448:             *
5449:             * @param actionId the action id
5450:             * @param mark <code>true</code> if the action is selection dependent
5451:             */
5452:            public void markAsSelectionDependentAction(String actionId,
5453:                    boolean mark) {
5454:                Assert.isNotNull(actionId);
5455:                if (mark) {
5456:                    if (!fSelectionActions.contains(actionId))
5457:                        fSelectionActions.add(actionId);
5458:                } else
5459:                    fSelectionActions.remove(actionId);
5460:            }
5461:
5462:            /**
5463:             * Marks or unmarks the given action to be updated on content changes.
5464:             *
5465:             * @param actionId the action id
5466:             * @param mark <code>true</code> if the action is content dependent
5467:             */
5468:            public void markAsContentDependentAction(String actionId,
5469:                    boolean mark) {
5470:                Assert.isNotNull(actionId);
5471:                if (mark) {
5472:                    if (!fContentActions.contains(actionId))
5473:                        fContentActions.add(actionId);
5474:                } else
5475:                    fContentActions.remove(actionId);
5476:            }
5477:
5478:            /**
5479:             * Marks or unmarks the given action to be updated on property changes.
5480:             *
5481:             * @param actionId the action id
5482:             * @param mark <code>true</code> if the action is property dependent
5483:             * @since 2.0
5484:             */
5485:            public void markAsPropertyDependentAction(String actionId,
5486:                    boolean mark) {
5487:                Assert.isNotNull(actionId);
5488:                if (mark) {
5489:                    if (!fPropertyActions.contains(actionId))
5490:                        fPropertyActions.add(actionId);
5491:                } else
5492:                    fPropertyActions.remove(actionId);
5493:            }
5494:
5495:            /**
5496:             * Marks or unmarks the given action to be updated on state changes.
5497:             *
5498:             * @param actionId the action id
5499:             * @param mark <code>true</code> if the action is state dependent
5500:             * @since 2.0
5501:             */
5502:            public void markAsStateDependentAction(String actionId, boolean mark) {
5503:                Assert.isNotNull(actionId);
5504:                if (mark) {
5505:                    if (!fStateActions.contains(actionId))
5506:                        fStateActions.add(actionId);
5507:                } else
5508:                    fStateActions.remove(actionId);
5509:            }
5510:
5511:            /**
5512:             * Updates all selection dependent actions.
5513:             */
5514:            protected void updateSelectionDependentActions() {
5515:                if (fSelectionActions != null) {
5516:                    Iterator e = fSelectionActions.iterator();
5517:                    while (e.hasNext())
5518:                        updateAction((String) e.next());
5519:                }
5520:            }
5521:
5522:            /**
5523:             * Updates all content dependent actions.
5524:             */
5525:            protected void updateContentDependentActions() {
5526:                if (fContentActions != null) {
5527:                    Iterator e = fContentActions.iterator();
5528:                    while (e.hasNext())
5529:                        updateAction((String) e.next());
5530:                }
5531:            }
5532:
5533:            /**
5534:             * Updates all property dependent actions.
5535:             * @since 2.0
5536:             */
5537:            protected void updatePropertyDependentActions() {
5538:                if (fPropertyActions != null) {
5539:                    Iterator e = fPropertyActions.iterator();
5540:                    while (e.hasNext())
5541:                        updateAction((String) e.next());
5542:                }
5543:            }
5544:
5545:            /**
5546:             * Updates all state dependent actions.
5547:             * @since 2.0
5548:             */
5549:            protected void updateStateDependentActions() {
5550:                if (fStateActions != null) {
5551:                    Iterator e = fStateActions.iterator();
5552:                    while (e.hasNext())
5553:                        updateAction((String) e.next());
5554:                }
5555:            }
5556:
5557:            /**
5558:             * Creates action entries for all SWT StyledText actions as defined in
5559:             * <code>org.eclipse.swt.custom.ST</code>. Overwrites and
5560:             * extends the list of these actions afterwards.
5561:             * <p>
5562:             * Subclasses may extend.
5563:             * </p>
5564:             * @since 2.0
5565:             */
5566:            protected void createNavigationActions() {
5567:
5568:                IAction action;
5569:
5570:                StyledText textWidget = fSourceViewer.getTextWidget();
5571:                for (int i = 0; i < ACTION_MAP.length; i++) {
5572:                    IdMapEntry entry = ACTION_MAP[i];
5573:                    action = new TextNavigationAction(textWidget, entry
5574:                            .getAction());
5575:                    action.setActionDefinitionId(entry.getActionId());
5576:                    setAction(entry.getActionId(), action);
5577:                }
5578:
5579:                action = new ToggleOverwriteModeAction(EditorMessages
5580:                        .getBundleForConstructedKeys(),
5581:                        "Editor.ToggleOverwriteMode."); //$NON-NLS-1$
5582:                action
5583:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.TOGGLE_OVERWRITE);
5584:                setAction(ITextEditorActionDefinitionIds.TOGGLE_OVERWRITE,
5585:                        action);
5586:                textWidget.setKeyBinding(SWT.INSERT, SWT.NULL);
5587:
5588:                action = new ScrollLinesAction(-1);
5589:                action
5590:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SCROLL_LINE_UP);
5591:                setAction(ITextEditorActionDefinitionIds.SCROLL_LINE_UP, action);
5592:
5593:                action = new ScrollLinesAction(1);
5594:                action
5595:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SCROLL_LINE_DOWN);
5596:                setAction(ITextEditorActionDefinitionIds.SCROLL_LINE_DOWN,
5597:                        action);
5598:
5599:                action = new LineEndAction(textWidget, false);
5600:                action
5601:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_END);
5602:                setAction(ITextEditorActionDefinitionIds.LINE_END, action);
5603:
5604:                action = new LineStartAction(textWidget, false);
5605:                action
5606:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_START);
5607:                setAction(ITextEditorActionDefinitionIds.LINE_START, action);
5608:
5609:                action = new LineEndAction(textWidget, true);
5610:                action
5611:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_END);
5612:                setAction(ITextEditorActionDefinitionIds.SELECT_LINE_END,
5613:                        action);
5614:
5615:                action = new LineStartAction(textWidget, true);
5616:                action
5617:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_START);
5618:                setAction(ITextEditorActionDefinitionIds.SELECT_LINE_START,
5619:                        action);
5620:
5621:                // to accommodate https://bugs.eclipse.org/bugs/show_bug.cgi?id=51516
5622:                // nullify handling of DELETE key by StyledText
5623:                textWidget.setKeyBinding(SWT.DEL, SWT.NULL);
5624:            }
5625:
5626:            /**
5627:             * Creates this editor's accessibility actions.
5628:             * @since 2.0
5629:             */
5630:            private void createAccessibilityActions() {
5631:                IAction action = new ShowRulerContextMenuAction();
5632:                action
5633:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SHOW_RULER_CONTEXT_MENU);
5634:                setAction(
5635:                        ITextEditorActionDefinitionIds.SHOW_RULER_CONTEXT_MENU,
5636:                        action);
5637:            }
5638:
5639:            /**
5640:             * Creates this editor's undo/redo actions.
5641:             * <p>
5642:             * Subclasses may override or extend.</p>
5643:             *
5644:             * @since 3.1
5645:             */
5646:            protected void createUndoRedoActions() {
5647:                IUndoContext undoContext = getUndoContext();
5648:                if (undoContext != null) {
5649:                    // Use actions provided by global undo/redo
5650:
5651:                    // Create the undo action
5652:                    OperationHistoryActionHandler undoAction = new UndoActionHandler(
5653:                            getEditorSite(), undoContext);
5654:                    PlatformUI.getWorkbench().getHelpSystem().setHelp(
5655:                            undoAction,
5656:                            IAbstractTextEditorHelpContextIds.UNDO_ACTION);
5657:                    undoAction
5658:                            .setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO);
5659:                    registerUndoRedoAction(ITextEditorActionConstants.UNDO,
5660:                            undoAction);
5661:
5662:                    // Create the redo action.
5663:                    OperationHistoryActionHandler redoAction = new RedoActionHandler(
5664:                            getEditorSite(), undoContext);
5665:                    PlatformUI.getWorkbench().getHelpSystem().setHelp(
5666:                            redoAction,
5667:                            IAbstractTextEditorHelpContextIds.REDO_ACTION);
5668:                    redoAction
5669:                            .setActionDefinitionId(IWorkbenchActionDefinitionIds.REDO);
5670:                    registerUndoRedoAction(ITextEditorActionConstants.REDO,
5671:                            redoAction);
5672:
5673:                    // Install operation approvers
5674:                    IOperationHistory history = OperationHistoryFactory
5675:                            .getOperationHistory();
5676:
5677:                    // The first approver will prompt when operations affecting outside elements are to be undone or redone.
5678:                    if (fNonLocalOperationApprover != null)
5679:                        history
5680:                                .removeOperationApprover(fNonLocalOperationApprover);
5681:                    fNonLocalOperationApprover = getUndoRedoOperationApprover(undoContext);
5682:                    history.addOperationApprover(fNonLocalOperationApprover);
5683:
5684:                    // The second approver will prompt from this editor when an undo is attempted on an operation
5685:                    // and it is not the most recent operation in the editor.
5686:                    if (fLinearUndoViolationApprover != null)
5687:                        history
5688:                                .removeOperationApprover(fLinearUndoViolationApprover);
5689:                    fLinearUndoViolationApprover = new LinearUndoViolationUserApprover(
5690:                            undoContext, this );
5691:                    history.addOperationApprover(fLinearUndoViolationApprover);
5692:
5693:                } else {
5694:                    // Use text operation actions (pre 3.1 style)
5695:
5696:                    ResourceAction action;
5697:
5698:                    if (getAction(ITextEditorActionConstants.UNDO) == null) {
5699:                        action = new TextOperationAction(EditorMessages
5700:                                .getBundleForConstructedKeys(),
5701:                                "Editor.Undo.", this , ITextOperationTarget.UNDO); //$NON-NLS-1$
5702:                        action
5703:                                .setHelpContextId(IAbstractTextEditorHelpContextIds.UNDO_ACTION);
5704:                        action
5705:                                .setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO);
5706:                        setAction(ITextEditorActionConstants.UNDO, action);
5707:                    }
5708:
5709:                    if (getAction(ITextEditorActionConstants.REDO) == null) {
5710:                        action = new TextOperationAction(EditorMessages
5711:                                .getBundleForConstructedKeys(),
5712:                                "Editor.Redo.", this , ITextOperationTarget.REDO); //$NON-NLS-1$
5713:                        action
5714:                                .setHelpContextId(IAbstractTextEditorHelpContextIds.REDO_ACTION);
5715:                        action
5716:                                .setActionDefinitionId(IWorkbenchActionDefinitionIds.REDO);
5717:                        setAction(ITextEditorActionConstants.REDO, action);
5718:                    }
5719:                }
5720:            }
5721:
5722:            /**
5723:             * Registers the given undo/redo action under the given ID and
5724:             * ensures that previously installed actions get disposed. It
5725:             * also takes care of re-registering the new action with the
5726:             * global action handler.
5727:             * 
5728:             * @param actionId	the action id under which to register the action
5729:             * @param action	the action to register
5730:             * @since 3.1
5731:             */
5732:            private void registerUndoRedoAction(String actionId,
5733:                    OperationHistoryActionHandler action) {
5734:                IAction oldAction = getAction(actionId);
5735:                if (oldAction instanceof  OperationHistoryActionHandler)
5736:                    ((OperationHistoryActionHandler) oldAction).dispose();
5737:
5738:                setAction(actionId, action);
5739:
5740:                IActionBars actionBars = getEditorSite().getActionBars();
5741:                if (actionBars != null)
5742:                    actionBars.setGlobalActionHandler(actionId, action);
5743:            }
5744:
5745:            /**
5746:             * Return an {@link IOperationApprover} appropriate for approving the undo and
5747:             * redo of operations that have the specified undo context.
5748:             * <p>
5749:             * Subclasses may override.
5750:             * </p>
5751:             * @param undoContext	the IUndoContext of operations that should be examined
5752:             * 						by the operation approver
5753:             * @return	the <code>IOperationApprover</code> appropriate for approving undo
5754:             * 			and redo operations inside this editor, or <code>null</code> if no
5755:             * 			approval is needed
5756:             * @since 3.1
5757:             */
5758:            protected IOperationApprover getUndoRedoOperationApprover(
5759:                    IUndoContext undoContext) {
5760:                return new NonLocalUndoUserApprover(undoContext, this ,
5761:                        new Object[] { getEditorInput() }, Object.class);
5762:            }
5763:
5764:            /**
5765:             * Creates this editor's standard actions and connects them with the global
5766:             * workbench actions.
5767:             * <p>
5768:             * Subclasses may extend.</p>
5769:             */
5770:            protected void createActions() {
5771:
5772:                ResourceAction action;
5773:
5774:                action = new TextOperationAction(EditorMessages
5775:                        .getBundleForConstructedKeys(),
5776:                        "Editor.Cut.", this , ITextOperationTarget.CUT); //$NON-NLS-1$
5777:                action
5778:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.CUT_ACTION);
5779:                action.setActionDefinitionId(IWorkbenchActionDefinitionIds.CUT);
5780:                setAction(ITextEditorActionConstants.CUT, action);
5781:
5782:                action = new TextOperationAction(EditorMessages
5783:                        .getBundleForConstructedKeys(),
5784:                        "Editor.Copy.", this , ITextOperationTarget.COPY, true); //$NON-NLS-1$
5785:                action
5786:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_ACTION);
5787:                action
5788:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY);
5789:                setAction(ITextEditorActionConstants.COPY, action);
5790:
5791:                action = new TextOperationAction(EditorMessages
5792:                        .getBundleForConstructedKeys(),
5793:                        "Editor.Paste.", this , ITextOperationTarget.PASTE); //$NON-NLS-1$
5794:                action
5795:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.PASTE_ACTION);
5796:                action
5797:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE);
5798:                setAction(ITextEditorActionConstants.PASTE, action);
5799:
5800:                action = new TextOperationAction(EditorMessages
5801:                        .getBundleForConstructedKeys(),
5802:                        "Editor.Delete.", this , ITextOperationTarget.DELETE); //$NON-NLS-1$
5803:                action
5804:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.DELETE_ACTION);
5805:                action
5806:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.DELETE);
5807:                setAction(ITextEditorActionConstants.DELETE, action);
5808:
5809:                action = new DeleteLineAction(
5810:                        EditorMessages.getBundleForConstructedKeys(),
5811:                        "Editor.DeleteLine.", this , DeleteLineAction.WHOLE, false); //$NON-NLS-1$
5812:                action
5813:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.DELETE_LINE_ACTION);
5814:                action
5815:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_LINE);
5816:                setAction(ITextEditorActionConstants.DELETE_LINE, action);
5817:
5818:                action = new DeleteLineAction(EditorMessages
5819:                        .getBundleForConstructedKeys(),
5820:                        "Editor.CutLine.", this , DeleteLineAction.WHOLE, true); //$NON-NLS-1$
5821:                action
5822:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.CUT_LINE_ACTION);
5823:                action
5824:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.CUT_LINE);
5825:                setAction(ITextEditorActionConstants.CUT_LINE, action);
5826:
5827:                action = new DeleteLineAction(
5828:                        EditorMessages.getBundleForConstructedKeys(),
5829:                        "Editor.DeleteLineToBeginning.", this , DeleteLineAction.TO_BEGINNING, false); //$NON-NLS-1$
5830:                action
5831:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.DELETE_LINE_TO_BEGINNING_ACTION);
5832:                action
5833:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_LINE_TO_BEGINNING);
5834:                setAction(ITextEditorActionConstants.DELETE_LINE_TO_BEGINNING,
5835:                        action);
5836:
5837:                action = new DeleteLineAction(
5838:                        EditorMessages.getBundleForConstructedKeys(),
5839:                        "Editor.CutLineToBeginning.", this , DeleteLineAction.TO_BEGINNING, true); //$NON-NLS-1$
5840:                action
5841:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.CUT_LINE_TO_BEGINNING_ACTION);
5842:                action
5843:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.CUT_LINE_TO_BEGINNING);
5844:                setAction(ITextEditorActionConstants.CUT_LINE_TO_BEGINNING,
5845:                        action);
5846:
5847:                action = new DeleteLineAction(
5848:                        EditorMessages.getBundleForConstructedKeys(),
5849:                        "Editor.DeleteLineToEnd.", this , DeleteLineAction.TO_END, false); //$NON-NLS-1$
5850:                action
5851:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.DELETE_LINE_TO_END_ACTION);
5852:                action
5853:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_LINE_TO_END);
5854:                setAction(ITextEditorActionConstants.DELETE_LINE_TO_END, action);
5855:
5856:                action = new DeleteLineAction(
5857:                        EditorMessages.getBundleForConstructedKeys(),
5858:                        "Editor.CutLineToEnd.", this , DeleteLineAction.TO_END, true); //$NON-NLS-1$
5859:                action
5860:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.CUT_LINE_TO_END_ACTION);
5861:                action
5862:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.CUT_LINE_TO_END);
5863:                setAction(ITextEditorActionConstants.CUT_LINE_TO_END, action);
5864:
5865:                action = new JoinLinesAction(EditorMessages
5866:                        .getBundleForConstructedKeys(),
5867:                        "Editor.JoinLines.", this , " "); //$NON-NLS-1$ //$NON-NLS-2$
5868:                action
5869:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.JOIN_LINES_ACTION);
5870:                action
5871:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.JOIN_LINES);
5872:                setAction(ITextEditorActionConstants.JOIN_LINES, action);
5873:
5874:                action = new MarkAction(EditorMessages
5875:                        .getBundleForConstructedKeys(),
5876:                        "Editor.SetMark.", this , MarkAction.SET_MARK); //$NON-NLS-1$
5877:                action
5878:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SET_MARK_ACTION);
5879:                action
5880:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SET_MARK);
5881:                setAction(ITextEditorActionConstants.SET_MARK, action);
5882:
5883:                action = new MarkAction(EditorMessages
5884:                        .getBundleForConstructedKeys(),
5885:                        "Editor.ClearMark.", this , MarkAction.CLEAR_MARK); //$NON-NLS-1$
5886:                action
5887:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.CLEAR_MARK_ACTION);
5888:                action
5889:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.CLEAR_MARK);
5890:                setAction(ITextEditorActionConstants.CLEAR_MARK, action);
5891:
5892:                action = new MarkAction(EditorMessages
5893:                        .getBundleForConstructedKeys(),
5894:                        "Editor.SwapMark.", this , MarkAction.SWAP_MARK); //$NON-NLS-1$
5895:                action
5896:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SWAP_MARK_ACTION);
5897:                action
5898:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SWAP_MARK);
5899:                setAction(ITextEditorActionConstants.SWAP_MARK, action);
5900:
5901:                action = new TextOperationAction(
5902:                        EditorMessages.getBundleForConstructedKeys(),
5903:                        "Editor.SelectAll.", this , ITextOperationTarget.SELECT_ALL, true); //$NON-NLS-1$
5904:                action
5905:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SELECT_ALL_ACTION);
5906:                action
5907:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.SELECT_ALL);
5908:                setAction(ITextEditorActionConstants.SELECT_ALL, action);
5909:
5910:                action = new ShiftAction(
5911:                        EditorMessages.getBundleForConstructedKeys(),
5912:                        "Editor.ShiftRight.", this , ITextOperationTarget.SHIFT_RIGHT); //$NON-NLS-1$
5913:                action
5914:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SHIFT_RIGHT_ACTION);
5915:                action
5916:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SHIFT_RIGHT);
5917:                setAction(ITextEditorActionConstants.SHIFT_RIGHT, action);
5918:
5919:                action = new ShiftAction(
5920:                        EditorMessages.getBundleForConstructedKeys(),
5921:                        "Editor.ShiftRight.", this , ITextOperationTarget.SHIFT_RIGHT) { //$NON-NLS-1$
5922:                    public void update() {
5923:                        updateForTab();
5924:                    }
5925:                };
5926:                setAction(ITextEditorActionConstants.SHIFT_RIGHT_TAB, action);
5927:
5928:                action = new ShiftAction(
5929:                        EditorMessages.getBundleForConstructedKeys(),
5930:                        "Editor.ShiftLeft.", this , ITextOperationTarget.SHIFT_LEFT); //$NON-NLS-1$
5931:                action
5932:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SHIFT_LEFT_ACTION);
5933:                action
5934:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SHIFT_LEFT);
5935:                setAction(ITextEditorActionConstants.SHIFT_LEFT, action);
5936:
5937:                action = new TextOperationAction(EditorMessages
5938:                        .getBundleForConstructedKeys(),
5939:                        "Editor.Print.", this , ITextOperationTarget.PRINT, true); //$NON-NLS-1$
5940:                action
5941:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.PRINT_ACTION);
5942:                action
5943:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.PRINT);
5944:                setAction(ITextEditorActionConstants.PRINT, action);
5945:
5946:                action = new FindReplaceAction(EditorMessages
5947:                        .getBundleForConstructedKeys(),
5948:                        "Editor.FindReplace.", this ); //$NON-NLS-1$
5949:                action
5950:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_ACTION);
5951:                action
5952:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_REPLACE);
5953:                setAction(ITextEditorActionConstants.FIND, action);
5954:
5955:                action = new FindNextAction(EditorMessages
5956:                        .getBundleForConstructedKeys(),
5957:                        "Editor.FindNext.", this , true); //$NON-NLS-1$
5958:                action
5959:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_NEXT_ACTION);
5960:                action
5961:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_NEXT);
5962:                setAction(ITextEditorActionConstants.FIND_NEXT, action);
5963:
5964:                action = new FindNextAction(EditorMessages
5965:                        .getBundleForConstructedKeys(),
5966:                        "Editor.FindPrevious.", this , false); //$NON-NLS-1$
5967:                action
5968:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_PREVIOUS_ACTION);
5969:                action
5970:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_PREVIOUS);
5971:                setAction(ITextEditorActionConstants.FIND_PREVIOUS, action);
5972:
5973:                action = new IncrementalFindAction(EditorMessages
5974:                        .getBundleForConstructedKeys(),
5975:                        "Editor.FindIncremental.", this , true); //$NON-NLS-1$
5976:                action
5977:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_INCREMENTAL_ACTION);
5978:                action
5979:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_INCREMENTAL);
5980:                setAction(ITextEditorActionConstants.FIND_INCREMENTAL, action);
5981:
5982:                action = new IncrementalFindAction(EditorMessages
5983:                        .getBundleForConstructedKeys(),
5984:                        "Editor.FindIncrementalReverse.", this , false); //$NON-NLS-1$
5985:                action
5986:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_INCREMENTAL_REVERSE_ACTION);
5987:                action
5988:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_INCREMENTAL_REVERSE);
5989:                setAction(ITextEditorActionConstants.FIND_INCREMENTAL_REVERSE,
5990:                        action);
5991:
5992:                action = new SaveAction(EditorMessages
5993:                        .getBundleForConstructedKeys(), "Editor.Save.", this ); //$NON-NLS-1$
5994:                action
5995:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SAVE_ACTION);
5996:                /*
5997:                 * if the line below is uncommented then the key binding does not work any more
5998:                 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53417
5999:                 */
6000:                //		action.setActionDefinitionId(ITextEditorActionDefinitionIds.SAVE);
6001:                setAction(ITextEditorActionConstants.SAVE, action);
6002:
6003:                action = new RevertToSavedAction(EditorMessages
6004:                        .getBundleForConstructedKeys(), "Editor.Revert.", this ); //$NON-NLS-1$
6005:                action
6006:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.REVERT_TO_SAVED_ACTION);
6007:                action
6008:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.REVERT_TO_SAVED);
6009:                setAction(ITextEditorActionConstants.REVERT_TO_SAVED, action);
6010:
6011:                action = new GotoLineAction(EditorMessages
6012:                        .getBundleForConstructedKeys(),
6013:                        "Editor.GotoLine.", this ); //$NON-NLS-1$
6014:                action
6015:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.GOTO_LINE_ACTION);
6016:                action
6017:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_GOTO);
6018:                setAction(ITextEditorActionConstants.GOTO_LINE, action);
6019:
6020:                action = new MoveLinesAction(EditorMessages
6021:                        .getBundleForConstructedKeys(),
6022:                        "Editor.MoveLinesUp.", this , true, false); //$NON-NLS-1$
6023:                action
6024:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.MOVE_LINES_ACTION);
6025:                action
6026:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.MOVE_LINES_UP);
6027:                setAction(ITextEditorActionConstants.MOVE_LINE_UP, action);
6028:
6029:                action = new MoveLinesAction(EditorMessages
6030:                        .getBundleForConstructedKeys(),
6031:                        "Editor.MoveLinesDown.", this , false, false); //$NON-NLS-1$
6032:                action
6033:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.MOVE_LINES_ACTION);
6034:                action
6035:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.MOVE_LINES_DOWN);
6036:                setAction(ITextEditorActionConstants.MOVE_LINE_DOWN, action);
6037:
6038:                action = new MoveLinesAction(EditorMessages
6039:                        .getBundleForConstructedKeys(),
6040:                        "Editor.CopyLineUp.", this , true, true); //$NON-NLS-1$
6041:                action
6042:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_LINES_ACTION);
6043:                action
6044:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.COPY_LINES_UP);
6045:                setAction(ITextEditorActionConstants.COPY_LINE_UP, action);
6046:
6047:                action = new MoveLinesAction(EditorMessages
6048:                        .getBundleForConstructedKeys(),
6049:                        "Editor.CopyLineDown.", this , false, true); //$NON-NLS-1$
6050:                action
6051:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_LINES_ACTION);
6052:                action
6053:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.COPY_LINES_DOWN);
6054:                setAction(ITextEditorActionConstants.COPY_LINE_DOWN, action);
6055:
6056:                action = new CaseAction(EditorMessages
6057:                        .getBundleForConstructedKeys(),
6058:                        "Editor.UpperCase.", this , true); //$NON-NLS-1$
6059:                action
6060:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.UPPER_CASE_ACTION);
6061:                action
6062:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.UPPER_CASE);
6063:                setAction(ITextEditorActionConstants.UPPER_CASE, action);
6064:
6065:                action = new CaseAction(EditorMessages
6066:                        .getBundleForConstructedKeys(),
6067:                        "Editor.LowerCase.", this , false); //$NON-NLS-1$
6068:                action
6069:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.LOWER_CASE_ACTION);
6070:                action
6071:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.LOWER_CASE);
6072:                setAction(ITextEditorActionConstants.LOWER_CASE, action);
6073:
6074:                action = new InsertLineAction(EditorMessages
6075:                        .getBundleForConstructedKeys(),
6076:                        "Editor.SmartEnter.", this , false); //$NON-NLS-1$
6077:                action
6078:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SMART_ENTER_ACTION);
6079:                action
6080:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SMART_ENTER);
6081:                setAction(ITextEditorActionConstants.SMART_ENTER, action);
6082:
6083:                action = new InsertLineAction(EditorMessages
6084:                        .getBundleForConstructedKeys(),
6085:                        "Editor.SmartEnterInverse.", this , true); //$NON-NLS-1$
6086:                action
6087:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SMART_ENTER_ACTION);
6088:                action
6089:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SMART_ENTER_INVERSE);
6090:                setAction(ITextEditorActionConstants.SMART_ENTER_INVERSE,
6091:                        action);
6092:
6093:                action = new ToggleInsertModeAction(EditorMessages
6094:                        .getBundleForConstructedKeys(),
6095:                        "Editor.ToggleInsertMode."); //$NON-NLS-1$
6096:                action
6097:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.TOGGLE_INSERT_MODE_ACTION);
6098:                action
6099:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.TOGGLE_INSERT_MODE);
6100:                setAction(ITextEditorActionConstants.TOGGLE_INSERT_MODE, action);
6101:
6102:                action = new HippieCompleteAction(EditorMessages
6103:                        .getBundleForConstructedKeys(),
6104:                        "Editor.HippieCompletion.", this ); //$NON-NLS-1$
6105:                action
6106:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.HIPPIE_COMPLETION_ACTION);
6107:                action
6108:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.HIPPIE_COMPLETION);
6109:                setAction(ITextEditorActionConstants.HIPPIE_COMPLETION, action);
6110:
6111:                action = new TextOperationAction(EditorMessages
6112:                        .getBundleForConstructedKeys(),
6113:                        "Editor.QuickAssist.", this , ISourceViewer.QUICK_ASSIST); //$NON-NLS-1$
6114:                action
6115:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.QUICK_ASSIST_ACTION);
6116:                action
6117:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.QUICK_ASSIST);
6118:                setAction(ITextEditorActionConstants.QUICK_ASSIST, action);
6119:                markAsStateDependentAction(
6120:                        ITextEditorActionConstants.QUICK_ASSIST, true);
6121:
6122:                action = new GotoAnnotationAction(this , true);
6123:                setAction(ITextEditorActionConstants.NEXT, action);
6124:                action = new GotoAnnotationAction(this , false);
6125:                setAction(ITextEditorActionConstants.PREVIOUS, action);
6126:
6127:                action = new RecenterAction(EditorMessages
6128:                        .getBundleForConstructedKeys(),
6129:                        "Editor.Recenter.", this ); //$NON-NLS-1$
6130:                action
6131:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.RECENTER_ACTION);
6132:                action
6133:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.RECENTER);
6134:                setAction(ITextEditorActionConstants.RECENTER, action);
6135:
6136:                action = new ShowWhitespaceCharactersAction(
6137:                        EditorMessages.getBundleForConstructedKeys(),
6138:                        "Editor.ShowWhitespaceCharacters.", this , getPreferenceStore()); //$NON-NLS-1$
6139:                action
6140:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SHOW_WHITESPACE_CHARACTERS_ACTION);
6141:                action
6142:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SHOW_WHITESPACE_CHARACTERS);
6143:                setAction(
6144:                        ITextEditorActionConstants.SHOW_WHITESPACE_CHARACTERS,
6145:                        action);
6146:
6147:                ResourceAction resAction = new TextOperationAction(
6148:                        EditorMessages.getBundleForConstructedKeys(),
6149:                        "Editor.ShowInformation.", this , ISourceViewer.INFORMATION, true); //$NON-NLS-1$
6150:                resAction = new InformationDispatchAction(
6151:                        EditorMessages.getBundleForConstructedKeys(),
6152:                        "Editor.ShowInformation.", (TextOperationAction) resAction); //$NON-NLS-1$
6153:                action
6154:                        .setHelpContextId(IAbstractTextEditorHelpContextIds.SHOW_INFORMATION_ACTION);
6155:                resAction
6156:                        .setActionDefinitionId(ITextEditorActionDefinitionIds.SHOW_INFORMATION);
6157:                setAction(ITextEditorActionConstants.SHOW_INFORMATION,
6158:                        resAction);
6159:
6160:                PropertyDialogAction openProperties = new PropertyDialogAction(
6161:                        new IShellProvider() {
6162:                            public Shell getShell() {
6163:                                return getSite().getShell();
6164:                            }
6165:                        }, new ISelectionProvider() {
6166:                            public void addSelectionChangedListener(
6167:                                    ISelectionChangedListener listener) {
6168:                            }
6169:
6170:                            public ISelection getSelection() {
6171:                                return new StructuredSelection(getEditorInput());
6172:                            }
6173:
6174:                            public void removeSelectionChangedListener(
6175:                                    ISelectionChangedListener listener) {
6176:                            }
6177:
6178:                            public void setSelection(ISelection selection) {
6179:                            }
6180:                        });
6181:                openProperties
6182:                        .setActionDefinitionId(IWorkbenchActionDefinitionIds.PROPERTIES);
6183:                setAction(ITextEditorActionConstants.PROPERTIES, openProperties);
6184:
6185:                markAsContentDependentAction(ITextEditorActionConstants.UNDO,
6186:                        true);
6187:                markAsContentDependentAction(ITextEditorActionConstants.REDO,
6188:                        true);
6189:                markAsContentDependentAction(ITextEditorActionConstants.FIND,
6190:                        true);
6191:                markAsContentDependentAction(
6192:                        ITextEditorActionConstants.FIND_NEXT, true);
6193:                markAsContentDependentAction(
6194:                        ITextEditorActionConstants.FIND_PREVIOUS, true);
6195:                markAsContentDependentAction(
6196:                        ITextEditorActionConstants.FIND_INCREMENTAL, true);
6197:                markAsContentDependentAction(
6198:                        ITextEditorActionConstants.FIND_INCREMENTAL_REVERSE,
6199:                        true);
6200:
6201:                markAsSelectionDependentAction(ITextEditorActionConstants.CUT,
6202:                        true);
6203:                markAsSelectionDependentAction(ITextEditorActionConstants.COPY,
6204:                        true);
6205:                markAsSelectionDependentAction(
6206:                        ITextEditorActionConstants.PASTE, true);
6207:                markAsSelectionDependentAction(
6208:                        ITextEditorActionConstants.DELETE, true);
6209:                markAsSelectionDependentAction(
6210:                        ITextEditorActionConstants.SHIFT_RIGHT, true);
6211:                markAsSelectionDependentAction(
6212:                        ITextEditorActionConstants.SHIFT_RIGHT_TAB, true);
6213:                markAsSelectionDependentAction(
6214:                        ITextEditorActionConstants.UPPER_CASE, true);
6215:                markAsSelectionDependentAction(
6216:                        ITextEditorActionConstants.LOWER_CASE, true);
6217:
6218:                markAsPropertyDependentAction(ITextEditorActionConstants.UNDO,
6219:                        true);
6220:                markAsPropertyDependentAction(ITextEditorActionConstants.REDO,
6221:                        true);
6222:                markAsPropertyDependentAction(
6223:                        ITextEditorActionConstants.REVERT_TO_SAVED, true);
6224:
6225:                markAsStateDependentAction(ITextEditorActionConstants.UNDO,
6226:                        true);
6227:                markAsStateDependentAction(ITextEditorActionConstants.REDO,
6228:                        true);
6229:                markAsStateDependentAction(ITextEditorActionConstants.CUT, true);
6230:                markAsStateDependentAction(ITextEditorActionConstants.PASTE,
6231:                        true);
6232:                markAsStateDependentAction(ITextEditorActionConstants.DELETE,
6233:                        true);
6234:                markAsStateDependentAction(
6235:                        ITextEditorActionConstants.SHIFT_RIGHT, true);
6236:                markAsStateDependentAction(
6237:                        ITextEditorActionConstants.SHIFT_RIGHT_TAB, true);
6238:                markAsStateDependentAction(
6239:                        ITextEditorActionConstants.SHIFT_LEFT, true);
6240:                markAsStateDependentAction(ITextEditorActionConstants.FIND,
6241:                        true);
6242:                markAsStateDependentAction(
6243:                        ITextEditorActionConstants.DELETE_LINE, true);
6244:                markAsStateDependentAction(
6245:                        ITextEditorActionConstants.DELETE_LINE_TO_BEGINNING,
6246:                        true);
6247:                markAsStateDependentAction(
6248:                        ITextEditorActionConstants.DELETE_LINE_TO_END, true);
6249:                markAsStateDependentAction(
6250:                        ITextEditorActionConstants.MOVE_LINE_UP, true);
6251:                markAsStateDependentAction(
6252:                        ITextEditorActionConstants.MOVE_LINE_DOWN, true);
6253:                markAsStateDependentAction(ITextEditorActionConstants.CUT_LINE,
6254:                        true);
6255:                markAsStateDependentAction(
6256:                        ITextEditorActionConstants.CUT_LINE_TO_BEGINNING, true);
6257:                markAsStateDependentAction(
6258:                        ITextEditorActionConstants.CUT_LINE_TO_END, true);
6259:
6260:                setActionActivationCode(
6261:                        ITextEditorActionConstants.SHIFT_RIGHT_TAB, '\t', -1,
6262:                        SWT.NONE);
6263:                setActionActivationCode(ITextEditorActionConstants.SHIFT_LEFT,
6264:                        '\t', -1, SWT.SHIFT);
6265:            }
6266:
6267:            /**
6268:             * Convenience method to add the action installed under the given action id to the given menu.
6269:             * @param menu the menu to add the action to
6270:             * @param actionId the id of the action to be added
6271:             */
6272:            protected final void addAction(IMenuManager menu, String actionId) {
6273:                IAction action = getAction(actionId);
6274:                if (action != null) {
6275:                    if (action instanceof  IUpdate)
6276:                        ((IUpdate) action).update();
6277:                    menu.add(action);
6278:                }
6279:            }
6280:
6281:            /**
6282:             * Convenience method to add the action installed under the given action id to the specified group of the menu.
6283:             * @param menu the menu to add the action to
6284:             * @param group the group in the menu
6285:             * @param actionId the id of the action to add
6286:             */
6287:            protected final void addAction(IMenuManager menu, String group,
6288:                    String actionId) {
6289:                IAction action = getAction(actionId);
6290:                if (action != null) {
6291:                    if (action instanceof  IUpdate)
6292:                        ((IUpdate) action).update();
6293:
6294:                    IMenuManager subMenu = menu.findMenuUsingPath(group);
6295:                    if (subMenu != null)
6296:                        subMenu.add(action);
6297:                    else
6298:                        menu.appendToGroup(group, action);
6299:                }
6300:            }
6301:
6302:            /**
6303:             * Convenience method to add a new group after the specified group.
6304:             * @param menu the menu to add the new group to
6305:             * @param existingGroup the group after which to insert the new group
6306:             * @param newGroup the new group
6307:             */
6308:            protected final void addGroup(IMenuManager menu,
6309:                    String existingGroup, String newGroup) {
6310:                IMenuManager subMenu = menu.findMenuUsingPath(existingGroup);
6311:                if (subMenu != null)
6312:                    subMenu.add(new Separator(newGroup));
6313:                else
6314:                    menu.appendToGroup(existingGroup, new Separator(newGroup));
6315:            }
6316:
6317:            /**
6318:             * Sets up the ruler context menu before it is made visible.
6319:             * <p>
6320:             * Subclasses may extend to add other actions.</p>
6321:             *
6322:             * @param menu the menu
6323:             */
6324:            protected void rulerContextMenuAboutToShow(IMenuManager menu) {
6325:
6326:                menu.add(new Separator(ITextEditorActionConstants.GROUP_REST));
6327:                menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
6328:
6329:                for (Iterator i = fRulerContextMenuListeners.iterator(); i
6330:                        .hasNext();)
6331:                    ((IMenuListener) i.next()).menuAboutToShow(menu);
6332:
6333:                addAction(menu,
6334:                        ITextEditorActionConstants.RULER_MANAGE_BOOKMARKS);
6335:                addAction(menu, ITextEditorActionConstants.RULER_MANAGE_TASKS);
6336:            }
6337:
6338:            /**
6339:             * Sets up this editor's context menu before it is made visible.
6340:             * <p>
6341:             * Subclasses may extend to add other actions.</p>
6342:             *
6343:             * @param menu the menu
6344:             */
6345:            protected void editorContextMenuAboutToShow(IMenuManager menu) {
6346:
6347:                menu.add(new Separator(ITextEditorActionConstants.GROUP_UNDO));
6348:                menu
6349:                        .add(new GroupMarker(
6350:                                ITextEditorActionConstants.GROUP_SAVE));
6351:                menu.add(new Separator(ITextEditorActionConstants.GROUP_COPY));
6352:                menu.add(new Separator(ITextEditorActionConstants.GROUP_PRINT));
6353:                menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));
6354:                menu.add(new Separator(ITextEditorActionConstants.GROUP_FIND));
6355:                menu.add(new Separator(IWorkbenchActionConstants.GROUP_ADD));
6356:                menu.add(new Separator(ITextEditorActionConstants.GROUP_REST));
6357:                menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
6358:
6359:                if (isEditable()) {
6360:                    addAction(menu, ITextEditorActionConstants.GROUP_UNDO,
6361:                            ITextEditorActionConstants.UNDO);
6362:                    addAction(menu, ITextEditorActionConstants.GROUP_UNDO,
6363:                            ITextEditorActionConstants.REVERT_TO_SAVED);
6364:                    addAction(menu, ITextEditorActionConstants.GROUP_SAVE,
6365:                            ITextEditorActionConstants.SAVE);
6366:                    addAction(menu, ITextEditorActionConstants.GROUP_COPY,
6367:                            ITextEditorActionConstants.CUT);
6368:                    addAction(menu, ITextEditorActionConstants.GROUP_COPY,
6369:                            ITextEditorActionConstants.COPY);
6370:                    addAction(menu, ITextEditorActionConstants.GROUP_COPY,
6371:                            ITextEditorActionConstants.PASTE);
6372:                } else {
6373:                    addAction(menu, ITextEditorActionConstants.GROUP_COPY,
6374:                            ITextEditorActionConstants.COPY);
6375:                }
6376:            }
6377:
6378:            /**
6379:             * Returns the status line manager of this editor.
6380:             * 
6381:             * @return the status line manager of this editor
6382:             * @since 2.0, protected since 3.3
6383:             */
6384:            protected IStatusLineManager getStatusLineManager() {
6385:                return getEditorSite().getActionBars().getStatusLineManager();
6386:            }
6387:
6388:            /*
6389:             * @see IAdaptable#getAdapter(java.lang.Class)
6390:             */
6391:            public Object getAdapter(Class required) {
6392:
6393:                if (IEditorStatusLine.class.equals(required)) {
6394:                    if (fEditorStatusLine == null) {
6395:                        IStatusLineManager statusLineManager = getStatusLineManager();
6396:                        ISelectionProvider selectionProvider = getSelectionProvider();
6397:                        if (statusLineManager != null
6398:                                && selectionProvider != null)
6399:                            fEditorStatusLine = new EditorStatusLine(
6400:                                    statusLineManager, selectionProvider);
6401:                    }
6402:                    return fEditorStatusLine;
6403:                }
6404:
6405:                if (IVerticalRulerInfo.class.equals(required)) {
6406:                    if (fVerticalRuler != null)
6407:                        return fVerticalRuler;
6408:                }
6409:
6410:                if (IMarkRegionTarget.class.equals(required)) {
6411:                    if (fMarkRegionTarget == null) {
6412:                        IStatusLineManager manager = getStatusLineManager();
6413:                        if (manager != null)
6414:                            fMarkRegionTarget = (fSourceViewer == null ? null
6415:                                    : new MarkRegionTarget(fSourceViewer,
6416:                                            manager));
6417:                    }
6418:                    return fMarkRegionTarget;
6419:                }
6420:
6421:                if (DeleteLineTarget.class.equals(required)) {
6422:                    if (fDeleteLineTarget == null) {
6423:                        fDeleteLineTarget = new DeleteLineTarget(fSourceViewer);
6424:                    }
6425:                    return fDeleteLineTarget;
6426:                }
6427:
6428:                if (IncrementalFindTarget.class.equals(required)) {
6429:                    if (fIncrementalFindTarget == null) {
6430:                        IStatusLineManager manager = getStatusLineManager();
6431:                        if (manager != null)
6432:                            fIncrementalFindTarget = (fSourceViewer == null ? null
6433:                                    : new IncrementalFindTarget(fSourceViewer,
6434:                                            manager));
6435:                    }
6436:                    return fIncrementalFindTarget;
6437:                }
6438:
6439:                if (IFindReplaceTarget.class.equals(required)) {
6440:                    if (fFindReplaceTarget == null) {
6441:                        IFindReplaceTarget target = (fSourceViewer == null ? null
6442:                                : fSourceViewer.getFindReplaceTarget());
6443:                        if (target != null) {
6444:                            fFindReplaceTarget = new FindReplaceTarget(this ,
6445:                                    target);
6446:                            if (fFindScopeHighlightColor != null)
6447:                                fFindReplaceTarget
6448:                                        .setScopeHighlightColor(fFindScopeHighlightColor);
6449:                        }
6450:                    }
6451:                    return fFindReplaceTarget;
6452:                }
6453:
6454:                if (ITextOperationTarget.class.equals(required))
6455:                    return (fSourceViewer == null ? null : fSourceViewer
6456:                            .getTextOperationTarget());
6457:
6458:                if (IRewriteTarget.class.equals(required)) {
6459:                    if (fSourceViewer instanceof  ITextViewerExtension) {
6460:                        ITextViewerExtension extension = (ITextViewerExtension) fSourceViewer;
6461:                        return extension.getRewriteTarget();
6462:                    }
6463:                    return null;
6464:                }
6465:
6466:                if (Control.class.equals(required))
6467:                    return fSourceViewer != null ? fSourceViewer
6468:                            .getTextWidget() : null;
6469:
6470:                if (IColumnSupport.class.equals(required)) {
6471:                    if (fColumnSupport == null)
6472:                        fColumnSupport = createColumnSupport();
6473:                    return fColumnSupport;
6474:                }
6475:
6476:                return super .getAdapter(required);
6477:            }
6478:
6479:            /*
6480:             * @see IWorkbenchPart#setFocus()
6481:             */
6482:            public void setFocus() {
6483:                if (fSourceViewer != null
6484:                        && fSourceViewer.getTextWidget() != null)
6485:                    fSourceViewer.getTextWidget().setFocus();
6486:            }
6487:
6488:            /*
6489:             * @see ITextEditor#showsHighlightRangeOnly()
6490:             */
6491:            public boolean showsHighlightRangeOnly() {
6492:                return fShowHighlightRangeOnly;
6493:            }
6494:
6495:            /*
6496:             * @see ITextEditor#showHighlightRangeOnly(boolean)
6497:             */
6498:            public void showHighlightRangeOnly(boolean showHighlightRangeOnly) {
6499:                fShowHighlightRangeOnly = showHighlightRangeOnly;
6500:            }
6501:
6502:            /*
6503:             * @see ITextEditor#setHighlightRange(int, int, boolean)
6504:             */
6505:            public void setHighlightRange(int offset, int length,
6506:                    boolean moveCursor) {
6507:                if (fSourceViewer == null)
6508:                    return;
6509:
6510:                if (fShowHighlightRangeOnly) {
6511:                    if (moveCursor)
6512:                        fSourceViewer.setVisibleRegion(offset, length);
6513:                } else {
6514:                    IRegion rangeIndication = fSourceViewer
6515:                            .getRangeIndication();
6516:                    if (rangeIndication == null
6517:                            || offset != rangeIndication.getOffset()
6518:                            || length != rangeIndication.getLength())
6519:                        fSourceViewer.setRangeIndication(offset, length,
6520:                                moveCursor);
6521:                }
6522:            }
6523:
6524:            /*
6525:             * @see ITextEditor#getHighlightRange()
6526:             */
6527:            public IRegion getHighlightRange() {
6528:                if (fSourceViewer == null)
6529:                    return null;
6530:
6531:                if (fShowHighlightRangeOnly)
6532:                    return getCoverage(fSourceViewer);
6533:
6534:                return fSourceViewer.getRangeIndication();
6535:            }
6536:
6537:            /*
6538:             * @see ITextEditor#resetHighlightRange
6539:             */
6540:            public void resetHighlightRange() {
6541:                if (fSourceViewer == null)
6542:                    return;
6543:
6544:                if (fShowHighlightRangeOnly)
6545:                    fSourceViewer.resetVisibleRegion();
6546:                else
6547:                    fSourceViewer.removeRangeIndication();
6548:            }
6549:
6550:            /**
6551:             * Adjusts the highlight range so that at least the specified range
6552:             * is highlighted.
6553:             * <p>
6554:             * Subclasses may re-implement this method.</p>
6555:             *
6556:             * @param offset the offset of the range which at least should be highlighted
6557:             * @param length the length of the range which at least should be highlighted
6558:             */
6559:            protected void adjustHighlightRange(int offset, int length) {
6560:                if (fSourceViewer == null)
6561:                    return;
6562:
6563:                if (fSourceViewer instanceof  ITextViewerExtension5) {
6564:                    ITextViewerExtension5 extension = (ITextViewerExtension5) fSourceViewer;
6565:                    extension.exposeModelRange(new Region(offset, length));
6566:                } else if (!isVisible(fSourceViewer, offset, length)) {
6567:                    fSourceViewer.resetVisibleRegion();
6568:                }
6569:            }
6570:
6571:            /*
6572:             * @see ITextEditor#selectAndReveal(int, int)
6573:             */
6574:            public void selectAndReveal(int start, int length) {
6575:                selectAndReveal(start, length, start, length);
6576:            }
6577:
6578:            /**
6579:             * Selects and reveals the specified ranges in this text editor.
6580:             *
6581:             * @param selectionStart the offset of the selection
6582:             * @param selectionLength the length of the selection
6583:             * @param revealStart the offset of the revealed range
6584:             * @param revealLength the length of the revealed range
6585:             * @since 3.0
6586:             */
6587:            protected void selectAndReveal(int selectionStart,
6588:                    int selectionLength, int revealStart, int revealLength) {
6589:                if (fSourceViewer == null)
6590:                    return;
6591:
6592:                ISelection selection = getSelectionProvider().getSelection();
6593:                if (selection instanceof  ITextSelection) {
6594:                    ITextSelection textSelection = (ITextSelection) selection;
6595:                    if (textSelection.getOffset() != 0
6596:                            || textSelection.getLength() != 0)
6597:                        markInNavigationHistory();
6598:                }
6599:
6600:                StyledText widget = fSourceViewer.getTextWidget();
6601:                widget.setRedraw(false);
6602:                {
6603:                    adjustHighlightRange(revealStart, revealLength);
6604:                    fSourceViewer.revealRange(revealStart, revealLength);
6605:
6606:                    fSourceViewer.setSelectedRange(selectionStart,
6607:                            selectionLength);
6608:
6609:                    markInNavigationHistory();
6610:                }
6611:                widget.setRedraw(true);
6612:            }
6613:
6614:            /*
6615:             * @see org.eclipse.ui.INavigationLocationProvider#createNavigationLocation()
6616:             * @since 2.1
6617:             */
6618:            public INavigationLocation createEmptyNavigationLocation() {
6619:                return new TextSelectionNavigationLocation(this , false);
6620:            }
6621:
6622:            /*
6623:             * @see org.eclipse.ui.INavigationLocationProvider#createNavigationLocation()
6624:             */
6625:            public INavigationLocation createNavigationLocation() {
6626:                return new TextSelectionNavigationLocation(this , true);
6627:            }
6628:
6629:            /**
6630:             * Writes a check mark of the given situation into the navigation history.
6631:             * @since 2.1
6632:             */
6633:            protected void markInNavigationHistory() {
6634:                getSite().getPage().getNavigationHistory().markLocation(this );
6635:            }
6636:
6637:            /**
6638:             * Hook which gets called when the editor has been saved.
6639:             * Subclasses may extend.
6640:             * @since 2.1
6641:             */
6642:            protected void editorSaved() {
6643:                INavigationLocation[] locations = getSite().getPage()
6644:                        .getNavigationHistory().getLocations();
6645:                IEditorInput input = getEditorInput();
6646:                for (int i = 0; i < locations.length; i++) {
6647:                    if (locations[i] instanceof  TextSelectionNavigationLocation) {
6648:                        if (input.equals(locations[i].getInput())) {
6649:                            TextSelectionNavigationLocation location = (TextSelectionNavigationLocation) locations[i];
6650:                            location.partSaved(this );
6651:                        }
6652:                    }
6653:                }
6654:            }
6655:
6656:            /*
6657:             * @see WorkbenchPart#firePropertyChange(int)
6658:             */
6659:            protected void firePropertyChange(int property) {
6660:                super .firePropertyChange(property);
6661:                updatePropertyDependentActions();
6662:            }
6663:
6664:            /*
6665:             * @see ITextEditorExtension#setStatusField(IStatusField, String)
6666:             * @since 2.0
6667:             */
6668:            public void setStatusField(IStatusField field, String category) {
6669:                Assert.isNotNull(category);
6670:                if (field != null) {
6671:
6672:                    if (fStatusFields == null)
6673:                        fStatusFields = new HashMap(3);
6674:
6675:                    fStatusFields.put(category, field);
6676:                    updateStatusField(category);
6677:
6678:                } else if (fStatusFields != null)
6679:                    fStatusFields.remove(category);
6680:
6681:                if (fIncrementalFindTarget != null
6682:                        && ITextEditorActionConstants.STATUS_CATEGORY_FIND_FIELD
6683:                                .equals(category))
6684:                    fIncrementalFindTarget.setStatusField(field);
6685:            }
6686:
6687:            /**
6688:             * Returns the current status field for the given status category.
6689:             *
6690:             * @param category the status category
6691:             * @return the current status field for the given status category
6692:             * @since 2.0
6693:             */
6694:            protected IStatusField getStatusField(String category) {
6695:                if (category != null && fStatusFields != null)
6696:                    return (IStatusField) fStatusFields.get(category);
6697:                return null;
6698:            }
6699:
6700:            /**
6701:             * Returns whether this editor is in overwrite or insert mode.
6702:             *
6703:             * @return <code>true</code> if in insert mode, <code>false</code> for overwrite mode
6704:             * @since 2.0
6705:             */
6706:            protected boolean isInInsertMode() {
6707:                return !fIsOverwriting;
6708:            }
6709:
6710:            /*
6711:             * @see org.eclipse.ui.texteditor.ITextEditorExtension3#getInsertMode()
6712:             * @since 3.0
6713:             */
6714:            public InsertMode getInsertMode() {
6715:                return fInsertMode;
6716:            }
6717:
6718:            /*
6719:             * @see org.eclipse.ui.texteditor.ITextEditorExtension3#setInsertMode(org.eclipse.ui.texteditor.ITextEditorExtension3.InsertMode)
6720:             * @since 3.0
6721:             */
6722:            public void setInsertMode(InsertMode newMode) {
6723:                List legalModes = getLegalInsertModes();
6724:                if (!legalModes.contains(newMode))
6725:                    throw new IllegalArgumentException();
6726:
6727:                fInsertMode = newMode;
6728:
6729:                handleInsertModeChanged();
6730:            }
6731:
6732:            /**
6733:             * Returns the set of legal insert modes. If insert modes are configured all defined insert modes
6734:             * are legal.
6735:             *
6736:             * @return the set of legal insert modes
6737:             * @since 3.0
6738:             */
6739:            protected List getLegalInsertModes() {
6740:                if (fLegalInsertModes == null) {
6741:                    fLegalInsertModes = new ArrayList();
6742:                    fLegalInsertModes.add(SMART_INSERT);
6743:                    fLegalInsertModes.add(INSERT);
6744:                }
6745:                return fLegalInsertModes;
6746:            }
6747:
6748:            private void switchToNextInsertMode() {
6749:
6750:                InsertMode mode = getInsertMode();
6751:                List legalModes = getLegalInsertModes();
6752:
6753:                int i = 0;
6754:                while (i < legalModes.size()) {
6755:                    if (legalModes.get(i) == mode)
6756:                        break;
6757:                    ++i;
6758:                }
6759:
6760:                i = (i + 1) % legalModes.size();
6761:                InsertMode newMode = (InsertMode) legalModes.get(i);
6762:                setInsertMode(newMode);
6763:            }
6764:
6765:            private void toggleOverwriteMode() {
6766:                if (fIsOverwriteModeEnabled) {
6767:                    fIsOverwriting = !fIsOverwriting;
6768:                    fSourceViewer.getTextWidget().invokeAction(
6769:                            ST.TOGGLE_OVERWRITE);
6770:                    handleInsertModeChanged();
6771:                }
6772:            }
6773:
6774:            /**
6775:             * Configures the given insert mode as legal or illegal. This call is ignored if the set of legal
6776:             * input modes would be empty after the call.
6777:             *
6778:             * @param mode the insert mode to be configured
6779:             * @param legal <code>true</code> if the given mode is legal, <code>false</code> otherwise
6780:             * @since 3.0
6781:             */
6782:            protected void configureInsertMode(InsertMode mode, boolean legal) {
6783:                List legalModes = getLegalInsertModes();
6784:                if (legal) {
6785:                    if (!legalModes.contains(mode))
6786:                        legalModes.add(mode);
6787:                } else if (legalModes.size() > 1) {
6788:                    if (getInsertMode() == mode)
6789:                        switchToNextInsertMode();
6790:                    legalModes.remove(mode);
6791:                }
6792:            }
6793:
6794:            /**
6795:             * Sets the overwrite mode enablement.
6796:             *
6797:             * @param enable <code>true</code> to enable new overwrite mode,
6798:             *        <code>false</code> to disable
6799:             * @since 3.0
6800:             */
6801:            protected void enableOverwriteMode(boolean enable) {
6802:                if (fIsOverwriting && !enable)
6803:                    toggleOverwriteMode();
6804:                fIsOverwriteModeEnabled = enable;
6805:            }
6806:
6807:            private Caret createOverwriteCaret(StyledText styledText) {
6808:                Caret caret = new Caret(styledText, SWT.NULL);
6809:                GC gc = new GC(styledText);
6810:                // XXX this overwrite box is not proportional-font aware
6811:                // take 'a' as a medium sized character
6812:                Point charSize = gc.stringExtent("a"); //$NON-NLS-1$
6813:
6814:                // XXX: Filed request to get a caret with auto-height: https://bugs.eclipse.org/bugs/show_bug.cgi?id=118612
6815:                caret.setSize(charSize.x, styledText.getLineHeight());
6816:                caret.setFont(styledText.getFont());
6817:
6818:                gc.dispose();
6819:
6820:                return caret;
6821:            }
6822:
6823:            private Caret createInsertCaret(StyledText styledText) {
6824:                Caret caret = new Caret(styledText, SWT.NULL);
6825:
6826:                // XXX: Filed request to get a caret with auto-height: https://bugs.eclipse.org/bugs/show_bug.cgi?id=118612
6827:                caret.setSize(getCaretWidthPreference(), styledText
6828:                        .getLineHeight());
6829:                caret.setFont(styledText.getFont());
6830:
6831:                return caret;
6832:            }
6833:
6834:            private Image createRawInsertModeCaretImage(StyledText styledText) {
6835:
6836:                PaletteData caretPalette = new PaletteData(new RGB[] {
6837:                        new RGB(0, 0, 0), new RGB(255, 255, 255) });
6838:                int width = getCaretWidthPreference();
6839:                int widthOffset = width - 1;
6840:
6841:                // XXX: Filed request to get a caret with auto-height: https://bugs.eclipse.org/bugs/show_bug.cgi?id=118612		
6842:                ImageData imageData = new ImageData(4 + widthOffset, styledText
6843:                        .getLineHeight(), 1, caretPalette);
6844:
6845:                Display display = styledText.getDisplay();
6846:                Image bracketImage = new Image(display, imageData);
6847:                GC gc = new GC(bracketImage);
6848:                gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
6849:                gc.setLineWidth(0); // NOTE: 0 means width is 1 but with optimized performance
6850:                int height = imageData.height / 3;
6851:                // gap between two bars of one third of the height
6852:                // draw boxes using lines as drawing a line of a certain width produces
6853:                // rounded corners.
6854:                for (int i = 0; i < width; i++) {
6855:                    gc.drawLine(i, 0, i, height - 1);
6856:                    gc.drawLine(i, imageData.height - height, i,
6857:                            imageData.height - 1);
6858:                }
6859:
6860:                gc.dispose();
6861:
6862:                return bracketImage;
6863:            }
6864:
6865:            private Caret createRawInsertModeCaret(StyledText styledText) {
6866:                // don't draw special raw caret if no smart mode is enabled
6867:                if (!getLegalInsertModes().contains(SMART_INSERT))
6868:                    return createInsertCaret(styledText);
6869:
6870:                Caret caret = new Caret(styledText, SWT.NULL);
6871:                Image image = createRawInsertModeCaretImage(styledText);
6872:                if (image != null)
6873:                    caret.setImage(image);
6874:                else {
6875:                    // XXX: Filed request to get a caret with auto-height: https://bugs.eclipse.org/bugs/show_bug.cgi?id=118612
6876:                    caret.setSize(getCaretWidthPreference(), styledText
6877:                            .getLineHeight());
6878:                }
6879:
6880:                caret.setFont(styledText.getFont());
6881:
6882:                return caret;
6883:            }
6884:
6885:            private int getCaretWidthPreference() {
6886:                if (getPreferenceStore() != null
6887:                        && getPreferenceStore().getBoolean(
6888:                                PREFERENCE_WIDE_CARET))
6889:                    return WIDE_CARET_WIDTH;
6890:
6891:                return SINGLE_CARET_WIDTH;
6892:            }
6893:
6894:            private void updateCaret() {
6895:
6896:                if (fSourceViewer == null)
6897:                    return;
6898:
6899:                StyledText styledText = fSourceViewer.getTextWidget();
6900:
6901:                InsertMode mode = getInsertMode();
6902:
6903:                styledText.setCaret(null);
6904:                disposeNonDefaultCaret();
6905:
6906:                if (getPreferenceStore() == null
6907:                        || !getPreferenceStore().getBoolean(
6908:                                PREFERENCE_USE_CUSTOM_CARETS))
6909:                    Assert.isTrue(fNonDefaultCaret == null);
6910:                else if (fIsOverwriting)
6911:                    fNonDefaultCaret = createOverwriteCaret(styledText);
6912:                else if (SMART_INSERT == mode)
6913:                    fNonDefaultCaret = createInsertCaret(styledText);
6914:                else if (INSERT == mode)
6915:                    fNonDefaultCaret = createRawInsertModeCaret(styledText);
6916:
6917:                if (fNonDefaultCaret != null) {
6918:                    styledText.setCaret(fNonDefaultCaret);
6919:                    fNonDefaultCaretImage = fNonDefaultCaret.getImage();
6920:                } else if (fInitialCaret != styledText.getCaret())
6921:                    styledText.setCaret(fInitialCaret);
6922:            }
6923:
6924:            private void disposeNonDefaultCaret() {
6925:                if (fNonDefaultCaretImage != null) {
6926:                    fNonDefaultCaretImage.dispose();
6927:                    fNonDefaultCaretImage = null;
6928:                }
6929:
6930:                if (fNonDefaultCaret != null) {
6931:                    fNonDefaultCaret.dispose();
6932:                    fNonDefaultCaret = null;
6933:                }
6934:            }
6935:
6936:            /**
6937:             * Handles a change of the editor's insert mode.
6938:             * Subclasses may extend.
6939:             *
6940:             * @since 2.0
6941:             */
6942:            protected void handleInsertModeChanged() {
6943:                updateInsertModeAction();
6944:                updateCaret();
6945:                updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_INPUT_MODE);
6946:            }
6947:
6948:            private void updateInsertModeAction() {
6949:
6950:                // this may be called before the part is fully initialized (see configureInsertMode)
6951:                // drop out in this case.
6952:                if (getSite() == null)
6953:                    return;
6954:
6955:                IAction action = getAction(ITextEditorActionConstants.TOGGLE_INSERT_MODE);
6956:                if (action != null) {
6957:                    action.setEnabled(!fIsOverwriting);
6958:                    action.setChecked(fInsertMode == SMART_INSERT);
6959:                }
6960:            }
6961:
6962:            /**
6963:             * Handles a potential change of the cursor position.
6964:             * Subclasses may extend.
6965:             *
6966:             * @since 2.0
6967:             */
6968:            protected void handleCursorPositionChanged() {
6969:                updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_INPUT_POSITION);
6970:            }
6971:
6972:            /**
6973:             * Updates the status fields for the given category.
6974:             *
6975:             * @param category
6976:             * @since 2.0
6977:             */
6978:            protected void updateStatusField(String category) {
6979:
6980:                if (category == null)
6981:                    return;
6982:
6983:                IStatusField field = getStatusField(category);
6984:                if (field != null) {
6985:
6986:                    String text = null;
6987:
6988:                    if (ITextEditorActionConstants.STATUS_CATEGORY_INPUT_POSITION
6989:                            .equals(category))
6990:                        text = getCursorPosition();
6991:                    else if (ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE
6992:                            .equals(category))
6993:                        text = isEditorInputReadOnly() ? fReadOnlyLabel
6994:                                : fWritableLabel;
6995:                    else if (ITextEditorActionConstants.STATUS_CATEGORY_INPUT_MODE
6996:                            .equals(category)) {
6997:                        InsertMode mode = getInsertMode();
6998:                        if (fIsOverwriting)
6999:                            text = fOverwriteModeLabel;
7000:                        else if (INSERT == mode)
7001:                            text = fInsertModeLabel;
7002:                        else if (SMART_INSERT == mode)
7003:                            text = fSmartInsertModeLabel;
7004:                    }
7005:
7006:                    field.setText(text == null ? fErrorLabel : text);
7007:                }
7008:            }
7009:
7010:            /**
7011:             * Updates all status fields.
7012:             *
7013:             * @since 2.0
7014:             */
7015:            protected void updateStatusFields() {
7016:                if (fStatusFields != null) {
7017:                    Iterator e = fStatusFields.keySet().iterator();
7018:                    while (e.hasNext())
7019:                        updateStatusField((String) e.next());
7020:                }
7021:            }
7022:
7023:            /**
7024:             * Returns a description of the cursor position.
7025:             *
7026:             * @return a description of the cursor position
7027:             * @since 2.0
7028:             */
7029:            protected String getCursorPosition() {
7030:
7031:                if (fSourceViewer == null)
7032:                    return fErrorLabel;
7033:
7034:                StyledText styledText = fSourceViewer.getTextWidget();
7035:                int caret = widgetOffset2ModelOffset(fSourceViewer, styledText
7036:                        .getCaretOffset());
7037:                IDocument document = fSourceViewer.getDocument();
7038:
7039:                if (document == null)
7040:                    return fErrorLabel;
7041:
7042:                try {
7043:
7044:                    int line = document.getLineOfOffset(caret);
7045:
7046:                    int lineOffset = document.getLineOffset(line);
7047:                    int tabWidth = styledText.getTabs();
7048:                    int column = 0;
7049:                    for (int i = lineOffset; i < caret; i++)
7050:                        if ('\t' == document.getChar(i))
7051:                            column += tabWidth
7052:                                    - (tabWidth == 0 ? 0 : column % tabWidth);
7053:                        else
7054:                            column++;
7055:
7056:                    fLineLabel.fValue = line + 1;
7057:                    fColumnLabel.fValue = column + 1;
7058:                    return NLSUtility.format(fPositionLabelPattern,
7059:                            fPositionLabelPatternArguments);
7060:
7061:                } catch (BadLocationException x) {
7062:                    return fErrorLabel;
7063:                }
7064:            }
7065:
7066:            /*
7067:             * @see ITextEditorExtension#isEditorInputReadOnly()
7068:             * @since 2.0
7069:             */
7070:            public boolean isEditorInputReadOnly() {
7071:                IDocumentProvider provider = getDocumentProvider();
7072:                if (provider instanceof  IDocumentProviderExtension) {
7073:                    IDocumentProviderExtension extension = (IDocumentProviderExtension) provider;
7074:                    return extension.isReadOnly(getEditorInput());
7075:                }
7076:                return true;
7077:            }
7078:
7079:            /*
7080:             * @see ITextEditorExtension2#isEditorInputModifiable()
7081:             * @since 2.1
7082:             */
7083:            public boolean isEditorInputModifiable() {
7084:                IDocumentProvider provider = getDocumentProvider();
7085:                if (provider instanceof  IDocumentProviderExtension) {
7086:                    IDocumentProviderExtension extension = (IDocumentProviderExtension) provider;
7087:                    return extension.isModifiable(getEditorInput());
7088:                }
7089:                return true;
7090:            }
7091:
7092:            /*
7093:             * @see ITextEditorExtension#addRulerContextMenuListener(IMenuListener)
7094:             * @since 2.0
7095:             */
7096:            public void addRulerContextMenuListener(IMenuListener listener) {
7097:                fRulerContextMenuListeners.add(listener);
7098:            }
7099:
7100:            /*
7101:             * @see ITextEditorExtension#removeRulerContextMenuListener(IMenuListener)
7102:             * @since 2.0
7103:             */
7104:            public void removeRulerContextMenuListener(IMenuListener listener) {
7105:                fRulerContextMenuListeners.remove(listener);
7106:            }
7107:
7108:            /**
7109:             * Returns whether this editor can handle the move of the original element
7110:             * so that it ends up being the moved element. By default this method
7111:             * returns <code>true</code>. Subclasses may reimplement.
7112:             *
7113:             * @param originalElement the original element
7114:             * @param movedElement the moved element
7115:             * @return whether this editor can handle the move of the original element
7116:             *         so that it ends up being the moved element
7117:             * @since 2.0
7118:             */
7119:            protected boolean canHandleMove(IEditorInput originalElement,
7120:                    IEditorInput movedElement) {
7121:                return true;
7122:            }
7123:
7124:            /**
7125:             * Returns the offset of the given source viewer's document that corresponds
7126:             * to the given widget offset or <code>-1</code> if there is no such offset.
7127:             *
7128:             * @param viewer the source viewer
7129:             * @param widgetOffset the widget offset
7130:             * @return the corresponding offset in the source viewer's document or <code>-1</code>
7131:             * @since 2.1
7132:             */
7133:            protected final static int widgetOffset2ModelOffset(
7134:                    ISourceViewer viewer, int widgetOffset) {
7135:                if (viewer instanceof  ITextViewerExtension5) {
7136:                    ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
7137:                    return extension.widgetOffset2ModelOffset(widgetOffset);
7138:                }
7139:                return widgetOffset + viewer.getVisibleRegion().getOffset();
7140:            }
7141:
7142:            /**
7143:             * Returns the offset of the given source viewer's text widget that corresponds
7144:             * to the given model offset or <code>-1</code> if there is no such offset.
7145:             *
7146:             * @param viewer the source viewer
7147:             * @param modelOffset the model offset
7148:             * @return the corresponding offset in the source viewer's text widget or <code>-1</code>
7149:             * @since 3.0
7150:             */
7151:            protected final static int modelOffset2WidgetOffset(
7152:                    ISourceViewer viewer, int modelOffset) {
7153:                if (viewer instanceof  ITextViewerExtension5) {
7154:                    ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
7155:                    return extension.modelOffset2WidgetOffset(modelOffset);
7156:                }
7157:                return modelOffset - viewer.getVisibleRegion().getOffset();
7158:            }
7159:
7160:            /**
7161:             * Returns the minimal region of the given source viewer's document that completely
7162:             * comprises everything that is visible in the viewer's widget.
7163:             *
7164:             * @param viewer the viewer go return the coverage for
7165:             * @return the minimal region of the source viewer's document comprising the contents of the viewer's widget
7166:             * @since 2.1
7167:             */
7168:            protected final static IRegion getCoverage(ISourceViewer viewer) {
7169:                if (viewer instanceof  ITextViewerExtension5) {
7170:                    ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
7171:                    return extension.getModelCoverage();
7172:                }
7173:                return viewer.getVisibleRegion();
7174:            }
7175:
7176:            /**
7177:             * Tells whether the given region is visible in the given source viewer.
7178:             *
7179:             * @param viewer the source viewer
7180:             * @param offset the offset of the region
7181:             * @param length the length of the region
7182:             * @return <code>true</code> if visible
7183:             * @since 2.1
7184:             */
7185:            protected static final boolean isVisible(ISourceViewer viewer,
7186:                    int offset, int length) {
7187:                if (viewer instanceof  ITextViewerExtension5) {
7188:                    ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
7189:                    IRegion overlap = extension
7190:                            .modelRange2WidgetRange(new Region(offset, length));
7191:                    return overlap != null;
7192:                }
7193:                return viewer.overlapsWithVisibleRegion(offset, length);
7194:            }
7195:
7196:            /*
7197:             * @see org.eclipse.ui.texteditor.ITextEditorExtension3#showChangeInformation(boolean)
7198:             * @since 3.0
7199:             */
7200:            public void showChangeInformation(boolean show) {
7201:                // do nothing
7202:            }
7203:
7204:            /*
7205:             * @see org.eclipse.ui.texteditor.ITextEditorExtension3#isChangeInformationShowing()
7206:             * @since 3.0
7207:             */
7208:            public boolean isChangeInformationShowing() {
7209:                return false;
7210:            }
7211:
7212:            /**
7213:             * Sets the given message as error message to this editor's status line.
7214:             *
7215:             * @param message message to be set
7216:             * @since 3.2
7217:             */
7218:            protected void setStatusLineErrorMessage(String message) {
7219:                IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
7220:                if (statusLine != null)
7221:                    statusLine.setMessage(true, message, null);
7222:            }
7223:
7224:            /**
7225:             * Sets the given message as message to this editor's status line.
7226:             *
7227:             * @param message message to be set
7228:             * @since 3.2
7229:             */
7230:            protected void setStatusLineMessage(String message) {
7231:                IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
7232:                if (statusLine != null)
7233:                    statusLine.setMessage(false, message, null);
7234:            }
7235:
7236:            /**
7237:             * Jumps to the next annotation according to the given direction.
7238:             *
7239:             * @param forward <code>true</code> if search direction is forward, <code>false</code> if backward
7240:             * @return the selected annotation or <code>null</code> if none
7241:             * @see #isNavigationTarget(Annotation)
7242:             * @see #findAnnotation(int, int, boolean, Position)
7243:             * @since 3.2
7244:             */
7245:            public Annotation gotoAnnotation(boolean forward) {
7246:                ITextSelection selection = (ITextSelection) getSelectionProvider()
7247:                        .getSelection();
7248:                Position position = new Position(0, 0);
7249:                Annotation annotation = findAnnotation(selection.getOffset(),
7250:                        selection.getLength(), forward, position);
7251:                setStatusLineErrorMessage(null);
7252:                setStatusLineMessage(null);
7253:
7254:                if (annotation != null) {
7255:                    selectAndReveal(position.getOffset(), position.getLength());
7256:                    setStatusLineMessage(annotation.getText());
7257:                }
7258:                return annotation;
7259:            }
7260:
7261:            /**
7262:             * Returns the annotation closest to the given range respecting the given
7263:             * direction. If an annotation is found, the annotations current position
7264:             * is copied into the provided annotation position.
7265:             *
7266:             * @param offset the region offset
7267:             * @param length the region length
7268:             * @param forward <code>true</code> for forwards, <code>false</code> for backward
7269:             * @param annotationPosition the position of the found annotation
7270:             * @return the found annotation
7271:             * @since 3.2
7272:             */
7273:            protected Annotation findAnnotation(final int offset,
7274:                    final int length, boolean forward,
7275:                    Position annotationPosition) {
7276:
7277:                Annotation nextAnnotation = null;
7278:                Position nextAnnotationPosition = null;
7279:                Annotation containingAnnotation = null;
7280:                Position containingAnnotationPosition = null;
7281:                boolean currentAnnotation = false;
7282:
7283:                IDocument document = getDocumentProvider().getDocument(
7284:                        getEditorInput());
7285:                int endOfDocument = document.getLength();
7286:                int distance = Integer.MAX_VALUE;
7287:
7288:                IAnnotationModel model = getDocumentProvider()
7289:                        .getAnnotationModel(getEditorInput());
7290:                Iterator e = model.getAnnotationIterator();
7291:                while (e.hasNext()) {
7292:                    Annotation a = (Annotation) e.next();
7293:                    if (!isNavigationTarget(a))
7294:                        continue;
7295:
7296:                    Position p = model.getPosition(a);
7297:                    if (p == null)
7298:                        continue;
7299:
7300:                    if (forward && p.offset == offset || !forward
7301:                            && p.offset + p.getLength() == offset + length) {// || p.includes(offset)) {
7302:                        if (containingAnnotation == null
7303:                                || (forward
7304:                                        && p.length >= containingAnnotationPosition.length || !forward
7305:                                        && p.length >= containingAnnotationPosition.length)) {
7306:                            containingAnnotation = a;
7307:                            containingAnnotationPosition = p;
7308:                            currentAnnotation = p.length == length;
7309:                        }
7310:                    } else {
7311:                        int currentDistance = 0;
7312:
7313:                        if (forward) {
7314:                            currentDistance = p.getOffset() - offset;
7315:                            if (currentDistance < 0)
7316:                                currentDistance = endOfDocument
7317:                                        + currentDistance;
7318:
7319:                            if (currentDistance < distance
7320:                                    || currentDistance == distance
7321:                                    && p.length < nextAnnotationPosition.length) {
7322:                                distance = currentDistance;
7323:                                nextAnnotation = a;
7324:                                nextAnnotationPosition = p;
7325:                            }
7326:                        } else {
7327:                            currentDistance = offset + length
7328:                                    - (p.getOffset() + p.length);
7329:                            if (currentDistance < 0)
7330:                                currentDistance = endOfDocument
7331:                                        + currentDistance;
7332:
7333:                            if (currentDistance < distance
7334:                                    || currentDistance == distance
7335:                                    && p.length < nextAnnotationPosition.length) {
7336:                                distance = currentDistance;
7337:                                nextAnnotation = a;
7338:                                nextAnnotationPosition = p;
7339:                            }
7340:                        }
7341:                    }
7342:                }
7343:                if (containingAnnotationPosition != null
7344:                        && (!currentAnnotation || nextAnnotation == null)) {
7345:                    annotationPosition.setOffset(containingAnnotationPosition
7346:                            .getOffset());
7347:                    annotationPosition.setLength(containingAnnotationPosition
7348:                            .getLength());
7349:                    return containingAnnotation;
7350:                }
7351:                if (nextAnnotationPosition != null) {
7352:                    annotationPosition.setOffset(nextAnnotationPosition
7353:                            .getOffset());
7354:                    annotationPosition.setLength(nextAnnotationPosition
7355:                            .getLength());
7356:                }
7357:
7358:                return nextAnnotation;
7359:            }
7360:
7361:            /**
7362:             * Returns whether the given annotation is configured as a target for the
7363:             * "Go to Next/Previous Annotation" actions.
7364:             * <p>
7365:             * Per default every annotation is a target.
7366:             * </p>
7367:             *
7368:             * @param annotation the annotation
7369:             * @return <code>true</code> if this is a target, <code>false</code> otherwise
7370:             * @since 3.2
7371:             */
7372:            protected boolean isNavigationTarget(Annotation annotation) {
7373:                return true;
7374:            }
7375:
7376:            /*
7377:             * @see org.eclipse.ui.texteditor.ITextEditorExtension4#showRevisionInformation(org.eclipse.jface.text.revisions.RevisionInformation, java.lang.String)
7378:             * @since 3.2
7379:             */
7380:            public void showRevisionInformation(RevisionInformation info,
7381:                    String quickDiffProviderId) {
7382:                // no implementation
7383:            }
7384:
7385:            /*
7386:             * @see org.eclipse.ui.IEditorPersistable#restoreState(org.eclipse.ui.IMemento)
7387:             * @since 3.3
7388:             */
7389:            public void restoreState(IMemento memento) {
7390:                fMementoToRestore = memento;
7391:            }
7392:
7393:            /*
7394:             * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento)
7395:             * @since 3.3
7396:             */
7397:            public void saveState(IMemento memento) {
7398:                ISelection selection = doGetSelection();
7399:                if (selection instanceof  ITextSelection) {
7400:                    memento.putInteger(TAG_SELECTION_OFFSET,
7401:                            ((ITextSelection) selection).getOffset());
7402:                    memento.putInteger(TAG_SELECTION_LENGTH,
7403:                            ((ITextSelection) selection).getLength());
7404:                    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=168524
7405:                    memento.putInteger(TAG_SELECTION_HPIXEL, getSourceViewer()
7406:                            .getTextWidget().getHorizontalPixel());
7407:                }
7408:            }
7409:
7410:            /**
7411:             * Returns whether the given memento contains saved state
7412:             * <p>
7413:             * Subclasses may extend or override this method.</p>
7414:             * 
7415:             * @param memento the saved state of this editor
7416:             * @return <code>true</code> if the given memento contains saved state
7417:             * @since 3.3
7418:             */
7419:            protected boolean containsSavedState(IMemento memento) {
7420:                return memento.getInteger(TAG_SELECTION_OFFSET) != null
7421:                        && memento.getInteger(TAG_SELECTION_LENGTH) != null;
7422:            }
7423:
7424:            /**
7425:             * Restores this editor's state using the given memento.
7426:             * <p>
7427:             * Subclasses may extend or override this method.</p>
7428:             * 
7429:             * @param memento the saved state of this editor
7430:             * @since 3.3
7431:             */
7432:            protected void doRestoreState(IMemento memento) {
7433:                Integer offset = memento.getInteger(TAG_SELECTION_OFFSET);
7434:                if (offset == null)
7435:                    return;
7436:
7437:                Integer length = memento.getInteger(TAG_SELECTION_LENGTH);
7438:                if (length == null)
7439:                    return;
7440:
7441:                doSetSelection(new TextSelection(offset.intValue(), length
7442:                        .intValue()));
7443:
7444:                // XXX: https://bugs.eclipse.org/bugs/show_bug.cgi?id=168524
7445:                Integer horizontalPixel = memento
7446:                        .getInteger(TAG_SELECTION_HPIXEL);
7447:                if (horizontalPixel == null)
7448:                    return;
7449:                StyledText textWidget = getSourceViewer().getTextWidget();
7450:                if (!textWidget.isVisible())
7451:                    textWidget.setHorizontalPixel(horizontalPixel.intValue());
7452:            }
7453:
7454:            /*
7455:             * @see org.eclipse.ui.ISaveablesSource#getSaveables()
7456:             * @since 3.3
7457:             */
7458:            public Saveable[] getSaveables() {
7459:                if (fSavable == null)
7460:                    fSavable = new TextEditorSavable(this );
7461:
7462:                return new Saveable[] { fSavable };
7463:            }
7464:
7465:            /*
7466:             * @see org.eclipse.ui.ISaveablesSource#getActiveSaveables()
7467:             * @since 3.3
7468:             */
7469:            public Saveable[] getActiveSaveables() {
7470:                return getSaveables();
7471:            }
7472:
7473:            /**
7474:             * This text editor's savable.
7475:             * 
7476:             * @since 3.3
7477:             */
7478:            protected static class TextEditorSavable extends Saveable {
7479:
7480:                /** The cached editor. */
7481:                private ITextEditor fTextEditor;
7482:                /** The cached editor input. */
7483:                private IEditorInput fEditorInput;
7484:                /** The cached document. */
7485:                private IDocument fDocument;
7486:
7487:                /**
7488:                 * Creates a new savable for this text editor.
7489:                 * 
7490:                 * @param textEditor the text editor 
7491:                 */
7492:                public TextEditorSavable(ITextEditor textEditor) {
7493:                    Assert.isLegal(textEditor != null);
7494:                    fTextEditor = textEditor;
7495:                    fEditorInput = fTextEditor.getEditorInput();
7496:                    Assert.isLegal(fEditorInput != null);
7497:                }
7498:
7499:                /**
7500:                 * Disconnects the editor from this savable.
7501:                 */
7502:                public void disconnectEditor() {
7503:                    getAdapter(IDocument.class); // make sure the document is cached
7504:                    fTextEditor = null;
7505:                }
7506:
7507:                /*
7508:                 * @see org.eclipse.ui.Saveable#getName()
7509:                 */
7510:                public String getName() {
7511:                    return fEditorInput.getName();
7512:                }
7513:
7514:                /*
7515:                 * @see org.eclipse.ui.Saveable#getToolTipText()
7516:                 */
7517:                public String getToolTipText() {
7518:                    return fEditorInput.getToolTipText();
7519:                }
7520:
7521:                /*
7522:                 * @see org.eclipse.ui.Saveable#getImageDescriptor()
7523:                 */
7524:                public ImageDescriptor getImageDescriptor() {
7525:                    return fEditorInput.getImageDescriptor();
7526:                }
7527:
7528:                /*
7529:                 * @see org.eclipse.ui.Saveable#doSave(org.eclipse.core.runtime.IProgressMonitor)
7530:                 * @since 3.3
7531:                 */
7532:                public void doSave(IProgressMonitor monitor)
7533:                        throws CoreException {
7534:                    fTextEditor.doSave(monitor);
7535:                }
7536:
7537:                public boolean isDirty() {
7538:                    return fTextEditor.isDirty();
7539:                }
7540:
7541:                /*
7542:                 * @see org.eclipse.ui.Saveable#supportsBackgroundSave()
7543:                 */
7544:                public boolean supportsBackgroundSave() {
7545:                    return false;
7546:                }
7547:
7548:                /*
7549:                 * @see org.eclipse.ui.Saveable#hashCode()
7550:                 */
7551:                public int hashCode() {
7552:                    Object document = getAdapter(IDocument.class);
7553:                    if (document == null)
7554:                        return 0;
7555:                    return document.hashCode();
7556:                }
7557:
7558:                /*
7559:                 * @see org.eclipse.ui.Saveable#equals(java.lang.Object)
7560:                 */
7561:                public boolean equals(Object obj) {
7562:                    if (this  == obj)
7563:                        return true;
7564:
7565:                    if (!(obj instanceof  Saveable))
7566:                        return false;
7567:
7568:                    Object this Document = getAdapter(IDocument.class);
7569:                    Object otherDocument = ((Saveable) obj)
7570:                            .getAdapter(IDocument.class);
7571:
7572:                    if (this Document == null && otherDocument == null)
7573:                        return true;
7574:
7575:                    return this Document != null
7576:                            && this Document.equals(otherDocument);
7577:                }
7578:
7579:                /**
7580:                 * Explicit comment needed to suppress wrong waning caused
7581:                 * by http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4848177
7582:                 * 
7583:                 * @see org.eclipse.ui.Saveable#getAdapter(java.lang.Class)
7584:                 */
7585:                public Object getAdapter(Class adapter) {
7586:                    if (adapter == IDocument.class) {
7587:                        if (fDocument == null) {
7588:                            IDocumentProvider documentProvider = fTextEditor
7589:                                    .getDocumentProvider();
7590:                            if (documentProvider != null)
7591:                                fDocument = documentProvider
7592:                                        .getDocument(fEditorInput);
7593:                        }
7594:                        return fDocument;
7595:                    }
7596:                    return super .getAdapter(adapter);
7597:                }
7598:            }
7599:
7600:            //---- Tabs to spaces conversion support ------------------
7601:
7602:            /**
7603:             * Installs a tabs to spaces converter.
7604:             * 
7605:             * <p>Subclasses may extend or override this method.</p>
7606:             * 
7607:             * @since 3.3
7608:             */
7609:            protected void installTabsToSpacesConverter() {
7610:                SourceViewerConfiguration config = getSourceViewerConfiguration();
7611:                if (config != null
7612:                        && fSourceViewer instanceof  ITextViewerExtension7) {
7613:                    int tabWidth = config.getTabWidth(fSourceViewer);
7614:                    TabsToSpacesConverter tabToSpacesConverter = new TabsToSpacesConverter();
7615:                    tabToSpacesConverter
7616:                            .setLineTracker(new DefaultLineTracker());
7617:                    tabToSpacesConverter.setNumberOfSpacesPerTab(tabWidth);
7618:                    ((ITextViewerExtension7) fSourceViewer)
7619:                            .setTabsToSpacesConverter(tabToSpacesConverter);
7620:                    updateIndentPrefixes();
7621:                }
7622:            }
7623:
7624:            /**
7625:             * Installs a tabs to spaces converter.
7626:             * 
7627:             * <p>Subclasses may extend or override this method.</p>
7628:             * 
7629:             * @since 3.3
7630:             */
7631:            protected void uninstallTabsToSpacesConverter() {
7632:                if (fSourceViewer instanceof  ITextViewerExtension7) {
7633:                    ((ITextViewerExtension7) fSourceViewer)
7634:                            .setTabsToSpacesConverter(null);
7635:                    if (fSourceViewer.getTextWidget() != null)
7636:                        updateIndentPrefixes();
7637:                }
7638:            }
7639:
7640:            /**
7641:             * Tells whether tabs should be converted to
7642:             * spaces while editing inside this editor.
7643:             * 
7644:             * <p>Subclasses may override this method.</p>
7645:             * 
7646:             * @return <code>true</code> if tabs should be converted to spaces
7647:             * @since 3.3
7648:             */
7649:            protected boolean isTabsToSpacesConversionEnabled() {
7650:                return false;
7651:            }
7652:
7653:            /**
7654:             * Updates the source viewer's indent prefixes with
7655:             * the values provided by the source viewer configuration.
7656:             * 
7657:             * @since 3.3
7658:             */
7659:            protected final void updateIndentPrefixes() {
7660:                SourceViewerConfiguration configuration = getSourceViewerConfiguration();
7661:                String[] types = configuration
7662:                        .getConfiguredContentTypes(fSourceViewer);
7663:                for (int i = 0; i < types.length; i++) {
7664:                    String[] prefixes = configuration.getIndentPrefixes(
7665:                            fSourceViewer, types[i]);
7666:                    if (prefixes != null && prefixes.length > 0)
7667:                        fSourceViewer.setIndentPrefixes(prefixes, types[i]);
7668:                }
7669:            }
7670:
7671:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.