blob: e1ba398663f27d68fca87f521a916dcf0a8c8bb6 [file] [log] [blame]
/*
* 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;
}
}