/* Copyright (C) 2009 Mobile Sorcery AB
This program is free software; you can redistribute it and/or modify it
under the terms of the Eclipse Public License v1.0.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for
more details.
You should have received a copy of the Eclipse Public License v1.0 along
with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html
*/
package com.mobilesorcery.sdk.ui.targetphone.internal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowPulldownDelegate;
import org.eclipse.ui.dialogs.ListDialog;
import com.mobilesorcery.sdk.core.MoSyncTool;
import com.mobilesorcery.sdk.core.Util;
import com.mobilesorcery.sdk.profiles.IProfile;
import com.mobilesorcery.sdk.ui.targetphone.ITargetPhone;
import com.mobilesorcery.sdk.ui.targetphone.ITargetPhoneTransport;
import com.mobilesorcery.sdk.ui.targetphone.TargetPhonePlugin;
public class SelectTargetPhoneAction implements
IWorkbenchWindowPulldownDelegate {
class ScanJob extends Job {
private final ITargetPhoneTransport transport;
public ScanJob(ITargetPhoneTransport transport) {
super("Scanning for devices");
this.transport = transport;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
ITargetPhone phone = transport.scan(window, monitor);
if (phone != null) {
TargetPhonePlugin.getDefault().addToHistory(phone);
monitor.setTaskName(MessageFormat.format(
"Assigning profile to {0}", phone.getName()));
SelectTargetPhoneAction.selectProfileForPhone(
TargetPhonePlugin.getDefault().getCurrentProfileManagerType(),
phone, window, false);
}
return Status.OK_STATUS;
} catch (CoreException e) {
return e.getStatus();
}
}
}
private ISelection selection;
protected IAction targetDialogAction;
IWorkbenchWindow window;
@Override
public Menu getMenu(Control parent) {
Menu menu = new Menu(parent);
List<ITargetPhone> phones = TargetPhonePlugin.getDefault()
.getSelectedTargetPhoneHistory();
for (Iterator<ITargetPhone> phoneIterator = phones.iterator(); phoneIterator
.hasNext();) {
ITargetPhone phone = phoneIterator.next();
MenuItem item = new MenuItem(menu, SWT.CHECK);
item.setText(computeTargetPhoneLabel(phone));
item.setSelection(phone == TargetPhonePlugin.getDefault()
.getCurrentlySelectedPhone());
item.setData(phone);
item.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}
@Override
public void widgetSelected(SelectionEvent event) {
ITargetPhone phone = (ITargetPhone) event.widget.getData();
TargetPhonePlugin.getDefault().setCurrentlySelectedPhone(
phone);
}
});
}
if (phones.size() == 0) {
MenuItem empty = new MenuItem(menu, SWT.PUSH);
empty.setText("<Empty>");
empty.setEnabled(false);
}
new MenuItem(menu, SWT.SEPARATOR);
Collection<ITargetPhoneTransport> transports = TargetPhonePlugin
.getDefault().getTargetPhoneTransports();
for (final ITargetPhoneTransport transport : transports) {
MenuItem select = new MenuItem(menu, SWT.PUSH);
select.setText(MessageFormat.format("Scan for {0} device", transport.getDescription("")));
Image icon = TargetPhonePlugin.getDefault().getIcon(transport);
if (icon != null) {
select.setImage(icon);
}
select.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
ScanJob job = new ScanJob(transport);
job.setUser(true);
job.schedule();
}
});
}
if (phones.size() > 0) {
new MenuItem(menu, SWT.SEPARATOR);
final MenuItem reassign = new MenuItem(menu, SWT.PUSH);
reassign.setText("Edit Device &List...");
reassign.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
openTargetPhoneListDialog(reassign.getDisplay());
}
});
}
return menu;
}
private static String computeTargetPhoneLabel(ITargetPhone phone) {
ArrayList<String> preferredProfiles = new ArrayList<String>();
IProfile preferredProfile = phone.getPreferredProfile(MoSyncTool.DEFAULT_PROFILE_TYPE);
if (preferredProfile != null) {
preferredProfiles.add(preferredProfile.getName());
}
IProfile preferredLegacyProfile = phone.getPreferredProfile(MoSyncTool.LEGACY_PROFILE_TYPE);
if (preferredLegacyProfile != null) {
preferredProfiles.add(preferredLegacyProfile.getName());
}
String preferredProfileStr = preferredProfiles.isEmpty() ? "" : " - ["
+ Util.join(preferredProfiles.toArray(), ",") + "]";
return phone.getName() + preferredProfileStr;
}
protected void openTargetPhoneListDialog(Display display) {
Shell shell = new Shell(display);
try {
EditDeviceListDialog dialog = new EditDeviceListDialog(shell);
dialog.open();
} finally {
shell.dispose();
}
}
@Override
public void dispose() {
}
@Override
public void init(IWorkbenchWindow window) {
this.window = window;
}
@Override
public void selectionChanged(IAction action, ISelection selection) {
this.targetDialogAction = action;
this.selection = selection;
}
/**
* A utility method for querying the user for which profile to assign
* to a specific device. If applicable, a device list dialog pops up (with the
* device fixed to the device passed in to this method)
* @param profileManagerType
* @param phone The target device, must not be <code>null</code>
* @param shellProvider
* @param askOnlyIfNotAssigned If <code>true</code>, will only ask the user
* if no profile is already assigned.
* @return
*/
public static IProfile selectProfileForPhone(int profileManagerType, final ITargetPhone phone,
final IShellProvider shellProvider, boolean askOnlyIfNotAssigned) {
if (!askOnlyIfNotAssigned || phone.getPreferredProfile(profileManagerType) == null) {
Display d = shellProvider == null ? Display.getDefault()
: shellProvider.getShell().getDisplay();
d.syncExec(new Runnable() {
@Override
public void run() {
Shell shell = shellProvider == null ? new Shell(Display
.getDefault()) : shellProvider.getShell();
EditDeviceListDialog dialog = new EditDeviceListDialog(
shell);
dialog.setFixedDevice(true);
dialog.setInitialTargetPhone(phone);
dialog.open();
}
});
}
return phone.getPreferredProfile(profileManagerType);
}
/**
* Lets the user select a target phone. If there is more than one
* <code>ITargetPhoneTransport</code> installed, a dialog is popped up which
* lets the user select type of transport.
* @param profileManagerType
*
* @return
*/
public static ITargetPhone selectPhone(ITargetPhone targetPhone, int profileManagerType, IShellProvider shellProvider,
IProgressMonitor monitor) throws CoreException {
ITargetPhoneTransport selectedTransport = targetPhone == null ? null : targetPhone.getTransport();
if (selectedTransport == null) {
selectedTransport = selectTransport(shellProvider);
if (selectedTransport != null) {
targetPhone = selectedTransport.scan(shellProvider, monitor);
}
}
if (targetPhone != null) {
TargetPhonePlugin.getDefault().addToHistory(targetPhone);
if (targetPhone.getPreferredProfile(profileManagerType) == null) {
monitor.setTaskName(MessageFormat.format(
"Assigning profile to {0}", targetPhone.getName()));
SelectTargetPhoneAction.selectProfileForPhone(profileManagerType, targetPhone,
shellProvider, true);
}
}
return targetPhone;
}
public static ITargetPhoneTransport selectTransport(
IShellProvider shellProvider) {
List<ITargetPhoneTransport> transports = TargetPhonePlugin.getDefault()
.getTargetPhoneTransports();
ITargetPhoneTransport selectedTransport = null;
if (transports.size() == 1) {
selectedTransport = transports.get(0);
} else {
selectedTransport = showTransportsDialog(shellProvider);
}
return selectedTransport;
}
private static ITargetPhoneTransport showTransportsDialog(
IShellProvider shellProvider) {
final Shell shell = shellProvider.getShell();
final ITargetPhoneTransport[] result = new ITargetPhoneTransport[1];
shell.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
ListDialog dialog = new ListDialog(shell);
dialog.setTitle("Select type of transport");
dialog.setMessage("Select how you want to scan for the device");
dialog.setContentProvider(new ArrayContentProvider());
dialog.setLabelProvider(new TargetPhoneTransportLabelProvider());
dialog.setInput(TargetPhonePlugin.getDefault()
.getTargetPhoneTransports().toArray());
if (dialog.open() == ListDialog.OK) {
Object[] dialogResult = dialog.getResult();
if (dialogResult.length > 0) {
result[0] = (ITargetPhoneTransport) dialogResult[0];
}
}
}
});
return result[0];
}
@Override
public void run(IAction action) {
ITargetPhoneTransport transport = selectTransport(window);
if (transport != null) {
ScanJob job = new ScanJob(transport);
job.setUser(true);
job.schedule();
}
}
}