/*******************************************************************************
* Copyright (c) 2016 Weasis Team 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:
* Nicolas Roduit - initial API and implementation
*******************************************************************************/
package org.weasis.core.ui.model.utils.imp;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import org.weasis.core.api.gui.model.ViewModel;
import org.weasis.core.api.gui.model.ViewModelChangeListener;
import org.weasis.core.api.gui.util.MathUtil;
/**
* The Class DefaultViewModel.
*
* @author Nicolas Roduit
*/
public class DefaultViewModel implements ViewModel {
/**
* The x-offset in model coordinates of the upper left view pixel
*/
private double modelOffsetX;
/**
* The y-offset in model coordinates of the upper left view pixel
*/
private double modelOffsetY;
/**
* The current view scale
*/
private double viewScale;
/**
* The maximum view scale. Minimum is given as 1.0 / viewScaleMax.
*/
private double viewScaleMax;
private double viewScaleMin;
public static final double SCALE_MIN = 1.0 / 12.0;
public static final double SCALE_MAX = 12.0;
/**
* This view model's area. Enables scrolling with scroll bars.
*/
private Rectangle2D modelArea;
/**
* The list of change listeners
*/
private final ArrayList<ViewModelChangeListener> viewModelChangeListenerList;
private boolean enableViewModelChangeListeners;
public DefaultViewModel(double viewScaleMin, double viewScaleMax) {
this.modelOffsetX = 0;
this.modelOffsetY = 0;
this.viewScale = 1.0;
this.viewScaleMin = viewScaleMin;
this.viewScaleMax = viewScaleMax;
this.modelArea = new Rectangle2D.Double();
this.viewModelChangeListenerList = new ArrayList<>();
this.enableViewModelChangeListeners = true;
}
public DefaultViewModel() {
this(SCALE_MIN, SCALE_MAX);
}
public boolean isEnableViewModelChangeListeners() {
return enableViewModelChangeListeners;
}
public void setEnableViewModelChangeListeners(boolean enableViewModelChangeListeners) {
this.enableViewModelChangeListeners = enableViewModelChangeListeners;
}
@Override
public double getModelOffsetX() {
return modelOffsetX;
}
@Override
public double getModelOffsetY() {
return modelOffsetY;
}
@Override
public void setModelOffset(double modelOffsetX, double modelOffsetY) {
if (MathUtil.isDifferent(this.modelOffsetX, modelOffsetX)
|| MathUtil.isDifferent(this.modelOffsetY, modelOffsetY)) {
this.modelOffsetX = modelOffsetX;
this.modelOffsetY = modelOffsetY;
fireViewModelChanged();
}
}
@Override
public void setModelOffset(double modelOffsetX, double modelOffsetY, double viewScale) {
double scale = maybeCropViewScale(viewScale);
if (MathUtil.isDifferent(this.modelOffsetX, modelOffsetX)
|| MathUtil.isDifferent(this.modelOffsetY, modelOffsetY)
|| MathUtil.isDifferent(this.viewScale, scale)) {
this.modelOffsetX = modelOffsetX;
this.modelOffsetY = modelOffsetY;
this.viewScale = scale;
fireViewModelChanged();
}
}
@Override
public double getViewScale() {
return viewScale;
}
@Override
public void setViewScale(double viewScale) {
double scale = maybeCropViewScale(viewScale);
if (MathUtil.isDifferent(this.viewScale, scale)) {
this.viewScale = scale;
fireViewModelChanged();
}
}
@Override
public double getViewScaleMax() {
return viewScaleMax;
}
@Override
public void setViewScaleMax(double viewScaleMax) {
this.viewScaleMax = viewScaleMax;
}
@Override
public Rectangle2D getModelArea() {
return new Rectangle2D.Double(modelArea.getX(), modelArea.getY(), modelArea.getWidth(), modelArea.getHeight());
}
@Override
public double getViewScaleMin() {
return viewScaleMin;
}
@Override
public void setModelArea(Rectangle2D modelArea) {
if (!this.modelArea.equals(modelArea)) {
this.modelArea =
new Rectangle2D.Double(modelArea.getX(), modelArea.getY(), modelArea.getWidth(), modelArea.getHeight());
fireViewModelChanged();
}
}
@Override
public void setViewScaleMin(double viewScaleMin) {
this.viewScaleMin = viewScaleMin;
}
@Override
public ViewModelChangeListener[] getViewModelChangeListeners() {
final ViewModelChangeListener[] viewModelChangeListeners =
new ViewModelChangeListener[viewModelChangeListenerList.size()];
return viewModelChangeListenerList.toArray(viewModelChangeListeners);
}
@Override
public void addViewModelChangeListener(ViewModelChangeListener l) {
if (l != null && !viewModelChangeListenerList.contains(l)) {
viewModelChangeListenerList.add(l);
}
}
@Override
public void removeViewModelChangeListener(ViewModelChangeListener l) {
if (l != null) {
viewModelChangeListenerList.remove(l);
}
}
protected void fireViewModelChanged() {
if (enableViewModelChangeListeners) {
for (int i = 0; i < viewModelChangeListenerList.size(); i++) {
ViewModelChangeListener l = viewModelChangeListenerList.get(i);
l.handleViewModelChanged(this);
}
}
}
public static double cropViewScale(double viewScale, final double viewScaleMin, final double viewScaleMax) {
if (viewScaleMax > 1.0) {
if (viewScale < viewScaleMin) {
return viewScaleMin;
} else if (viewScale > viewScaleMax) {
return viewScaleMax;
}
}
return viewScale;
}
private double maybeCropViewScale(double viewScale) {
return cropViewScale(viewScale, getViewScaleMin(), getViewScaleMax());
}
public void adjustMinViewScaleFromImage(int width, int height) {
double ratio = 250.0 / (width > height ? width : height);
if (ratio < viewScaleMin) {
this.viewScaleMin = ratio;
}
}
}