/*******************************************************************************
* Copyright (c) 2005, 2015 Zend Technologies 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:
* Zend Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.php.refactoring.ui.actions;
import java.io.IOException;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dltk.core.*;
import org.eclipse.dltk.internal.core.ProjectFragment;
import org.eclipse.dltk.internal.core.SourceField;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.php.core.PHPToolkitUtil;
import org.eclipse.php.core.ast.nodes.ASTNode;
import org.eclipse.php.core.ast.nodes.Program;
import org.eclipse.php.internal.core.corext.dom.NodeFinder;
import org.eclipse.php.internal.ui.actions.IPHPActionDelegator;
import org.eclipse.php.internal.ui.editor.PHPStructuredEditor;
import org.eclipse.php.refactoring.core.utils.ASTUtils;
import org.eclipse.php.refactoring.core.utils.RefactoringUtility;
import org.eclipse.php.refactoring.ui.RefactoringUIPlugin;
import org.eclipse.php.refactoring.ui.prefereces.PreferenceConstants;
import org.eclipse.php.refactoring.ui.rename.RefactoringExecutionStarter;
import org.eclipse.php.refactoring.ui.rename.RenameLinkedMode;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.RenameResourceAction;
public class RenamePHPElementActionDelegate implements IPHPActionDelegator {
private static final String DIALOG_TITLE = Messages.RenamePHPElementActionDelegate_0;
private IWorkbenchWindow fWindow;
private ISelection selection;
public void run(IAction action) {
// The action is run from a editor.
if (selection instanceof ITextSelection) {
execute((ITextSelection) selection);
}
// The action is run from a view.
else if (selection instanceof IStructuredSelection) {
execute(((IStructuredSelection) selection));
}
}
private void execute(ITextSelection selection) {
setWindowIfEmpty();
IEditorPart fEditor = fWindow.getActivePage().getActiveEditor();
if (fEditor != null && fEditor instanceof PHPStructuredEditor) {
IModelElement source = ((PHPStructuredEditor) fEditor).getModelElement();
if (!(source instanceof ISourceModule)) {
MessageDialog.openError(fWindow.getShell(), DIALOG_TITLE, Messages.RenamePHPElementActionDelegate_1);
return;
}
Program program = null;
try {
program = ASTUtils.createProgramFromSource((ISourceModule) source);
} catch (Exception e) {
MessageDialog.openError(fWindow.getShell(), DIALOG_TITLE,
"Unexpected error happenned:" + e.getMessage()); //$NON-NLS-1$
}
if (program == null) {
MessageDialog.openInformation(fWindow.getShell(), DIALOG_TITLE,
Messages.RenamePHPElementActionDelegate_2);
return;
}
IPreferenceStore store = RefactoringUIPlugin.getDefault().getPreferenceStore();
boolean isInline = store.getBoolean(PreferenceConstants.REFACTOR_LIGHTWEIGHT);
ISourceViewer viewer = ((PHPStructuredEditor) fEditor).getTextViewer();
// this is work around for the case
// that the offset from editor is not accurate
// use the offset from source viewer instead.
Point originalSelection = viewer.getSelectedRange();
if (originalSelection != null) {
run(source.getResource(), program, originalSelection.x, originalSelection.y, fEditor, isInline);
} else {
run(source.getResource(), program, selection.getOffset(), selection.getLength(), fEditor, isInline);
}
}
}
private void setWindowIfEmpty() {
if (fWindow == null) {
fWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
}
}
private void run(IResource resource, Program program, int offset, int length, IEditorPart fEditor,
boolean isInline) {
ASTNode selectedNode = getSelectedNode(program, offset, length);
Shell activeShell = null;
if (fWindow != null) {
activeShell = fWindow.getShell();
} else {
activeShell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
}
if (selectedNode != null) {
if (isInline) {
new RenameLinkedMode(null, (PHPStructuredEditor) fEditor).start();
} else
try {
RefactoringExecutionStarter.startRenameRefactoring(resource, selectedNode, activeShell);
} catch (CoreException e) {
MessageDialog.openInformation(fWindow.getShell(), DIALOG_TITLE,
Messages.RenamePHPElementActionDelegate_2);
}
} else {
MessageDialog.openInformation(fWindow.getShell(), DIALOG_TITLE, Messages.RenamePHPElementActionDelegate_2);
}
}
protected ASTNode getSelectedNode(Program program, int offset, int length) {
ASTNode selectedNode = NodeFinder.perform(program, offset, length);
if (selectedNode != null && selectedNode.getType() == ASTNode.IN_LINE_HTML) {
selectedNode = selectedNode.getProgramRoot();
}
return selectedNode;
}
private void execute(IStructuredSelection selection) {
Object object = selection.getFirstElement();
setWindowIfEmpty();
if (object instanceof IResource) {
object = DLTKCore.create((IResource) object);
}
if (isScriptContainer(object)) {
IModelElement element = (IModelElement) object;
try {
RefactoringExecutionStarter.startRenameRefactoring(element.getResource(), null, fWindow.getShell());
} catch (CoreException e) {
MessageDialog.openInformation(fWindow.getShell(), DIALOG_TITLE,
Messages.RenamePHPElementActionDelegate_2);
}
return;
} else if (isSourceReference(object) && isModelElement(object)
&& PHPToolkitUtil.isFromPHPProject((IModelElement) object)) {
IModelElement element = (IModelElement) object;
IModelElement type = element.getPrimaryElement();
ISourceModule source = RefactoringUtility.getSourceModule(type);
if (source == null) {
MessageDialog.openInformation(fWindow.getShell(), DIALOG_TITLE,
Messages.RenamePHPElementActionDelegate_2);
return;
}
Program program = null;
try {
program = ASTUtils.createProgramFromSource(source);
} catch (ModelException e) {
} catch (IOException e) {
} catch (Exception e) {
}
if (program == null) {
MessageDialog.openInformation(fWindow.getShell(), DIALOG_TITLE,
Messages.RenamePHPElementActionDelegate_2);
return;
}
try {
int offset = getSourceOffset(element);
run(element.getResource(), program, offset, 0, fWindow.getActivePage().getActiveEditor(), false);
} catch (ModelException e) {
MessageDialog.openInformation(fWindow.getShell(), DIALOG_TITLE,
Messages.RenamePHPElementActionDelegate_2);
return;
}
} else {
RenameResourceAction renameAction = new RenameResourceAction(new IShellProvider() {
public Shell getShell() {
return fWindow.getShell();
}
});
renameAction.selectionChanged(selection);
renameAction.run();
}
}
protected boolean isModelElement(Object object) {
return object instanceof IModelElement;
}
protected int getSourceOffset(IModelElement element) throws ModelException {
// This is the work around for the case of multiple
// variable/constant declaration in one line.
if (element instanceof SourceField) {
return ((SourceField) element).getNameRange().getOffset();
} else {
return ((ISourceReference) element).getSourceRange().getOffset();
}
}
protected boolean isSourceReference(Object object) {
return object instanceof ISourceReference;
}
protected boolean isScriptContainer(Object object) {
return object instanceof IScriptFolder || object instanceof IScriptProject || object instanceof ProjectFragment;
}
public void dispose() {
}
public void init(IWorkbenchWindow window) {
this.fWindow = window;
}
public void selectionChanged(IAction action, ISelection selection) {
this.selection = selection;
}
public void setActiveEditor(IAction action, IEditorPart targetEditor) {
}
}