From b2888c8235f138b7d0da67b7a390f18f619b65d1 Mon Sep 17 00:00:00 2001 From: lempinen Date: Wed, 9 Nov 2011 08:41:15 +0000 Subject: [PATCH] Drag scrolling and drop target separators for ChartPanel git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@23232 ac1ea38d-2e2b-0410-8846-a27921b304fc --- org.simantics.sysdyn.ui/plugin.xml | 2 +- .../ChartPanelOrientationHandler.java | 7 +- .../simantics/sysdyn/ui/trend/ChartPanel.java | 130 +++++++++++++++--- .../sysdyn/ui/trend/ChartPanelHeader.java | 69 +++++++++- .../sysdyn/ui/trend/ChartPanelSeparator.java | 91 ++++++++++++ 5 files changed, 270 insertions(+), 29 deletions(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanelSeparator.java diff --git a/org.simantics.sysdyn.ui/plugin.xml b/org.simantics.sysdyn.ui/plugin.xml index 33696445..2eedf70d 100644 --- a/org.simantics.sysdyn.ui/plugin.xml +++ b/org.simantics.sysdyn.ui/plugin.xml @@ -740,7 +740,7 @@ locationURI="toolbar:org.simantics.sysdyn.ui.chartPanel"> diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ChartPanelOrientationHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ChartPanelOrientationHandler.java index c000bf81..87ee362a 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ChartPanelOrientationHandler.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ChartPanelOrientationHandler.java @@ -52,7 +52,7 @@ public class ChartPanelOrientationHandler extends AbstractHandler implements IEl String orientation = settings.get(ChartPanel.CHART_PANEL_ORIENTATION); if(orientation == null) - settings.put(ChartPanel.CHART_PANEL_ORIENTATION, ChartPanel.CHART_PANEL_VERTICAL); + settings.put(ChartPanel.CHART_PANEL_ORIENTATION, ChartPanel.CHART_PANEL_HORIZONTAL); if(ChartPanel.CHART_PANEL_VERTICAL.equals(orientation)) orientation = ChartPanel.CHART_PANEL_HORIZONTAL; @@ -80,9 +80,8 @@ public class ChartPanelOrientationHandler extends AbstractHandler implements IEl return; IDialogSettings settings = Activator.getDefault().getDialogSettings().getSection(ChartPanel.CHART_PANEL_SETTINGS); - if (settings == null) { - settings = Activator.getDefault().getDialogSettings().addNewSection(ChartPanel.CHART_PANEL_SETTINGS); - } + if(settings == null) + return; String orientation = settings.get(ChartPanel.CHART_PANEL_ORIENTATION); if(orientation == null) diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanel.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanel.java index 5782adf4..1bf12a70 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanel.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanel.java @@ -18,6 +18,15 @@ import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; +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.Transfer; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IMemento; @@ -25,6 +34,7 @@ import org.eclipse.ui.IViewSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.part.ViewPart; import org.simantics.sysdyn.ui.Activator; +import org.simantics.ui.dnd.LocalObjectTransfer; /** * Chart panel displays multiple charts in a single view. The view can be oriented @@ -87,11 +97,10 @@ public class ChartPanel extends ViewPart { for(String m : minimizedURIs) minimizedCharts.add(m); - String orientation = settings.get(CHART_PANEL_ORIENTATION); if(CHART_PANEL_VERTICAL.equals(orientation)) this.vertical = true; - else + else if(CHART_PANEL_HORIZONTAL.equals(orientation)) this.vertical = false; } @@ -106,6 +115,8 @@ public class ChartPanel extends ViewPart { GridDataFactory.fillDefaults().grab(true, true).applyTo(sc); sc.setExpandHorizontal(true); sc.setExpandVertical(true); + sc.getVerticalBar().setIncrement(sc.getVerticalBar().getIncrement()*3); + setupDropTarget(sc); body = new Composite(sc, SWT.NONE); GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(body); @@ -113,7 +124,7 @@ public class ChartPanel extends ViewPart { sc.setContent(body); - createContents(body); + createContents(); } /** @@ -124,35 +135,45 @@ public class ChartPanel extends ViewPart { * * @param parent Body located inside a scrolled composite and containing the charts. (always private Composite body?) */ - private void createContents(Composite parent) { - for(Control c : parent.getChildren()) + private void createContents() { + for(Control c : body.getChildren()) c.dispose(); - Composite composite = new Composite(parent, SWT.NONE); - + Composite composite = new Composite(body, SWT.NONE); + int separator; if(vertical) { GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(composite); GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + separator = SWT.VERTICAL; } else { - int en = expandedCharts.size(); - int mn = minimizedCharts.isEmpty() ? 0 : 1; - GridLayoutFactory.fillDefaults().spacing(0, 0).numColumns(en + mn).applyTo(composite); + int chartPanels = expandedCharts.size(); + int minimizedPanel = minimizedCharts.isEmpty() ? 0 : 1; + int separators = 1 + expandedCharts.size() + minimizedCharts.size(); + + GridLayoutFactory.fillDefaults().spacing(0, 0).numColumns(chartPanels + minimizedPanel + separators).applyTo(composite); GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + separator = SWT.HORIZONTAL; } - for(String e : expandedCharts) + new ChartPanelSeparator(composite, separator); + + for(String e : expandedCharts) { new ChartPanelElement(composite, this, e, SWT.NONE); + new ChartPanelSeparator(composite, separator).addMouseListener(new SCFocusListener()); + } if(!minimizedCharts.isEmpty()) { Composite minimized = new Composite(composite, SWT.NONE); - GridDataFactory.fillDefaults().hint(ChartPanelHeader.HEADER_MINIMUM_WIDTH, SWT.DEFAULT).applyTo(minimized); + GridDataFactory.fillDefaults().grab(true, false).hint(ChartPanelHeader.HEADER_MINIMUM_WIDTH, SWT.DEFAULT).applyTo(minimized); GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(minimized); - for(String m : minimizedCharts) + for(String m : minimizedCharts) { new ChartPanelHeader(minimized, this, m, SWT.BORDER); + new ChartPanelSeparator(minimized, SWT.VERTICAL).addMouseListener(new SCFocusListener()); + } } - parent.layout(); + body.layout(); sc.setMinSize(body.computeSize(SWT.DEFAULT, SWT.DEFAULT)); saveState(); @@ -160,8 +181,8 @@ public class ChartPanel extends ViewPart { @Override public void setFocus() { - if(!body.isDisposed()) - body.setFocus(); + if(!sc.isDisposed()) + sc.setFocus(); } @Override @@ -216,8 +237,7 @@ public class ChartPanel extends ViewPart { expandedCharts.add(expandedCharts.isEmpty() ? 0 : expandedCharts.size(), chart); else minimizedCharts.add(0, chart); - - createContents(body); + refresh(); } /** @@ -230,7 +250,79 @@ public class ChartPanel extends ViewPart { this.vertical = true; else this.vertical = false; + refresh(); + } + + /** + * Removes a chart from this panel + * + * @param chart The name of the chart to be removed + */ + public void removeChart(String chart) { + if(this.expandedCharts.contains(chart)) + this.expandedCharts.remove(chart); + else if(this.minimizedCharts.contains(chart)) + this.minimizedCharts.remove(chart); + refresh(); + } + + + /** + * Convenience method for refreshing the contents of the panel + */ + private void refresh() { + createContents(); + } + + + /** + * Sets up drag-scrolling for a scrolled composite + * + * @param control + */ + protected void setupDropTarget(final ScrolledComposite sc) { + DropTarget target = new DropTarget(sc, DND.DROP_NONE); + target.setTransfer(new Transfer[] { LocalObjectTransfer.getTransfer() }); - createContents(body); + target.addDropListener(new DropTargetAdapter() { + + private int activeMargin = 20; + private int moveAmount = 1; + + @Override + public void dragOver(DropTargetEvent event) { + Point original = sc.getOrigin(); + Point origin = sc.getOrigin(); + Point pointer = sc.toControl(event.x, event.y); + Rectangle bounds = sc.getBounds(); + + if(pointer.y < activeMargin) + origin.y = origin.y - moveAmount; + else if(bounds.height - pointer.y < activeMargin) + origin.y = origin.y + moveAmount; + if(pointer.x < activeMargin) + origin.x = origin.x - moveAmount; + else if(bounds.width - pointer.x < activeMargin) + origin.x = origin.x + moveAmount; + + if(origin != original) { + sc.setOrigin (origin.x, origin.y); + sc.redraw(); + } + } + + }); + + } + + /** + * Listener for directing focus to scrollableComposite + * @author Teemu Lempinen + * + */ + private class SCFocusListener extends MouseAdapter { + public void mouseDown(MouseEvent e) { + ChartPanel.this.setFocus(); + } } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanelHeader.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanelHeader.java index 558f8ccc..b710fad8 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanelHeader.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanelHeader.java @@ -17,7 +17,9 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; /** @@ -50,21 +52,26 @@ public class ChartPanelHeader extends Composite { GridLayoutFactory.fillDefaults().numColumns(3).applyTo(this); GridDataFactory.fillDefaults().grab(true, false).applyTo(this); + // Label for the chart name (also minimize/expand) Label label = new Label(this, SWT.NONE); label.setText(name); GridDataFactory.fillDefaults().grab(true, false).applyTo(label); - + label.addMouseListener(new MinimizeListener(label)); + label.setCursor(new Cursor(label.getDisplay(), SWT.CURSOR_HAND)); + + // Label for minimizing/expanding chart label = new Label(this, SWT.NONE); label.setText("^"); GridDataFactory.fillDefaults().applyTo(label); - label.addMouseListener(new MinimizeListener()); + label.addMouseListener(new MinimizeListener(label)); label.setCursor(new Cursor(label.getDisplay(), SWT.CURSOR_HAND)); - + // Label for closing/removing the chart label = new Label(this, SWT.NONE); label.setText("x"); GridDataFactory.fillDefaults().applyTo(label); - + label.addMouseListener(new RemoveChartListener(label)); + label.setCursor(new Cursor(label.getDisplay(), SWT.CURSOR_HAND)); } /** @@ -76,19 +83,71 @@ public class ChartPanelHeader extends Composite { */ private class MinimizeListener implements MouseListener { + private Control control; + + public MinimizeListener(Control control) { + this.control = control; + } + @Override public void mouseDoubleClick(MouseEvent e) { } @Override public void mouseDown(MouseEvent e) { + panel.setFocus(); } @Override public void mouseUp(MouseEvent e) { - if(!ChartPanelHeader.this.isDisposed()) + if(ChartPanelHeader.this.isDisposed()) + return; + + // Expand only if mouse was released inside the control + Rectangle bounds = control.getBounds(); + bounds.x = 0; + bounds.y = 0; + if(bounds.contains(e.x, e.y)) panel.expandChart(name); } } + /** + * Mouse listener for removing this chart from the chart panel. + * + * @author Teemu Lempinen + * + */ + private class RemoveChartListener implements MouseListener { + + Control control; + + public RemoveChartListener(Control control) { + this.control = control; + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + } + + @Override + public void mouseDown(MouseEvent e) { + panel.setFocus(); + } + + @Override + public void mouseUp(MouseEvent e) { + if(!ChartPanelHeader.this.isDisposed()) { + // Remove only if mouse was released inside the control + Rectangle bounds = control.getBounds(); + bounds.x = 0; + bounds.y = 0; + if(bounds.contains(e.x, e.y)) + panel.removeChart(name); + } + + + } + + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanelSeparator.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanelSeparator.java new file mode 100644 index 00000000..5b354ba0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/ChartPanelSeparator.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2007, 2011 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.sysdyn.ui.trend; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +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.Transfer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.simantics.ui.dnd.LocalObjectTransfer; + +/** + * Class for separating charts in {@link ChartPanel}. Acts as a drop participant for adding + * and moving charts in {@link ChartPanel}. + * + * @author Teemu Lempinen + * + */ +public class ChartPanelSeparator extends Composite { + + /** + * Set up a small horizontal or vertical separator depending on SWT style + * + * @param parent + * @param style + */ + public ChartPanelSeparator(Composite parent, int style) { + super(parent, SWT.NONE); + if((style & SWT.VERTICAL) > 0) { + GridDataFactory.fillDefaults().grab(true, false).applyTo(this); + GridLayoutFactory.fillDefaults().margins(0, 2).applyTo(this); + } else if((style & SWT.HORIZONTAL) > 0) { + GridDataFactory.fillDefaults().grab(false, true).applyTo(this); + GridLayoutFactory.fillDefaults().margins(2, 0).applyTo(this); + } + setupDropTarget(this); + } + + /** + * Set up the drop target for this separator + * + * @param control + */ + protected void setupDropTarget(Control control) { + DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_LINK); + target.setTransfer(new Transfer[] { LocalObjectTransfer.getTransfer() }); + target.addDropListener(new DropTargetAdapter() { + + Composite composite = ChartPanelSeparator.this; + Display display = composite.getDisplay(); + + @Override + public void dragEnter(DropTargetEvent event) { + event.detail = DND.DROP_COPY; + composite.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); + } + + @Override + public void dragLeave(DropTargetEvent event) { + composite.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); + } + + @Override + public void drop(DropTargetEvent event) { + } + + @Override + public void dropAccept(DropTargetEvent event) { + } + + @Override + public void dragOver(DropTargetEvent event) { + } + }); + } +} -- 2.47.1