// Copyright 2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.android.stardroid.control; import com.google.android.stardroid.base.VisibleForTesting; import com.google.android.stardroid.units.GeocentricCoordinates; import com.google.android.stardroid.util.MiscUtil; import android.content.Context; import android.util.Log; import java.util.ArrayList; import java.util.Date; /** * Manages all the different controllers that affect the model of the observer. * Is both a factory and acts as a facade to the underlying controllers. * * @author John Taylor */ public class ControllerGroup implements Controller { private final static String TAG = MiscUtil.getTag(ControllerGroup.class); private final ArrayList<Controller> controllers = new ArrayList<Controller>(); private ZoomController zoomController; private ManualOrientationController manualDirectionController; private SensorOrientationController sensorOrientationController; private TimeTravelClock timeTravelClock = new TimeTravelClock(); private TransitioningCompositeClock transitioningClock = new TransitioningCompositeClock( timeTravelClock, new RealClock()); private TeleportingController teleportingController; private boolean usingAutoMode = true; private AstronomerModel model; /** * Creates controller group, fully populated with the required subcontrollers. */ public static ControllerGroup createControllerGroup(Context context) { ControllerGroup group = new ControllerGroup(); group.addController(new LocationController(context)); group.sensorOrientationController = new SensorOrientationController(context); group.addController(group.sensorOrientationController); group.manualDirectionController = new ManualOrientationController(); group.addController(group.manualDirectionController); group.zoomController = new ZoomController(); group.addController(group.zoomController); group.teleportingController = new TeleportingController(); group.addController(group.teleportingController); group.setAutoMode(true); return group; } /** * Clients will generally use the factory method * {@link #createControllerGroup(Context)}. */ @VisibleForTesting public ControllerGroup() { } @Override public void setEnabled(boolean enabled) { Log.i(TAG, "Enabling all controllers"); for (Controller controller : controllers) { controller.setEnabled(enabled); } } @Override public void setModel(AstronomerModel model) { Log.i(TAG, "Setting model"); for (Controller controller : controllers) { controller.setModel(model); } this.model = model; model.setAutoUpdatePointing(usingAutoMode); model.setClock(transitioningClock); } /** * Switches to time-travel model and start with the supplied time. * See {@link #useRealTime()}. */ public void goTimeTravel(Date d) { transitioningClock.goTimeTravel(d); } /** * Gets the id of the string used to display the current speed of time travel. */ public int getCurrentSpeedTag() { return timeTravelClock.getCurrentSpeedTag(); } /** * Sets the model back to using real time. * See {@link #goTimeTravel(Date)}. */ public void useRealTime() { transitioningClock.returnToRealTime(); } /** * Increases the rate of time travel into the future (or decreases the rate of * time travel into the past) if in time travel mode. */ public void accelerateTimeTravel() { timeTravelClock.accelerateTimeTravel(); } /** * Decreases the rate of time travel into the future (or increases the rate of * time travel into the past) if in time travel mode. */ public void decelerateTimeTravel() { timeTravelClock.decelerateTimeTravel(); } /** * Pauses time, if in time travel mode. */ public void pauseTime() { timeTravelClock.pauseTime(); } /** * Are we in auto mode (aka sensor mode) or manual? */ public boolean isAutoMode() { return usingAutoMode; } /** * Sets auto mode (true) or manual mode (false). */ public void setAutoMode(boolean enabled) { manualDirectionController.setEnabled(!enabled); sensorOrientationController.setEnabled(enabled); if (model != null) { model.setAutoUpdatePointing(enabled); } usingAutoMode = enabled; } @Override public void start() { Log.i(TAG, "Starting controllers"); for (Controller controller : controllers) { controller.start(); } } @Override public void stop() { Log.i(TAG, "Stopping controllers"); for (Controller controller : controllers) { controller.stop(); } } /** * Moves the pointing right and left. * * @param radians the angular change in the pointing in radians (only * accurate in the limit as radians tends to 0.) */ public void changeRightLeft(float radians) { manualDirectionController.changeRightLeft(radians); } /** * Moves the pointing up and down. * * @param radians the angular change in the pointing in radians (only * accurate in the limit as radians tends to 0.) */ public void changeUpDown(float radians) { manualDirectionController.changeUpDown(radians); } /** * Rotates the view about the current center point. */ public void rotate(float degrees) { manualDirectionController.rotate(degrees); } /** * Zooms the user in. */ public void zoomIn() { zoomController.zoomIn(); } /** * Zooms the user out. */ public void zoomOut() { zoomController.zoomOut(); } /** * Sends the astronomer's pointing to the new target. * * @param target the destination */ public void teleport(GeocentricCoordinates target) { teleportingController.teleport(target); } /** * Adds a new controller to this group. */ @VisibleForTesting public void addController(Controller controller) { controllers.add(controller); } public void zoomBy(float ratio) { zoomController.zoomBy(ratio); } }