1 /* 2 * VideoController.java 15 fev 2010 3 * 4 * Sweet Home 3D, Copyright (c) 2010 Emmanuel PUYBARET / eTeks <info@eteks.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 package com.eteks.sweethome3d.viewcontroller; 21 22 import java.beans.PropertyChangeEvent; 23 import java.beans.PropertyChangeListener; 24 import java.beans.PropertyChangeSupport; 25 import java.lang.ref.WeakReference; 26 import java.util.List; 27 28 import com.eteks.sweethome3d.model.AspectRatio; 29 import com.eteks.sweethome3d.model.Camera; 30 import com.eteks.sweethome3d.model.Home; 31 import com.eteks.sweethome3d.model.HomeEnvironment; 32 import com.eteks.sweethome3d.model.UserPreferences; 33 34 /** 35 * The controller of the video creation view. 36 * @author Emmanuel Puybaret 37 */ 38 public class VideoController implements Controller { 39 /** 40 * The properties that may be edited by the view associated to this controller. 41 */ 42 public enum Property {ASPECT_RATIO, FRAME_RATE, WIDTH, HEIGHT, QUALITY, SPEED, CAMERA_PATH, TIME, CEILING_LIGHT_COLOR} 43 44 private final Home home; 45 private final UserPreferences preferences; 46 private final ViewFactory viewFactory; 47 private final ContentManager contentManager; 48 private final PropertyChangeSupport propertyChangeSupport; 49 private DialogView videoView; 50 51 private AspectRatio aspectRatio; 52 private int frameRate; 53 private int width; 54 private int height; 55 private int quality; 56 private float speed; 57 private List<Camera> cameraPath; 58 private long time; 59 private int ceilingLightColor; 60 VideoController(Home home, UserPreferences preferences, ViewFactory viewFactory, ContentManager contentManager)61 public VideoController(Home home, 62 UserPreferences preferences, 63 ViewFactory viewFactory, 64 ContentManager contentManager) { 65 this.home = home; 66 this.preferences = preferences; 67 this.viewFactory = viewFactory; 68 this.contentManager = contentManager; 69 this.propertyChangeSupport = new PropertyChangeSupport(this); 70 71 updateProperties(); 72 home.getEnvironment().addPropertyChangeListener(HomeEnvironment.Property.CEILING_LIGHT_COLOR, new HomeEnvironmentChangeListener(this)); 73 } 74 75 /** 76 * Home environment listener that updates properties. This listener is bound to this controller 77 * with a weak reference to avoid strong link between home and this controller. 78 */ 79 private static class HomeEnvironmentChangeListener implements PropertyChangeListener { 80 private WeakReference<VideoController> videoController; 81 HomeEnvironmentChangeListener(VideoController videoController)82 public HomeEnvironmentChangeListener(VideoController videoController) { 83 this.videoController = new WeakReference<VideoController>(videoController); 84 } 85 propertyChange(PropertyChangeEvent ev)86 public void propertyChange(PropertyChangeEvent ev) { 87 // If controller was garbage collected, remove this listener from home 88 final VideoController controller = this.videoController.get(); 89 if (controller == null) { 90 ((HomeEnvironment)ev.getSource()).removePropertyChangeListener(HomeEnvironment.Property.CEILING_LIGHT_COLOR, this); 91 } else { 92 controller.updateProperties(); 93 } 94 } 95 } 96 97 /** 98 * Returns the view associated with this controller. 99 */ getView()100 public DialogView getView() { 101 // Create view lazily only once it's needed 102 if (this.videoView == null) { 103 this.videoView = this.viewFactory.createVideoView(this.home, this.preferences, this); 104 } 105 return this.videoView; 106 } 107 108 /** 109 * Displays the view controlled by this controller. 110 */ displayView(View parentView)111 public void displayView(View parentView) { 112 getView().displayView(parentView); 113 } 114 115 /** 116 * Returns the content manager of this controller. 117 */ getContentManager()118 public ContentManager getContentManager() { 119 return this.contentManager; 120 } 121 122 /** 123 * Adds the property change <code>listener</code> in parameter to this controller. 124 */ addPropertyChangeListener(Property property, PropertyChangeListener listener)125 public void addPropertyChangeListener(Property property, PropertyChangeListener listener) { 126 this.propertyChangeSupport.addPropertyChangeListener(property.name(), listener); 127 } 128 129 /** 130 * Removes the property change <code>listener</code> in parameter from this controller. 131 */ removePropertyChangeListener(Property property, PropertyChangeListener listener)132 public void removePropertyChangeListener(Property property, PropertyChangeListener listener) { 133 this.propertyChangeSupport.removePropertyChangeListener(property.name(), listener); 134 } 135 136 /** 137 * Updates edited properties from the video creation preferences. 138 */ updateProperties()139 protected void updateProperties() { 140 HomeEnvironment homeEnvironment = this.home.getEnvironment(); 141 setFrameRate(homeEnvironment.getVideoFrameRate()); 142 setWidth(homeEnvironment.getVideoWidth(), false); 143 setHeight(homeEnvironment.getVideoHeight(), false); 144 setAspectRatio(homeEnvironment.getVideoAspectRatio()); 145 setQuality(homeEnvironment.getVideoQuality()); 146 setSpeed(homeEnvironment.getVideoSpeed()); 147 List<Camera> videoCameraPath = homeEnvironment.getVideoCameraPath(); 148 setCameraPath(videoCameraPath); 149 setTime(videoCameraPath.isEmpty() 150 ? this.home.getCamera().getTime() 151 : videoCameraPath.get(0).getTime()); 152 setCeilingLightColor(homeEnvironment.getCeillingLightColor()); 153 } 154 155 /** 156 * Sets the aspect ratio of the video. 157 */ setAspectRatio(AspectRatio aspectRatio)158 public void setAspectRatio(AspectRatio aspectRatio) { 159 if (this.aspectRatio != aspectRatio) { 160 AspectRatio oldAspectRatio = this.aspectRatio; 161 this.aspectRatio = aspectRatio; 162 this.propertyChangeSupport.firePropertyChange(Property.ASPECT_RATIO.name(), oldAspectRatio, aspectRatio); 163 this.home.getEnvironment().setVideoAspectRatio(this.aspectRatio); 164 setHeight(Math.round(this.width / this.aspectRatio.getValue()), false); 165 } 166 } 167 168 /** 169 * Returns the aspect ratio of the video. 170 */ getAspectRatio()171 public AspectRatio getAspectRatio() { 172 return this.aspectRatio; 173 } 174 175 /** 176 * Sets the frame rate of the video. 177 */ setFrameRate(int frameRate)178 public void setFrameRate(int frameRate) { 179 if (this.frameRate != frameRate) { 180 int oldFrameRate = this.frameRate; 181 this.frameRate = frameRate; 182 this.propertyChangeSupport.firePropertyChange(Property.QUALITY.name(), oldFrameRate, frameRate); 183 this.home.getEnvironment().setVideoFrameRate(this.frameRate); 184 } 185 } 186 187 /** 188 * Returns the frame rate of the video. 189 */ getFrameRate()190 public int getFrameRate() { 191 return this.frameRate; 192 } 193 194 /** 195 * Sets the width of the video. 196 */ setWidth(int width)197 public void setWidth(int width) { 198 setWidth(width, true); 199 } 200 setWidth(int width, boolean updateHeight)201 private void setWidth(int width, boolean updateHeight) { 202 if (this.width != width) { 203 int oldWidth = this.width; 204 this.width = width; 205 this.propertyChangeSupport.firePropertyChange(Property.WIDTH.name(), oldWidth, width); 206 if (updateHeight) { 207 setHeight(Math.round(width / this.aspectRatio.getValue()), false); 208 } 209 this.home.getEnvironment().setVideoWidth(this.width); 210 } 211 } 212 213 /** 214 * Returns the width of the video. 215 */ getWidth()216 public int getWidth() { 217 return this.width; 218 } 219 220 /** 221 * Sets the height of the video. 222 */ setHeight(int height)223 public void setHeight(int height) { 224 setHeight(height, true); 225 } 226 setHeight(int height, boolean updateWidth)227 private void setHeight(int height, boolean updateWidth) { 228 if (this.height != height) { 229 int oldHeight = this.height; 230 this.height = height; 231 this.propertyChangeSupport.firePropertyChange(Property.HEIGHT.name(), oldHeight, height); 232 if (updateWidth) { 233 setWidth(Math.round(height * this.aspectRatio.getValue()), false); 234 } 235 } 236 } 237 238 /** 239 * Returns the height of the video. 240 */ getHeight()241 public int getHeight() { 242 return this.height; 243 } 244 245 /** 246 * Sets the rendering quality of the video. 247 */ setQuality(int quality)248 public void setQuality(int quality) { 249 if (this.quality != quality) { 250 int oldQuality = this.quality; 251 this.quality = Math.min(quality, getQualityLevelCount() - 1); 252 this.propertyChangeSupport.firePropertyChange(Property.QUALITY.name(), oldQuality, quality); 253 this.home.getEnvironment().setVideoQuality(this.quality); 254 } 255 } 256 257 /** 258 * Returns the rendering quality of the video. 259 */ getQuality()260 public int getQuality() { 261 return this.quality; 262 } 263 264 /** 265 * Sets the preferred speed of movements in the video in m/s. 266 * @since 6.0 267 */ setSpeed(float speed)268 public void setSpeed(float speed) { 269 if (this.speed != speed) { 270 float oldSpeed = this.speed; 271 this.speed = speed; 272 this.propertyChangeSupport.firePropertyChange(Property.SPEED.name(), oldSpeed, speed); 273 this.home.getEnvironment().setVideoSpeed(this.speed); 274 } 275 } 276 277 /** 278 * Returns the preferred speed of movements in the video in m/s. 279 * @since 6.0 280 */ getSpeed()281 public float getSpeed() { 282 return this.speed; 283 } 284 285 /** 286 * Returns the maximum value for quality. 287 */ getQualityLevelCount()288 public int getQualityLevelCount() { 289 return 4; 290 } 291 292 /** 293 * Returns the camera path of the video. 294 */ getCameraPath()295 public List<Camera> getCameraPath() { 296 return this.cameraPath; 297 } 298 299 /** 300 * Sets the camera locations of the video. 301 */ setCameraPath(List<Camera> cameraPath)302 public void setCameraPath(List<Camera> cameraPath) { 303 if (this.cameraPath != cameraPath) { 304 List<Camera> oldCameraPath = this.cameraPath; 305 this.cameraPath = cameraPath; 306 this.propertyChangeSupport.firePropertyChange(Property.CAMERA_PATH.name(), oldCameraPath, cameraPath); 307 this.home.getEnvironment().setVideoCameraPath(this.cameraPath); 308 } 309 } 310 311 /** 312 * Sets the edited time in UTC time zone. 313 */ setTime(long time)314 public void setTime(long time) { 315 if (this.time != time) { 316 long oldTime = this.time; 317 this.time = time; 318 this.propertyChangeSupport.firePropertyChange(Property.TIME.name(), oldTime, time); 319 this.home.getCamera().setTime(time); 320 } 321 } 322 323 /** 324 * Returns the edited time in UTC time zone. 325 */ getTime()326 public long getTime() { 327 return this.time; 328 } 329 330 /** 331 * Sets the edited ceiling light color. 332 */ setCeilingLightColor(int ceilingLightColor)333 public void setCeilingLightColor(int ceilingLightColor) { 334 if (this.ceilingLightColor != ceilingLightColor) { 335 int oldCeilingLightColor = this.ceilingLightColor; 336 this.ceilingLightColor = ceilingLightColor; 337 this.propertyChangeSupport.firePropertyChange(Property.CEILING_LIGHT_COLOR.name(), oldCeilingLightColor, ceilingLightColor); 338 this.home.getEnvironment().setCeillingLightColor(ceilingLightColor); 339 } 340 } 341 342 /** 343 * Returns the edited ceiling light color. 344 */ getCeilingLightColor()345 public int getCeilingLightColor() { 346 return this.ceilingLightColor; 347 } 348 349 /** 350 * Controls the change of value of a visual property in home. 351 * @deprecated {@link #setVisualProperty(String, Object) setVisualProperty} should be replaced by a call to 352 * {@link #setHomeProperty(String, String) setHomeProperty} to ensure the property can be easily saved and read. 353 */ setVisualProperty(String propertyName, Object propertyValue)354 public void setVisualProperty(String propertyName, 355 Object propertyValue) { 356 this.home.setVisualProperty(propertyName, propertyValue); 357 } 358 359 /** 360 * Controls the change of value of a property in home. 361 * @since 5.2 362 */ setHomeProperty(String propertyName, String propertyValue)363 public void setHomeProperty(String propertyName, 364 String propertyValue) { 365 this.home.setProperty(propertyName, propertyValue); 366 } 367 } 368