View Javadoc
1   package org.argeo.eclipse.ui.parts;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.argeo.eclipse.ui.ColumnDefinition;
7   import org.argeo.eclipse.ui.EclipseUiException;
8   import org.argeo.eclipse.ui.EclipseUiUtils;
9   import org.argeo.eclipse.ui.util.ViewerUtils;
10  import org.eclipse.jface.layout.TableColumnLayout;
11  import org.eclipse.jface.viewers.CheckboxTableViewer;
12  import org.eclipse.jface.viewers.ColumnLabelProvider;
13  import org.eclipse.jface.viewers.ColumnWeightData;
14  import org.eclipse.jface.viewers.IStructuredContentProvider;
15  import org.eclipse.jface.viewers.TableViewer;
16  import org.eclipse.jface.viewers.TableViewerColumn;
17  import org.eclipse.jface.viewers.Viewer;
18  import org.eclipse.swt.SWT;
19  import org.eclipse.swt.events.ModifyEvent;
20  import org.eclipse.swt.events.ModifyListener;
21  import org.eclipse.swt.events.SelectionAdapter;
22  import org.eclipse.swt.events.SelectionEvent;
23  import org.eclipse.swt.layout.GridData;
24  import org.eclipse.swt.layout.GridLayout;
25  import org.eclipse.swt.widgets.Composite;
26  import org.eclipse.swt.widgets.Link;
27  import org.eclipse.swt.widgets.Table;
28  import org.eclipse.swt.widgets.TableColumn;
29  import org.eclipse.swt.widgets.Text;
30  import org.osgi.service.useradmin.User;
31  
32  /**
33   * Generic composite that display a filter and a table viewer to display users
34   * (can also be groups)
35   * 
36   * Warning: this class does not extends <code>TableViewer</code>. Use the
37   * getTableViewer method to access it.
38   * 
39   */
40  public abstract class LdifUsersTable extends Composite {
41  	private static final long serialVersionUID = -7385959046279360420L;
42  
43  	// Context
44  	// private UserAdmin userAdmin;
45  
46  	// Configuration
47  	private List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
48  	private boolean hasFilter;
49  	private boolean preventTableLayout = false;
50  	private boolean hasSelectionColumn;
51  	private int tableStyle;
52  
53  	// Local UI Objects
54  	private TableViewer usersViewer;
55  	private Text filterTxt;
56  
57  	/* EXPOSED METHODS */
58  
59  	/**
60  	 * @param parent
61  	 * @param style
62  	 */
63  	public LdifUsersTable(Composite parent, int style) {
64  		super(parent, SWT.NO_FOCUS);
65  		this.tableStyle = style;
66  	}
67  
68  	// TODO workaround the bug of the table layout in the Form
69  	public LdifUsersTable(Composite parent, int style, boolean preventTableLayout) {
70  		super(parent, SWT.NO_FOCUS);
71  		this.tableStyle = style;
72  		this.preventTableLayout = preventTableLayout;
73  	}
74  
75  	/** This must be called before the call to populate method */
76  	public void setColumnDefinitions(List<ColumnDefinition> columnDefinitions) {
77  		this.columnDefs = columnDefinitions;
78  	}
79  
80  	/**
81  	 * 
82  	 * @param addFilter
83  	 *            choose to add a field to filter results or not
84  	 * @param addSelection
85  	 *            choose to add a column to select some of the displayed results or
86  	 *            not
87  	 */
88  	public void populate(boolean addFilter, boolean addSelection) {
89  		// initialization
90  		Composite parent = this;
91  		hasFilter = addFilter;
92  		hasSelectionColumn = addSelection;
93  
94  		// Main Layout
95  		GridLayout layout = EclipseUiUtils.noSpaceGridLayout();
96  		layout.verticalSpacing = 5;
97  		this.setLayout(layout);
98  		if (hasFilter)
99  			createFilterPart(parent);
100 
101 		Composite tableComp = new Composite(parent, SWT.NO_FOCUS);
102 		tableComp.setLayoutData(EclipseUiUtils.fillAll());
103 		usersViewer = createTableViewer(tableComp);
104 		usersViewer.setContentProvider(new UsersContentProvider());
105 	}
106 
107 	/**
108 	 * 
109 	 * @param showMore
110 	 *            display static filters on creation
111 	 * @param addSelection
112 	 *            choose to add a column to select some of the displayed results or
113 	 *            not
114 	 */
115 	public void populateWithStaticFilters(boolean showMore, boolean addSelection) {
116 		// initialization
117 		Composite parent = this;
118 		hasFilter = true;
119 		hasSelectionColumn = addSelection;
120 
121 		// Main Layout
122 		GridLayout layout = EclipseUiUtils.noSpaceGridLayout();
123 		layout.verticalSpacing = 5;
124 		this.setLayout(layout);
125 		createStaticFilterPart(parent, showMore);
126 
127 		Composite tableComp = new Composite(parent, SWT.NO_FOCUS);
128 		tableComp.setLayoutData(EclipseUiUtils.fillAll());
129 		usersViewer = createTableViewer(tableComp);
130 		usersViewer.setContentProvider(new UsersContentProvider());
131 	}
132 
133 	/** Enable access to the selected users or groups */
134 	public List<User> getSelectedUsers() {
135 		if (hasSelectionColumn) {
136 			Object[] elements = ((CheckboxTableViewer) usersViewer).getCheckedElements();
137 
138 			List<User> result = new ArrayList<User>();
139 			for (Object obj : elements) {
140 				result.add((User) obj);
141 			}
142 			return result;
143 		} else
144 			throw new EclipseUiException(
145 					"Unvalid request: no selection column " + "has been created for the current table");
146 	}
147 
148 	/** Returns the User table viewer, typically to add doubleclick listener */
149 	public TableViewer getTableViewer() {
150 		return usersViewer;
151 	}
152 
153 	/**
154 	 * Force the refresh of the underlying table using the current filter string if
155 	 * relevant
156 	 */
157 	public void refresh() {
158 		String filter = hasFilter ? filterTxt.getText().trim() : null;
159 		if ("".equals(filter))
160 			filter = null;
161 		refreshFilteredList(filter);
162 	}
163 
164 	/** Effective repository request: caller must implement this method */
165 	abstract protected List<User> listFilteredElements(String filter);
166 
167 	// protected List<User> listFilteredElements(String filter) {
168 	// List<User> users = new ArrayList<User>();
169 	// try {
170 	// Role[] roles = userAdmin.getRoles(filter);
171 	// // Display all users and groups
172 	// for (Role role : roles)
173 	// users.add((User) role);
174 	// } catch (InvalidSyntaxException e) {
175 	// throw new EclipseUiException("Unable to get roles with filter: "
176 	// + filter, e);
177 	// }
178 	// return users;
179 	// }
180 
181 	/* GENERIC COMPOSITE METHODS */
182 	@Override
183 	public boolean setFocus() {
184 		if (hasFilter)
185 			return filterTxt.setFocus();
186 		else
187 			return usersViewer.getTable().setFocus();
188 	}
189 
190 	@Override
191 	public void dispose() {
192 		super.dispose();
193 	}
194 
195 	/* LOCAL CLASSES AND METHODS */
196 	// Will be usefull to rather use a virtual table viewer
197 	private void refreshFilteredList(String filter) {
198 		List<User> users = listFilteredElements(filter);
199 		usersViewer.setInput(users.toArray());
200 	}
201 
202 	private class UsersContentProvider implements IStructuredContentProvider {
203 		private static final long serialVersionUID = 1L;
204 
205 		public Object[] getElements(Object inputElement) {
206 			return (Object[]) inputElement;
207 		}
208 
209 		public void dispose() {
210 		}
211 
212 		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
213 		}
214 	}
215 
216 	/* MANAGE FILTER */
217 	private void createFilterPart(Composite parent) {
218 		// Text Area for the filter
219 		filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
220 		filterTxt.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
221 		filterTxt.addModifyListener(new ModifyListener() {
222 			private static final long serialVersionUID = 1L;
223 
224 			public void modifyText(ModifyEvent event) {
225 				refreshFilteredList(filterTxt.getText());
226 			}
227 		});
228 	}
229 
230 	private void createStaticFilterPart(Composite parent, boolean showMore) {
231 		Composite filterComp = new Composite(parent, SWT.NO_FOCUS);
232 		filterComp.setLayout(new GridLayout(2, false));
233 		filterComp.setLayoutData(EclipseUiUtils.fillWidth());
234 		// generic search
235 		filterTxt = new Text(filterComp, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
236 		filterTxt.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
237 		// filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL |
238 		// GridData.HORIZONTAL_ALIGN_FILL));
239 		filterTxt.addModifyListener(new ModifyListener() {
240 			private static final long serialVersionUID = 1L;
241 
242 			public void modifyText(ModifyEvent event) {
243 				refreshFilteredList(filterTxt.getText());
244 			}
245 		});
246 
247 		// add static filter abilities
248 		Link moreLk = new Link(filterComp, SWT.NONE);
249 		Composite staticFilterCmp = new Composite(filterComp, SWT.NO_FOCUS);
250 		staticFilterCmp.setLayoutData(EclipseUiUtils.fillWidth(2));
251 		populateStaticFilters(staticFilterCmp);
252 
253 		MoreLinkListener listener = new MoreLinkListener(moreLk, staticFilterCmp, showMore);
254 		// initialise the layout
255 		listener.refresh();
256 		moreLk.addSelectionListener(listener);
257 	}
258 
259 	/** Overwrite to add static filters */
260 	protected void populateStaticFilters(Composite staticFilterCmp) {
261 	}
262 
263 	// private void addMoreSL(final Link more) {
264 	// more.addSelectionListener( }
265 
266 	private class MoreLinkListener extends SelectionAdapter {
267 		private static final long serialVersionUID = -524987616510893463L;
268 		private boolean isShown;
269 		private final Composite staticFilterCmp;
270 		private final Link moreLk;
271 
272 		public MoreLinkListener(Link moreLk, Composite staticFilterCmp, boolean isShown) {
273 			this.moreLk = moreLk;
274 			this.staticFilterCmp = staticFilterCmp;
275 			this.isShown = isShown;
276 		}
277 
278 		@Override
279 		public void widgetSelected(SelectionEvent e) {
280 			isShown = !isShown;
281 			refresh();
282 		}
283 
284 		public void refresh() {
285 			GridData gd = (GridData) staticFilterCmp.getLayoutData();
286 			if (isShown) {
287 				moreLk.setText("<a> Less... </a>");
288 				gd.heightHint = SWT.DEFAULT;
289 			} else {
290 				moreLk.setText("<a> More... </a>");
291 				gd.heightHint = 0;
292 			}
293 			forceLayout();
294 		}
295 	}
296 
297 	private void forceLayout() {
298 		LdifUsersTable.this.getParent().layout(true, true);
299 	}
300 
301 	private TableViewer createTableViewer(final Composite parent) {
302 
303 		int style = tableStyle | SWT.H_SCROLL | SWT.V_SCROLL;
304 		if (hasSelectionColumn)
305 			style = style | SWT.CHECK;
306 		Table table = new Table(parent, style);
307 		TableColumnLayout layout = new TableColumnLayout();
308 
309 		// TODO the table layout does not works with the scrolled form
310 
311 		if (preventTableLayout) {
312 			parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
313 			table.setLayoutData(EclipseUiUtils.fillAll());
314 		} else
315 			parent.setLayout(layout);
316 
317 		TableViewer viewer;
318 		if (hasSelectionColumn)
319 			viewer = new CheckboxTableViewer(table);
320 		else
321 			viewer = new TableViewer(table);
322 		table.setLinesVisible(true);
323 		table.setHeaderVisible(true);
324 
325 		TableViewerColumn column;
326 		// int offset = 0;
327 		if (hasSelectionColumn) {
328 			// offset = 1;
329 			column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE, 25);
330 			column.setLabelProvider(new ColumnLabelProvider() {
331 				private static final long serialVersionUID = 1L;
332 
333 				@Override
334 				public String getText(Object element) {
335 					return null;
336 				}
337 			});
338 			layout.setColumnData(column.getColumn(), new ColumnWeightData(25, 25, false));
339 
340 			SelectionAdapter selectionAdapter = new SelectionAdapter() {
341 				private static final long serialVersionUID = 1L;
342 
343 				boolean allSelected = false;
344 
345 				@Override
346 				public void widgetSelected(SelectionEvent e) {
347 					allSelected = !allSelected;
348 					((CheckboxTableViewer) usersViewer).setAllChecked(allSelected);
349 				}
350 			};
351 			column.getColumn().addSelectionListener(selectionAdapter);
352 		}
353 
354 		// NodeViewerComparator comparator = new NodeViewerComparator();
355 		// TODO enable the sort by click on the header
356 		// int i = offset;
357 		for (ColumnDefinition colDef : columnDefs)
358 			createTableColumn(viewer, layout, colDef);
359 
360 		// column = ViewerUtils.createTableViewerColumn(viewer,
361 		// colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize());
362 		// column.setLabelProvider(new CLProvider(colDef.getPropertyName()));
363 		// column.getColumn().addSelectionListener(
364 		// JcrUiUtils.getNodeSelectionAdapter(i,
365 		// colDef.getPropertyType(), colDef.getPropertyName(),
366 		// comparator, viewer));
367 		// i++;
368 		// }
369 
370 		// IMPORTANT: initialize comparator before setting it
371 		// JcrColumnDefinition firstCol = colDefs.get(0);
372 		// comparator.setColumn(firstCol.getPropertyType(),
373 		// firstCol.getPropertyName());
374 		// viewer.setComparator(comparator);
375 
376 		return viewer;
377 	}
378 
379 	/** Default creation of a column for a user table */
380 	private TableViewerColumn createTableColumn(TableViewer tableViewer, TableColumnLayout layout,
381 			ColumnDefinition columnDef) {
382 
383 		boolean resizable = true;
384 		TableViewerColumn tvc = new TableViewerColumn(tableViewer, SWT.NONE);
385 		TableColumn column = tvc.getColumn();
386 
387 		column.setText(columnDef.getLabel());
388 		column.setWidth(columnDef.getMinWidth());
389 		column.setResizable(resizable);
390 
391 		ColumnLabelProvider lp = columnDef.getLabelProvider();
392 		// add a reference to the display to enable font management
393 		// if (lp instanceof UserAdminAbstractLP)
394 		// ((UserAdminAbstractLP) lp).setDisplay(tableViewer.getTable()
395 		// .getDisplay());
396 		tvc.setLabelProvider(lp);
397 
398 		layout.setColumnData(column, new ColumnWeightData(columnDef.getWeight(), columnDef.getMinWidth(), resizable));
399 
400 		return tvc;
401 	}
402 }