summaryrefslogtreecommitdiff
path: root/src/plugins/emulator/src/com/motorola/studio/android/emulator/core/emulationui/SrcDestComposite.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/emulator/src/com/motorola/studio/android/emulator/core/emulationui/SrcDestComposite.java')
-rw-r--r--src/plugins/emulator/src/com/motorola/studio/android/emulator/core/emulationui/SrcDestComposite.java439
1 files changed, 439 insertions, 0 deletions
diff --git a/src/plugins/emulator/src/com/motorola/studio/android/emulator/core/emulationui/SrcDestComposite.java b/src/plugins/emulator/src/com/motorola/studio/android/emulator/core/emulationui/SrcDestComposite.java
new file mode 100644
index 0000000..a70194e
--- /dev/null
+++ b/src/plugins/emulator/src/com/motorola/studio/android/emulator/core/emulationui/SrcDestComposite.java
@@ -0,0 +1,439 @@
+/*
+* 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.motorola.studio.android.emulator.core.emulationui;
+
+import static com.motorola.studio.android.common.log.StudioLogger.debug;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.osgi.util.NLS;
+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.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import com.motorola.studio.android.emulator.core.devfrm.DeviceFrameworkManager;
+import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance;
+import com.motorola.studio.android.emulator.i18n.EmulatorNLS;
+
+/**
+ * DESCRIPTION:
+ * This is a composite that is used by several emulation UI elements to choose source and
+ * destination elements
+ *
+ * RESPONSIBILITY:
+ * Provide means for the user to choose which emulator and phone number will be involved
+ * in a emulation
+ *
+ * COLABORATORS:
+ * None.
+ *
+ * USAGE:
+ * Add the composite to a UI element that needs to have a emulator and a phone number
+ * chosen by the user
+ */
+public class SrcDestComposite extends Composite
+{
+ /**
+ * Message that will be shown near the emulator combo
+ */
+ private String emulatorLabelStr;
+
+ /**
+ * Message that will be shown near the phone number text field
+ */
+ private String phoneNumberLabelStr;
+
+ /**
+ * Emulator currently selected
+ */
+ private String selectedEmulator;
+
+ /**
+ * Phone number currently selected
+ */
+ private String selectedPhoneNumber;
+
+ /**
+ * True if the composite is valid and can provide information to the user class
+ * False if not.
+ */
+ private boolean isValid = false;
+
+ /**
+ * Error message to be shown to the user if the composite data is not valid
+ */
+ private String errorMessage =
+ NLS.bind(EmulatorNLS.ERR_SrcDestComposite_InvalidFillingBase,
+ EmulatorNLS.ERR_SrcDestComposite_InvalidFillingPhoneNumber,
+ EmulatorNLS.ERR_SrcDestComposite_InvalidFillingEmulator);
+
+ // Widgets
+ private Combo runningEmulatorsCombo;
+
+ private Text phoneNumberText;
+
+ // attribute for calculating label sizes (for layout purposes)
+ private FontMetrics fontMetrics = null;
+
+ /**
+ * Constructor.
+ *
+ * @param parent The parent composite of this one
+ * @param style Style of the composite. See constants at SWT class
+ * @param showSrcControls True if this composite should show
+ * the emulation source controls. False otherwise
+ * @param isEmulatorSrc True if this composite will have the emulator
+ * part as source in emulation. False if the phone number
+ * will be the source
+ */
+ public SrcDestComposite(Composite parent, int style, boolean showSrcControls,
+ boolean isEmulatorSrc)
+ {
+ super(parent, style);
+
+ GridLayout layout = new GridLayout(2, false);
+ layout.marginHeight = 5;
+ layout.marginWidth = 5;
+ layout.verticalSpacing = 5;
+ layout.horizontalSpacing = 2;
+ this.setLayout(layout);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ this.setLayoutData(data);
+
+ // initialize font metrics
+ GC gc = new GC(this);
+ gc.setFont(this.getFont());
+ fontMetrics = gc.getFontMetrics();
+ gc.dispose();
+
+ if (isEmulatorSrc)
+ {
+ // When emulator is the source part, its UI is build prior to phone number UI,
+ // and appropriate labels are used for both
+ debug("Using emulator as source");
+ emulatorLabelStr = EmulatorNLS.UI_SrcDestComposite_OriginatingRunningEmulatorLabel;
+ phoneNumberLabelStr = EmulatorNLS.UI_SrcDestComposite_DestinationPhoneNumberLabel;
+ if (showSrcControls)
+ {
+ debug("Showing source controls");
+ createEmulatorUI();
+ }
+ createPhoneNumberUI();
+ }
+ else
+ {
+ // When phone number is the source part, its UI is build prior to emulator UI,
+ // and appropriate labels are used for both
+ debug("Using phone number as source");
+ emulatorLabelStr = EmulatorNLS.UI_SrcDestComposite_DestinationRunningEmulatorLabel;
+ phoneNumberLabelStr = EmulatorNLS.UI_SrcDestComposite_OriginatingPhoneNumberLabel;
+ if (showSrcControls)
+ {
+ debug("Showing source controls");
+ createPhoneNumberUI();
+ }
+ createEmulatorUI();
+ }
+
+ addListeners();
+
+ // call the check method to refresh error message.
+ checkData();
+
+ }
+
+ /**
+ * Build the emulator part controls
+ */
+ private void createEmulatorUI()
+ {
+
+ Label runningEmulatorsLabel = new Label(this, SWT.NONE);
+ runningEmulatorsLabel.setText(emulatorLabelStr);
+ GridData data = new GridData(SWT.FILL, SWT.CENTER, false, false);
+ data.widthHint = getLabelWidthHint(runningEmulatorsLabel);
+ runningEmulatorsLabel.setLayoutData(data);
+
+ this.runningEmulatorsCombo = new Combo(this, SWT.BORDER | SWT.READ_ONLY);
+ data = new GridData(SWT.FILL, SWT.FILL, true, false);
+ this.runningEmulatorsCombo.setLayoutData(data);
+ populateEmulatorCombo();
+
+ }
+
+ /**
+ * Build the phone number part controls
+ */
+ private void createPhoneNumberUI()
+ {
+
+ Label phoneNumberLabel = new Label(this, SWT.NONE);
+ phoneNumberLabel.setText(phoneNumberLabelStr);
+ GridData data = new GridData(SWT.FILL, SWT.CENTER, false, false);
+ data.widthHint = getLabelWidthHint(phoneNumberLabel);
+ phoneNumberLabel.setLayoutData(data);
+
+ this.phoneNumberText = new Text(this, SWT.BORDER);
+ data = new GridData(SWT.FILL, SWT.FILL, true, false);
+ this.phoneNumberText.setLayoutData(data);
+ this.phoneNumberText.setTextLimit(40);
+
+ }
+
+ /**
+ * Add listeners to the composite controls
+ */
+ private void addListeners()
+ {
+
+ if (runningEmulatorsCombo != null)
+ {
+ runningEmulatorsCombo.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ selectedEmulator = getCurrentlySelectedIdentifier();
+ checkData();
+ }
+ });
+ }
+
+ if (phoneNumberText != null)
+ {
+ phoneNumberText.addModifyListener(new ModifyListener()
+ {
+ public void modifyText(ModifyEvent e)
+ {
+ selectedPhoneNumber = phoneNumberText.getText();
+ checkData();
+ }
+ });
+ }
+ }
+
+ /**
+ * Defines the width hint to be used for the given label on a GridData object.
+ *
+ * @param label the label to calculate the width hint for
+ *
+ * @return the width hint
+ */
+ private int getLabelWidthHint(Label label)
+ {
+ int widthHint = Dialog.convertHorizontalDLUsToPixels(fontMetrics, label.getText().length());
+ return Math.max(widthHint, label.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
+ }
+
+ /**
+ * Populates the emulator combo box with the currently running emulators
+ */
+ private void populateEmulatorCombo()
+ {
+
+ // Populating emulator combo with all running emulator names
+ // Besides, keeping an array of the identifiers as combo data.
+ Map<String, String> identifiersAndNames = new HashMap<String, String>();
+ Collection<IAndroidEmulatorInstance> startedInstances =
+ DeviceFrameworkManager.getInstance().getAllStartedInstances();
+ for (IAndroidEmulatorInstance instance : startedInstances)
+ {
+ identifiersAndNames.put(instance.getInstanceIdentifier(), instance.getName());
+ }
+
+ String[] instanceNamesArray = new String[identifiersAndNames.size()];
+ String[] identifiersArray = new String[identifiersAndNames.size()];
+ int i = 0;
+
+ Set<String> identifiers = identifiersAndNames.keySet();
+ for (String identifier : identifiers)
+ {
+
+ String viewerName = identifiersAndNames.get(identifier);
+
+ // It is VERY important that the index used at the data array is equal to the
+ // index used at the items array. According to the selected item in the combo, the
+ // corresponding identifier is retrieved from the data array in the future
+ instanceNamesArray[i] = viewerName;
+ identifiersArray[i] = identifier;
+ i++;
+ }
+
+ runningEmulatorsCombo.setItems(instanceNamesArray);
+ runningEmulatorsCombo.setData(identifiersArray);
+
+ // if there is just one emulator in the combo list,
+ // it will be chose by default.
+ if (runningEmulatorsCombo.getItemCount() == 1)
+ {
+ runningEmulatorsCombo.select(0);
+ selectedEmulator = getCurrentlySelectedIdentifier();
+ checkData();
+ }
+
+ }
+
+ /**
+ * Retrieve the identifier of the selected instance at Android Emulator combo box
+ *
+ * @return The identifier, or an empty string if no emulator is selected
+ */
+ private String getCurrentlySelectedIdentifier()
+ {
+
+ String currentlySelectedSerial = "";
+ int index = runningEmulatorsCombo.getSelectionIndex();
+
+ if (index >= 0)
+ {
+ String[] serials = (String[]) runningEmulatorsCombo.getData();
+ currentlySelectedSerial = serials[index];
+
+ }
+
+ return currentlySelectedSerial;
+ }
+
+ /**
+ * Get the emulator identifier that was selected by the user
+ *
+ * @return The selected emulator identifier
+ */
+ public String getSelectedEmulator()
+ {
+ return selectedEmulator;
+ }
+
+ /**
+ * Get the phone number that was typed by the user
+ *
+ * @return The phone number typed by the user
+ */
+ public String getSelectedPhoneNumber()
+ {
+ return selectedPhoneNumber;
+ }
+
+ /**
+ * Tests if the values chosen/typed by the user are valid
+ * By invoking this method, the user class is able to know if it can proceed
+ *
+ * @return True if the user has chosen valid values. False otherwise
+ */
+ public boolean isValid()
+ {
+ return isValid;
+ }
+
+ /**
+ * Retrieves the error message to be shown to the user if the composite is
+ * not valid
+ *
+ * @return The error message if the composite is not valid, or <code>null</code> if
+ * the composite is valid and no error message should be displayed.
+ */
+ public String getErrorMessage()
+ {
+ return errorMessage;
+ }
+
+ /**
+ * Check if the data entered by the user is correct and set instance variables
+ * to store the test results
+ */
+ private void checkData()
+ {
+
+ isValid = false;
+
+ boolean isEmulatorValid = false;
+ boolean isPhoneNumberValid = false;
+
+ boolean isUsingPhoneNumber = (phoneNumberText != null);
+ boolean isUsingEmulator = (runningEmulatorsCombo != null);
+
+ // Tests if emulator selection is valid.
+ //
+ // If the emulator combo is null, that means that the user decided not to use it. In
+ // this case, it will always be valid. Otherwise, the combo selection needs to be
+ // not null and not blank
+ if ((!isUsingEmulator) || ((selectedEmulator != null) && (!selectedEmulator.equals(""))))
+ {
+ isEmulatorValid = true;
+ }
+
+ // Tests if phone number selection is valid.
+ //
+ // If the phone number text is null, that means that the user decided not to use it. In
+ // this case, it will always be valid. Otherwise, the text field selection needs to be
+ // not null, not blank and can be parsed to double (that means that the contents are
+ // composed by numerals only)
+ if (!isUsingPhoneNumber)
+ {
+ isPhoneNumberValid = true;
+ }
+ else if ((selectedPhoneNumber != null) && (!selectedPhoneNumber.equals("")))
+ {
+ Pattern p = Pattern.compile("(\\d)+");
+ Matcher m = p.matcher(selectedPhoneNumber);
+ isPhoneNumberValid = m.matches();
+ }
+
+ // Based on previous checks, determine if the composite state is valid
+ if (isEmulatorValid && isPhoneNumberValid)
+ {
+ isValid = true;
+ errorMessage = null;
+ }
+ else
+ {
+ // If not valid, an error message will be shown. The following calculations
+ // are for determining which error has happened to build the message
+ String phoneNumberError = "";
+ String emulatorError = "";
+
+ if (isUsingPhoneNumber && (!isPhoneNumberValid))
+ {
+ phoneNumberError = EmulatorNLS.ERR_SrcDestComposite_InvalidFillingPhoneNumber;
+ }
+ if (isUsingEmulator && (!isEmulatorValid))
+ {
+ emulatorError = EmulatorNLS.ERR_SrcDestComposite_InvalidFillingEmulator;
+ }
+
+ errorMessage =
+ NLS.bind(EmulatorNLS.ERR_SrcDestComposite_InvalidFillingBase,
+ phoneNumberError, emulatorError);
+ }
+
+ }
+}