package com.mobilesorcery.sdk.ui.launch;
import java.text.MessageFormat;
import java.util.HashMap;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IconAndMessageDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
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.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.PreferencesUtil;
import com.mobilesorcery.sdk.core.CoreMoSyncPlugin;
import com.mobilesorcery.sdk.core.IPackager;
import com.mobilesorcery.sdk.core.launch.IEmulatorLauncher;
import com.mobilesorcery.sdk.core.launch.MoReLauncher;
import com.mobilesorcery.sdk.ui.UpdateListener;
import com.mobilesorcery.sdk.ui.UpdateListener.IUpdatableControl;
public abstract class ConfigureNativeEmulatorDialog extends IconAndMessageDialog implements IUpdatableControl {
public static final int CONFIGURE_ID = 0xff01;
public static final int NATIVE_LAUNCHER_ID = CONFIGURE_ID + 1;
public static final int FALLBACK_ID = NATIVE_LAUNCHER_ID + 1;
private Button dontAskAgain;
private boolean isAutomaticSelection;
private boolean needsConfig;
private final HashMap<Integer, IEmulatorLauncher> idToLauncherMap = new HashMap<Integer, IEmulatorLauncher>();
private IEmulatorLauncher selectedLauncher;
public ConfigureNativeEmulatorDialog(Shell parentShell) {
super(parentShell);
}
/**
* Performs the configure action. (When the user presses the button with {@link #CONFIGURE_ID}.)
*/
protected abstract void configure();
/**
* Returns the packager (platform) that this dialog applies to -- also used to derive which
* the native launcher is.
* @return
*/
protected abstract IPackager getPackager();
/**
* <p>Clients must override this method to provide the user with a sensible message.</p>
* <p>Typically, three different messages should be provided: one for every possible
* combination of {@code isAutomaticSelection} and {@code needsConfig}, except for
* when both are {@code false}.</p>
* <p>However, there is no need to handle the exceptional case, since the code will
* never reach this point if so.</p>
*
* @param isAutomaticSelection Whether this is an 'automatic' launch or not; in general
* non-automatic launches should not provide any option to run other emulators.
* @param needsConfig Whether the native emulator is not properly configured.
* @return
*/
protected abstract String createMessageBody(boolean isAutomaticSelection, boolean needsConfig);
@Override
public Control createDialogArea(Composite parent) {
if (!isAutomaticSelection && !needsConfig) {
throw new IllegalStateException("Cannot both platform specific AND properly configured. (Then we don't need this dialog.)");
}
getShell().setText(MessageFormat.format("Configure {0} launcher", getNativeLauncher().getName()));
Composite contents = (Composite) super.createDialogArea(parent);
contents.setLayout(new GridLayout(2, false));
message = createMessageBody(isAutomaticSelection, needsConfig);
createMessageArea(contents);
if (isAutomaticSelection) {
Label spacer = new Label(contents, SWT.NONE);
dontAskAgain = new Button(contents, SWT.CHECK);
dontAskAgain.setText("Do not ask this again");
dontAskAgain.addListener(SWT.Selection, new UpdateListener(this));
dontAskAgain.setSelection(!needsConfig);
}
return contents;
}
@Override
public void createButtonsForButtonBar(Composite parent) {
if (needsConfig) {
createConfigureButton(parent, !isAutomaticSelection);
}
if (isAutomaticSelection && !needsConfig) {
createFallbackButtons(parent);
}
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
if (isAutomaticSelection && needsConfig) {
createFallbackButtons(parent);
}
if (!needsConfig) {
createLauncherButton(parent, getNativeLauncher(), NATIVE_LAUNCHER_ID, true);
}
}
/**
* Clients may override this to create the configure button, which should have id {@code CONFIGURE_ID}
* @param parent
*/
protected void createConfigureButton(Composite parent, boolean defaultButton) {
createButton(parent, CONFIGURE_ID, MessageFormat.format("Configure {0} launcher", getNativeLauncher().getName()), defaultButton);
}
protected IEmulatorLauncher getNativeLauncher() {
IPackager packager = getPackager();
for (String id : CoreMoSyncPlugin.getDefault().getEmulatorLauncherIds()) {
IEmulatorLauncher launcher = CoreMoSyncPlugin.getDefault().getEmulatorLauncher(id);
if (launcher.getLaunchType(packager) == IEmulatorLauncher.LAUNCH_TYPE_NATIVE) {
return launcher;
}
}
return null;
}
/**
* <p>Clients may override this to create several possible fallback options,
* by calling {@link #createLauncherButton(Composite, IEmulatorLauncher, int, boolean)}.</p>
* <p>The default implementation creates a button for the default emulator.</p>
* @param parent
*/
protected void createFallbackButtons(Composite parent) {
createLauncherButton(parent, CoreMoSyncPlugin.getDefault().getEmulatorLauncher(MoReLauncher.ID), FALLBACK_ID, isAutomaticSelection);
}
protected void createLauncherButton(Composite parent, IEmulatorLauncher launcher, int id, boolean defaultButton) {
createButton(parent, id, MessageFormat.format("Run in {0}", launcher.getName()), defaultButton);
idToLauncherMap.put(id, launcher);
}
@Override
public void buttonPressed(int buttonId) {
selectedLauncher = idToLauncherMap.get(buttonId);
if (selectedLauncher != null) {
buttonId = FALLBACK_ID;
}
setReturnCode(buttonId);
if (CONFIGURE_ID == buttonId) {
close();
CoreMoSyncPlugin.getDefault().setPreferredLauncher(getPackager().getId(), getNativeLauncher().getId());
configure();
} else if (FALLBACK_ID == buttonId) {
if (dontAskAgain.getSelection()) {
CoreMoSyncPlugin.getDefault().setPreferredLauncher(getPackager().getId(), selectedLauncher.getId());
}
close();
} else {
super.buttonPressed(buttonId);
}
}
/**
* Returns the selected launcher, or {@code null} if none was selected.
* @return
*/
public IEmulatorLauncher getSelectedLauncher() {
return selectedLauncher;
}
protected void setSelectedLauncher(IEmulatorLauncher selectedLauncher) {
this.selectedLauncher = selectedLauncher;
}
public void setIsAutomaticSelection(boolean isAutomaticSelection) {
this.isAutomaticSelection = isAutomaticSelection;
}
public void setNeedsConfig(boolean needsConfig) {
this.needsConfig = needsConfig;
}
@Override
protected Image getImage() {
return getQuestionImage();
}
@Override
public void updateUI() {
if (isAutomaticSelection) {
getButton(CONFIGURE_ID).setEnabled(!dontAskAgain.getSelection());
}
}
}