### Eclipse Workspace Patch 1.0 #P org.eclipse.mylyn.tasks.ui Index: src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListTableSorter.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListTableSorter.java,v retrieving revision 1.38 diff -u -r1.38 TaskListTableSorter.java --- src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListTableSorter.java 5 May 2008 16:41:16 -0000 1.38 +++ src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListTableSorter.java 6 May 2008 20:47:28 -0000 @@ -12,6 +12,7 @@ import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.mylyn.internal.tasks.core.AbstractRepositoryQuery; +import org.eclipse.mylyn.internal.tasks.core.AbstractTask; import org.eclipse.mylyn.internal.tasks.core.ScheduledTaskContainer; import org.eclipse.mylyn.internal.tasks.core.UncategorizedTaskContainer; import org.eclipse.mylyn.internal.tasks.core.UnmatchedTaskContainer; @@ -35,6 +36,10 @@ private SortByIndex sortByIndex = SortByIndex.PRIORITY; + private int sortDirection2 = DEFAULT_SORT_DIRECTION; + + private SortByIndex sortByIndex2 = SortByIndex.DATE_CREATED; + private final TaskListView view; private final TaskKeyComparator taskKeyComparator = new TaskKeyComparator(); @@ -105,8 +110,7 @@ if (o2 instanceof ITaskElement || o2 instanceof AbstractRepositoryQuery) { return this.sortDirection - * ((ITaskElement) o1).getSummary().compareToIgnoreCase( - ((ITaskElement) o2).getSummary()); + * ((ITaskElement) o1).getSummary().compareToIgnoreCase(((ITaskElement) o2).getSummary()); } else { return -1; } @@ -127,30 +131,49 @@ private int compareElements(ITaskElement element1, ITaskElement element2) { if (SortByIndex.PRIORITY.equals(sortByIndex)) { - int result = this.sortDirection * element1.getPriority().compareTo(element2.getPriority()); + int result = sortByPriority(element1, element2, sortDirection); if (result != 0) { return result; } - return sortBySummary(element1, element2); + if (SortByIndex.DATE_CREATED.equals(sortByIndex2)) { + return sortByDate(element1, element2, sortDirection2); + } else { + if (SortByIndex.SUMMARY.equals(sortByIndex2)) { + return sortBySummary(element1, element2, sortDirection2); + } else { + return result; + } + } } else if (SortByIndex.DATE_CREATED.equals(sortByIndex)) { - ITask t1 = null; - ITask t2 = null; - if (element1 instanceof ITask) { - t1 = (ITask) element1; - } - if (element2 instanceof ITask) { - t2 = (ITask) element2; - } - if (t1 != null && t2 != null) { - if (t1.getCreationDate() != null) { - return t1.getCreationDate().compareTo(t2.getCreationDate()); + int result = sortByDate(element1, element2, sortDirection); + if (result != 0) { + return result; + } + if (SortByIndex.PRIORITY.equals(sortByIndex2)) { + return sortByPriority(element1, element2, sortDirection2); + } else { + if (SortByIndex.SUMMARY.equals(sortByIndex2)) { + return sortBySummary(element1, element2, sortDirection2); + } else { + return result; } } } else { - return sortBySummary(element1, element2); + int result = sortBySummary(element1, element2, sortDirection); + if (result != 0) { + return result; + } + if (SortByIndex.DATE_CREATED.equals(sortByIndex2)) { + return sortByDate(element1, element2, sortDirection2); + } else { + if (SortByIndex.PRIORITY.equals(sortByIndex2)) { + return sortByPriority(element1, element2, sortDirection2); + } else { + return result; + } + } } - return 0; } /** @@ -160,13 +183,48 @@ * @param element2 * @return sort order */ - private int sortBySummary(ITaskElement element1, ITaskElement element2) { - return this.sortDirection + private int sortBySummary(ITaskElement element1, ITaskElement element2, int sortDirection) { + return sortDirection * taskKeyComparator.compare(getSortableFromElement(element1), getSortableFromElement(element2)); } /** - * Return a sortable string in the format "key: summary" + * Determine the sort order of two tasks by priority + * + * @param element1 + * @param element2 + * @return sort order + */ + private int sortByPriority(ITaskElement element1, ITaskElement element2, int sortDirection) { + return sortDirection * element1.getPriority().compareTo(element2.getPriority()); + } + + /** + * Determine the sort order of two tasks by creation date + * + * @param element1 + * @param element2 + * @return sort order + */ + private int sortByDate(ITaskElement element1, ITaskElement element2, int sortDirection) { + AbstractTask t1 = null; + AbstractTask t2 = null; + if (element1 instanceof AbstractTask) { + t1 = (AbstractTask) element1; + } + if (element2 instanceof AbstractTask) { + t2 = (AbstractTask) element2; + } + if (t1 != null && t2 != null) { + if (t1.getCreationDate() != null) { + return sortDirection * t1.getCreationDate().compareTo(t2.getCreationDate()); + } + } + return 0; + } + + /** + * * Return a sortable string in the format "key: summary" * * @param element * @return sortable string @@ -228,4 +286,29 @@ } } + public SortByIndex getSortByIndex2() { + return sortByIndex2; + } + + public void setSortByIndex2(SortByIndex sortByIndex) { + SortByIndex oldValue = this.sortByIndex2; + this.sortByIndex2 = sortByIndex; + if (!oldValue.equals(sortByIndex)) { + view.getViewer().refresh(); + } + + } + + public int getSortDirection2() { + return sortDirection2; + } + + public void setSortDirection2(int sortDirection) { + int oldValue = this.sortDirection2; + this.sortDirection2 = sortDirection; + if (oldValue != this.sortDirection2) { + view.getViewer().refresh(); + } + } + } Index: src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListView.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListView.java,v retrieving revision 1.255 diff -u -r1.255 TaskListView.java --- src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListView.java 6 May 2008 08:30:31 -0000 1.255 +++ src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListView.java 6 May 2008 20:47:30 -0000 @@ -94,6 +94,7 @@ import org.eclipse.mylyn.internal.tasks.ui.actions.SynchronizeAutomaticallyAction; import org.eclipse.mylyn.internal.tasks.ui.actions.TaskActivateAction; import org.eclipse.mylyn.internal.tasks.ui.actions.TaskDeactivateAction; +import org.eclipse.mylyn.internal.tasks.ui.actions.TaskListSortAction; import org.eclipse.mylyn.internal.tasks.ui.editors.TaskListChangeAdapter; import org.eclipse.mylyn.internal.tasks.ui.util.TaskDragSourceListener; import org.eclipse.mylyn.internal.tasks.ui.views.TaskListTableSorter.SortByIndex; @@ -178,6 +179,8 @@ private static final String MEMENTO_KEY_SORTER = "sorter"; + private static final String MEMENTO_KEY_SORTER2 = "sorter2"; + private static final String MEMENTO_KEY_SORT_INDEX = "sortIndex"; private static final String MEMENTO_SORT_INDEX = "org.eclipse.mylyn.tasklist.ui.views.tasklist.sortIndex"; @@ -269,7 +272,7 @@ private PriorityDropDownAction filterOnPriorityAction; - private SortyByDropDownAction sortByAction; + private TaskListSortAction sortDialogAction; private PresentationDropDownSelectionAction presentationDropDownSelectionAction; @@ -649,6 +652,19 @@ } m.putInteger(MEMENTO_KEY_SORT_DIRECTION, tableSorter.getSortDirection()); + IMemento m2 = sorter.createChild(MEMENTO_KEY_SORTER2); + switch (tableSorter.getSortByIndex2()) { + case SUMMARY: + m2.putInteger(MEMENTO_KEY_SORT_INDEX, 1); + break; + case DATE_CREATED: + m2.putInteger(MEMENTO_KEY_SORT_INDEX, 2); + break; + default: + m2.putInteger(MEMENTO_KEY_SORT_INDEX, 0); + } + + m2.putInteger(MEMENTO_KEY_SORT_DIRECTION, tableSorter.getSortDirection2()); memento.putString(MEMENTO_LINK_WITH_EDITOR, Boolean.toString(linkWithEditor)); memento.putString(MEMENTO_PRESENTATION, currentPresentation.getId()); } @@ -660,6 +676,7 @@ int restoredSortIndex = 0; if (sorterMemento != null) { int sortDirection = -1; + tableSorter = new TaskListTableSorter(this); IMemento m = sorterMemento.getChild(MEMENTO_KEY_SORTER); if (m != null) { Integer sortIndexInt = m.getInteger(MEMENTO_KEY_SORT_INDEX); @@ -669,7 +686,6 @@ Integer sortDirInt = m.getInteger(MEMENTO_KEY_SORT_DIRECTION); if (sortDirInt != null) { sortDirection = sortDirInt.intValue(); - tableSorter = new TaskListTableSorter(this); tableSorter.setSortDirection(sortDirection); switch (restoredSortIndex) { case 1: @@ -683,6 +699,29 @@ } } } + + IMemento m2 = sorterMemento.getChild(MEMENTO_KEY_SORTER2); + if (m2 != null) { + Integer sortIndexInt = m2.getInteger(MEMENTO_KEY_SORT_INDEX); + if (sortIndexInt != null) { + restoredSortIndex = sortIndexInt.intValue(); + } + Integer sortDirInt = m2.getInteger(MEMENTO_KEY_SORT_DIRECTION); + if (sortDirInt != null) { + sortDirection = sortDirInt.intValue(); + tableSorter.setSortDirection2(sortDirection); + switch (restoredSortIndex) { + case 1: + tableSorter.setSortByIndex2(SortByIndex.SUMMARY); + break; + case 2: + tableSorter.setSortByIndex2(SortByIndex.DATE_CREATED); + break; + default: + tableSorter.setSortByIndex2(SortByIndex.PRIORITY); + } + } + } } applyPresentation(taskListMemento.getString(MEMENTO_PRESENTATION)); } @@ -1069,7 +1108,7 @@ manager.add(collapseAll); manager.add(expandAll); manager.add(new Separator(ID_SEPARATOR_FILTERS)); - manager.add(sortByAction); + manager.add(sortDialogAction); manager.add(filterOnPriorityAction); manager.add(filterCompleteTask); //manager.add(filterArchiveCategory); @@ -1314,7 +1353,7 @@ synchronizeAutomatically = new SynchronizeAutomaticallyAction(); openPreferencesAction = new OpenTasksUiPreferencesAction(); //filterArchiveCategory = new FilterArchiveContainerAction(this); - sortByAction = new SortyByDropDownAction(this); + sortDialogAction = new TaskListSortAction(getSite(), this); filterOnPriorityAction = new PriorityDropDownAction(this); linkWithEditorAction = new LinkWithEditorAction(this); presentationDropDownSelectionAction = new PresentationDropDownSelectionAction(this); @@ -1578,7 +1617,7 @@ } public void setManualFiltersEnabled(boolean enabled) { - sortByAction.setEnabled(enabled); + sortDialogAction.setEnabled(enabled); filterOnPriorityAction.setEnabled(enabled); filterCompleteTask.setEnabled(enabled); //filterArchiveCategory.setEnabled(enabled); Index: src/org/eclipse/mylyn/internal/tasks/ui/dialogs/TaskListSortDialog.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/ui/dialogs/TaskListSortDialog.java diff -N src/org/eclipse/mylyn/internal/tasks/ui/dialogs/TaskListSortDialog.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/ui/dialogs/TaskListSortDialog.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,266 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.dialogs; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; + +import org.eclipse.jface.window.IShellProvider; +import org.eclipse.mylyn.internal.tasks.ui.views.TaskListView; +import org.eclipse.mylyn.internal.tasks.ui.views.TaskListTableSorter.SortByIndex; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.dialogs.SelectionDialog; + +public class TaskListSortDialog extends SelectionDialog { + private Combo[] priorityCombos; + + private Button[] ascendingButtons; + + private Button[] descendingButtons; + + private final String[] propertyText; + + private boolean dirty = false; + + private final TaskListView taskListView; + + public TaskListSortDialog(IShellProvider parentShell, TaskListView taskListView) { + super(parentShell.getShell()); + propertyText = new String[3]; + propertyText[0] = "Priority"; + propertyText[1] = "Summary"; + propertyText[2] = "Date Created"; + this.taskListView = taskListView; + setTitle(TaskListView.LABEL_VIEW + " Sorting"); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + + initializeDialogUnits(composite); + + Composite prioritiesArea = new Composite(composite, SWT.NULL); + prioritiesArea.setLayout(new GridLayout(3, false)); + + Label sortByLabel = new Label(prioritiesArea, SWT.NULL); + sortByLabel.setText("Sort order:"); + GridData data = new GridData(); + data.horizontalSpan = 3; + sortByLabel.setLayoutData(data); + + ascendingButtons = new Button[2]; + descendingButtons = new Button[2]; + priorityCombos = new Combo[2]; + + for (int i = 0; i < 2; i++) { + final int index = i; + Label numberLabel = new Label(prioritiesArea, SWT.NULL); + numberLabel.setText("" + (i + 1) + "."); + priorityCombos[i] = new Combo(prioritiesArea, SWT.READ_ONLY); + priorityCombos[i].setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Composite directionGroup = new Composite(prioritiesArea, SWT.NONE); + directionGroup.setLayout(new GridLayout(2, false)); + ascendingButtons[i] = new Button(directionGroup, SWT.RADIO); + ascendingButtons[i].setText("Ascending"); + ascendingButtons[i].addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + markDirty(); + } + }); + descendingButtons[i] = new Button(directionGroup, SWT.RADIO); + descendingButtons[i].setText("Descending"); + descendingButtons[i].addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + markDirty(); + } + }); + if (i < priorityCombos.length - 1) { + priorityCombos[i].addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + int oldSelectionDirection = 1; + if (descendingButtons[index].getSelection()) { + oldSelectionDirection = -1; + } + ArrayList oldSelectionList = new ArrayList( + Arrays.asList(priorityCombos[index].getItems())); + oldSelectionList.removeAll(Arrays.asList(priorityCombos[index + 1].getItems())); + if (oldSelectionList.size() != 1) { + return; + } + String oldSelection = oldSelectionList.get(0); + String newSelection = priorityCombos[index].getItem(priorityCombos[index].getSelectionIndex()); + if (oldSelection.equals(newSelection)) { + return; + } + for (int j = index + 1; j < priorityCombos.length; j++) { + int newSelectionIndex = priorityCombos[j].indexOf(newSelection); + //this combo's current selection is equal to newSelection + if (priorityCombos[j].getSelectionIndex() == newSelectionIndex) { + priorityCombos[j].remove(newSelection); + int insertionPoint = -1 + - Arrays.binarySearch(priorityCombos[j].getItems(), oldSelection, + columnComparator); + if (insertionPoint >= 0 && insertionPoint <= priorityCombos[j].getItemCount()) { + priorityCombos[j].add(oldSelection, insertionPoint); + } else { + priorityCombos[j].add(oldSelection); + } + priorityCombos[j].select(priorityCombos[j].indexOf(oldSelection)); + ascendingButtons[index].setSelection(ascendingButtons[j].getSelection()); + descendingButtons[index].setSelection(descendingButtons[j].getSelection()); + ascendingButtons[j].setSelection(oldSelectionDirection == 1); + descendingButtons[j].setSelection(oldSelectionDirection == -1); + } + //this combo contains newSelection + else if (newSelectionIndex >= 0) { + String currentText = priorityCombos[j].getText(); + priorityCombos[j].remove(newSelection); + int insertionPoint = -1 + - Arrays.binarySearch(priorityCombos[j].getItems(), oldSelection, + columnComparator); + if (insertionPoint >= 0 && insertionPoint <= priorityCombos[j].getItemCount()) { + priorityCombos[j].add(oldSelection, insertionPoint); + priorityCombos[j].select(priorityCombos[j].indexOf(currentText)); + } else { + priorityCombos[j].add(oldSelection); + } + } + } + markDirty(); + } + }); + } else { + priorityCombos[i].addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + markDirty(); + } + }); + } + + } + int a[] = new int[2]; + int b[] = new int[2]; + switch (taskListView.getSorter().getSortByIndex()) { + case PRIORITY: + a[0] = 0; + break; + case SUMMARY: + a[0] = 1; + break; + case DATE_CREATED: + a[0] = 2; + break; + } + + switch (taskListView.getSorter().getSortByIndex2()) { + case PRIORITY: + a[1] = 0; + break; + case SUMMARY: + a[1] = 1; + break; + case DATE_CREATED: + a[1] = 2; + break; + } + b[0] = taskListView.getSorter().getSortDirection(); + b[1] = taskListView.getSorter().getSortDirection2(); + updateUI(a, b); + return composite; + } + + @Override + protected void okPressed() { + if (isDirty()) { + taskListView.getSorter() + .setSortByIndex( + SortByIndex.valueOf(priorityCombos[0].getItem(priorityCombos[0].getSelectionIndex()) + .toUpperCase())); + taskListView.getSorter() + .setSortByIndex2( + SortByIndex.valueOf(priorityCombos[1].getItem(priorityCombos[1].getSelectionIndex()) + .toUpperCase())); + if (descendingButtons[0].getSelection()) { + taskListView.getSorter().setSortDirection(-1); + } else { + taskListView.getSorter().setSortDirection(1); + } + if (descendingButtons[1].getSelection()) { + taskListView.getSorter().setSortDirection2(-1); + } else { + taskListView.getSorter().setSortDirection2(1); + } + + } + super.okPressed(); + } + + /** + * @return boolean + */ + public boolean isDirty() { + return dirty; + } + + /** + * Sets the dirty flag to true. + */ + public void markDirty() { + dirty = true; + } + + private final Comparator columnComparator = new Comparator() { + public int compare(String arg0, String arg1) { + int index0 = -1; + int index1 = -1; + for (int i = 0; i < propertyText.length; i++) { + if (propertyText[i].equals(arg0)) { + index0 = i; + } + if (propertyText[i].equals(arg1)) { + index1 = i; + } + } + return index0 - index1; + } + }; + + private void updateUI(int[] priorities, int[] directions) { + ArrayList availablePriorities = new ArrayList(Arrays.asList(propertyText)); + + for (int i = 0; i < priorityCombos.length; i++) { + priorityCombos[i].removeAll(); + for (int j = 0; j < availablePriorities.size(); j++) { + priorityCombos[i].add(availablePriorities.get(j)); + } + priorityCombos[i].select(priorityCombos[i].indexOf(propertyText[priorities[i]])); + availablePriorities.remove(propertyText[priorities[i]]); + + ascendingButtons[i].setSelection(directions[i] == 1); + descendingButtons[i].setSelection(directions[i] == -1); + } + } + +} Index: src/org/eclipse/mylyn/internal/tasks/ui/actions/TaskListSortAction.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/ui/actions/TaskListSortAction.java diff -N src/org/eclipse/mylyn/internal/tasks/ui/actions/TaskListSortAction.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/ui/actions/TaskListSortAction.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.actions; + +import org.eclipse.jface.action.Action; +import org.eclipse.mylyn.internal.tasks.ui.dialogs.TaskListSortDialog; +import org.eclipse.mylyn.internal.tasks.ui.views.TaskListView; +import org.eclipse.ui.IWorkbenchPartSite; + +public class TaskListSortAction extends Action { + + private final TaskListSortDialog dialog; + + public TaskListSortAction(IWorkbenchPartSite site, TaskListView taskListView) { + super("Sort..."); + setEnabled(true); + dialog = new TaskListSortDialog(site, taskListView); + } + + @Override + public void run() { + dialog.open(); + } + +}