/* Copyright (C) 2005-2011 Fabio Riccardi */
package com.lightcrafts.ui.editor;
import com.lightcrafts.model.Engine;
import com.lightcrafts.model.Scale;
import java.util.*;
/** This is a model for zoom-related actions on Engine Scales. It maintains
* a List of Scales obtained from an Engine, in sorted order. keeps track of
* the current Scale and defines the next-larges and next-smallest neighbor
* Scales. It also enables and disables two corresponding actions, so long
* as all Scale changes happen through <code>setScale()</code>.
*/
public class ScaleModel {
private final static Scale MinScale = new Scale(1, 40);
private final static Scale MaxScale = new Scale(12, 1);
private Engine engine;
private ArrayList<Scale> scales; // A copy of engine.getPreferredScales();
private int index; // The current scale from the scales List
private Scale offScale; // The current Scale if it is not from the List
private LinkedList<ScaleListener> listeners;
/** Construct a ScaleModel with the Scale set to 1:1.
*/
ScaleModel(Engine engine) {
this(engine, new Scale(1, 1));
}
/** Construct a Scale model with the Scale set to a given Scale.
*/
ScaleModel(Engine engine, Scale scale) {
this.engine = engine;
scales = new ArrayList(engine.getPreferredScales());
Collections.sort(scales);
listeners = new LinkedList<ScaleListener>();
setScale(scale);
}
public List<Scale> getScales() {
return new ArrayList<Scale>(scales);
}
public Scale getCurrentScale() {
if (offScale != null) {
return offScale;
}
return scales.get(index);
}
public boolean setScale(Scale scale) {
if ((scale.compareTo(MinScale) < 0) || scale.compareTo(MaxScale) > 0) {
return false;
}
int i = getIndexOf(scale);
if (i >= 0) {
index = i;
offScale = null;
}
else {
offScale = scale;
}
engine.setScale(scale);
notifyListeners();
return true;
}
public void addScaleListener(ScaleListener listener) {
listeners.add(listener);
}
public void removeScaleListener(ScaleListener listener) {
listeners.remove(listener);
}
private void notifyListeners() {
Scale scale = getCurrentScale();
for (ScaleListener listener : listeners) {
listener.scaleChanged(scale);
}
}
public boolean scaleUp() {
Scale scale = getNextScaleUp();
return setScale(scale);
}
public boolean scaleDown() {
Scale scale = getNextScaleDown();
return setScale(scale);
}
boolean scaleBy(float percent) {
Scale scale = getCurrentScale();
float factor = scale.getFactor();
factor *= percent;
scale = new Scale(factor);
return setScale(scale);
}
private Scale getNextScaleUp() {
Scale current = getCurrentScale();
for (Scale next : scales) {
if (next.compareTo(current) > 0) {
return next;
}
}
return null;
}
private Scale getNextScaleDown() {
Scale current = getCurrentScale();
for (int n=scales.size()-1; n>= 0; n--) {
Scale next = scales.get(n);
if (next.compareTo(current) < 0) {
return next;
}
}
return null;
}
public boolean canScaleUp() {
return getNextScaleUp() != null;
}
public boolean canScaleDown() {
return getNextScaleDown() != null;
}
private int getIndexOf(Scale scale) {
for (int n=0; n<scales.size(); n++) {
Scale s = scales.get(n);
if (s.equals(scale)) {
return n;
}
}
return -1;
}
}