View | Details | Raw Unified | Return to bug 188333 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jface/viewers/SimpleStyledCellLabelProvider.java (+484 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jface.viewers;
12
13
import org.eclipse.core.runtime.Assert;
14
import org.eclipse.jface.window.Window;
15
import org.eclipse.swt.SWT;
16
import org.eclipse.swt.custom.StyleRange;
17
import org.eclipse.swt.graphics.Color;
18
import org.eclipse.swt.graphics.Font;
19
import org.eclipse.swt.graphics.GC;
20
import org.eclipse.swt.graphics.Image;
21
import org.eclipse.swt.graphics.Rectangle;
22
import org.eclipse.swt.graphics.TextLayout;
23
import org.eclipse.swt.widgets.Display;
24
import org.eclipse.swt.widgets.Event;
25
import org.eclipse.swt.widgets.Item;
26
import org.eclipse.swt.widgets.TableItem;
27
import org.eclipse.swt.widgets.TreeItem;
28
29
/**
30
 * A {@link SimpleStyledCellLabelProvider} supports styled labels by using owner
31
 * draw by preserving native viewer behavior:
32
 * <ul>
33
 * <li>similar image and label positioning</li>
34
 * <li>native drawing of focus and selection</li>
35
 * </ul>
36
 * 
37
 * 
38
 * <p>
39
 * For providing the label's styles, create a subclass and overwrite
40
 * {@link SimpleStyledCellLabelProvider#getLabelPresentationInfo(Object)} to
41
 * return all information needed to render a element.
42
 * </p>
43
 * <p>
44
 * The {@link SimpleStyledCellLabelProvider} will ignore all font settings on
45
 * {@link StyleRange}. Different fonts would make labels wider, and the native
46
 * selection drawing could not be reused.
47
 * </p>
48
 * 
49
 * <p>
50
 * To set up styled labels for your viewer's control, you must call
51
 * {@link OwnerDrawLabelProvider#setUpOwnerDraw(ColumnViewer)}.
52
 * </p>
53
 * 
54
 * <p><strong>NOTE:</strong> This API is experimental and may be deleted or
55
 * changed before 3.4 is released.</p>
56
 * 
57
 * @since 3.4
58
 */
59
public abstract class SimpleStyledCellLabelProvider extends
60
		OwnerDrawLabelProvider {
61
62
	/**
63
	 * Holds all information used to render a styled element.
64
	 */
65
	public static class LabelPresentationInfo {
66
67
		private final String text;
68
		private final Image image;
69
		private final StyleRange[] ranges;
70
71
		private final Font defaultFont;
72
		private final Color defaultForegroundColor;
73
		private final Color defaultBackgroundColor;
74
75
		/**
76
		 * Creates a {@link SimpleStyledCellLabelProvider.LabelPresentationInfo}.
77
		 * 
78
		 * @param text
79
		 *            the text of the current element
80
		 * @param ranges
81
		 *            the styled ranges for the element
82
		 * @param image
83
		 *            the image for the element or <code>null</code>
84
		 * @param defaultFont
85
		 *            the default font for the element or <code>null</code>
86
		 * @param defaultForegroundColor
87
		 *            the default foreground color for the element or
88
		 *            <code>null</code>
89
		 * @param defaultBackgroundColor
90
		 *            the default background color for the element or
91
		 *            <code>null</code>
92
		 */
93
		public LabelPresentationInfo(String text, StyleRange[] ranges,
94
				Image image, Font defaultFont, Color defaultForegroundColor,
95
				Color defaultBackgroundColor) {
96
			Assert.isNotNull(text);
97
			Assert.isNotNull(ranges);
98
			this.text = text;
99
			this.ranges = ranges;
100
			this.image = image;
101
			this.defaultFont = defaultFont;
102
			this.defaultForegroundColor = defaultForegroundColor;
103
			this.defaultBackgroundColor = defaultBackgroundColor;
104
		}
105
106
		/**
107
		 * Provides the text of the current element.
108
		 * 
109
		 * @return returns the text.
110
		 */
111
		public String getText() {
112
			return this.text;
113
		}
114
115
		/**
116
		 * Provides the styled ranges that can be applied to the text provided
117
		 * by {@link #getText()}. The {@link SimpleStyledCellLabelProvider}
118
		 * will ignore all font settings.
119
		 * 
120
		 * @return the styled ranges for the element
121
		 */
122
		public StyleRange[] getStyleRanges() {
123
			return this.ranges;
124
		}
125
126
		/**
127
		 * Provides the image of the current element.
128
		 * 
129
		 * @return returns the image.
130
		 */
131
		public Image getImage() {
132
			return this.image;
133
		}
134
135
		/**
136
		 * Provides a default background color of the current element, which is
137
		 * used for the part of the label where no background color is specified
138
		 * in the StyleRanges provided by {@link #getStyleRanges}.
139
		 * 
140
		 * @return the background color for the element, or <code>null</code>
141
		 *         to use the default background color
142
		 */
143
		public Color getDefaultBackground() {
144
			return this.defaultBackgroundColor;
145
		}
146
147
		/**
148
		 * Provides a default font of the current element.
149
		 * 
150
		 * @return the font for the element, or <code>null</code> to use the
151
		 *         default font
152
		 */
153
		public Font getDefaultFont() {
154
			return this.defaultFont;
155
		}
156
157
		/**
158
		 * Provides a default foreground color of the current element, which is
159
		 * used for the part of the label where no foreground color is specified
160
		 * in the StyleRanges provided by {@link #getStyleRanges}.
161
		 * 
162
		 * @return the foreground color for the element, or <code>null</code>
163
		 *         to use the default foreground color
164
		 */
165
		public Color getDefaultForeground() {
166
			return this.defaultForegroundColor;
167
		}
168
169
	}
170
171
	private static final String KEY_TEXT_LAYOUT = "styled_label_key_"; //$NON-NLS-1$
172
173
	/**
174
	 * Style constant for indicating that the styled colors are to be applied
175
	 * even it the viewer's item is selected. Default is not to apply colors.
176
	 */
177
	public static final int COLORS_ON_SELECTION = 1 << 0;
178
179
	/**
180
	 * Style constant for indicating to draw the focus if requested by the owner
181
	 * draw event. Default is to draw the focus.
182
	 */
183
	public static final int NO_FOCUS = 1 << 1;
184
185
	private final int style;
186
187
	private TextLayout cachedTextLayout; // reused text layout for
188
											// 'cachedLabelInfo'
189
	private LabelPresentationInfo cachedLabelInfo;
190
	private boolean cachedWasWithColors;
191
192
	/**
193
	 * Creates a new StyledCellLabelProvider. The label provider does not apply
194
	 * colors on selection.
195
	 */
196
	public SimpleStyledCellLabelProvider() {
197
		this(0);
198
	}
199
200
	/**
201
	 * Creates a new StyledCellLabelProvider.
202
	 * 
203
	 * @param style
204
	 *            the style bits
205
	 * @see SimpleStyledCellLabelProvider#COLORS_ON_SELECTION
206
	 * @see SimpleStyledCellLabelProvider#NO_FOCUS
207
	 */
208
	public SimpleStyledCellLabelProvider(int style) {
209
		this.style = style;
210
	}
211
212
	/**
213
	 * Returns a {@link LabelPresentationInfo} instance containing the text,
214
	 * image and style information to use for displaying element.
215
	 * 
216
	 * @param element
217
	 *            the element to create a presentation info for
218
	 * @return the presentation info
219
	 */
220
	protected abstract LabelPresentationInfo getLabelPresentationInfo(
221
			Object element);
222
223
	/*
224
	 * (non-Javadoc)
225
	 * 
226
	 * @see org.eclipse.jface.viewers.BaseLabelProvider#dispose()
227
	 */
228
	public void dispose() {
229
		if (this.cachedTextLayout != null) {
230
			cachedTextLayout.dispose();
231
			cachedTextLayout = null;
232
		}
233
		cachedLabelInfo = null;
234
	}
235
236
	/*
237
	 * (non-Javadoc)
238
	 * 
239
	 * @see org.eclipse.jface.viewers.OwnerDrawLabelProvider#update(org.eclipse.jface.viewers.ViewerCell)
240
	 */
241
	public void update(ViewerCell cell) {
242
		LabelPresentationInfo info = getLabelPresentationInfo(cell.getElement());
243
		cell.getItem().setData(KEY_TEXT_LAYOUT + cell.getColumnIndex(), info); // store it in the item
244
														// to avoid
245
														// recomputation
246
247
		cell.setImage(info.getImage()); // seems to be necessary so that
248
										// item.getText/ImageBounds work
249
		cell.setText(info.getText());
250
		cell.setFont(info.getDefaultFont());
251
252
		super.update(cell);
253
	}
254
255
	private TextLayout getSharedTextLayout(Display display) {
256
		if (cachedTextLayout == null) {
257
			cachedTextLayout = new TextLayout(display);
258
			cachedTextLayout.setOrientation(Window.getDefaultOrientation());
259
		}
260
		return cachedTextLayout;
261
	}
262
263
	private boolean useColors(Event event) {
264
		return (event.detail & SWT.SELECTED) == 0
265
				|| (this.style & COLORS_ON_SELECTION) != 0;
266
	}
267
268
	private boolean drawFocus(Event event) {
269
		return (event.detail & SWT.FOCUSED) != 0
270
				&& (this.style & NO_FOCUS) == 0;
271
	}
272
273
	/**
274
	 * Returns a {@link LabelPresentationInfo} instance for the given event.
275
	 * 
276
	 * @param event
277
	 *            the measure or paint event for which a TextLayout is needed
278
	 * @param element
279
	 *            the model element
280
	 * @return a TextLayout instance
281
	 */
282
	private LabelPresentationInfo getLabelPresentationInfo(Event event,
283
			Object element) {
284
285
		// cache the label info in the data as owner draw labels are requested
286
		// in a high rate
287
		LabelPresentationInfo labelInfo = (LabelPresentationInfo) event.item
288
				.getData(KEY_TEXT_LAYOUT + event.index);
289
		if (labelInfo == null) {
290
			labelInfo = getLabelPresentationInfo(element);
291
			event.item.setData(KEY_TEXT_LAYOUT + event.index, labelInfo);
292
		}
293
		return labelInfo;
294
	}
295
296
	/**
297
	 * Returns a {@link TextLayout} instance for the given
298
	 * {@link LabelPresentationInfo}. The text layout instance is managed by
299
	 * the label provider. Caller of the method must not dispose the text
300
	 * layout.
301
	 * 
302
	 * @param diplay
303
	 *            the current display
304
	 * @param labelPresentation
305
	 *            the viewerLabel the label info
306
	 * 
307
	 * @param applyColors
308
	 *            if set, create colors in the result
309
	 * @param element
310
	 *            the model element
311
	 * @return a TextLayout instance
312
	 */
313
	private TextLayout getTextLayoutForInfo(Display display,
314
			LabelPresentationInfo labelPresentation, boolean applyColors) {
315
		// can use cache?
316
		if (cachedLabelInfo == labelPresentation
317
				&& applyColors == cachedWasWithColors) {
318
			return cachedTextLayout; // use cached layout
319
		}
320
321
		TextLayout sharedLayout = getSharedTextLayout(display);
322
		applyInfoToLayout(sharedLayout, labelPresentation, applyColors);
323
324
		cachedLabelInfo = labelPresentation;
325
		cachedWasWithColors = applyColors;
326
327
		return sharedLayout;
328
	}
329
330
	/**
331
	 * Fills the given text layout with the styles, text and font of the label
332
	 * info.
333
	 * 
334
	 * @param layout
335
	 *            the text layout to fill
336
	 * @param labelInfo
337
	 *            the viewer label
338
	 * @param applyColors
339
	 *            is set, colors will be used
340
	 */
341
	private void applyInfoToLayout(TextLayout layout,
342
			LabelPresentationInfo labelInfo, boolean applyColors) {
343
		layout.setText(""); // make sure no previous ranges are kept //$NON-NLS-1$
344
		layout.setText(labelInfo.getText());
345
		layout.setFont(labelInfo.getDefaultFont()); // set also if null to clear
346
													// previous usages
347
348
		StyleRange[] styleRanges = labelInfo.getStyleRanges();
349
350
		for (int i = 0; i < styleRanges.length; i++) {
351
			StyleRange curr = styleRanges[i];
352
353
			// if no colors apply or font is set, create a clone and clear the
354
			// colors and font
355
			if (curr.font != null || !applyColors
356
					&& (curr.foreground != null || curr.background != null)) {
357
				curr = (StyleRange) curr.clone();
358
				curr.font = null;
359
				if (!applyColors) {
360
					curr.foreground = null;
361
					curr.background = null;
362
				}
363
			}
364
			layout.setStyle(curr, curr.start, curr.start + curr.length - 1);
365
		}
366
	}
367
368
	/**
369
	 * Handle the erase event. The default implementation does nothing to ensure
370
	 * keep native selection highlighting working.
371
	 * 
372
	 * @param event
373
	 *            the erase event
374
	 * @param element
375
	 *            the model object
376
	 * @see SWT#EraseItem
377
	 */
378
	protected void erase(Event event, Object element) {
379
		event.detail &= ~SWT.FOREGROUND;
380
	}
381
382
	/*
383
	 * (non-Javadoc)
384
	 * 
385
	 * @see org.eclipse.jface.viewers.OwnerDrawLabelProvider#measure(org.eclipse.swt.widgets.Event,
386
	 *      java.lang.Object)
387
	 */
388
	protected void measure(Event event, Object element) {
389
		// use native measuring
390
	}
391
392
	/*
393
	 * (non-Javadoc)
394
	 * 
395
	 * @see org.eclipse.jface.viewers.OwnerDrawLabelProvider#paint(org.eclipse.swt.widgets.Event,
396
	 *      java.lang.Object)
397
	 */
398
	protected void paint(Event event, Object element) {
399
		LabelPresentationInfo labelInfo = getLabelPresentationInfo(event,
400
				element);
401
402
		boolean applyColors = useColors(event);
403
		GC gc = event.gc;
404
		Color oldForeground = gc.getForeground(); // remember colors to
405
													// restore the GC later
406
		Color oldBackground = gc.getBackground();
407
408
		if (applyColors) {
409
			Color foreground = labelInfo.getDefaultForeground();
410
			if (foreground != null) {
411
				gc.setForeground(foreground);
412
			}
413
			Color background = labelInfo.getDefaultBackground();
414
			if (background != null) {
415
				gc.setBackground(background);
416
			}
417
		}
418
419
		Image image = labelInfo.getImage();
420
		if (image != null) {
421
			Rectangle imageBounds = getImageBounds(event);
422
			Rectangle bounds = image.getBounds();
423
424
			// center the image in the given space
425
			int x = imageBounds.x
426
					+ Math.max(0, (imageBounds.width - bounds.width) / 2);
427
			int y = imageBounds.y
428
					+ Math.max(0, (imageBounds.height - bounds.height) / 2);
429
			gc.drawImage(image, x, y);
430
		}
431
432
		TextLayout textLayout = getTextLayoutForInfo(event.display, labelInfo,
433
				applyColors);
434
435
		Rectangle layoutBounds = textLayout.getBounds();
436
		Rectangle textBounds = getTextBounds(event);
437
438
		int x = textBounds.x;
439
		int y = textBounds.y
440
				+ Math.max(0, (textBounds.height - layoutBounds.height) / 2);
441
442
		textLayout.draw(gc, x, y);
443
444
		if (drawFocus(event)) {
445
			Rectangle focusBounds = getBounds(event);
446
			gc.drawFocus(focusBounds.x, focusBounds.y, focusBounds.width,
447
					focusBounds.height);
448
		}
449
450
		gc.setForeground(oldForeground);
451
		gc.setBackground(oldBackground);
452
	}
453
454
	private Rectangle getBounds(Event event) {
455
		Item item = (Item) event.item;
456
		if (item instanceof TreeItem) {
457
			return ((TreeItem) item).getBounds();
458
		} else if (item instanceof TableItem) {
459
			return ((TableItem) item).getBounds();
460
		}
461
		return null;
462
	}
463
464
	private Rectangle getImageBounds(Event event) {
465
		Item item = (Item) event.item;
466
		if (item instanceof TreeItem) {
467
			return ((TreeItem) item).getImageBounds(event.index);
468
		} else if (item instanceof TableItem) {
469
			return ((TableItem) item).getImageBounds(event.index);
470
		}
471
		return null;
472
	}
473
474
	private Rectangle getTextBounds(Event event) {
475
		Item item = (Item) event.item;
476
		if (item instanceof TreeItem) {
477
			return ((TreeItem) item).getTextBounds(event.index);
478
		} else if (item instanceof TableItem) {
479
			return ((TableItem) item).getTextBounds(event.index);
480
		}
481
		return null;
482
	}
483
484
}
(-)Eclipse (+247 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.jface.snippets.viewers;
13
14
import java.io.File;
15
import java.text.MessageFormat;
16
17
import org.eclipse.jface.viewers.ColumnViewer;
18
import org.eclipse.jface.viewers.IBaseLabelProvider;
19
import org.eclipse.jface.viewers.ILabelProvider;
20
import org.eclipse.jface.viewers.ITreeContentProvider;
21
import org.eclipse.jface.viewers.LabelProvider;
22
import org.eclipse.jface.viewers.OwnerDrawLabelProvider;
23
import org.eclipse.jface.viewers.SimpleStyledCellLabelProvider;
24
import org.eclipse.jface.viewers.TableViewer;
25
import org.eclipse.jface.viewers.Viewer;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.custom.StyleRange;
28
import org.eclipse.swt.graphics.Color;
29
import org.eclipse.swt.graphics.Image;
30
import org.eclipse.swt.layout.GridData;
31
import org.eclipse.swt.layout.GridLayout;
32
import org.eclipse.swt.widgets.Button;
33
import org.eclipse.swt.widgets.Composite;
34
import org.eclipse.swt.widgets.Display;
35
import org.eclipse.swt.widgets.Event;
36
import org.eclipse.swt.widgets.Label;
37
import org.eclipse.swt.widgets.Listener;
38
import org.eclipse.swt.widgets.Shell;
39
40
/**
41
 * Using a {@link SimpleStyledCellLabelProvider} on table viewer. Compare the result with a native table viewer.
42
 */
43
44
public class Snippet101SimpleStyledCellLabelProvider {
45
	
46
	
47
	private static final int SHELL_WIDTH= 640;
48
	private static final Display DISPLAY= Display.getDefault();
49
50
51
	public static void main(String[] args) {
52
53
		Shell shell= new Shell(DISPLAY, SWT.CLOSE | SWT.RESIZE);
54
		shell.setSize(SHELL_WIDTH, 300);
55
		shell.setLayout(new GridLayout(1, false));
56
57
		Snippet101SimpleStyledCellLabelProvider example= new Snippet101SimpleStyledCellLabelProvider();
58
		example.createPartControl(shell);
59
60
		shell.open();
61
62
		while (!shell.isDisposed()) {
63
			if (!DISPLAY.readAndDispatch()) {
64
				DISPLAY.sleep();
65
			}
66
		}
67
		DISPLAY.dispose();
68
	}
69
70
	public Snippet101SimpleStyledCellLabelProvider() {
71
	}
72
73
	public void createPartControl(Composite parent) {
74
		Composite composite= new Composite(parent, SWT.NONE);
75
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
76
		composite.setLayout(new GridLayout(2, true));
77
78
		ExampleLabelProvider labelProvider= new ExampleLabelProvider();
79
80
		final ColumnViewer ownerDrawViewer= createViewer("Owner draw viewer:", composite, new DecoratingLabelProvider(labelProvider)); //$NON-NLS-1$
81
		OwnerDrawLabelProvider.setUpOwnerDraw(ownerDrawViewer);
82
83
		final ColumnViewer normalViewer= createViewer("Normal viewer:", composite, labelProvider); //$NON-NLS-1$
84
85
		Button button= new Button(parent, SWT.NONE);
86
		button.setText("Refresh Viewers"); //$NON-NLS-1$
87
		button.addListener(SWT.Modify, new Listener() {
88
89
			public void handleEvent(Event event) {
90
				ownerDrawViewer.refresh();
91
				normalViewer.refresh();
92
			}
93
		});
94
95
	}
96
97
	private ColumnViewer createViewer(String description, Composite parent, IBaseLabelProvider labelProviders) {
98
99
		Composite composite= new Composite(parent, SWT.NONE);
100
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
101
		composite.setLayout(new GridLayout(1, true));
102
103
		Label label= new Label(composite, SWT.NONE);
104
		label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
105
		label.setText(description);
106
107
		TableViewer tableViewer= new TableViewer(composite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
108
		tableViewer.setContentProvider(new FileSystemContentProvider());
109
		tableViewer.setLabelProvider(labelProviders);
110
111
		GridData data= new GridData(GridData.FILL, GridData.FILL, true, true);
112
		tableViewer.getControl().setLayoutData(data);
113
		File[] roots = File.listRoots();
114
		File root = null;
115
		for (int i = 0; i < roots.length; i++) {
116
			String[] list = roots[i].list();
117
			if (list != null && list.length > 0) {
118
				root = roots[i];
119
				break;
120
			}
121
		}
122
		if (root == null) {
123
			throw new RuntimeException("couldn't get a non-empty root file");
124
		}
125
		tableViewer.setInput(root);
126
127
		return tableViewer;
128
	}
129
	
130
	/**
131
	 * Implements a {@link SimpleStyledCellLabelProvider} that wraps a normal label
132
	 * provider and adds some decorations in color
133
	 */
134
	private static class DecoratingLabelProvider extends SimpleStyledCellLabelProvider {
135
136
		private static final StyleRange[] NO_RANGES= new StyleRange[0];
137
		private final ILabelProvider fWrappedLabelProvider;
138
		
139
		public DecoratingLabelProvider(ILabelProvider labelProvider) {
140
			fWrappedLabelProvider= labelProvider;
141
		}
142
143
		protected LabelPresentationInfo getLabelPresentationInfo(Object element) {
144
			String text= fWrappedLabelProvider.getText(element);
145
			Image image= fWrappedLabelProvider.getImage(element);
146
147
			
148
			StyleRange[] ranges= NO_RANGES;
149
			if (element instanceof File) {
150
				File file= (File) element;
151
				if (file.isFile()) {
152
					String decoration= MessageFormat.format(" ({0} bytes)", new Object[] { new Long(file.length()) }); //$NON-NLS-1$
153
										
154
					int decorationStart= text.length();
155
					int decorationLength= decoration.length();
156
157
					text+= decoration;
158
					
159
					Color decorationColor= Display.getDefault().getSystemColor(SWT.COLOR_DARK_BLUE);
160
					
161
					StyleRange styleRange= new StyleRange(decorationStart, decorationLength, decorationColor, null);
162
					ranges= new StyleRange[] { styleRange };
163
				}
164
			}
165
			return new LabelPresentationInfo(text, ranges, image, null, null, null);
166
		}
167
		
168
		public void dispose() {
169
			super.dispose();
170
			fWrappedLabelProvider.dispose();
171
		}
172
	}
173
	
174
175
	/**
176
	 * A simple label provider
177
	 */
178
	private static class ExampleLabelProvider extends LabelProvider {
179
		
180
		private static int IMAGE_SIZE= 16;
181
		private static final Image IMAGE1= new Image(DISPLAY, DISPLAY.getSystemImage(SWT.ICON_WARNING).getImageData().scaledTo(IMAGE_SIZE, IMAGE_SIZE));
182
		private static final Image IMAGE2= new Image(DISPLAY, DISPLAY.getSystemImage(SWT.ICON_ERROR).getImageData().scaledTo(IMAGE_SIZE, IMAGE_SIZE));
183
184
		public Image getImage(Object element) {
185
			if (element instanceof File) {
186
				File file= (File) element;
187
				if (file.isDirectory()) {
188
					return IMAGE1;
189
				} else {
190
					return IMAGE2;
191
				}
192
			}
193
			return null;
194
		}
195
196
		public String getText(Object element) {
197
			if (element instanceof File) {
198
				File file= (File) element;
199
				return file.getName();
200
			}
201
			return "null"; //$NON-NLS-1$
202
		}
203
204
	}
205
	
206
	private static class FileSystemContentProvider implements ITreeContentProvider {
207
208
		public Object[] getChildren(Object element) {
209
			if (element instanceof File) {
210
				File file= (File) element;
211
				if (file.isDirectory()) {
212
					File[] listFiles= file.listFiles();
213
					if (listFiles != null) {
214
						return listFiles;
215
					}
216
				}
217
			}
218
			return new Object[0];
219
		}
220
221
		public Object getParent(Object element) {
222
			if (element instanceof File) {
223
				File file= (File) element;
224
				return file.getParentFile();
225
			}
226
			return null;
227
		}
228
229
		public boolean hasChildren(Object element) {
230
			return getChildren(element).length > 0;
231
		}
232
233
		public Object[] getElements(Object inputElement) {
234
			return getChildren(inputElement);
235
		}
236
237
		public void dispose() {
238
		}
239
240
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
241
		}
242
	}
243
244
245
246
247
}
(-)Eclipse (+309 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.jface.snippets.viewers;
13
14
import java.io.File;
15
import java.text.MessageFormat;
16
import java.util.Date;
17
18
import org.eclipse.jface.viewers.CellLabelProvider;
19
import org.eclipse.jface.viewers.ColumnLabelProvider;
20
import org.eclipse.jface.viewers.ColumnViewer;
21
import org.eclipse.jface.viewers.IBaseLabelProvider;
22
import org.eclipse.jface.viewers.ILabelProvider;
23
import org.eclipse.jface.viewers.ITreeContentProvider;
24
import org.eclipse.jface.viewers.OwnerDrawLabelProvider;
25
import org.eclipse.jface.viewers.SimpleStyledCellLabelProvider;
26
import org.eclipse.jface.viewers.TreeViewer;
27
import org.eclipse.jface.viewers.TreeViewerColumn;
28
import org.eclipse.jface.viewers.Viewer;
29
import org.eclipse.swt.SWT;
30
import org.eclipse.swt.custom.StyleRange;
31
import org.eclipse.swt.graphics.Color;
32
import org.eclipse.swt.graphics.Image;
33
import org.eclipse.swt.layout.GridData;
34
import org.eclipse.swt.layout.GridLayout;
35
import org.eclipse.swt.widgets.Button;
36
import org.eclipse.swt.widgets.Composite;
37
import org.eclipse.swt.widgets.Display;
38
import org.eclipse.swt.widgets.Event;
39
import org.eclipse.swt.widgets.Label;
40
import org.eclipse.swt.widgets.Listener;
41
import org.eclipse.swt.widgets.Shell;
42
43
44
/**
45
 * Using a {@link SimpleStyledCellLabelProvider} on tree viewer. Compare the result with a native tree viewer.
46
 */
47
public class Snippet100SimpleStyledCellLabelProvider {
48
	
49
	
50
	private static final int SHELL_WIDTH= 640;
51
	private static final Display DISPLAY= Display.getDefault();
52
53
54
	public static void main(String[] args) {
55
56
		Shell shell= new Shell(DISPLAY, SWT.CLOSE | SWT.RESIZE);
57
		shell.setSize(SHELL_WIDTH, 300);
58
		shell.setLayout(new GridLayout(1, false));
59
60
		Snippet100SimpleStyledCellLabelProvider example= new Snippet100SimpleStyledCellLabelProvider();
61
		example.createPartControl(shell);
62
63
		shell.open();
64
65
		while (!shell.isDisposed()) {
66
			if (!DISPLAY.readAndDispatch()) {
67
				DISPLAY.sleep();
68
			}
69
		}
70
		DISPLAY.dispose();
71
	}
72
73
	public Snippet100SimpleStyledCellLabelProvider() {
74
	}
75
76
	public void createPartControl(Composite parent) {
77
		Composite composite= new Composite(parent, SWT.NONE);
78
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
79
		composite.setLayout(new GridLayout(2, true));
80
81
		ExampleLabelProvider labelProvider= new ExampleLabelProvider();
82
		ModifiedDateLabelProvider dateLabelProvider= new ModifiedDateLabelProvider();
83
84
		final ColumnViewer ownerDrawViewer= createViewer("Owner draw viewer:", composite, new DecoratingLabelProvider(labelProvider), new DecoratingDateLabelProvider(dateLabelProvider)); //$NON-NLS-1$
85
		OwnerDrawLabelProvider.setUpOwnerDraw(ownerDrawViewer);
86
87
		final ColumnViewer normalViewer= createViewer("Normal viewer:", composite, labelProvider, dateLabelProvider); //$NON-NLS-1$
88
89
		Button button= new Button(parent, SWT.NONE);
90
		button.setText("Refresh Viewers"); //$NON-NLS-1$
91
		button.addListener(SWT.Modify, new Listener() {
92
93
			public void handleEvent(Event event) {
94
				ownerDrawViewer.refresh();
95
				normalViewer.refresh();
96
			}
97
		});
98
99
	}
100
101
	private ColumnViewer createViewer(String description, Composite parent, CellLabelProvider labelProvider1, CellLabelProvider labelProvider2) {
102
103
		Composite composite= new Composite(parent, SWT.NONE);
104
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
105
		composite.setLayout(new GridLayout(1, true));
106
107
		Label label= new Label(composite, SWT.NONE);
108
		label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
109
		label.setText(description);
110
111
		TreeViewer treeViewer= new TreeViewer(composite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
112
		treeViewer.getTree().setHeaderVisible(true);
113
		treeViewer.setContentProvider(new FileSystemContentProvider());
114
		
115
		TreeViewerColumn tvc1 = new TreeViewerColumn(treeViewer, SWT.NONE);
116
		tvc1.getColumn().setText("Name");
117
		tvc1.getColumn().setWidth(200);
118
		tvc1.setLabelProvider(labelProvider1);
119
120
		TreeViewerColumn tvc2 = new TreeViewerColumn(treeViewer, SWT.NONE);
121
		tvc2.getColumn().setText("Date Modified");
122
		tvc2.getColumn().setWidth(200);
123
		tvc2.setLabelProvider(labelProvider2);
124
		
125
		GridData data= new GridData(GridData.FILL, GridData.FILL, true, true);
126
		treeViewer.getControl().setLayoutData(data);
127
		File[] roots = File.listRoots();
128
		File root = null;
129
		for (int i = 0; i < roots.length; i++) {
130
			String[] list = roots[i].list();
131
			if (list != null && list.length > 0) {
132
				root = roots[i];
133
				break;
134
			}
135
		}
136
		if (root == null) {
137
			throw new RuntimeException("couldn't get a non-empty root file");
138
		}
139
		treeViewer.setInput(root);
140
141
		return treeViewer;
142
	}
143
	
144
	/**
145
	 * Implements a {@link SimpleStyledCellLabelProvider} that wraps a normal label
146
	 * provider and adds some decorations in color
147
	 */
148
	private static class DecoratingLabelProvider extends SimpleStyledCellLabelProvider {
149
150
		private static final StyleRange[] NO_RANGES= new StyleRange[0];
151
		private final ILabelProvider fWrappedLabelProvider;
152
		
153
		public DecoratingLabelProvider(ILabelProvider labelProvider) {
154
			fWrappedLabelProvider= labelProvider;
155
		}
156
157
		protected LabelPresentationInfo getLabelPresentationInfo(Object element) {
158
			String text= fWrappedLabelProvider.getText(element);
159
			Image image= fWrappedLabelProvider.getImage(element);
160
161
			
162
			StyleRange[] ranges= NO_RANGES;
163
			if (element instanceof File) {
164
				File file= (File) element;
165
				if (file.isFile()) {
166
					String decoration= MessageFormat.format(" ({0} bytes)", new Object[] { new Long(file.length()) }); //$NON-NLS-1$
167
										
168
					int decorationStart= text.length();
169
					int decorationLength= decoration.length();
170
171
					text+= decoration;
172
					
173
					Color decorationColor= Display.getDefault().getSystemColor(SWT.COLOR_DARK_BLUE);
174
					
175
					StyleRange styleRange= new StyleRange(decorationStart, decorationLength, decorationColor, null);
176
					ranges= new StyleRange[] { styleRange };
177
				}
178
			}
179
			return new LabelPresentationInfo(text, ranges, image, null, null, null);
180
		}
181
		
182
		public void dispose() {
183
			super.dispose();
184
			fWrappedLabelProvider.dispose();
185
		}
186
	}
187
	
188
	private static class DecoratingDateLabelProvider extends SimpleStyledCellLabelProvider {
189
		
190
		private static final String[] DAYS = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
191
		private static final StyleRange[] NO_RANGES= new StyleRange[0];
192
		private final ILabelProvider fWrappedLabelProvider;
193
		
194
		public DecoratingDateLabelProvider(ILabelProvider labelProvider) {
195
			fWrappedLabelProvider= labelProvider;
196
		}
197
		
198
		protected LabelPresentationInfo getLabelPresentationInfo(Object element) {
199
			String text= fWrappedLabelProvider.getText(element);
200
			Image image= fWrappedLabelProvider.getImage(element);
201
			
202
			StyleRange[] ranges= NO_RANGES;
203
			if (element instanceof File) {
204
				File file= (File) element;
205
				String decoration= " " + DAYS[new Date(file.lastModified()).getDay()]; 
206
				
207
				int decorationStart= text.length();
208
				int decorationLength= decoration.length();
209
				
210
				text+= decoration;
211
				
212
				Color decorationColor= Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
213
				
214
				StyleRange styleRange= new StyleRange(decorationStart, decorationLength, decorationColor, null);
215
				ranges= new StyleRange[] { styleRange };
216
			}
217
			return new LabelPresentationInfo(text, ranges, image, null, null, null);
218
		}
219
		
220
		public void dispose() {
221
			super.dispose();
222
			fWrappedLabelProvider.dispose();
223
		}
224
	}
225
	
226
227
	/**
228
	 * A simple label provider
229
	 */
230
	private static class ExampleLabelProvider extends ColumnLabelProvider {
231
		
232
		private static int IMAGE_SIZE= 16;
233
		private static final Image IMAGE1= new Image(DISPLAY, DISPLAY.getSystemImage(SWT.ICON_WARNING).getImageData().scaledTo(IMAGE_SIZE, IMAGE_SIZE));
234
		private static final Image IMAGE2= new Image(DISPLAY, DISPLAY.getSystemImage(SWT.ICON_ERROR).getImageData().scaledTo(IMAGE_SIZE, IMAGE_SIZE));
235
236
		public Image getImage(Object element) {
237
			if (element instanceof File) {
238
				File file= (File) element;
239
				if (file.isDirectory()) {
240
					return IMAGE1;
241
				} else {
242
					return IMAGE2;
243
				}
244
			}
245
			return null;
246
		}
247
248
		public String getText(Object element) {
249
			if (element instanceof File) {
250
				File file= (File) element;
251
				return file.getName();
252
			}
253
			return "null"; //$NON-NLS-1$
254
		}
255
256
	}
257
	
258
	private static class ModifiedDateLabelProvider extends ColumnLabelProvider {
259
		public String getText(Object element) {
260
			if (element instanceof File) {
261
				File file= (File) element;
262
				return new Date(file.lastModified()).toLocaleString();
263
			}
264
			return "-"; //$NON-NLS-1$
265
		}
266
	}
267
	
268
	private static class FileSystemContentProvider implements ITreeContentProvider {
269
270
		public Object[] getChildren(Object element) {
271
			if (element instanceof File) {
272
				File file= (File) element;
273
				if (file.isDirectory()) {
274
					File[] listFiles= file.listFiles();
275
					if (listFiles != null) {
276
						return listFiles;
277
					}
278
				}
279
			}
280
			return new Object[0];
281
		}
282
283
		public Object getParent(Object element) {
284
			if (element instanceof File) {
285
				File file= (File) element;
286
				return file.getParentFile();
287
			}
288
			return null;
289
		}
290
291
		public boolean hasChildren(Object element) {
292
			return getChildren(element).length > 0;
293
		}
294
295
		public Object[] getElements(Object inputElement) {
296
			return getChildren(inputElement);
297
		}
298
299
		public void dispose() {
300
		}
301
302
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
303
		}
304
	}
305
306
307
308
309
}

Return to bug 188333