1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 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.monitor.ddms; 18 19 import com.android.ddmuilib.TableHelper; 20 import com.android.ide.eclipse.ddms.DdmsPlugin; 21 22 import org.eclipse.swt.SWT; 23 import org.eclipse.swt.events.SelectionAdapter; 24 import org.eclipse.swt.events.SelectionEvent; 25 import org.eclipse.swt.graphics.Rectangle; 26 import org.eclipse.swt.layout.GridData; 27 import org.eclipse.swt.layout.GridLayout; 28 import org.eclipse.swt.widgets.Button; 29 import org.eclipse.swt.widgets.Composite; 30 import org.eclipse.swt.widgets.Dialog; 31 import org.eclipse.swt.widgets.Display; 32 import org.eclipse.swt.widgets.Event; 33 import org.eclipse.swt.widgets.Listener; 34 import org.eclipse.swt.widgets.Shell; 35 import org.eclipse.swt.widgets.Table; 36 import org.eclipse.swt.widgets.TableItem; 37 38 import java.util.ArrayList; 39 import java.util.HashMap; 40 import java.util.Map; 41 import java.util.Set; 42 43 /** 44 * Dialog to configure the static debug ports. 45 * 46 */ 47 public class StaticPortConfigDialog extends Dialog { 48 49 /** Preference name for the 0th column width */ 50 private static final String PREFS_DEVICE_COL = "spcd.deviceColumn"; //$NON-NLS-1$ 51 52 /** Preference name for the 1st column width */ 53 private static final String PREFS_APP_COL = "spcd.AppColumn"; //$NON-NLS-1$ 54 55 /** Preference name for the 2nd column width */ 56 private static final String PREFS_PORT_COL = "spcd.PortColumn"; //$NON-NLS-1$ 57 58 private static final int COL_DEVICE = 0; 59 private static final int COL_APPLICATION = 1; 60 private static final int COL_PORT = 2; 61 62 63 private static final int DLG_WIDTH = 500; 64 private static final int DLG_HEIGHT = 300; 65 66 private Shell mShell; 67 private Shell mParent; 68 69 private Table mPortTable; 70 71 /** 72 * Array containing the list of already used static port to avoid 73 * duplication. 74 */ 75 private ArrayList<Integer> mPorts = new ArrayList<Integer>(); 76 77 /** 78 * Basic constructor. 79 * @param parent 80 */ 81 public StaticPortConfigDialog(Shell parent) { 82 super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL); 83 } 84 85 /** 86 * Open and display the dialog. This method returns only when the 87 * user closes the dialog somehow. 88 * 89 */ 90 public void open() { 91 createUI(); 92 93 if (mParent == null || mShell == null) { 94 return; 95 } 96 97 updateFromStore(); 98 99 // Set the dialog size. 100 mShell.setMinimumSize(DLG_WIDTH, DLG_HEIGHT); 101 Rectangle r = mParent.getBounds(); 102 // get the center new top left. 103 int cx = r.x + r.width/2; 104 int x = cx - DLG_WIDTH / 2; 105 int cy = r.y + r.height/2; 106 int y = cy - DLG_HEIGHT / 2; 107 mShell.setBounds(x, y, DLG_WIDTH, DLG_HEIGHT); 108 109 mShell.pack(); 110 111 // actually open the dialog 112 mShell.open(); 113 114 // event loop until the dialog is closed. 115 Display display = mParent.getDisplay(); 116 while (!mShell.isDisposed()) { 117 if (!display.readAndDispatch()) 118 display.sleep(); 119 } 120 } 121 122 /** 123 * Creates the dialog ui. 124 */ 125 private void createUI() { 126 mParent = getParent(); 127 mShell = new Shell(mParent, getStyle()); 128 mShell.setText("Static Port Configuration"); 129 130 mShell.setLayout(new GridLayout(1, true)); 131 132 mShell.addListener(SWT.Close, new Listener() { 133 @Override 134 public void handleEvent(Event event) { 135 event.doit = true; 136 } 137 }); 138 139 // center part with the list on the left and the buttons 140 // on the right. 141 Composite main = new Composite(mShell, SWT.NONE); 142 main.setLayoutData(new GridData(GridData.FILL_BOTH)); 143 main.setLayout(new GridLayout(2, false)); 144 145 // left part: list view 146 mPortTable = new Table(main, SWT.SINGLE | SWT.FULL_SELECTION); 147 mPortTable.setLayoutData(new GridData(GridData.FILL_BOTH)); 148 mPortTable.setHeaderVisible(true); 149 mPortTable.setLinesVisible(true); 150 151 TableHelper.createTableColumn(mPortTable, "Device Serial Number", 152 SWT.LEFT, "emulator-5554", //$NON-NLS-1$ 153 PREFS_DEVICE_COL, DdmsPlugin.getDefault().getPreferenceStore()); 154 155 TableHelper.createTableColumn(mPortTable, "Application Package", 156 SWT.LEFT, "com.android.samples.phone", //$NON-NLS-1$ 157 PREFS_APP_COL, DdmsPlugin.getDefault().getPreferenceStore()); 158 159 TableHelper.createTableColumn(mPortTable, "Debug Port", 160 SWT.RIGHT, "Debug Port", //$NON-NLS-1$ 161 PREFS_PORT_COL, DdmsPlugin.getDefault().getPreferenceStore()); 162 163 // right part: buttons 164 Composite buttons = new Composite(main, SWT.NONE); 165 buttons.setLayoutData(new GridData(GridData.FILL_VERTICAL)); 166 buttons.setLayout(new GridLayout(1, true)); 167 168 Button newButton = new Button(buttons, SWT.NONE); 169 newButton.setText("New..."); 170 newButton.addSelectionListener(new SelectionAdapter() { 171 @Override 172 public void widgetSelected(SelectionEvent e) { 173 StaticPortEditDialog dlg = new StaticPortEditDialog(mShell, 174 mPorts); 175 if (dlg.open()) { 176 // get the text 177 String device = dlg.getDeviceSN(); 178 String app = dlg.getAppName(); 179 int port = dlg.getPortNumber(); 180 181 // add it to the list 182 addEntry(device, app, port); 183 } 184 } 185 }); 186 187 final Button editButton = new Button(buttons, SWT.NONE); 188 editButton.setText("Edit..."); 189 editButton.setEnabled(false); 190 editButton.addSelectionListener(new SelectionAdapter() { 191 @Override 192 public void widgetSelected(SelectionEvent e) { 193 int index = mPortTable.getSelectionIndex(); 194 String oldDeviceName = getDeviceName(index); 195 String oldAppName = getAppName(index); 196 String oldPortNumber = getPortNumber(index); 197 StaticPortEditDialog dlg = new StaticPortEditDialog(mShell, 198 mPorts, oldDeviceName, oldAppName, oldPortNumber); 199 if (dlg.open()) { 200 // get the text 201 String deviceName = dlg.getDeviceSN(); 202 String app = dlg.getAppName(); 203 int port = dlg.getPortNumber(); 204 205 // add it to the list 206 replaceEntry(index, deviceName, app, port); 207 } 208 } 209 }); 210 211 final Button deleteButton = new Button(buttons, SWT.NONE); 212 deleteButton.setText("Delete"); 213 deleteButton.setEnabled(false); 214 deleteButton.addSelectionListener(new SelectionAdapter() { 215 @Override 216 public void widgetSelected(SelectionEvent e) { 217 int index = mPortTable.getSelectionIndex(); 218 removeEntry(index); 219 } 220 }); 221 222 // bottom part with the ok/cancel 223 Composite bottomComp = new Composite(mShell, SWT.NONE); 224 bottomComp.setLayoutData(new GridData( 225 GridData.HORIZONTAL_ALIGN_CENTER)); 226 bottomComp.setLayout(new GridLayout(2, true)); 227 228 Button okButton = new Button(bottomComp, SWT.NONE); 229 okButton.setText("OK"); 230 okButton.addSelectionListener(new SelectionAdapter() { 231 @Override 232 public void widgetSelected(SelectionEvent e) { 233 updateStore(); 234 mShell.close(); 235 } 236 }); 237 238 Button cancelButton = new Button(bottomComp, SWT.NONE); 239 cancelButton.setText("Cancel"); 240 cancelButton.addSelectionListener(new SelectionAdapter() { 241 @Override 242 public void widgetSelected(SelectionEvent e) { 243 mShell.close(); 244 } 245 }); 246 247 mPortTable.addSelectionListener(new SelectionAdapter() { 248 @Override 249 public void widgetSelected(SelectionEvent e) { 250 // get the selection index 251 int index = mPortTable.getSelectionIndex(); 252 253 boolean enabled = index != -1; 254 editButton.setEnabled(enabled); 255 deleteButton.setEnabled(enabled); 256 } 257 }); 258 259 mShell.pack(); 260 261 } 262 263 /** 264 * Add a new entry in the list. 265 * @param deviceName the serial number of the device 266 * @param appName java package for the application 267 * @param portNumber port number 268 */ 269 private void addEntry(String deviceName, String appName, int portNumber) { 270 // create a new item for the table 271 TableItem item = new TableItem(mPortTable, SWT.NONE); 272 273 item.setText(COL_DEVICE, deviceName); 274 item.setText(COL_APPLICATION, appName); 275 item.setText(COL_PORT, Integer.toString(portNumber)); 276 277 // add the port to the list of port number used. 278 mPorts.add(portNumber); 279 } 280 281 /** 282 * Remove an entry from the list. 283 * @param index The index of the entry to be removed 284 */ 285 private void removeEntry(int index) { 286 // remove from the ui 287 mPortTable.remove(index); 288 289 // and from the port list. 290 mPorts.remove(index); 291 } 292 293 /** 294 * Replace an entry in the list with new values. 295 * @param index The index of the item to be replaced 296 * @param deviceName the serial number of the device 297 * @param appName The new java package for the application 298 * @param portNumber The new port number. 299 */ 300 private void replaceEntry(int index, String deviceName, String appName, int portNumber) { 301 // get the table item by index 302 TableItem item = mPortTable.getItem(index); 303 304 // set its new value 305 item.setText(COL_DEVICE, deviceName); 306 item.setText(COL_APPLICATION, appName); 307 item.setText(COL_PORT, Integer.toString(portNumber)); 308 309 // and replace the port number in the port list. 310 mPorts.set(index, portNumber); 311 } 312 313 314 /** 315 * Returns the device name for a specific index 316 * @param index The index 317 * @return the java package name of the application 318 */ 319 private String getDeviceName(int index) { 320 TableItem item = mPortTable.getItem(index); 321 return item.getText(COL_DEVICE); 322 } 323 324 /** 325 * Returns the application name for a specific index 326 * @param index The index 327 * @return the java package name of the application 328 */ 329 private String getAppName(int index) { 330 TableItem item = mPortTable.getItem(index); 331 return item.getText(COL_APPLICATION); 332 } 333 334 /** 335 * Returns the port number for a specific index 336 * @param index The index 337 * @return the port number 338 */ 339 private String getPortNumber(int index) { 340 TableItem item = mPortTable.getItem(index); 341 return item.getText(COL_PORT); 342 } 343 344 /** 345 * Updates the ui from the value in the preference store. 346 */ 347 private void updateFromStore() { 348 // get the map from the debug port manager 349 DebugPortProvider provider = DebugPortProvider.getInstance(); 350 Map<String, Map<String, Integer>> map = provider.getPortList(); 351 352 // we're going to loop on the keys and fill the table. 353 Set<String> deviceKeys = map.keySet(); 354 355 for (String deviceKey : deviceKeys) { 356 Map<String, Integer> deviceMap = map.get(deviceKey); 357 if (deviceMap != null) { 358 Set<String> appKeys = deviceMap.keySet(); 359 360 for (String appKey : appKeys) { 361 Integer port = deviceMap.get(appKey); 362 if (port != null) { 363 addEntry(deviceKey, appKey, port); 364 } 365 } 366 } 367 } 368 } 369 370 /** 371 * Update the store from the content of the ui. 372 */ 373 private void updateStore() { 374 // create a new Map object and fill it. 375 HashMap<String, Map<String, Integer>> map = new HashMap<String, Map<String, Integer>>(); 376 377 int count = mPortTable.getItemCount(); 378 379 for (int i = 0 ; i < count ; i++) { 380 TableItem item = mPortTable.getItem(i); 381 String deviceName = item.getText(COL_DEVICE); 382 383 Map<String, Integer> deviceMap = map.get(deviceName); 384 if (deviceMap == null) { 385 deviceMap = new HashMap<String, Integer>(); 386 map.put(deviceName, deviceMap); 387 } 388 389 deviceMap.put(item.getText(COL_APPLICATION), Integer.valueOf(item.getText(COL_PORT))); 390 } 391 392 // set it in the store through the debug port manager. 393 DebugPortProvider provider = DebugPortProvider.getInstance(); 394 provider.setPortList(map); 395 } 396 } 397