| /******************************************************************************* |
| * Copyright (c) 2004, 2015 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 |
| * Eric Booth - initial prototype |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.tasks.ui.editors; |
| |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.action.ContributionManager; |
| import org.eclipse.jface.action.ControlContribution; |
| import org.eclipse.jface.action.GroupMarker; |
| import org.eclipse.jface.action.IMenuListener; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.IToolBarManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.action.ToolBarManager; |
| import org.eclipse.jface.dialogs.IMessageProvider; |
| import org.eclipse.jface.resource.CompositeImageDescriptor; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.TextViewer; |
| import org.eclipse.jface.util.LocalSelectionTransfer; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionProvider; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.mylyn.commons.core.StatusHandler; |
| import org.eclipse.mylyn.commons.ui.CommonImages; |
| import org.eclipse.mylyn.commons.ui.CommonUiUtil; |
| import org.eclipse.mylyn.commons.ui.PlatformUiUtil; |
| import org.eclipse.mylyn.commons.ui.SelectionProviderAdapter; |
| import org.eclipse.mylyn.commons.workbench.BusyAnimator; |
| import org.eclipse.mylyn.commons.workbench.BusyAnimator.IBusyClient; |
| import org.eclipse.mylyn.commons.workbench.WorkbenchUtil; |
| import org.eclipse.mylyn.commons.workbench.editors.CommonTextSupport; |
| import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector; |
| import org.eclipse.mylyn.internal.tasks.core.TaskList; |
| import org.eclipse.mylyn.internal.tasks.ui.TaskEditorBloatMonitor; |
| import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; |
| import org.eclipse.mylyn.internal.tasks.ui.actions.OpenWithBrowserAction; |
| import org.eclipse.mylyn.internal.tasks.ui.actions.TaskEditorScheduleAction; |
| import org.eclipse.mylyn.internal.tasks.ui.actions.ToggleTaskActivationAction; |
| import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil; |
| import org.eclipse.mylyn.internal.tasks.ui.editors.Messages; |
| import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorActionContributor; |
| import org.eclipse.mylyn.internal.tasks.ui.util.TaskDragSourceListener; |
| import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal; |
| import org.eclipse.mylyn.tasks.core.ITask; |
| import org.eclipse.mylyn.tasks.core.TaskRepository; |
| import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; |
| import org.eclipse.mylyn.tasks.ui.TasksUiImages; |
| import org.eclipse.mylyn.tasks.ui.TasksUiUtil; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DragSource; |
| import org.eclipse.swt.dnd.FileTransfer; |
| import org.eclipse.swt.dnd.TextTransfer; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.events.ControlAdapter; |
| import org.eclipse.swt.events.ControlEvent; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.events.FocusAdapter; |
| import org.eclipse.swt.events.FocusEvent; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.RowLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.ToolBar; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IEditorSite; |
| import org.eclipse.ui.IWorkbenchActionConstants; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.contexts.IContextService; |
| import org.eclipse.ui.forms.IFormColors; |
| import org.eclipse.ui.forms.IManagedForm; |
| import org.eclipse.ui.forms.editor.IFormPage; |
| import org.eclipse.ui.forms.editor.SharedHeaderFormEditor; |
| import org.eclipse.ui.forms.events.HyperlinkAdapter; |
| import org.eclipse.ui.forms.events.HyperlinkEvent; |
| import org.eclipse.ui.forms.events.IHyperlinkListener; |
| import org.eclipse.ui.forms.widgets.Form; |
| import org.eclipse.ui.forms.widgets.FormToolkit; |
| import org.eclipse.ui.forms.widgets.ImageHyperlink; |
| import org.eclipse.ui.handlers.IHandlerService; |
| import org.eclipse.ui.internal.forms.widgets.BusyIndicator; |
| import org.eclipse.ui.internal.forms.widgets.FormHeading; |
| import org.eclipse.ui.internal.forms.widgets.TitleRegion; |
| import org.eclipse.ui.menus.IMenuService; |
| import org.eclipse.ui.part.WorkbenchPart; |
| import org.eclipse.ui.progress.IWorkbenchSiteProgressService; |
| import org.eclipse.ui.services.IDisposable; |
| import org.eclipse.ui.views.contentoutline.IContentOutlinePage; |
| |
| /** |
| * @author Mik Kersten |
| * @author Rob Elves |
| * @author Steffen Pingel |
| * @author Thomas Ehrnhoefer |
| * @since 2.0 |
| */ |
| public class TaskEditor extends SharedHeaderFormEditor { |
| |
| /** |
| * @since 2.0 |
| */ |
| public static final String ID_EDITOR = "org.eclipse.mylyn.tasks.ui.editors.task"; //$NON-NLS-1$ |
| |
| /** |
| * @since 3.2 |
| */ |
| public static final String ID_TOOLBAR_HEADER = "org.eclipse.mylyn.tasks.ui.editors.task.toolbar.header"; //$NON-NLS-1$ |
| |
| private static final String ID_LEFT_TOOLBAR_HEADER = "org.eclipse.mylyn.tasks.ui.editors.task.toolbar.header.left"; //$NON-NLS-1$ |
| |
| private static final int LEFT_TOOLBAR_HEADER_TOOLBAR_PADDING = 3; |
| |
| private ToggleTaskActivationAction activateAction; |
| |
| @Deprecated |
| private final IEditorPart contentOutlineProvider = null; |
| |
| private BusyAnimator editorBusyIndicator; |
| |
| private MenuManager menuManager; |
| |
| private IHyperlinkListener messageHyperLinkListener; |
| |
| private ITask task; |
| |
| private TaskEditorInput taskEditorInput; |
| |
| private TaskDragSourceListener titleDragSourceListener; |
| |
| private Composite editorParent; |
| |
| private IMenuService menuService; |
| |
| private IToolBarManager toolBarManager; |
| |
| private ToolBarManager leftToolBarManager; |
| |
| private ToolBar leftToolBar; |
| |
| private Image headerImage; |
| |
| // private int initialLeftToolbarSize; |
| |
| private boolean noExtraPadding; |
| |
| // private boolean headerLabelInitialized; |
| |
| private BusyIndicator busyLabel; |
| |
| private StyledText titleLabel; |
| |
| private CommonTextSupport textSupport; |
| |
| private TaskEditorScheduleAction scheduleAction; |
| |
| OpenWithBrowserAction openWithBrowserAction; |
| |
| private static boolean toolBarFailureLogged; |
| |
| public TaskEditor() { |
| } |
| |
| @Override |
| protected void createPages() { |
| super.createPages(); |
| TaskEditorBloatMonitor.editorOpened(this); |
| } |
| |
| @Override |
| protected Composite createPageContainer(Composite parent) { |
| this.editorParent = parent; |
| Composite composite = super.createPageContainer(parent); |
| |
| EditorUtil.initializeScrollbars(getHeaderForm().getForm()); |
| |
| // create left tool bar that replaces form heading label |
| try { |
| FormHeading heading = (FormHeading) getHeaderForm().getForm().getForm().getHead(); |
| |
| Field field = FormHeading.class.getDeclaredField("titleRegion"); //$NON-NLS-1$ |
| field.setAccessible(true); |
| |
| TitleRegion titleRegion = (TitleRegion) field.get(heading); |
| |
| leftToolBarManager = new ToolBarManager(SWT.FLAT); |
| leftToolBar = leftToolBarManager.createControl(titleRegion); |
| leftToolBar.addControlListener(new ControlAdapter() { |
| private boolean ignoreResizeEvents; |
| |
| @Override |
| public void controlResized(ControlEvent e) { |
| if (ignoreResizeEvents) { |
| return; |
| } |
| ignoreResizeEvents = true; |
| try { |
| // the tool bar contents has changed, update state |
| updateHeaderImage(); |
| updateHeaderLabel(); |
| } finally { |
| ignoreResizeEvents = false; |
| } |
| } |
| }); |
| |
| //titleLabel = new Label(titleRegion, SWT.NONE); |
| // need a viewer for copy support |
| TextViewer titleViewer = new TextViewer(titleRegion, SWT.READ_ONLY); |
| // Eclipse 3.3 needs a document, otherwise an NPE is thrown |
| titleViewer.setDocument(new Document()); |
| |
| titleLabel = titleViewer.getTextWidget(); |
| titleLabel.setForeground(heading.getForeground()); |
| titleLabel.setFont(heading.getFont()); |
| // XXX work-around problem that causes field to maintain selection when unfocused |
| titleLabel.addFocusListener(new FocusAdapter() { |
| @Override |
| public void focusLost(FocusEvent e) { |
| titleLabel.setSelection(0); |
| } |
| }); |
| |
| titleRegion.addControlListener(new ControlAdapter() { |
| @Override |
| public void controlResized(ControlEvent e) { |
| // do not create busyLabel to avoid recursion |
| updateSizeAndLocations(); |
| } |
| }); |
| |
| IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class); |
| if (handlerService != null) { |
| textSupport = new CommonTextSupport(handlerService); |
| textSupport.install(titleViewer, false); |
| } |
| } catch (Exception e) { |
| if (!toolBarFailureLogged) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Failed to obtain busy label toolbar", e)); //$NON-NLS-1$ |
| } |
| if (titleLabel != null) { |
| titleLabel.dispose(); |
| titleLabel = null; |
| } |
| if (leftToolBar != null) { |
| leftToolBar.dispose(); |
| leftToolBar = null; |
| } |
| if (leftToolBarManager != null) { |
| leftToolBarManager.dispose(); |
| leftToolBarManager = null; |
| } |
| } |
| |
| updateHeader(); |
| |
| return composite; |
| } |
| |
| private BusyIndicator getBusyLabel() { |
| if (busyLabel != null) { |
| return busyLabel; |
| } |
| try { |
| FormHeading heading = (FormHeading) getHeaderForm().getForm().getForm().getHead(); |
| // ensure that busy label exists |
| heading.setBusy(true); |
| heading.setBusy(false); |
| |
| Field field = FormHeading.class.getDeclaredField("titleRegion"); //$NON-NLS-1$ |
| field.setAccessible(true); |
| |
| TitleRegion titleRegion = (TitleRegion) field.get(heading); |
| |
| for (Control child : titleRegion.getChildren()) { |
| if (child instanceof BusyIndicator) { |
| busyLabel = (BusyIndicator) child; |
| } |
| } |
| if (busyLabel == null) { |
| return null; |
| } |
| busyLabel.addControlListener(new ControlAdapter() { |
| @Override |
| public void controlMoved(ControlEvent e) { |
| updateSizeAndLocations(); |
| } |
| }); |
| // the busy label may get disposed if it has no image |
| busyLabel.addDisposeListener(new DisposeListener() { |
| public void widgetDisposed(DisposeEvent e) { |
| busyLabel.setMenu(null); |
| busyLabel = null; |
| } |
| }); |
| |
| if (leftToolBar != null) { |
| leftToolBar.moveAbove(busyLabel); |
| } |
| if (titleLabel != null) { |
| titleLabel.moveAbove(busyLabel); |
| } |
| |
| updateSizeAndLocations(); |
| |
| return busyLabel; |
| } catch (Exception e) { |
| if (!toolBarFailureLogged) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Failed to obtain busy label toolbar", e)); //$NON-NLS-1$ |
| } |
| busyLabel = null; |
| } |
| return busyLabel; |
| } |
| |
| private void updateSizeAndLocations() { |
| if (busyLabel == null || busyLabel.isDisposed()) { |
| return; |
| } |
| |
| Point leftToolBarSize = new Point(0, 0); |
| if (leftToolBar != null && !leftToolBar.isDisposed()) { |
| // bottom align tool bar in title region |
| leftToolBarSize = leftToolBar.getSize(); |
| int y = leftToolBar.getParent().getSize().y - leftToolBarSize.y - 2; |
| if (!hasLeftToolBar()) { |
| // hide tool bar to avoid overlaying busyLabel on windows |
| leftToolBarSize.x = 0; |
| } |
| leftToolBar.setBounds(busyLabel.getLocation().x, y, leftToolBarSize.x, leftToolBarSize.y); |
| } |
| if (titleLabel != null && !titleLabel.isDisposed()) { |
| // center align title text in title region |
| Point size = titleLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| int y = (titleLabel.getParent().getSize().y - size.y) / 2; |
| titleLabel.setBounds(busyLabel.getLocation().x + LEFT_TOOLBAR_HEADER_TOOLBAR_PADDING + leftToolBarSize.x, |
| y, size.x, size.y); |
| } |
| } |
| |
| Composite getEditorParent() { |
| return editorParent; |
| } |
| |
| @Override |
| protected void addPages() { |
| initialize(); |
| |
| // determine factories |
| Set<String> conflictingIds = new HashSet<String>(); |
| ArrayList<AbstractTaskEditorPageFactory> pageFactories = new ArrayList<AbstractTaskEditorPageFactory>(); |
| for (AbstractTaskEditorPageFactory pageFactory : TasksUiPlugin.getDefault().getTaskEditorPageFactories()) { |
| if (pageFactory.canCreatePageFor(getTaskEditorInput()) && WorkbenchUtil.allowUseOf(pageFactory)) { |
| pageFactories.add(pageFactory); |
| String[] ids = pageFactory.getConflictingIds(getTaskEditorInput()); |
| if (ids != null) { |
| conflictingIds.addAll(Arrays.asList(ids)); |
| } |
| } |
| } |
| for (Iterator<AbstractTaskEditorPageFactory> it = pageFactories.iterator(); it.hasNext();) { |
| if (conflictingIds.contains(it.next().getId())) { |
| it.remove(); |
| } |
| } |
| |
| // sort by priority |
| Collections.sort(pageFactories, new Comparator<AbstractTaskEditorPageFactory>() { |
| public int compare(AbstractTaskEditorPageFactory o1, AbstractTaskEditorPageFactory o2) { |
| return o1.getPriority() - o2.getPriority(); |
| } |
| }); |
| |
| // create pages |
| for (AbstractTaskEditorPageFactory factory : pageFactories) { |
| try { |
| IFormPage page = factory.createPage(this); |
| int index = addPage(page); |
| setPageImage(index, factory.getPageImage(this, page)); |
| setPageText(index, factory.getPageText(this, page)); |
| if (factory.getPriority() == AbstractTaskEditorPageFactory.PRIORITY_TASK) { |
| setActivePage(index); |
| } |
| if (page instanceof ISelectionProvider) { |
| ((ISelectionProvider) page).addSelectionChangedListener(getActionBarContributor()); |
| } |
| } catch (Exception e) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Could not create editor via factory: " + factory, e)); //$NON-NLS-1$ |
| } |
| } |
| |
| updateTitleImage(); |
| updateHeaderToolBar(); |
| installTitleDrag(getHeaderForm().getForm().getForm()); |
| |
| // do this late to allow pages to replace the selection provider |
| getEditorSite().registerContextMenu(menuManager, getEditorSite().getSelectionProvider(), true); |
| } |
| |
| private void initialize() { |
| editorBusyIndicator = new BusyAnimator(new IBusyClient() { |
| public Image getImage() { |
| return TaskEditor.this.getTitleImage(); |
| } |
| |
| public void setImage(Image image) { |
| TaskEditor.this.setTitleImage(image); |
| } |
| }); |
| |
| menuManager = new MenuManager(); |
| configureContextMenuManager(menuManager); |
| Menu menu = menuManager.createContextMenu(getContainer()); |
| getContainer().setMenu(menu); |
| |
| // install context menu on form heading and title |
| getHeaderForm().getForm().setMenu(menu); |
| Composite head = getHeaderForm().getForm().getForm().getHead(); |
| if (head != null) { |
| CommonUiUtil.setMenu(head, menu); |
| } |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| @Deprecated |
| public void configureContextMenuManager(MenuManager manager) { |
| if (manager == null) { |
| return; |
| } |
| IMenuListener listener = new IMenuListener() { |
| public void menuAboutToShow(IMenuManager manager) { |
| contextMenuAboutToShow(manager); |
| } |
| }; |
| manager.setRemoveAllWhenShown(true); |
| manager.addMenuListener(listener); |
| } |
| |
| @Deprecated |
| protected void contextMenuAboutToShow(IMenuManager manager) { |
| TaskEditorActionContributor contributor = getActionBarContributor(); |
| if (contributor != null) { |
| contributor.contextMenuAboutToShow(manager); |
| } |
| } |
| |
| @Override |
| protected FormToolkit createToolkit(Display display) { |
| // create a toolkit that shares colors between editors. |
| return new FormToolkit(TasksUiPlugin.getDefault().getFormColors(display)); |
| } |
| |
| @Override |
| protected void createHeaderContents(IManagedForm headerForm) { |
| getToolkit().decorateFormHeading(headerForm.getForm().getForm()); |
| } |
| |
| @Override |
| public void dispose() { |
| disposeScheduleAction(); |
| if (headerImage != null) { |
| headerImage.dispose(); |
| } |
| if (editorBusyIndicator != null) { |
| editorBusyIndicator.stop(); |
| } |
| if (activateAction != null) { |
| activateAction.dispose(); |
| } |
| if (menuService != null) { |
| if (leftToolBarManager != null) { |
| menuService.releaseContributions(leftToolBarManager); |
| } |
| if (toolBarManager instanceof ContributionManager) { |
| menuService.releaseContributions((ContributionManager) toolBarManager); |
| } |
| } |
| if (textSupport != null) { |
| textSupport.dispose(); |
| } |
| if (messageHyperLinkListener instanceof IDisposable) { |
| ((IDisposable) messageHyperLinkListener).dispose(); |
| } |
| super.dispose(); |
| } |
| |
| @Override |
| public void doSave(IProgressMonitor monitor) { |
| for (IFormPage page : getPages()) { |
| if (page.isDirty()) { |
| page.doSave(monitor); |
| } |
| } |
| |
| editorDirtyStateChanged(); |
| } |
| |
| @Override |
| public void doSaveAs() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| private TaskEditorActionContributor getActionBarContributor() { |
| return (TaskEditorActionContributor) getEditorSite().getActionBarContributor(); |
| } |
| |
| @SuppressWarnings("rawtypes") |
| @Override |
| public Object getAdapter(Class adapter) { |
| if (contentOutlineProvider != null) { |
| return contentOutlineProvider.getAdapter(adapter); |
| } else if (IContentOutlinePage.class.equals(adapter)) { |
| IFormPage[] pages = getPages(); |
| for (IFormPage page : pages) { |
| Object outlinePage = page.getAdapter(adapter); |
| if (outlinePage != null) { |
| return outlinePage; |
| } |
| } |
| } |
| return super.getAdapter(adapter); |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public Menu getMenu() { |
| return getContainer().getMenu(); |
| } |
| |
| IFormPage[] getPages() { |
| List<IFormPage> formPages = new ArrayList<IFormPage>(); |
| if (pages != null) { |
| for (int i = 0; i < pages.size(); i++) { |
| Object page = pages.get(i); |
| if (page instanceof IFormPage) { |
| formPages.add((IFormPage) page); |
| } |
| } |
| } |
| return formPages.toArray(new IFormPage[formPages.size()]); |
| } |
| |
| @Deprecated |
| protected IWorkbenchSiteProgressService getProgressService() { |
| Object siteService = getEditorSite().getAdapter(IWorkbenchSiteProgressService.class); |
| if (siteService != null) { |
| return (IWorkbenchSiteProgressService) siteService; |
| } |
| return null; |
| } |
| |
| @Deprecated |
| public ISelection getSelection() { |
| if (getSite() != null && getSite().getSelectionProvider() != null) { |
| return getSite().getSelectionProvider().getSelection(); |
| } else { |
| return StructuredSelection.EMPTY; |
| } |
| } |
| |
| public TaskEditorInput getTaskEditorInput() { |
| return taskEditorInput; |
| } |
| |
| @Deprecated |
| public Form getTopForm() { |
| return this.getHeaderForm().getForm().getForm(); |
| } |
| |
| @Override |
| public void init(IEditorSite site, IEditorInput input) throws PartInitException { |
| if (!(input instanceof TaskEditorInput)) { |
| throw new PartInitException("Invalid editor input \"" + input.getClass() + "\""); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| super.init(site, input); |
| |
| this.taskEditorInput = (TaskEditorInput) input; |
| this.task = taskEditorInput.getTask(); |
| |
| // initialize selection |
| site.getSelectionProvider().setSelection(new StructuredSelection(task)); |
| |
| setPartName(input.getName()); |
| |
| // activate context |
| IContextService contextSupport = (IContextService) site.getService(IContextService.class); |
| if (contextSupport != null) { |
| contextSupport.activateContext(ID_EDITOR); |
| } |
| } |
| |
| private void installTitleDrag(Form form) { |
| if (titleDragSourceListener == null /*&& !hasLeftToolBar()*/) { |
| Transfer[] transferTypes; |
| if (null == task) { |
| transferTypes = new Transfer[] { TextTransfer.getInstance() }; |
| } else { |
| transferTypes = new Transfer[] { LocalSelectionTransfer.getTransfer(), TextTransfer.getInstance(), |
| FileTransfer.getInstance() }; |
| } |
| titleDragSourceListener = new TaskDragSourceListener(new SelectionProviderAdapter() { |
| @Override |
| public ISelection getSelection() { |
| return new StructuredSelection(task); |
| } |
| }); |
| |
| if (titleLabel != null) { |
| DragSource source = new DragSource(titleLabel, DND.DROP_MOVE | DND.DROP_LINK); |
| source.setTransfer(transferTypes); |
| source.addDragListener(titleDragSourceListener); |
| } else { |
| form.addTitleDragSupport(DND.DROP_MOVE | DND.DROP_LINK, transferTypes, titleDragSourceListener); |
| } |
| } |
| } |
| |
| @Override |
| public boolean isDirty() { |
| for (IFormPage page : getPages()) { |
| if (page.isDirty()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean isSaveAsAllowed() { |
| return false; |
| } |
| |
| @Deprecated |
| public void markDirty() { |
| firePropertyChange(PROP_DIRTY); |
| } |
| |
| /** |
| * Refresh editor pages with new contents. |
| * |
| * @since 3.0 |
| */ |
| public void refreshPages() { |
| for (IFormPage page : getPages()) { |
| if (page instanceof TaskFormPage) { |
| if (page.getManagedForm() != null && !page.getManagedForm().getForm().isDisposed()) { |
| ((TaskFormPage) page).refresh(); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void setFocus() { |
| IFormPage page = getActivePageInstance(); |
| if (page != null) { |
| page.setFocus(); |
| } else { |
| super.setFocus(); |
| } |
| } |
| |
| @Deprecated |
| public void setFocusOfActivePage() { |
| if (this.getActivePage() > -1) { |
| IFormPage page = this.getPages()[this.getActivePage()]; |
| if (page != null) { |
| page.setFocus(); |
| } |
| } |
| } |
| |
| public void setMessage(String message, int type) { |
| setMessage(message, type, null); |
| } |
| |
| private boolean isHeaderFormDisposed() { |
| return getHeaderForm() == null || getHeaderForm().getForm() == null || getHeaderForm().getForm().isDisposed(); |
| } |
| |
| /** |
| * @since 2.3 |
| */ |
| public void setMessage(String message, int type, IHyperlinkListener listener) { |
| if (isHeaderFormDisposed()) { |
| return; |
| } |
| |
| try { |
| // avoid flicker of the left header toolbar |
| getHeaderForm().getForm().setRedraw(false); |
| |
| Form form = getHeaderForm().getForm().getForm(); |
| if (message != null) { |
| message = message.replace('\n', ' '); |
| } |
| form.setMessage(message, type, null); |
| if (messageHyperLinkListener != null) { |
| form.removeMessageHyperlinkListener(messageHyperLinkListener); |
| if (messageHyperLinkListener instanceof IDisposable) { |
| ((IDisposable) messageHyperLinkListener).dispose(); |
| } |
| } |
| if (listener != null) { |
| form.addMessageHyperlinkListener(listener); |
| } |
| messageHyperLinkListener = listener; |
| |
| // make sure the busyLabel image is large enough to accommodate the tool bar |
| if (hasLeftToolBar()) { |
| BusyIndicator busyLabel = getBusyLabel(); |
| if (message != null && busyLabel != null) { |
| setHeaderImage(busyLabel.getImage()); |
| } else { |
| setHeaderImage(null); |
| } |
| } |
| } finally { |
| getHeaderForm().getForm().setRedraw(true); |
| } |
| } |
| |
| private void setHeaderImage(final Image image) { |
| BusyIndicator busyLabel = getBusyLabel(); |
| if (busyLabel == null) { |
| return; |
| } |
| |
| final Point size = leftToolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| Point titleSize = titleLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| size.x += titleSize.x + LEFT_TOOLBAR_HEADER_TOOLBAR_PADDING; |
| size.y = Math.max(titleSize.y, size.y); |
| |
| // padding between toolbar and image, ensure image is at least one pixel wide to avoid SWT error |
| final int padding = (size.x > 0 && !noExtraPadding) ? 10 : 1; |
| final Rectangle imageBounds = (image != null) ? image.getBounds() : new Rectangle(0, 0, 0, 0); |
| int tempHeight = (image != null) ? Math.max(size.y + 1, imageBounds.height) : size.y + 1; |
| // avoid extra padding due to margin added by TitleRegion.VMARGIN |
| final int height = (tempHeight > imageBounds.height + 5) ? tempHeight - 5 : tempHeight; |
| |
| CompositeImageDescriptor descriptor = new CompositeImageDescriptor() { |
| @Override |
| protected void drawCompositeImage(int width, int height) { |
| if (image != null) { |
| drawImage(image.getImageData(), size.x + padding, (height - image.getBounds().height) / 2); |
| } |
| } |
| |
| @Override |
| protected Point getSize() { |
| return new Point(size.x + padding + imageBounds.width, height); |
| } |
| |
| }; |
| Image newHeaderImage = descriptor.createImage(); |
| |
| // directly set on busyLabel since getHeaderForm().getForm().setImage() does not update |
| // the image if a message is currently displayed |
| busyLabel.setImage(newHeaderImage); |
| |
| if (headerImage != null) { |
| headerImage.dispose(); |
| } |
| headerImage = newHeaderImage; |
| |
| // avoid extra padding due to large title font |
| // TODO reset font in case tool bar is empty |
| //leftToolBar.getParent().setFont(JFaceResources.getDefaultFont()); |
| getHeaderForm().getForm().reflow(true); |
| } |
| |
| /** |
| * @since 3.1 |
| */ |
| public String getMessage() { |
| if (getHeaderForm() != null && getHeaderForm().getForm() != null) { |
| if (!getHeaderForm().getForm().isDisposed()) { |
| Form form = getHeaderForm().getForm().getForm(); |
| return form.getMessage(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public void setStatus(String message, final String title, final IStatus status) { |
| setMessage(message, IMessageProvider.ERROR, new HyperlinkAdapter() { |
| @Override |
| public void linkActivated(HyperlinkEvent event) { |
| TasksUiInternal.displayStatus(title, status); |
| } |
| }); |
| } |
| |
| @Override |
| public void showBusy(boolean busy) { |
| if (editorBusyIndicator != null) { |
| if (busy) { |
| if (TasksUiInternal.isAnimationsEnabled()) { |
| editorBusyIndicator.start(); |
| } |
| } else { |
| editorBusyIndicator.stop(); |
| } |
| } |
| |
| if (!isHeaderFormDisposed()) { |
| Form form = getHeaderForm().getForm().getForm(); |
| if (form != null && !form.isDisposed()) { |
| // TODO consider only disabling certain actions |
| IToolBarManager toolBarManager = form.getToolBarManager(); |
| if (toolBarManager instanceof ToolBarManager) { |
| ToolBar control = ((ToolBarManager) toolBarManager).getControl(); |
| if (control != null) { |
| control.setEnabled(!busy); |
| } |
| } |
| |
| if (leftToolBar != null) { |
| leftToolBar.setEnabled(!busy); |
| } |
| if (titleLabel != null) { |
| titleLabel.setEnabled(!busy); |
| } |
| |
| CommonUiUtil.setEnabled(form.getBody(), !busy); |
| for (IFormPage page : getPages()) { |
| if (page instanceof WorkbenchPart) { |
| WorkbenchPart part = (WorkbenchPart) page; |
| part.showBusy(busy); |
| } |
| } |
| } |
| } |
| } |
| |
| private void updateHeader() { |
| IEditorInput input = getEditorInput(); |
| updateHeaderImage(); |
| updateHeaderLabel(); |
| setTitleToolTip(input.getToolTipText()); |
| setPartName(input.getName()); |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public void updateHeaderToolBar() { |
| if (isHeaderFormDisposed()) { |
| return; |
| } |
| |
| final Form form = getHeaderForm().getForm().getForm(); |
| toolBarManager = form.getToolBarManager(); |
| |
| toolBarManager.removeAll(); |
| // toolBarManager.update(true); |
| |
| TaskRepository outgoingNewRepository = TasksUiUtil.getOutgoingNewTaskRepository(task); |
| final TaskRepository taskRepository = (outgoingNewRepository != null) |
| ? outgoingNewRepository |
| : taskEditorInput.getTaskRepository(); |
| ControlContribution repositoryLabelControl = new ControlContribution(Messages.AbstractTaskEditorPage_Title) { |
| @Override |
| protected Control createControl(Composite parent) { |
| FormToolkit toolkit = getHeaderForm().getToolkit(); |
| Composite composite = toolkit.createComposite(parent); |
| RowLayout layout = new RowLayout(); |
| if (PlatformUiUtil.hasNarrowToolBar()) { |
| layout.marginTop = 0; |
| layout.marginBottom = 0; |
| layout.center = true; |
| } |
| composite.setLayout(layout); |
| composite.setBackground(null); |
| String label = taskRepository.getRepositoryLabel(); |
| if (label.indexOf("//") != -1) { //$NON-NLS-1$ |
| label = label.substring((taskRepository.getRepositoryUrl().indexOf("//") + 2)); //$NON-NLS-1$ |
| } |
| |
| ImageHyperlink link = new ImageHyperlink(composite, SWT.NONE); |
| link.setText(label); |
| link.setFont(JFaceResources.getBannerFont()); |
| link.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); |
| link.setToolTipText(Messages.TaskEditor_Edit_Task_Repository_ToolTip); |
| link.addHyperlinkListener(new HyperlinkAdapter() { |
| @Override |
| public void linkActivated(HyperlinkEvent e) { |
| TasksUiUtil.openEditRepositoryWizard(taskRepository); |
| } |
| }); |
| |
| return composite; |
| } |
| }; |
| toolBarManager.add(repositoryLabelControl); |
| |
| toolBarManager.add(new GroupMarker("repository")); //$NON-NLS-1$ |
| toolBarManager.add(new GroupMarker("new")); //$NON-NLS-1$ |
| toolBarManager.add(new GroupMarker("open")); //$NON-NLS-1$ |
| toolBarManager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); |
| |
| openWithBrowserAction = new OpenWithBrowserAction(); |
| openWithBrowserAction.selectionChanged(new StructuredSelection(task)); |
| if (openWithBrowserAction.isEnabled()) { |
| // ImageDescriptor overlay = TasksUiPlugin.getDefault().getOverlayIcon(taskRepository.getConnectorKind()); |
| // ImageDescriptor compositeDescriptor = new TaskListImageDescriptor(TasksUiImages.REPOSITORY_SMALL_TOP, |
| // overlay, false, true); |
| openWithBrowserAction.setImageDescriptor(CommonImages.WEB); |
| //openWithBrowserAction.setImageDescriptor(CommonImages.BROWSER_OPEN_TASK); |
| openWithBrowserAction.setToolTipText(Messages.AbstractTaskEditorPage_Open_with_Web_Browser); |
| toolBarManager.appendToGroup("open", openWithBrowserAction); //$NON-NLS-1$ |
| } else { |
| openWithBrowserAction = null; |
| } |
| |
| if (activateAction == null) { |
| activateAction = new ToggleTaskActivationAction(task) { |
| @Override |
| public void run() { |
| TaskList taskList = TasksUiPlugin.getTaskList(); |
| if (taskList.getTask(task.getRepositoryUrl(), task.getTaskId()) == null) { |
| setMessage(Messages.TaskEditor_Task_added_to_the_Uncategorized_container, |
| IMessageProvider.INFORMATION); |
| } |
| super.run(); |
| } |
| }; |
| } |
| |
| toolBarManager.add(new Separator("planning")); //$NON-NLS-1$ |
| disposeScheduleAction(); |
| scheduleAction = new TaskEditorScheduleAction(task); |
| toolBarManager.add(scheduleAction); |
| |
| toolBarManager.add(new GroupMarker("page")); //$NON-NLS-1$ |
| for (IFormPage page : getPages()) { |
| if (page instanceof TaskFormPage) { |
| TaskFormPage taskEditorPage = (TaskFormPage) page; |
| taskEditorPage.fillToolBar(toolBarManager); |
| } |
| } |
| |
| toolBarManager.add(new Separator("activation")); //$NON-NLS-1$ |
| |
| // ContributionItem spacer = new ContributionItem() { |
| // @Override |
| // public void fill(ToolBar toolbar, int index) { |
| // ToolItem item = new ToolItem(toolbar, SWT.NONE); |
| // int scaleHeight = 42; |
| // if (PlatformUtil.needsCarbonToolBarFix()) { |
| // scaleHeight = 32; |
| // } |
| // final Image image = new Image(toolbar.getDisplay(), CommonImages.getImage(CommonImages.BLANK) |
| // .getImageData() |
| // .scaledTo(1, scaleHeight)); |
| // item.setImage(image); |
| // item.addDisposeListener(new DisposeListener() { |
| // public void widgetDisposed(DisposeEvent e) { |
| // image.dispose(); |
| // } |
| // }); |
| // item.setWidth(5); |
| // item.setEnabled(false); |
| // } |
| // }; |
| // toolBarManager.add(spacer); |
| |
| // for (IFormPage page : getPages()) { |
| // if (page instanceof AbstractTaskEditorPage) { |
| // AbstractTaskEditorPage taskEditorPage = (AbstractTaskEditorPage) page; |
| // taskEditorPage.fillLeftHeaderToolBar(toolBarManager); |
| // } else if (page instanceof TaskPlanningEditor) { |
| // TaskPlanningEditor taskEditorPage = (TaskPlanningEditor) page; |
| // taskEditorPage.fillLeftHeaderToolBar(toolBarManager); |
| // } |
| // } |
| |
| // add external contributions |
| menuService = (IMenuService) getSite().getService(IMenuService.class); |
| if (menuService != null && toolBarManager instanceof ContributionManager) { |
| menuService.populateContributionManager((ContributionManager) toolBarManager, "toolbar:" //$NON-NLS-1$ |
| + ID_TOOLBAR_HEADER + "." + taskRepository.getConnectorKind()); //$NON-NLS-1$ |
| menuService.populateContributionManager((ContributionManager) toolBarManager, "toolbar:" //$NON-NLS-1$ |
| + ID_TOOLBAR_HEADER); |
| } |
| |
| toolBarManager.update(true); |
| |
| // XXX move this call |
| updateLeftHeaderToolBar(); |
| updateHeader(); |
| } |
| |
| private void disposeScheduleAction() { |
| if (scheduleAction != null) { |
| scheduleAction.dispose(); |
| scheduleAction = null; |
| } |
| } |
| |
| private void updateLeftHeaderToolBar() { |
| leftToolBarManager.removeAll(); |
| |
| leftToolBarManager.add(new Separator("activation")); //$NON-NLS-1$ |
| leftToolBarManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
| |
| // initialLeftToolbarSize = leftToolBarManager.getSize(); |
| |
| leftToolBarManager.add(activateAction); |
| |
| // for (IFormPage page : getPages()) { |
| // if (page instanceof AbstractTaskEditorPage) { |
| // AbstractTaskEditorPage taskEditorPage = (AbstractTaskEditorPage) page; |
| // taskEditorPage.fillLeftHeaderToolBar(leftToolBarManager); |
| // } else if (page instanceof TaskPlanningEditor) { |
| // TaskPlanningEditor taskEditorPage = (TaskPlanningEditor) page; |
| // taskEditorPage.fillLeftHeaderToolBar(leftToolBarManager); |
| // } |
| // } |
| |
| // add external contributions |
| menuService = (IMenuService) getSite().getService(IMenuService.class); |
| if (menuService != null && leftToolBarManager instanceof ContributionManager) { |
| TaskRepository outgoingNewRepository = TasksUiUtil.getOutgoingNewTaskRepository(task); |
| TaskRepository taskRepository = (outgoingNewRepository != null) |
| ? outgoingNewRepository |
| : taskEditorInput.getTaskRepository(); |
| menuService.populateContributionManager(leftToolBarManager, "toolbar:" + ID_LEFT_TOOLBAR_HEADER + "." //$NON-NLS-1$ //$NON-NLS-2$ |
| + taskRepository.getConnectorKind()); |
| } |
| |
| leftToolBarManager.update(true); |
| |
| if (hasLeftToolBar()) { |
| // XXX work around a bug in Gtk that causes the toolbar size to be incorrect if no |
| // tool bar buttons are contributed |
| // if (leftToolBar != null) { |
| // Point size = leftToolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT, false); |
| // boolean changed = false; |
| // for (Control control : leftToolBar.getChildren()) { |
| // final Point childSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, false); |
| // if (childSize.y > size.y) { |
| // size.y = childSize.y; |
| // changed = true; |
| // } |
| // } |
| // if (changed) { |
| // leftToolBar.setSize(size); |
| // } |
| // } |
| // |
| // if (PlatformUtil.isToolBarHeightBroken(leftToolBar)) { |
| // ToolItem item = new ToolItem(leftToolBar, SWT.NONE); |
| // item.setEnabled(false); |
| // item.setImage(CommonImages.getImage(CommonImages.BLANK)); |
| // item.setWidth(1); |
| // noExtraPadding = true; |
| // } else if (PlatformUtil.needsToolItemToForceToolBarHeight()) { |
| // ToolItem item = new ToolItem(leftToolBar, SWT.NONE); |
| // item.setEnabled(false); |
| // int scaleHeight = 22; |
| // if (PlatformUtil.needsCarbonToolBarFix()) { |
| // scaleHeight = 32; |
| // } |
| // final Image image = new Image(item.getDisplay(), CommonImages.getImage(CommonImages.BLANK) |
| // .getImageData() |
| // .scaledTo(1, scaleHeight)); |
| // item.setImage(image); |
| // item.addDisposeListener(new DisposeListener() { |
| // public void widgetDisposed(DisposeEvent e) { |
| // image.dispose(); |
| // } |
| // }); |
| // item.setWidth(1); |
| // noExtraPadding = true; |
| // } |
| |
| // fix size of toolbar on Gtk with Eclipse 3.3 |
| Point size = leftToolBar.getSize(); |
| if (size.x == 0 && size.y == 0) { |
| size = leftToolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| leftToolBar.setSize(size); |
| } |
| } |
| } |
| |
| private void updateHeaderImage() { |
| if (hasLeftToolBar()) { |
| setHeaderImage(null); |
| } else { |
| getHeaderForm().getForm().setImage(getBrandingImage()); |
| } |
| } |
| |
| private Image getBrandingImage() { |
| String connectorKind; |
| TaskRepository outgoingNewRepository = TasksUiUtil.getOutgoingNewTaskRepository(task); |
| if (outgoingNewRepository != null) { |
| connectorKind = outgoingNewRepository.getConnectorKind(); |
| } else { |
| connectorKind = task.getConnectorKind(); |
| } |
| |
| if (LocalRepositoryConnector.CONNECTOR_KIND.equals(connectorKind)) { |
| return CommonImages.getImage(TasksUiImages.TASK); |
| } else { |
| ImageDescriptor overlay; |
| if (outgoingNewRepository != null) { |
| overlay = TasksUiPlugin.getDefault().getBrandManager().getOverlayIcon(outgoingNewRepository); |
| } else { |
| overlay = TasksUiPlugin.getDefault().getBrandManager().getOverlayIcon(task); |
| } |
| Image image = CommonImages.getImageWithOverlay(TasksUiImages.REPOSITORY, overlay, false, false); |
| return image; |
| } |
| } |
| |
| private boolean hasLeftToolBar() { |
| return leftToolBar != null && leftToolBarManager != null; |
| // && leftToolBarManager.getSize() > initialLeftToolbarSize; |
| } |
| |
| private void updateHeaderLabel() { |
| TaskRepository outgoingNewRepository = TasksUiUtil.getOutgoingNewTaskRepository(task); |
| final TaskRepository taskRepository = (outgoingNewRepository != null) |
| ? outgoingNewRepository |
| : taskEditorInput.getTaskRepository(); |
| |
| // if (taskRepository.getConnectorKind().equals(LocalRepositoryConnector.CONNECTOR_KIND)) { |
| // getHeaderForm().getForm().setText(Messages.TaskEditor_Task_ + task.getSummary()); |
| // } else { |
| AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(taskRepository.getConnectorKind()); |
| String kindLabel = Messages.TaskEditor_Task; |
| if (connectorUi != null) { |
| kindLabel = connectorUi.getTaskKindLabel(task); |
| } |
| |
| String idLabel = task.getTaskKey(); |
| if (idLabel != null) { |
| kindLabel += " " + idLabel; //$NON-NLS-1$ |
| } |
| |
| if (hasLeftToolBar() && titleLabel != null) { |
| titleLabel.setText(kindLabel); |
| getHeaderForm().getForm().setText(null); |
| setHeaderImage(null); |
| } else { |
| getHeaderForm().getForm().setText(kindLabel); |
| } |
| } |
| |
| /** |
| * Update the title of the editor. |
| * |
| * @deprecated use {@link #updateHeaderToolBar()} instead |
| */ |
| @Deprecated |
| public void updateTitle(String name) { |
| updateHeader(); |
| } |
| |
| private void updateTitleImage() { |
| if (task != null) { |
| AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(task.getConnectorKind()); |
| if (connectorUi != null) { |
| ImageDescriptor overlayDescriptor = connectorUi.getTaskKindOverlay(task); |
| setTitleImage(CommonImages.getCompositeTaskImage(TasksUiImages.TASK, overlayDescriptor, false)); |
| } else { |
| setTitleImage(CommonImages.getImage(TasksUiImages.TASK)); |
| } |
| // } else if (getEditorInput() instanceof AbstractRepositoryTaskEditorInput) { |
| // setTitleImage(CommonImages.getImage(TasksUiImages.TASK_REMOTE)); |
| } else { |
| setTitleImage(CommonImages.getImage(TasksUiImages.TASK)); |
| } |
| } |
| |
| } |