View Javadoc
1   package org.argeo.connect.ui.util;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.argeo.cms.util.CmsUtils;
7   import org.argeo.connect.ui.ConnectColumnDefinition;
8   import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
9   import org.argeo.eclipse.ui.utils.ViewerUtils;
10  import org.eclipse.jface.layout.TableColumnLayout;
11  import org.eclipse.jface.viewers.CellEditor;
12  import org.eclipse.jface.viewers.CheckboxCellEditor;
13  import org.eclipse.jface.viewers.ColumnLabelProvider;
14  import org.eclipse.jface.viewers.ColumnWeightData;
15  import org.eclipse.jface.viewers.EditingSupport;
16  import org.eclipse.jface.viewers.ILazyContentProvider;
17  import org.eclipse.jface.viewers.TableViewer;
18  import org.eclipse.jface.viewers.TableViewerColumn;
19  import org.eclipse.jface.viewers.Viewer;
20  import org.eclipse.swt.SWT;
21  import org.eclipse.swt.graphics.Image;
22  import org.eclipse.swt.widgets.Composite;
23  import org.eclipse.swt.widgets.Table;
24  
25  /**
26   * Utility class that wraps a virtual table viewer to display JCR rows or nodes
27   */
28  public class VirtualJcrTableViewer extends Composite {
29  	// private final static Log log = LogFactory
30  	// .getLog(VirtualJcrTableViewer.class);
31  
32  	private static final long serialVersionUID = 1L;
33  	private TableViewer viewer;
34  
35  	private List<ConnectColumnDefinition> colDefs;
36  	private int tableStyle;
37  
38  	// Management of displayed row and selection
39  	private Object[] elements;
40  	// Work around : keep a flag to know which elements have already been loaded
41  	// or not
42  	private boolean[] loadedFlags;
43  
44  	private List<Object> selectedElements = new ArrayList<Object>();
45  	private boolean hasCheckBoxes = false;
46  
47  	private MyLazyContentProvider lazyContentProvider;
48  
49  	public List<ConnectColumnDefinition> getColumnsDef() {
50  		return colDefs;
51  	}
52  
53  	// CONSTRUCTOR
54  	public VirtualJcrTableViewer(Composite parent, int style, List<ConnectColumnDefinition> columns) {
55  		super(parent, SWT.NONE);
56  		this.tableStyle = style;
57  		this.colDefs = columns;
58  		populate();
59  	}
60  
61  	public VirtualJcrTableViewer(Composite parent, int style, List<ConnectColumnDefinition> columns,
62  			boolean addCheckBoxes) {
63  		super(parent, SWT.NONE);
64  		this.tableStyle = style;
65  		this.colDefs = columns;
66  		hasCheckBoxes = addCheckBoxes;
67  		populate();
68  	}
69  
70  	protected void populate() {
71  		// initialization
72  		Composite parent = this;
73  		// Main Layout
74  		// GridLayout layout = EclipseUiUtils.noSpaceGridLayout();
75  		// this.setLayout(layout);
76  		createTableViewer(parent);
77  		EclipseUiSpecificUtils.enableToolTipSupport(viewer);
78  	}
79  
80  	/** Returns the User table viewer, typically to add doubleclick listener */
81  	public TableViewer getTableViewer() {
82  		return viewer;
83  	}
84  
85  	private void createTableViewer(final Composite parent) {
86  		int swtStyle = tableStyle | SWT.VIRTUAL;
87  		Table table = new Table(parent, swtStyle);
88  		table.setLinesVisible(true);
89  		table.setHeaderVisible(true);
90  		CmsUtils.markup(table);
91  
92  		TableViewerColumn column;
93  		TableColumnLayout tableColumnLayout = new TableColumnLayout();
94  		viewer = new TableViewer(table);
95  
96  		if (hasCheckBoxes) {
97  			// check column
98  			column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE, 20);
99  			column.setLabelProvider(new ColumnLabelProvider() {
100 				private static final long serialVersionUID = 1L;
101 
102 				public String getText(Object element) {
103 					return null;
104 				}
105 
106 				public Image getImage(Object element) {
107 					if (selectedElements.contains(element))
108 						return getDisplay().getSystemImage(SWT.CHECK);
109 					else
110 						return null;
111 					// return PeopleRapImages.CHECK_SELECTED;
112 					// else
113 					// return PeopleRapImages.CHECK_UNSELECTED;
114 				}
115 			});
116 			column.setEditingSupport(new SelectionEditingSupport());
117 			tableColumnLayout.setColumnData(column.getColumn(), new ColumnWeightData(20, 24, true));
118 		}
119 
120 		for (ConnectColumnDefinition colDef : colDefs) {
121 			column = ViewerUtils.createTableViewerColumn(viewer, colDef.getHeaderLabel(), SWT.NONE,
122 					colDef.getColumnSize());
123 			column.setLabelProvider(colDef.getColumnLabelProvider());
124 			tableColumnLayout.setColumnData(column.getColumn(),
125 					new ColumnWeightData(colDef.getColumnSize(), colDef.getColumnSize(), true));
126 		}
127 
128 		lazyContentProvider = new MyLazyContentProvider(viewer);
129 		viewer.setContentProvider(lazyContentProvider);
130 		parent.setLayout(tableColumnLayout);
131 	}
132 
133 	private class MyLazyContentProvider implements ILazyContentProvider {
134 		private static final long serialVersionUID = 1L;
135 		private TableViewer viewer;
136 
137 		public MyLazyContentProvider(TableViewer viewer) {
138 			this.viewer = viewer;
139 		}
140 
141 		public void dispose() {
142 		}
143 
144 		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
145 			// IMPORTANT: don't forget this: an exception will be thrown if a
146 			// selected object is not part of the results anymore.
147 			viewer.setSelection(null);
148 			selectedElements.clear();
149 			elements = (Object[]) newInput;
150 			loadedFlags = new boolean[elements == null ? 0 : elements.length];
151 		}
152 
153 		public void updateElement(int index) {
154 			viewer.replace(elements[index], index);
155 			loadedFlags[index] = true;
156 		}
157 	}
158 
159 	/** Select the columns by editing the checkbox in the first column */
160 	class SelectionEditingSupport extends EditingSupport {
161 		private static final long serialVersionUID = 398089475969012249L;
162 
163 		public SelectionEditingSupport() {
164 			super(viewer);
165 		}
166 
167 		@Override
168 		protected CellEditor getCellEditor(Object element) {
169 			return new CheckboxCellEditor(null, SWT.CHECK | SWT.READ_ONLY);
170 		}
171 
172 		@Override
173 		protected boolean canEdit(Object element) {
174 			return true;
175 		}
176 
177 		@Override
178 		protected Object getValue(Object element) {
179 			return selectedElements.contains(element);
180 		}
181 
182 		@Override
183 		protected void setValue(Object element, Object value) {
184 			Boolean selected = (Boolean) value;
185 			if (selected && !selectedElements.contains(element)) {
186 				selectedElements.add(element);
187 			} else if (!selected && selectedElements.contains(element)) {
188 				selectedElements.remove(element);
189 			}
190 		}
191 	}
192 
193 	public void setAllChecked(boolean checked) {
194 		selectedElements.clear();
195 		if (checked)
196 			for (Object currEl : elements) {
197 				selectedElements.add(currEl);
198 			}
199 		// Cannot violently refresh. loop issues
200 		// refresh();
201 		// workaround
202 		int count = viewer.getTable().getItemCount();
203 		for (int i = 0; i < count; i++)
204 			if (loadedFlags[i])
205 				lazyContentProvider.updateElement(i);
206 	}
207 
208 	public Object[] getSelectedElements() {
209 		return selectedElements.toArray();
210 	}
211 
212 	public void refresh() {
213 		viewer.refresh();
214 	}
215 
216 	@Override
217 	public boolean setFocus() {
218 		viewer.getTable().setFocus();
219 		return true;
220 	}
221 }