ScopeViewActions.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.viewer.scope;
00002 
00003 import org.eclipse.jface.viewers.ISelection;
00004 import org.eclipse.jface.viewers.TreeSelection;
00005 import org.eclipse.jface.viewers.TreePath;
00006 import org.eclipse.jface.viewers.TreeViewerColumn;
00007 import org.eclipse.jface.dialogs.Dialog;
00008 
00009 import org.eclipse.ui.IWorkbenchWindow;
00010 import org.eclipse.swt.widgets.Display;
00011 import org.eclipse.swt.widgets.TreeItem;
00012 import org.eclipse.swt.widgets.Composite;
00013 import org.eclipse.swt.widgets.Shell;
00014 import org.eclipse.swt.widgets.TreeColumn;
00015 import org.eclipse.swt.widgets.CoolBar;
00016 
00017 import edu.rice.cs.hpc.data.experiment.Experiment;
00018 import edu.rice.cs.hpc.data.experiment.scope.RootScope;
00019 import edu.rice.cs.hpc.data.experiment.scope.Scope;
00020 import edu.rice.cs.hpc.data.experiment.metric.*;
00021 import edu.rice.cs.hpc.viewer.metric.*;
00022 import edu.rice.cs.hpc.viewer.util.Utilities;
00023 import edu.rice.cs.hpc.viewer.window.Database;
00024 import edu.rice.cs.hpc.viewer.window.ViewerWindow;
00025 import edu.rice.cs.hpc.viewer.window.ViewerWindowManager;
00037 public abstract class ScopeViewActions extends ScopeActions /* implements IToolbarManager*/ {
00038     //-------------- DATA
00039     protected ScopeTreeViewer   treeViewer;         // tree 
00040     protected RootScope         myRootScope;        // the root scope of this view
00041 
00042     // laksono 2009.04.07
00043     protected ScopeZoom objZoom = null;
00044     
00045     public interface IActionType {};
00046     public enum ActionType implements IActionType {ZoomIn, ZoomOut} ;
00047     
00048     protected IWorkbenchWindow objWindow;
00049     
00055     public ScopeViewActions(Shell shell, IWorkbenchWindow window, Composite parent, CoolBar coolbar) {
00056         super(shell, parent, coolbar);
00057         
00058         this.objWindow  = window;
00059         createGUI(parent, coolbar);
00060         // need to instantiate the zoom class after the creation of GUIs
00061         objZoom = new ScopeZoom(treeViewer, (ScopeViewActionsGUI) this.objActionsGUI);
00062     }
00063 
00067     abstract protected  Composite createGUI(Composite parent, CoolBar coolbar);
00068 
00076     public void updateContent(Experiment exp, RootScope scope) {
00077         this.myRootScope = scope;
00078         this.objActionsGUI.updateContent(exp, scope);
00079     }
00080     
00085     public void setTreeViewer(ScopeTreeViewer tree) {
00086         this.treeViewer = tree;
00087         this.objActionsGUI.setTreeViewer(tree);
00088         this.objZoom.setViewer(tree);
00089     }
00090 
00100     private HotCallPath getHotCallPath(TreePath pathItem, TreeItem item, Scope scope, BaseMetric metric, int iLevel) {
00101         if(scope == null || metric == null || item == null)
00102             return null;
00103         // expand the immediate child if necessary
00104         if(!item.getExpanded()) {
00105             this.treeViewer.expandToLevel(pathItem, 1);
00106         }
00107         int iCounts = item.getItemCount();
00108 
00109         HotCallPath objCallPath = new HotCallPath();
00110         // we found the hot call path
00111         objCallPath.path = pathItem; // this.treeViewer.getTreePath(child);
00112         objCallPath.item = item; // child;
00113         objCallPath.node = (Scope) item.getData(); // nodeChild;
00114         objCallPath.is_found = false;
00115 
00116         // singly depth first search
00117         // bug fix: we only drill once !
00118         if (iCounts > 0) {
00119             TreeItem child = item.getItem(0);
00120             Object o = child.getData();
00121             if(o instanceof Scope) {
00122                 // get the child node
00123                 Scope scopeChild = (Scope) o;
00124 
00125                 MetricValue mvParent = metric.getValue(scope);
00126                 MetricValue mvChild = metric.getValue(scopeChild);
00127                 double dParent = MetricValue.getValue(mvParent);
00128                 double dChild = MetricValue.getValue(mvChild);
00129                 
00130                 // simple comparison: if the child has "significant" difference compared to its parent
00131                 // then we consider it as hot path node.
00132                 if(dChild < (ScopeViewActions.fTHRESHOLD * dParent)) {
00133                     objCallPath.is_found = (iLevel>0);
00134                     return objCallPath;
00135                 } else {
00136                     // let's move deeper down the tree
00137                     HotCallPath objHotPath = this.getHotCallPath(this.treeViewer.getTreePath(child), 
00138                             child, scopeChild, metric, iLevel+ 1);
00139                     return objHotPath; 
00140                 }
00141             }
00142         } else {
00143             objCallPath.is_found = true;
00144         }
00145         // if we reach at this statement, then there is no hot call path !
00146         return objCallPath;
00147     }
00148 
00153     private Scope getInputNode() {
00154         Object o = treeViewer.getInput();
00155         Scope child;
00156         if (!(o instanceof Scope)) {
00157                 TreeItem []tiObjects = this.treeViewer.getTree().getItems();
00158                 o = tiObjects[0];
00159                 if(o instanceof Scope)
00160                     child = (Scope)tiObjects[0].getData(); //the 0th item can be the aggregate metric
00161                 else if(tiObjects.length>1)
00162                     // in case of the top row is not a node, the second one MUST BE a node
00163                     child = (Scope)tiObjects[1].getData();
00164                 else
00165                     // Otherwise there is something wrong with the data and the tree
00166                     throw (new java.lang.RuntimeException("ScopeViewActions: tree contains unknown objects"));
00167                 // tricky solution when zoom-out the flattened node
00168                 if(child != null)
00169                     child = (Scope)child.getParent();
00170         } else 
00171             child = (Scope) o;
00172         return child;
00173     }
00174     
00175     
00176     //====================================================================================
00177     // ----------------------------- ACTIONS ---------------------------------------------
00178     //====================================================================================
00179 
00186     private class RestoreMessageThread extends Thread { 
00187         RestoreMessageThread() {
00188             super();
00189         }
00190          public void run() {
00191              try{
00192                  sleep(5000);
00193              } catch(InterruptedException e) {
00194                  e.printStackTrace();
00195              }
00196              // need to run from UI-thread for restoring the background
00197              // without UI-thread we will get SWTException !!
00198              if (objShell != null && !objShell.isDisposed()) {
00199                  Display display = objShell.getDisplay();
00200                  if (display != null && !display.isDisposed()) {
00201                      display.asyncExec(new Runnable() {
00202                          public void run() {
00203                              objActionsGUI.restoreMessage();
00204                          }
00205                      });
00206                  }
00207              }
00208          }
00209      }
00210     
00211     public void showInfoMessage(String sMsg) {
00212         this.objActionsGUI.showInfoMessage(sMsg);
00213         // remove the msg in 5 secs
00214         RestoreMessageThread thrRestoreMessage = new RestoreMessageThread();
00215         thrRestoreMessage.start();
00216     }
00217     
00223     public void showErrorMessage(String strMsg) {
00224         this.objActionsGUI.showErrorMessage(strMsg);
00225         // remove the msg in 5 secs
00226         RestoreMessageThread thrRestoreMessage = new RestoreMessageThread();
00227         thrRestoreMessage.start();
00228 
00229     }
00230     
00234     public void showHotCallPath() {
00235         // find the selected node
00236         ISelection sel = treeViewer.getSelection();
00237         if (!(sel instanceof TreeSelection)) {
00238             System.err.println("SVA: not a TreeSelecton instance");
00239             return;
00240         }
00241         TreeSelection objSel = (TreeSelection) sel;
00242         // get the node
00243         Object o = objSel.getFirstElement();
00244         if (!(o instanceof Scope)) {
00245             showErrorMessage("Please select a scope node.");
00246             return;
00247         }
00248         Scope current = (Scope) o;
00249         // get the item
00250         TreeItem item = this.treeViewer.getTree().getSelection()[0];
00251         // get the path
00252         TreePath []arrPath = objSel.getPaths();
00253         // get the selected metric
00254         TreeColumn colSelected = this.treeViewer.getTree().getSortColumn();
00255         if((colSelected == null) || colSelected.getWidth() == 0) {
00256             // the column is hidden or there is no column sorted
00257             this.showErrorMessage("Please select a column to sort before using this feature.");
00258             return;
00259         }
00260         // get the metric data
00261         Object data = colSelected.getData();
00262         if(data instanceof BaseMetric && item != null) {
00263             BaseMetric metric = (BaseMetric) data;
00264             // find the hot call path
00265             int iLevel = 0;
00266             HotCallPath objHot = this.getHotCallPath(arrPath[0], item, current, metric, iLevel);
00267             this.treeViewer.setSelection(new TreeSelection(objHot.path), true);
00268             if(objHot.is_found == false) {
00269                 this.showErrorMessage("No hot child.");
00270             }
00271         } else {
00272             // It is almost impossible for the jvm to reach this part of branch.
00273             // but if it is the case, it should be a BUG !!
00274             if(data !=null )
00275                 System.err.println("SVA BUG: data="+data.getClass()+" item= " + (item==null? 0 : item.getItemCount()));
00276             else
00277                 this.showErrorMessage("Please select a metric column !");
00278         }
00279     }
00280     
00285     public Scope getSelectedNode() {
00286         ISelection sel = treeViewer.getSelection();
00287         if (!(sel instanceof TreeSelection))
00288             return null;
00289         Object o = ((TreeSelection)sel).getFirstElement();
00290         if (!(o instanceof Scope)) {
00291             return null;
00292         }
00293         return (Scope) o;
00294     }
00298     public void zoomIn() {
00299         // set the new view based on the selected node
00300         Scope current = this.getSelectedNode();
00301         if(current == null)
00302             return;
00303         
00304         // ---------------------- save the current view
00305         Scope objInputNode = this.getInputNode();
00306         objZoom.zoomIn(current, objInputNode);
00307         Scope nodeSelected = this.getSelectedNode();
00308         
00309         registerAction(ActionType.ZoomIn);
00310         
00311         checkStates(nodeSelected);
00312     }
00313     
00317     public void zoomOut() {     
00318         objZoom.zoomOut();
00319         // funny behavior on Windows: they still keep the track of the previously selected item !!
00320         // therefore we need to check again the state of the buttons
00321         Scope nodeSelected = this.getSelectedNode();
00322         
00323         registerAction(ActionType.ZoomOut);
00324 
00325         this.checkStates(nodeSelected);
00326     }
00327     
00332     public ScopeZoom getScopeZoom () {
00333         return this.objZoom;
00334     }
00335     
00340     protected void addTreeColumn(TreeColumn colMetric) {
00341         this.objActionsGUI.addMetricColumns(colMetric);
00342     }
00343     
00347     public void addExtNewMetric() {
00348         
00349         if (this.myRootScope == null)
00350             return;
00351         
00352         final Experiment exp = (Experiment) this.myRootScope.getExperiment();
00353         
00354         // prepare the dialog box
00355         ExtDerivedMetricDlg dlg = new ExtDerivedMetricDlg(this.objShell, exp);
00356 
00357         // display the dialog box
00358         if(dlg.open() == Dialog.OK) {
00359 
00360             final DerivedMetric objMetric = dlg.getMetric();
00361             
00362             exp.addDerivedMetric(objMetric);
00363                         
00364             // get our database file and the experiment index assigned for it
00365             String dbPath = exp.getDefaultDirectory().getAbsolutePath();
00366             ViewerWindow vWin = ViewerWindowManager.getViewerWindow(this.objWindow);
00367             if (vWin == null) {
00368                 System.out.printf("ScopeViewActions.addExtNewMetric: ViewerWindow class not found\n");
00369                 return;
00370             }
00371             int dbNum = vWin.getDbNum(exp);
00372             if (dbNum < 0) {
00373                 System.out.printf("ScopeViewActions.addExtNewMetric: Database for path " + dbPath + " not found\n");
00374                 return;
00375             }
00376 
00377             // get the views created for our database
00378             Database db = vWin.getDb(dbPath);
00379             if (db == null) {
00380                 System.out.printf("ScopeViewActions.addExtNewMetric: Database class not found\n");
00381                 return;
00382             }
00383             
00384             for(BaseScopeView view: db.getExperimentView().getViews()) {
00385                 
00386                 ScopeTreeViewer objTreeViewer = view.getTreeViewer();
00387                 
00388                 objTreeViewer.getTree().setRedraw(false);
00389                 TreeViewerColumn colDerived = objTreeViewer.addTreeColumn(objMetric,  false);
00390                 
00391                 // update the viewer, to refresh its content and invoke the provider
00392                 // bug SWT https://bugs.eclipse.org/bugs/show_bug.cgi?id=199811
00393                 // we need to hold the UI to draw until all the data is available
00394                 // 2012.09.21: do not refresh. It crashes on linux/gtk/ppc
00395                 //objTreeViewer.refresh();  // we refresh to update the data model of the table
00396                 
00397                 // notify the GUI that we have added a new column
00398                 ScopeViewActions objAction = view.getViewActions();
00399                 objAction.addTreeColumn(colDerived.getColumn());
00400                 //this.objActionsGUI.addMetricColumns(colDerived); 
00401                 objTreeViewer.getTree().setRedraw(true);
00402                 // adjust the column width 
00403                 //colDerived.getColumn().pack();
00404                 
00405                 // instead of refresh, we use update which will reset the input and
00406                 //  reinitialize the table. It isn't elegant, but works in all platforms
00407                 view.updateDisplay();
00408             }
00409         }
00410     }
00411 
00415     public void resizeColumns() {
00416         this.objActionsGUI.resizeTableColumns();
00417     }
00418 
00419 
00427     public String getContent(TreeItem []items, String sSeparator) {
00428         StringBuffer sbText = new StringBuffer();
00429         
00430         // get all selected items
00431         for (int i=0; i< items.length; i++) {
00432             TreeItem objItem = items[i];
00433             Object o = objItem.getData();
00434             // let get the metrics if the selected item is a scope node
00435             if (o instanceof Scope) {
00436                 Scope objScope = (Scope) o;
00437                 this.getContent(objScope, sSeparator, sbText);
00438             } else {
00439                 // in case user click the first row, we need a special treatment
00440                 // first row of the table is supposed to be a sub-header, but at the moment we allow user
00441                 //      to do anything s/he wants.
00442                 String sElements[] = (String []) o; 
00443                 sbText.append( "\"" + sElements[0] + "\"" );
00444                 sbText.append( sSeparator ); // separate the node title and the metrics
00445                 sbText.append( this.treeViewer.getTextBasedOnColumnStatus(sElements, sSeparator, 1, 0) );
00446             }
00447             sbText.append(Utilities.NEW_LINE);
00448         }
00449         return sbText.toString();
00450     }
00451     
00459     private void getContent( Scope objScope, String sSeparator, StringBuffer sbText ) {
00460 
00461         final TreeColumn []columns = treeViewer.getTree().getColumns();
00462         sbText.append( "\"" + objScope.getName() + "\"" );
00463         
00464         final Experiment exp = (Experiment) objScope.getExperiment();
00465         
00466         for(int j=1; j<columns.length; j++) 
00467         {
00468             if (columns[j].getWidth()>0) {
00469                 // the column is not hidden
00470                 BaseMetric metric = exp.getMetric(j-1); // bug fix: the metric starts from 0
00471                 sbText.append(sSeparator + metric.getMetricTextValue(objScope));
00472             }
00473         }
00474     }
00475     
00482     public String getContent(TreePath []elements, String sSeparator) {
00483         StringBuffer sbText = new StringBuffer();
00484         for (int i=0; i<elements.length; i++ ) {
00485             TreePath item = elements[i];
00486             int nbSegments = item.getSegmentCount();
00487             for ( int j=0; j<nbSegments; j++ ) {
00488                 Object o = item.getSegment(j);
00489                 if (o instanceof Scope) {
00490                     this.getContent((Scope)o, sSeparator, sbText);
00491                 }
00492             }
00493             sbText.append(Utilities.NEW_LINE);
00494         }
00495         return sbText.toString();
00496     }
00497     
00498     //--------------------------------------------------------------------------
00499     // BUTTONS CHECK
00500     //--------------------------------------------------------------------------
00506     public boolean shouldZoomInBeEnabled(Scope node) {
00507         return this.objZoom.canZoomIn(node);
00508     }
00509     
00515     public boolean shouldZoomOutBeEnabled() {
00516         if (objZoom == null )
00517             return false;
00518         else
00519             return objZoom.canZoomOut();
00520     }
00521     
00522 
00528     public void checkNodeButtons() {
00529         Scope nodeSelected = this.getSelectedNode();
00530         if(nodeSelected == null)
00531             this.objActionsGUI.disableNodeButtons();
00532         else
00533             this.checkStates(nodeSelected);
00534     }
00535     
00539     public void disableButtons () {
00540         objActionsGUI.disableNodeButtons();
00541     }
00542     
00543     
00544     
00552     public abstract void checkStates ( Scope nodeSelected );
00553     
00554     public abstract void checkStates();
00555     
00556     protected abstract void registerAction( IActionType type );
00557     
00558     //===========================================================================
00559     //------------------- ADDITIONAL CLASSES ------------------------------------
00560     //===========================================================================
00566     class HotCallPath {
00567         // the path of the item
00568         public TreePath path;
00569         // the item
00570         public TreeItem item;
00571         // the node associated
00572         public Scope node;
00573         
00574         // indicate if a hot path is found or not
00575         public boolean is_found = false;
00576     }
00577 
00578 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1