/***** 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.astviewer.views;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
import org.jruby.ast.Node;
import org.rubypeople.rdt.astviewer.Activator;
import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditor;
public class AstView extends ViewPart {
private TreeViewer viewer;
private DrillDownAdapter drillDownAdapter;
private Action refreshAction;
private Action dumpToConsoleAction;
private Action dumpJRubyTestFormatAction;
private Action doubleClickAction;
private Action clickAction;
private ViewContentProvider viewContentProvider;
private SashForm sashForm;
private SourceViewer detailsViewer;
public void createPartControl(Composite parent) {
sashForm = new SashForm(parent, SWT.NONE);
sashForm.setOrientation(SWT.VERTICAL);
PatternFilter patternFilter = new PatternFilter();
final FilteredTree filter = new FilteredTree(sashForm, SWT.MULTI
| SWT.H_SCROLL | SWT.V_SCROLL, patternFilter);
viewer = filter.getViewer();
drillDownAdapter = new DrillDownAdapter(viewer);
viewContentProvider = new ViewContentProvider(getViewSite());
viewer.setContentProvider(viewContentProvider);
viewer.setLabelProvider(new ViewLabelProvider());
viewer.setInput(getViewSite());
makeActions();
hookContextMenu();
hookClickAction();
hookDoubleClickAction();
contributeToActionBars();
//setupListeners();
viewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
detailsViewer= new SourceViewer(sashForm, null, SWT.V_SCROLL | SWT.H_SCROLL);
detailsViewer.setEditable(false);
detailsViewer.setDocument(new Document());
Control control = detailsViewer.getControl();
GridData gd = new GridData(GridData.FILL_BOTH);
control.setLayoutData(gd);
sashForm.setWeights(new int[]{90, 10});
}
// Tried to automatically update the view, but could not figure out yet how to do it properly.
// private void setupListeners(){
//
// final IPartListener partListener = new IPartListener(){
// public void partActivated(IWorkbenchPart part) {
// partWasActivated();
// }
// public void partBroughtToTop(IWorkbenchPart part) {}
// public void partClosed(IWorkbenchPart part) {}
// public void partDeactivated(IWorkbenchPart part) {}
// public void partOpened(IWorkbenchPart part) {
// partWasActivated();
// }
// };
//
// PlatformUI.getWorkbench().getActiveWorkbenchWindow().addPageListener(new IPageListener(){
//
// public void pageActivated(final IWorkbenchPage page) {
// page.addPartListener(partListener);
// }
//
// public void pageClosed(IWorkbenchPage page) {}
//
// public void pageOpened(IWorkbenchPage page) {
// page.addPartListener(partListener);
// }});
// }
//
// private void partWasActivated() {
// if(viewContentProvider.updateContent()) {
// viewer.setInput(getViewSite());
// viewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
// }
// }
private void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
AstView.this.fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
}
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
private void fillLocalPullDown(IMenuManager manager) {
manager.add(refreshAction);
manager.add(dumpToConsoleAction);
manager.add(dumpJRubyTestFormatAction);
}
private void fillContextMenu(IMenuManager manager) {
manager.add(refreshAction);
manager.add(dumpToConsoleAction);
//manager.add(dumpJRubyTestFormatAction);
drillDownAdapter.addNavigationActions(manager);
// Other plug-ins can contribute there actions here
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void fillLocalToolBar(IToolBarManager manager) {
manager.add(refreshAction);
manager.add(dumpToConsoleAction);
manager.add(dumpJRubyTestFormatAction);
drillDownAdapter.addNavigationActions(manager);
}
private void makeActions() {
makeRefreshAction();
makeDumpAction();
makeDumpJRubyFormatAction();
}
private void makeDumpJRubyFormatAction() {
dumpJRubyTestFormatAction = new Action() {
public void run() {
AstViewConsole.print(AstUtility.nodeListJRubyFormat(AstUtility.findAllNodes(getRootNode())));
AstViewConsole.print("test_tree(list, <<END)");
AstViewConsole.print(textEditorContentToString().toString().trim());
AstViewConsole.print("END");
}
private StringBuilder textEditorContentToString() {
IEditorInput editorInput = getEditor().getEditorInput();
IFile aFile = null;
if(editorInput instanceof IFileEditorInput){
aFile = ((IFileEditorInput)editorInput).getFile();
}
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
try {
br = new BufferedReader(new InputStreamReader(aFile.getContents()));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
} catch (CoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return sb;
}
};
dumpJRubyTestFormatAction.setText("Dump in JRuby-Test");
dumpJRubyTestFormatAction.setToolTipText("Dumps node and all child-nodes to the console, formatted like as in JRuby's testPositions.rb");
dumpJRubyTestFormatAction.setImageDescriptor(Activator.getImageDescriptor("icons/dump_jruby.gif"));
}
private void makeDumpAction() {
dumpToConsoleAction = new Action() {
public void run() {
AstViewConsole.print(AstUtility.nodeList(AstUtility.findAllNodes(getSelectedNode())));
}
};
dumpToConsoleAction.setText("Dump Node");
dumpToConsoleAction.setToolTipText("Dumps node and all child-nodes to the console.");
dumpToConsoleAction.setImageDescriptor(Activator.getImageDescriptor("icons/dump.gif"));
}
private void makeRefreshAction() {
refreshAction = new Action() {
public void run() {
viewContentProvider.forceUpdateContent();
viewer.setInput(getViewSite());
viewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
}
};
refreshAction.setText("Refresh the AST View");
refreshAction.setToolTipText("Performs a complete refresh over the whole AST.");
refreshAction.setImageDescriptor(Activator.getImageDescriptor("icons/refresh.gif"));
}
private void setSelection(RubyEditor editor, Node n) {
if (n == null || n.getPosition() == null)
return;
editor.selectAndReveal(n.getPosition().getStartOffset(), n.getPosition().getEndOffset() - n.getPosition().getStartOffset());
}
private void hookClickAction() {
clickAction = new Action(){
public void run() {
detailsViewer.getDocument().set(AstUtility.formatedPosition(getSelectedNode()));
}
};
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(@SuppressWarnings("unused")
SelectionChangedEvent event) {
clickAction.run();
}
});
}
private Node getSelectedNode() {
TreeItem[] selection = viewer.getTree().getSelection();
if(selection.length <= 0)
return null;
return ((TreeObject) selection[0].getData()).getNode();
}
private Node getRootNode() {
TreeItem root = viewer.getTree().getItem(0);
return ((TreeObject) root.getData()).getNode();
}
private RubyEditor getEditor() {
return (RubyEditor) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
}
private void hookDoubleClickAction() {
doubleClickAction = new Action(){
public void run() {
setSelection(getEditor(), getSelectedNode());
}
};
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(@SuppressWarnings("unused")
DoubleClickEvent event) {
doubleClickAction.run();
}
});
}
public void setFocus() {
viewer.getControl().setFocus();
}
}