/*******************************************************************************
* Copyright (c) 2000, 2012 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Benjamin Muskalla <bmuskalla@eclipsesource.com>
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.extractfunction;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
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.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.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.ui.text.CSourceViewerConfiguration;
import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.dialogs.TextFieldNavigationHandler;
import org.eclipse.cdt.internal.ui.editor.CSourceViewer;
import org.eclipse.cdt.internal.ui.refactoring.ChangeParametersControl;
import org.eclipse.cdt.internal.ui.refactoring.ChangeParametersControl.Mode;
import org.eclipse.cdt.internal.ui.refactoring.IParameterListChangeListener;
import org.eclipse.cdt.internal.ui.refactoring.NameInformation;
import org.eclipse.cdt.internal.ui.refactoring.StubTypeContext;
import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
import org.eclipse.cdt.internal.ui.util.RowLayouter;
public class ExtractFunctionInputPage extends UserInputWizardPage {
public static final String PAGE_NAME = "ExtractFunctionInputPage"; //$NON-NLS-1$
static final String DIALOG_SETTING_SECTION = "ExtractFunctionWizard"; //$NON-NLS-1$
private ExtractFunctionRefactoring refactoring;
private ExtractFunctionInformation info;
private Text textField;
private boolean firstTime;
private CSourceViewer signaturePreview;
private final Document signaturePreviewDocument;
private IDialogSettings settings;
private static final String DESCRIPTION = Messages.ExtractFunctionInputPage_description;
private static final String ACCESS_MODIFIER = "AccessModifier"; //$NON-NLS-1$
public ExtractFunctionInputPage() {
super(PAGE_NAME);
setImageDescriptor(CPluginImages.DESC_WIZBAN_REFACTOR_TU);
setDescription(DESCRIPTION);
firstTime = true;
signaturePreviewDocument = new Document();
}
@Override
public void createControl(Composite parent) {
refactoring = (ExtractFunctionRefactoring) getRefactoring();
info = ((ExtractFunctionRefactoring) getRefactoring()).getRefactoringInfo();
loadSettings();
Composite result = new Composite(parent, SWT.NONE);
setControl(result);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
result.setLayout(layout);
RowLayouter layouter = new RowLayouter(2);
GridData gd = null;
initializeDialogUnits(result);
Label label = new Label(result, SWT.NONE);
label.setText(getLabelText());
textField = createTextInputField(result, SWT.BORDER);
textField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
layouter.perform(label, textField, 1);
label = new Label(result, SWT.NONE);
label.setText(Messages.ExtractFunctionInputPage_access_modifier);
Composite group = new Composite(result, SWT.NONE);
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
layout = new GridLayout();
layout.numColumns = 4;
layout.marginWidth = 0;
group.setLayout(layout);
String[] labels = new String[] {
Messages.ExtractFunctionInputPage_public,
Messages.ExtractFunctionInputPage_protected,
Messages.ExtractFunctionInputPage_private
};
VisibilityEnum[] visibilityValues = new VisibilityEnum[] {
VisibilityEnum.v_public, VisibilityEnum.v_protected, VisibilityEnum.v_private
};
VisibilityEnum visibility = info.getVisibility();
for (int i = 0; i < labels.length; i++) {
Button radio = new Button(group, SWT.RADIO);
radio.setText(labels[i]);
radio.setData(visibilityValues[i]);
if (visibilityValues[i].equals(visibility))
radio.setSelection(true);
radio.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
final VisibilityEnum selectedModifier = (VisibilityEnum) event.widget.getData();
settings.put(ACCESS_MODIFIER, selectedModifier.toString());
setVisibility(selectedModifier);
}
});
}
layouter.perform(label, group, 1);
if (!info.getParameters().isEmpty()) {
Mode mode = info.getMandatoryReturnVariable() != null ?
Mode.EXTRACT_METHOD_FIXED_RETURN : Mode.EXTRACT_METHOD;
ChangeParametersControl paramControl = new ChangeParametersControl(result, SWT.NONE,
Messages.ExtractFunctionInputPage_parameters,
new IParameterListChangeListener() {
@Override
public void parameterChanged(NameInformation parameter) {
parameterModified();
}
@Override
public void parameterListChanged() {
parameterModified();
}
@Override
public void parameterAdded(NameInformation parameter) {
updatePreview(getText());
}
},
mode,
new StubTypeContext(refactoring.getTranslationUnit()));
gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
paramControl.setLayoutData(gd);
paramControl.setInput(info.getParameters());
}
int duplicates = refactoring.getNumberOfDuplicates();
Button checkBox = new Button(result, SWT.CHECK);
if (duplicates == 0) {
checkBox.setText(Messages.ExtractFunctionInputPage_duplicates_none);
} else if (duplicates == 1) {
checkBox.setText(Messages.ExtractFunctionInputPage_duplicates_single);
} else {
checkBox.setText(NLS.bind(
Messages.ExtractFunctionInputPage_duplicates_multi, Integer.valueOf(duplicates)));
}
checkBox.setSelection(info.isReplaceDuplicates());
checkBox.setEnabled(duplicates > 0);
checkBox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
info.setReplaceDuplicates(((Button) e.widget).getSelection());
}
});
layouter.perform(checkBox);
label = new Label(result, SWT.SEPARATOR | SWT.HORIZONTAL);
label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
layouter.perform(label);
createSignaturePreview(result, layouter);
Dialog.applyDialogFont(result);
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
ICHelpContextIds.EXTRACT_FUNCTION_WIZARD_PAGE);
}
private Text createTextInputField(Composite parent, int style) {
Text result = new Text(parent, style);
result.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
textModified(getText());
}
});
TextFieldNavigationHandler.install(result);
return result;
}
private String getText() {
if (textField == null)
return null;
return textField.getText();
}
private String getLabelText(){
return Messages.ExtractFunctionInputPage_label_text;
}
private void setVisibility(VisibilityEnum visibility) {
info.setVisibility(visibility);
updatePreview(getText());
}
private void createSignaturePreview(Composite composite, RowLayouter layouter) {
Label previewLabel = new Label(composite, SWT.NONE);
previewLabel.setText(Messages.ExtractFunctionInputPage_signature_preview);
layouter.perform(previewLabel);
IPreferenceStore store = CUIPlugin.getDefault().getCombinedPreferenceStore();
signaturePreview = new CSourceViewer(composite, null, null, false, SWT.READ_ONLY | SWT.V_SCROLL | SWT.WRAP /*| SWT.BORDER*/, store);
signaturePreview.configure(new CSourceViewerConfiguration(CUIPlugin.getDefault().getTextTools().getColorManager(), store, null, null));
signaturePreview.getTextWidget().setFont(JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT));
signaturePreview.adaptBackgroundColor(composite);
signaturePreview.setDocument(signaturePreviewDocument);
signaturePreview.setEditable(false);
// Layouting problems with wrapped text: see http://bugs.eclipse.org/bugs/show_bug.cgi?id=9866
Control signaturePreviewControl = signaturePreview.getControl();
PixelConverter pixelConverter = new PixelConverter(signaturePreviewControl);
GridData gdata = new GridData(GridData.FILL_BOTH);
gdata.widthHint = pixelConverter.convertWidthInCharsToPixels(50);
gdata.heightHint = pixelConverter.convertHeightInCharsToPixels(3);
signaturePreviewControl.setLayoutData(gdata);
layouter.perform(signaturePreviewControl);
}
private void updatePreview(String methodName) {
if (signaturePreview == null)
return;
if (methodName.isEmpty()) {
methodName = StubUtility.suggestMethodName("extracted", null, //$NON-NLS-1$
refactoring.getTranslationUnit());
}
int top = signaturePreview.getTextWidget().getTopPixel();
String signature = refactoring.getSignature(methodName);
signaturePreviewDocument.set(signature);
signaturePreview.getTextWidget().setTopPixel(top);
}
private void loadSettings() {
settings = getDialogSettings().getSection(DIALOG_SETTING_SECTION);
if (settings == null) {
settings = getDialogSettings().addNewSection(DIALOG_SETTING_SECTION);
settings.put(ACCESS_MODIFIER, VisibilityEnum.v_private.toString());
}
final String accessModifier = settings.get(ACCESS_MODIFIER);
if (accessModifier != null) {
info.setVisibility(VisibilityEnum.getEnumForStringRepresentation(accessModifier));
}
}
//---- Input validation ------------------------------------------------------
@Override
public void setVisible(boolean visible) {
if (visible) {
if (firstTime) {
firstTime = false;
setPageComplete(false);
updatePreview(getText());
textField.setFocus();
} else {
setPageComplete(validatePage(true));
}
}
super.setVisible(visible);
}
private void textModified(String methodName) {
info.setMethodName(methodName);
RefactoringStatus status = validatePage(true);
if (!status.hasFatalError()) {
updatePreview(methodName);
} else {
signaturePreviewDocument.set(""); //$NON-NLS-1$
}
setPageComplete(status);
}
private void parameterModified() {
updatePreview(getText());
setPageComplete(validatePage(false));
}
private RefactoringStatus validatePage(boolean text) {
RefactoringStatus result = new RefactoringStatus();
if (text) {
result.merge(validateMethodName());
result.merge(validateParameters());
} else {
result.merge(validateParameters());
result.merge(validateMethodName());
}
return result;
}
private RefactoringStatus validateMethodName() {
RefactoringStatus result = new RefactoringStatus();
String methodName = getText();
if (methodName.isEmpty()) {
result.addFatalError(Messages.ExtractFunctionInputPage_validation_empty_function_name);
return result;
}
result.merge(refactoring.checkMethodName());
return result;
}
private RefactoringStatus validateParameters() {
RefactoringStatus result = new RefactoringStatus();
for (NameInformation paramInfo : info.getParameters()) {
if (paramInfo.getNewName().isEmpty()) {
result.addFatalError(Messages.ExtractFunctionInputPage_validation_empty_parameter_name);
return result;
}
}
result.merge(refactoring.checkParameterNames());
return result;
}
}