AbstractBaseScopeView.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.viewer.scope;
00002 
00003 import java.io.FileNotFoundException;
00004 import java.util.Map;
00005 //User interface
00006 import org.eclipse.ui.commands.ICommandService;
00007 import org.eclipse.ui.part.ViewPart;
00008 import org.eclipse.ui.services.ISourceProviderService;
00009 import org.eclipse.ui.ISourceProviderListener;
00010 import org.eclipse.ui.IWorkbenchActionConstants;
00011 import org.eclipse.ui.IWorkbenchPage;
00012 //SWT
00013 import org.eclipse.swt.*;
00014 import org.eclipse.swt.layout.GridData;
00015 import org.eclipse.swt.layout.GridLayout;
00016 import org.eclipse.swt.widgets.*;
00017 import org.eclipse.swt.dnd.Clipboard;
00018 import org.eclipse.swt.dnd.TextTransfer;
00019 import org.eclipse.swt.dnd.Transfer;
00020 import org.eclipse.swt.graphics.GC;
00021 import org.eclipse.swt.graphics.Point;
00022 import org.eclipse.swt.graphics.Rectangle;
00023 
00024 //Jface
00025 import org.eclipse.core.commands.ExecutionEvent;
00026 import org.eclipse.core.commands.ExecutionException;
00027 import org.eclipse.core.commands.IExecutionListener;
00028 import org.eclipse.core.commands.NotHandledException;
00029 import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
00030 import org.eclipse.jface.action.MenuManager;
00031 import org.eclipse.jface.action.IMenuListener;
00032 import org.eclipse.jface.action.IMenuManager;
00033 import org.eclipse.jface.action.Separator;
00034 import org.eclipse.jface.action.Action;
00035 import org.eclipse.jface.viewers.CellLabelProvider;
00036 import org.eclipse.jface.viewers.ISelectionChangedListener;
00037 import org.eclipse.jface.viewers.SelectionChangedEvent;
00038 import org.eclipse.jface.viewers.TreeExpansionEvent;
00039 import org.eclipse.jface.viewers.TreeSelection;
00040 import org.eclipse.jface.viewers.TreeViewerColumn;
00041 import org.eclipse.jface.viewers.ITreeViewerListener;
00042 import org.eclipse.jface.window.ToolTip;
00043 
00044 //HPC
00045 import edu.rice.cs.hpc.common.ui.Util;
00046 import edu.rice.cs.hpc.data.experiment.*;
00047 import edu.rice.cs.hpc.data.experiment.scope.*;
00048 import edu.rice.cs.hpc.data.util.OSValidator;
00049 import edu.rice.cs.hpc.viewer.actions.DebugShowCCT;
00050 import edu.rice.cs.hpc.viewer.actions.DebugShowFlatID;
00051 import edu.rice.cs.hpc.viewer.actions.ShowMetricProperties;
00052 import edu.rice.cs.hpc.viewer.editor.EditorManager;
00053 import edu.rice.cs.hpc.viewer.provider.DatabaseState;
00054 import edu.rice.cs.hpc.viewer.util.Utilities;
00055 import edu.rice.cs.hpc.viewer.window.Database;
00056 
00066 abstract public class AbstractBaseScopeView  extends ViewPart 
00067 {   
00068     protected ScopeTreeViewer   treeViewer;         // tree for the caller and callees
00069     
00070     protected Database  database;       // experiment data  
00071     protected RootScope         myRootScope;        // the root scope of this view
00072     protected ColumnViewerSorter sorterTreeColumn;  // sorter for the tree
00073     protected ScopeViewActions objViewActions;  // actions for this scope view
00074     
00075     private EditorManager editorSourceCode; // manager to display the source code
00076     private Clipboard cb = null;
00077     private GC gc = null;
00078     
00079     private ISourceProviderListener listener;
00080 
00084     protected CoolBar objCoolbar;
00085     
00086     //======================================================
00087     // ................ HELPER ............................
00088     //======================================================
00089     public AbstractBaseScopeView()
00090     {
00091         final ISourceProviderService service   = (ISourceProviderService)Util.getActiveWindow().
00092                 getService(ISourceProviderService.class);
00093         DatabaseState serviceProvider  = (DatabaseState) service.getSourceProvider(DatabaseState.DATABASE_NEED_REFRESH);
00094         listener         = new ISourceProviderListener() {
00095             
00096             @Override
00097             public void sourceChanged(int sourcePriority, String sourceName,
00098                     Object sourceValue) {
00099                 if (sourceName.equals(DatabaseState.DATABASE_NEED_REFRESH))
00100                 {
00101                     if (sourceValue instanceof Boolean)
00102                     {
00103                         Boolean state = (Boolean) sourceValue;
00104                         enableFilter(state);
00105                     }
00106                 }
00107             }
00108             
00109             @Override
00110             public void sourceChanged(int sourcePriority, Map sourceValuesByName) {}
00111         };
00112         serviceProvider.addSourceProviderListener(listener);
00113 
00114     }
00115     
00116     //======================================================
00117     // ................ HELPER ............................
00118     //======================================================
00119     
00124     private void displayFileEditor(Scope scope) {
00125         if(editorSourceCode == null) {
00126             this.editorSourceCode = new EditorManager(this.getSite());
00127         }
00128         try {
00129             this.editorSourceCode.displayFileEditor(scope);
00130         } catch (FileNotFoundException e) {
00131             this.objViewActions.showErrorMessage("No source available for binary file "+e.getMessage());
00132         }
00133     }
00134 
00135     //======================================================
00136     // ................ ACTIONS ............................
00137     //======================================================
00138 
00142     private Action acZoomin = new Action("Zoom-in"){
00143         public void run() {
00144             objViewActions.zoomIn();
00145         }
00146     };
00147     
00151     private Action acZoomout = new Action("Zoom-out"){
00152         public void run() {
00153             objViewActions.zoomOut();
00154         }
00155     };
00156 
00161     private boolean isItemSelected() {
00162         return (this.treeViewer.getTree().getSelectionCount() > 0);
00163     }
00164     
00169     private Scope getSelectedItem() {
00170         TreeItem[] selection = this.treeViewer.getTree().getSelection();
00171         if(selection != null) {
00172             Object o = selection[0].getData();
00177             if(o instanceof Scope)
00178                 return (Scope)o;
00179         }
00180         return null;
00181     }
00182     
00188     private void fillContextMenu(IMenuManager mgr) {
00189         Scope scope = this.getSelectedItem();
00190         final Action acCopy = new Action("Copy") {
00191             public void run() {
00192                 copyToClipboard();
00193             }
00194         }; 
00199         if(scope == null) {
00200             mgr.add(acCopy);
00201             return;
00202         }
00203         // ---- zoomin
00204         mgr.add(acZoomin);
00205         acZoomin.setEnabled(this.objViewActions.shouldZoomInBeEnabled(scope));
00206         // ---- zoomout
00207         mgr.add(acZoomout);
00208         acZoomout.setEnabled(this.objViewActions.shouldZoomOutBeEnabled());
00209 
00210         // ---- additional feature
00211         mgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
00212 
00213 
00214         // Laks 2009.06.22: add new feature to copy selected line to the clipboard
00215         mgr.add(acCopy);
00216 
00217         //--------------------------------------------------------------------------
00218         // ---------- show the source code
00219         //--------------------------------------------------------------------------
00220         
00221         // show the editor source code
00222         final String SHOW_MENU = "Show ";
00223         
00224         String sMenuTitle ;
00225         if(scope instanceof FileScope) {
00226             sMenuTitle = SHOW_MENU + scope.getSourceFile().getName();
00227         } else
00228             sMenuTitle= SHOW_MENU +scope.getToolTip(); // the tooltip contains the info we need: file and the linenum
00229         
00230         ScopeViewTreeAction acShowCode = new ScopeViewTreeAction(sMenuTitle, scope){
00231             public void run() {
00232                 displayFileEditor(this.scope);
00233             }
00234         };
00235         acShowCode.setEnabled(Utilities.isFileReadable(scope));
00236         mgr.add(acShowCode);
00237 
00238         // show the call site in case this one exists
00239         if(scope instanceof CallSiteScope) {
00240             // get the call site scope
00241             CallSiteScope callSiteScope = (CallSiteScope) scope;
00242             LineScope lineScope = (LineScope) callSiteScope.getLineScope();
00243             // setup the menu
00244             sMenuTitle = "Callsite "+lineScope.getToolTip();
00245             ScopeViewTreeAction acShowCallsite = new ScopeViewTreeAction(sMenuTitle, lineScope){
00246                 public void run() {
00247                     displayFileEditor(this.scope);
00248                 }
00249             }; 
00250             // do not show up in the menu context if the callsite does not exist
00251             acShowCallsite.setEnabled(Utilities.isFileReadable(lineScope));
00252             mgr.add(acShowCallsite);
00253         }
00254         
00255 
00256         //--------------------------------------------------------------------------
00257         // ---------- additional context menu
00258         //--------------------------------------------------------------------------
00259         mgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
00260 
00261         this.createAdditionalContextMenu(mgr, scope);
00262     }
00263     
00264     
00268     private void copyToClipboard() {
00269         // only selected items that are copied into clipboard
00270         TreeItem []itemsSelected = this.treeViewer.getTree().getSelection();
00271         // convert the table into a string
00272         String sText = this.objViewActions.getContent(itemsSelected, "\t");
00273         // send the string into clipboard
00274         TextTransfer textTransfer = TextTransfer.getInstance();
00275         if (this.cb == null)
00276             this.cb = new Clipboard(this.getSite().getShell().getDisplay());
00277         cb.setContents(new Object[]{sText}, new Transfer[]{textTransfer});
00278     }
00279     
00283     private void createContextMenu() {
00284         // Create menu manager.
00285         MenuManager menuMgr = new MenuManager();
00286         menuMgr.setRemoveAllWhenShown(true);
00287         menuMgr.addMenuListener(new IMenuListener() {
00288                 public void menuAboutToShow(IMenuManager mgr) {
00289                     if(isItemSelected())
00290                         fillContextMenu(mgr);
00291                 }
00292         });
00293         
00294         // Create menu.
00295         Menu menu = menuMgr.createContextMenu(this.treeViewer.getControl());
00296         this.treeViewer.getControl().setMenu(menu);
00297         
00298         // Register menu for extension.    
00299         // Using an id allows code that extends this class to add entries to this context menu.
00300         getSite().registerContextMenu("edu.rice.cs.hpc.viewer.scope.ScopeView", menuMgr, this.treeViewer);
00301     }
00302     
00308     protected class ScopeViewTreeAction extends Action {
00309         protected Scope scope;
00310         public ScopeViewTreeAction(String sTitle, Scope scopeCurrent) {
00311             super(sTitle);
00312             this.scope = scopeCurrent;
00313         }
00314     }
00315     
00316     
00317     //===================================================================
00318     // ---------- VIEW CREATION -----------------------------------------
00319     //===================================================================
00320     
00324     public void createPartControl(Composite aParent) {
00325         Composite objCompositeParent;
00326         objCompositeParent = this.createToolBarArea(aParent);
00327         this.objCoolbar = this.initToolbar(objCompositeParent);
00328         this.objViewActions =  createActions(objCompositeParent, this.objCoolbar); //actions of the tree
00329         
00330         // ----- 03.21.2008 Laks: add virtual library for better memory consumption
00331         // Laks 2009.06.22: add multi-selection for enabling copying into clipboard 
00332         treeViewer = new ScopeTreeViewer(aParent,SWT.BORDER|SWT.FULL_SELECTION | SWT.VIRTUAL | SWT.MULTI);
00333         // set the attributes
00334         AbstractContentProvider treeContentProvider = getScopeContentProvider(); 
00335         treeViewer.setContentProvider(treeContentProvider);
00336         treeViewer.getTree().setHeaderVisible(true);
00337         treeViewer.getTree().setLinesVisible(true);
00338         
00339         // --------------------------------------------------------------------
00340         // tricky code for linux: by default on linux the tooltip doesn't show up
00341         //  we should manually tell eclipse/jface that we want a tooltip for the table
00342         // --------------------------------------------------------------------
00343         if (OSValidator.isUnix())
00344             ColumnViewerToolTipSupport.enableFor(treeViewer, ToolTip.NO_RECREATE);
00345 
00346         //treeViewer.setAutoExpandLevel(2);
00347         
00348         //----------------- create the column tree
00349         TreeViewerColumn colTree;       // column for the scope tree
00350         colTree = new TreeViewerColumn(treeViewer,SWT.LEFT, 0);
00351         colTree.getColumn().setText("Scope");
00352         colTree.getColumn().setWidth(200); //TODO dynamic size
00353         colTree.setLabelProvider( getLabelProvider() ); // laks addendum
00354         sorterTreeColumn = new ColumnViewerSorter(this.treeViewer, colTree.getColumn(), null,0); 
00355         
00356         //-----------------
00357         // Laks 11.11.07: need this to expand the tree for all view
00358         GridData data = new GridData(GridData.FILL_BOTH);
00359         treeViewer.getTree().setLayoutData(data);
00360         //-----------------
00361         // create the context menus
00362         this.createContextMenu();
00363 
00364         //------------------------ LISTENER --------------
00369         gc = new GC(this.treeViewer.getTree().getDisplay());
00370         treeViewer.getTree().addListener(SWT.MouseDown, new ScopeMouseListener(gc, this.getSite().getPage())); 
00371         
00372         // bug #132: https://outreach.scidac.gov/tracker/index.php?func=detail&aid=132&group_id=22&atid=169
00373         // need to capture event of "collapse" tree then check if the button state should be updated or not.
00374         treeViewer.addTreeListener(new ITreeViewerListener(){
00375             public void treeCollapsed(TreeExpansionEvent event) {
00376                 objViewActions.checkNodeButtons();
00377             }
00378             public void treeExpanded(TreeExpansionEvent event){
00379                 
00380             }
00381         });
00382         
00383         Utilities.listenerToResetRowHeight( treeViewer );
00384 
00385         // allow other views to listen for selections in this view (site)
00386         this.getSite().setSelectionProvider(treeViewer);
00387         
00392         treeViewer.addSelectionChangedListener(new ISelectionChangedListener(){
00393             public void selectionChanged(SelectionChangedEvent event)
00394               {
00395                 TreeSelection selection =
00396                   (TreeSelection) event.getSelection();
00397 
00398                 Object objElement = selection.getFirstElement();
00399                 if(objElement instanceof Scope) {
00400                     Scope nodeSelected = (Scope) objElement;
00401                     if(nodeSelected != null) {
00402                         // update the state of the toolbar items
00403                         objViewActions.checkStates(nodeSelected);
00404                     }
00405                 } else {
00406                     // selection on wrong node
00407                     objViewActions.disableButtons();
00408                     objViewActions.checkStates();
00409                 }
00410               }
00411         }); 
00412 
00413         // ---------------------------------------------------------------
00414         // register listener to capture debugging mode
00415         // ---------------------------------------------------------------
00416         final ICommandService commandService = (ICommandService) this.getSite().getService(ICommandService.class);
00417         commandService.addExecutionListener( new IExecutionListener(){
00418 
00419             public void notHandled(String commandId, NotHandledException exception) {}
00420             public void postExecuteFailure(String commandId, ExecutionException exception) {}
00421             public void preExecute(String commandId, ExecutionEvent event) {}
00422 
00423             /*
00424              * (non-Javadoc)
00425              * @see org.eclipse.core.commands.IExecutionListener#postExecuteSuccess(java.lang.String, java.lang.Object)
00426              */
00427             public void postExecuteSuccess(String commandId, Object returnValue) 
00428             {
00429                 if (commandId.equals(DebugShowCCT.commandId) || commandId.equals(DebugShowFlatID.commandId))
00430                 {
00431                     // refresh the table to take into account the turn on/off debugging mode
00432                     Utilities.resetView(treeViewer);
00433                 } 
00434                 else if (commandId.equals( ShowMetricProperties.COMMAND_REFRESH_METRICS ) ) 
00435                 {
00436                     treeViewer.refreshColumnTitle();
00437                 }
00438             }
00439         });
00440     }
00441     
00447     protected Composite createToolBarArea(Composite parent) {
00448         // make the parent with grid layout
00449         Composite toolbarArea = new Composite(parent, SWT.NONE);
00450         GridLayout grid = new GridLayout(1,false);
00451         parent.setLayout(grid);
00452         return toolbarArea;
00453     }
00454 
00460     protected CoolBar initToolbar(Composite toolbarArea) {
00461         CoolBar coolBar = new CoolBar(toolbarArea, SWT.FLAT);
00462         GridData data = new GridData(GridData.FILL_HORIZONTAL);
00463         coolBar.setLayoutData(data);
00464 
00465         return coolBar;
00466     }
00467     
00468 
00469     /*
00470      * (non-Javadoc)
00471      * @see org.eclipse.ui.part.WorkbenchPart#dispose()
00472      */
00473     public void dispose() {
00474         if (gc != null)
00475             gc.dispose();
00476     }
00477     
00478     //======================================================
00479     // ................ UPDATE ............................
00480     //======================================================
00481     // laks: we need experiment and rootscope
00485     public void setInput(Database db, RootScope scope, boolean keepColumnStatus) {
00486         initDatabase(db, scope, keepColumnStatus);
00487         updateDisplay();
00488     }
00489     
00490     /***
00491      * initialize view without creating the tree and the metric columns
00492      * 
00493      * @param db
00494      * @param scope
00495      */
00496     public void initDatabase(Database db, RootScope scope, boolean keepColumnStatus) {
00497         database = db;
00498         myRootScope = scope;// try to get the aggregate value
00499 
00500         // tell the action class that we have built the tree
00501         this.objViewActions.setTreeViewer(treeViewer);
00502         
00503         initTableColumns(keepColumnStatus);
00504     }
00505     
00506     
00507     //======================================================
00508     // ................ MISC ............................
00509     //======================================================
00514     public void setViewTitle(String sName) {
00515         super.setPartName(sName);
00516     }
00517     public void setFocus() {
00518             treeViewer.getTree().setFocus();
00519     }
00520     
00521     public ScopeViewActions getViewActions() {
00522         return this.objViewActions;
00523     }
00528     public ScopeTreeViewer getTreeViewer() {
00529         return this.treeViewer;
00530     }
00531 
00532     /****
00533      * get the experiment of this view
00534      * @return
00535      */
00536     public Experiment getExperiment() {
00537         if (database != null)
00538             return database.getExperiment();
00539         return null;
00540     }
00541 
00542     /****
00543      * get the root scope (either cct, caller tree or flat tree)
00544      * @return
00545      */
00546     public RootScope getRootScope() {
00547         return this.myRootScope;
00548     }
00549     
00550     public Database getDatabase() {
00551         return database;
00552     }
00553     //======================================================
00554     // ................ ABSTRACT...........................
00555     //======================================================
00556 
00561     abstract public void updateDisplay();
00562 
00563     abstract protected void initTableColumns(boolean keepColumnStatus);
00564     
00573     abstract protected ScopeViewActions createActions(Composite parent, CoolBar coolbar);
00574     
00575     /***
00576      * event when a user starts to click
00577      * @param event
00578      */
00579     protected abstract void mouseDownEvent(Event event);
00580 
00581     abstract protected void createAdditionalContextMenu(IMenuManager mgr, Scope scope);
00582     
00583     abstract protected AbstractContentProvider getScopeContentProvider();
00584 
00585     abstract protected void enableFilter(boolean isEnabled);
00586     abstract protected CellLabelProvider getLabelProvider(); 
00587 
00588     //======================================================
00589     // ................ CLASSES...........................
00590     //======================================================
00591 
00592     
00593     /***
00594      * 
00595      * class to handle mouse up and down event in scope tree
00596      *
00597      */
00598     public class ScopeMouseListener implements Listener {
00599 
00600         final private GC gc;
00601         final private IWorkbenchPage page;
00602         
00607         public ScopeMouseListener(final GC gc, IWorkbenchPage page) {
00608             this.gc = gc;
00609             this.page = page;
00610         }
00611         
00612         /*
00613          * (non-Javadoc)
00614          * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
00615          */
00616         public void handleEvent(Event event) {
00617 
00618             // tell the children to handle the mouse click
00619             mouseDownEvent(event);
00620 
00621             if(event.button != 1) {
00622                 // yes, we only allow the first button
00623                 return;
00624             }
00625             
00626             // get the item
00627             TreeItem []itemsSelected = treeViewer.getTree().getSelection();
00628             if(itemsSelected == null || itemsSelected.length==0)
00629                 return; // no selected. it will hard to for us to go further
00630             TreeItem item = itemsSelected[0];
00631             Rectangle recImage = item.getImageBounds(0);    // get the image location (if exist)
00632             Rectangle recText = item.getTextBounds(0);
00633             
00634             // verify if the user click on the icon
00635             if(recImage.intersects(event.x, event.y, event.width, event.height)) {
00636                 // Check the object of the click/select item
00637                 TreeSelection selection = (TreeSelection) treeViewer.getSelection();
00638                 Object o = selection.getFirstElement();
00639                 
00640                 // we will treat this click if the object is Scope
00641                 if(o instanceof Scope) {
00642                     Scope scope = (Scope) o;
00643                     // show the call site in case this one exists
00644                     if(scope instanceof CallSiteScope) {
00645                         // get the call site scope
00646                         CallSiteScope callSiteScope = (CallSiteScope) scope;
00647                         LineScope lineScope = (LineScope) callSiteScope.getLineScope();
00648                         displaySourceCode(lineScope);
00649                     } else {
00650                     }
00651                 }
00652             } else if(recText.intersects(event.x, event.y, 1, 1)){
00653                 // Check the object of the click/select item
00654                 TreeSelection selection = (TreeSelection) treeViewer.getSelection();
00655                 Object o = selection.getFirstElement();
00656                 
00657                 // we will treat this click if the object is Scope.Node
00658                 if(o instanceof Scope) {
00659                     if (o instanceof CallSiteScope) {
00660                         CallSiteScope cs = (CallSiteScope) o;
00661                         // the line number in xml is started from zero, while the source
00662                         //  code starts from 1
00663                         int line = 1 + cs.getLineScope().getFirstLineNumber();
00664                         
00665                         if (gc != null && line>0) {
00666                             Point p = gc.textExtent(":" + line);
00667                             if (p.x+recText.x >= event.x && p.y+recText.y>= event.y) {
00668                                 displaySourceCode( cs.getLineScope() );
00669                                 return;
00670                             }
00671                         }
00672                     }
00673                     displaySourceCode( (Scope)o );
00674                 }
00675             } else {
00676                 // User click a region other than tree
00677             }       
00678         }
00679         
00684         private void displaySourceCode( Scope scope ) {
00685             // display the source code if the view is not maximized
00686             int state = page.getPartState( page.getActivePartReference() );
00687             if (state != IWorkbenchPage.STATE_MAXIMIZED) {
00688                 displayFileEditor( scope );
00689             }
00690         }
00691     }
00692 
00693 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1