001: /*****************************************************************************************
002: * Copyright (c) 2007 Andrei Loskutov. All rights reserved. This program and the
003: * accompanying materials are made available under the terms of the BSD License which
004: * accompanies this distribution, and is available at
005: * http://www.opensource.org/licenses/bsd-license.php
006: * Contributor: Eugene Kuleshov - initial API and implementation
007: ****************************************************************************************/package de.loskutov.bco.views;
008:
009: import java.net.URL;
010:
011: import org.eclipse.core.runtime.IStatus;
012: import org.eclipse.help.internal.base.BaseHelpSystem;
013: import org.eclipse.jface.action.IToolBarManager;
014: import org.eclipse.jface.text.ITextSelection;
015: import org.eclipse.jface.viewers.ISelection;
016: import org.eclipse.jface.viewers.IStructuredSelection;
017: import org.eclipse.swt.SWT;
018: import org.eclipse.swt.browser.Browser;
019: import org.eclipse.swt.widgets.Composite;
020: import org.eclipse.ui.IActionBars;
021: import org.eclipse.ui.IPartListener2;
022: import org.eclipse.ui.ISelectionListener;
023: import org.eclipse.ui.ISelectionService;
024: import org.eclipse.ui.IViewPart;
025: import org.eclipse.ui.IViewReference;
026: import org.eclipse.ui.IWorkbenchPart;
027: import org.eclipse.ui.IWorkbenchPartReference;
028: import org.eclipse.ui.IWorkbenchWindow;
029: import org.eclipse.ui.PartInitException;
030: import org.eclipse.ui.part.ViewPart;
031: import org.objectweb.asm.util.AbstractVisitor;
032:
033: import de.loskutov.bco.BytecodeOutlinePlugin;
034: import de.loskutov.bco.editors.BytecodeClassFileEditor;
035: import de.loskutov.bco.preferences.BCOConstants;
036: import de.loskutov.bco.ui.actions.DefaultToggleAction;
037:
038: public class BytecodeReferenceView extends ViewPart implements
039: IPartListener2, ISelectionListener {
040:
041: private static final String NLS_PREFIX = "BytecodeReferenceView.";
042: private Browser browser;
043: private DefaultToggleAction linkWithViewAction;
044: private boolean linkWithView;
045:
046: public BytecodeReferenceView() {
047: super ();
048: }
049:
050: public void createPartControl(Composite parent) {
051: browser = new Browser(parent, SWT.BORDER);
052: final IWorkbenchWindow workbenchWindow = getSite()
053: .getWorkbenchWindow();
054: linkWithView = BytecodeOutlinePlugin.getDefault()
055: .getPreferenceStore().getBoolean(
056: BCOConstants.LINK_REF_VIEW_TO_EDITOR);
057: linkWithViewAction = new DefaultToggleAction(
058: BCOConstants.LINK_REF_VIEW_TO_EDITOR) {
059: public void run(boolean newState) {
060: linkWithView = newState;
061: if (linkWithView) {
062: ISelectionService selectionService = workbenchWindow
063: .getSelectionService();
064: try {
065: IViewPart part = workbenchWindow
066: .getActivePage()
067: .showView(
068: "de.loskutov.bco.views.BytecodeOutlineView");
069: ISelection selection = selectionService
070: .getSelection("de.loskutov.bco.views.BytecodeOutlineView");
071: selectionChanged(part, selection);
072: } catch (PartInitException e) {
073: BytecodeOutlinePlugin.log(e, IStatus.ERROR);
074: }
075: }
076: }
077: };
078: final IActionBars bars = getViewSite().getActionBars();
079: final IToolBarManager tmanager = bars.getToolBarManager();
080: tmanager.add(linkWithViewAction);
081: shouDefaultEmptyPage();
082: workbenchWindow.getPartService().addPartListener(this );
083: }
084:
085: public void dispose() {
086: getSite().getWorkbenchWindow().getPartService()
087: .removePartListener(this );
088: browser.dispose();
089: browser = null;
090: linkWithViewAction = null;
091: super .dispose();
092: }
093:
094: public void setFocus() {
095: browser.setFocus();
096: }
097:
098: public void partActivated(IWorkbenchPartReference partRef) {
099: //
100: }
101:
102: public void partBroughtToTop(IWorkbenchPartReference partRef) {
103: //
104: }
105:
106: public void partClosed(IWorkbenchPartReference partRef) {
107: //
108: }
109:
110: public void partDeactivated(IWorkbenchPartReference partRef) {
111: //
112: }
113:
114: public void partOpened(IWorkbenchPartReference partRef) {
115: // WORKAROUND - sometimes Eclipse does not invoke partVisible(),
116: // but only partOpened()...
117: partVisible(partRef);
118: }
119:
120: public void partHidden(IWorkbenchPartReference partRef) {
121: if (partRef.getId().equals(getSite().getId())) {
122: getSite().getWorkbenchWindow().getSelectionService()
123: .removePostSelectionListener(this );
124: }
125: }
126:
127: public void partVisible(IWorkbenchPartReference partRef) {
128: if (partRef.getId().equals(getSite().getId())) {
129: IWorkbenchWindow workbenchWindow = getSite()
130: .getWorkbenchWindow();
131: ISelectionService selectionService = workbenchWindow
132: .getSelectionService();
133: String partId = BytecodeOutlineView.class.getName();
134: selectionService.addPostSelectionListener(this );
135:
136: // perform initialization with already existing selection (if any)
137: ISelection selection = selectionService
138: .getSelection(partId);
139: if (selection != null) {
140: IViewReference viewReference = workbenchWindow
141: .getActivePage().findViewReference(partId);
142: if (viewReference != null) {
143: selectionChanged(viewReference.getView(false),
144: selection);
145: }
146: }
147: }
148: }
149:
150: public void partInputChanged(IWorkbenchPartReference partRef) {
151: //
152: }
153:
154: public void selectionChanged(IWorkbenchPart part,
155: ISelection selection) {
156: boolean isViewSelection = part instanceof BytecodeOutlineView;
157: if (!linkWithView
158: || !(isViewSelection || part instanceof BytecodeClassFileEditor)) {
159: return;
160: }
161: int line = -1;
162: String opcodeName = null;
163: if (selection instanceof ITextSelection) {
164: line = ((ITextSelection) selection).getStartLine();
165: } else if (selection instanceof IStructuredSelection) {
166: IStructuredSelection sselection = (IStructuredSelection) selection;
167: int size = sselection.size();
168: if (size == 1
169: && sselection.getFirstElement() instanceof Integer) {
170: line = ((Integer) sselection.getFirstElement())
171: .intValue();
172: }
173: }
174:
175: if (line >= 0) {
176: int opcode;
177: if (isViewSelection) {
178: opcode = ((BytecodeOutlineView) part)
179: .getBytecodeInstructionAtLine(line);
180: } else {
181: opcode = ((BytecodeClassFileEditor) part)
182: .getBytecodeInstructionAtLine(line);
183: }
184: if (opcode != -1) {
185: opcodeName = AbstractVisitor.OPCODES[opcode];
186: }
187: }
188:
189: if (opcodeName != null) {
190: opcodeName = checkOpcodeName(opcodeName);
191:
192: URL url = getHelpResource(opcodeName);
193: if (url != null) {
194: browser.setUrl(url.toString());
195: } else {
196: shouDefaultEmptyPage();
197: }
198: } else {
199: shouDefaultEmptyPage();
200: }
201: }
202:
203: private void shouDefaultEmptyPage() {
204: browser
205: .setText(BytecodeOutlinePlugin
206: .getResourceString(NLS_PREFIX
207: + "empty.selection.text"));
208: }
209:
210: private String checkOpcodeName(String opcodeName) {
211: opcodeName = opcodeName.toLowerCase();
212: /*
213: * we need an additional check for DCONST_1...5, FCONST_1...5 etc case
214: * to convert it to DCONST_D etc
215: */
216: int sepIndex = opcodeName.indexOf('_');
217: if (sepIndex > 0
218: && Character.isDigit(opcodeName.charAt(sepIndex + 1))) {
219: opcodeName = opcodeName.substring(0, sepIndex);
220: switch (opcodeName.charAt(0)) {
221: case 'd':
222: opcodeName += "_d";
223: break;
224: case 'f':
225: opcodeName += "_f";
226: break;
227: case 'l':
228: opcodeName += "_l";
229: break;
230: default:
231: // ICONST uses "n"
232: opcodeName += "_n";
233: break;
234: }
235: }
236: return opcodeName;
237: }
238:
239: private URL getHelpResource(String name) {
240: try {
241: String href = "/"
242: + BytecodeOutlinePlugin.getDefault().getBundle()
243: .getSymbolicName() + "/doc/ref-" + name
244: + ".html";
245: return BaseHelpSystem.resolve(href, true);
246: } catch (Exception e) {
247: return null;
248: }
249: }
250: }
|