/*
* CompassController.java 22 sept. 2010
*
* Sweet Home 3D, Copyright (c) 2010 Emmanuel PUYBARET / eTeks <info@eteks.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.eteks.sweethome3d.viewcontroller;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoableEdit;
import javax.swing.undo.UndoableEditSupport;
import com.eteks.sweethome3d.model.Compass;
import com.eteks.sweethome3d.model.Home;
import com.eteks.sweethome3d.model.UserPreferences;
/**
* A MVC controller for the compass view.
* @author Emmanuel Puybaret
*/
public class CompassController implements Controller {
/**
* The properties that may be edited by the view associated to this controller.
*/
public enum Property {X, Y, DIAMETER, VISIBLE, NORTH_DIRECTION_IN_DEGREES,
LATITUDE_IN_DEGREES, LONGITUDE_IN_DEGREES, TIME_ZONE}
private final Home home;
private final UserPreferences preferences;
private final ViewFactory viewFactory;
private final UndoableEditSupport undoSupport;
private final PropertyChangeSupport propertyChangeSupport;
private DialogView compassView;
private float x;
private float y;
private float diameter;
private boolean visible;
private float northDirectionInDegrees;
private float latitudeInDegrees;
private float longitudeInDegrees;
private String timeZone;
public CompassController(Home home,
UserPreferences preferences,
ViewFactory viewFactory,
UndoableEditSupport undoSupport) {
this.home = home;
this.preferences = preferences;
this.viewFactory = viewFactory;
this.undoSupport = undoSupport;
this.propertyChangeSupport = new PropertyChangeSupport(this);
updateProperties();
}
/**
* Returns the view associated with this controller.
*/
public DialogView getView() {
// Create view lazily only once it's needed
if (this.compassView == null) {
this.compassView = this.viewFactory.createCompassView(
this.preferences, this);
}
return this.compassView;
}
/**
* Displays the view controlled by this controller.
*/
public void displayView(View parentView) {
getView().displayView(parentView);
}
/**
* Adds the property change <code>listener</code> in parameter to this controller.
*/
public void addPropertyChangeListener(Property property, PropertyChangeListener listener) {
this.propertyChangeSupport.addPropertyChangeListener(property.name(), listener);
}
/**
* Removes the property change <code>listener</code> in parameter from this controller.
*/
public void removePropertyChangeListener(Property property, PropertyChangeListener listener) {
this.propertyChangeSupport.removePropertyChangeListener(property.name(), listener);
}
/**
* Updates compass properties edited by this controller.
*/
protected void updateProperties() {
Compass compass = this.home.getCompass();
setX(compass.getX());
setY(compass.getY());
setDiameter(compass.getDiameter());
setVisible(compass.isVisible());
setNorthDirectionInDegrees((float)Math.toDegrees(compass.getNorthDirection()));
setLatitudeInDegrees((float)Math.toDegrees(compass.getLatitude()));
setLongitudeInDegrees((float)Math.toDegrees(compass.getLongitude()));
setTimeZone(compass.getTimeZone());
}
/**
* Returns the edited abscissa of the center.
*/
public float getX() {
return this.x;
}
/**
* Sets the edited abscissa of the center.
*/
public void setX(float x) {
if (x != this.x) {
float oldX = this.x;
this.x = x;
this.propertyChangeSupport.firePropertyChange(Property.X.name(), oldX, x);
}
}
/**
* Returns the edited ordinate of the center.
*/
public float getY() {
return this.y;
}
/**
* Sets the edited ordinate of the center.
*/
public void setY(float y) {
if (y != this.y) {
float oldY = this.y;
this.y = y;
this.propertyChangeSupport.firePropertyChange(Property.Y.name(), oldY, y);
}
}
/**
* Returns the edited diameter.
*/
public float getDiameter() {
return this.diameter;
}
/**
* Sets the edited diameter.
*/
public void setDiameter(float diameter) {
if (diameter != this.diameter) {
float oldDiameter = this.diameter;
this.diameter = diameter;
this.propertyChangeSupport.firePropertyChange(Property.DIAMETER.name(), oldDiameter, diameter);
}
}
/**
* Returns whether compass is visible or not.
*/
public boolean isVisible() {
return this.visible;
}
/**
* Sets whether this compass is visible or not.
*/
public void setVisible(boolean visible) {
if (visible != this.visible) {
this.visible = visible;
this.propertyChangeSupport.firePropertyChange(Property.VISIBLE.name(), !visible, visible);
}
}
/**
* Returns the edited North direction angle in degrees.
*/
public float getNorthDirectionInDegrees() {
return this.northDirectionInDegrees;
}
/**
* Sets the edited North direction angle.
*/
public void setNorthDirectionInDegrees(float northDirectionInDegrees) {
if (northDirectionInDegrees != this.northDirectionInDegrees) {
float oldNorthDirectionInDegrees = this.northDirectionInDegrees;
this.northDirectionInDegrees = northDirectionInDegrees;
this.propertyChangeSupport.firePropertyChange(Property.NORTH_DIRECTION_IN_DEGREES.name(),
oldNorthDirectionInDegrees, northDirectionInDegrees);
}
}
/**
* Returns the edited latitude in degrees.
*/
public final float getLatitudeInDegrees() {
return this.latitudeInDegrees;
}
/**
* Sets the edited latitude in degrees.
*/
public void setLatitudeInDegrees(float latitudeInDegrees) {
if (latitudeInDegrees != this.latitudeInDegrees) {
float oldLatitudeInDegrees = this.latitudeInDegrees;
this.latitudeInDegrees = latitudeInDegrees;
this.propertyChangeSupport.firePropertyChange(Property.LATITUDE_IN_DEGREES.name(), oldLatitudeInDegrees, latitudeInDegrees);
}
}
/**
* Returns the edited longitude in degrees.
*/
public final float getLongitudeInDegrees() {
return this.longitudeInDegrees;
}
/**
* Sets the edited longitude of the center.
*/
public void setLongitudeInDegrees(float longitudeInDegrees) {
if (longitudeInDegrees != this.longitudeInDegrees) {
float oldLongitudeInDegrees = this.longitudeInDegrees;
this.longitudeInDegrees = longitudeInDegrees;
this.propertyChangeSupport.firePropertyChange(Property.LONGITUDE_IN_DEGREES.name(), oldLongitudeInDegrees, longitudeInDegrees);
}
}
/**
* Returns the edited time zone identifier.
*/
public String getTimeZone() {
return this.timeZone;
}
/**
* Sets the edited time zone identifier.
*/
public void setTimeZone(String timeZone) {
if (!timeZone.equals(this.timeZone)) {
String oldTimeZone = this.timeZone;
this.timeZone = timeZone;
this.propertyChangeSupport.firePropertyChange(Property.TIME_ZONE.name(), oldTimeZone, timeZone);
}
}
/**
* Modifies home compass from the values stored in this controller.
*/
public void modifyCompass() {
float x = getX();
float y = getY();
float diameter = getDiameter();
boolean visible = isVisible();
float northDirection = (float)Math.toRadians(getNorthDirectionInDegrees());
float latitude = (float)Math.toRadians(getLatitudeInDegrees());
float longitude = (float)Math.toRadians(getLongitudeInDegrees());
String timeZone = getTimeZone();
UndoableEdit undoableEdit =
new CompassUndoableEdit(this.home.getCompass(), this.preferences,
x, y, diameter, visible, northDirection, latitude, longitude, timeZone);
doModifyCompass(this.home.getCompass(), x, y, diameter, visible, northDirection, latitude, longitude, timeZone);
this.undoSupport.postEdit(undoableEdit);
}
/**
* Undoable edit for compass. This class isn't anonymous to avoid
* being bound to controller and its view.
*/
private static class CompassUndoableEdit extends AbstractUndoableEdit {
private final Compass compass;
private final UserPreferences preferences;
private final float oldX;
private final float oldY;
private final float oldDiameter;
private final float oldNorthDirection;
private final float oldLatitude;
private final float oldLongitude;
private final String oldTimeZone;
private final boolean oldVisible;
private final float newX;
private final float newY;
private final float newDiameter;
private final float newNorthDirection;
private final float newLatitude;
private final float newLongitude;
private final String newTimeZone;
private final boolean newVisible;
public CompassUndoableEdit(Compass compass, UserPreferences preferences, float newX, float newY,
float newDiameter, boolean newVisible, float newNorthDirection,
float newLatitude, float newLongitude, String newTimeZone) {
this.compass = compass;
this.preferences = preferences;
this.oldX = compass.getX();
this.oldY = compass.getY();
this.oldDiameter = compass.getDiameter();
this.oldVisible = compass.isVisible();
this.oldNorthDirection = compass.getNorthDirection();
this.oldLatitude = compass.getLatitude();
this.oldLongitude = compass.getLongitude();
this.oldTimeZone = compass.getTimeZone();
this.newX = newX;
this.newY = newY;
this.newDiameter = newDiameter;
this.newVisible = newVisible;
this.newNorthDirection = newNorthDirection;
this.newLatitude = newLatitude;
this.newLongitude = newLongitude;
this.newTimeZone = newTimeZone;
}
@Override
public void undo() throws CannotUndoException {
super.undo();
doModifyCompass(this.compass, this.oldX, this.oldY, this.oldDiameter, this.oldVisible,
this.oldNorthDirection, this.oldLatitude, this.oldLongitude, this.oldTimeZone);
}
@Override
public void redo() throws CannotRedoException {
super.redo();
doModifyCompass(this.compass, this.newX, this.newY, this.newDiameter, this.newVisible,
this.newNorthDirection, this.newLatitude, this.newLongitude, this.newTimeZone);
}
@Override
public String getPresentationName() {
return this.preferences.getLocalizedString(CompassController.class, "undoModifyCompassName");
}
}
private static void doModifyCompass(Compass compass, float x, float y, float diameter, boolean visible,
float northDirection, float latitude, float longitude, String timeZone) {
compass.setX(x);
compass.setY(y);
compass.setDiameter(diameter);
compass.setVisible(visible);
compass.setNorthDirection(northDirection);
compass.setLatitude(latitude);
compass.setLongitude(longitude);
compass.setTimeZone(timeZone);
}
}