| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * 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.motorola.studio.android.emulator.ui.controls.maindisplay; |
| |
| import static com.motorola.studio.android.common.log.StudioLogger.info; |
| |
| import java.util.Properties; |
| |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.sequoyah.vnc.vncviewer.graphics.IRemoteDisplay; |
| import org.eclipse.sequoyah.vnc.vncviewer.graphics.swt.SWTRemoteDisplay; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ControlAdapter; |
| import org.eclipse.swt.events.ControlEvent; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.KeyListener; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseListener; |
| import org.eclipse.swt.events.MouseMoveListener; |
| import org.eclipse.swt.events.MouseWheelListener; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Composite; |
| |
| import com.motorola.studio.android.adt.DDMSFacade; |
| import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance; |
| import com.motorola.studio.android.emulator.core.model.IInputLogic; |
| import com.motorola.studio.android.emulator.logic.AndroidLogicUtils; |
| import com.motorola.studio.android.emulator.skin.android.AndroidSkinTranslator; |
| import com.motorola.studio.android.emulator.ui.controls.IAndroidComposite; |
| import com.motorola.studio.android.emulator.ui.controls.UIHelper; |
| import com.motorola.studio.android.emulator.ui.handlers.IHandlerConstants; |
| import com.motorola.studio.android.nativeos.NativeUIUtils; |
| |
| /** |
| * This class is the composite that holds the main display and it is shown by |
| * the Emulator Main Display View. |
| */ |
| public class MainDisplayComposite extends Composite implements IAndroidComposite |
| { |
| |
| /** |
| * The zoom factor whose default value is 1.0 (100%) |
| */ |
| private double zoomFactor = 1.0; |
| |
| private double fitZoomfactor; |
| |
| // Minimum value to be used as zoom factor. This is necessary to avoid |
| // divisions to zero |
| private static final double MINIMUM_ZOOM_FACTOR = 0.0001; |
| |
| private static final double ZOOM_FIT = 0.0; |
| |
| /** |
| * The flag indicating that Ctrl key is pressed |
| */ |
| private boolean ctrlPressed = false; |
| |
| /** |
| * SWT key pressed/released events listener. |
| */ |
| private KeyListener keyListener; |
| |
| private MouseListener mouseListener; |
| |
| private MouseMoveListener mouseMoveListener; |
| |
| private IInputLogic androidInput; |
| |
| private boolean isMouseLeftButtonPressed; |
| |
| private boolean isFitToWindow; |
| |
| private IAndroidEmulatorInstance androidInstance; |
| |
| private Properties keyMap; |
| |
| /** |
| * Constructor |
| * |
| * @param parent |
| * composite |
| * @param style |
| * style |
| * @param baseWidth |
| * the default main display width |
| * @param baseHeight |
| * the default main display height |
| */ |
| public MainDisplayComposite(Composite parent, int style, int baseWidth, int baseHeight, |
| IAndroidEmulatorInstance instance) |
| { |
| super(parent, style); |
| |
| androidInput = instance.getInputLogic(); |
| |
| androidInstance = instance; |
| |
| isMouseLeftButtonPressed = false; |
| |
| keyMap = AndroidSkinTranslator.getQwertyKeyMap(); |
| |
| addListener(); |
| |
| if (!Platform.getOS().equals(Platform.OS_MACOSX)) |
| { |
| hideEmulatorWindow(); |
| } |
| |
| } |
| |
| private void hideEmulatorWindow() |
| { |
| int port = |
| AndroidLogicUtils.getEmulatorPort(DDMSFacade.getSerialNumberByName(androidInstance |
| .getName())); |
| long windowHandle = NativeUIUtils.getWindowHandle(androidInstance.getName(), port); |
| androidInstance.setWindowHandle(windowHandle); |
| |
| NativeUIUtils.hideWindow(windowHandle); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.swt.widgets.Widget#dispose() |
| */ |
| @Override |
| public void dispose() |
| { |
| if (androidInput != null) |
| { |
| androidInput.dispose(); |
| } |
| |
| keyListener = null; |
| mouseListener = null; |
| mouseMoveListener = null; |
| |
| if (!Platform.getOS().equals(Platform.OS_MACOSX)) |
| { |
| long hnd = androidInstance.getWindowHandle(); |
| if (hnd > 0) |
| { |
| NativeUIUtils.showWindow(hnd); |
| NativeUIUtils.restoreWindow(hnd); |
| } |
| |
| //Force update on redrawing |
| androidInstance.setWindowHandle(0); |
| } |
| |
| super.dispose(); |
| } |
| |
| /** |
| * Updates the composite size when zoom is changed. |
| * |
| * @param zoom |
| * the zoom factor |
| */ |
| public void setZoomFactor(double zoomFactor) |
| { |
| info("Update detached view composite size"); |
| if (zoomFactor == ZOOM_FIT) |
| { |
| isFitToWindow = true; |
| } |
| else |
| { |
| isFitToWindow = false; |
| } |
| this.zoomFactor = zoomFactor; |
| } |
| |
| /** |
| * Gets the zoom factor. |
| * |
| * @return zoom the zoom factor. |
| */ |
| public double getZoomFactor() |
| { |
| return zoomFactor; |
| } |
| |
| /** |
| * Applies the zoom factor to the components of the composite, updating the |
| * composite size to hold totally the main display. |
| */ |
| public void applyZoomFactor() |
| { |
| |
| SWTRemoteDisplay mainDisplay = UIHelper.getRemoteDisplayAssociatedToControl(this); |
| IRemoteDisplay.Rotation rotation = mainDisplay.getRotation(); |
| |
| int baseHeight; |
| int baseWidth; |
| |
| switch (rotation) |
| { |
| case ROTATION_90DEG_COUNTERCLOCKWISE: |
| baseHeight = mainDisplay.getScreenWidth(); |
| baseWidth = mainDisplay.getScreenHeight(); |
| break; |
| default: |
| baseHeight = mainDisplay.getScreenHeight(); |
| baseWidth = mainDisplay.getScreenWidth(); |
| |
| } |
| |
| int width; |
| int height; |
| if (isFitToWindow) |
| { |
| Rectangle clientArea = getParent().getClientArea(); |
| if ((clientArea.width == 0) || (clientArea.height == 0)) |
| { |
| // zoom factor cannot be zero, otherwise an |
| // IllegalArgumentException |
| // is raised in some SWT methods |
| fitZoomfactor = MINIMUM_ZOOM_FACTOR; |
| } |
| else |
| { |
| double widthRatio = (double) (clientArea.width) / baseWidth; |
| double heightRatio = (double) (clientArea.height) / baseHeight; |
| fitZoomfactor = Math.min(widthRatio, heightRatio); |
| } |
| width = new Double(baseWidth * fitZoomfactor).intValue(); |
| height = new Double(baseHeight * fitZoomfactor).intValue(); |
| |
| if (mainDisplay != null) |
| { |
| mainDisplay.setZoomFactor(fitZoomfactor); |
| } |
| } |
| else |
| { |
| width = new Double(baseWidth * zoomFactor).intValue(); |
| height = new Double(baseHeight * zoomFactor).intValue(); |
| |
| if (mainDisplay != null) |
| { |
| mainDisplay.setZoomFactor(zoomFactor); |
| } |
| } |
| |
| setSize(width, height); |
| } |
| |
| /** |
| * Adds listener for SWT events. |
| */ |
| private void addListener() |
| { |
| // add listener to handle keyboard key pressing |
| keyListener = new KeyListener() |
| { |
| |
| public void keyPressed(KeyEvent arg0) |
| { |
| |
| int keyCode = arg0.keyCode; |
| |
| if (keyCode == SWT.CTRL) |
| { |
| ctrlPressed = true; |
| } |
| else |
| { |
| // send message to emulator |
| androidInput.sendKey(arg0.character, keyCode, keyMap); |
| } |
| |
| } |
| |
| public void keyReleased(KeyEvent arg0) |
| { |
| int keyCode = arg0.keyCode; |
| |
| if (keyCode == SWT.CTRL) |
| { |
| ctrlPressed = false; |
| } |
| } |
| |
| }; |
| |
| // listener to change the zoom factor using Ctrl + Mouse Wheel |
| addMouseWheelListener(new MouseWheelListener() |
| { |
| |
| public void mouseScrolled(MouseEvent event) |
| { |
| if (ctrlPressed) |
| { |
| |
| if ((event.count > 0) && (zoomFactor < IHandlerConstants.MAXIMUM_ZOOM)) |
| { |
| // increase zoom factor |
| setZoomFactor(zoomFactor + IHandlerConstants.STEP_ZOOM); |
| applyZoomFactor(); |
| } |
| |
| else if ((event.count < 0) && (zoomFactor > IHandlerConstants.MINIMUM_ZOOM)) |
| { |
| // decrease zoom factor |
| setZoomFactor(zoomFactor - IHandlerConstants.STEP_ZOOM); |
| applyZoomFactor(); |
| } |
| } |
| } |
| }); |
| |
| mouseListener = new MouseAdapter() |
| { |
| /** |
| * @see org.eclipse.swt.events.MouseListener#mouseUp(MouseEvent) |
| */ |
| @Override |
| public void mouseUp(MouseEvent e) |
| { |
| handleMouseUp(e); |
| } |
| |
| /** |
| * @see org.eclipse.swt.events.MouseListener#mouseDown(MouseEvent) |
| */ |
| @Override |
| public void mouseDown(MouseEvent e) |
| { |
| setFocus(); |
| handleMouseDown(e); |
| } |
| }; |
| |
| mouseMoveListener = new MouseMoveListener() |
| { |
| /** |
| * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(MouseEvent) |
| */ |
| public void mouseMove(MouseEvent e) |
| { |
| handleMouseMove(e); |
| } |
| }; |
| |
| getParent().addControlListener(new ControlAdapter() |
| { |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.swt.events.ControlAdapter#controlResized(org.eclipse.swt.events.ControlEvent) |
| */ |
| @Override |
| public void controlResized(ControlEvent event) |
| { |
| if (isFitToWindow) |
| { |
| applyZoomFactor(); |
| } |
| } |
| }); |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see com.motorola.studio.android.emulator.ui.controls.IAndroidComposite#applyLayout(java.lang.String) |
| */ |
| public void applyLayout(String layoutName) |
| { |
| //do nothing |
| } |
| |
| /** |
| * Gets the listener that handles SWT key pressing and releasing events. |
| * |
| * @return the KeyListener object |
| */ |
| public KeyListener getKeyListener() |
| { |
| return keyListener; |
| } |
| |
| /** |
| * Gets the listener that handles SWT mouse clicking events. |
| * |
| * @return the MouseListener object |
| */ |
| public MouseListener getMouseListener() |
| { |
| return mouseListener; |
| } |
| |
| /** |
| * Gets the listener that handles SWT mouse moving events. |
| * |
| * @return the MouseMoveListener object |
| */ |
| public MouseMoveListener getMouseMoveListener() |
| { |
| return mouseMoveListener; |
| } |
| |
| /** |
| * Handles the mouse up event on the skin composite |
| * |
| * @param e |
| * The mouse up event |
| */ |
| private void handleMouseUp(MouseEvent e) |
| { |
| if (e.button == 1) |
| { |
| isMouseLeftButtonPressed = false; |
| UIHelper.ajustCoordinates(e, this); |
| androidInput.sendMouseUp(e.x, e.y); |
| } |
| } |
| |
| /** |
| * Handles the mouse down event on the skin composite |
| * |
| * @param e |
| * The mouse down event |
| */ |
| private void handleMouseDown(MouseEvent e) |
| { |
| if (e.button == 1) |
| { |
| UIHelper.ajustCoordinates(e, this); |
| androidInput.sendMouseDown(e.x, e.y); |
| isMouseLeftButtonPressed = true; |
| } |
| |
| } |
| |
| /** |
| * Handles the mouse move event on the skin composite |
| * |
| * @param e |
| * The mouse move event |
| */ |
| private void handleMouseMove(MouseEvent e) |
| { |
| if (isMouseLeftButtonPressed) |
| { |
| UIHelper.ajustCoordinates(e, this); |
| androidInput.sendMouseMove(e.x, e.y); |
| } |
| } |
| |
| public boolean isFitToWindowSelected() |
| { |
| return isFitToWindow; |
| } |
| } |