Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 175655 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/mylyn/internal/context/ui/Messages.java (+4 lines)
Lines 40-43 Link Here
40
	public static String AbstractFocusViewAction_Apply_Mylyn;
40
	public static String AbstractFocusViewAction_Apply_Mylyn;
41
41
42
	public static String AbstractFocusViewAction_Empty_task_context;
42
	public static String AbstractFocusViewAction_Empty_task_context;
43
44
	public static String FilteredChildrenDecorationDrawer_No_Filtered_Children;
45
46
	public static String FilteredChildrenDecorationDrawer_Show_Filtered_Children;
43
}
47
}
(-)src/org/eclipse/mylyn/internal/context/ui/BrowseFilteredListener.java (-1 / +16 lines)
Lines 42-47 Link Here
42
42
43
	private final StructuredViewer viewer;
43
	private final StructuredViewer viewer;
44
44
45
	private boolean wasExternalClick = false;
46
45
	public BrowseFilteredListener(StructuredViewer viewer) {
47
	public BrowseFilteredListener(StructuredViewer viewer) {
46
		this.viewer = viewer;
48
		this.viewer = viewer;
47
	}
49
	}
Lines 78-83 Link Here
78
		}
80
		}
79
	}
81
	}
80
82
83
	public void setWasExternalClick(boolean wasExternalClick) {
84
		this.wasExternalClick = wasExternalClick;
85
	}
86
81
	public void keyPressed(KeyEvent event) {
87
	public void keyPressed(KeyEvent event) {
82
		// ignore
88
		// ignore
83
	}
89
	}
Lines 130-137 Link Here
130
			unfilter(filter, treeViewer, selectedObject);
136
			unfilter(filter, treeViewer, selectedObject);
131
		} else {
137
		} else {
132
			if (event.button == 1) {
138
			if (event.button == 1) {
133
				if ((event.stateMask & SWT.MOD1) != 0) {
139
				if ((event.stateMask & SWT.MOD1) != 0 || wasExternalClick) {
134
					viewer.refresh(selectedObject);
140
					viewer.refresh(selectedObject);
141
					wasExternalClick = false;
135
				} else {
142
				} else {
136
					final Object unfiltered = filter.getLastTemporarilyUnfiltered();
143
					final Object unfiltered = filter.getLastTemporarilyUnfiltered();
137
					if (unfiltered != null) {
144
					if (unfiltered != null) {
Lines 187-190 Link Here
187
		}
194
		}
188
		return null;
195
		return null;
189
	}
196
	}
197
198
	public boolean isUnfiltered(Object object) {
199
		InterestFilter interestFilter = getInterestFilter(viewer);
200
		if (interestFilter != null) {
201
			return interestFilter.isTemporarilyUnfiltered(object);
202
		}
203
		return false;
204
	}
190
}
205
}
(-)src/org/eclipse/mylyn/internal/context/ui/FocusedViewerManager.java (-3 / +32 lines)
Lines 199-207 Link Here
199
		}
199
		}
200
	}
200
	}
201
201
202
	private final Map<TreeViewer, FilteredChildrenDecorationDrawer> decorationMap = new HashMap<TreeViewer, FilteredChildrenDecorationDrawer>();
203
204
	private void removeFilterDecorations(StructuredViewer viewer) {
205
		if (viewer instanceof TreeViewer) {
206
			TreeViewer treeViewer = (TreeViewer) viewer;
207
208
			FilteredChildrenDecorationDrawer filterViewDrawer = decorationMap.remove(treeViewer);
209
			if (filterViewDrawer != null) {
210
				filterViewDrawer.dispose();
211
			}
212
		}
213
	}
214
215
	private void addFilterDecorations(StructuredViewer viewer, BrowseFilteredListener listener) {
216
		if (viewer instanceof TreeViewer) {
217
			TreeViewer treeViewer = (TreeViewer) viewer;
218
			FilteredChildrenDecorationDrawer filteredViewDrawer = new FilteredChildrenDecorationDrawer(treeViewer,
219
					listener);
220
			decorationMap.put(treeViewer, filteredViewDrawer);
221
			filteredViewDrawer.applyToTreeViewer();
222
223
		}
224
	}
225
202
	public void removeManagedViewer(StructuredViewer viewer, IWorkbenchPart viewPart) {
226
	public void removeManagedViewer(StructuredViewer viewer, IWorkbenchPart viewPart) {
203
		managedViewers.remove(viewer);
227
		managedViewers.remove(viewer);
204
		partToViewerMap.remove(viewPart);
228
		partToViewerMap.remove(viewPart);
229
		removeFilterDecorations(viewer);
205
		BrowseFilteredListener listener = listenerMap.get(viewer);
230
		BrowseFilteredListener listener = listenerMap.get(viewer);
206
		if (listener != null && viewer != null && !viewer.getControl().isDisposed()) {
231
		if (listener != null && viewer != null && !viewer.getControl().isDisposed()) {
207
			viewer.getControl().removeMouseListener(listener);
232
			viewer.getControl().removeMouseListener(listener);
Lines 214-219 Link Here
214
		if (viewer != null && action != null) {
239
		if (viewer != null && action != null) {
215
			focusActions.put(viewer, action);
240
			focusActions.put(viewer, action);
216
		}
241
		}
242
		BrowseFilteredListener listener = listenerMap.get(viewer);
243
		if (listener != null) {
244
			addFilterDecorations(viewer, listener);
245
		}
217
	}
246
	}
218
247
219
	@Deprecated
248
	@Deprecated
Lines 224-229 Link Here
224
	}
253
	}
225
254
226
	public void removeFilteredViewer(StructuredViewer viewer) {
255
	public void removeFilteredViewer(StructuredViewer viewer) {
256
		removeFilterDecorations(viewer);
227
		focusActions.remove(viewer);
257
		focusActions.remove(viewer);
228
		filteredViewers.remove(viewer);
258
		filteredViewers.remove(viewer);
229
	}
259
	}
Lines 368-376 Link Here
368
		if (viewer instanceof TreeViewer
398
		if (viewer instanceof TreeViewer
369
				&& filteredViewers.contains(viewer)
399
				&& filteredViewers.contains(viewer)
370
				&& hasInterestFilter(viewer, true)
400
				&& hasInterestFilter(viewer, true)
371
				&& ContextUiPlugin.getDefault()
401
				&& ContextUiPlugin.getDefault().getPreferenceStore().getBoolean(
372
						.getPreferenceStore()
402
						IContextUiPreferenceContstants.AUTO_MANAGE_EXPANSION)) {
373
						.getBoolean(IContextUiPreferenceContstants.AUTO_MANAGE_EXPANSION)) {
374
			TreeViewer treeViewer = (TreeViewer) viewer;
403
			TreeViewer treeViewer = (TreeViewer) viewer;
375
404
376
			// HACK to fix bug 278569: [context] errors with Markers view and active Mylyn task
405
			// HACK to fix bug 278569: [context] errors with Markers view and active Mylyn task
(-)src/org/eclipse/mylyn/internal/context/ui/messages.properties (+2 lines)
Lines 18-20 Link Here
18
18
19
AbstractFocusViewAction_Apply_Mylyn=Apply Mylyn
19
AbstractFocusViewAction_Apply_Mylyn=Apply Mylyn
20
AbstractFocusViewAction_Empty_task_context=Empty task context, unfocus or Alt+click
20
AbstractFocusViewAction_Empty_task_context=Empty task context, unfocus or Alt+click
21
FilteredChildrenDecorationDrawer_No_Filtered_Children=No Filtered Children
22
FilteredChildrenDecorationDrawer_Show_Filtered_Children=Show Filtered Children (Alt+click)
(-)src/org/eclipse/mylyn/context/ui/InterestFilter.java (-1 / +4 lines)
Lines 144-150 Link Here
144
//		}
144
//		}
145
	}
145
	}
146
146
147
	private boolean isTemporarilyUnfiltered(Object parent) {
147
	/**
148
	 * @since 3.5
149
	 */
150
	public boolean isTemporarilyUnfiltered(Object parent) {
148
		if (parent instanceof TreePath) {
151
		if (parent instanceof TreePath) {
149
			TreePath treePath = (TreePath) parent;
152
			TreePath treePath = (TreePath) parent;
150
			parent = treePath.getLastSegment();
153
			parent = treePath.getLastSegment();
(-)src/org/eclipse/mylyn/internal/context/ui/FilteredChildrenDecorationDrawer.java (+289 lines)
Added Link Here
1
package org.eclipse.mylyn.internal.context.ui;
2
3
import org.eclipse.jface.viewers.StructuredSelection;
4
import org.eclipse.jface.viewers.TreeViewer;
5
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages;
6
import org.eclipse.mylyn.internal.provisional.commons.ui.WorkbenchUtil;
7
import org.eclipse.swt.SWT;
8
import org.eclipse.swt.events.MouseEvent;
9
import org.eclipse.swt.events.MouseListener;
10
import org.eclipse.swt.events.MouseMoveListener;
11
import org.eclipse.swt.events.MouseTrackListener;
12
import org.eclipse.swt.graphics.Image;
13
import org.eclipse.swt.graphics.Point;
14
import org.eclipse.swt.graphics.Rectangle;
15
import org.eclipse.swt.widgets.Event;
16
import org.eclipse.swt.widgets.Listener;
17
import org.eclipse.swt.widgets.ToolTip;
18
import org.eclipse.swt.widgets.Tree;
19
import org.eclipse.swt.widgets.TreeItem;
20
21
/**
22
 * @author Mik Kersten
23
 */
24
25
public class FilteredChildrenDecorationDrawer implements Listener {
26
27
	private final class MoveListener implements MouseMoveListener, MouseListener, MouseTrackListener {
28
29
		private TreeItem lastItem;
30
31
		private final TreeViewer viewer;
32
33
		private final BrowseFilteredListener browseFilteredListener;
34
35
		private final ToolTip toolTip;
36
37
		public MoveListener(TreeViewer viewer, BrowseFilteredListener browseFilteredListener) {
38
			this.viewer = viewer;
39
			this.browseFilteredListener = browseFilteredListener;
40
			toolTip = new ToolTip(WorkbenchUtil.getShell(), SWT.NONE);
41
		}
42
43
		public void mouseEnter(MouseEvent e) {
44
			mouseMove(e);
45
		}
46
47
		public void mouseExit(MouseEvent e) {
48
			if (lastItem != null && !lastItem.isDisposed()) {
49
				lastItem.setData(ID_HOVER, NodeState.LESS);
50
			}
51
			if (toolTip != null && !toolTip.isDisposed()) {
52
				toolTip.setVisible(false);
53
			}
54
55
			lastItem = null;
56
			redrawTree();
57
		}
58
59
		private void redrawTree() {
60
			if (viewer.getTree() != null && !viewer.getTree().isDisposed()) {
61
				viewer.getTree().redraw();
62
			}
63
		}
64
65
		public void mouseHover(MouseEvent e) {
66
67
			if (toolTip != null && !toolTip.isDisposed()) {
68
				Tree tree = (Tree) e.widget;
69
				TreeItem item = findItem(tree, e.y);
70
				if (item != null && !item.isDisposed()) {
71
					Object data = item.getData(ID_HOVER);
72
					if (data == NodeState.MORE) {
73
						toolTip.setText(Messages.FilteredChildrenDecorationDrawer_Show_Filtered_Children);
74
					} else {
75
						toolTip.setText(Messages.FilteredChildrenDecorationDrawer_No_Filtered_Children);
76
					}
77
					if (inImageBounds(tree, item, e)) {
78
						toolTip.setVisible(true);
79
					}
80
				}
81
			}
82
		}
83
84
		private boolean inImageBounds(Tree tree, TreeItem item, MouseEvent e) {
85
			boolean shouldUnfilter = false;
86
			int selectedX = e.x;
87
88
			int imageStartX = item.getBounds().x + item.getBounds().width + IMAGE_PADDING;
89
90
			Rectangle clientArea = tree.getClientArea();
91
			int currentTreeBounds = clientArea.x + clientArea.width;
92
			if (imageStartX > currentTreeBounds) {
93
				imageStartX = currentTreeBounds - moreImage.getBounds().width;
94
			}
95
96
			int imageEndX = imageStartX + moreImage.getBounds().width;
97
98
			return selectedX > imageStartX && selectedX < imageEndX;
99
		}
100
101
		public void mouseMove(MouseEvent e) {
102
			if (toolTip != null && !toolTip.isDisposed()) {
103
				toolTip.setVisible(false);
104
			}
105
106
			if (!(e.widget instanceof Tree) || e.widget.isDisposed()) {
107
				return;
108
			}
109
			Tree tree = (Tree) e.widget;
110
			TreeItem item = findItem(tree, e.y);
111
			if (item != null && !item.isDisposed()) {
112
				if (lastItem != null && !lastItem.isDisposed() && !lastItem.equals(item)) {
113
					lastItem.setData(ID_HOVER, NodeState.LESS);
114
				}
115
116
				Object data = item.getData(ID_HAS_CHILDREN);
117
				if (data == null || data == Boolean.TRUE) {
118
					item.setData(ID_HOVER, NodeState.MORE);
119
				} else {
120
					item.setData(ID_HOVER, NodeState.LESS);
121
				}
122
				if (lastItem == null || (!lastItem.isDisposed() && !lastItem.equals(item))) {
123
					redrawTree();
124
				}
125
				lastItem = item;
126
			} else {
127
				if (lastItem != null && !lastItem.isDisposed() && !lastItem.equals(item)) {
128
					lastItem.setData(ID_HOVER, NodeState.LESS);
129
					redrawTree();
130
				}
131
				lastItem = item;
132
			}
133
		}
134
135
		public void dispose() {
136
			if (toolTip != null && !toolTip.isDisposed()) {
137
				toolTip.dispose();
138
			}
139
		}
140
141
		public void mouseDoubleClick(MouseEvent e) {
142
			// ignore
143
144
		}
145
146
		public void mouseDown(MouseEvent e) {
147
			if (toolTip != null && !toolTip.isDisposed()) {
148
				toolTip.setVisible(false);
149
			}
150
151
			if (!(e.widget instanceof Tree) || e.widget.isDisposed()) {
152
				// we only handle tree's
153
				return;
154
			}
155
156
			Tree tree = (Tree) e.widget;
157
			TreeItem item = findItem(tree, e.y);
158
159
			if (item == null || item.isDisposed()) {
160
				// we can't do anything if we cant find the tree items
161
				return;
162
			}
163
164
			int prevNumberItems = item.getItemCount();
165
			boolean wasUnfiltered = browseFilteredListener.isUnfiltered(item.getData());
166
			if (inImageBounds(tree, item, e)) {
167
				browseFilteredListener.setWasExternalClick(true);
168
				browseFilteredListener.unfilterSelection(viewer, new StructuredSelection(item.getData()));
169
			}
170
			int newNumItems = item.getItemCount();
171
			if (newNumItems == prevNumberItems && !wasUnfiltered) {
172
				item.setData(ID_HOVER, NodeState.MORE_ERROR);
173
				item.setData(ID_HAS_CHILDREN, Boolean.FALSE);
174
				redrawTree();
175
			}
176
		}
177
178
		public void mouseUp(MouseEvent e) {
179
			// ignore
180
181
		}
182
	}
183
184
	private static final int SCROLL_BAR_OFFSET = 15;
185
186
	private static final int IMAGE_PADDING = 5;
187
188
	// XXX Update Images
189
	private final Image moreImage = CommonImages.getImage(CommonImages.EXPAND_ALL);
190
191
	private final Image moreErrorImage = CommonImages.getImage(CommonImages.REMOVE);
192
193
	enum NodeState {
194
		MORE, LESS, MORE_ERROR
195
	};
196
197
	private static final String ID_HOVER = "mylyn-context-hover"; //$NON-NLS-1$
198
199
	private static final String ID_HAS_CHILDREN = "mylyn-context-has-children"; //$NON-NLS-1$
200
201
	private final TreeViewer treeViewer;
202
203
	private MoveListener listener;
204
205
	private final BrowseFilteredListener browseFilteredListener;
206
207
	public FilteredChildrenDecorationDrawer(TreeViewer treeViewer, BrowseFilteredListener browseFilteredListener) {
208
		this.treeViewer = treeViewer;
209
		this.browseFilteredListener = browseFilteredListener;
210
	}
211
212
	public void applyToTreeViewer() {
213
		if (treeViewer.getTree() != null && !treeViewer.getTree().isDisposed()) {
214
			treeViewer.getTree().addListener(SWT.PaintItem, this);
215
216
			listener = new MoveListener(treeViewer, browseFilteredListener);
217
			treeViewer.getTree().addMouseMoveListener(listener);
218
			treeViewer.getTree().addMouseListener(listener);
219
			treeViewer.getTree().addMouseTrackListener(listener);
220
		}
221
	}
222
223
	public void dispose() {
224
		if (treeViewer.getTree() == null || treeViewer.getTree().isDisposed()) {
225
			return;
226
		}
227
		treeViewer.getTree().removeListener(SWT.PaintItem, this);
228
229
		if (listener != null) {
230
			treeViewer.getTree().removeMouseMoveListener(listener);
231
			treeViewer.getTree().removeMouseListener(listener);
232
			treeViewer.getTree().removeMouseTrackListener(listener);
233
			listener.dispose();
234
		}
235
	}
236
237
	/*
238
	 * NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
239
	 * Therefore, it is critical for performance that these methods be as
240
	 * efficient as possible.
241
	 */
242
	public void handleEvent(Event event) {
243
244
		if (!(event.widget instanceof Tree)) {
245
			// we only handle tree's
246
			return;
247
		}
248
249
		switch (event.type) {
250
		case SWT.PaintItem: {
251
			Tree tree = (Tree) event.widget;
252
			if (tree.isDisposed()) {
253
				return;
254
			}
255
			TreeItem item = findItem(tree, event.y);
256
			if (item == null || item.isDisposed()) {
257
				return;
258
			}
259
260
			int imageStartX = event.x + event.width + IMAGE_PADDING;
261
262
			Rectangle clientArea = tree.getClientArea();
263
			int currentTreeBounds = clientArea.x + clientArea.width;
264
			if (imageStartX > currentTreeBounds) {
265
				imageStartX = currentTreeBounds - moreImage.getBounds().width;
266
			}
267
268
			NodeState value = (NodeState) item.getData(ID_HOVER);
269
			if (value != null && value.equals(NodeState.MORE)) {
270
				event.gc.drawImage(moreImage, imageStartX, event.y);
271
			} else if (value != null && value.equals(NodeState.MORE_ERROR)) {
272
				event.gc.drawImage(moreErrorImage, imageStartX, event.y);
273
			}
274
			break;
275
		}
276
		}
277
	}
278
279
	private TreeItem findItem(Tree tree, int y) {
280
		TreeItem item = null;
281
		Point size = tree.getSize();
282
		final int RATE = 17;
283
		for (int i = 0; i <= RATE && item == null; i++) {
284
			int position = size.x / RATE + (i * size.x / RATE);
285
			item = tree.getItem(new Point(position, y));
286
		}
287
		return item;
288
	}
289
}

Return to bug 175655