Home | History | Annotate | Download | only in ddms
      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.ddmlib.IDevice;
     20 
     21 import org.eclipse.swt.SWT;
     22 import org.eclipse.swt.events.ModifyEvent;
     23 import org.eclipse.swt.events.ModifyListener;
     24 import org.eclipse.swt.events.SelectionAdapter;
     25 import org.eclipse.swt.events.SelectionEvent;
     26 import org.eclipse.swt.graphics.Rectangle;
     27 import org.eclipse.swt.layout.GridData;
     28 import org.eclipse.swt.layout.GridLayout;
     29 import org.eclipse.swt.widgets.Button;
     30 import org.eclipse.swt.widgets.Composite;
     31 import org.eclipse.swt.widgets.Dialog;
     32 import org.eclipse.swt.widgets.Display;
     33 import org.eclipse.swt.widgets.Event;
     34 import org.eclipse.swt.widgets.Label;
     35 import org.eclipse.swt.widgets.Listener;
     36 import org.eclipse.swt.widgets.Shell;
     37 import org.eclipse.swt.widgets.Text;
     38 
     39 import java.util.ArrayList;
     40 
     41 /**
     42  * Small dialog box to edit a static port number.
     43  */
     44 public class StaticPortEditDialog extends Dialog {
     45 
     46     private static final int DLG_WIDTH = 400;
     47     private static final int DLG_HEIGHT = 200;
     48 
     49     private Shell mParent;
     50 
     51     private Shell mShell;
     52 
     53     private boolean mOk = false;
     54 
     55     private String mAppName;
     56 
     57     private String mPortNumber;
     58 
     59     private Button mOkButton;
     60 
     61     private Label mWarning;
     62 
     63     /** List of ports already in use */
     64     private ArrayList<Integer> mPorts;
     65 
     66     /** This is the port being edited. */
     67     private int mEditPort = -1;
     68     private String mDeviceSn;
     69 
     70     /**
     71      * Creates a dialog with empty fields.
     72      * @param parent The parent Shell
     73      * @param ports The list of already used port numbers.
     74      */
     75     public StaticPortEditDialog(Shell parent, ArrayList<Integer> ports) {
     76         super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL);
     77         mPorts = ports;
     78         mDeviceSn = IDevice.FIRST_EMULATOR_SN;
     79     }
     80 
     81     /**
     82      * Creates a dialog with predefined values.
     83      * @param shell The parent shell
     84      * @param ports The list of already used port numbers.
     85      * @param oldDeviceSN the device serial number to display
     86      * @param oldAppName The application name to display
     87      * @param oldPortNumber The port number to display
     88      */
     89     public StaticPortEditDialog(Shell shell, ArrayList<Integer> ports,
     90             String oldDeviceSN, String oldAppName, String oldPortNumber) {
     91         this(shell, ports);
     92 
     93         mDeviceSn = oldDeviceSN;
     94         mAppName = oldAppName;
     95         mPortNumber = oldPortNumber;
     96         mEditPort = Integer.valueOf(mPortNumber);
     97     }
     98 
     99     /**
    100      * Opens the dialog. The method will return when the user closes the dialog
    101      * somehow.
    102      *
    103      * @return true if ok was pressed, false if cancelled.
    104      */
    105     public boolean open() {
    106         createUI();
    107 
    108         if (mParent == null || mShell == null) {
    109             return false;
    110         }
    111 
    112         mShell.setMinimumSize(DLG_WIDTH, DLG_HEIGHT);
    113         Rectangle r = mParent.getBounds();
    114         // get the center new top left.
    115         int cx = r.x + r.width/2;
    116         int x = cx - DLG_WIDTH / 2;
    117         int cy = r.y + r.height/2;
    118         int y = cy - DLG_HEIGHT / 2;
    119         mShell.setBounds(x, y, DLG_WIDTH, DLG_HEIGHT);
    120 
    121         mShell.open();
    122 
    123         Display display = mParent.getDisplay();
    124         while (!mShell.isDisposed()) {
    125             if (!display.readAndDispatch())
    126                 display.sleep();
    127         }
    128 
    129         return mOk;
    130     }
    131 
    132     public String getDeviceSN() {
    133         return mDeviceSn;
    134     }
    135 
    136     public String getAppName() {
    137         return mAppName;
    138     }
    139 
    140     public int getPortNumber() {
    141         return Integer.valueOf(mPortNumber);
    142     }
    143 
    144     private void createUI() {
    145         mParent = getParent();
    146         mShell = new Shell(mParent, getStyle());
    147         mShell.setText("Static Port");
    148 
    149         mShell.setLayout(new GridLayout(1, false));
    150 
    151         mShell.addListener(SWT.Close, new Listener() {
    152             @Override
    153             public void handleEvent(Event event) {
    154             }
    155         });
    156 
    157         // center part with the edit field
    158         Composite main = new Composite(mShell, SWT.NONE);
    159         main.setLayoutData(new GridData(GridData.FILL_BOTH));
    160         main.setLayout(new GridLayout(2, false));
    161 
    162         Label l0 = new Label(main, SWT.NONE);
    163         l0.setText("Device Name:");
    164 
    165         final Text deviceSNText = new Text(main, SWT.SINGLE | SWT.BORDER);
    166         deviceSNText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    167         if (mDeviceSn != null) {
    168             deviceSNText.setText(mDeviceSn);
    169         }
    170         deviceSNText.addModifyListener(new ModifyListener() {
    171             @Override
    172             public void modifyText(ModifyEvent e) {
    173                 mDeviceSn = deviceSNText.getText().trim();
    174                 validate();
    175             }
    176         });
    177 
    178         Label l = new Label(main, SWT.NONE);
    179         l.setText("Application Name:");
    180 
    181         final Text appNameText = new Text(main, SWT.SINGLE | SWT.BORDER);
    182         if (mAppName != null) {
    183             appNameText.setText(mAppName);
    184         }
    185         appNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    186         appNameText.addModifyListener(new ModifyListener() {
    187             @Override
    188             public void modifyText(ModifyEvent e) {
    189                 mAppName = appNameText.getText().trim();
    190                 validate();
    191             }
    192         });
    193 
    194         Label l2 = new Label(main, SWT.NONE);
    195         l2.setText("Debug Port:");
    196 
    197         final Text debugPortText = new Text(main, SWT.SINGLE | SWT.BORDER);
    198         if (mPortNumber != null) {
    199             debugPortText.setText(mPortNumber);
    200         }
    201         debugPortText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    202         debugPortText.addModifyListener(new ModifyListener() {
    203             @Override
    204             public void modifyText(ModifyEvent e) {
    205                 mPortNumber = debugPortText.getText().trim();
    206                 validate();
    207             }
    208         });
    209 
    210         // warning label
    211         Composite warningComp = new Composite(mShell, SWT.NONE);
    212         warningComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    213         warningComp.setLayout(new GridLayout(1, true));
    214 
    215         mWarning = new Label(warningComp, SWT.NONE);
    216         mWarning.setText("");
    217         mWarning.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    218 
    219         // bottom part with the ok/cancel
    220         Composite bottomComp = new Composite(mShell, SWT.NONE);
    221         bottomComp
    222                 .setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
    223         bottomComp.setLayout(new GridLayout(2, true));
    224 
    225         mOkButton = new Button(bottomComp, SWT.NONE);
    226         mOkButton.setText("OK");
    227         mOkButton.addSelectionListener(new SelectionAdapter() {
    228             @Override
    229             public void widgetSelected(SelectionEvent e) {
    230                 mOk = true;
    231                 mShell.close();
    232             }
    233         });
    234         mOkButton.setEnabled(false);
    235         mShell.setDefaultButton(mOkButton);
    236 
    237         Button cancelButton = new Button(bottomComp, SWT.NONE);
    238         cancelButton.setText("Cancel");
    239         cancelButton.addSelectionListener(new SelectionAdapter() {
    240             @Override
    241             public void widgetSelected(SelectionEvent e) {
    242                 mShell.close();
    243             }
    244         });
    245 
    246         validate();
    247     }
    248 
    249     /**
    250      * Validates the content of the 2 text fields and enable/disable "ok", while
    251      * setting up the warning/error message.
    252      */
    253     private void validate() {
    254         // first we reset the warning dialog. This allows us to latter
    255         // display warnings.
    256         mWarning.setText(""); //$NON-NLS-1$
    257 
    258         // check the device name field is not empty
    259         if (mDeviceSn == null || mDeviceSn.length() == 0) {
    260             mWarning.setText("Device name missing.");
    261             mOkButton.setEnabled(false);
    262             return;
    263         }
    264 
    265         // check the application name field is not empty
    266         if (mAppName == null || mAppName.length() == 0) {
    267             mWarning.setText("Application name missing.");
    268             mOkButton.setEnabled(false);
    269             return;
    270         }
    271 
    272         String packageError = "Application name must be a valid Java package name.";
    273 
    274         // validate the package name as well. It must be a fully qualified
    275         // java package.
    276         String[] packageSegments = mAppName.split("\\."); //$NON-NLS-1$
    277         for (String p : packageSegments) {
    278             if (p.matches("^[a-zA-Z][a-zA-Z0-9]*") == false) { //$NON-NLS-1$
    279                 mWarning.setText(packageError);
    280                 mOkButton.setEnabled(false);
    281                 return;
    282             }
    283 
    284             // lets also display a warning if the package contains upper case
    285             // letters.
    286             if (p.matches("^[a-z][a-z0-9]*") == false) { //$NON-NLS-1$
    287                 mWarning.setText("Lower case is recommended for Java packages.");
    288             }
    289         }
    290 
    291         // the split will not detect the last char being a '.'
    292         // so we test it manually
    293         if (mAppName.charAt(mAppName.length()-1) == '.') {
    294             mWarning.setText(packageError);
    295             mOkButton.setEnabled(false);
    296             return;
    297         }
    298 
    299         // now we test the package name field is not empty.
    300         if (mPortNumber == null || mPortNumber.length() == 0) {
    301             mWarning.setText("Port Number missing.");
    302             mOkButton.setEnabled(false);
    303             return;
    304         }
    305 
    306         // then we check it only contains digits.
    307         if (mPortNumber.matches("[0-9]*") == false) { //$NON-NLS-1$
    308             mWarning.setText("Port Number invalid.");
    309             mOkButton.setEnabled(false);
    310             return;
    311         }
    312 
    313         // get the int from the port number to validate
    314         long port = Long.valueOf(mPortNumber);
    315         if (port >= 32767) {
    316             mOkButton.setEnabled(false);
    317             return;
    318         }
    319 
    320         // check if its in the list of already used ports
    321         if (port != mEditPort) {
    322             for (Integer i : mPorts) {
    323                 if (port == i.intValue()) {
    324                     mWarning.setText("Port already in use.");
    325                     mOkButton.setEnabled(false);
    326                     return;
    327                 }
    328             }
    329         }
    330 
    331         // at this point there's not error, so we enable the ok button.
    332         mOkButton.setEnabled(true);
    333     }
    334 }
    335