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