/*****************************************************************************
* Copyright (c) 2014 Montages AG and others
*
*
* 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:
* Anatoly Tishenko (ticher777@gmail.com) - Initial API and implementation
*/
package org.eclipse.gmf.tooling.examples.linklf.diagram.edit.parts;
import java.beans.PropertyChangeListener;
import org.eclipse.draw2d.FreeformViewport;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LayoutAnimator;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.RangeModel;
import org.eclipse.draw2d.ScrollBar;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Translatable;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.SnapToGrid;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart;
import org.eclipse.gmf.runtime.diagram.ui.figures.BorderItemsAwareFreeFormLayer;
import org.eclipse.gmf.runtime.diagram.ui.figures.ResizableCompartmentFigure;
import org.eclipse.gmf.runtime.diagram.ui.figures.ShapeCompartmentFigure;
import org.eclipse.gmf.runtime.diagram.ui.layout.FreeFormLayoutEx;
import org.eclipse.gmf.runtime.draw2d.ui.internal.figures.AnimatableScrollPane;
import org.eclipse.gmf.runtime.draw2d.ui.internal.figures.OverlayScrollPaneLayout;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.IMapMode;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.gmf.tooling.runtime.linklf.DiagramGridSpec.GridSpecListener;
public class LinksLFCompartmentEditPart extends ShapeCompartmentEditPart {
private final GridSpecListener myGridListener = new GridSpecListener() {
@Override
public void gridSpecChanged() {
updateGridBehavior();
}
};
public LinksLFCompartmentEditPart(View view) {
super(view);
}
@Override
public IFigure createFigure() {
ShapeCompartmentFigure result = new ShapeCompartmentFigureEx(getCompartmentName(), getMapMode());
result.getContentPane().setLayoutManager(getLayoutManager());
result.getContentPane().addLayoutListener(LayoutAnimator.getDefault());
return result;
}
@Override
public void addNotify() {
super.addNotify();
getViewer().addPropertyChangeListener(myGridListener);
updateGridBehavior();
}
@Override
public void removeNotify() {
getViewer().removePropertyChangeListener(myGridListener);
super.removeNotify();
}
protected void updateGridBehavior() {
Rectangle gridSpec = getGridSpec(getViewer());
if (gridSpec != null) {
setScrollGridBehaviour((ResizableCompartmentFigure) getFigure());
}
}
protected void setScrollGridBehaviour(ResizableCompartmentFigure compartmentFigure) {
ScrollPane sp = compartmentFigure.getScrollPane();
decorateHorizontalRange(sp);
decorateVerticalRange(sp);
updateStepIncrements(sp);
}
private void updateStepIncrements(ScrollPane pane) {
Rectangle gridSpec = getGridSpec(getViewer());
if (gridSpec == null) {
return;
}
ScrollBar hScroll = pane.getHorizontalScrollBar();
hScroll.setStepIncrement(gridSpec.height);
ScrollBar wScroll = pane.getVerticalScrollBar();
wScroll.setStepIncrement(gridSpec.width);
}
private void decorateVerticalRange(ScrollPane pane) {
ScrollBar scroll = pane.getVerticalScrollBar();
RangeModel model = scroll.getRangeModel();
if (false == model instanceof SnapToGridRangeModel) {
SnapToGridRangeModel range = new SnapToGridRangeModel(model);
scroll.setRangeModel(range);
pane.getViewport().setVerticalRangeModel(range);
}
}
private void decorateHorizontalRange(ScrollPane pane) {
ScrollBar scroll = pane.getHorizontalScrollBar();
RangeModel model = scroll.getRangeModel();
if (false == model instanceof SnapToGridRangeModel) {
SnapToGridRangeModel range = new SnapToGridRangeModel(model);
scroll.setRangeModel(range);
pane.getViewport().setHorizontalRangeModel(range);
}
}
protected static Rectangle getGridSpec(EditPartViewer viewer) {
Boolean enabled = (Boolean) viewer.getProperty(SnapToGrid.PROPERTY_GRID_ENABLED);
if (enabled == null || !enabled) {
return null;
}
int gridX = 0;
int gridY = 0;
Point origin;
Dimension spacing = (Dimension) viewer.getProperty(SnapToGrid.PROPERTY_GRID_SPACING);
if (spacing != null) {
gridX = spacing.width;
gridY = spacing.height;
}
if (gridX == 0) {
gridX = SnapToGrid.DEFAULT_GRID_SIZE;
}
if (gridY == 0) {
gridY = SnapToGrid.DEFAULT_GRID_SIZE;
}
Point loc = (Point) viewer.getProperty(SnapToGrid.PROPERTY_GRID_ORIGIN);
if (loc != null) {
origin = loc;
} else {
origin = new Point();
}
return new Rectangle(origin.x, origin.y, gridX, gridY);
}
private class SnapToGridRangeModel implements RangeModel {
private final RangeModel myBaseRangeModel;
public SnapToGridRangeModel(RangeModel rangeModel) {
myBaseRangeModel = rangeModel;
}
@Override
public void setValue(int value) {
Rectangle gridSpec = getGridSpec(getViewer());
if (gridSpec != null) {
value = Math.max(value, 0);
value = gridSpec.height * (value / gridSpec.height);
}
if (value + getMinimum() <= getMaximum()) {
myBaseRangeModel.setValue(value);
}
}
@Override
public void setMinimum(int min) {
myBaseRangeModel.setMinimum(min);
}
@Override
public void setMaximum(int max) {
myBaseRangeModel.setMaximum(max);
}
@Override
public void setExtent(int extent) {
myBaseRangeModel.setExtent(extent);
}
@Override
public void setAll(int min, int extent, int max) {
myBaseRangeModel.setAll(min, extent, max);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
myBaseRangeModel.removePropertyChangeListener(listener);
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public int getValue() {
return myBaseRangeModel.getValue();
}
@Override
public int getMinimum() {
return myBaseRangeModel.getMinimum();
}
@Override
public int getMaximum() {
return myBaseRangeModel.getMaximum();
}
@Override
public int getExtent() {
return myBaseRangeModel.getExtent();
}
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
myBaseRangeModel.addPropertyChangeListener(listener);
}
}
public static class ShapeCompartmentFigureEx extends ShapeCompartmentFigure {
public ShapeCompartmentFigureEx(String title, IMapMode mm) {
super(title, mm);
}
@Override
protected void configureFigure(IMapMode mm) {
ScrollPane scrollpane = getScrollPane();
if (scrollpane == null) {
scrollpane = scrollPane = new AnimatableScrollPaneWithMM(mm);
}
scrollpane.setViewport(new FreeformViewport());
scrollPane.setScrollBarVisibility(ScrollPane.AUTOMATIC);
scrollpane.setLayoutManager(new OverlayScrollPaneLayout());
IFigure contents = new BorderItemsAwareFreeFormLayer();
contents.setLayoutManager(new FreeFormLayoutEx());
scrollpane.setContents(contents);
int MB = mm.DPtoLP(5);
scrollpane.setBorder(new MarginBorder(MB, MB, MB, MB));
int SZ = mm.DPtoLP(10);
scrollpane.setMinimumSize(new Dimension(SZ, SZ));
this.setFont(FONT_TITLE);
}
}
private static class AnimatableScrollPaneWithMM extends AnimatableScrollPane implements IMapMode {
private IMapMode myMapMode;
public AnimatableScrollPaneWithMM(IMapMode mm) {
myMapMode = mm;
}
@Override
public int LPtoDP(int logicalUnit) {
return myMapMode.LPtoDP(logicalUnit);
}
@Override
public int DPtoLP(int deviceUnit) {
return myMapMode.DPtoLP(deviceUnit);
}
@Override
public Translatable LPtoDP(Translatable t) {
return myMapMode.LPtoDP(t);
}
@Override
public Translatable DPtoLP(Translatable t) {
return myMapMode.DPtoLP(t);
}
}
}