1 /*******************************************************************************
2  * Copyright (c) 2009, 2018 Matthew Hall and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     Matthew Hall - initial API and implementation (bug 175735)
13  *     Matthew Hall - bugs 262407, 260337
14  ******************************************************************************/
15 
16 package org.eclipse.jface.examples.databinding.snippets;
17 
18 import java.beans.PropertyChangeListener;
19 import java.beans.PropertyChangeSupport;
20 import java.util.ArrayList;
21 import java.util.List;
22 
23 import org.eclipse.core.databinding.beans.typed.BeanProperties;
24 import org.eclipse.core.databinding.observable.Realm;
25 import org.eclipse.core.databinding.property.list.IListProperty;
26 import org.eclipse.core.databinding.property.list.MultiListProperty;
27 import org.eclipse.jface.databinding.swt.DisplayRealm;
28 import org.eclipse.jface.databinding.viewers.ObservableListTreeContentProvider;
29 import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
30 import org.eclipse.jface.viewers.TreeViewer;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.graphics.GC;
33 import org.eclipse.swt.graphics.Image;
34 import org.eclipse.swt.layout.FillLayout;
35 import org.eclipse.swt.layout.GridLayout;
36 import org.eclipse.swt.widgets.Display;
37 import org.eclipse.swt.widgets.Shell;
38 
39 public class Snippet029TreeViewerMultiListProperty {
40 	private TreeViewer viewer;
41 
main(String[] args)42 	public static void main(String[] args) {
43 		final Display display = Display.getDefault();
44 
45 		Realm.runWithDefault(DisplayRealm.getRealm(display), () -> {
46 			Shell shell = new Snippet029TreeViewerMultiListProperty().createShell();
47 
48 			while (!shell.isDisposed()) {
49 				if (!display.readAndDispatch()) {
50 					display.sleep();
51 				}
52 			}
53 		});
54 
55 		display.dispose();
56 	}
57 
createShell()58 	protected Shell createShell() {
59 		Shell shell = new Shell();
60 		shell.setSize(509, 375);
61 		shell.setText("Snippet029TreeViewerMultiListProperty.java");
62 		final GridLayout gridLayout = new GridLayout();
63 		gridLayout.makeColumnsEqualWidth = true;
64 		gridLayout.numColumns = 4;
65 		shell.setLayout(new FillLayout());
66 
67 		viewer = new TreeViewer(shell, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER);
68 
69 		bindUI();
70 
71 		shell.open();
72 		return shell;
73 	}
74 
75 	/** Helper class for implementing JavaBeans support. */
76 	public static abstract class AbstractModelObject {
77 		private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
78 
addPropertyChangeListener(PropertyChangeListener listener)79 		public void addPropertyChangeListener(PropertyChangeListener listener) {
80 			propertyChangeSupport.addPropertyChangeListener(listener);
81 		}
82 
addPropertyChangeListener(String propertyName, PropertyChangeListener listener)83 		public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
84 			propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
85 		}
86 
removePropertyChangeListener(PropertyChangeListener listener)87 		public void removePropertyChangeListener(PropertyChangeListener listener) {
88 			propertyChangeSupport.removePropertyChangeListener(listener);
89 		}
90 
removePropertyChangeListener(String propertyName, PropertyChangeListener listener)91 		public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
92 			propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
93 		}
94 
firePropertyChange(String propertyName, Object oldValue, Object newValue)95 		protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
96 			propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
97 		}
98 	}
99 
100 	public static class Catalog extends AbstractModelObject {
101 		private String name;
102 		private List<Catalog> catalogs = new ArrayList<>();
103 		private List<CatalogItem> items = new ArrayList<>();
104 
Catalog(String name)105 		public Catalog(String name) {
106 			this.name = name;
107 		}
108 
getName()109 		public String getName() {
110 			return name;
111 		}
112 
setName(String name)113 		public void setName(String name) {
114 			firePropertyChange("name", this.name, this.name = name);
115 		}
116 
getCatalogs()117 		public List<Catalog> getCatalogs() {
118 			return catalogs;
119 		}
120 
setCatalogs(List<Catalog> catalogs)121 		public void setCatalogs(List<Catalog> catalogs) {
122 			firePropertyChange("catalogs", this.catalogs, this.catalogs = catalogs);
123 		}
124 
getItems()125 		public List<CatalogItem> getItems() {
126 			return items;
127 		}
128 
setItems(List<CatalogItem> items)129 		public void setItems(List<CatalogItem> items) {
130 			firePropertyChange("items", this.items, this.items = items);
131 		}
132 	}
133 
134 	public static class CatalogItem extends AbstractModelObject {
135 		private String name;
136 
CatalogItem(String name)137 		public CatalogItem(String name) {
138 			this.name = name;
139 		}
140 
getName()141 		public String getName() {
142 			return name;
143 		}
144 
setName(String name)145 		public void setName(String name) {
146 			firePropertyChange("name", this.name, this.name = name);
147 		}
148 	}
149 
bindUI()150 	private void bindUI() {
151 		List<CatalogItem> items;
152 
153 		Catalog fruits = new Catalog("Fruits");
154 		items = new ArrayList<>();
155 		items.add(new CatalogItem("Apple"));
156 		items.add(new CatalogItem("Orange"));
157 		fruits.setItems(items);
158 
159 		Catalog vegetables = new Catalog("Vegetables");
160 		items = new ArrayList<>();
161 		items.add(new CatalogItem("Peas"));
162 		items.add(new CatalogItem("Carrots"));
163 		items.add(new CatalogItem("Potatoes"));
164 		vegetables.setItems(items);
165 
166 		Catalog foods = new Catalog("Foods");
167 		List<Catalog> catalogs = new ArrayList<>();
168 		catalogs.add(fruits);
169 		catalogs.add(vegetables);
170 		foods.setCatalogs(catalogs);
171 
172 		items = new ArrayList<>();
173 		items.add(new CatalogItem("Own Hand"));
174 		foods.setItems(items);
175 
176 		Catalog catalog = new Catalog("Main Catalog");
177 		catalogs = new ArrayList<>();
178 		catalogs.add(foods);
179 		catalog.setCatalogs(catalogs);
180 
181 		IListProperty<AbstractModelObject, AbstractModelObject> childrenProperty = new MultiListProperty<>(
182 				BeanProperties.list("catalogs"), BeanProperties.list("items"));
183 
184 		ObservableListTreeContentProvider<AbstractModelObject> contentProvider = new ObservableListTreeContentProvider<>(
185 				childrenProperty.listFactory(), null);
186 		viewer.setContentProvider(contentProvider);
187 
188 		ObservableMapLabelProvider labelProvider = new ObservableMapLabelProvider(
189 				BeanProperties.value("name").observeDetail(contentProvider.getKnownElements())) {
190 			Image catalogImage = createCatalogImage();
191 			Image catalogItemImage = createCatalogItemImage();
192 
193 			@Override
194 			public Image getImage(Object element) {
195 				if (element instanceof Catalog) {
196 					return catalogImage;
197 				}
198 				if (element instanceof CatalogItem) {
199 					return catalogItemImage;
200 				}
201 				return super.getImage(element);
202 			}
203 
204 			@Override
205 			public void dispose() {
206 				catalogImage.dispose();
207 				catalogItemImage.dispose();
208 				super.dispose();
209 			}
210 
211 			private Image createCatalogImage() {
212 				Display display = Display.getCurrent();
213 				Image catalogImage = new Image(display, 12, 12);
214 				GC gc = new GC(catalogImage);
215 				gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN));
216 				gc.fillArc(1, 1, 10, 10, 0, 360);
217 				gc.dispose();
218 				return catalogImage;
219 			}
220 
221 			private Image createCatalogItemImage() {
222 				Display display = Display.getCurrent();
223 				Image catalogImage = new Image(display, 12, 12);
224 				GC gc = new GC(catalogImage);
225 				gc.setBackground(display.getSystemColor(SWT.COLOR_CYAN));
226 				gc.fillPolygon(new int[] { 1, 10, 5, 1, 6, 1, 10, 10, 1, 10 });
227 				gc.dispose();
228 				return catalogImage;
229 			}
230 		};
231 		viewer.setLabelProvider(labelProvider);
232 
233 		viewer.setInput(catalog);
234 	}
235 }
236