/*******************************************************************************
* Copyright (c) 2017 Rogue Wave Software Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Rogue Wave Software Inc. - initial implementation
*******************************************************************************/
package org.eclipse.php.profile.ui.launcher;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.php.debug.ui.IDebugServerConnectionTest;
import org.eclipse.php.internal.core.Logger;
import org.eclipse.php.internal.debug.core.preferences.PHPDebugCorePreferenceNames;
import org.eclipse.php.internal.debug.core.preferences.PHPDebuggersRegistry;
import org.eclipse.php.internal.debug.ui.launching.AbstractPHPLaunchConfigurationTab;
import org.eclipse.php.profile.ui.ProfilerUIImages;
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.Font;
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.Label;
/**
* Abstract implementation of "Profiler" launch configuration tab. It handles
* switching between dedicated settings sections and updates the corresponding
* profiler type related data if it has been changed.
*
* @author Bartlomiej Laczkowski
*/
public abstract class AbstractPHPLaunchConfigurationProfilerTab
extends AbstractPHPLaunchConfigurationTab {
/**
* Widget listener that should be added to all controls that affects the
* state of corresponding launch configuration.
*/
public final class WidgetListener extends SelectionAdapter
implements ModifyListener {
public void modifyText(ModifyEvent e) {
setDirty(true);
updateLaunchConfigurationDialog();
}
public void widgetSelected(SelectionEvent e) {
setDirty(true);
updateLaunchConfigurationDialog();
}
}
/**
* Status message that provides information about validation result in given
* settings section.
*/
public final static class StatusMessage implements IMessageProvider {
private int type;
private String message;
public StatusMessage(int type, String message) {
this.type = type;
this.message = message;
}
@Override
public String getMessage() {
return message;
}
@Override
public int getMessageType() {
return type;
}
}
private final class NoneProfilerSection
extends ProfilerLaunchSettingsSectionAdapter {
@Override
public StatusMessage isValid(ILaunchConfiguration configuration) {
return new StatusMessage(IMessageProvider.ERROR,
getNoProfilerMessage());
}
}
private final class UnsupportedProfilerSection
extends ProfilerLaunchSettingsSectionAdapter {
@Override
public void createSection(Composite parent,
WidgetListener widgetListener) {
Label info = new Label(parent, SWT.NONE);
info.setText(
Messages.AbstractPHPLaunchConfigurationProfilerTab_Unsupported_profiler_type);
}
@Override
public StatusMessage isValid(ILaunchConfiguration configuration) {
return new StatusMessage(IMessageProvider.ERROR,
Messages.AbstractPHPLaunchConfigurationProfilerTab_Unsupported_profiler_type);
}
}
protected Button validateProfilerBtn;
protected IDebugServerConnectionTest[] profileTesters;
private Label profilerName;
private Button configureProfiler;
private Composite mainComposite;
private Composite settingsComposite;
private Map<String, IProfilerLaunchSettingsSection> currentSection = new HashMap<String, IProfilerLaunchSettingsSection>();
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
*/
public String getName() {
return Messages.AbstractPHPLaunchConfigurationProfilerTab_Profiler_group_name;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getImage()
*/
@Override
public Image getImage() {
return ProfilerUIImages.get(ProfilerUIImages.IMG_OBJ_PROFILE_CONF);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse
* .swt.widgets.Composite)
*/
public void createControl(Composite parent) {
// Create main composite
mainComposite = new Composite(parent, SWT.NONE);
GridLayout mainLayout = new GridLayout();
mainLayout.marginHeight = 0;
mainLayout.marginWidth = 0;
mainComposite.setLayout(mainLayout);
createProfilerSelectionControl(mainComposite);
// Create composite for debugger dedicated settings
settingsComposite = new Composite(mainComposite, SWT.NONE);
Dialog.applyDialogFont(mainComposite);
setControl(mainComposite);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.php.internal.debug.ui.launching.
* AbstractPHPLaunchConfigurationTab#setDefaults(org.eclipse.debug.core.
* ILaunchConfigurationWorkingCopy)
*/
@Override
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
super.setDefaults(configuration);
getSection().setDefaults(configuration);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.
* debug.core.ILaunchConfigurationWorkingCopy)
*/
@Override
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
configuration.setAttribute(PHPDebugCorePreferenceNames.PHP_DEBUGGER_ID,
getCurrentProfilerId());
getSection().performApply(configuration);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.debug.ui.AbstractLaunchConfigurationTab#isValid(org.eclipse.
* debug.core.ILaunchConfiguration)
*/
@Override
public boolean isValid(ILaunchConfiguration launchConfig) {
setMessage(null);
setWarningMessage(null);
setErrorMessage(null);
StatusMessage status = getSection().isValid(launchConfig);
switch (status.getMessageType()) {
case IMessageProvider.ERROR: {
setErrorMessage(status.getMessage());
return false;
}
case IMessageProvider.WARNING: {
setWarningMessage(status.getMessage());
return true;
}
default:
return true;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.php.internal.debug.ui.launching.
* AbstractPHPLaunchConfigurationTab#initialize(org.eclipse.debug.core.
* ILaunchConfiguration)
*/
@Override
protected void initialize(ILaunchConfiguration configuration) {
getSection().initialize(configuration);
}
/**
* Implementors should provide an action that handles triggering of
* "Configure..." profiler settings button.
*/
protected abstract void handleConfigureProfiler();
/**
* Implementors should provide the current profiler (debugger) ID that
* corresponds to debugger settings owner in related launch configuration.
*
* @return current profiler (debugger) ID
*/
protected abstract String getCurrentProfilerId();
/**
* Implementors should provide the appropriate message in case when there is
* no profiler attached to potential profiler/debugger settings owner.
*
* @return "No" profiler attached message.
*/
protected abstract String getNoProfilerMessage();
/**
* Implementors should update state of a "Test" button.
*/
protected abstract void updateProfileTest();
/**
* Implementors should provide an action that handles triggering of "Test"
* debugger connection button.
*/
protected abstract void performProfileTest();
private void createProfilerSelectionControl(Composite parent) {
Composite mainComposite = new Composite(parent, SWT.NONE);
GridLayout mcLayout = new GridLayout(1, false);
mcLayout.marginHeight = 0;
mcLayout.marginWidth = 0;
mainComposite.setLayout(mcLayout);
mainComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Composite profilerChoiceComposite = new Composite(mainComposite,
SWT.NONE);
GridLayout layout = new GridLayout(5, false);
profilerChoiceComposite.setLayout(layout);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
profilerChoiceComposite.setLayoutData(data);
Font font = parent.getFont();
profilerChoiceComposite.setFont(font);
Label label = new Label(profilerChoiceComposite, SWT.WRAP);
data = new GridData(SWT.BEGINNING);
label.setLayoutData(data);
label.setFont(font);
label.setText(
Messages.AbstractPHPLaunchConfigurationProfilerTab_Profiler_label);
profilerName = new Label(profilerChoiceComposite, SWT.NONE);
Label separator = new Label(profilerChoiceComposite, SWT.NONE);
data = new GridData(SWT.BEGINNING);
data.widthHint = 20;
separator.setLayoutData(data);
configureProfiler = createPushButton(profilerChoiceComposite,
Messages.AbstractPHPLaunchConfigurationProfilerTab_Configure,
null);
configureProfiler.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleConfigureProfiler();
}
});
configureProfiler.addSelectionListener(new WidgetListener());
validateProfilerBtn = createPushButton(profilerChoiceComposite,
Messages.AbstractPHPLaunchConfigurationProfilerTab_Test, null);
validateProfilerBtn.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
performProfileTest();
}
});
Label lineSeparator = new Label(mainComposite,
SWT.SEPARATOR | SWT.HORIZONTAL);
lineSeparator
.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
}
private IProfilerLaunchSettingsSection getSection() {
try {
String launchTypeId = getConfiguration().getType().getIdentifier();
String profilerId = getCurrentProfilerId();
IProfilerLaunchSettingsSection section = currentSection
.get(profilerId);
if (section == null) {
// Debugger type has been changed, rebuild section
if (PHPDebuggersRegistry.NONE_DEBUGGER_ID.equals(profilerId)) {
section = new NoneProfilerSection();
} else {
section = ProfilerLaunchSettingsSectionRegistry
.getSection(profilerId, launchTypeId);
if (section == null) {
section = new UnsupportedProfilerSection();
}
}
if (settingsComposite != null) {
buildSection(profilerId, section);
}
}
return section;
} catch (CoreException e) {
Logger.logException(e);
}
// Should never return null
return null;
}
private void buildSection(String debuggerId,
IProfilerLaunchSettingsSection section) {
// Update debugger type data first
updateProfiler(debuggerId);
// Store as singular key map (most recent section by debugger ID)
currentSection.clear();
currentSection.put(debuggerId, section);
settingsComposite.dispose();
settingsComposite = new Composite(mainComposite, SWT.NONE);
settingsComposite.setLayout(new GridLayout());
GridData dscData = new GridData(SWT.FILL, SWT.FILL, true, true);
settingsComposite.setLayoutData(dscData);
section.createSection(settingsComposite, new WidgetListener());
// Rebuild main composite
mainComposite.layout();
section.initialize(getConfiguration());
}
private void updateProfiler(String profilerId) {
profilerName.setText(PHPDebuggersRegistry.getDebuggerName(profilerId));
try {
// Update debugger type in original configuration
if (getOriginalConfiguration().contentsEqual(getConfiguration())) {
// Only debugger might have been changed, update original
// configuration
ILaunchConfigurationWorkingCopy wc = getOriginalConfiguration()
.getWorkingCopy();
wc.setAttribute(PHPDebugCorePreferenceNames.PHP_DEBUGGER_ID,
profilerId);
wc.doSave();
}
// Update in working copy
if (getConfiguration() instanceof ILaunchConfigurationWorkingCopy) {
((ILaunchConfigurationWorkingCopy) getConfiguration())
.setAttribute(
PHPDebugCorePreferenceNames.PHP_DEBUGGER_ID,
profilerId);
}
} catch (CoreException e) {
Logger.logException(e);
}
updateProfileTest();
}
}