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.Collection; 45 import java.util.Collections; 46 import java.util.List; 47 import java.util.Map; 48 import java.util.TreeMap; 49 50 /** 51 * The {@linkplain DeviceMenuListener} class is responsible for generating the device 52 * menu in the {@link ConfigurationChooser}. 53 */ 54 class DeviceMenuListener extends SelectionAdapter { 55 private final ConfigurationChooser mConfigChooser; 56 private final Device mDevice; 57 58 DeviceMenuListener( 59 @NonNull ConfigurationChooser configChooser, 60 @Nullable Device device) { 61 mConfigChooser = configChooser; 62 mDevice = device; 63 } 64 65 @Override 66 public void widgetSelected(SelectionEvent e) { 67 mConfigChooser.selectDevice(mDevice); 68 mConfigChooser.onDeviceChange(); 69 } 70 71 static void show(final ConfigurationChooser chooser, ToolItem combo) { 72 Configuration configuration = chooser.getConfiguration(); 73 Device current = configuration.getDevice(); 74 Menu menu = new Menu(chooser.getShell(), SWT.POP_UP); 75 76 Collection<Device> deviceCollection = chooser.getDevices(); 77 Sdk sdk = Sdk.getCurrent(); 78 if (sdk != null) { 79 AvdManager avdManager = sdk.getAvdManager(); 80 if (avdManager != null) { 81 boolean separatorNeeded = false; 82 AvdInfo[] avds = avdManager.getValidAvds(); 83 for (AvdInfo avd : avds) { 84 for (Device device : deviceCollection) { 85 if (device.getManufacturer().equals(avd.getDeviceManufacturer()) 86 && device.getName().equals(avd.getDeviceName())) { 87 separatorNeeded = true; 88 MenuItem item = new MenuItem(menu, SWT.CHECK); 89 item.setText(avd.getName()); 90 item.setSelection(current == device); 91 92 item.addSelectionListener(new DeviceMenuListener(chooser, device)); 93 } 94 } 95 } 96 97 if (separatorNeeded) { 98 @SuppressWarnings("unused") 99 MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); 100 } 101 } 102 } 103 104 // Group the devices by manufacturer, then put them in the menu. 105 // If we don't have anything but Nexus devices, group them together rather than 106 // make many manufacturer submenus. 107 boolean haveNexus = false; 108 boolean haveNonNexus = false; 109 if (!deviceCollection.isEmpty()) { 110 Map<String, List<Device>> manufacturers = new TreeMap<String, List<Device>>(); 111 for (Device device : deviceCollection) { 112 List<Device> devices; 113 if (isNexus(device)) { 114 haveNexus = true; 115 } else if (!isGeneric(device)) { 116 haveNonNexus = true; 117 } 118 if (manufacturers.containsKey(device.getManufacturer())) { 119 devices = manufacturers.get(device.getManufacturer()); 120 } else { 121 devices = new ArrayList<Device>(); 122 manufacturers.put(device.getManufacturer(), devices); 123 } 124 devices.add(device); 125 } 126 if (haveNonNexus) { 127 for (List<Device> devices : manufacturers.values()) { 128 Menu manufacturerMenu = menu; 129 if (manufacturers.size() > 1) { 130 MenuItem item = new MenuItem(menu, SWT.CASCADE); 131 item.setText(devices.get(0).getManufacturer()); 132 manufacturerMenu = new Menu(menu); 133 item.setMenu(manufacturerMenu); 134 } 135 for (final Device device : devices) { 136 MenuItem deviceItem = new MenuItem(manufacturerMenu, SWT.CHECK); 137 deviceItem.setText(getGenericLabel(device)); 138 deviceItem.setSelection(current == device); 139 deviceItem.addSelectionListener(new DeviceMenuListener(chooser, device)); 140 } 141 } 142 } else { 143 List<Device> nexus = new ArrayList<Device>(); 144 List<Device> generic = new ArrayList<Device>(); 145 if (haveNexus) { 146 // Nexus 147 for (List<Device> devices : manufacturers.values()) { 148 for (Device device : devices) { 149 if (isNexus(device)) { 150 if (device.getManufacturer().equals(MANUFACTURER_GENERIC)) { 151 generic.add(device); 152 } else { 153 nexus.add(device); 154 } 155 } else { 156 generic.add(device); 157 } 158 } 159 } 160 } 161 162 if (!nexus.isEmpty()) { 163 sortNexusList(nexus); 164 for (final Device device : nexus) { 165 MenuItem item = new MenuItem(menu, SWT.CHECK); 166 item.setText(getNexusLabel(device)); 167 item.setSelection(current == device); 168 item.addSelectionListener(new DeviceMenuListener(chooser, device)); 169 } 170 171 @SuppressWarnings("unused") 172 MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); 173 } 174 175 // Generate the generic menu. 176 Collections.reverse(generic); 177 for (final Device device : generic) { 178 MenuItem item = new MenuItem(menu, SWT.CHECK); 179 item.setText(getGenericLabel(device)); 180 item.setSelection(current == device); 181 item.addSelectionListener(new DeviceMenuListener(chooser, device)); 182 } 183 } 184 } 185 186 @SuppressWarnings("unused") 187 MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); 188 189 ConfigurationMenuListener.addTogglePreviewModeAction(menu, 190 "Preview All Screens", chooser, RenderPreviewMode.SCREENS); 191 192 193 Rectangle bounds = combo.getBounds(); 194 Point location = new Point(bounds.x, bounds.y + bounds.height); 195 location = combo.getParent().toDisplay(location); 196 menu.setLocation(location.x, location.y); 197 menu.setVisible(true); 198 } 199 } 200