/*
* PhotoController.java 5 mai 2009
*
* Sweet Home 3D, Copyright (c) 2009 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.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.ref.WeakReference;
import com.eteks.sweethome3d.model.AspectRatio;
import com.eteks.sweethome3d.model.Camera;
import com.eteks.sweethome3d.model.Home;
import com.eteks.sweethome3d.model.UserPreferences;
/**
* The controller of the photo creation view.
* @author Emmanuel Puybaret
*/
public class PhotoController extends AbstractPhotoController {
/**
* The properties that may be edited by the view associated to this controller.
*/
public enum Property {TIME, LENS}
private final Home home;
private final UserPreferences preferences;
private final ViewFactory viewFactory;
private final PropertyChangeSupport propertyChangeSupport;
private final CameraChangeListener cameraChangeListener;
private DialogView photoView;
private long time;
private Camera.Lens lens;
public PhotoController(Home home,
UserPreferences preferences,
View view3D, ViewFactory viewFactory,
ContentManager contentManager) {
super(home, preferences, view3D, contentManager);
this.home = home;
this.preferences = preferences;
this.viewFactory = viewFactory;
this.propertyChangeSupport = new PropertyChangeSupport(this);
this.cameraChangeListener = new CameraChangeListener(this);
home.getCamera().addPropertyChangeListener(this.cameraChangeListener);
home.addPropertyChangeListener(Home.Property.CAMERA, new HomeCameraChangeListener(this));
updateProperties();
}
/**
* Home camera listener that updates properties when home camera changes. This listener is bound to this controller
* with a weak reference to avoid strong link between home and this controller.
*/
private static class HomeCameraChangeListener implements PropertyChangeListener {
private WeakReference<PhotoController> photoController;
public HomeCameraChangeListener(PhotoController photoController) {
this.photoController = new WeakReference<PhotoController>(photoController);
}
public void propertyChange(PropertyChangeEvent ev) {
// If controller was garbage collected, remove this listener from home
final PhotoController controller = this.photoController.get();
if (controller == null) {
((Home)ev.getSource()).removePropertyChangeListener(Home.Property.CAMERA, this);
} else {
((Camera)ev.getOldValue()).removePropertyChangeListener(controller.cameraChangeListener);
controller.updateProperties();
((Camera)ev.getNewValue()).addPropertyChangeListener(controller.cameraChangeListener);
}
}
}
/**
* Camera listener that updates properties when camera changes. This listener is bound to this controller
* with a weak reference to avoid strong link between home and this controller.
*/
private static class CameraChangeListener implements PropertyChangeListener {
private WeakReference<AbstractPhotoController> photoController;
public CameraChangeListener(AbstractPhotoController photoController) {
this.photoController = new WeakReference<AbstractPhotoController>(photoController);
}
public void propertyChange(PropertyChangeEvent ev) {
// If controller was garbage collected, remove this listener from camera
final AbstractPhotoController controller = this.photoController.get();
if (controller == null) {
((Camera)ev.getSource()).removePropertyChangeListener(this);
} else {
controller.updateProperties();
}
}
}
/**
* Returns the view associated with this controller.
*/
public DialogView getView() {
// Create view lazily only once it's needed
if (this.photoView == null) {
this.photoView = this.viewFactory.createPhotoView(this.home, this.preferences, this);
}
return this.photoView;
}
/**
* 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 edited properties from the photo creation preferences.
*/
protected void updateProperties() {
// Update properties only once this object is initialized
if (this.home != null) {
super.updateProperties();
setTime(this.home.getCamera().getTime());
setLens(this.home.getCamera().getLens());
}
}
/**
* Sets the edited time in UTC time zone.
*/
public void setTime(long time) {
if (this.time != time) {
long oldTime = this.time;
this.time = time;
this.propertyChangeSupport.firePropertyChange(Property.TIME.name(), oldTime, time);
Camera homeCamera = this.home.getCamera();
homeCamera.removePropertyChangeListener(this.cameraChangeListener);
homeCamera.setTime(time);
homeCamera.addPropertyChangeListener(this.cameraChangeListener);
}
}
/**
* Returns the edited time in UTC time zone.
*/
public long getTime() {
return this.time;
}
/**
* Sets the edited camera lens.
*/
public void setLens(Camera.Lens lens) {
if (this.lens != lens) {
Camera.Lens oldLens = this.lens;
this.lens = lens;
this.propertyChangeSupport.firePropertyChange(Property.LENS.name(), oldLens, lens);
if (lens == Camera.Lens.SPHERICAL) {
setAspectRatio(AspectRatio.RATIO_2_1);
} else if (lens == Camera.Lens.FISHEYE) {
setAspectRatio(AspectRatio.SQUARE_RATIO);
}
this.home.getCamera().setLens(this.lens);
}
}
/**
* Returns the edited camera lens.
*/
public Camera.Lens getLens() {
return this.lens;
}
}