| /* |
| * Copyright (C) 2007 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.ddmuilib; |
| |
| import com.android.ddmlib.IDevice; |
| import com.android.ddmlib.EmulatorConsole; |
| import com.android.ddmlib.EmulatorConsole.GsmMode; |
| import com.android.ddmlib.EmulatorConsole.GsmStatus; |
| import com.android.ddmlib.EmulatorConsole.NetworkStatus; |
| import com.android.ddmuilib.location.CoordinateControls; |
| import com.android.ddmuilib.location.GpxParser; |
| import com.android.ddmuilib.location.KmlParser; |
| import com.android.ddmuilib.location.TrackContentProvider; |
| import com.android.ddmuilib.location.TrackLabelProvider; |
| import com.android.ddmuilib.location.TrackPoint; |
| import com.android.ddmuilib.location.WayPoint; |
| import com.android.ddmuilib.location.WayPointContentProvider; |
| import com.android.ddmuilib.location.WayPointLabelProvider; |
| import com.android.ddmuilib.location.GpxParser.Track; |
| |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.TableViewer; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.SWTException; |
| import org.eclipse.swt.custom.ScrolledComposite; |
| import org.eclipse.swt.custom.StackLayout; |
| import org.eclipse.swt.events.ControlAdapter; |
| import org.eclipse.swt.events.ControlEvent; |
| 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.Image; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.FillLayout; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.FileDialog; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.TabFolder; |
| import org.eclipse.swt.widgets.TabItem; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.Text; |
| |
| /** |
| * Panel to control the emulator using EmulatorConsole objects. |
| */ |
| public class EmulatorControlPanel extends SelectionDependentPanel { |
| |
| // default location: Patio outside Charlie's |
| private final static double DEFAULT_LONGITUDE = -122.084095; |
| private final static double DEFAULT_LATITUDE = 37.422006; |
| |
| private final static String SPEED_FORMAT = "Speed: %1$dX"; |
| |
| |
| /** |
| * Map between the display gsm mode and the internal tag used by the display. |
| */ |
| private final static String[][] GSM_MODES = new String[][] { |
| { "unregistered", GsmMode.UNREGISTERED.getTag() }, |
| { "home", GsmMode.HOME.getTag() }, |
| { "roaming", GsmMode.ROAMING.getTag() }, |
| { "searching", GsmMode.SEARCHING.getTag() }, |
| { "denied", GsmMode.DENIED.getTag() }, |
| }; |
| |
| private final static String[] NETWORK_SPEEDS = new String[] { |
| "Full", |
| "GSM", |
| "HSCSD", |
| "GPRS", |
| "EDGE", |
| "UMTS", |
| "HSDPA", |
| }; |
| |
| private final static String[] NETWORK_LATENCIES = new String[] { |
| "None", |
| "GPRS", |
| "EDGE", |
| "UMTS", |
| }; |
| |
| private final static int[] PLAY_SPEEDS = new int[] { 1, 2, 5, 10, 20, 50 }; |
| |
| private final static String RE_PHONE_NUMBER = "^[+#0-9]+$"; //$NON-NLS-1$ |
| private final static String PREFS_WAYPOINT_COL_NAME = "emulatorControl.waypoint.name"; //$NON-NLS-1$ |
| private final static String PREFS_WAYPOINT_COL_LONGITUDE = "emulatorControl.waypoint.longitude"; //$NON-NLS-1$ |
| private final static String PREFS_WAYPOINT_COL_LATITUDE = "emulatorControl.waypoint.latitude"; //$NON-NLS-1$ |
| private final static String PREFS_WAYPOINT_COL_ELEVATION = "emulatorControl.waypoint.elevation"; //$NON-NLS-1$ |
| private final static String PREFS_WAYPOINT_COL_DESCRIPTION = "emulatorControl.waypoint.desc"; //$NON-NLS-1$ |
| private final static String PREFS_TRACK_COL_NAME = "emulatorControl.track.name"; //$NON-NLS-1$ |
| private final static String PREFS_TRACK_COL_COUNT = "emulatorControl.track.count"; //$NON-NLS-1$ |
| private final static String PREFS_TRACK_COL_FIRST = "emulatorControl.track.first"; //$NON-NLS-1$ |
| private final static String PREFS_TRACK_COL_LAST = "emulatorControl.track.last"; //$NON-NLS-1$ |
| private final static String PREFS_TRACK_COL_COMMENT = "emulatorControl.track.comment"; //$NON-NLS-1$ |
| |
| private IImageLoader mImageLoader; |
| |
| private EmulatorConsole mEmulatorConsole; |
| |
| private Composite mParent; |
| |
| private Label mVoiceLabel; |
| private Combo mVoiceMode; |
| private Label mDataLabel; |
| private Combo mDataMode; |
| private Label mSpeedLabel; |
| private Combo mNetworkSpeed; |
| private Label mLatencyLabel; |
| private Combo mNetworkLatency; |
| |
| private Label mNumberLabel; |
| private Text mPhoneNumber; |
| |
| private Button mVoiceButton; |
| private Button mSmsButton; |
| |
| private Label mMessageLabel; |
| private Text mSmsMessage; |
| |
| private Button mCallButton; |
| private Button mCancelButton; |
| |
| private TabFolder mLocationFolders; |
| |
| private Button mDecimalButton; |
| private Button mSexagesimalButton; |
| private CoordinateControls mLongitudeControls; |
| private CoordinateControls mLatitudeControls; |
| private Button mGpxUploadButton; |
| private Table mGpxWayPointTable; |
| private Table mGpxTrackTable; |
| private Button mKmlUploadButton; |
| private Table mKmlWayPointTable; |
| |
| private Button mPlayGpxButton; |
| private Button mGpxBackwardButton; |
| private Button mGpxForwardButton; |
| private Button mGpxSpeedButton; |
| private Button mPlayKmlButton; |
| private Button mKmlBackwardButton; |
| private Button mKmlForwardButton; |
| private Button mKmlSpeedButton; |
| |
| private Image mPlayImage; |
| private Image mPauseImage; |
| |
| private Thread mPlayingThread; |
| private boolean mPlayingTrack; |
| private int mPlayDirection = 1; |
| private int mSpeed; |
| private int mSpeedIndex; |
| |
| private final SelectionAdapter mDirectionButtonAdapter = new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| Button b = (Button)e.getSource(); |
| if (b.getSelection() == false) { |
| // basically the button was unselected, which we don't allow. |
| // so we reselect it. |
| b.setSelection(true); |
| return; |
| } |
| |
| // now handle selection change. |
| if (b == mGpxForwardButton || b == mKmlForwardButton) { |
| mGpxBackwardButton.setSelection(false); |
| mGpxForwardButton.setSelection(true); |
| mKmlBackwardButton.setSelection(false); |
| mKmlForwardButton.setSelection(true); |
| mPlayDirection = 1; |
| |
| } else { |
| mGpxBackwardButton.setSelection(true); |
| mGpxForwardButton.setSelection(false); |
| mKmlBackwardButton.setSelection(true); |
| mKmlForwardButton.setSelection(false); |
| mPlayDirection = -1; |
| } |
| } |
| }; |
| |
| private final SelectionAdapter mSpeedButtonAdapter = new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| mSpeedIndex = (mSpeedIndex+1) % PLAY_SPEEDS.length; |
| mSpeed = PLAY_SPEEDS[mSpeedIndex]; |
| |
| mGpxSpeedButton.setText(String.format(SPEED_FORMAT, mSpeed)); |
| mGpxPlayControls.pack(); |
| mKmlSpeedButton.setText(String.format(SPEED_FORMAT, mSpeed)); |
| mKmlPlayControls.pack(); |
| |
| if (mPlayingThread != null) { |
| mPlayingThread.interrupt(); |
| } |
| } |
| }; |
| private Composite mKmlPlayControls; |
| private Composite mGpxPlayControls; |
| |
| |
| public EmulatorControlPanel(IImageLoader imageLoader) { |
| mImageLoader = imageLoader; |
| } |
| |
| /** |
| * Sent when a new device is selected. The new device can be accessed |
| * with {@link #getCurrentDevice()} |
| */ |
| @Override |
| public void deviceSelected() { |
| handleNewDevice(getCurrentDevice()); |
| } |
| |
| /** |
| * Sent when a new client is selected. The new client can be accessed |
| * with {@link #getCurrentClient()} |
| */ |
| @Override |
| public void clientSelected() { |
| // pass |
| } |
| |
| /** |
| * Creates a control capable of displaying some information. This is |
| * called once, when the application is initializing, from the UI thread. |
| */ |
| @Override |
| protected Control createControl(Composite parent) { |
| mParent = parent; |
| |
| final ScrolledComposite scollingParent = new ScrolledComposite(parent, SWT.V_SCROLL); |
| scollingParent.setExpandVertical(true); |
| scollingParent.setExpandHorizontal(true); |
| scollingParent.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| |
| final Composite top = new Composite(scollingParent, SWT.NONE); |
| scollingParent.setContent(top); |
| top.setLayout(new GridLayout(1, false)); |
| |
| // set the resize for the scrolling to work (why isn't that done automatically?!?) |
| scollingParent.addControlListener(new ControlAdapter() { |
| @Override |
| public void controlResized(ControlEvent e) { |
| Rectangle r = scollingParent.getClientArea(); |
| scollingParent.setMinSize(top.computeSize(r.width, SWT.DEFAULT)); |
| } |
| }); |
| |
| createRadioControls(top); |
| |
| createCallControls(top); |
| |
| createLocationControls(top); |
| |
| doEnable(false); |
| |
| top.layout(); |
| Rectangle r = scollingParent.getClientArea(); |
| scollingParent.setMinSize(top.computeSize(r.width, SWT.DEFAULT)); |
| |
| return scollingParent; |
| } |
| |
| /** |
| * Create Radio (on/off/roaming, for voice/data) controls. |
| * @param top |
| */ |
| private void createRadioControls(final Composite top) { |
| Group g1 = new Group(top, SWT.NONE); |
| g1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| g1.setLayout(new GridLayout(2, false)); |
| g1.setText("Telephony Status"); |
| |
| // the inside of the group is 2 composite so that all the column of the controls (mainly |
| // combos) have the same width, while not taking the whole screen width |
| Composite insideGroup = new Composite(g1, SWT.NONE); |
| GridLayout gl = new GridLayout(4, false); |
| gl.marginBottom = gl.marginHeight = gl.marginLeft = gl.marginRight = 0; |
| insideGroup.setLayout(gl); |
| |
| mVoiceLabel = new Label(insideGroup, SWT.NONE); |
| mVoiceLabel.setText("Voice:"); |
| mVoiceLabel.setAlignment(SWT.RIGHT); |
| |
| mVoiceMode = new Combo(insideGroup, SWT.READ_ONLY); |
| mVoiceMode.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| for (String[] mode : GSM_MODES) { |
| mVoiceMode.add(mode[0]); |
| } |
| mVoiceMode.addSelectionListener(new SelectionAdapter() { |
| // called when selection changes |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| setVoiceMode(mVoiceMode.getSelectionIndex()); |
| } |
| }); |
| |
| mSpeedLabel = new Label(insideGroup, SWT.NONE); |
| mSpeedLabel.setText("Speed:"); |
| mSpeedLabel.setAlignment(SWT.RIGHT); |
| |
| mNetworkSpeed = new Combo(insideGroup, SWT.READ_ONLY); |
| mNetworkSpeed.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| for (String mode : NETWORK_SPEEDS) { |
| mNetworkSpeed.add(mode); |
| } |
| mNetworkSpeed.addSelectionListener(new SelectionAdapter() { |
| // called when selection changes |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| setNetworkSpeed(mNetworkSpeed.getSelectionIndex()); |
| } |
| }); |
| |
| mDataLabel = new Label(insideGroup, SWT.NONE); |
| mDataLabel.setText("Data:"); |
| mDataLabel.setAlignment(SWT.RIGHT); |
| |
| mDataMode = new Combo(insideGroup, SWT.READ_ONLY); |
| mDataMode.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| for (String[] mode : GSM_MODES) { |
| mDataMode.add(mode[0]); |
| } |
| mDataMode.addSelectionListener(new SelectionAdapter() { |
| // called when selection changes |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| setDataMode(mDataMode.getSelectionIndex()); |
| } |
| }); |
| |
| mLatencyLabel = new Label(insideGroup, SWT.NONE); |
| mLatencyLabel.setText("Latency:"); |
| mLatencyLabel.setAlignment(SWT.RIGHT); |
| |
| mNetworkLatency = new Combo(insideGroup, SWT.READ_ONLY); |
| mNetworkLatency.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| for (String mode : NETWORK_LATENCIES) { |
| mNetworkLatency.add(mode); |
| } |
| mNetworkLatency.addSelectionListener(new SelectionAdapter() { |
| // called when selection changes |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| setNetworkLatency(mNetworkLatency.getSelectionIndex()); |
| } |
| }); |
| |
| // now an empty label to take the rest of the width of the group |
| Label l = new Label(g1, SWT.NONE); |
| l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| } |
| |
| /** |
| * Create Voice/SMS call/hang up controls |
| * @param top |
| */ |
| private void createCallControls(final Composite top) { |
| GridLayout gl; |
| Group g2 = new Group(top, SWT.NONE); |
| g2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| g2.setLayout(new GridLayout(1, false)); |
| g2.setText("Telephony Actions"); |
| |
| // horizontal composite for label + text field |
| Composite phoneComp = new Composite(g2, SWT.NONE); |
| phoneComp.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| gl = new GridLayout(2, false); |
| gl.marginBottom = gl.marginHeight = gl.marginLeft = gl.marginRight = 0; |
| phoneComp.setLayout(gl); |
| |
| mNumberLabel = new Label(phoneComp, SWT.NONE); |
| mNumberLabel.setText("Incoming number:"); |
| |
| mPhoneNumber = new Text(phoneComp, SWT.BORDER | SWT.LEFT | SWT.SINGLE); |
| mPhoneNumber.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| mPhoneNumber.addModifyListener(new ModifyListener() { |
| public void modifyText(ModifyEvent e) { |
| // Reenable the widgets based on the content of the text. |
| // doEnable checks the validity of the phone number to enable/disable some |
| // widgets. |
| // Looks like we're getting a callback at creation time, so we can't |
| // suppose that we are enabled when the text is modified... |
| doEnable(mEmulatorConsole != null); |
| } |
| }); |
| |
| mVoiceButton = new Button(phoneComp, SWT.RADIO); |
| GridData gd = new GridData(); |
| gd.horizontalSpan = 2; |
| mVoiceButton.setText("Voice"); |
| mVoiceButton.setLayoutData(gd); |
| mVoiceButton.setEnabled(false); |
| mVoiceButton.setSelection(true); |
| mVoiceButton.addSelectionListener(new SelectionAdapter() { |
| // called when selection changes |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| doEnable(true); |
| |
| if (mVoiceButton.getSelection()) { |
| mCallButton.setText("Call"); |
| } else { |
| mCallButton.setText("Send"); |
| } |
| } |
| }); |
| |
| mSmsButton = new Button(phoneComp, SWT.RADIO); |
| mSmsButton.setText("SMS"); |
| gd = new GridData(); |
| gd.horizontalSpan = 2; |
| mSmsButton.setLayoutData(gd); |
| mSmsButton.setEnabled(false); |
| // Since there are only 2 radio buttons, we can put a listener on only one (they |
| // are both called on select and unselect event. |
| |
| mMessageLabel = new Label(phoneComp, SWT.NONE); |
| gd = new GridData(); |
| gd.verticalAlignment = SWT.TOP; |
| mMessageLabel.setLayoutData(gd); |
| mMessageLabel.setText("Message:"); |
| mMessageLabel.setEnabled(false); |
| |
| mSmsMessage = new Text(phoneComp, SWT.BORDER | SWT.LEFT | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL); |
| mSmsMessage.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); |
| gd.heightHint = 70; |
| mSmsMessage.setEnabled(false); |
| |
| // composite to put the 2 buttons horizontally |
| Composite g2ButtonComp = new Composite(g2, SWT.NONE); |
| g2ButtonComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| gl = new GridLayout(2, false); |
| gl.marginWidth = gl.marginHeight = 0; |
| g2ButtonComp.setLayout(gl); |
| |
| // now a button below the phone number |
| mCallButton = new Button(g2ButtonComp, SWT.PUSH); |
| mCallButton.setText("Call"); |
| mCallButton.setEnabled(false); |
| mCallButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (mEmulatorConsole != null) { |
| if (mVoiceButton.getSelection()) { |
| processCommandResult(mEmulatorConsole.call(mPhoneNumber.getText().trim())); |
| } else { |
| // we need to encode the message. We need to replace the carriage return |
| // character by the 2 character string \n. |
| // Because of this the \ character needs to be escaped as well. |
| // ReplaceAll() expects regexp so \ char are escaped twice. |
| String message = mSmsMessage.getText(); |
| message = message.replaceAll("\\\\", //$NON-NLS-1$ |
| "\\\\\\\\"); //$NON-NLS-1$ |
| |
| // While the normal line delimiter is returned by Text.getLineDelimiter() |
| // it seems copy pasting text coming from somewhere else could have another |
| // delimited. For this reason, we'll replace is several steps |
| |
| // replace the dual CR-LF |
| message = message.replaceAll("\r\n", "\\\\n"); //$NON-NLS-1$ //$NON-NLS-1$ |
| |
| // replace remaining stand alone \n |
| message = message.replaceAll("\n", "\\\\n"); //$NON-NLS-1$ //$NON-NLS-1$ |
| |
| // replace remaining stand alone \r |
| message = message.replaceAll("\r", "\\\\n"); //$NON-NLS-1$ //$NON-NLS-1$ |
| |
| processCommandResult(mEmulatorConsole.sendSms(mPhoneNumber.getText().trim(), |
| message)); |
| } |
| } |
| } |
| }); |
| |
| mCancelButton = new Button(g2ButtonComp, SWT.PUSH); |
| mCancelButton.setText("Hang Up"); |
| mCancelButton.setEnabled(false); |
| mCancelButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (mEmulatorConsole != null) { |
| if (mVoiceButton.getSelection()) { |
| processCommandResult(mEmulatorConsole.cancelCall( |
| mPhoneNumber.getText().trim())); |
| } |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Create Location controls. |
| * @param top |
| */ |
| private void createLocationControls(final Composite top) { |
| Label l = new Label(top, SWT.NONE); |
| l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| l.setText("Location Controls"); |
| |
| mLocationFolders = new TabFolder(top, SWT.NONE); |
| mLocationFolders.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| |
| Composite manualLocationComp = new Composite(mLocationFolders, SWT.NONE); |
| TabItem item = new TabItem(mLocationFolders, SWT.NONE); |
| item.setText("Manual"); |
| item.setControl(manualLocationComp); |
| |
| createManualLocationControl(manualLocationComp); |
| |
| mPlayImage = mImageLoader.loadImage("play.png", mParent.getDisplay()); // $NON-NLS-1$ |
| mPauseImage = mImageLoader.loadImage("pause.png", mParent.getDisplay()); // $NON-NLS-1$ |
| |
| Composite gpxLocationComp = new Composite(mLocationFolders, SWT.NONE); |
| item = new TabItem(mLocationFolders, SWT.NONE); |
| item.setText("GPX"); |
| item.setControl(gpxLocationComp); |
| |
| createGpxLocationControl(gpxLocationComp); |
| |
| Composite kmlLocationComp = new Composite(mLocationFolders, SWT.NONE); |
| kmlLocationComp.setLayout(new FillLayout()); |
| item = new TabItem(mLocationFolders, SWT.NONE); |
| item.setText("KML"); |
| item.setControl(kmlLocationComp); |
| |
| createKmlLocationControl(kmlLocationComp); |
| } |
| |
| private void createManualLocationControl(Composite manualLocationComp) { |
| final StackLayout sl; |
| GridLayout gl; |
| Label label; |
| |
| manualLocationComp.setLayout(new GridLayout(1, false)); |
| mDecimalButton = new Button(manualLocationComp, SWT.RADIO); |
| mDecimalButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| mDecimalButton.setText("Decimal"); |
| mSexagesimalButton = new Button(manualLocationComp, SWT.RADIO); |
| mSexagesimalButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| mSexagesimalButton.setText("Sexagesimal"); |
| |
| // composite to hold and switching between the 2 modes. |
| final Composite content = new Composite(manualLocationComp, SWT.NONE); |
| content.setLayout(sl = new StackLayout()); |
| |
| // decimal display |
| final Composite decimalContent = new Composite(content, SWT.NONE); |
| decimalContent.setLayout(gl = new GridLayout(2, false)); |
| gl.marginHeight = gl.marginWidth = 0; |
| |
| mLongitudeControls = new CoordinateControls(); |
| mLatitudeControls = new CoordinateControls(); |
| |
| label = new Label(decimalContent, SWT.NONE); |
| label.setText("Longitude"); |
| |
| mLongitudeControls.createDecimalText(decimalContent); |
| |
| label = new Label(decimalContent, SWT.NONE); |
| label.setText("Latitude"); |
| |
| mLatitudeControls.createDecimalText(decimalContent); |
| |
| // sexagesimal content |
| final Composite sexagesimalContent = new Composite(content, SWT.NONE); |
| sexagesimalContent.setLayout(gl = new GridLayout(7, false)); |
| gl.marginHeight = gl.marginWidth = 0; |
| |
| label = new Label(sexagesimalContent, SWT.NONE); |
| label.setText("Longitude"); |
| |
| mLongitudeControls.createSexagesimalDegreeText(sexagesimalContent); |
| |
| label = new Label(sexagesimalContent, SWT.NONE); |
| label.setText("\u00B0"); // degree character |
| |
| mLongitudeControls.createSexagesimalMinuteText(sexagesimalContent); |
| |
| label = new Label(sexagesimalContent, SWT.NONE); |
| label.setText("'"); |
| |
| mLongitudeControls.createSexagesimalSecondText(sexagesimalContent); |
| |
| label = new Label(sexagesimalContent, SWT.NONE); |
| label.setText("\""); |
| |
| label = new Label(sexagesimalContent, SWT.NONE); |
| label.setText("Latitude"); |
| |
| mLatitudeControls.createSexagesimalDegreeText(sexagesimalContent); |
| |
| label = new Label(sexagesimalContent, SWT.NONE); |
| label.setText("\u00B0"); |
| |
| mLatitudeControls.createSexagesimalMinuteText(sexagesimalContent); |
| |
| label = new Label(sexagesimalContent, SWT.NONE); |
| label.setText("'"); |
| |
| mLatitudeControls.createSexagesimalSecondText(sexagesimalContent); |
| |
| label = new Label(sexagesimalContent, SWT.NONE); |
| label.setText("\""); |
| |
| // set the default display to decimal |
| sl.topControl = decimalContent; |
| mDecimalButton.setSelection(true); |
| |
| mDecimalButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (mDecimalButton.getSelection()) { |
| sl.topControl = decimalContent; |
| } else { |
| sl.topControl = sexagesimalContent; |
| } |
| content.layout(); |
| } |
| }); |
| |
| Button sendButton = new Button(manualLocationComp, SWT.PUSH); |
| sendButton.setText("Send"); |
| sendButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (mEmulatorConsole != null) { |
| processCommandResult(mEmulatorConsole.sendLocation( |
| mLongitudeControls.getValue(), mLatitudeControls.getValue(), 0)); |
| } |
| } |
| }); |
| |
| mLongitudeControls.setValue(DEFAULT_LONGITUDE); |
| mLatitudeControls.setValue(DEFAULT_LATITUDE); |
| } |
| |
| private void createGpxLocationControl(Composite gpxLocationComp) { |
| GridData gd; |
| |
| IPreferenceStore store = DdmUiPreferences.getStore(); |
| |
| gpxLocationComp.setLayout(new GridLayout(1, false)); |
| |
| mGpxUploadButton = new Button(gpxLocationComp, SWT.PUSH); |
| mGpxUploadButton.setText("Load GPX..."); |
| |
| // Table for way point |
| mGpxWayPointTable = new Table(gpxLocationComp, |
| SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION); |
| mGpxWayPointTable.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); |
| gd.heightHint = 100; |
| mGpxWayPointTable.setHeaderVisible(true); |
| mGpxWayPointTable.setLinesVisible(true); |
| |
| TableHelper.createTableColumn(mGpxWayPointTable, "Name", SWT.LEFT, |
| "Some Name", |
| PREFS_WAYPOINT_COL_NAME, store); |
| TableHelper.createTableColumn(mGpxWayPointTable, "Longitude", SWT.LEFT, |
| "-199.999999", |
| PREFS_WAYPOINT_COL_LONGITUDE, store); |
| TableHelper.createTableColumn(mGpxWayPointTable, "Latitude", SWT.LEFT, |
| "-199.999999", |
| PREFS_WAYPOINT_COL_LATITUDE, store); |
| TableHelper.createTableColumn(mGpxWayPointTable, "Elevation", SWT.LEFT, |
| "99999.9", |
| PREFS_WAYPOINT_COL_ELEVATION, store); |
| TableHelper.createTableColumn(mGpxWayPointTable, "Description", SWT.LEFT, |
| "Some Description", |
| PREFS_WAYPOINT_COL_DESCRIPTION, store); |
| |
| final TableViewer gpxWayPointViewer = new TableViewer(mGpxWayPointTable); |
| gpxWayPointViewer.setContentProvider(new WayPointContentProvider()); |
| gpxWayPointViewer.setLabelProvider(new WayPointLabelProvider()); |
| |
| gpxWayPointViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| public void selectionChanged(SelectionChangedEvent event) { |
| ISelection selection = event.getSelection(); |
| if (selection instanceof IStructuredSelection) { |
| IStructuredSelection structuredSelection = (IStructuredSelection)selection; |
| Object selectedObject = structuredSelection.getFirstElement(); |
| if (selectedObject instanceof WayPoint) { |
| WayPoint wayPoint = (WayPoint)selectedObject; |
| |
| if (mEmulatorConsole != null && mPlayingTrack == false) { |
| processCommandResult(mEmulatorConsole.sendLocation( |
| wayPoint.getLongitude(), wayPoint.getLatitude(), |
| wayPoint.getElevation())); |
| } |
| } |
| } |
| } |
| }); |
| |
| // table for tracks. |
| mGpxTrackTable = new Table(gpxLocationComp, |
| SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION); |
| mGpxTrackTable.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); |
| gd.heightHint = 100; |
| mGpxTrackTable.setHeaderVisible(true); |
| mGpxTrackTable.setLinesVisible(true); |
| |
| TableHelper.createTableColumn(mGpxTrackTable, "Name", SWT.LEFT, |
| "Some very long name", |
| PREFS_TRACK_COL_NAME, store); |
| TableHelper.createTableColumn(mGpxTrackTable, "Point Count", SWT.RIGHT, |
| "9999", |
| PREFS_TRACK_COL_COUNT, store); |
| TableHelper.createTableColumn(mGpxTrackTable, "First Point Time", SWT.LEFT, |
| "999-99-99T99:99:99Z", |
| PREFS_TRACK_COL_FIRST, store); |
| TableHelper.createTableColumn(mGpxTrackTable, "Last Point Time", SWT.LEFT, |
| "999-99-99T99:99:99Z", |
| PREFS_TRACK_COL_LAST, store); |
| TableHelper.createTableColumn(mGpxTrackTable, "Comment", SWT.LEFT, |
| "-199.999999", |
| PREFS_TRACK_COL_COMMENT, store); |
| |
| final TableViewer gpxTrackViewer = new TableViewer(mGpxTrackTable); |
| gpxTrackViewer.setContentProvider(new TrackContentProvider()); |
| gpxTrackViewer.setLabelProvider(new TrackLabelProvider()); |
| |
| gpxTrackViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| public void selectionChanged(SelectionChangedEvent event) { |
| ISelection selection = event.getSelection(); |
| if (selection instanceof IStructuredSelection) { |
| IStructuredSelection structuredSelection = (IStructuredSelection)selection; |
| Object selectedObject = structuredSelection.getFirstElement(); |
| if (selectedObject instanceof Track) { |
| Track track = (Track)selectedObject; |
| |
| if (mEmulatorConsole != null && mPlayingTrack == false) { |
| TrackPoint[] points = track.getPoints(); |
| processCommandResult(mEmulatorConsole.sendLocation( |
| points[0].getLongitude(), points[0].getLatitude(), |
| points[0].getElevation())); |
| } |
| |
| mPlayGpxButton.setEnabled(true); |
| mGpxBackwardButton.setEnabled(true); |
| mGpxForwardButton.setEnabled(true); |
| mGpxSpeedButton.setEnabled(true); |
| |
| return; |
| } |
| } |
| |
| mPlayGpxButton.setEnabled(false); |
| mGpxBackwardButton.setEnabled(false); |
| mGpxForwardButton.setEnabled(false); |
| mGpxSpeedButton.setEnabled(false); |
| } |
| }); |
| |
| mGpxUploadButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| FileDialog fileDialog = new FileDialog(mParent.getShell(), SWT.OPEN); |
| |
| fileDialog.setText("Load GPX File"); |
| fileDialog.setFilterExtensions(new String[] { "*.gpx" } ); |
| |
| String fileName = fileDialog.open(); |
| if (fileName != null) { |
| GpxParser parser = new GpxParser(fileName); |
| if (parser.parse()) { |
| gpxWayPointViewer.setInput(parser.getWayPoints()); |
| gpxTrackViewer.setInput(parser.getTracks()); |
| } |
| } |
| } |
| }); |
| |
| mGpxPlayControls = new Composite(gpxLocationComp, SWT.NONE); |
| GridLayout gl; |
| mGpxPlayControls.setLayout(gl = new GridLayout(5, false)); |
| gl.marginHeight = gl.marginWidth = 0; |
| mGpxPlayControls.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| |
| mPlayGpxButton = new Button(mGpxPlayControls, SWT.PUSH | SWT.FLAT); |
| mPlayGpxButton.setImage(mPlayImage); |
| mPlayGpxButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (mPlayingTrack == false) { |
| ISelection selection = gpxTrackViewer.getSelection(); |
| if (selection.isEmpty() == false && selection instanceof IStructuredSelection) { |
| IStructuredSelection structuredSelection = (IStructuredSelection)selection; |
| Object selectedObject = structuredSelection.getFirstElement(); |
| if (selectedObject instanceof Track) { |
| Track track = (Track)selectedObject; |
| playTrack(track); |
| } |
| } |
| } else { |
| // if we're playing, then we pause |
| mPlayingTrack = false; |
| if (mPlayingThread != null) { |
| mPlayingThread.interrupt(); |
| } |
| } |
| } |
| }); |
| |
| Label separator = new Label(mGpxPlayControls, SWT.SEPARATOR | SWT.VERTICAL); |
| separator.setLayoutData(gd = new GridData( |
| GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); |
| gd.heightHint = 0; |
| |
| mGpxBackwardButton = new Button(mGpxPlayControls, SWT.TOGGLE | SWT.FLAT); |
| mGpxBackwardButton.setImage(mImageLoader.loadImage("backward.png", mParent.getDisplay())); // $NON-NLS-1$ |
| mGpxBackwardButton.setSelection(false); |
| mGpxBackwardButton.addSelectionListener(mDirectionButtonAdapter); |
| mGpxForwardButton = new Button(mGpxPlayControls, SWT.TOGGLE | SWT.FLAT); |
| mGpxForwardButton.setImage(mImageLoader.loadImage("forward.png", mParent.getDisplay())); // $NON-NLS-1$ |
| mGpxForwardButton.setSelection(true); |
| mGpxForwardButton.addSelectionListener(mDirectionButtonAdapter); |
| |
| mGpxSpeedButton = new Button(mGpxPlayControls, SWT.PUSH | SWT.FLAT); |
| |
| mSpeedIndex = 0; |
| mSpeed = PLAY_SPEEDS[mSpeedIndex]; |
| |
| mGpxSpeedButton.setText(String.format(SPEED_FORMAT, mSpeed)); |
| mGpxSpeedButton.addSelectionListener(mSpeedButtonAdapter); |
| |
| mPlayGpxButton.setEnabled(false); |
| mGpxBackwardButton.setEnabled(false); |
| mGpxForwardButton.setEnabled(false); |
| mGpxSpeedButton.setEnabled(false); |
| |
| } |
| |
| private void createKmlLocationControl(Composite kmlLocationComp) { |
| GridData gd; |
| |
| IPreferenceStore store = DdmUiPreferences.getStore(); |
| |
| kmlLocationComp.setLayout(new GridLayout(1, false)); |
| |
| mKmlUploadButton = new Button(kmlLocationComp, SWT.PUSH); |
| mKmlUploadButton.setText("Load KML..."); |
| |
| // Table for way point |
| mKmlWayPointTable = new Table(kmlLocationComp, |
| SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION); |
| mKmlWayPointTable.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); |
| gd.heightHint = 200; |
| mKmlWayPointTable.setHeaderVisible(true); |
| mKmlWayPointTable.setLinesVisible(true); |
| |
| TableHelper.createTableColumn(mKmlWayPointTable, "Name", SWT.LEFT, |
| "Some Name", |
| PREFS_WAYPOINT_COL_NAME, store); |
| TableHelper.createTableColumn(mKmlWayPointTable, "Longitude", SWT.LEFT, |
| "-199.999999", |
| PREFS_WAYPOINT_COL_LONGITUDE, store); |
| TableHelper.createTableColumn(mKmlWayPointTable, "Latitude", SWT.LEFT, |
| "-199.999999", |
| PREFS_WAYPOINT_COL_LATITUDE, store); |
| TableHelper.createTableColumn(mKmlWayPointTable, "Elevation", SWT.LEFT, |
| "99999.9", |
| PREFS_WAYPOINT_COL_ELEVATION, store); |
| TableHelper.createTableColumn(mKmlWayPointTable, "Description", SWT.LEFT, |
| "Some Description", |
| PREFS_WAYPOINT_COL_DESCRIPTION, store); |
| |
| final TableViewer kmlWayPointViewer = new TableViewer(mKmlWayPointTable); |
| kmlWayPointViewer.setContentProvider(new WayPointContentProvider()); |
| kmlWayPointViewer.setLabelProvider(new WayPointLabelProvider()); |
| |
| mKmlUploadButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| FileDialog fileDialog = new FileDialog(mParent.getShell(), SWT.OPEN); |
| |
| fileDialog.setText("Load KML File"); |
| fileDialog.setFilterExtensions(new String[] { "*.kml" } ); |
| |
| String fileName = fileDialog.open(); |
| if (fileName != null) { |
| KmlParser parser = new KmlParser(fileName); |
| if (parser.parse()) { |
| kmlWayPointViewer.setInput(parser.getWayPoints()); |
| |
| mPlayKmlButton.setEnabled(true); |
| mKmlBackwardButton.setEnabled(true); |
| mKmlForwardButton.setEnabled(true); |
| mKmlSpeedButton.setEnabled(true); |
| } |
| } |
| } |
| }); |
| |
| kmlWayPointViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| public void selectionChanged(SelectionChangedEvent event) { |
| ISelection selection = event.getSelection(); |
| if (selection instanceof IStructuredSelection) { |
| IStructuredSelection structuredSelection = (IStructuredSelection)selection; |
| Object selectedObject = structuredSelection.getFirstElement(); |
| if (selectedObject instanceof WayPoint) { |
| WayPoint wayPoint = (WayPoint)selectedObject; |
| |
| if (mEmulatorConsole != null && mPlayingTrack == false) { |
| processCommandResult(mEmulatorConsole.sendLocation( |
| wayPoint.getLongitude(), wayPoint.getLatitude(), |
| wayPoint.getElevation())); |
| } |
| } |
| } |
| } |
| }); |
| |
| |
| |
| mKmlPlayControls = new Composite(kmlLocationComp, SWT.NONE); |
| GridLayout gl; |
| mKmlPlayControls.setLayout(gl = new GridLayout(5, false)); |
| gl.marginHeight = gl.marginWidth = 0; |
| mKmlPlayControls.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| |
| mPlayKmlButton = new Button(mKmlPlayControls, SWT.PUSH | SWT.FLAT); |
| mPlayKmlButton.setImage(mPlayImage); |
| mPlayKmlButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (mPlayingTrack == false) { |
| Object input = kmlWayPointViewer.getInput(); |
| if (input instanceof WayPoint[]) { |
| playKml((WayPoint[])input); |
| } |
| } else { |
| // if we're playing, then we pause |
| mPlayingTrack = false; |
| if (mPlayingThread != null) { |
| mPlayingThread.interrupt(); |
| } |
| } |
| } |
| }); |
| |
| Label separator = new Label(mKmlPlayControls, SWT.SEPARATOR | SWT.VERTICAL); |
| separator.setLayoutData(gd = new GridData( |
| GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); |
| gd.heightHint = 0; |
| |
| mKmlBackwardButton = new Button(mKmlPlayControls, SWT.TOGGLE | SWT.FLAT); |
| mKmlBackwardButton.setImage(mImageLoader.loadImage("backward.png", mParent.getDisplay())); // $NON-NLS-1$ |
| mKmlBackwardButton.setSelection(false); |
| mKmlBackwardButton.addSelectionListener(mDirectionButtonAdapter); |
| mKmlForwardButton = new Button(mKmlPlayControls, SWT.TOGGLE | SWT.FLAT); |
| mKmlForwardButton.setImage(mImageLoader.loadImage("forward.png", mParent.getDisplay())); // $NON-NLS-1$ |
| mKmlForwardButton.setSelection(true); |
| mKmlForwardButton.addSelectionListener(mDirectionButtonAdapter); |
| |
| mKmlSpeedButton = new Button(mKmlPlayControls, SWT.PUSH | SWT.FLAT); |
| |
| mSpeedIndex = 0; |
| mSpeed = PLAY_SPEEDS[mSpeedIndex]; |
| |
| mKmlSpeedButton.setText(String.format(SPEED_FORMAT, mSpeed)); |
| mKmlSpeedButton.addSelectionListener(mSpeedButtonAdapter); |
| |
| mPlayKmlButton.setEnabled(false); |
| mKmlBackwardButton.setEnabled(false); |
| mKmlForwardButton.setEnabled(false); |
| mKmlSpeedButton.setEnabled(false); |
| } |
| |
| /** |
| * Sets the focus to the proper control inside the panel. |
| */ |
| @Override |
| public void setFocus() { |
| } |
| |
| @Override |
| protected void postCreation() { |
| // pass |
| } |
| |
| private synchronized void setDataMode(int selectionIndex) { |
| if (mEmulatorConsole != null) { |
| processCommandResult(mEmulatorConsole.setGsmDataMode( |
| GsmMode.getEnum(GSM_MODES[selectionIndex][1]))); |
| } |
| } |
| |
| private synchronized void setVoiceMode(int selectionIndex) { |
| if (mEmulatorConsole != null) { |
| processCommandResult(mEmulatorConsole.setGsmVoiceMode( |
| GsmMode.getEnum(GSM_MODES[selectionIndex][1]))); |
| } |
| } |
| |
| private synchronized void setNetworkLatency(int selectionIndex) { |
| if (mEmulatorConsole != null) { |
| processCommandResult(mEmulatorConsole.setNetworkLatency(selectionIndex)); |
| } |
| } |
| |
| private synchronized void setNetworkSpeed(int selectionIndex) { |
| if (mEmulatorConsole != null) { |
| processCommandResult(mEmulatorConsole.setNetworkSpeed(selectionIndex)); |
| } |
| } |
| |
| |
| /** |
| * Callback on device selection change. |
| * @param device the new selected device |
| */ |
| public void handleNewDevice(IDevice device) { |
| if (mParent.isDisposed()) { |
| return; |
| } |
| // unlink to previous console. |
| synchronized (this) { |
| mEmulatorConsole = null; |
| } |
| |
| try { |
| // get the emulator console for this device |
| // First we need the device itself |
| if (device != null) { |
| GsmStatus gsm = null; |
| NetworkStatus netstatus = null; |
| |
| synchronized (this) { |
| mEmulatorConsole = EmulatorConsole.getConsole(device); |
| if (mEmulatorConsole != null) { |
| // get the gsm status |
| gsm = mEmulatorConsole.getGsmStatus(); |
| netstatus = mEmulatorConsole.getNetworkStatus(); |
| |
| if (gsm == null || netstatus == null) { |
| mEmulatorConsole = null; |
| } |
| } |
| } |
| |
| if (gsm != null && netstatus != null) { |
| Display d = mParent.getDisplay(); |
| if (d.isDisposed() == false) { |
| final GsmStatus f_gsm = gsm; |
| final NetworkStatus f_netstatus = netstatus; |
| |
| d.asyncExec(new Runnable() { |
| public void run() { |
| if (f_gsm.voice != GsmMode.UNKNOWN) { |
| mVoiceMode.select(getGsmComboIndex(f_gsm.voice)); |
| } else { |
| mVoiceMode.clearSelection(); |
| } |
| if (f_gsm.data != GsmMode.UNKNOWN) { |
| mDataMode.select(getGsmComboIndex(f_gsm.data)); |
| } else { |
| mDataMode.clearSelection(); |
| } |
| |
| if (f_netstatus.speed != -1) { |
| mNetworkSpeed.select(f_netstatus.speed); |
| } else { |
| mNetworkSpeed.clearSelection(); |
| } |
| |
| if (f_netstatus.latency != -1) { |
| mNetworkLatency.select(f_netstatus.latency); |
| } else { |
| mNetworkLatency.clearSelection(); |
| } |
| } |
| }); |
| } |
| } |
| } |
| } finally { |
| // enable/disable the ui |
| boolean enable = false; |
| synchronized (this) { |
| enable = mEmulatorConsole != null; |
| } |
| |
| enable(enable); |
| } |
| } |
| |
| /** |
| * Enable or disable the ui. Can be called from non ui threads. |
| * @param enabled |
| */ |
| private void enable(final boolean enabled) { |
| try { |
| Display d = mParent.getDisplay(); |
| d.asyncExec(new Runnable() { |
| public void run() { |
| if (mParent.isDisposed() == false) { |
| doEnable(enabled); |
| } |
| } |
| }); |
| } catch (SWTException e) { |
| // disposed. do nothing |
| } |
| } |
| |
| private boolean isValidPhoneNumber() { |
| String number = mPhoneNumber.getText().trim(); |
| |
| return number.matches(RE_PHONE_NUMBER); |
| } |
| |
| /** |
| * Enable or disable the ui. Cannot be called from non ui threads. |
| * @param enabled |
| */ |
| protected void doEnable(boolean enabled) { |
| mVoiceLabel.setEnabled(enabled); |
| mVoiceMode.setEnabled(enabled); |
| |
| mDataLabel.setEnabled(enabled); |
| mDataMode.setEnabled(enabled); |
| |
| mSpeedLabel.setEnabled(enabled); |
| mNetworkSpeed.setEnabled(enabled); |
| |
| mLatencyLabel.setEnabled(enabled); |
| mNetworkLatency.setEnabled(enabled); |
| |
| // Calling setEnabled on a text field will trigger a modifyText event, so we don't do it |
| // if we don't need to. |
| if (mPhoneNumber.isEnabled() != enabled) { |
| mNumberLabel.setEnabled(enabled); |
| mPhoneNumber.setEnabled(enabled); |
| } |
| |
| boolean valid = isValidPhoneNumber(); |
| |
| mVoiceButton.setEnabled(enabled && valid); |
| mSmsButton.setEnabled(enabled && valid); |
| |
| boolean smsValid = enabled && valid && mSmsButton.getSelection(); |
| |
| // Calling setEnabled on a text field will trigger a modifyText event, so we don't do it |
| // if we don't need to. |
| if (mSmsMessage.isEnabled() != smsValid) { |
| mMessageLabel.setEnabled(smsValid); |
| mSmsMessage.setEnabled(smsValid); |
| } |
| if (enabled == false) { |
| mSmsMessage.setText(""); //$NON-NLs-1$ |
| } |
| |
| mCallButton.setEnabled(enabled && valid); |
| mCancelButton.setEnabled(enabled && valid && mVoiceButton.getSelection()); |
| |
| if (enabled == false) { |
| mVoiceMode.clearSelection(); |
| mDataMode.clearSelection(); |
| mNetworkSpeed.clearSelection(); |
| mNetworkLatency.clearSelection(); |
| if (mPhoneNumber.getText().length() > 0) { |
| mPhoneNumber.setText(""); //$NON-NLS-1$ |
| } |
| } |
| |
| // location controls |
| mLocationFolders.setEnabled(enabled); |
| |
| mDecimalButton.setEnabled(enabled); |
| mSexagesimalButton.setEnabled(enabled); |
| mLongitudeControls.setEnabled(enabled); |
| mLatitudeControls.setEnabled(enabled); |
| |
| mGpxUploadButton.setEnabled(enabled); |
| mGpxWayPointTable.setEnabled(enabled); |
| mGpxTrackTable.setEnabled(enabled); |
| mKmlUploadButton.setEnabled(enabled); |
| mKmlWayPointTable.setEnabled(enabled); |
| } |
| |
| /** |
| * Returns the index of the combo item matching a specific GsmMode. |
| * @param mode |
| */ |
| private int getGsmComboIndex(GsmMode mode) { |
| for (int i = 0 ; i < GSM_MODES.length; i++) { |
| String[] modes = GSM_MODES[i]; |
| if (mode.getTag().equals(modes[1])) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Processes the result of a command sent to the console. |
| * @param result the result of the command. |
| */ |
| private boolean processCommandResult(final String result) { |
| if (result != EmulatorConsole.RESULT_OK) { |
| try { |
| mParent.getDisplay().asyncExec(new Runnable() { |
| public void run() { |
| if (mParent.isDisposed() == false) { |
| MessageDialog.openError(mParent.getShell(), "Emulator Console", |
| result); |
| } |
| } |
| }); |
| } catch (SWTException e) { |
| // we're quitting, just ignore |
| } |
| |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** |
| * @param track |
| */ |
| private void playTrack(final Track track) { |
| // no need to synchronize this check, the worst that can happen, is we start the thread |
| // for nothing. |
| if (mEmulatorConsole != null) { |
| mPlayGpxButton.setImage(mPauseImage); |
| mPlayKmlButton.setImage(mPauseImage); |
| mPlayingTrack = true; |
| |
| mPlayingThread = new Thread() { |
| @Override |
| public void run() { |
| try { |
| TrackPoint[] trackPoints = track.getPoints(); |
| int count = trackPoints.length; |
| |
| // get the start index. |
| int start = 0; |
| if (mPlayDirection == -1) { |
| start = count - 1; |
| } |
| |
| for (int p = start; p >= 0 && p < count; p += mPlayDirection) { |
| if (mPlayingTrack == false) { |
| return; |
| } |
| |
| // get the current point and send its location to |
| // the emulator. |
| final TrackPoint trackPoint = trackPoints[p]; |
| |
| synchronized (EmulatorControlPanel.this) { |
| if (mEmulatorConsole == null || |
| processCommandResult(mEmulatorConsole.sendLocation( |
| trackPoint.getLongitude(), trackPoint.getLatitude(), |
| trackPoint.getElevation())) == false) { |
| return; |
| } |
| } |
| |
| // if this is not the final point, then get the next one and |
| // compute the delta time |
| int nextIndex = p + mPlayDirection; |
| if (nextIndex >=0 && nextIndex < count) { |
| TrackPoint nextPoint = trackPoints[nextIndex]; |
| |
| long delta = nextPoint.getTime() - trackPoint.getTime(); |
| if (delta < 0) { |
| delta = -delta; |
| } |
| |
| long startTime = System.currentTimeMillis(); |
| |
| try { |
| sleep(delta / mSpeed); |
| } catch (InterruptedException e) { |
| if (mPlayingTrack == false) { |
| return; |
| } |
| |
| // we got interrupted, lets make sure we can play |
| do { |
| long waited = System.currentTimeMillis() - startTime; |
| long needToWait = delta / mSpeed; |
| if (waited < needToWait) { |
| try { |
| sleep(needToWait - waited); |
| } catch (InterruptedException e1) { |
| // we'll just loop and wait again if needed. |
| // unless we're supposed to stop |
| if (mPlayingTrack == false) { |
| return; |
| } |
| } |
| } else { |
| break; |
| } |
| } while (true); |
| } |
| } |
| } |
| } finally { |
| mPlayingTrack = false; |
| try { |
| mParent.getDisplay().asyncExec(new Runnable() { |
| public void run() { |
| if (mPlayGpxButton.isDisposed() == false) { |
| mPlayGpxButton.setImage(mPlayImage); |
| mPlayKmlButton.setImage(mPlayImage); |
| } |
| } |
| }); |
| } catch (SWTException e) { |
| // we're quitting, just ignore |
| } |
| } |
| } |
| }; |
| |
| mPlayingThread.start(); |
| } |
| } |
| |
| private void playKml(final WayPoint[] trackPoints) { |
| // no need to synchronize this check, the worst that can happen, is we start the thread |
| // for nothing. |
| if (mEmulatorConsole != null) { |
| mPlayGpxButton.setImage(mPauseImage); |
| mPlayKmlButton.setImage(mPauseImage); |
| mPlayingTrack = true; |
| |
| mPlayingThread = new Thread() { |
| @Override |
| public void run() { |
| try { |
| int count = trackPoints.length; |
| |
| // get the start index. |
| int start = 0; |
| if (mPlayDirection == -1) { |
| start = count - 1; |
| } |
| |
| for (int p = start; p >= 0 && p < count; p += mPlayDirection) { |
| if (mPlayingTrack == false) { |
| return; |
| } |
| |
| // get the current point and send its location to |
| // the emulator. |
| WayPoint trackPoint = trackPoints[p]; |
| |
| synchronized (EmulatorControlPanel.this) { |
| if (mEmulatorConsole == null || |
| processCommandResult(mEmulatorConsole.sendLocation( |
| trackPoint.getLongitude(), trackPoint.getLatitude(), |
| trackPoint.getElevation())) == false) { |
| return; |
| } |
| } |
| |
| // if this is not the final point, then get the next one and |
| // compute the delta time |
| int nextIndex = p + mPlayDirection; |
| if (nextIndex >=0 && nextIndex < count) { |
| |
| long delta = 1000; // 1 second |
| if (delta < 0) { |
| delta = -delta; |
| } |
| |
| long startTime = System.currentTimeMillis(); |
| |
| try { |
| sleep(delta / mSpeed); |
| } catch (InterruptedException e) { |
| if (mPlayingTrack == false) { |
| return; |
| } |
| |
| // we got interrupted, lets make sure we can play |
| do { |
| long waited = System.currentTimeMillis() - startTime; |
| long needToWait = delta / mSpeed; |
| if (waited < needToWait) { |
| try { |
| sleep(needToWait - waited); |
| } catch (InterruptedException e1) { |
| // we'll just loop and wait again if needed. |
| // unless we're supposed to stop |
| if (mPlayingTrack == false) { |
| return; |
| } |
| } |
| } else { |
| break; |
| } |
| } while (true); |
| } |
| } |
| } |
| } finally { |
| mPlayingTrack = false; |
| try { |
| mParent.getDisplay().asyncExec(new Runnable() { |
| public void run() { |
| if (mPlayGpxButton.isDisposed() == false) { |
| mPlayGpxButton.setImage(mPlayImage); |
| mPlayKmlButton.setImage(mPlayImage); |
| } |
| } |
| }); |
| } catch (SWTException e) { |
| // we're quitting, just ignore |
| } |
| } |
| } |
| }; |
| |
| mPlayingThread.start(); |
| } |
| } |
| } |