]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/view/ChangeInformationComposite.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / view / ChangeInformationComposite.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.modeling.ui.view;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Date;\r
16 import java.util.HashMap;\r
17 import java.util.HashSet;\r
18 import java.util.List;\r
19 import java.util.Map;\r
20 import java.util.Set;\r
21 \r
22 import org.eclipse.core.runtime.Assert;\r
23 import org.eclipse.core.runtime.IProgressMonitor;\r
24 import org.eclipse.core.runtime.IStatus;\r
25 import org.eclipse.core.runtime.Status;\r
26 import org.eclipse.core.runtime.SubMonitor;\r
27 import org.eclipse.core.runtime.jobs.Job;\r
28 import org.eclipse.jface.action.IStatusLineManager;\r
29 import org.eclipse.jface.layout.GridDataFactory;\r
30 import org.eclipse.jface.resource.ColorDescriptor;\r
31 import org.eclipse.jface.resource.JFaceResources;\r
32 import org.eclipse.jface.resource.LocalResourceManager;\r
33 import org.eclipse.nebula.widgets.cdatetime.CDT;\r
34 import org.eclipse.nebula.widgets.cdatetime.CDateTime;\r
35 import org.eclipse.nebula.widgets.nattable.NatTable;\r
36 import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration;\r
37 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;\r
38 import org.eclipse.nebula.widgets.nattable.data.IDataProvider;\r
39 import org.eclipse.nebula.widgets.nattable.grid.GridRegion;\r
40 import org.eclipse.nebula.widgets.nattable.grid.data.DefaultBodyDataProvider;\r
41 import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;\r
42 import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;\r
43 import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;\r
44 import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;\r
45 import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;\r
46 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;\r
47 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;\r
48 import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;\r
49 import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;\r
50 import org.eclipse.nebula.widgets.nattable.layer.DataLayer;\r
51 import org.eclipse.nebula.widgets.nattable.layer.ILayer;\r
52 import org.eclipse.nebula.widgets.nattable.reorder.RowReorderLayer;\r
53 import org.eclipse.nebula.widgets.nattable.resize.action.AutoResizeColumnAction;\r
54 import org.eclipse.nebula.widgets.nattable.resize.action.ColumnResizeCursorAction;\r
55 import org.eclipse.nebula.widgets.nattable.resize.event.ColumnResizeEventMatcher;\r
56 import org.eclipse.nebula.widgets.nattable.resize.mode.ColumnResizeDragMode;\r
57 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;\r
58 import org.eclipse.nebula.widgets.nattable.selection.config.DefaultSelectionStyleConfiguration;\r
59 import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;\r
60 import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;\r
61 import org.eclipse.nebula.widgets.nattable.style.HorizontalAlignmentEnum;\r
62 import org.eclipse.nebula.widgets.nattable.ui.action.ClearCursorAction;\r
63 import org.eclipse.nebula.widgets.nattable.ui.action.NoOpMouseAction;\r
64 import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;\r
65 import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;\r
66 import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;\r
67 import org.eclipse.swt.SWT;\r
68 import org.eclipse.swt.dnd.DND;\r
69 import org.eclipse.swt.dnd.DropTarget;\r
70 import org.eclipse.swt.dnd.DropTargetAdapter;\r
71 import org.eclipse.swt.dnd.DropTargetEvent;\r
72 import org.eclipse.swt.dnd.TextTransfer;\r
73 import org.eclipse.swt.dnd.Transfer;\r
74 import org.eclipse.swt.events.ModifyEvent;\r
75 import org.eclipse.swt.events.ModifyListener;\r
76 import org.eclipse.swt.events.SelectionEvent;\r
77 import org.eclipse.swt.events.SelectionListener;\r
78 import org.eclipse.swt.graphics.Color;\r
79 import org.eclipse.swt.graphics.RGB;\r
80 import org.eclipse.swt.layout.GridData;\r
81 import org.eclipse.swt.layout.GridLayout;\r
82 import org.eclipse.swt.widgets.Composite;\r
83 import org.eclipse.swt.widgets.Display;\r
84 import org.eclipse.swt.widgets.Group;\r
85 import org.eclipse.swt.widgets.Label;\r
86 import org.eclipse.swt.widgets.Text;\r
87 import org.eclipse.ui.IWorkbenchSite;\r
88 import org.simantics.DatabaseJob;\r
89 import org.simantics.databoard.util.URIStringUtils;\r
90 import org.simantics.db.ReadGraph;\r
91 import org.simantics.db.Resource;\r
92 import org.simantics.db.Session;\r
93 import org.simantics.db.common.ResourceArray;\r
94 import org.simantics.db.common.request.UniqueRead;\r
95 import org.simantics.db.common.utils.Logger;\r
96 import org.simantics.db.exception.DatabaseException;\r
97 import org.simantics.db.layer0.request.PossibleURI;\r
98 import org.simantics.db.service.SerialisationSupport;\r
99 import org.simantics.layer0.Layer0;\r
100 import org.simantics.modeling.ModelingResources;\r
101 import org.simantics.modeling.adapters.ChangeInformation;\r
102 import org.simantics.modeling.ui.Activator;\r
103 import org.simantics.ui.dnd.LocalObjectTransfer;\r
104 import org.simantics.ui.dnd.ResourceReferenceTransfer;\r
105 import org.simantics.ui.dnd.ResourceTransferUtils;\r
106 import org.simantics.ui.utils.ResourceAdaptionUtils;\r
107 import org.simantics.utils.ui.ErrorLogger;\r
108 import org.simantics.utils.ui.SWTUtils;\r
109 import org.simantics.utils.ui.dialogs.ShowMessage;\r
110 import org.simantics.utils.ui.workbench.WorkbenchUtils;\r
111 \r
112 \r
113 public class ChangeInformationComposite extends Composite {\r
114 \r
115     private final LocalResourceManager                  resourceManager;\r
116 \r
117     private final ColorDescriptor                       green = ColorDescriptor.createFrom(new RGB(0x57, 0xbc, 0x95));\r
118     \r
119     /**\r
120      * The Session used to access the graph. Received from outside of this\r
121      * class and therefore it is not disposed here, just used.\r
122      */\r
123     private final Session                               session;\r
124     \r
125     private   Resource                              resource;\r
126 \r
127     private   List<Bean>                               allContents = new ArrayList<Bean>();\r
128 \r
129     private   List<Bean>                               contents  = new ArrayList<Bean>();\r
130 \r
131     protected Layer0                                    L0;\r
132 \r
133     protected IWorkbenchSite                            site;\r
134     \r
135     private NatTable                                    table;\r
136     \r
137     private IDataProvider                               bodyDataProvider;\r
138     \r
139     private CDateTime                                   createdBefore; \r
140     private CDateTime                                   createdAfter; \r
141     private CDateTime                                   modifiedBefore; \r
142     private CDateTime                                   modifiedAfter; \r
143     \r
144     private Label dropLabel;\r
145     \r
146     private Text creatorText;\r
147     private Text modifierText;\r
148     private Text nameText;\r
149     private Text pathText;\r
150     private Text typesText;\r
151     \r
152     private BeanSortModel sortModel;\r
153 \r
154     /**\r
155      * @param parent\r
156      * @param style\r
157      * @param session\r
158      * @param resource the initial resource to debug or <code>null</code> for\r
159      *        initially blank UI.\r
160      */\r
161     public ChangeInformationComposite(Composite parent, int style, final Session session, Resource resource, IWorkbenchSite site) {\r
162         super(parent, style);\r
163         Assert.isNotNull(session, "session is null");\r
164         this.session = session;\r
165         this.resource = resource;\r
166         this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);\r
167         this.site = site;\r
168     }\r
169 \r
170     /**\r
171      * When given to setStatus, indicates that the message shouldn't be touched\r
172      * since <code>null</code> has a different meaning.\r
173      */\r
174     private static final String DONT_TOUCH = "DONT_TOUCH";\r
175 \r
176     protected void setStatus(String message, String error) {\r
177         IStatusLineManager status = WorkbenchUtils.getStatusLine(site);\r
178         if (status != null) {\r
179             if (message != DONT_TOUCH)\r
180                 status.setMessage(message);\r
181             if (error != DONT_TOUCH)\r
182                 status.setErrorMessage(error);\r
183         }\r
184     }\r
185 \r
186     public void defaultInitializeUI() {\r
187         \r
188         setLayout(new GridLayout(4, false));\r
189         setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
190 \r
191         createDropLabel(this);\r
192         createContents(this);\r
193 \r
194     }\r
195 \r
196     public Label createDropLabel(Composite parent) {\r
197         dropLabel = new Label(parent, SWT.BORDER);\r
198         dropLabel.setAlignment(SWT.CENTER);\r
199         dropLabel.setText("Drag a resource here");\r
200         dropLabel.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));\r
201         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(4, 1).grab(true, false).applyTo(dropLabel);\r
202 \r
203         // Add resource id drop support to the drop-area.\r
204         DropTarget dropTarget = new DropTarget(dropLabel, DND.DROP_LINK | DND.DROP_COPY);\r
205         dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance(), ResourceReferenceTransfer.getInstance(), LocalObjectTransfer.getTransfer() });\r
206         dropTarget.addDropListener(new DropTargetAdapter() {\r
207             @Override\r
208             public void dragEnter(DropTargetEvent event) {\r
209                 event.detail = DND.DROP_LINK;\r
210                 dropLabel.setBackground((Color) resourceManager.get(green));\r
211                 return;\r
212             }\r
213             @Override\r
214             public void dragLeave(DropTargetEvent event) {\r
215                 dropLabel.setBackground(null);\r
216             }\r
217 \r
218             @Override\r
219             public void drop(DropTargetEvent event) {\r
220                 dropLabel.setBackground(null);\r
221                 ResourceArray[] data = parseEventData(event);\r
222                 if (data == null || data.length != 1) {\r
223                     event.detail = DND.DROP_NONE;\r
224                     return;\r
225                 }\r
226                 final ResourceArray array = data[0];\r
227                 final Resource r = array.resources[array.resources.length - 1];\r
228 \r
229                 changeLocation(r);\r
230             }\r
231 \r
232             private ResourceArray[] parseEventData(DropTargetEvent event) {\r
233                 //System.out.println("DATA: " + event.data);\r
234                 if (event.data instanceof String) {\r
235                     try {\r
236                         SerialisationSupport support = session.getService(SerialisationSupport.class);\r
237                         return ResourceTransferUtils.readStringTransferable(support, (String) event.data).toResourceArrayArray();\r
238                     } catch (IllegalArgumentException e) {\r
239                         ErrorLogger.defaultLogError(e);\r
240                     } catch (DatabaseException e) {\r
241                         ErrorLogger.defaultLogError(e);\r
242                     }\r
243                 }\r
244                 ResourceArray[] ret = ResourceAdaptionUtils.toResourceArrays(event.data);\r
245                 if (ret.length > 0)\r
246                     return ret;\r
247                 return null;\r
248             }\r
249         });\r
250 \r
251         return dropLabel;\r
252     }\r
253 \r
254     public void createContents(Composite parent) {\r
255 \r
256         Group fieldGroup = new Group(parent, SWT.NONE);\r
257         fieldGroup.setLayout(new GridLayout(2, false));\r
258         fieldGroup.setText("Filter modifications by text in columns");\r
259         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).span(4, 1).grab(true, false).applyTo(fieldGroup);\r
260 \r
261         {\r
262         \r
263                 final Label label = new Label(fieldGroup, SWT.NONE);\r
264                 label.setAlignment(SWT.CENTER);\r
265                 label.setText("Created By:");\r
266                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
267 \r
268                 creatorText = new Text(fieldGroup, SWT.BORDER);\r
269                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(creatorText);\r
270 \r
271                 creatorText.addModifyListener(new ModifyListener() {\r
272 \r
273                         @Override\r
274                         public void modifyText(ModifyEvent e) {\r
275                                 updateData(false);\r
276                         }\r
277                 });\r
278         \r
279         }\r
280 \r
281         {\r
282                 \r
283                 final Label label = new Label(fieldGroup, SWT.NONE);\r
284                 label.setAlignment(SWT.CENTER);\r
285                 label.setText("Modified By:");\r
286                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
287 \r
288                 modifierText = new Text(fieldGroup, SWT.BORDER);\r
289                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(modifierText);\r
290 \r
291                 modifierText.addModifyListener(new ModifyListener() {\r
292 \r
293                         @Override\r
294                         public void modifyText(ModifyEvent e) {\r
295                                 updateData(false);\r
296                         }\r
297                 });\r
298         \r
299         }\r
300 \r
301         {\r
302                 \r
303                 final Label label = new Label(fieldGroup, SWT.NONE);\r
304                 label.setAlignment(SWT.CENTER);\r
305                 label.setText("Name:");\r
306                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
307 \r
308                 nameText = new Text(fieldGroup, SWT.BORDER);\r
309                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(nameText);\r
310 \r
311                 nameText.addModifyListener(new ModifyListener() {\r
312 \r
313                         @Override\r
314                         public void modifyText(ModifyEvent e) {\r
315                                 updateData(false);\r
316                         }\r
317                 });\r
318         \r
319         }\r
320 \r
321         {\r
322                 \r
323                 final Label label = new Label(fieldGroup, SWT.NONE);\r
324                 label.setAlignment(SWT.CENTER);\r
325                 label.setText("Path:");\r
326                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
327 \r
328                 pathText = new Text(fieldGroup, SWT.BORDER);\r
329                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(pathText);\r
330 \r
331                 pathText.addModifyListener(new ModifyListener() {\r
332 \r
333                         @Override\r
334                         public void modifyText(ModifyEvent e) {\r
335                                 updateData(false);\r
336                         }\r
337                 });\r
338         \r
339         }\r
340         \r
341         {\r
342                 \r
343                 final Label label = new Label(fieldGroup, SWT.NONE);\r
344                 label.setAlignment(SWT.CENTER);\r
345                 label.setText("Types:");\r
346                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
347 \r
348                 typesText = new Text(fieldGroup, SWT.BORDER);\r
349                 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(typesText);\r
350 \r
351                 typesText.addModifyListener(new ModifyListener() {\r
352 \r
353                         @Override\r
354                         public void modifyText(ModifyEvent e) {\r
355                                 updateData(false);\r
356                         }\r
357                 });\r
358         \r
359         }\r
360 \r
361 \r
362         SelectionListener selectionListener = new SelectionListener() {\r
363                         \r
364                         @Override\r
365                         public void widgetSelected(SelectionEvent e) {\r
366                                 widgetDefaultSelected(e);\r
367                         }\r
368                         \r
369                         @Override\r
370                         public void widgetDefaultSelected(SelectionEvent e) {\r
371                                 updateData(false);\r
372                         }\r
373                 };\r
374         \r
375         Group timeGroup = new Group(parent, SWT.NONE);\r
376         timeGroup.setLayout(new GridLayout(2, false));\r
377         timeGroup.setText("Filter modifications by time");\r
378         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).span(4, 1).grab(true, false).applyTo(timeGroup);\r
379         \r
380         createdAfter = new CDateTime(timeGroup, CDT.BORDER | CDT.DROP_DOWN | CDT.CLOCK_12_HOUR);\r
381         createdAfter.setPattern("'Created after 'd.M.yyy '@' H:mm");\r
382         createdAfter.setNullText("<choose created after>");\r
383         createdAfter.addSelectionListener(selectionListener);\r
384         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(createdAfter);\r
385         createdBefore = new CDateTime(timeGroup, CDT.BORDER | CDT.DROP_DOWN | CDT.CLOCK_12_HOUR);\r
386         createdBefore.setPattern("'Created before 'd.M.yyy '@' H:mm");\r
387         createdBefore.setNullText("<choose created before>");\r
388         createdBefore.addSelectionListener(selectionListener);\r
389         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(createdBefore);\r
390 \r
391         modifiedAfter = new CDateTime(timeGroup, CDT.BORDER | CDT.DROP_DOWN | CDT.CLOCK_12_HOUR);\r
392         modifiedAfter.setPattern("'Modified after 'd.M.yyy '@' H:mm");\r
393         modifiedAfter.setNullText("<choose modified after>");\r
394         modifiedAfter.addSelectionListener(selectionListener);\r
395         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(modifiedAfter);\r
396         modifiedBefore = new CDateTime(timeGroup, CDT.BORDER | CDT.DROP_DOWN | CDT.CLOCK_12_HOUR);\r
397         modifiedBefore.setPattern("'Modified before 'd.M.yyy '@' H:mm");\r
398         modifiedBefore.setNullText("<choose modified before>");\r
399         modifiedBefore.addSelectionListener(selectionListener);\r
400         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(modifiedBefore);\r
401         \r
402         //property names of the Person class\r
403         String[] propertyNames = {"name", "path", "types", "createdBy", "createdAt", "modifiedBy", "modifiedAt"};\r
404         \r
405         //mapping from property to label, needed for column header labels\r
406         Map<String, String> propertyToLabelMap = new HashMap<String, String>();\r
407         propertyToLabelMap.put("name", "Name");\r
408         propertyToLabelMap.put("path", "Path");\r
409         propertyToLabelMap.put("types", "Types");\r
410         propertyToLabelMap.put("createdBy", "Created By");\r
411         propertyToLabelMap.put("createdAt", "Created At");\r
412         propertyToLabelMap.put("modifiedBy", "Last Modified By");\r
413         propertyToLabelMap.put("modifiedAt", "Last Modified At");\r
414         \r
415         //build the body layer stack \r
416         //Usually you would create a new layer stack by extending AbstractIndexLayerTransform and\r
417         //setting the ViewportLayer as underlying layer. But in this case using the ViewportLayer\r
418         //directly as body layer is also working.\r
419         bodyDataProvider = new DefaultBodyDataProvider<Bean>(contents, propertyNames);\r
420         final DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);\r
421         bodyDataLayer.setColumnWidthByPosition(0, 145);\r
422         bodyDataLayer.setColumnWidthByPosition(1, 170);\r
423         bodyDataLayer.setColumnWidthByPosition(2, 120);\r
424         bodyDataLayer.setColumnWidthByPosition(3, 85);\r
425         bodyDataLayer.setColumnWidthByPosition(4, 85);\r
426         bodyDataLayer.setColumnWidthByPosition(5, 115);\r
427         bodyDataLayer.setColumnWidthByPosition(6, 115);\r
428         \r
429         final RowReorderLayer rowReorderLayer = new RowReorderLayer(bodyDataLayer);\r
430         final SelectionLayer selectionLayer = new SelectionLayer(rowReorderLayer);\r
431         ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);\r
432 \r
433         //build the column header layer\r
434         IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);\r
435         DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);\r
436         ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);\r
437 \r
438         sortModel = new BeanSortModel(allContents, contents);\r
439         \r
440         SortHeaderLayer<Bean> sortHeaderLayer = new SortHeaderLayer<Bean>(\r
441                         columnHeaderLayer, sortModel);\r
442         \r
443         //build the row header layer\r
444         IDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);\r
445         DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);\r
446         rowHeaderDataLayer.setColumnWidthByPosition(0, 90);\r
447         \r
448         RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, viewportLayer, selectionLayer);\r
449         \r
450         //build the corner layer\r
451         IDataProvider cornerDataProvider = new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider);\r
452         DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);\r
453         ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, sortHeaderLayer);\r
454         \r
455         //build the grid layer\r
456         GridLayer gridLayer = new GridLayer(viewportLayer, sortHeaderLayer, rowHeaderLayer, cornerLayer);\r
457         \r
458         table = new NatTable(parent, gridLayer, false);\r
459         \r
460         DefaultNatTableStyleConfiguration styleConfiguration = new DefaultNatTableStyleConfiguration();\r
461         styleConfiguration.hAlign = HorizontalAlignmentEnum.LEFT;\r
462         table.addConfiguration(styleConfiguration);\r
463         // Change the default sort key bindings. Note that 'auto configure' was turned off\r
464         table.addConfiguration(new SingleClickSortConfiguration());\r
465         table.addConfiguration(new DefaultSelectionStyleConfiguration());\r
466         \r
467         \r
468         table.addConfiguration(new AbstractUiBindingConfiguration() {\r
469 \r
470                 @Override\r
471                 public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {\r
472                         // Mouse move - Show resize cursor\r
473                         uiBindingRegistry.registerFirstMouseMoveBinding(new ColumnResizeEventMatcher(SWT.NONE,\r
474                                         GridRegion.ROW_HEADER, 0), new ColumnResizeCursorAction());\r
475                         uiBindingRegistry.registerMouseMoveBinding(new MouseEventMatcher(), new ClearCursorAction());\r
476 \r
477                         // Column resize\r
478                         uiBindingRegistry.registerFirstMouseDragMode(new ColumnResizeEventMatcher(SWT.NONE,\r
479                                         GridRegion.ROW_HEADER, 1), new ColumnResizeDragMode());\r
480 \r
481                         uiBindingRegistry.registerDoubleClickBinding(new ColumnResizeEventMatcher(SWT.NONE,\r
482                                         GridRegion.ROW_HEADER, 1), new AutoResizeColumnAction());\r
483                         uiBindingRegistry.registerSingleClickBinding(new ColumnResizeEventMatcher(SWT.NONE,\r
484                                         GridRegion.ROW_HEADER, 1), new NoOpMouseAction());\r
485                 }\r
486         });\r
487         \r
488         table.configure();\r
489         \r
490         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(4, 1).grab(true, true).applyTo(table);\r
491         \r
492     }\r
493 \r
494     public void changeLocation(Resource element) {\r
495         \r
496         resource = element;\r
497         \r
498                 try {\r
499                         String uri = session.syncRequest(new PossibleURI(resource));\r
500                         if(uri != null) {\r
501                                 uri = uri.replace("http://Projects/Development%20Project/", "");\r
502                                 uri = URIStringUtils.unescape(uri);\r
503                                 dropLabel.setText("Drag a resource here - searching at " + uri);\r
504                         }\r
505                 } catch (DatabaseException e) {\r
506                         Logger.defaultLogError(e);\r
507                 }\r
508         \r
509         refresh();\r
510         \r
511     }\r
512     \r
513     public void refresh() {\r
514 \r
515         searchAndUpdate();\r
516 \r
517     }\r
518 \r
519     public void updateData(boolean sort) {\r
520 \r
521         filter();\r
522         \r
523         if(sort) sortModel.sortCurrent();\r
524         \r
525         table.refresh();\r
526         \r
527         setStatus(DONT_TOUCH, null);\r
528 \r
529     }\r
530     \r
531     private long getPossibleTime(CDateTime widget) {\r
532         Date d = widget.getSelection();\r
533         if(d == null) return 0;\r
534         else return d.getTime();\r
535     }\r
536     \r
537     public void filter() {\r
538         \r
539         long createdAfterTime = getPossibleTime(createdAfter);\r
540         long createdBeforeTime = getPossibleTime(createdBefore);\r
541         long modifiedAfterTime = getPossibleTime(modifiedAfter);\r
542         long modifiedBeforeTime = getPossibleTime(modifiedBefore);\r
543         \r
544         String creatorFilter = creatorText.getText().toLowerCase();\r
545         if(creatorFilter.isEmpty()) creatorFilter = null;\r
546         String modifierFilter = modifierText.getText().toLowerCase();\r
547         if(modifierFilter.isEmpty()) modifierFilter = null;\r
548         String[] nameFilter = null;\r
549         if(!nameText.getText().isEmpty()) nameFilter = nameText.getText().toLowerCase().split(" ");\r
550         String[] pathFilter = null;\r
551         if(!pathText.getText().isEmpty()) pathFilter = pathText.getText().toLowerCase().split(" ");\r
552         String[] typesFilter = null;\r
553         if(!typesText.getText().isEmpty()) typesFilter = typesText.getText().toLowerCase().split(" ");\r
554         \r
555         contents.clear();\r
556         for(Bean b : allContents) {\r
557                 \r
558                 if(createdAfterTime > 0 && b.createdAt < createdAfterTime) continue;\r
559                 if(createdBeforeTime > 0 && b.createdAt > createdBeforeTime) continue;\r
560                 if(modifiedAfterTime > 0 && b.modifiedAt < modifiedAfterTime) continue;\r
561                 if(modifiedBeforeTime > 0 && b.modifiedAt > modifiedBeforeTime) continue;\r
562                 \r
563                 if(creatorFilter != null && !b.getCreatedBy().toLowerCase().contains(creatorFilter)) continue;\r
564                 if(modifierFilter != null && !b.getModifiedBy().toLowerCase().contains(modifierFilter)) continue;\r
565                 if(nameFilter!= null) {\r
566                         String name = b.getName().toLowerCase();\r
567                         boolean ok = false;\r
568                         for(String t : nameFilter) {\r
569                         if(name.contains(t)) {\r
570                                 ok=true;\r
571                                 break;\r
572                         }\r
573                         }\r
574                         if(!ok) continue;\r
575                 }\r
576                 if(pathFilter!= null) {\r
577                         String name = b.getPath().toLowerCase();\r
578                         boolean ok = false;\r
579                         for(String t : pathFilter) {\r
580                         if(name.contains(t)) {\r
581                                 ok=true;\r
582                                 break;\r
583                         }\r
584                         }\r
585                         if(!ok) continue;\r
586                 }\r
587                 if(typesFilter != null) {\r
588                         String types = b.getTypes().toLowerCase();\r
589                         boolean ok = false;\r
590                         for(String t : typesFilter) {\r
591                         if(types.contains(t)) {\r
592                                 ok=true;\r
593                                 break;\r
594                         }\r
595                         }\r
596                         if(!ok) continue;\r
597                 }\r
598                 contents.add(b);\r
599         }\r
600         \r
601     }\r
602     \r
603     public void searchAndUpdate() {\r
604 \r
605         final Display display = WorkbenchUtils.getActiveWorkbenchWindowShell().getDisplay();\r
606         Job job = new DatabaseJob("Processing change information") {\r
607                 @Override\r
608                 protected IStatus run(final IProgressMonitor monitor) {\r
609                         \r
610                         try {\r
611                                 \r
612                                 allContents.clear();\r
613                                 allContents.addAll(session.syncRequest(new UniqueRead<List<Bean>>() {\r
614 \r
615                                         private void browse(ReadGraph graph, Layer0 L0, Resource r, Set<Resource> visited) throws DatabaseException {\r
616 \r
617                                                 if(!visited.add(r)) return;\r
618 \r
619                                                 for(Resource object : graph.getObjects(r, L0.DependsOn))\r
620                                                         browse(graph, L0, object, visited);\r
621 \r
622                                         }\r
623 \r
624                                         @Override\r
625                                         public List<Bean> perform(ReadGraph graph) throws DatabaseException {\r
626 \r
627                                                 SubMonitor sub = SubMonitor.convert(monitor, "Readying change information", 100);\r
628 \r
629                                                 sub.setTaskName("Searching for change records");\r
630                                                 \r
631                                                 ArrayList<Bean> result = new ArrayList<Bean>();\r
632                                                 if(resource == null) return result;\r
633 \r
634                                                 HashSet<Resource> visited = new HashSet<Resource>();\r
635 \r
636                                                 Layer0 L0 = Layer0.getInstance(graph);\r
637                                                 ModelingResources MOD = ModelingResources.getInstance(graph);\r
638                                                 \r
639                                                 browse(graph, L0, resource, visited);\r
640                                                 \r
641                                                 sub.worked(30);\r
642 \r
643                                                 sub.setTaskName("Processing " + visited.size() + " change records");\r
644                                                 sub.setWorkRemaining(visited.size());\r
645 \r
646                                                 String baseURI = graph.getPossibleURI(resource);\r
647                                                 \r
648                                                 for(Resource r : visited) {\r
649                                                         ChangeInformation ci = graph.getPossibleRelatedValue(r, MOD.changeInformation, ChangeInformation.BINDING);\r
650                                                         if(ci != null) result.add(new Bean(graph, r, ci, baseURI));\r
651                                                                 sub.worked(1);\r
652                                                 }\r
653                                                 \r
654                                                 return result;\r
655 \r
656                                         }\r
657 \r
658                                 }));\r
659                                 return Status.OK_STATUS;\r
660                         } catch (final DatabaseException e) {\r
661                                 showMessage(display, e.getMessage());\r
662                                 // WARNING, because we don't want the job system to pop up it's own error dialog\r
663                                 // which would happen if ERROR was used.\r
664                                 return new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Errors while reading change information.", e);\r
665                         } finally {\r
666                                 monitor.done();\r
667                                 \r
668                     SWTUtils.asyncExec(display, new Runnable() {\r
669                         @Override\r
670                         public void run() {\r
671                                 updateData(true);\r
672                         }\r
673                     });\r
674 \r
675                         }\r
676 \r
677                 }\r
678                 \r
679             private void showMessage(Display display, final String message) {\r
680                 SWTUtils.asyncExec(display, new Runnable() {\r
681                     @Override\r
682                     public void run() {\r
683                         ShowMessage.showError("Problems while reading change information", message);\r
684                     }\r
685                 });\r
686             }\r
687 \r
688         };\r
689         job.setUser(true);\r
690         job.schedule();\r
691     }\r
692 \r
693 }\r