diff options
author | spingel | 2010-05-24 21:30:25 +0000 |
---|---|---|
committer | spingel | 2010-05-24 21:30:25 +0000 |
commit | 070a4ea489907f716460e182d3ec9230322dd936 (patch) | |
tree | 969e27a3a0ad53fe635ba0629cdf2d3ba20f39de /org.eclipse.mylyn.tasks.ui/src | |
parent | 218c0ef5843c22522d06ca96db7c4ac37e15fb68 (diff) | |
download | org.eclipse.mylyn.tasks-070a4ea489907f716460e182d3ec9230322dd936.tar.gz org.eclipse.mylyn.tasks-070a4ea489907f716460e182d3ec9230322dd936.tar.xz org.eclipse.mylyn.tasks-070a4ea489907f716460e182d3ec9230322dd936.zip |
ASSIGNED - bug 278102: [patch] add quick outline to task editor and provide quick access to related tasks
https://bugs.eclipse.org/bugs/show_bug.cgi?id=278102
Diffstat (limited to 'org.eclipse.mylyn.tasks.ui/src')
14 files changed, 1109 insertions, 139 deletions
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/EditorUtil.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/EditorUtil.java index 72f8bdc40..3c9d61175 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/EditorUtil.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/EditorUtil.java @@ -153,7 +153,7 @@ public class EditorUtil { * @param control * The StyledText to scroll to */ - private static void focusOn(ScrolledForm form, Control control) { + public static void focusOn(ScrolledForm form, Control control) { int pos = 0; control.setEnabled(true); control.setFocus(); @@ -405,8 +405,11 @@ public class EditorUtil { } else { roundedBorder.setLayout(GridLayoutFactory.fillDefaults().margins(0, 6).create()); } - GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).hint(EditorUtil.MAXIMUM_WIDTH, SWT.DEFAULT).grab( - true, false).applyTo(roundedBorder); + GridDataFactory.fillDefaults() + .align(SWT.FILL, SWT.BEGINNING) + .hint(EditorUtil.MAXIMUM_WIDTH, SWT.DEFAULT) + .grab(true, false) + .applyTo(roundedBorder); return roundedBorder; } @@ -432,8 +435,11 @@ public class EditorUtil { textFont.dispose(); } }); - Color color = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().get( - CommonThemes.COLOR_COMPLETED); + Color color = PlatformUI.getWorkbench() + .getThemeManager() + .getCurrentTheme() + .getColorRegistry() + .get(CommonThemes.COLOR_COMPLETED); text.setForeground(color); return textFont; } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java index f769d28bd..86eb5e371 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/Messages.java @@ -151,14 +151,24 @@ public class Messages extends NLS { public static String TaskEditorNewCommentPart_New_Comment; + public static String TaskEditorOutlineNode_Attachments; + + public static String TaskEditorOutlineNode_Attributes; + public static String TaskEditorOutlineNode_Comments; public static String TaskEditorOutlineNode_Description; public static String TaskEditorOutlineNode_New_Comment; + public static String TaskEditorOutlineNode_Related_Tasks; + public static String TaskEditorOutlineNode_Task_; + public static String TaskEditorOutlineNode_TaskRelation_Label; + + public static String TaskEditorOutlineNode_unknown_Label; + public static String TaskEditorPeoplePart_People; public static String TaskEditorPlanningPart_0_SECOUNDS; diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineContentProvider.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineContentProvider.java new file mode 100644 index 000000000..07545d2d7 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineContentProvider.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2010 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.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +public class TaskEditorOutlineContentProvider implements ITreeContentProvider { + + public void dispose() { + // ignore + } + + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof TaskEditorOutlineNode) { + Object[] children = ((TaskEditorOutlineNode) parentElement).getChildren(); + return children; + } + return new Object[0]; + } + + public Object[] getElements(Object inputElement) { + if (inputElement instanceof TaskEditorOutlineModel) { + return new Object[] { ((TaskEditorOutlineModel) inputElement).getRoot() }; + } + return new Object[0]; + } + + public Object getParent(Object element) { + if (element instanceof TaskEditorOutlineNode) { + return ((TaskEditorOutlineNode) element).getParent(); + } + return null; + } + + public boolean hasChildren(Object element) { + if (element instanceof TaskEditorOutlineNode) { + return ((TaskEditorOutlineNode) element).getChildren().length > 0; + } + return false; + } + + public void inputChanged(Viewer viewerChanged, Object oldInput, Object newInput) { + // ignore + } + +}
\ No newline at end of file diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineModel.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineModel.java new file mode 100644 index 000000000..28478dc37 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineModel.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2010 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; + +public class TaskEditorOutlineModel { + + private final TaskEditorOutlineNode root; + + public TaskEditorOutlineModel(TaskEditorOutlineNode root) { + this.root = root; + } + + public TaskEditorOutlineNode getRoot() { + return root; + } + +}
\ No newline at end of file diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineNode.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineNode.java index a3ada9523..44489a945 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineNode.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineNode.java @@ -12,15 +12,27 @@ package org.eclipse.mylyn.internal.tasks.ui.editors; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.Map; import org.eclipse.core.runtime.Assert; +import org.eclipse.mylyn.internal.tasks.core.TaskList; +import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.internal.tasks.ui.util.AttachmentUtil; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.IRepositoryPerson; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.ITaskAttachment; import org.eclipse.mylyn.tasks.core.ITaskComment; +import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.core.data.TaskRelation; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.osgi.util.NLS; /** * A node for the tree in {@link TaskEditorOutlinePage}. @@ -35,6 +47,12 @@ public class TaskEditorOutlineNode { public static final String LABEL_NEW_COMMENT = Messages.TaskEditorOutlineNode_New_Comment; + public static final String LABEL_ATTACHMENTS = Messages.TaskEditorOutlineNode_Attachments; + + public static final String LABEL_ATTRIBUTES = Messages.TaskEditorOutlineNode_Attributes; + + public static final String LABEL_RELATED_TASKS = Messages.TaskEditorOutlineNode_Related_Tasks; + private static TaskEditorOutlineNode createNode(TaskData taskData, String attributeId, String label) { TaskAttribute taskAttribute = taskData.getRoot().getMappedAttribute(attributeId); if (taskAttribute != null) { @@ -69,19 +87,90 @@ public class TaskEditorOutlineNode { node.setTaskComment(taskComment); return node; } + } else if (TaskAttribute.TYPE_ATTACHMENT.equals(type)) { + ITaskAttachment taskAttachment = TasksUiPlugin.getRepositoryModel().createTaskAttachment(taskAttribute); + if (taskAttachment != null) { + taskAttribute.getTaskData().getAttributeMapper().updateTaskAttachment(taskAttachment, taskAttribute); + StringBuilder sb = new StringBuilder(); + sb.append(taskAttribute.getTaskData().getAttributeMapper().getValueLabel(taskAttribute)); + sb.append(": "); //$NON-NLS-1$ + if (AttachmentUtil.isContext(taskAttachment)) { + sb.append(Messages.AttachmentTableLabelProvider_Task_Context); + } else if (taskAttachment.isPatch()) { + sb.append(Messages.AttachmentTableLabelProvider_Patch); + } else { + sb.append(taskAttachment.getFileName()); + } + TaskEditorOutlineNode node = new TaskEditorOutlineNode(sb.toString(), taskAttribute); + node.setTaskAttachment(taskAttachment); + return node; + } } else { - String label = taskAttribute.getTaskData().getAttributeMapper().getValueLabel(taskAttribute); + String label = taskAttribute.getTaskData().getAttributeMapper().getLabel(taskAttribute); + if (label.endsWith(":")) { //$NON-NLS-1$ + label = label.substring(0, label.length() - 1); + } return new TaskEditorOutlineNode(label, taskAttribute); } return null; } - public static TaskEditorOutlineNode parse(TaskData taskData) { + public static TaskEditorOutlineNode parse(TaskData taskData, boolean includeAttributes) { TaskEditorOutlineNode rootNode = createNode(taskData, TaskAttribute.SUMMARY, null); if (rootNode == null) { rootNode = new TaskEditorOutlineNode(Messages.TaskEditorOutlineNode_Task_ + taskData.getTaskId()); } + if (includeAttributes) { + final TaskList taskList = TasksUiPlugin.getTaskList(); + TaskEditorOutlineNode relatedTasksNode = new TaskEditorOutlineNode(LABEL_RELATED_TASKS); + rootNode.addChild(relatedTasksNode); + AbstractRepositoryConnector connector = TasksUi.getRepositoryConnector(taskData.getConnectorKind()); + Collection<TaskRelation> relations = connector.getTaskRelations(taskData); + TaskRepositoryManager manager = TasksUiPlugin.getRepositoryManager(); + TaskRepository taskRepository = manager.getRepository(taskData.getConnectorKind(), + taskData.getRepositoryUrl()); + for (TaskRelation taskRelation : relations) { + ITask task = taskList.getTask(taskData.getRepositoryUrl(), taskRelation.getTaskId()); + String label; + if (task != null) { + label = NLS.bind(Messages.TaskEditorOutlineNode_TaskRelation_Label, + new Object[] { taskRelation.getTaskId(), task.getSummary() }); + } else { + label = NLS.bind(Messages.TaskEditorOutlineNode_TaskRelation_Label, + new Object[] { taskRelation.getTaskId(), Messages.TaskEditorOutlineNode_unknown_Label }); + } + TaskEditorOutlineNode childNode = new TaskEditorOutlineNode(label); + + childNode.setTaskRelation(taskRelation); + childNode.setTaskRepository(taskRepository); + relatedTasksNode.addChild(childNode); + } + + TaskEditorOutlineNode attributesNode = new TaskEditorOutlineNode(LABEL_ATTRIBUTES); + rootNode.addChild(attributesNode); + Map<String, TaskAttribute> attributes = taskData.getRoot().getAttributes(); + for (TaskAttribute attribute : attributes.values()) { + if (TaskAttribute.KIND_DEFAULT.equals(attribute.getMetaData().getKind())) { + TaskEditorOutlineNode node = createNode(attribute); + if (node != null) { + attributesNode.addChild(node); + } + } + } + } addNode(rootNode, taskData, TaskAttribute.DESCRIPTION, LABEL_DESCRIPTION); + List<TaskAttribute> attachments = taskData.getAttributeMapper().getAttributesByType(taskData, + TaskAttribute.TYPE_ATTACHMENT); + if (attachments.size() > 0) { + TaskEditorOutlineNode attachmentNode = new TaskEditorOutlineNode(LABEL_ATTACHMENTS); + rootNode.addChild(attachmentNode); + for (TaskAttribute attachmentAttribute : attachments) { + TaskEditorOutlineNode node = createNode(attachmentAttribute); + if (node != null) { + attachmentNode.addChild(node); + } + } + } List<TaskAttribute> comments = taskData.getAttributeMapper().getAttributesByType(taskData, TaskAttribute.TYPE_COMMENT); if (comments.size() > 0) { @@ -118,6 +207,12 @@ public class TaskEditorOutlineNode { private ITaskComment taskComment; + private ITaskAttachment taskAttachment; + + private TaskRelation taskRelation; + + private TaskRepository taskRepository; + public TaskEditorOutlineNode(String label) { this(label, null); } @@ -183,4 +278,28 @@ public class TaskEditorOutlineNode { return getLabel(); } + public ITaskAttachment getTaskAttachment() { + return taskAttachment; + } + + public void setTaskAttachment(ITaskAttachment taskAttachment) { + this.taskAttachment = taskAttachment; + } + + public TaskRelation getTaskRelation() { + return taskRelation; + } + + public void setTaskRelation(TaskRelation taskRelation) { + this.taskRelation = taskRelation; + } + + public TaskRepository getTaskRepository() { + return taskRepository; + } + + public void setTaskRepository(TaskRepository taskRepository) { + this.taskRepository = taskRepository; + } + } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineNodeLabelProvider.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineNodeLabelProvider.java new file mode 100644 index 000000000..379ded4c4 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlineNodeLabelProvider.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2010 Frank Becker 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: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.editors; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages; +import org.eclipse.mylyn.internal.tasks.ui.util.AttachmentUtil; +import org.eclipse.mylyn.tasks.core.IRepositoryPerson; +import org.eclipse.mylyn.tasks.core.ITaskAttachment; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.mylyn.tasks.ui.TasksUiImages; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.internal.WorkbenchImages; + +/** + * @author Frank Becker + */ +public class TaskEditorOutlineNodeLabelProvider extends LabelProvider { + + private static final String[] IMAGE_EXTENSIONS = { "jpg", "gif", "png", "tiff", "tif", "bmp" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ @Override + + @Override + public Image getImage(Object element) { + if (element instanceof TaskEditorOutlineNode) { + TaskEditorOutlineNode node = (TaskEditorOutlineNode) element; + if (TaskEditorOutlineNode.LABEL_COMMENTS.equals(node.getLabel()) + || TaskEditorOutlineNode.LABEL_NEW_COMMENT.equals(node.getLabel())) { + return CommonImages.getImage(TasksUiImages.COMMENT); + } + if (TaskEditorOutlineNode.LABEL_DESCRIPTION.equals(node.getLabel())) { + return CommonImages.getImage(TasksUiImages.TASK_NOTES); + } else if (node.getTaskComment() != null) { + IRepositoryPerson author = node.getTaskComment().getAuthor(); + TaskAttribute taskAttribute = node.getData(); + String repositoryUrl = taskAttribute.getTaskData().getRepositoryUrl(); + String connectorKind = null; + TaskRepository taskRepository = null; + if (repositoryUrl != null) { + connectorKind = taskAttribute.getTaskData().getConnectorKind(); + if (connectorKind != null) { + taskRepository = TasksUi.getRepositoryManager().getRepository(connectorKind, repositoryUrl); + } + } + if (taskRepository != null && author != null + && author.getPersonId().equals(taskRepository.getUserName())) { + return CommonImages.getImage(CommonImages.PERSON_ME); + } else { + return CommonImages.getImage(CommonImages.PERSON); + } + } else if (node.getTaskAttachment() != null) { + ITaskAttachment attachment = node.getTaskAttachment(); + if (AttachmentUtil.isContext(attachment)) { + return CommonImages.getImage(TasksUiImages.CONTEXT_TRANSFER); + } else if (attachment.isPatch()) { + return CommonImages.getImage(TasksUiImages.TASK_ATTACHMENT_PATCH); + } else { + String filename = attachment.getFileName(); + if (filename != null) { + int dotIndex = filename.lastIndexOf('.'); + if (dotIndex != -1) { + String fileType = filename.substring(dotIndex + 1); + for (String element2 : IMAGE_EXTENSIONS) { + if (element2.equalsIgnoreCase(fileType)) { + return CommonImages.getImage(CommonImages.IMAGE_FILE); + } + } + } + } + return WorkbenchImages.getImage(ISharedImages.IMG_OBJ_FILE); + } + } else if (node.getParent() == null) { + return CommonImages.getImage(TasksUiImages.TASK); + } + } + return super.getImage(element); + } + + @Override + public String getText(Object element) { + if (element instanceof TaskEditorOutlineNode) { + TaskEditorOutlineNode node = (TaskEditorOutlineNode) element; + if (TaskEditorOutlineNode.LABEL_COMMENTS.equals(node.getLabel()) + || TaskEditorOutlineNode.LABEL_NEW_COMMENT.equals(node.getLabel()) + || TaskEditorOutlineNode.LABEL_DESCRIPTION.equals(node.getLabel())) { + return node.getLabel(); + } + if (node.getData() != null && node.getTaskAttachment() == null && node.getTaskComment() == null) { + // regular attribute + TaskAttribute taskAttribute = node.getData(); + String label = taskAttribute.getTaskData().getAttributeMapper().getLabel(taskAttribute); + if (!label.endsWith(":")) { //$NON-NLS-1$ + label += ":"; //$NON-NLS-1$ + } + return label + " " + taskAttribute.getTaskData().getAttributeMapper().getValueLabel(taskAttribute); //$NON-NLS-1$ + } + return node.getLabel(); + } + return super.getText(element); + } + +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlinePage.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlinePage.java index 52a3046b7..085c09915 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlinePage.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorOutlinePage.java @@ -11,16 +11,9 @@ package org.eclipse.mylyn.internal.tasks.ui.editors; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages; -import org.eclipse.mylyn.tasks.core.IRepositoryPerson; import org.eclipse.mylyn.tasks.core.TaskRepository; -import org.eclipse.mylyn.tasks.ui.TasksUiImages; import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; -import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.views.contentoutline.ContentOutlinePage; @@ -31,61 +24,6 @@ import org.eclipse.ui.views.contentoutline.ContentOutlinePage; */ public class TaskEditorOutlinePage extends ContentOutlinePage { - private static class TaskEditorOutlineContentProvider implements ITreeContentProvider { - - public void dispose() { - // ignore - } - - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof TaskEditorOutlineNode) { - Object[] children = ((TaskEditorOutlineNode) parentElement).getChildren(); - return children; - } - return new Object[0]; - } - - public Object[] getElements(Object inputElement) { - if (inputElement instanceof TaskEditorOutlineModel) { - return new Object[] { ((TaskEditorOutlineModel) inputElement).getRoot() }; - } - return new Object[0]; - } - - public Object getParent(Object element) { - if (element instanceof TaskEditorOutlineNode) { - return ((TaskEditorOutlineNode) element).getParent(); - } - return null; - } - - public boolean hasChildren(Object element) { - if (element instanceof TaskEditorOutlineNode) { - return ((TaskEditorOutlineNode) element).getChildren().length > 0; - } - return false; - } - - public void inputChanged(Viewer viewerChanged, Object oldInput, Object newInput) { - // ignore - } - - } - - private static class TaskEditorOutlineModel { - - private final TaskEditorOutlineNode root; - - public TaskEditorOutlineModel(TaskEditorOutlineNode root) { - this.root = root; - } - - public TaskEditorOutlineNode getRoot() { - return root; - } - - } - private TaskEditorOutlineModel model; private TaskRepository taskRepository; @@ -113,42 +51,7 @@ public class TaskEditorOutlinePage extends ContentOutlinePage { super.createControl(parent); viewer = getTreeViewer(); viewer.setContentProvider(new TaskEditorOutlineContentProvider()); - viewer.setLabelProvider(new LabelProvider() { - @Override - public Image getImage(Object element) { - if (element instanceof TaskEditorOutlineNode) { - TaskEditorOutlineNode node = (TaskEditorOutlineNode) element; - if (TaskEditorOutlineNode.LABEL_COMMENTS.equals(node.getLabel()) - || TaskEditorOutlineNode.LABEL_NEW_COMMENT.equals(node.getLabel())) { - return CommonImages.getImage(TasksUiImages.COMMENT); - } - if (TaskEditorOutlineNode.LABEL_DESCRIPTION.equals(node.getLabel())) { - return CommonImages.getImage(TasksUiImages.TASK_NOTES); - } else if (node.getTaskComment() != null) { - IRepositoryPerson author = node.getTaskComment().getAuthor(); - if (taskRepository != null && author != null - && author.getPersonId().equals(taskRepository.getUserName())) { - return CommonImages.getImage(CommonImages.PERSON_ME); - } else { - return CommonImages.getImage(CommonImages.PERSON); - } - } else { - return CommonImages.getImage(TasksUiImages.TASK); - } - } else { - return super.getImage(element); - } - } - - @Override - public String getText(Object element) { - if (element instanceof TaskEditorOutlineNode) { - TaskEditorOutlineNode node = (TaskEditorOutlineNode) element; - return node.getLabel(); - } - return super.getText(element); - } - }); + viewer.setLabelProvider(new TaskEditorOutlineNodeLabelProvider()); viewer.setInput(model); viewer.expandAll(); } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties index a137f85c1..0f27c0c02 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/messages.properties @@ -83,10 +83,15 @@ TaskEditorDescriptionPart_The_duplicate_detector_did_not_return_a_valid_query=Th TaskEditorDescriptionPart_Search=Search TaskEditorNewCommentPart_New_Comment=New Comment +TaskEditorOutlineNode_Attachments=Attachments +TaskEditorOutlineNode_Attributes=Attributes TaskEditorOutlineNode_Comments=Comments TaskEditorOutlineNode_Description=Description TaskEditorOutlineNode_New_Comment=New Comment +TaskEditorOutlineNode_Related_Tasks=Related Tasks TaskEditorOutlineNode_Task_=Task +TaskEditorOutlineNode_TaskRelation_Label={0}: {1} +TaskEditorOutlineNode_unknown_Label=<unknown> TaskEditorPeoplePart_People=People diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/Messages.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/Messages.java new file mode 100644 index 000000000..a427243a6 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/Messages.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2010 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.outline; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.mylyn.internal.tasks.ui.editors.outline.messages"; //$NON-NLS-1$ + + public static String QuickOutlineDialog_Press_Esc_Info_Text; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/QuickOutlineDialog.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/QuickOutlineDialog.java new file mode 100644 index 000000000..2c98c864f --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/QuickOutlineDialog.java @@ -0,0 +1,532 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Tasktop Technologies - adapted for Mylyn + * Frank Becker - adapted for Mylyn Task Editor + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.editors.outline; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.PopupDialog; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlExtension; +import org.eclipse.jface.text.IInformationControlExtension2; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IOpenListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.OpenEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorOutlineContentProvider; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorOutlineModel; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorOutlineNode; +import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage; +import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.dialogs.PatternFilter; +import org.eclipse.ui.forms.editor.IFormPage; + +/** + * @author Mik Kersten + * @author Frank Becker + * @author Steffen Pingel + */ +public class QuickOutlineDialog extends PopupDialog implements IInformationControl, IInformationControlExtension, + IInformationControlExtension2, DisposeListener { + + private class OpenListener implements IOpenListener, IDoubleClickListener, MouseListener { + + private final Viewer viewer; + + public OpenListener(Viewer viewer) { + this.viewer = viewer; + } + + public void mouseDoubleClick(MouseEvent e) { + setSelection(e); + } + + public void mouseDown(MouseEvent e) { + setSelection(e); + } + + public void mouseUp(MouseEvent e) { + // ignore + + } + + public void doubleClick(DoubleClickEvent event) { + open(null); + } + + public void open(OpenEvent event) { + AbstractTaskEditorPage taskEditorPage = getTaskEditorPage(); + if (taskEditorPage == null) { + return; + } + + StructuredSelection selection = (StructuredSelection) viewer.getSelection(); + Object select = (selection).getFirstElement(); + taskEditorPage.selectReveal(select); + } + + private void setSelection(MouseEvent event) { + try { + Object selection = ((Tree) event.getSource()).getSelection()[0].getData(); + viewer.setSelection(new StructuredSelection(selection)); + open(null); + } catch (Exception e) { + // ignore + } + } + + } + + public static final String ID_VIEWER = "org.eclipse.mylyn.internal.tasks.ui.taskdata.quick"; //$NON-NLS-1$ + + private TreeViewer viewer; + + private Text filterText; + + private PatternFilter namePatternFilter; + + private OpenListener openListener; + + private final IWorkbenchWindow window; + + public QuickOutlineDialog(IWorkbenchWindow window) { + super(window.getShell(), SWT.RESIZE, true, true, true, true, true, null, null); + this.window = window; + setInfoText(Messages.QuickOutlineDialog_Press_Esc_Info_Text); + create(); + } + + @Override + public boolean close() { + // nothing additional to dispose + return super.close(); + } + + @Override + protected Control createDialogArea(Composite parent) { + createViewer(parent); + createUIListenersTreeViewer(); + addDisposeListener(this); + + return viewer.getControl(); + } + + private void createViewer(Composite parent) { + Control composite = super.createDialogArea(parent); + viewer = createCommonViewer((Composite) composite); + openListener = new OpenListener(viewer); + + viewer.addOpenListener(openListener); + viewer.getTree().addMouseListener(openListener); + + namePatternFilter = new PatternFilter(); + namePatternFilter.setIncludeLeadingWildcard(true); + viewer.addFilter(namePatternFilter); + + AbstractTaskEditorPage taskEditorPage = getTaskEditorPage(); + if (taskEditorPage != null) { + try { + viewer.getControl().setRedraw(false); + TaskEditorOutlineNode root = TaskEditorOutlineNode.parse(taskEditorPage.getModel().getTaskData(), true); + viewer.setInput(new TaskEditorOutlineModel(root)); + viewer.expandAll(); + } finally { + viewer.getControl().setRedraw(true); + } + } + } + + protected TreeViewer createCommonViewer(Composite parent) { + TreeViewer viewer = new TreeViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL); + viewer.setUseHashlookup(true); + viewer.getControl().setLayoutData(new GridData(500, 400)); + viewer.setContentProvider(new TaskEditorOutlineContentProvider()); + viewer.setLabelProvider(new QuickOutlineLabelProvider()); + return viewer; + } + + @Override + protected void fillDialogMenu(IMenuManager dialogMenu) { + dialogMenu.add(new Separator()); + super.fillDialogMenu(dialogMenu); + } + + private void createUIListenersTreeViewer() { + final Tree tree = viewer.getTree(); + tree.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + if (e.character == 0x1B) { + // Dispose on ESC key press + dispose(); + } + } + + public void keyReleased(KeyEvent e) { + // ignore + } + }); + + tree.addMouseListener(new MouseAdapter() { + @Override + public void mouseUp(MouseEvent e) { + handleTreeViewerMouseUp(tree, e); + } + }); + + tree.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + // ignore + } + + public void widgetDefaultSelected(SelectionEvent e) { + gotoSelectedElement(); + } + }); + } + + private void handleTreeViewerMouseUp(final Tree tree, MouseEvent e) { + if ((tree.getSelectionCount() < 1) || (e.button != 1) || (tree.equals(e.getSource()) == false)) { + return; + } + // Selection is made in the selection changed listener + Object object = tree.getItem(new Point(e.x, e.y)); + TreeItem selection = tree.getSelection()[0]; + if (selection.equals(object)) { + gotoSelectedElement(); + } + } + + private Object getSelectedElement() { + if (viewer == null) { + return null; + } + return ((IStructuredSelection) viewer.getSelection()).getFirstElement(); + } + + public void addDisposeListener(DisposeListener listener) { + getShell().addDisposeListener(listener); + } + + public void addFocusListener(FocusListener listener) { + getShell().addFocusListener(listener); + } + + public Point computeSizeHint() { + // Note that it already has the persisted size if persisting is enabled. + return getShell().getSize(); + } + + public void dispose() { + close(); + } + + public boolean isFocusControl() { + if (viewer.getControl().isFocusControl() || filterText.isFocusControl()) { + return true; + } + return false; + } + + public void removeDisposeListener(DisposeListener listener) { + getShell().removeDisposeListener(listener); + } + + public void removeFocusListener(FocusListener listener) { + getShell().removeFocusListener(listener); + } + + public void setBackgroundColor(Color background) { + applyBackgroundColor(background, getContents()); + } + + public void setFocus() { + getShell().forceFocus(); + filterText.setFocus(); + } + + public void setForegroundColor(Color foreground) { + applyForegroundColor(foreground, getContents()); + } + + public void setInformation(String information) { + // See IInformationControlExtension2 + } + + public void setLocation(Point location) { + /* + * If the location is persisted, it gets managed by PopupDialog - fine. Otherwise, the location is + * computed in Window#getInitialLocation, which will center it in the parent shell / main + * monitor, which is wrong for two reasons: + * - we want to center over the editor / subject control, not the parent shell + * - the center is computed via the initalSize, which may be also wrong since the size may + * have been updated since via min/max sizing of AbstractInformationControlManager. + * In that case, override the location with the one computed by the manager. Note that + * the call to constrainShellSize in PopupDialog.open will still ensure that the shell is + * entirely visible. + */ + if (getPersistLocation() == false || getDialogSettings() == null) { + getShell().setLocation(location); + } + } + + public void setSize(int width, int height) { + getShell().setSize(width, height); + } + + public void setSizeConstraints(int maxWidth, int maxHeight) { + // Ignore + } + + public void setVisible(boolean visible) { + if (visible) { + open(); + } else { + saveDialogBounds(getShell()); + getShell().setVisible(false); + } + } + + public boolean hasContents() { + if ((viewer == null) || (viewer.getInput() == null)) { + return false; + } + return true; + } + + public void setInput(Object input) { + if (input != null) { + viewer.setSelection(new StructuredSelection(input)); + } + } + + public void widgetDisposed(DisposeEvent e) { + // Note: We do not reuse the dialog + viewer = null; + filterText = null; + } + + @Override + protected Control createTitleControl(Composite parent) { + Composite control = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + layout.marginHeight = 0; + control.setLayout(layout); + control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + // Applies only to dialog title - not body. See createDialogArea + // Create the text widget + createUIWidgetFilterText(control); + // Add listeners to the text widget + createUIListenersFilterText(); + // Return the text widget + return control; + } + + private void createUIWidgetFilterText(Composite parent) { + // Create the widget + filterText = new Text(parent, SWT.NONE); + // Set the font + GC gc = new GC(parent); + gc.setFont(parent.getFont()); + FontMetrics fontMetrics = gc.getFontMetrics(); + gc.dispose(); + // Create the layout + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.heightHint = Dialog.convertHeightInCharsToPixels(fontMetrics, 1); + data.horizontalAlignment = GridData.FILL; + data.verticalAlignment = GridData.CENTER; + filterText.setLayoutData(data); + } + + /** + * + */ + private void gotoSelectedElement() { + Object selectedElement = getSelectedElement(); + if (selectedElement == null) { + return; + } + dispose(); + } + + private void createUIListenersFilterText() { + filterText.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + if (e.keyCode == 0x0D) { + // Return key was pressed + gotoSelectedElement(); + } else if (e.keyCode == SWT.ARROW_DOWN) { + // Down key was pressed + viewer.getTree().setFocus(); + } else if (e.keyCode == SWT.ARROW_UP) { + // Up key was pressed + viewer.getTree().setFocus(); + } else if (e.character == 0x1B) { + // Escape key was pressed + dispose(); + } + } + + public void keyReleased(KeyEvent e) { + // NO-OP + } + }); + // Handle text modify events + filterText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + String text = ((Text) e.widget).getText(); + int length = text.length(); + if (length > 0) { + // Append a '*' pattern to the end of the text value if it + // does not have one already + if (text.charAt(length - 1) != '*') { + text = text + '*'; + } + // Prepend a '*' pattern to the beginning of the text value + // if it does not have one already + if (text.charAt(0) != '*') { + text = '*' + text; + } + } + // Set and update the pattern + setMatcherString(text, true); + } + }); + } + + /** + * Sets the patterns to filter out for the receiver. + * <p> + * The following characters have special meaning: ? => any character * => any string + * </p> + * + * @param pattern + * the pattern + * @param update + * <code>true</code> if the viewer should be updated + */ + private void setMatcherString(String pattern, boolean update) { + namePatternFilter.setPattern(pattern); + if (update) { + stringMatcherUpdated(); + } + } + + /** + * The string matcher has been modified. The default implementation refreshes the view and selects the first matched + * element + */ + private void stringMatcherUpdated() { + // Refresh the tree viewer to re-filter + viewer.getControl().setRedraw(false); + viewer.refresh(); + viewer.expandAll(); +// selectFirstMatch(); + viewer.getControl().setRedraw(true); + } + + protected AbstractTaskEditorPage getTaskEditorPage() { + IWorkbenchPage activePage = window.getActivePage(); + if (activePage == null) { + return null; + } + IEditorPart editorPart = activePage.getActiveEditor(); + AbstractTaskEditorPage taskEditorPage = null; + if (editorPart instanceof TaskEditor) { + TaskEditor taskEditor = (TaskEditor) editorPart; + IFormPage formPage = taskEditor.getActivePageInstance(); + if (formPage instanceof AbstractTaskEditorPage) { + taskEditorPage = (AbstractTaskEditorPage) formPage; + } + } + return taskEditorPage; + } + +// /** +// * Selects the first element in the tree which matches the current filter pattern. +// */ +// private void selectFirstMatch() { +// Tree tree = viewer.getTree(); +// Object element = findFirstMatchToPattern(tree.getItems()); +// if (element != null) { +// viewer.setSelection(new StructuredSelection(element), true); +// } else { +// viewer.setSelection(StructuredSelection.EMPTY); +// } +// } +// +// /** +// * @param items +// * @return +// */ +// private Object findFirstMatchToPattern(TreeItem[] items) { +// // Match the string pattern against labels +// ILabelProvider labelProvider = (ILabelProvider) viewer.getLabelProvider(); +// // Process each item in the tree +// for (TreeItem item : items) { +// Object element = item.getData(); +// // Return the first element if no pattern is set +// if (fStringMatcher == null) { +// return element; +// } +// // Return the element if it matches the pattern +// if (element != null) { +// String label = labelProvider.getText(element); +// if (fStringMatcher.match(label)) { +// return element; +// } +// } +// // Recursively check the elements children for a match +// element = findFirstMatchToPattern(item.getItems()); +// // Return the child element match if found +// if (element != null) { +// return element; +// } +// } +// // No match found +// return null; +// } + +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/QuickOutlineLabelProvider.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/QuickOutlineLabelProvider.java new file mode 100644 index 000000000..de2d8cdb1 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/QuickOutlineLabelProvider.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2010 Frank Becker 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: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.editors.outline; + +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorOutlineNode; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorOutlineNodeLabelProvider; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskAttributeMetaData; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.swt.graphics.Image; + +/** + * @author Frank Becker + */ +public class QuickOutlineLabelProvider extends TaskEditorOutlineNodeLabelProvider { + + @Override + public String getText(Object element) { + String result = ""; //$NON-NLS-1$ + if (element instanceof TaskData) { + TaskData node = (TaskData) element; + result = node.getTaskId(); + } else if (element instanceof TaskAttribute) { + TaskAttribute node = (TaskAttribute) element; + TaskAttributeMetaData meta = node.getMetaData(); + if (meta != null) { + String lable = meta.getLabel(); + if (lable != null) { + result = lable + " (" + node.getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } else { + if (TaskAttribute.TYPE_ATTACHMENT.equals(meta.getType())) { + result = "Attachment: " + node.getValue(); //$NON-NLS-1$ + } else if (TaskAttribute.TYPE_COMMENT.equals(meta.getType())) { + result = "Comment: " + node.getValue(); //$NON-NLS-1$ + } else { + result = "<" + node.getId() + ">"; //$NON-NLS-1$//$NON-NLS-2$ + } + } + } + } else if (element instanceof TaskEditorOutlineNode) { + result = super.getText(element); + } else if (element instanceof String) { + result = (String) element; + } + return result; + } + + @Override + public Image getImage(Object element) { + if (element instanceof TaskEditorOutlineNode) { + return super.getImage(element); + } else { + return null; + } + } + +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/ShowQuickOutlineHandler.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/ShowQuickOutlineHandler.java new file mode 100644 index 000000000..c54ea2546 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/ShowQuickOutlineHandler.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2010 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.outline; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * @author Steffen Pingel + */ +public class ShowQuickOutlineHandler extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event); + QuickOutlineDialog dialog = new QuickOutlineDialog(window); + dialog.open(); + dialog.setFocus(); + return null; + } + +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/messages.properties b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/messages.properties new file mode 100644 index 000000000..c6a363b66 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/outline/messages.properties @@ -0,0 +1 @@ +QuickOutlineDialog_Press_Esc_Info_Text=Press 'Esc' to exit the dialog. diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java index f08315bab..fffa47edf 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java @@ -89,6 +89,7 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.IRepositoryElement; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.ITask.SynchronizationState; +import org.eclipse.mylyn.tasks.core.ITaskAttachment; import org.eclipse.mylyn.tasks.core.RepositoryStatus; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.ITaskDataWorkingCopy; @@ -97,6 +98,7 @@ import org.eclipse.mylyn.tasks.core.data.TaskData; import org.eclipse.mylyn.tasks.core.data.TaskDataModel; import org.eclipse.mylyn.tasks.core.data.TaskDataModelEvent; import org.eclipse.mylyn.tasks.core.data.TaskDataModelListener; +import org.eclipse.mylyn.tasks.core.data.TaskRelation; import org.eclipse.mylyn.tasks.core.sync.SubmitJob; import org.eclipse.mylyn.tasks.core.sync.SubmitJobEvent; import org.eclipse.mylyn.tasks.core.sync.SubmitJobListener; @@ -123,6 +125,7 @@ import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PlatformUI; @@ -1033,39 +1036,14 @@ public abstract class AbstractTaskEditorPage extends TaskFormPage implements ISe ISelection selection = event.getSelection(); if (selection instanceof StructuredSelection) { Object select = ((StructuredSelection) selection).getFirstElement(); - if (select instanceof TaskEditorOutlineNode) { - TaskEditorOutlineNode node = (TaskEditorOutlineNode) select; - TaskAttribute attribute = node.getData(); - if (attribute != null) { - if (TaskAttribute.TYPE_COMMENT.equals(attribute.getMetaData().getType())) { - AbstractTaskEditorPart actionPart = getPart(ID_PART_COMMENTS); - if (actionPart != null && actionPart.getControl() instanceof ExpandableComposite) { - CommonFormUtil.setExpanded((ExpandableComposite) actionPart.getControl(), true); - if (actionPart.getControl() instanceof Section) { - Control client = ((Section) actionPart.getControl()).getClient(); - if (client instanceof Composite) { - for (Control control : ((Composite) client).getChildren()) { - // toggle subsections - if (control instanceof Section) { - CommonFormUtil.setExpanded((Section) control, true); - } - } - } - } - } - } - EditorUtil.reveal(form, attribute.getId()); - } else { - EditorUtil.reveal(form, node.getLabel()); - } - getEditor().setActivePage(getId()); - } + selectReveal(select); + getEditor().setActivePage(getId()); } } }); } if (getModel() != null) { - TaskEditorOutlineNode node = TaskEditorOutlineNode.parse(getModel().getTaskData()); + TaskEditorOutlineNode node = TaskEditorOutlineNode.parse(getModel().getTaskData(), false); outlinePage.setInput(getTaskRepository(), node); } else { outlinePage.setInput(null, null); @@ -1239,15 +1217,21 @@ public abstract class AbstractTaskEditorPage extends TaskFormPage implements ISe if (part.getControl() != null) { if (ID_PART_ACTIONS.equals(part.getPartId())) { // do not expand horizontally - GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(false, false).applyTo( - part.getControl()); + GridDataFactory.fillDefaults() + .align(SWT.FILL, SWT.FILL) + .grab(false, false) + .applyTo(part.getControl()); } else { if (part.getExpandVertically()) { - GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo( - part.getControl()); + GridDataFactory.fillDefaults() + .align(SWT.FILL, SWT.FILL) + .grab(true, true) + .applyTo(part.getControl()); } else { - GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).applyTo( - part.getControl()); + GridDataFactory.fillDefaults() + .align(SWT.FILL, SWT.TOP) + .grab(true, false) + .applyTo(part.getControl()); } } // for outline @@ -1670,4 +1654,93 @@ public abstract class AbstractTaskEditorPage extends TaskFormPage implements ISe // } // } + @Override + public boolean selectReveal(Object object) { + if (object instanceof TaskEditorOutlineNode) { + TaskEditorOutlineNode node = (TaskEditorOutlineNode) object; + TaskAttribute attribute = node.getData(); + if (attribute != null) { + if (TaskAttribute.TYPE_COMMENT.equals(attribute.getMetaData().getType())) { + AbstractTaskEditorPart actionPart = this.getPart(AbstractTaskEditorPage.ID_PART_COMMENTS); + if (actionPart != null && actionPart.getControl() instanceof ExpandableComposite) { + CommonFormUtil.setExpanded((ExpandableComposite) actionPart.getControl(), true); + if (actionPart.getControl() instanceof Section) { + Control client = ((Section) actionPart.getControl()).getClient(); + if (client instanceof Composite) { + for (Control control : ((Composite) client).getChildren()) { + // toggle subsections + if (control instanceof Section) { + CommonFormUtil.setExpanded((Section) control, true); + } + } + } + } + } + EditorUtil.reveal(this.getManagedForm().getForm(), attribute.getId()); + return true; + } else if (TaskAttribute.TYPE_ATTACHMENT.equals(attribute.getMetaData().getType())) { + AbstractTaskEditorPart actionPart = this.getPart(AbstractTaskEditorPage.ID_PART_ATTACHMENTS); + if (actionPart != null && actionPart.getControl() instanceof ExpandableComposite) { + CommonFormUtil.setExpanded((ExpandableComposite) actionPart.getControl(), true); + if (actionPart.getControl() instanceof Section) { + Control client = actionPart.getControl(); + if (client instanceof Composite) { + for (Control control : ((Composite) client).getChildren()) { + if (control instanceof Composite) { + for (Control control1 : ((Composite) control).getChildren()) { + if (control1 instanceof org.eclipse.swt.widgets.Table) { + org.eclipse.swt.widgets.Table attachmentTable = ((org.eclipse.swt.widgets.Table) control1); + TableItem[] attachments = attachmentTable.getItems(); + int index = 0; + for (TableItem attachment : attachments) { + Object data = attachment.getData(); + if (data instanceof ITaskAttachment) { + ITaskAttachment attachmentData = ((ITaskAttachment) data); + if (attachmentData.getTaskAttribute() == attribute) { + attachmentTable.deselectAll(); + attachmentTable.select(index); + IManagedForm mform = actionPart.getManagedForm(); + ScrolledForm form = mform.getForm(); + EditorUtil.focusOn(form, attachmentTable); + return true; + } + } + index++; + } + } + } + } + } + } + } + } + } else { + TaskEditorAttributePart actionPart = (TaskEditorAttributePart) this.getPart(AbstractTaskEditorPage.ID_PART_ATTRIBUTES); + Section section = actionPart.getSection(); + boolean expanded = section.isExpanded(); + if (!expanded && actionPart != null && actionPart.getControl() instanceof ExpandableComposite) { + CommonFormUtil.setExpanded((ExpandableComposite) actionPart.getControl(), true); + if (!expanded) { + CommonFormUtil.setExpanded((ExpandableComposite) actionPart.getControl(), false); + } + } + + EditorUtil.reveal(this.getManagedForm().getForm(), attribute.getId()); + return true; + } + } else { + TaskRelation taskRelation = node.getTaskRelation(); + TaskRepository taskRepository = node.getTaskRepository(); + if (taskRelation != null && taskRepository != null) { + String taskID = taskRelation.getTaskId(); + TasksUiUtil.openTask(taskRepository, taskID); + } else { + EditorUtil.reveal(this.getManagedForm().getForm(), node.getLabel()); + } + return true; + } + } + return super.selectReveal(object); + } + } |