--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.modeling.ui.view;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.Assert;\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.eclipse.core.runtime.SubMonitor;\r
+import org.eclipse.core.runtime.jobs.Job;\r
+import org.eclipse.jface.action.IStatusLineManager;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.resource.ColorDescriptor;\r
+import org.eclipse.jface.resource.JFaceResources;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.nebula.widgets.cdatetime.CDT;\r
+import org.eclipse.nebula.widgets.cdatetime.CDateTime;\r
+import org.eclipse.nebula.widgets.nattable.NatTable;\r
+import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration;\r
+import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;\r
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;\r
+import org.eclipse.nebula.widgets.nattable.grid.GridRegion;\r
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultBodyDataProvider;\r
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;\r
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;\r
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;\r
+import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;\r
+import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;\r
+import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;\r
+import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;\r
+import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;\r
+import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;\r
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;\r
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;\r
+import org.eclipse.nebula.widgets.nattable.reorder.RowReorderLayer;\r
+import org.eclipse.nebula.widgets.nattable.resize.action.AutoResizeColumnAction;\r
+import org.eclipse.nebula.widgets.nattable.resize.action.ColumnResizeCursorAction;\r
+import org.eclipse.nebula.widgets.nattable.resize.event.ColumnResizeEventMatcher;\r
+import org.eclipse.nebula.widgets.nattable.resize.mode.ColumnResizeDragMode;\r
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;\r
+import org.eclipse.nebula.widgets.nattable.selection.config.DefaultSelectionStyleConfiguration;\r
+import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;\r
+import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;\r
+import org.eclipse.nebula.widgets.nattable.style.HorizontalAlignmentEnum;\r
+import org.eclipse.nebula.widgets.nattable.ui.action.ClearCursorAction;\r
+import org.eclipse.nebula.widgets.nattable.ui.action.NoOpMouseAction;\r
+import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;\r
+import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;\r
+import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.dnd.DND;\r
+import org.eclipse.swt.dnd.DropTarget;\r
+import org.eclipse.swt.dnd.DropTargetAdapter;\r
+import org.eclipse.swt.dnd.DropTargetEvent;\r
+import org.eclipse.swt.dnd.TextTransfer;\r
+import org.eclipse.swt.dnd.Transfer;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.DatabaseJob;\r
+import org.simantics.databoard.util.URIStringUtils;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.common.ResourceArray;\r
+import org.simantics.db.common.request.UniqueRead;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.request.PossibleURI;\r
+import org.simantics.db.service.SerialisationSupport;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.modeling.adapters.ChangeInformation;\r
+import org.simantics.modeling.ui.Activator;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.ui.dnd.ResourceReferenceTransfer;\r
+import org.simantics.ui.dnd.ResourceTransferUtils;\r
+import org.simantics.ui.utils.ResourceAdaptionUtils;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+import org.simantics.utils.ui.SWTUtils;\r
+import org.simantics.utils.ui.dialogs.ShowMessage;\r
+import org.simantics.utils.ui.workbench.WorkbenchUtils;\r
+\r
+\r
+public class ChangeInformationComposite extends Composite {\r
+\r
+ private final LocalResourceManager resourceManager;\r
+\r
+ private final ColorDescriptor green = ColorDescriptor.createFrom(new RGB(0x57, 0xbc, 0x95));\r
+ \r
+ /**\r
+ * The Session used to access the graph. Received from outside of this\r
+ * class and therefore it is not disposed here, just used.\r
+ */\r
+ private final Session session;\r
+ \r
+ private Resource resource;\r
+\r
+ private List<Bean> allContents = new ArrayList<Bean>();\r
+\r
+ private List<Bean> contents = new ArrayList<Bean>();\r
+\r
+ protected Layer0 L0;\r
+\r
+ protected IWorkbenchSite site;\r
+ \r
+ private NatTable table;\r
+ \r
+ private IDataProvider bodyDataProvider;\r
+ \r
+ private CDateTime createdBefore; \r
+ private CDateTime createdAfter; \r
+ private CDateTime modifiedBefore; \r
+ private CDateTime modifiedAfter; \r
+ \r
+ private Label dropLabel;\r
+ \r
+ private Text creatorText;\r
+ private Text modifierText;\r
+ private Text nameText;\r
+ private Text pathText;\r
+ private Text typesText;\r
+ \r
+ private BeanSortModel sortModel;\r
+\r
+ /**\r
+ * @param parent\r
+ * @param style\r
+ * @param session\r
+ * @param resource the initial resource to debug or <code>null</code> for\r
+ * initially blank UI.\r
+ */\r
+ public ChangeInformationComposite(Composite parent, int style, final Session session, Resource resource, IWorkbenchSite site) {\r
+ super(parent, style);\r
+ Assert.isNotNull(session, "session is null");\r
+ this.session = session;\r
+ this.resource = resource;\r
+ this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);\r
+ this.site = site;\r
+ }\r
+\r
+ /**\r
+ * When given to setStatus, indicates that the message shouldn't be touched\r
+ * since <code>null</code> has a different meaning.\r
+ */\r
+ private static final String DONT_TOUCH = "DONT_TOUCH";\r
+\r
+ protected void setStatus(String message, String error) {\r
+ IStatusLineManager status = WorkbenchUtils.getStatusLine(site);\r
+ if (status != null) {\r
+ if (message != DONT_TOUCH)\r
+ status.setMessage(message);\r
+ if (error != DONT_TOUCH)\r
+ status.setErrorMessage(error);\r
+ }\r
+ }\r
+\r
+ public void defaultInitializeUI() {\r
+ \r
+ setLayout(new GridLayout(4, false));\r
+ setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+\r
+ createDropLabel(this);\r
+ createContents(this);\r
+\r
+ }\r
+\r
+ public Label createDropLabel(Composite parent) {\r
+ dropLabel = new Label(parent, SWT.BORDER);\r
+ dropLabel.setAlignment(SWT.CENTER);\r
+ dropLabel.setText("Drag a resource here");\r
+ dropLabel.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(4, 1).grab(true, false).applyTo(dropLabel);\r
+\r
+ // Add resource id drop support to the drop-area.\r
+ DropTarget dropTarget = new DropTarget(dropLabel, DND.DROP_LINK | DND.DROP_COPY);\r
+ dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance(), ResourceReferenceTransfer.getInstance(), LocalObjectTransfer.getTransfer() });\r
+ dropTarget.addDropListener(new DropTargetAdapter() {\r
+ @Override\r
+ public void dragEnter(DropTargetEvent event) {\r
+ event.detail = DND.DROP_LINK;\r
+ dropLabel.setBackground((Color) resourceManager.get(green));\r
+ return;\r
+ }\r
+ @Override\r
+ public void dragLeave(DropTargetEvent event) {\r
+ dropLabel.setBackground(null);\r
+ }\r
+\r
+ @Override\r
+ public void drop(DropTargetEvent event) {\r
+ dropLabel.setBackground(null);\r
+ ResourceArray[] data = parseEventData(event);\r
+ if (data == null || data.length != 1) {\r
+ event.detail = DND.DROP_NONE;\r
+ return;\r
+ }\r
+ final ResourceArray array = data[0];\r
+ final Resource r = array.resources[array.resources.length - 1];\r
+\r
+ changeLocation(r);\r
+ }\r
+\r
+ private ResourceArray[] parseEventData(DropTargetEvent event) {\r
+ //System.out.println("DATA: " + event.data);\r
+ if (event.data instanceof String) {\r
+ try {\r
+ SerialisationSupport support = session.getService(SerialisationSupport.class);\r
+ return ResourceTransferUtils.readStringTransferable(support, (String) event.data).toResourceArrayArray();\r
+ } catch (IllegalArgumentException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ } catch (DatabaseException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ }\r
+ }\r
+ ResourceArray[] ret = ResourceAdaptionUtils.toResourceArrays(event.data);\r
+ if (ret.length > 0)\r
+ return ret;\r
+ return null;\r
+ }\r
+ });\r
+\r
+ return dropLabel;\r
+ }\r
+\r
+ public void createContents(Composite parent) {\r
+\r
+ Group fieldGroup = new Group(parent, SWT.NONE);\r
+ fieldGroup.setLayout(new GridLayout(2, false));\r
+ fieldGroup.setText("Filter modifications by text in columns");\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).span(4, 1).grab(true, false).applyTo(fieldGroup);\r
+\r
+ {\r
+ \r
+ final Label label = new Label(fieldGroup, SWT.NONE);\r
+ label.setAlignment(SWT.CENTER);\r
+ label.setText("Created By:");\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
+\r
+ creatorText = new Text(fieldGroup, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(creatorText);\r
+\r
+ creatorText.addModifyListener(new ModifyListener() {\r
+\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ updateData(false);\r
+ }\r
+ });\r
+ \r
+ }\r
+\r
+ {\r
+ \r
+ final Label label = new Label(fieldGroup, SWT.NONE);\r
+ label.setAlignment(SWT.CENTER);\r
+ label.setText("Modified By:");\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
+\r
+ modifierText = new Text(fieldGroup, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(modifierText);\r
+\r
+ modifierText.addModifyListener(new ModifyListener() {\r
+\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ updateData(false);\r
+ }\r
+ });\r
+ \r
+ }\r
+\r
+ {\r
+ \r
+ final Label label = new Label(fieldGroup, SWT.NONE);\r
+ label.setAlignment(SWT.CENTER);\r
+ label.setText("Name:");\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
+\r
+ nameText = new Text(fieldGroup, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(nameText);\r
+\r
+ nameText.addModifyListener(new ModifyListener() {\r
+\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ updateData(false);\r
+ }\r
+ });\r
+ \r
+ }\r
+\r
+ {\r
+ \r
+ final Label label = new Label(fieldGroup, SWT.NONE);\r
+ label.setAlignment(SWT.CENTER);\r
+ label.setText("Path:");\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
+\r
+ pathText = new Text(fieldGroup, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(pathText);\r
+\r
+ pathText.addModifyListener(new ModifyListener() {\r
+\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ updateData(false);\r
+ }\r
+ });\r
+ \r
+ }\r
+ \r
+ {\r
+ \r
+ final Label label = new Label(fieldGroup, SWT.NONE);\r
+ label.setAlignment(SWT.CENTER);\r
+ label.setText("Types:");\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(false, false).applyTo(label);\r
+\r
+ typesText = new Text(fieldGroup, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(typesText);\r
+\r
+ typesText.addModifyListener(new ModifyListener() {\r
+\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ updateData(false);\r
+ }\r
+ });\r
+ \r
+ }\r
+\r
+\r
+ SelectionListener selectionListener = new SelectionListener() {\r
+ \r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ widgetDefaultSelected(e);\r
+ }\r
+ \r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ updateData(false);\r
+ }\r
+ };\r
+ \r
+ Group timeGroup = new Group(parent, SWT.NONE);\r
+ timeGroup.setLayout(new GridLayout(2, false));\r
+ timeGroup.setText("Filter modifications by time");\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).span(4, 1).grab(true, false).applyTo(timeGroup);\r
+ \r
+ createdAfter = new CDateTime(timeGroup, CDT.BORDER | CDT.DROP_DOWN | CDT.CLOCK_12_HOUR);\r
+ createdAfter.setPattern("'Created after 'd.M.yyy '@' H:mm");\r
+ createdAfter.setNullText("<choose created after>");\r
+ createdAfter.addSelectionListener(selectionListener);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(createdAfter);\r
+ createdBefore = new CDateTime(timeGroup, CDT.BORDER | CDT.DROP_DOWN | CDT.CLOCK_12_HOUR);\r
+ createdBefore.setPattern("'Created before 'd.M.yyy '@' H:mm");\r
+ createdBefore.setNullText("<choose created before>");\r
+ createdBefore.addSelectionListener(selectionListener);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(createdBefore);\r
+\r
+ modifiedAfter = new CDateTime(timeGroup, CDT.BORDER | CDT.DROP_DOWN | CDT.CLOCK_12_HOUR);\r
+ modifiedAfter.setPattern("'Modified after 'd.M.yyy '@' H:mm");\r
+ modifiedAfter.setNullText("<choose modified after>");\r
+ modifiedAfter.addSelectionListener(selectionListener);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(modifiedAfter);\r
+ modifiedBefore = new CDateTime(timeGroup, CDT.BORDER | CDT.DROP_DOWN | CDT.CLOCK_12_HOUR);\r
+ modifiedBefore.setPattern("'Modified before 'd.M.yyy '@' H:mm");\r
+ modifiedBefore.setNullText("<choose modified before>");\r
+ modifiedBefore.addSelectionListener(selectionListener);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(1, 1).grab(true, false).applyTo(modifiedBefore);\r
+ \r
+ //property names of the Person class\r
+ String[] propertyNames = {"name", "path", "types", "createdBy", "createdAt", "modifiedBy", "modifiedAt"};\r
+ \r
+ //mapping from property to label, needed for column header labels\r
+ Map<String, String> propertyToLabelMap = new HashMap<String, String>();\r
+ propertyToLabelMap.put("name", "Name");\r
+ propertyToLabelMap.put("path", "Path");\r
+ propertyToLabelMap.put("types", "Types");\r
+ propertyToLabelMap.put("createdBy", "Created By");\r
+ propertyToLabelMap.put("createdAt", "Created At");\r
+ propertyToLabelMap.put("modifiedBy", "Last Modified By");\r
+ propertyToLabelMap.put("modifiedAt", "Last Modified At");\r
+ \r
+ //build the body layer stack \r
+ //Usually you would create a new layer stack by extending AbstractIndexLayerTransform and\r
+ //setting the ViewportLayer as underlying layer. But in this case using the ViewportLayer\r
+ //directly as body layer is also working.\r
+ bodyDataProvider = new DefaultBodyDataProvider<Bean>(contents, propertyNames);\r
+ final DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);\r
+ bodyDataLayer.setColumnWidthByPosition(0, 145);\r
+ bodyDataLayer.setColumnWidthByPosition(1, 170);\r
+ bodyDataLayer.setColumnWidthByPosition(2, 120);\r
+ bodyDataLayer.setColumnWidthByPosition(3, 85);\r
+ bodyDataLayer.setColumnWidthByPosition(4, 85);\r
+ bodyDataLayer.setColumnWidthByPosition(5, 115);\r
+ bodyDataLayer.setColumnWidthByPosition(6, 115);\r
+ \r
+ final RowReorderLayer rowReorderLayer = new RowReorderLayer(bodyDataLayer);\r
+ final SelectionLayer selectionLayer = new SelectionLayer(rowReorderLayer);\r
+ ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);\r
+\r
+ //build the column header layer\r
+ IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);\r
+ DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);\r
+ ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);\r
+\r
+ sortModel = new BeanSortModel(allContents, contents);\r
+ \r
+ SortHeaderLayer<Bean> sortHeaderLayer = new SortHeaderLayer<Bean>(\r
+ columnHeaderLayer, sortModel);\r
+ \r
+ //build the row header layer\r
+ IDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);\r
+ DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);\r
+ rowHeaderDataLayer.setColumnWidthByPosition(0, 90);\r
+ \r
+ RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, viewportLayer, selectionLayer);\r
+ \r
+ //build the corner layer\r
+ IDataProvider cornerDataProvider = new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider);\r
+ DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);\r
+ ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, sortHeaderLayer);\r
+ \r
+ //build the grid layer\r
+ GridLayer gridLayer = new GridLayer(viewportLayer, sortHeaderLayer, rowHeaderLayer, cornerLayer);\r
+ \r
+ table = new NatTable(parent, gridLayer, false);\r
+ \r
+ DefaultNatTableStyleConfiguration styleConfiguration = new DefaultNatTableStyleConfiguration();\r
+ styleConfiguration.hAlign = HorizontalAlignmentEnum.LEFT;\r
+ table.addConfiguration(styleConfiguration);\r
+ // Change the default sort key bindings. Note that 'auto configure' was turned off\r
+ table.addConfiguration(new SingleClickSortConfiguration());\r
+ table.addConfiguration(new DefaultSelectionStyleConfiguration());\r
+ \r
+ \r
+ table.addConfiguration(new AbstractUiBindingConfiguration() {\r
+\r
+ @Override\r
+ public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {\r
+ // Mouse move - Show resize cursor\r
+ uiBindingRegistry.registerFirstMouseMoveBinding(new ColumnResizeEventMatcher(SWT.NONE,\r
+ GridRegion.ROW_HEADER, 0), new ColumnResizeCursorAction());\r
+ uiBindingRegistry.registerMouseMoveBinding(new MouseEventMatcher(), new ClearCursorAction());\r
+\r
+ // Column resize\r
+ uiBindingRegistry.registerFirstMouseDragMode(new ColumnResizeEventMatcher(SWT.NONE,\r
+ GridRegion.ROW_HEADER, 1), new ColumnResizeDragMode());\r
+\r
+ uiBindingRegistry.registerDoubleClickBinding(new ColumnResizeEventMatcher(SWT.NONE,\r
+ GridRegion.ROW_HEADER, 1), new AutoResizeColumnAction());\r
+ uiBindingRegistry.registerSingleClickBinding(new ColumnResizeEventMatcher(SWT.NONE,\r
+ GridRegion.ROW_HEADER, 1), new NoOpMouseAction());\r
+ }\r
+ });\r
+ \r
+ table.configure();\r
+ \r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 20).span(4, 1).grab(true, true).applyTo(table);\r
+ \r
+ }\r
+\r
+ public void changeLocation(Resource element) {\r
+ \r
+ resource = element;\r
+ \r
+ try {\r
+ String uri = session.syncRequest(new PossibleURI(resource));\r
+ if(uri != null) {\r
+ uri = uri.replace("http://Projects/Development%20Project/", "");\r
+ uri = URIStringUtils.unescape(uri);\r
+ dropLabel.setText("Drag a resource here - searching at " + uri);\r
+ }\r
+ } catch (DatabaseException e) {\r
+ Logger.defaultLogError(e);\r
+ }\r
+ \r
+ refresh();\r
+ \r
+ }\r
+ \r
+ public void refresh() {\r
+\r
+ searchAndUpdate();\r
+\r
+ }\r
+\r
+ public void updateData(boolean sort) {\r
+\r
+ filter();\r
+ \r
+ if(sort) sortModel.sortCurrent();\r
+ \r
+ table.refresh();\r
+ \r
+ setStatus(DONT_TOUCH, null);\r
+\r
+ }\r
+ \r
+ private long getPossibleTime(CDateTime widget) {\r
+ Date d = widget.getSelection();\r
+ if(d == null) return 0;\r
+ else return d.getTime();\r
+ }\r
+ \r
+ public void filter() {\r
+ \r
+ long createdAfterTime = getPossibleTime(createdAfter);\r
+ long createdBeforeTime = getPossibleTime(createdBefore);\r
+ long modifiedAfterTime = getPossibleTime(modifiedAfter);\r
+ long modifiedBeforeTime = getPossibleTime(modifiedBefore);\r
+ \r
+ String creatorFilter = creatorText.getText().toLowerCase();\r
+ if(creatorFilter.isEmpty()) creatorFilter = null;\r
+ String modifierFilter = modifierText.getText().toLowerCase();\r
+ if(modifierFilter.isEmpty()) modifierFilter = null;\r
+ String[] nameFilter = null;\r
+ if(!nameText.getText().isEmpty()) nameFilter = nameText.getText().toLowerCase().split(" ");\r
+ String[] pathFilter = null;\r
+ if(!pathText.getText().isEmpty()) pathFilter = pathText.getText().toLowerCase().split(" ");\r
+ String[] typesFilter = null;\r
+ if(!typesText.getText().isEmpty()) typesFilter = typesText.getText().toLowerCase().split(" ");\r
+ \r
+ contents.clear();\r
+ for(Bean b : allContents) {\r
+ \r
+ if(createdAfterTime > 0 && b.createdAt < createdAfterTime) continue;\r
+ if(createdBeforeTime > 0 && b.createdAt > createdBeforeTime) continue;\r
+ if(modifiedAfterTime > 0 && b.modifiedAt < modifiedAfterTime) continue;\r
+ if(modifiedBeforeTime > 0 && b.modifiedAt > modifiedBeforeTime) continue;\r
+ \r
+ if(creatorFilter != null && !b.getCreatedBy().toLowerCase().contains(creatorFilter)) continue;\r
+ if(modifierFilter != null && !b.getModifiedBy().toLowerCase().contains(modifierFilter)) continue;\r
+ if(nameFilter!= null) {\r
+ String name = b.getName().toLowerCase();\r
+ boolean ok = false;\r
+ for(String t : nameFilter) {\r
+ if(name.contains(t)) {\r
+ ok=true;\r
+ break;\r
+ }\r
+ }\r
+ if(!ok) continue;\r
+ }\r
+ if(pathFilter!= null) {\r
+ String name = b.getPath().toLowerCase();\r
+ boolean ok = false;\r
+ for(String t : pathFilter) {\r
+ if(name.contains(t)) {\r
+ ok=true;\r
+ break;\r
+ }\r
+ }\r
+ if(!ok) continue;\r
+ }\r
+ if(typesFilter != null) {\r
+ String types = b.getTypes().toLowerCase();\r
+ boolean ok = false;\r
+ for(String t : typesFilter) {\r
+ if(types.contains(t)) {\r
+ ok=true;\r
+ break;\r
+ }\r
+ }\r
+ if(!ok) continue;\r
+ }\r
+ contents.add(b);\r
+ }\r
+ \r
+ }\r
+ \r
+ public void searchAndUpdate() {\r
+\r
+ final Display display = WorkbenchUtils.getActiveWorkbenchWindowShell().getDisplay();\r
+ Job job = new DatabaseJob("Processing change information") {\r
+ @Override\r
+ protected IStatus run(final IProgressMonitor monitor) {\r
+ \r
+ try {\r
+ \r
+ allContents.clear();\r
+ allContents.addAll(session.syncRequest(new UniqueRead<List<Bean>>() {\r
+\r
+ private void browse(ReadGraph graph, Layer0 L0, Resource r, Set<Resource> visited) throws DatabaseException {\r
+\r
+ if(!visited.add(r)) return;\r
+\r
+ for(Resource object : graph.getObjects(r, L0.DependsOn))\r
+ browse(graph, L0, object, visited);\r
+\r
+ }\r
+\r
+ @Override\r
+ public List<Bean> perform(ReadGraph graph) throws DatabaseException {\r
+\r
+ SubMonitor sub = SubMonitor.convert(monitor, "Readying change information", 100);\r
+\r
+ sub.setTaskName("Searching for change records");\r
+ \r
+ ArrayList<Bean> result = new ArrayList<Bean>();\r
+ if(resource == null) return result;\r
+\r
+ HashSet<Resource> visited = new HashSet<Resource>();\r
+\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ \r
+ browse(graph, L0, resource, visited);\r
+ \r
+ sub.worked(30);\r
+\r
+ sub.setTaskName("Processing " + visited.size() + " change records");\r
+ sub.setWorkRemaining(visited.size());\r
+\r
+ String baseURI = graph.getPossibleURI(resource);\r
+ \r
+ for(Resource r : visited) {\r
+ ChangeInformation ci = graph.getPossibleRelatedValue(r, MOD.changeInformation, ChangeInformation.BINDING);\r
+ if(ci != null) result.add(new Bean(graph, r, ci, baseURI));\r
+ sub.worked(1);\r
+ }\r
+ \r
+ return result;\r
+\r
+ }\r
+\r
+ }));\r
+ return Status.OK_STATUS;\r
+ } catch (final DatabaseException e) {\r
+ showMessage(display, e.getMessage());\r
+ // WARNING, because we don't want the job system to pop up it's own error dialog\r
+ // which would happen if ERROR was used.\r
+ return new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Errors while reading change information.", e);\r
+ } finally {\r
+ monitor.done();\r
+ \r
+ SWTUtils.asyncExec(display, new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ updateData(true);\r
+ }\r
+ });\r
+\r
+ }\r
+\r
+ }\r
+ \r
+ private void showMessage(Display display, final String message) {\r
+ SWTUtils.asyncExec(display, new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ ShowMessage.showError("Problems while reading change information", message);\r
+ }\r
+ });\r
+ }\r
+\r
+ };\r
+ job.setUser(true);\r
+ job.schedule();\r
+ }\r
+\r
+}\r