| /* |
| * 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.perspective; |
| |
| import static com.motorola.studio.android.common.log.StudioLogger.error; |
| import static com.motorola.studio.android.common.log.StudioLogger.warn; |
| |
| import java.util.Collection; |
| import java.util.TreeSet; |
| |
| import org.eclipse.ui.IFolderLayout; |
| import org.eclipse.ui.IPageLayout; |
| import org.eclipse.ui.IPerspectiveFactory; |
| import org.eclipse.ui.PartInitException; |
| |
| import com.motorola.studio.android.common.utilities.EclipseUtils; |
| import com.motorola.studio.android.emulator.ui.perspective.extension.AndroidPerspectiveExtensionBean; |
| import com.motorola.studio.android.emulator.ui.perspective.extension.AndroidPerspectiveExtensionBean.PerspectiveAreas; |
| import com.motorola.studio.android.emulator.ui.perspective.extension.AndroidPerspectiveExtensionReader; |
| import com.motorola.studio.android.emulator.ui.perspective.extension.IAndroidPerspectiveExtensionConstants; |
| import com.motorola.studio.android.emulator.ui.view.AndroidView; |
| import com.motorola.studio.android.emulator.ui.view.MainDisplayView; |
| |
| /** |
| * DESCRIPTION: |
| * This class represents the Android Emulator perspective. |
| * |
| * RESPONSIBILITY: |
| * Create the Android Emulator perspective. |
| * |
| * COLABORATORS: |
| * None |
| * |
| * USAGE: |
| * This class is referenced by the plugin.xml file of this plugin. |
| */ |
| public class AndroidEmulatorPerspective implements IPerspectiveFactory |
| { |
| private static String LAUNCH_COOLBAR_SHORTCUT = "org.eclipse.debug.ui.launchActionSet"; |
| |
| /** |
| * Creates the initial layout for a page. |
| * |
| * @param layout the page layout |
| * |
| * @see IPerspectiveFactory#createInitialLayout(IPageLayout) |
| */ |
| public void createInitialLayout(IPageLayout layout) |
| { |
| // ---------------HOW THE PERSPECTIVE IS LAID OUT--------------- |
| // |
| // The Android Perspective will be dynamically populated according to |
| // the contributions declared to it through the androidPerspectiveExtension |
| // extension point. |
| // The perspective consists of three areas: |
| // - the area where the Android Emulator View is placed, on the right side |
| // - the area where device management related views are placed, on the left side |
| // - the area for emulation views, on the middle |
| // The areas that are dynamically populated are the two last ones, and they will |
| // be referred to as 'dynamic areas' by methods. |
| // |
| // The first area is filled by the code on this method by itself, and the two other |
| // ones are filled depending on what is found for the extension point. |
| // The following drawing illustrates the position of each area on the workbench: |
| // |
| // ____________________________________ |
| // | | | | |
| // | | | | |
| // | Dev | | Moto | |
| // | Mgt | | magx | |
| // | Views | Emu Views Area | Emu | |
| // | Area | | View | |
| // | | | Area | |
| // | | | | |
| // |_______|___________________|_______| |
| // |
| // Device Management views are placed atop of each other on their respective area. |
| // Emulation views are laid out depending on the number of views declared. If there |
| // is only one emulation view, it is placed occupying the entire emulation views area. |
| // If there are two emulation views, they divide the emulation views area in half and |
| // occupy the area from bottom to top, as seen on the following drawing: |
| // |
| // ____________________________________ |
| // | | | | |
| // | | | | |
| // | Dev | Emu Views part 2 | Moto | |
| // | Mgt | | magx | |
| // | Views |___________________| Emu | |
| // | Area | | View | |
| // | | Emu Views part 1 | Area | |
| // | | | | |
| // |_______|___________________|_______| |
| // |
| // If there are three emulation views or more, they divide the emulation views area in |
| // three parts, which are occupied from bottom to top, as seen on the following drawing: |
| // |
| // ____________________________________ |
| // | | | | |
| // | | Emu Views part 3 | | |
| // | Dev |___________________| Moto | |
| // | Mgt | | magx | |
| // | Views | Emu Views part 2 | Emu | |
| // | Area |___________________| View | |
| // | | | Area | |
| // | | Emu Views part 1 | | |
| // |_______|___________________|_______| |
| // |
| // If there are no device management or no emulation views (or both), their folders are |
| // always created so that the workbench is always divided into the correct areas for |
| // better user experience. |
| // |
| // ------------------------------------------------------------- |
| |
| addEmulatorView(layout); |
| addRunCoolbar(layout); |
| createAndPopulateDynamicAreas(layout); |
| |
| // hide the editor area (not necessary on this perspective) |
| layout.setEditorAreaVisible(false); |
| } |
| |
| private void addEmulatorView(IPageLayout layout) |
| { |
| // emulator view is a sticky view, no place holder is necessary (only open it) |
| try |
| { |
| EclipseUtils.showView(AndroidView.ANDROID_VIEW_ID); |
| } |
| catch (PartInitException e) |
| { |
| error("Unable to open Android Emulator View on Android Emulator Perspective."); |
| } |
| |
| layout.addShowViewShortcut(AndroidView.ANDROID_VIEW_ID); |
| layout.addShowViewShortcut(MainDisplayView.EMULATOR_MAIN_DISPLAY_VIEW_ID); |
| } |
| |
| private void addRunCoolbar(IPageLayout layout) |
| { |
| layout.addActionSet(LAUNCH_COOLBAR_SHORTCUT); |
| } |
| |
| private void createAndPopulateDynamicAreas(IPageLayout layout) |
| { |
| // read the extensions for this perspective, as declared by the androidPerspectiveExtension |
| // extension point |
| Collection<AndroidPerspectiveExtensionBean> perspectiveExtensionBeans = |
| AndroidPerspectiveExtensionReader.readAndroidPerspectiveExtensions(); |
| |
| // the folder for placing device management related views |
| IFolderLayout devMgtArea = createDeviceMgtViewsArea(layout); |
| |
| // collection of emuy area view ids for later placement |
| // it is alphabetically ordered (so that a group of defined |
| // views always open on the same location) |
| Collection<String> emuAreaViewIds = new TreeSet<String>(); |
| |
| for (AndroidPerspectiveExtensionBean extensionBean : perspectiveExtensionBeans) |
| { |
| if (PerspectiveAreas.DEVICE_MANAGEMENT_VIEWS_AREA.equals(extensionBean.getArea())) |
| { |
| // put dev mgt views atop of each other on the folder |
| devMgtArea.addView(extensionBean.getViewId()); |
| } |
| else if (PerspectiveAreas.EMULATION_VIEWS_AREA.equals(extensionBean.getArea())) |
| { |
| // collect emu views for later placement |
| emuAreaViewIds.add(extensionBean.getViewId()); |
| } |
| else |
| { |
| // in case of something not expected, log the problem |
| warn("View of id " + extensionBean.getViewId() |
| + " could not be added to Android Emulator perspective"); |
| } |
| } |
| |
| // the number of emu views, for defining the number of folders necessary |
| int numEmuViews = emuAreaViewIds.size(); |
| |
| // create the emu area folders, which will be at most size 3 |
| IFolderLayout[] emuAreaFolders = createEmuArea(layout, numEmuViews); |
| |
| // place the views on the correct folder by using the leftover of dividing the |
| // number of the current view by number of maximum folders (3) |
| int i = 0; |
| for (String viewId : emuAreaViewIds) |
| { |
| emuAreaFolders[i % 3].addView(viewId); |
| i++; // next view |
| } |
| } |
| |
| private IFolderLayout createDeviceMgtViewsArea(IPageLayout layout) |
| { |
| return layout.createFolder(IAndroidPerspectiveExtensionConstants.ATT_AREA_DEVMGT_VALUE, |
| IPageLayout.LEFT, 0.30f, IPageLayout.ID_EDITOR_AREA); |
| } |
| |
| private IFolderLayout[] createEmuArea(IPageLayout layout, int numEmuViews) |
| { |
| // at most 3 folders are necessary |
| IFolderLayout[] emuAreaFolders = new IFolderLayout[3]; |
| |
| // the number of divisions the emu views area will be divided into |
| int div = (numEmuViews >= 3 ? 3 : (numEmuViews == 2 ? 2 : 1)); |
| |
| // the ratio for the first folder to be placed (the bottom one, which may turn |
| // to be the only one if div is equal to 1) |
| float ratio = 1.00f / div; |
| |
| // the bottom folder (#1) is always necessary |
| // for 3 folders, ratio = 0.33f; for 2 folders, ratio = 0.5f |
| emuAreaFolders[0] = |
| layout.createFolder("emuAreaBottom", IPageLayout.BOTTOM, ratio, |
| IPageLayout.ID_EDITOR_AREA); |
| |
| // create folder #2 only if necessary |
| if (numEmuViews >= 2) |
| { |
| // adjust ratio depending on the number of folders in total: |
| // for 3 folders, ratio = 0.67f; for 2 folders, ratio = 0.5f |
| if (numEmuViews > 2) |
| { |
| ratio = 2 * ratio; |
| } |
| emuAreaFolders[1] = |
| layout.createFolder("emuAreaMiddle", IPageLayout.TOP, ratio, "emuAreaBottom"); |
| } |
| |
| // create folder #3 only if necessary |
| if (numEmuViews >= 3) |
| { |
| // ratio is always half of folder #2 space |
| emuAreaFolders[2] = |
| layout.createFolder("emuAreaTop", IPageLayout.TOP, 0.50f, "emuAreaMiddle"); |
| } |
| |
| return emuAreaFolders; |
| } |
| } |