1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.editors.layout.configuration; 18 19 import static com.android.ide.common.rendering.HardwareConfigHelper.MANUFACTURER_GENERIC; 20 import static com.android.ide.common.rendering.HardwareConfigHelper.getGenericLabel; 21 import static com.android.ide.common.rendering.HardwareConfigHelper.getNexusLabel; 22 import static com.android.ide.common.rendering.HardwareConfigHelper.isGeneric; 23 import static com.android.ide.common.rendering.HardwareConfigHelper.isNexus; 24 import static com.android.ide.common.rendering.HardwareConfigHelper.sortNexusList; 25 26 import com.android.annotations.NonNull; 27 import com.android.annotations.Nullable; 28 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewMode; 29 import com.android.ide.eclipse.adt.internal.sdk.Sdk; 30 import com.android.sdklib.devices.Device; 31 import com.android.sdklib.internal.avd.AvdInfo; 32 import com.android.sdklib.internal.avd.AvdManager; 33 34 import org.eclipse.swt.SWT; 35 import org.eclipse.swt.events.SelectionAdapter; 36 import org.eclipse.swt.events.SelectionEvent; 37 import org.eclipse.swt.graphics.Point; 38 import org.eclipse.swt.graphics.Rectangle; 39 import org.eclipse.swt.widgets.Menu; 40 import org.eclipse.swt.widgets.MenuItem; 41 import org.eclipse.swt.widgets.ToolItem; 42 43 import java.util.ArrayList; 44 import java.util.Collections; 45 import java.util.List; 46 import java.util.Map; 47 import java.util.TreeMap; 48 49 /** 50 * The {@linkplain DeviceMenuListener} class is responsible for generating the device 51 * menu in the {@link ConfigurationChooser}. 52 */ 53 class DeviceMenuListener extends SelectionAdapter { 54 private final ConfigurationChooser mConfigChooser; 55 private final Device mDevice; 56 57 DeviceMenuListener( 58 @NonNull ConfigurationChooser configChooser, 59 @Nullable Device device) { 60 mConfigChooser = configChooser; 61 mDevice = device; 62 } 63 64 @Override 65 public void widgetSelected(SelectionEvent e) { 66 mConfigChooser.selectDevice(mDevice); 67 mConfigChooser.onDeviceChange(); 68 } 69 70 static void show(final ConfigurationChooser chooser, ToolItem combo) { 71 Configuration configuration = chooser.getConfiguration(); 72 Device current = configuration.getDevice(); 73 Menu menu = new Menu(chooser.getShell(), SWT.POP_UP); 74 75 List<Device> deviceList = chooser.getDeviceList(); 76 Sdk sdk = Sdk.getCurrent(); 77 if (sdk != null) { 78 AvdManager avdManager = sdk.getAvdManager(); 79 if (avdManager != null) { 80 boolean separatorNeeded = false; 81 AvdInfo[] avds = avdManager.getValidAvds(); 82 for (AvdInfo avd : avds) { 83 for (Device device : deviceList) { 84 if (device.getManufacturer().equals(avd.getDeviceManufacturer()) 85 && device.getName().equals(avd.getDeviceName())) { 86 separatorNeeded = true; 87 MenuItem item = new MenuItem(menu, SWT.CHECK); 88 item.setText(avd.getName()); 89 item.setSelection(current == device); 90 91 item.addSelectionListener(new DeviceMenuListener(chooser, device)); 92 } 93 } 94 } 95 96 if (separatorNeeded) { 97 @SuppressWarnings("unused") 98 MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); 99 } 100 } 101 } 102 103 // Group the devices by manufacturer, then put them in the menu. 104 // If we don't have anything but Nexus devices, group them together rather than 105 // make many manufacturer submenus. 106 boolean haveNexus = false; 107 boolean haveNonNexus = false; 108 if (!deviceList.isEmpty()) { 109 Map<String, List<Device>> manufacturers = new TreeMap<String, List<Device>>(); 110 for (Device device : deviceList) { 111 List<Device> devices; 112 if (isNexus(device)) { 113 haveNexus = true; 114 } else if (!isGeneric(device)) { 115 haveNonNexus = true; 116 } 117 if (manufacturers.containsKey(device.getManufacturer())) { 118 devices = manufacturers.get(device.getManufacturer()); 119 } else { 120 devices = new ArrayList<Device>(); 121 manufacturers.put(device.getManufacturer(), devices); 122 } 123 devices.add(device); 124 } 125 if (haveNonNexus) { 126 for (List<Device> devices : manufacturers.values()) { 127 Menu manufacturerMenu = menu; 128 if (manufacturers.size() > 1) { 129 MenuItem item = new MenuItem(menu, SWT.CASCADE); 130 item.setText(devices.get(0).getManufacturer()); 131 manufacturerMenu = new Menu(menu); 132 item.setMenu(manufacturerMenu); 133 } 134 for (final Device device : devices) { 135 MenuItem deviceItem = new MenuItem(manufacturerMenu, SWT.CHECK); 136 deviceItem.setText(getGenericLabel(device)); 137 deviceItem.setSelection(current == device); 138 deviceItem.addSelectionListener(new DeviceMenuListener(chooser, device)); 139 } 140 } 141 } else { 142 List<Device> nexus = new ArrayList<Device>(); 143 List<Device> generic = new ArrayList<Device>(); 144 if (haveNexus) { 145 // Nexus 146 for (List<Device> devices : manufacturers.values()) { 147 for (Device device : devices) { 148 if (isNexus(device)) { 149 if (device.getManufacturer().equals(MANUFACTURER_GENERIC)) { 150 generic.add(device); 151 } else { 152 nexus.add(device); 153 } 154 } else { 155 generic.add(device); 156 } 157 } 158 } 159 } 160 161 if (!nexus.isEmpty()) { 162 sortNexusList(nexus); 163 for (final Device device : nexus) { 164 MenuItem item = new MenuItem(menu, SWT.CHECK); 165 item.setText(getNexusLabel(device)); 166 item.setSelection(current == device); 167 item.addSelectionListener(new DeviceMenuListener(chooser, device)); 168 } 169 170 @SuppressWarnings("unused") 171 MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); 172 } 173 174 // Generate the generic menu. 175 Collections.reverse(generic); 176 for (final Device device : generic) { 177 MenuItem item = new MenuItem(menu, SWT.CHECK); 178 item.setText(getGenericLabel(device)); 179 item.setSelection(current == device); 180 item.addSelectionListener(new DeviceMenuListener(chooser, device)); 181 } 182 } 183 } 184 185 @SuppressWarnings("unused") 186 MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); 187 188 ConfigurationMenuListener.addTogglePreviewModeAction(menu, 189 "Preview All Screens", chooser, RenderPreviewMode.SCREENS); 190 191 192 Rectangle bounds = combo.getBounds(); 193 Point location = new Point(bounds.x, bounds.y + bounds.height); 194 location = combo.getParent().toDisplay(location); 195 menu.setLocation(location.x, location.y); 196 menu.setVisible(true); 197 } 198 } 199