### Eclipse Workspace Patch 1.0 #P org.eclipse.mylyn.tasks.ui Index: src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java,v retrieving revision 1.93 diff -u -r1.93 AbstractTaskEditorPage.java --- src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java 11 Jan 2009 08:19:48 -0000 1.93 +++ src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java 12 Jan 2009 08:42:51 -0000 @@ -50,6 +50,7 @@ import org.eclipse.jface.window.Window; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.context.core.ContextCore; +import org.eclipse.mylyn.internal.commons.ui.CommonTextSupport; import org.eclipse.mylyn.internal.context.core.ContextCorePlugin; import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages; import org.eclipse.mylyn.internal.tasks.core.AbstractTask; @@ -449,6 +450,8 @@ private TaskAttachmentDropListener defaultDropListener; + private CommonTextSupport textSupport; + // TODO 3.1 define constructor for setting id and label public AbstractTaskEditorPage(TaskEditor editor, String connectorKind) { super(editor, "id", "label"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -520,8 +523,7 @@ } AttributeEditorToolkit createAttributeEditorToolkit() { - IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class); - return new AttributeEditorToolkit(handlerService); + return new AttributeEditorToolkit(textSupport); } @Override @@ -620,7 +622,6 @@ attributeEditorToolkit = createAttributeEditorToolkit(); Assert.isNotNull(attributeEditorToolkit); attributeEditorToolkit.setMenu(editorComposite.getMenu()); - attributeEditorToolkit.setSelectionChangedListener(this); attributeEditorFactory.setEditorToolkit(attributeEditorToolkit); createParts(); @@ -1113,6 +1114,8 @@ this.task = taskEditorInput.getTask(); this.defaultSelection = new StructuredSelection(task); this.lastSelection = defaultSelection; + IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class); + this.textSupport = new CommonTextSupport(handlerService); initModel(taskEditorInput); @@ -1424,4 +1427,11 @@ } } + /** + * @since 3.1 + */ + public CommonTextSupport getTextSupport() { + return textSupport; + } + } Index: src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorToolkit.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorToolkit.java,v retrieving revision 1.16 diff -u -r1.16 AttributeEditorToolkit.java --- src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorToolkit.java 7 Dec 2008 03:26:58 -0000 1.16 +++ src/org/eclipse/mylyn/tasks/ui/editors/AttributeEditorToolkit.java 12 Jan 2009 08:42:51 -0000 @@ -11,9 +11,6 @@ package org.eclipse.mylyn.tasks.ui.editors; -import org.eclipse.core.commands.IHandler; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.commands.ActionHandler; import org.eclipse.jface.fieldassist.ComboContentAdapter; import org.eclipse.jface.fieldassist.ContentProposalAdapter; import org.eclipse.jface.fieldassist.ControlDecoration; @@ -22,15 +19,10 @@ import org.eclipse.jface.fieldassist.IContentProposalProvider; import org.eclipse.jface.fieldassist.IControlContentAdapter; import org.eclipse.jface.fieldassist.TextContentAdapter; -import org.eclipse.jface.text.ITextListener; -import org.eclipse.jface.text.TextEvent; import org.eclipse.jface.text.TextViewer; -import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.mylyn.internal.commons.ui.CommonTextSupport; import org.eclipse.mylyn.internal.provisional.commons.ui.CommonThemes; import org.eclipse.mylyn.internal.tasks.ui.PersonProposalLabelProvider; import org.eclipse.mylyn.internal.tasks.ui.PersonProposalProvider; @@ -42,21 +34,16 @@ import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; -import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.ActiveShellExpression; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; import org.eclipse.ui.handlers.IHandlerActivation; -import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.keys.IBindingService; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.eclipse.ui.themes.IThemeManager; @@ -68,74 +55,23 @@ // TODO EDITOR rename to AttributeUiToolkit? public class AttributeEditorToolkit { - private class StyledTextFocusListener implements FocusListener { - - private final boolean spellCheck; - - private final SourceViewer viewer; - - public StyledTextFocusListener(SourceViewer viewer, boolean spellCheck) { - this.viewer = viewer; - this.spellCheck = spellCheck; - } - - public void focusGained(FocusEvent e) { - if (selectionChangedListener != null) { - selectionChangedListener.selectionChanged(new SelectionChangedEvent(viewer, viewer.getSelection())); - } - activateHandlers(viewer, spellCheck); - } - - public void focusLost(FocusEvent e) { - deactivateHandlers(); - if (selectionChangedListener != null) { - // make sure selection no text is selected when control looses focus - StyledText st = (StyledText) e.widget; - st.setSelectionRange(st.getCaretOffset(), 0); - // update action enablement - selectionChangedListener.selectionChanged(new SelectionChangedEvent(viewer, StructuredSelection.EMPTY)); - } - } - - } - private final Color colorIncoming; - public IHandlerActivation contentAssistHandlerActivation; - - private final IHandlerService handlerService; - private Menu menu; - private IHandlerActivation quickAssistHandlerActivation; + private AbstractRenderingEngine renderingEngine; - private ISelectionChangedListener selectionChangedListener; + private final CommonTextSupport textSupport; - private AbstractRenderingEngine renderingEngine; + @Deprecated + public IHandlerActivation contentAssistHandlerActivation; - AttributeEditorToolkit(IHandlerService handlerService) { - this.handlerService = handlerService; + AttributeEditorToolkit(CommonTextSupport textSupport) { + this.textSupport = textSupport; IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager(); colorIncoming = themeManager.getCurrentTheme().getColorRegistry().get(CommonThemes.COLOR_INCOMING_BACKGROUND); } - private IHandlerActivation activateHandler(SourceViewer viewer, int operation, String actionDefinitionId) { - IHandler handler = createActionHandler(viewer, operation, actionDefinitionId); - return handlerService.activateHandler(actionDefinitionId, handler, // - new ActiveShellExpression(viewer.getTextWidget().getShell())); - } - - private void activateHandlers(SourceViewer viewer, boolean spellCheck) { - deactivateHandlers(); - if (spellCheck) { - quickAssistHandlerActivation = activateHandler(viewer, ISourceViewer.QUICK_ASSIST, - ITextEditorActionDefinitionIds.QUICK_ASSIST); - } - contentAssistHandlerActivation = activateHandler(viewer, ISourceViewer.CONTENTASSIST_PROPOSALS, - ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); - - } - public void adapt(AbstractAttributeEditor editor) { if (editor.getControl() instanceof Text || editor.getControl() instanceof CCombo) { Control control = editor.getControl(); @@ -154,37 +90,15 @@ RichTextAttributeEditor richTextEditor = (RichTextAttributeEditor) editor; boolean spellCheck = hasSpellChecking(editor.getTaskAttribute()); final SourceViewer viewer = richTextEditor.getViewer(); - viewer.getControl().addFocusListener(new StyledTextFocusListener(viewer, spellCheck)); - if (selectionChangedListener != null) { - viewer.addSelectionChangedListener(selectionChangedListener); - viewer.addTextListener(new ITextListener() { - public void textChanged(TextEvent event) { - if (selectionChangedListener != null) { - selectionChangedListener.selectionChanged(new SelectionChangedEvent(viewer, - viewer.getSelection())); - } - } - }); - } + textSupport.install(viewer, spellCheck); if (!editor.isReadOnly() && richTextEditor.getMode() == Mode.TASK_RELATION) { installContentAssistControlDecoration(viewer.getControl()); } installMenu(viewer.getControl()); - EditorUtil.setTextViewer(editor.getControl(), viewer); } else { final TextViewer viewer = EditorUtil.getTextViewer(editor.getControl()); if (viewer != null) { - if (selectionChangedListener != null) { - viewer.addSelectionChangedListener(selectionChangedListener); - viewer.addTextListener(new ITextListener() { - public void textChanged(TextEvent event) { - if (selectionChangedListener != null) { - selectionChangedListener.selectionChanged(new SelectionChangedEvent(viewer, - viewer.getSelection())); - } - } - }); - } + textSupport.install(viewer, false); installMenu(viewer.getControl()); } } @@ -236,19 +150,6 @@ return controlDecoration; } - private IHandler createActionHandler(final SourceViewer viewer, final int operation, String actionDefinitionId) { - Action quickFixAction = new Action() { - @Override - public void run() { - if (viewer.canDoOperation(operation)) { - viewer.doOperation(operation); - } - } - }; - quickFixAction.setActionDefinitionId(actionDefinitionId); - return new ActionHandler(quickFixAction); - } - /** * Creates an IContentProposalProvider to provide content assist proposals for the given attribute. * @@ -264,19 +165,8 @@ return new PersonProposalLabelProvider(); } - private void deactivateHandlers() { - if (quickAssistHandlerActivation != null) { - handlerService.deactivateHandler(quickAssistHandlerActivation); - quickAssistHandlerActivation = null; - } - if (contentAssistHandlerActivation != null) { - handlerService.deactivateHandler(contentAssistHandlerActivation); - contentAssistHandlerActivation = null; - } - } - void dispose() { - deactivateHandlers(); + // FIXME textSupport.deactivateHandlers(); } public Color getColorIncoming() { @@ -298,10 +188,6 @@ return renderingEngine; } - ISelectionChangedListener getSelectionChangedListener() { - return selectionChangedListener; - } - /** * Called to check if there's content assist available for the given attribute. * @@ -331,10 +217,6 @@ this.menu = menu; } - void setSelectionChangedListener(ISelectionChangedListener selectionListener) { - this.selectionChangedListener = selectionListener; - } - public void setRenderingEngine(AbstractRenderingEngine renderingEngine) { this.renderingEngine = renderingEngine; } Index: src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorActionContributor.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorActionContributor.java,v retrieving revision 1.72 diff -u -r1.72 TaskEditorActionContributor.java --- src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorActionContributor.java 5 Dec 2008 23:25:50 -0000 1.72 +++ src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorActionContributor.java 12 Jan 2009 08:42:51 -0000 @@ -29,7 +29,8 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages; +import org.eclipse.mylyn.internal.commons.ui.WorkbenchActionSupport; +import org.eclipse.mylyn.internal.commons.ui.WorkbenchActionSupport.WorkbenchActionCallback; import org.eclipse.mylyn.internal.tasks.core.AbstractTaskCategory; import org.eclipse.mylyn.internal.tasks.core.LocalTask; import org.eclipse.mylyn.internal.tasks.core.UnmatchedTaskContainer; @@ -51,20 +52,16 @@ import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage; import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; import org.eclipse.mylyn.tasks.ui.editors.TaskEditorInput; +import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.forms.editor.IFormPage; -import org.eclipse.ui.internal.WorkbenchImages; -import org.eclipse.ui.internal.WorkbenchMessages; import org.eclipse.ui.part.MultiPageEditorActionBarContributor; import org.eclipse.ui.progress.IProgressService; -import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; /** * @author Mik Kersten @@ -86,78 +83,22 @@ private final NewTaskFromSelectionAction newTaskFromSelectionAction = new NewTaskFromSelectionAction(); - private final GlobalAction cutAction; - - private final GlobalAction undoAction; - - private final GlobalAction redoAction; - - private final GlobalAction copyAction; - - private final GlobalAction pasteAction; - - private final GlobalAction selectAllAction; - - private final GlobalAction findAction; + private final WorkbenchActionSupport actionSupport; public TaskEditorActionContributor() { - cutAction = new GlobalAction(ActionFactory.CUT.getId()); - cutAction.setText(WorkbenchMessages.Workbench_cut); - cutAction.setToolTipText(WorkbenchMessages.Workbench_cutToolTip); - cutAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT)); - cutAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT)); - cutAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED)); - cutAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.CUT); - - pasteAction = new GlobalAction(ActionFactory.PASTE.getId()); - pasteAction.setText(WorkbenchMessages.Workbench_paste); - pasteAction.setToolTipText(WorkbenchMessages.Workbench_pasteToolTip); - pasteAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE)); - pasteAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE)); - pasteAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED)); - pasteAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE); - - copyAction = new GlobalAction(ActionFactory.COPY.getId()); - copyAction.setText(WorkbenchMessages.Workbench_copy); - copyAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); - copyAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); - copyAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED)); - copyAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY); - - undoAction = new GlobalAction(ActionFactory.UNDO.getId()); - undoAction.setText(WorkbenchMessages.Workbench_undo); - undoAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO)); - undoAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO)); - undoAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO_DISABLED)); - undoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO); - - redoAction = new GlobalAction(ActionFactory.REDO.getId()); - redoAction.setText(WorkbenchMessages.Workbench_redo); - redoAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO)); - redoAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO)); - redoAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO_DISABLED)); - redoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.REDO); - - selectAllAction = new GlobalAction(ActionFactory.SELECT_ALL.getId()); - selectAllAction.setText(WorkbenchMessages.Workbench_selectAll); - selectAllAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.SELECT_ALL); - selectAllAction.setEnabled(true); - - findAction = new GlobalAction(ActionFactory.FIND.getId()); - findAction.setText(Messages.TaskEditorActionContributor_Find); - findAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_REPLACE); - findAction.setImageDescriptor(CommonImages.FIND); + actionSupport = new WorkbenchActionSupport(); + actionSupport.setCallback(new EditorPageCallback()); } public void addClipboardActions(IMenuManager manager) { - manager.add(undoAction); - manager.add(redoAction); + manager.add(actionSupport.getUndoAction()); + manager.add(actionSupport.getRedoAction()); manager.add(new Separator()); - manager.add(cutAction); - manager.add(copyAction); + manager.add(actionSupport.getCutAction()); + manager.add(actionSupport.getCopyAction()); manager.add(copyTaskDetailsAction); - manager.add(pasteAction); - manager.add(selectAllAction); + manager.add(actionSupport.getPasteAction()); + manager.add(actionSupport.getSelectAllAction()); manager.add(newTaskFromSelectionAction); manager.add(new Separator()); } @@ -275,14 +216,8 @@ public void updateSelectableActions(ISelection selection) { if (editor != null) { - cutAction.selectionChanged(selection); - copyAction.selectionChanged(selection); - pasteAction.selectionChanged(selection); - undoAction.selectionChanged(selection); - redoAction.selectionChanged(selection); - selectAllAction.selectionChanged(selection); + actionSupport.updateActions(selection); newTaskFromSelectionAction.selectionChanged(selection); - findAction.selectionChanged(selection); } } @@ -305,8 +240,7 @@ @Override public void init(IActionBars bars, IWorkbenchPage page) { super.init(bars, page); - registerGlobalHandlers(bars); - findAction.selectionChanged(StructuredSelection.EMPTY); + actionSupport.install(bars); } public TaskEditor getEditor() { @@ -332,80 +266,54 @@ updateSelectableActions(event.getSelection()); } - private class GlobalAction extends Action { - - private final String actionId; - - public GlobalAction(String actionId) { - this.actionId = actionId; - } + private class EditorPageCallback extends WorkbenchActionCallback { @Override - public void run() { + public void doAction(String actionId, Control control) { IFormPage page = getActivePage(); - if (page instanceof TaskFormPage) { - TaskFormPage editor = (TaskFormPage) page; - editor.doAction(actionId); - } else if (page instanceof AbstractTaskEditorPage) { + if (page instanceof AbstractTaskEditorPage) { AbstractTaskEditorPage editor = (AbstractTaskEditorPage) page; editor.doAction(actionId); } else { - EditorUtil.doAction(actionId, EditorUtil.getFocusControl(getActivePage())); + WorkbenchActionCallback textSupport = (WorkbenchActionCallback) page.getAdapter(WorkbenchActionCallback.class); + if (textSupport != null) { + textSupport.doAction(actionId, control); + } else { + super.doAction(actionId, control); + } } - updateSelectableActions(getSelection()); } - public void selectionChanged(ISelection selection) { + @Override + public boolean canPerformAction(String actionId, Control control) { IFormPage page = getActivePage(); if (page instanceof TaskFormPage) { TaskFormPage editor = (TaskFormPage) page; - setEnabled(editor.canPerformAction(actionId)); - } else if (page instanceof AbstractTaskEditorPage) { - AbstractTaskEditorPage editor = (AbstractTaskEditorPage) page; - setEnabled(editor.canPerformAction(actionId)); + return editor.canPerformAction(actionId); } else { - setEnabled(EditorUtil.canPerformAction(actionId, EditorUtil.getFocusControl(getActivePage()))); + WorkbenchActionCallback textSupport = (WorkbenchActionCallback) page.getAdapter(WorkbenchActionCallback.class); + if (textSupport != null) { + return textSupport.canPerformAction(actionId, control); + } else { + return super.canPerformAction(actionId, control); + } } } - } - private void registerGlobalHandlers(IActionBars bars) { - bars.setGlobalActionHandler(ActionFactory.CUT.getId(), cutAction); - bars.setGlobalActionHandler(ActionFactory.PASTE.getId(), pasteAction); - bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction); - bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), undoAction); - bars.setGlobalActionHandler(ActionFactory.REDO.getId(), redoAction); - bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAllAction); - bars.setGlobalActionHandler(ActionFactory.FIND.getId(), findAction); - bars.updateActionBars(); - } - - @SuppressWarnings("unused") - private void unregisterGlobalHandlers(IActionBars bars) { - bars.setGlobalActionHandler(ActionFactory.CUT.getId(), null); - bars.setGlobalActionHandler(ActionFactory.PASTE.getId(), null); - bars.setGlobalActionHandler(ActionFactory.COPY.getId(), null); - bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), null); - bars.setGlobalActionHandler(ActionFactory.REDO.getId(), null); - bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), null); - bars.setGlobalActionHandler(ActionFactory.FIND.getId(), null); - bars.updateActionBars(); - } + @Override + public ISelection getSelection() { + return TaskEditorActionContributor.this.getSelection(); + } - public void forceActionsEnabled() { - cutAction.setEnabled(true); - copyAction.setEnabled(true); - pasteAction.setEnabled(true); - selectAllAction.setEnabled(true); - undoAction.setEnabled(false); - redoAction.setEnabled(false); - } + @Override + public Control getFocusControl() { + IFormPage page = getActivePage(); + return EditorUtil.getFocusControl(page); + } - private IFormPage getActivePage() { - return (editor != null) ? editor.getActivePageInstance() : null; } - private ISelection getSelection() { + public ISelection getSelection() { if (editor != null && editor.getSite().getSelectionProvider() != null) { return editor.getSite().getSelectionProvider().getSelection(); } else { @@ -413,4 +321,12 @@ } } + public void forceActionsEnabled() { + actionSupport.forceActionsEnabled(); + } + + private IFormPage getActivePage() { + return (editor != null) ? editor.getActivePageInstance() : null; + } + } Index: src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskPlanningEditor.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskPlanningEditor.java,v retrieving revision 1.157 diff -u -r1.157 TaskPlanningEditor.java --- src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskPlanningEditor.java 10 Jan 2009 21:57:44 -0000 1.157 +++ src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskPlanningEditor.java 12 Jan 2009 08:42:51 -0000 @@ -24,11 +24,14 @@ import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.text.Document; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.TextEvent; import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.mylyn.commons.core.StatusHandler; +import org.eclipse.mylyn.internal.commons.ui.CommonTextSupport; import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages; import org.eclipse.mylyn.internal.provisional.commons.ui.DatePicker; import org.eclipse.mylyn.internal.tasks.core.AbstractTask; @@ -77,9 +80,12 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormPage; import org.eclipse.ui.forms.events.ExpansionEvent; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; @@ -90,12 +96,13 @@ import org.eclipse.ui.forms.widgets.ImageHyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.handlers.IHandlerService; /** * @author Mik Kersten * @author Rob Elves */ -public class TaskPlanningEditor extends TaskFormPage { +public class TaskPlanningEditor extends FormPage { private static final String RESET = Messages.TaskPlanningEditor_Reset; @@ -182,12 +189,31 @@ private ITaskActivityListener timingListener; + private boolean isDirty; + + private CommonTextSupport textSupport; + public TaskPlanningEditor(TaskEditor editor) { super(editor, ITasksUiConstants.ID_PAGE_PLANNING, Messages.TaskPlanningEditor_Planning); this.parentEditor = editor; TasksUiInternal.getTaskList().addChangeListener(TASK_LIST_LISTENER); } + @Override + public void init(IEditorSite site, IEditorInput input) { + super.init(site, input); + this.textSupport = new CommonTextSupport((IHandlerService) getSite().getService(IHandlerService.class)); + this.textSupport.setSelectionChangedListener((TaskEditorActionContributor) getEditorSite().getActionBarContributor()); + } + + @Override + public Object getAdapter(Class adapter) { + if (adapter == CommonTextSupport.class) { + return textSupport; + } + return super.getAdapter(adapter); + } + /** * Override for customizing the tool bar. */ @@ -564,6 +590,19 @@ toolkit.paintBordersFor(statusComposite); } + private TextViewer addTextEditor(TaskRepository repository, Composite parent, String text, boolean spellCheck, + int style) { + SourceViewer viewer = new SourceViewer(parent, null, style); + viewer.configure(new RepositoryTextViewerConfiguration(repository, spellCheck)); + textSupport.configure(viewer, new Document(text), spellCheck); + return viewer; + } + + private void markDirty(boolean dirty) { + isDirty = dirty; + getManagedForm().dirtyStateChanged(); + } + /** * Attempts to set the task pageTitle to the title from the specified url */ Index: src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorNotesPart.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorNotesPart.java diff -N src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorNotesPart.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorNotesPart.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.editors; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.mylyn.internal.tasks.core.AbstractTask; +import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage; +import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPart; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.internal.EditorAreaHelper; +import org.eclipse.ui.internal.WorkbenchPage; + +/** + * @author Steffen Pingel + */ +public class TaskEditorNotesPart extends AbstractTaskEditorPart { + + private String value; + + private AbstractTask task; + + private SourceViewer noteEditor; + + public TaskEditorNotesPart() { + setPartName(Messages.TaskPlanningEditor_Notes); + } + + @Override + public void initialize(AbstractTaskEditorPage taskEditorPage) { + super.initialize(taskEditorPage); + task = (AbstractTask) taskEditorPage.getTask(); + } + + private boolean notesEqual() { + if (task.getNotes() == null && value == null) { + return true; + } + + if (task.getNotes() != null && value != null) { + return task.getNotes().equals(value); + } + return false; + } + + @Override + public void commit(boolean onSave) { + Assert.isNotNull(task); + + if (!notesEqual()) { + task.setNotes(value); + // XXX REFRESH THE TASLKIST + } + + super.commit(onSave); + } + + @Override + public void createControl(Composite parent, FormToolkit toolkit) { + this.value = task.getNotes(); + if (this.value == null) { + this.value = ""; + } + + Section section = createSection(parent, toolkit, this.value != null && this.value.length() > 0); + + Composite composite = toolkit.createComposite(section); + GridLayout layout = new GridLayout(); + layout.numColumns = 1; + composite.setLayout(layout); + + noteEditor = new SourceViewer(parent, null, SWT.FLAT | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL); + noteEditor.configure(new RepositoryTextViewerConfiguration(getModel().getTaskRepository(), true)); + getTaskEditorPage().getTextSupport().configure(noteEditor, new Document(this.value), true); + noteEditor.addTextListener(new ITextListener() { + public void textChanged(TextEvent event) { + TaskEditorNotesPart.this.value = noteEditor.getTextWidget().getText(); + markDirty(); + } + }); + + final GridData gd = new GridData(GridData.FILL_BOTH); + int widthHint = 0; + + if (getManagedForm() != null && getManagedForm().getForm() != null) { + widthHint = getManagedForm().getForm().getClientArea().width - 90; + } + if (widthHint <= 0 && getTaskEditorPage().getEditor().getEditorSite() != null + && getTaskEditorPage().getEditor().getEditorSite().getPage() != null) { + EditorAreaHelper editorManager = ((WorkbenchPage) getTaskEditorPage().getEditor().getEditorSite().getPage()).getEditorPresentation(); + if (editorManager != null && editorManager.getLayoutPart() != null) { + widthHint = editorManager.getLayoutPart().getControl().getBounds().width - 90; + } + } + + if (widthHint <= 0) { + widthHint = 100; + } + + gd.widthHint = widthHint; + gd.minimumHeight = 100; + gd.grabExcessHorizontalSpace = true; + + noteEditor.getControl().setLayoutData(gd); + noteEditor.getControl().setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER); + noteEditor.setEditable(true); + + toolkit.paintBordersFor(composite); + section.setClient(composite); + setSection(toolkit, section); + } + +} #P org.eclipse.mylyn.commons.ui Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.commons.ui/META-INF/MANIFEST.MF,v retrieving revision 1.12 diff -u -r1.12 MANIFEST.MF --- META-INF/MANIFEST.MF 10 Jan 2009 08:39:37 -0000 1.12 +++ META-INF/MANIFEST.MF 12 Jan 2009 08:42:52 -0000 @@ -4,7 +4,10 @@ Bundle-SymbolicName: org.eclipse.mylyn.commons.ui;singleton:=true Bundle-Version: 3.1.0.qualifier Require-Bundle: org.eclipse.core.runtime, + org.eclipse.core.expressions, + org.eclipse.jface.text, org.eclipse.ui, + org.eclipse.ui.editors;resolution:=optional, org.eclipse.ui.forms;resolution:=optional Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 Index: src/org/eclipse/mylyn/internal/commons/ui/WorkbenchActionSupport.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/commons/ui/WorkbenchActionSupport.java diff -N src/org/eclipse/mylyn/internal/commons/ui/WorkbenchActionSupport.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/commons/ui/WorkbenchActionSupport.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,267 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.commons.ui; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.internal.WorkbenchImages; +import org.eclipse.ui.internal.WorkbenchMessages; + +/** + * @author Mik Kersten + * @author Rob Elves + * @author Steffen Pingel + */ +@SuppressWarnings("restriction") +public class WorkbenchActionSupport implements ISelectionChangedListener { + + private class GlobalAction extends Action { + + private final String actionId; + + public GlobalAction(String actionId) { + this.actionId = actionId; + } + + @Override + public void run() { + if (callback != null) { + callback.doAction(actionId, callback.getFocusControl()); + updateActions(callback.getSelection()); + } + } + + public void selectionChanged(ISelection selection) { + if (callback != null) { + setEnabled(callback.canPerformAction(actionId, callback.getFocusControl())); + } else { + setEnabled(false); + } + } + } + + public static class WorkbenchActionCallback { + + public boolean canPerformAction(String actionId, Control control) { + return CommonTextSupport.canPerformAction(actionId, control); + } + + public void doAction(String actionId, Control control) { + CommonTextSupport.doAction(actionId, control); + } + + public Control getFocusControl() { + return Display.getDefault().getFocusControl(); + } + + public ISelection getSelection() { + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window != null && window.getSelectionService() != null) { + return window.getSelectionService().getSelection(); + } + return null; + } + + } + + public static final String COPY = "org.eclipse.ui.edit.copy"; //$NON-NLS-1$ + + public static final String CUT = "org.eclipse.ui.edit.cut"; //$NON-NLS-1$ + + public static final String FIND_REPLACE = "org.eclipse.ui.edit.findReplace"; //$NON-NLS-1$ + + public static final String PASTE = "org.eclipse.ui.edit.paste"; //$NON-NLS-1$ + + public static final String REDO = "org.eclipse.ui.edit.redo"; //$NON-NLS-1$ + + public static final String SELECT_ALL = "org.eclipse.ui.edit.selectAll"; //$NON-NLS-1$ + + public static final String UNDO = "org.eclipse.ui.edit.undo"; //$NON-NLS-1$ + + public WorkbenchActionCallback callback; + + private final GlobalAction copyAction; + + private final GlobalAction cutAction; + + private final GlobalAction findAction; + + private final GlobalAction pasteAction; + + private final GlobalAction redoAction; + + private final GlobalAction selectAllAction; + + private final GlobalAction undoAction; + + public WorkbenchActionSupport() { + cutAction = new GlobalAction(ActionFactory.CUT.getId()); + cutAction.setText(WorkbenchMessages.Workbench_cut); + cutAction.setToolTipText(WorkbenchMessages.Workbench_cutToolTip); + cutAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT)); + cutAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT)); + cutAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED)); + cutAction.setActionDefinitionId(CUT); + + pasteAction = new GlobalAction(ActionFactory.PASTE.getId()); + pasteAction.setText(WorkbenchMessages.Workbench_paste); + pasteAction.setToolTipText(WorkbenchMessages.Workbench_pasteToolTip); + pasteAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE)); + pasteAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE)); + pasteAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED)); + pasteAction.setActionDefinitionId(PASTE); + + copyAction = new GlobalAction(ActionFactory.COPY.getId()); + copyAction.setText(WorkbenchMessages.Workbench_copy); + copyAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); + copyAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); + copyAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED)); + copyAction.setActionDefinitionId(COPY); + + undoAction = new GlobalAction(ActionFactory.UNDO.getId()); + undoAction.setText(WorkbenchMessages.Workbench_undo); + undoAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO)); + undoAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO)); + undoAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO_DISABLED)); + undoAction.setActionDefinitionId(UNDO); + + redoAction = new GlobalAction(ActionFactory.REDO.getId()); + redoAction.setText(WorkbenchMessages.Workbench_redo); + redoAction.setImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO)); + redoAction.setHoverImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO)); + redoAction.setDisabledImageDescriptor(WorkbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO_DISABLED)); + redoAction.setActionDefinitionId(REDO); + + selectAllAction = new GlobalAction(ActionFactory.SELECT_ALL.getId()); + selectAllAction.setText(WorkbenchMessages.Workbench_selectAll); + selectAllAction.setActionDefinitionId(SELECT_ALL); + selectAllAction.setEnabled(true); + + findAction = new GlobalAction(ActionFactory.FIND.getId()); + findAction.setText(WorkbenchMessages.Workbench_findReplace); + findAction.setImageDescriptor(CommonImages.FIND); + findAction.setActionDefinitionId(FIND_REPLACE); + } + + public void contributeActions(IMenuManager manager) { + manager.add(undoAction); + manager.add(redoAction); + manager.add(new Separator()); + manager.add(cutAction); + manager.add(copyAction); + manager.add(pasteAction); + manager.add(selectAllAction); + manager.add(new Separator()); + } + + public void forceActionsEnabled() { + cutAction.setEnabled(true); + copyAction.setEnabled(true); + pasteAction.setEnabled(true); + selectAllAction.setEnabled(true); + undoAction.setEnabled(false); + redoAction.setEnabled(false); + } + + public Action getCopyAction() { + return copyAction; + } + + public Action getCutAction() { + return cutAction; + } + + public Action getFindAction() { + return findAction; + } + + public Action getPasteAction() { + return pasteAction; + } + + public Action getRedoAction() { + return redoAction; + } + + public Action getSelectAllAction() { + return selectAllAction; + } + + public Action getUndoAction() { + return undoAction; + } + + public void install(IActionBars bars) { + bars.setGlobalActionHandler(ActionFactory.CUT.getId(), cutAction); + bars.setGlobalActionHandler(ActionFactory.PASTE.getId(), pasteAction); + bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction); + bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), undoAction); + bars.setGlobalActionHandler(ActionFactory.REDO.getId(), redoAction); + bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAllAction); + bars.setGlobalActionHandler(ActionFactory.FIND.getId(), findAction); + bars.updateActionBars(); + } + + public void selectionChanged(SelectionChangedEvent event) { + ISelection selection = event.getSelection(); + if (selection instanceof TextSelection) { + // only update global actions + updateActions(event.getSelection()); + } else if (selection.isEmpty()) { + // XXX a styled text widget has lost focus, re-enable all edit actions + forceActionsEnabled(); + } + } + + public void uninstall(IActionBars bars) { + bars.setGlobalActionHandler(ActionFactory.CUT.getId(), null); + bars.setGlobalActionHandler(ActionFactory.PASTE.getId(), null); + bars.setGlobalActionHandler(ActionFactory.COPY.getId(), null); + bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), null); + bars.setGlobalActionHandler(ActionFactory.REDO.getId(), null); + bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), null); + bars.setGlobalActionHandler(ActionFactory.FIND.getId(), null); + bars.updateActionBars(); + } + + public void updateActions(ISelection selection) { + cutAction.selectionChanged(selection); + copyAction.selectionChanged(selection); + pasteAction.selectionChanged(selection); + undoAction.selectionChanged(selection); + redoAction.selectionChanged(selection); + selectAllAction.selectionChanged(selection); + findAction.selectionChanged(selection); + } + + public void setCallback(WorkbenchActionCallback callback) { + this.callback = callback; + } + + public WorkbenchActionCallback getCallback() { + return callback; + } + +} Index: src/org/eclipse/mylyn/internal/commons/ui/CommonTextSupport.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/commons/ui/CommonTextSupport.java diff -N src/org/eclipse/mylyn/internal/commons/ui/CommonTextSupport.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/commons/ui/CommonTextSupport.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.commons.ui; + +import java.util.Iterator; + +import org.eclipse.core.commands.IHandler; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.commands.ActionHandler; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.IAnnotationAccess; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; +import org.eclipse.ui.ActiveShellExpression; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.editors.text.EditorsUI; +import org.eclipse.ui.handlers.IHandlerActivation; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.texteditor.AnnotationPreference; +import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; +import org.eclipse.ui.texteditor.MarkerAnnotationPreferences; +import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; + +/** + * @author Steffen Pingel + */ +public class CommonTextSupport { + + private class TextViewerFocusListener implements FocusListener { + + private final boolean spellCheck; + + private final TextViewer viewer; + + public TextViewerFocusListener(TextViewer viewer, boolean spellCheck) { + this.viewer = viewer; + this.spellCheck = spellCheck; + } + + public void focusGained(FocusEvent e) { + if (selectionChangedListener != null) { + selectionChangedListener.selectionChanged(new SelectionChangedEvent(viewer, viewer.getSelection())); + } + activateHandlers(viewer, spellCheck); + } + + public void focusLost(FocusEvent e) { + deactivateHandlers(); + if (selectionChangedListener != null) { + // make sure selection no text is selected when control looses focus + StyledText st = (StyledText) e.widget; + st.setSelectionRange(st.getCaretOffset(), 0); + // update action enablement + selectionChangedListener.selectionChanged(new SelectionChangedEvent(viewer, StructuredSelection.EMPTY)); + } + } + + } + + private static String CONTENT_ASSIST_PROPOSALS = "org.eclipse.ui.edit.text.contentAssist.proposals"; //$NON-NLS-1$ + + private static final String KEY_TEXT_VIEWER = "textViewer"; //$NON-NLS-1$ + + private static final String QUICK_ASSIST = "org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals"; //$NON-NLS-1$ + + static boolean canDoGlobalAction(String actionId, TextViewer textViewer) { + if (actionId.equals(ActionFactory.CUT.getId())) { + return textViewer.canDoOperation(ITextOperationTarget.CUT); + } else if (actionId.equals(ActionFactory.COPY.getId())) { + return textViewer.canDoOperation(ITextOperationTarget.COPY); + } else if (actionId.equals(ActionFactory.PASTE.getId())) { + return textViewer.canDoOperation(ITextOperationTarget.PASTE); + } else if (actionId.equals(ActionFactory.DELETE.getId())) { + return textViewer.canDoOperation(ITextOperationTarget.DELETE); + } else if (actionId.equals(ActionFactory.UNDO.getId())) { + return textViewer.canDoOperation(ITextOperationTarget.UNDO); + } else if (actionId.equals(ActionFactory.REDO.getId())) { + return textViewer.canDoOperation(ITextOperationTarget.REDO); + } else if (actionId.equals(ActionFactory.SELECT_ALL.getId())) { + return textViewer.canDoOperation(ITextOperationTarget.SELECT_ALL); + } + return false; + } + + public static boolean canPerformAction(String actionId, Control focusControl) { + TextViewer viewer = getTextViewer(focusControl); + if (viewer != null) { + return canDoGlobalAction(actionId, viewer); + } + if (actionId.equals(ActionFactory.UNDO.getId()) || actionId.equals(ActionFactory.REDO.getId())) { + return false; + } + return true; + } + + private static boolean canPerformDirectly(String id, Control control) { + if (control instanceof Text) { + Text text = (Text) control; + if (id.equals(ActionFactory.CUT.getId())) { + text.cut(); + return true; + } + if (id.equals(ActionFactory.COPY.getId())) { + text.copy(); + return true; + } + if (id.equals(ActionFactory.PASTE.getId())) { + text.paste(); + return true; + } + if (id.equals(ActionFactory.SELECT_ALL.getId())) { + text.selectAll(); + return true; + } + if (id.equals(ActionFactory.DELETE.getId())) { + int count = text.getSelectionCount(); + if (count == 0) { + int caretPos = text.getCaretPosition(); + text.setSelection(caretPos, caretPos + 1); + } + text.insert(""); //$NON-NLS-1$ + return true; + } + } + return false; + } + + public static void doAction(String actionId, Control focusControl) { + if (canPerformDirectly(actionId, focusControl)) { + return; + } + TextViewer viewer = getTextViewer(focusControl); + if (viewer != null) { + doGlobalAction(actionId, viewer); + } + } + + private static boolean doGlobalAction(String actionId, TextViewer textViewer) { + if (actionId.equals(ActionFactory.CUT.getId())) { + textViewer.doOperation(ITextOperationTarget.CUT); + return true; + } else if (actionId.equals(ActionFactory.COPY.getId())) { + textViewer.doOperation(ITextOperationTarget.COPY); + return true; + } else if (actionId.equals(ActionFactory.PASTE.getId())) { + textViewer.doOperation(ITextOperationTarget.PASTE); + return true; + } else if (actionId.equals(ActionFactory.DELETE.getId())) { + textViewer.doOperation(ITextOperationTarget.DELETE); + return true; + } else if (actionId.equals(ActionFactory.UNDO.getId())) { + textViewer.doOperation(ITextOperationTarget.UNDO); + return true; + } else if (actionId.equals(ActionFactory.REDO.getId())) { + textViewer.doOperation(ITextOperationTarget.REDO); + return true; + } else if (actionId.equals(ActionFactory.SELECT_ALL.getId())) { + textViewer.doOperation(ITextOperationTarget.SELECT_ALL); + return true; + } + return false; + } + + public static TextViewer getTextViewer(Widget widget) { + if (widget instanceof StyledText) { + Object data = widget.getData(KEY_TEXT_VIEWER); + if (data instanceof TextViewer) { + return (TextViewer) data; + } + } + return null; + } + + public static void setTextViewer(Widget widget, TextViewer textViewer) { + widget.setData(KEY_TEXT_VIEWER, textViewer); + } + + public IHandlerActivation contentAssistHandlerActivation; + + private final IHandlerService handlerService; + + private IHandlerActivation quickAssistHandlerActivation; + + private ISelectionChangedListener selectionChangedListener; + + public CommonTextSupport(IHandlerService handlerService) { + this.handlerService = handlerService; + } + + private IHandlerActivation activateHandler(TextViewer viewer, int operation, String actionDefinitionId) { + IHandler handler = createActionHandler(viewer, operation, actionDefinitionId); + return handlerService.activateHandler(actionDefinitionId, handler, // + new ActiveShellExpression(viewer.getTextWidget().getShell())); + } + + private void activateHandlers(TextViewer viewer, boolean spellCheck) { + deactivateHandlers(); + if (spellCheck) { + quickAssistHandlerActivation = activateHandler(viewer, ISourceViewer.QUICK_ASSIST, QUICK_ASSIST); + } + contentAssistHandlerActivation = activateHandler(viewer, ISourceViewer.CONTENTASSIST_PROPOSALS, + CONTENT_ASSIST_PROPOSALS); + + } + + private IHandler createActionHandler(final ITextOperationTarget viewer, final int operation, + String actionDefinitionId) { + Action action = new Action() { + @Override + public void run() { + if (viewer.canDoOperation(operation)) { + viewer.doOperation(operation); + } + } + }; + action.setActionDefinitionId(actionDefinitionId); + return new ActionHandler(action); + } + + private void deactivateHandlers() { + if (quickAssistHandlerActivation != null) { + handlerService.deactivateHandler(quickAssistHandlerActivation); + quickAssistHandlerActivation = null; + } + if (contentAssistHandlerActivation != null) { + handlerService.deactivateHandler(contentAssistHandlerActivation); + contentAssistHandlerActivation = null; + } + } + + /** Configures annotation model for spell checking. */ + private void configureAsEditor(ISourceViewer viewer, Document document) { + IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess(); + final SourceViewerDecorationSupport support = new SourceViewerDecorationSupport(viewer, null, annotationAccess, + EditorsUI.getSharedTextColors()); + Iterator e = new MarkerAnnotationPreferences().getAnnotationPreferences().iterator(); + while (e.hasNext()) { + support.setAnnotationPreference((AnnotationPreference) e.next()); + } + support.install(EditorsUI.getPreferenceStore()); + viewer.getTextWidget().addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + support.uninstall(); + } + }); + AnnotationModel annotationModel = new AnnotationModel(); + viewer.setDocument(document, annotationModel); + } + + public void configure(final TextViewer viewer, Document document, boolean spellCheck) { + if (spellCheck && viewer instanceof ISourceViewer) { + configureAsEditor((ISourceViewer) viewer, document); + } else { + viewer.setDocument(document); + } + install(viewer, spellCheck); + } + + public void install(final TextViewer viewer, boolean spellCheck) { + viewer.getControl().addFocusListener(new TextViewerFocusListener(viewer, spellCheck)); + if (selectionChangedListener != null) { + viewer.addSelectionChangedListener(selectionChangedListener); + viewer.addTextListener(new ITextListener() { + public void textChanged(TextEvent event) { + if (selectionChangedListener != null) { + selectionChangedListener.selectionChanged(new SelectionChangedEvent(viewer, + viewer.getSelection())); + } + } + }); + } + setTextViewer(viewer.getControl(), viewer); + } + + public void setSelectionChangedListener(ISelectionChangedListener selectionChangedListener) { + this.selectionChangedListener = selectionChangedListener; + } + + public ISelectionChangedListener getSelectionChangedListener() { + return selectionChangedListener; + } + +}