/***** BEGIN LICENSE BLOCK *****
* Version: CPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Common Public
* License Version 1.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.eclipse.org/legal/cpl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2006 Mirko Stocker <me@misto.ch>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the CPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the CPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.rubypeople.rdt.refactoring.ui.pages;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.rubypeople.rdt.internal.refactoring.RefactoringMessages;
import org.rubypeople.rdt.refactoring.core.IRefactoringContext;
import org.rubypeople.rdt.refactoring.core.extractmethod.ExtractedMethodHelper;
import org.rubypeople.rdt.refactoring.core.extractmethod.MethodExtractor;
import org.rubypeople.rdt.refactoring.nodewrapper.VisibilityNodeWrapper;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.ButtonStateListener;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.ExtractMethodComposite;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.IValidationController;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.MethodArgumentTableItem;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.MethodNameListener;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.ParameterTextChanged;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.ParametersButtonDownListener;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.ParametersButtonUpListener;
import org.rubypeople.rdt.refactoring.ui.pages.extractmethod.SignatureObserver;
import org.rubypeople.rdt.refactoring.util.NodeUtil;
public class ExtractMethodPage extends RefactoringWizardPage implements IValidationController {
private static final String title = Messages.ExtractMethodPage_Title;
private MethodExtractor methodExtractor;
private ExtractMethodComposite extractComposite;
private final IRefactoringContext selectionInformation;
private ExtractedMethodHelper extractedMethod;
public ExtractMethodPage(MethodExtractor methodExtractor, IRefactoringContext selectionInformation) {
super(title);
this.methodExtractor = methodExtractor;
extractedMethod = methodExtractor.getExtractedMethod();
this.selectionInformation = selectionInformation;
}
private class ItemNameObserver implements Observer {
public void update(Observable o, Object arg) {
ParameterTextChanged change = (ParameterTextChanged) arg;
extractedMethod.changeParameter(change.getOriginalPosition(), change.getTo());
}
}
private class ItemOrderObserver implements Observer {
public void update(Observable o, Object arg) {
ParameterTextChanged change = (ParameterTextChanged) arg;
extractedMethod.changeParameter(change.getOriginalPosition(), change.getNewPosition());
}
}
public void createControl(Composite parent) {
extractComposite = new ExtractMethodComposite(parent, this, extractedMethod.hasArguments(), extractedMethod
.getVisibility() != VisibilityNodeWrapper.METHOD_VISIBILITY.NONE);
extractedMethod.addObserver(
new SignatureObserver(extractComposite.getMethodSignaturePreviewLabel(), extractedMethod));
if (extractedMethod.hasArguments()) {
setupArgumentsTable(extractComposite.getParametersTable(), extractComposite.getUpParametersButton(), extractComposite
.getDownParametersButton(), extractComposite.getEditParametersButton());
}
setControl(extractComposite);
addNewMethodNameListener();
if (extractedMethod.getVisibility() != VisibilityNodeWrapper.METHOD_VISIBILITY.NONE) {
setupVisibilityHandlers();
}
if (extractComposite.getCellEditorListener() != null) {
extractComposite.getCellEditorListener().addObserver(new ItemNameObserver());
}
setupSelectionPreview();
// Checkbox for replacing all occurrences of exact same code with method call
final Button replaceAllInstance = new Button(extractComposite, SWT.CHECK);
GridData checkData = new GridData();
replaceAllInstance.setLayoutData(checkData);
replaceAllInstance.setText(RefactoringMessages.ExtractConstantInputPage_replace_all_occurrences);
replaceAllInstance.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
methodExtractor.setReplaceAllInstances(replaceAllInstance.getSelection());
}
});
}
private void setupSelectionPreview() {
extractComposite.getCodeViewer().setPreviewText(selectionInformation.getSource());
int nodeStart = NodeUtil.subPositionUnion(extractedMethod.getSelectedNodes()).getStartOffset();
int nodeLength = NodeUtil.subPositionUnion(extractedMethod.getSelectedNodes()).getEndOffset() - nodeStart;
extractComposite.getCodeViewer().setBackgroundColor(nodeStart, nodeLength, SWT.COLOR_GRAY);
int selectionStart = selectionInformation.getStartOffset();
int selectionLength = selectionInformation.getEndOffset() - selectionStart + 1;
extractComposite.getCodeViewer().setBackgroundColor(selectionStart, selectionLength, SWT.COLOR_DARK_GRAY);
scrollToSelection();
}
private void setupVisibilityHandlers() {
if (ExtractedMethodHelper.DEFAULT_VISIBILITY.equals(VisibilityNodeWrapper.METHOD_VISIBILITY.PRIVATE)) {
extractComposite.getPrivateAccessRadioButton().setSelection(true);
} else if (ExtractedMethodHelper.DEFAULT_VISIBILITY.equals(VisibilityNodeWrapper.METHOD_VISIBILITY.PROTECTED)) {
extractComposite.getProtectedAccessRadioButton().setSelection(true);
} else if (ExtractedMethodHelper.DEFAULT_VISIBILITY.equals(VisibilityNodeWrapper.METHOD_VISIBILITY.PUBLIC)) {
extractComposite.getPublicAccessRadioButton().setSelection(true);
}
extractComposite.getPrivateAccessRadioButton().addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
extractedMethod.setVisibility(VisibilityNodeWrapper.METHOD_VISIBILITY.PRIVATE);
}
});
extractComposite.getPublicAccessRadioButton().addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
extractedMethod.setVisibility(VisibilityNodeWrapper.METHOD_VISIBILITY.PUBLIC);
}
});
extractComposite.getProtectedAccessRadioButton().addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
extractedMethod.setVisibility(VisibilityNodeWrapper.METHOD_VISIBILITY.PROTECTED);
}
});
extractComposite.getNoneAccessRadioButton().addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
extractedMethod.setVisibility(VisibilityNodeWrapper.METHOD_VISIBILITY.NONE);
}
});
}
private void setupArgumentsTable(final Table table, Button upButton, Button downButton, Button editButton) {
insertParameterItems(table);
ParametersButtonUpListener upListener = new ParametersButtonUpListener(extractComposite.getParametersTable());
ParametersButtonDownListener downListener = new ParametersButtonDownListener(extractComposite.getParametersTable());
extractComposite.getUpParametersButton().addListener(SWT.Selection, upListener);
extractComposite.getDownParametersButton().addListener(SWT.Selection, downListener);
ButtonStateListener listener = new ButtonStateListener(table, upButton, downButton, editButton);
upListener.addObserver(listener);
downListener.addObserver(listener);
upListener.addObserver(new ItemOrderObserver());
downListener.addObserver(new ItemOrderObserver());
table.addListener(SWT.Selection, listener);
}
private void insertParameterItems(final Table table) {
String[] names = extractedMethod.getArguments().toArray(new String[extractedMethod.getArguments().size()]);
for (int i = 0; i < names.length; i++) {
new MethodArgumentTableItem(table, names[i], true, i, i);
}
}
private void addNewMethodNameListener() {
MethodNameListener methodNameListener = new MethodNameListener(methodExtractor, this);
extractComposite.getNewMethodNameText().getText().addModifyListener(methodNameListener);
setComplete(methodNameListener, false);
}
private HashMap<Object, Boolean> completedValidators = new HashMap<Object, Boolean>();
public void setError(String message) {
setMessage(message, IMessageProvider.ERROR);
}
public void setComplete(Object source, boolean complete) {
completedValidators.put(source, Boolean.valueOf(complete));
boolean allOk = true;
for (boolean ok : completedValidators.values()) {
if (!ok) {
allOk = false;
}
}
setPageComplete(allOk);
}
public void scrollToSelection() {
extractComposite.getCodeViewer().getTextWidget().setSelection(selectionInformation.getStartOffset());
extractComposite.getCodeViewer().getTextWidget().setSelection(selectionInformation.getEndOffset());
extractComposite.getCodeViewer().getTextWidget().showSelection();
}
public ArrayList<String> getInvalidNames() {
return extractedMethod.getLocalOnlyVariables();
}
}