/******************************************************************************* * Copyright (c) 2015, 2016 itemis 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: * Matthias Wienand (itemis AG) - initial API & implementation * Alexander Nyßen (itemis AG) - refactorings * *******************************************************************************/ package org.eclipse.gef.zest.fx.models; import java.util.IdentityHashMap; import java.util.Map; import java.util.Set; import org.eclipse.gef.geometry.planar.AffineTransform; import org.eclipse.gef.graph.Graph; /** * The {@link NavigationModel} manages a {@link Set} of {@link Graph}s for which * the next layout pass should be skipped (due to transformation or navigation * changes). Moreover, it manages a {@link Map} saving a {@link ViewportState} * per {@link Graph}, so that the scroll position and zoom factor can be * restored when navigating nested graphs. * * @author mwienand * @author anyssen * */ public class NavigationModel { /* * TODO: Store translateX, translateY, width, and height relative to the * underlying contents. */ /** * Representation of a viewport's state, which manifests itself in x and y * translation, width and height, as well as a contents transform. * * @author anyssen * */ public static class ViewportState { private double translateX = 0; private double translateY = 0; private double width = 0; private double height = 0; private AffineTransform contentsTransform = null; /** * Creates a new {@link ViewportState} with * <code>tx = ty = width = height = 0</code> and an identity transform. */ public ViewportState() { this(0, 0, 0, 0, new AffineTransform()); } /** * Creates a new {@link ViewportState} for the given translation, size, * and transform. * * @param translateX * The horizontal translation. * @param translateY * The vertical translation. * @param width * The viewport width. * @param height * The viewport height. * @param contentsTransform * The contents transform. */ public ViewportState(double translateX, double translateY, double width, double height, AffineTransform contentsTransform) { this.translateX = translateX; this.translateY = translateY; this.width = width; this.height = height; this.contentsTransform = contentsTransform; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } ViewportState other = (ViewportState) obj; if (contentsTransform == null) { if (other.contentsTransform != null) { return false; } } else if (!contentsTransform.equals(other.contentsTransform)) { return false; } if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height)) { return false; } if (Double.doubleToLongBits(translateX) != Double.doubleToLongBits(other.translateX)) { return false; } if (Double.doubleToLongBits(translateY) != Double.doubleToLongBits(other.translateY)) { return false; } if (Double.doubleToLongBits(width) != Double.doubleToLongBits(other.width)) { return false; } return true; } /** * Returns the contents transform associated with this * {@link ViewportState}. * * @return The contents transform. */ public AffineTransform getContentsTransform() { return contentsTransform; } /** * Returns a copy of this {@link ViewportState}. * * @return A copy of this {@link ViewportState}. */ public ViewportState getCopy() { return new ViewportState(translateX, translateY, width, height, contentsTransform.getCopy()); } /** * Returns the viewport height associated with this * {@link ViewportState}. * * @return The viewport height. */ public double getHeight() { return height; } /** * Returns the horizontal translation associated with this * {@link ViewportState}. * * @return The horizontal translation. */ public double getTranslateX() { return translateX; } /** * Returns the vertical translation associated with this * {@link ViewportState}. * * @return The vertical translation. */ public double getTranslateY() { return translateY; } /** * Returns the viewport width associated with this {@link ViewportState} * . * * @return The viewport width. */ public double getWidth() { return width; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((contentsTransform == null) ? 0 : contentsTransform.hashCode()); long temp; temp = Double.doubleToLongBits(height); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(translateX); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(translateY); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(width); result = prime * result + (int) (temp ^ (temp >>> 32)); return result; } } private Map<Graph, ViewportState> viewportStates = new IdentityHashMap<>(); /** * Default constructor. */ public NavigationModel() { } /** * Retrieves the {@link ViewportState} that is currently saved for the given * {@link Graph}. * * @param graph * The {@link Graph} of which the saved {@link ViewportState} is * returned. * @return The {@link ViewportState} that was saved for the given * {@link Graph}. */ public ViewportState getViewportState(Graph graph) { return viewportStates.get(graph); } /** * Removes the {@link ViewportState} for the given {@link Graph}. * * @param graph * The {@link Graph} for which to remove the * {@link ViewportState}. */ public void removeViewportState(Graph graph) { viewportStates.remove(graph); } /** * Saves the given {@link ViewportState} for the given {@link Graph}. * * @param graph * The {@link Graph} for which to save a {@link ViewportState}. * @param state * The {@link ViewportState} that is saved for the given * {@link Graph}. */ public void setViewportState(Graph graph, ViewportState state) { viewportStates.put(graph, state); } }