| /* |
| * 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.android.ide.eclipse.monitor.ddms; |
| |
| import com.android.ddmlib.IDevice; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Dialog; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| |
| import java.util.ArrayList; |
| |
| /** |
| * Small dialog box to edit a static port number. |
| */ |
| public class StaticPortEditDialog extends Dialog { |
| |
| private static final int DLG_WIDTH = 400; |
| private static final int DLG_HEIGHT = 200; |
| |
| private Shell mParent; |
| |
| private Shell mShell; |
| |
| private boolean mOk = false; |
| |
| private String mAppName; |
| |
| private String mPortNumber; |
| |
| private Button mOkButton; |
| |
| private Label mWarning; |
| |
| /** List of ports already in use */ |
| private ArrayList<Integer> mPorts; |
| |
| /** This is the port being edited. */ |
| private int mEditPort = -1; |
| private String mDeviceSn; |
| |
| /** |
| * Creates a dialog with empty fields. |
| * @param parent The parent Shell |
| * @param ports The list of already used port numbers. |
| */ |
| public StaticPortEditDialog(Shell parent, ArrayList<Integer> ports) { |
| super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL); |
| mPorts = ports; |
| mDeviceSn = IDevice.FIRST_EMULATOR_SN; |
| } |
| |
| /** |
| * Creates a dialog with predefined values. |
| * @param shell The parent shell |
| * @param ports The list of already used port numbers. |
| * @param oldDeviceSN the device serial number to display |
| * @param oldAppName The application name to display |
| * @param oldPortNumber The port number to display |
| */ |
| public StaticPortEditDialog(Shell shell, ArrayList<Integer> ports, |
| String oldDeviceSN, String oldAppName, String oldPortNumber) { |
| this(shell, ports); |
| |
| mDeviceSn = oldDeviceSN; |
| mAppName = oldAppName; |
| mPortNumber = oldPortNumber; |
| mEditPort = Integer.valueOf(mPortNumber); |
| } |
| |
| /** |
| * Opens the dialog. The method will return when the user closes the dialog |
| * somehow. |
| * |
| * @return true if ok was pressed, false if cancelled. |
| */ |
| public boolean open() { |
| createUI(); |
| |
| if (mParent == null || mShell == null) { |
| return false; |
| } |
| |
| mShell.setMinimumSize(DLG_WIDTH, DLG_HEIGHT); |
| Rectangle r = mParent.getBounds(); |
| // get the center new top left. |
| int cx = r.x + r.width/2; |
| int x = cx - DLG_WIDTH / 2; |
| int cy = r.y + r.height/2; |
| int y = cy - DLG_HEIGHT / 2; |
| mShell.setBounds(x, y, DLG_WIDTH, DLG_HEIGHT); |
| |
| mShell.open(); |
| |
| Display display = mParent.getDisplay(); |
| while (!mShell.isDisposed()) { |
| if (!display.readAndDispatch()) |
| display.sleep(); |
| } |
| |
| return mOk; |
| } |
| |
| public String getDeviceSN() { |
| return mDeviceSn; |
| } |
| |
| public String getAppName() { |
| return mAppName; |
| } |
| |
| public int getPortNumber() { |
| return Integer.valueOf(mPortNumber); |
| } |
| |
| private void createUI() { |
| mParent = getParent(); |
| mShell = new Shell(mParent, getStyle()); |
| mShell.setText("Static Port"); |
| |
| mShell.setLayout(new GridLayout(1, false)); |
| |
| mShell.addListener(SWT.Close, new Listener() { |
| @Override |
| public void handleEvent(Event event) { |
| } |
| }); |
| |
| // center part with the edit field |
| Composite main = new Composite(mShell, SWT.NONE); |
| main.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| main.setLayout(new GridLayout(2, false)); |
| |
| Label l0 = new Label(main, SWT.NONE); |
| l0.setText("Device Name:"); |
| |
| final Text deviceSNText = new Text(main, SWT.SINGLE | SWT.BORDER); |
| deviceSNText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| if (mDeviceSn != null) { |
| deviceSNText.setText(mDeviceSn); |
| } |
| deviceSNText.addModifyListener(new ModifyListener() { |
| @Override |
| public void modifyText(ModifyEvent e) { |
| mDeviceSn = deviceSNText.getText().trim(); |
| validate(); |
| } |
| }); |
| |
| Label l = new Label(main, SWT.NONE); |
| l.setText("Application Name:"); |
| |
| final Text appNameText = new Text(main, SWT.SINGLE | SWT.BORDER); |
| if (mAppName != null) { |
| appNameText.setText(mAppName); |
| } |
| appNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| appNameText.addModifyListener(new ModifyListener() { |
| @Override |
| public void modifyText(ModifyEvent e) { |
| mAppName = appNameText.getText().trim(); |
| validate(); |
| } |
| }); |
| |
| Label l2 = new Label(main, SWT.NONE); |
| l2.setText("Debug Port:"); |
| |
| final Text debugPortText = new Text(main, SWT.SINGLE | SWT.BORDER); |
| if (mPortNumber != null) { |
| debugPortText.setText(mPortNumber); |
| } |
| debugPortText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| debugPortText.addModifyListener(new ModifyListener() { |
| @Override |
| public void modifyText(ModifyEvent e) { |
| mPortNumber = debugPortText.getText().trim(); |
| validate(); |
| } |
| }); |
| |
| // warning label |
| Composite warningComp = new Composite(mShell, SWT.NONE); |
| warningComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| warningComp.setLayout(new GridLayout(1, true)); |
| |
| mWarning = new Label(warningComp, SWT.NONE); |
| mWarning.setText(""); |
| mWarning.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| |
| // bottom part with the ok/cancel |
| Composite bottomComp = new Composite(mShell, SWT.NONE); |
| bottomComp |
| .setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER)); |
| bottomComp.setLayout(new GridLayout(2, true)); |
| |
| mOkButton = new Button(bottomComp, SWT.NONE); |
| mOkButton.setText("OK"); |
| mOkButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| mOk = true; |
| mShell.close(); |
| } |
| }); |
| mOkButton.setEnabled(false); |
| mShell.setDefaultButton(mOkButton); |
| |
| Button cancelButton = new Button(bottomComp, SWT.NONE); |
| cancelButton.setText("Cancel"); |
| cancelButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| mShell.close(); |
| } |
| }); |
| |
| validate(); |
| } |
| |
| /** |
| * Validates the content of the 2 text fields and enable/disable "ok", while |
| * setting up the warning/error message. |
| */ |
| private void validate() { |
| // first we reset the warning dialog. This allows us to latter |
| // display warnings. |
| mWarning.setText(""); //$NON-NLS-1$ |
| |
| // check the device name field is not empty |
| if (mDeviceSn == null || mDeviceSn.length() == 0) { |
| mWarning.setText("Device name missing."); |
| mOkButton.setEnabled(false); |
| return; |
| } |
| |
| // check the application name field is not empty |
| if (mAppName == null || mAppName.length() == 0) { |
| mWarning.setText("Application name missing."); |
| mOkButton.setEnabled(false); |
| return; |
| } |
| |
| String packageError = "Application name must be a valid Java package name."; |
| |
| // validate the package name as well. It must be a fully qualified |
| // java package. |
| String[] packageSegments = mAppName.split("\\."); //$NON-NLS-1$ |
| for (String p : packageSegments) { |
| if (p.matches("^[a-zA-Z][a-zA-Z0-9]*") == false) { //$NON-NLS-1$ |
| mWarning.setText(packageError); |
| mOkButton.setEnabled(false); |
| return; |
| } |
| |
| // lets also display a warning if the package contains upper case |
| // letters. |
| if (p.matches("^[a-z][a-z0-9]*") == false) { //$NON-NLS-1$ |
| mWarning.setText("Lower case is recommended for Java packages."); |
| } |
| } |
| |
| // the split will not detect the last char being a '.' |
| // so we test it manually |
| if (mAppName.charAt(mAppName.length()-1) == '.') { |
| mWarning.setText(packageError); |
| mOkButton.setEnabled(false); |
| return; |
| } |
| |
| // now we test the package name field is not empty. |
| if (mPortNumber == null || mPortNumber.length() == 0) { |
| mWarning.setText("Port Number missing."); |
| mOkButton.setEnabled(false); |
| return; |
| } |
| |
| // then we check it only contains digits. |
| if (mPortNumber.matches("[0-9]*") == false) { //$NON-NLS-1$ |
| mWarning.setText("Port Number invalid."); |
| mOkButton.setEnabled(false); |
| return; |
| } |
| |
| // get the int from the port number to validate |
| long port = Long.valueOf(mPortNumber); |
| if (port >= 32767) { |
| mOkButton.setEnabled(false); |
| return; |
| } |
| |
| // check if its in the list of already used ports |
| if (port != mEditPort) { |
| for (Integer i : mPorts) { |
| if (port == i.intValue()) { |
| mWarning.setText("Port already in use."); |
| mOkButton.setEnabled(false); |
| return; |
| } |
| } |
| } |
| |
| // at this point there's not error, so we enable the ok button. |
| mOkButton.setEnabled(true); |
| } |
| } |