ProcedureClassDialog.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.traceviewer.ui;
00002 
00003 import java.util.Collection;
00004 import java.util.HashMap;
00005 import java.util.Iterator;
00006 import java.util.Map.Entry;
00007 
00008 import org.eclipse.jface.dialogs.Dialog;
00009 import org.eclipse.jface.dialogs.MessageDialog;
00010 import org.eclipse.jface.dialogs.TitleAreaDialog;
00011 import org.eclipse.jface.layout.GridDataFactory;
00012 import org.eclipse.jface.layout.GridLayoutFactory;
00013 import org.eclipse.jface.viewers.ArrayContentProvider;
00014 import org.eclipse.jface.viewers.ColumnLabelProvider;
00015 import org.eclipse.jface.viewers.IStructuredSelection;
00016 import org.eclipse.jface.viewers.TableViewer;
00017 import org.eclipse.jface.viewers.TableViewerColumn;
00018 import org.eclipse.jface.viewers.Viewer;
00019 import org.eclipse.jface.viewers.ViewerComparator;
00020 import org.eclipse.swt.SWT;
00021 import org.eclipse.swt.events.SelectionAdapter;
00022 import org.eclipse.swt.events.SelectionEvent;
00023 import org.eclipse.swt.graphics.Image;
00024 import org.eclipse.swt.graphics.RGB;
00025 import org.eclipse.swt.layout.FillLayout;
00026 import org.eclipse.swt.widgets.Button;
00027 import org.eclipse.swt.widgets.Composite;
00028 import org.eclipse.swt.widgets.Control;
00029 import org.eclipse.swt.widgets.Display;
00030 import org.eclipse.swt.widgets.Shell;
00031 import org.eclipse.swt.widgets.Table;
00032 import org.eclipse.swt.widgets.TableColumn;
00033 
00034 import edu.rice.cs.hpc.common.util.ProcedureClassData;
00035 import edu.rice.cs.hpc.traceviewer.data.graph.ColorTable;
00036 import edu.rice.cs.hpc.traceviewer.data.util.ProcedureClassMap;
00037 
00038 /*********************************
00039  * 
00040  * Dialog window to show the class and the procedure associated
00041  *
00042  */
00043 public class ProcedureClassDialog extends TitleAreaDialog {
00044 
00045     final private String UnknownData = "unknown";
00046     
00047     private TableViewer tableViewer ;
00048     final private ProcedureClassMap data;
00049     
00050     private Button btnRemove;
00051     private Button btnEdit;
00052     
00053     private boolean isModified;
00054     
00055     /***
00056      * constructor 
00057      * @param parentShell
00058      */
00059     public ProcedureClassDialog(Shell parentShell, ProcedureClassMap data ) {
00060         super(parentShell);
00061         this.data = data;
00062     }
00063 
00064     /***
00065      * return true if the data has been modified
00066      * 
00067      * @return
00068      */
00069     public boolean isModified() {
00070         return isModified;
00071     }
00072     
00073     /****
00074      * update data in the map and in the table 
00075      * it is unfortunate we have two storage of the same data.
00076      * 
00077      * @param proc
00078      * @param procClass
00079      * @param rgb
00080      */
00081     private void updateData(String proc, String procClass, RGB rgb) {
00082         // update the map
00083         data.put(proc, procClass, rgb);
00084         
00085         // update the table of colors
00086         cacheImages.put(proc, rgb);
00087         
00088         isModified = true;
00089         tableViewer.setInput(data.getEntrySet());
00090     }
00091     
00092     /*
00093      * (non-Javadoc)
00094      * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
00095      */
00096     protected Control createDialogArea(Composite parent) {
00097         
00098         final Composite composite = new Composite(parent, SWT.BORDER);
00099         GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
00100         GridLayoutFactory.fillDefaults().numColumns(1).applyTo(composite);
00101         
00102         //-----------------------------------------------------------------
00103         // Toolbar area
00104         //-----------------------------------------------------------------
00105         
00106         final Composite areaAction = new Composite( composite, SWT.NULL );
00107         
00108         final Button btnAdd   = new Button(areaAction, SWT.PUSH | SWT.FLAT);
00109         btnAdd.setText("Add");
00110         btnAdd.setToolTipText("Add a procedure-color pair");
00111         btnAdd.addSelectionListener( new SelectionAdapter() {
00112 
00113             public void widgetSelected(SelectionEvent e) {
00114                 ProcedureMapDetailDialog dlg = new ProcedureMapDetailDialog(getShell(), 
00115                         "Add a new procedure-color map", "", "", null);
00116                 if (dlg.open() == Dialog.OK) {
00117                     // update the map and the table
00118                     ProcedureClassDialog.this.updateData(dlg.getProcedure(), dlg.getDescription(), dlg.getRGB());
00119                 }
00120             }
00121         });
00122         
00123         btnRemove   = new Button(areaAction, SWT.PUSH| SWT.FLAT);
00124         btnRemove.setText("Delete");
00125         btnRemove.setToolTipText("Remove a selected procedure-color pair");
00126         btnRemove.setEnabled(false);
00127         btnRemove.addSelectionListener(new SelectionAdapter() {
00128 
00129             public void widgetSelected(SelectionEvent e) {
00130                 remove(e);
00131             }
00132         });
00133         
00134         btnEdit   = new Button(areaAction, SWT.PUSH| SWT.FLAT);
00135         btnEdit.setText("Edit");
00136         btnEdit.setToolTipText("Edit a selected procedure-color pair");
00137         btnEdit.setEnabled(false);
00138         btnEdit.addSelectionListener( new SelectionAdapter() {
00139 
00140             public void widgetSelected(SelectionEvent e) 
00141             {
00142                 IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
00143                 Object item = selection.getFirstElement();
00144                 if (item instanceof Entry<?,?>) {
00145                     final String proc = (String)((Entry<?, ?>) item).getKey();
00146                     final ProcedureClassData pclass = (ProcedureClassData) 
00147                             ((Entry<?, ?>)item).getValue();
00148 
00149                     ProcedureMapDetailDialog dlg = new ProcedureMapDetailDialog(getShell(), 
00150                             "Edit procedure-color map", proc, pclass.getProcedureClass(), pclass.getRGB());
00151                     if (dlg.open() == Dialog.OK) {
00152                         // update: remove the old data, and then insert a new one
00153                         // Attention: these two actions have to be atomic !
00154                         ProcedureClassDialog.this.data.remove(proc);
00155                         // update the map and the table
00156                         ProcedureClassDialog.this.updateData(dlg.getProcedure(), dlg.getDescription(), dlg.getRGB());
00157                     }
00158                 }
00159             }
00160         });
00161         
00162         final Button btnReset = new Button(areaAction, SWT.PUSH | SWT.FLAT);
00163         btnReset.setText("Reset");
00164         btnReset.setToolTipText("Reset to the default configuration");
00165         btnReset.addSelectionListener( new SelectionAdapter() {
00166             public void widgetSelected(SelectionEvent e) {
00167                 ProcedureClassDialog.this.data.clear();
00168                 ProcedureClassDialog.this.data.initDefault();
00169                 ProcedureClassDialog.this.tableViewer.setInput(data.getEntrySet());
00170             }
00171         });
00172         
00173         GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).grab(true, false).applyTo(areaAction);
00174         GridLayoutFactory.fillDefaults().numColumns(4).applyTo(areaAction);
00175         
00176         //-----------------------------------------------------------------
00177         // table area
00178         //-----------------------------------------------------------------
00179         
00180         tableViewer = new TableViewer(composite, SWT.MULTI | SWT.VIRTUAL);
00181 
00182         // set procedure column
00183         final TableViewerColumn colProcedure = new TableViewerColumn(tableViewer, SWT.LEFT);
00184         TableColumn col = colProcedure.getColumn();
00185         col.setText("Procedure");
00186         col.setResizable(true);
00187         col.setMoveable(true);
00188         col.setWidth(220);
00189         
00190         colProcedure.setLabelProvider( new ClassColumnLabelProvider() );
00191         new ColumnViewerSorter(tableViewer, colProcedure, COLUMN_ID.PROCEDURE);
00192         
00193         // set description column
00194         final TableViewerColumn colClass = new TableViewerColumn(tableViewer, SWT.LEFT);
00195         col = colClass.getColumn();
00196         col.setText("Description");
00197         col.setResizable(true);
00198         col.setMoveable(true);
00199         col.setWidth(150);
00200         
00201         colClass.setLabelProvider( new ColumnLabelProvider(){
00202             public String getText(Object element) {
00203                 return ProcedureClassDialog.this.getClassName(element);
00204             }
00205         });
00206         ColumnViewerSorter sortColClass = new ColumnViewerSorter(tableViewer, colClass, COLUMN_ID.CLASS);
00207         
00208         tableViewer.setUseHashlookup(true);
00209         
00210         tableViewer.setContentProvider(new ArrayContentProvider());
00211 
00212         final Table table = tableViewer.getTable();
00213         table.setHeaderVisible(true);
00214         table.setLinesVisible(true);
00215         table.pack();
00216         
00217         GridDataFactory.fillDefaults().grab(true, true).applyTo(table);
00218         GridLayoutFactory.fillDefaults().numColumns(1).applyTo( table );
00219         
00220         tableViewer.setInput(data.getEntrySet());
00221         tableViewer.getTable().addSelectionListener(new SelectionAdapter(){
00222             public void widgetSelected(SelectionEvent e) {
00223                 checkButton();
00224             }
00225         });
00226         
00227         sortColClass.setSorter(sortColClass, Direction.ASC);
00228         setTitle("Procedure and color mapping");
00229         setMessage("Add, remove or edit a procedure-color mapping");
00230         getShell().setText("Procedure-color mapping");
00231         
00232         return composite;
00233     }
00234     
00235     /*
00236      * (non-Javadoc)
00237      * @see org.eclipse.jface.window.Window#setShellStyle(int)
00238      */
00239     protected void setShellStyle(int newShellStyle) {
00240 
00241         super.setShellStyle(newShellStyle | SWT.RESIZE );
00242     } 
00243     
00244     /***
00245      * check and set button status
00246      */
00247     private void checkButton() {
00248         
00249         int numSelection = tableViewer.getTable().getSelectionCount();
00250 
00251         btnEdit.setEnabled(numSelection == 1);      
00252         btnRemove.setEnabled(numSelection>0);
00253     }
00254     
00255     /***
00256      * refresh the data and reset the table
00257      */
00258     private void refresh() {
00259         tableViewer.setInput(data.getEntrySet());
00260         tableViewer.refresh();
00261         checkButton();
00262     }
00263     /***
00264      * removing selected element in the table
00265      * @param event
00266      */
00267     private void remove(SelectionEvent event) {
00268         IStructuredSelection selection = (IStructuredSelection) this.tableViewer.getSelection();
00269         Object sels[] = selection.toArray();
00270         
00271         boolean cont = false;
00272         if (sels != null) {
00273             if (sels.length>1) {
00274                 cont = MessageDialog.openQuestion(getShell(), "Removing " + sels.length+ " mappings", 
00275                         "Are you sure to remove " + sels.length + " mapping elements ?");
00276             } else {
00277                 cont = MessageDialog.openQuestion(getShell(), "Removing an element", 
00278                         "Are you sure to remove this mapping element ?" );
00279             }
00280         }
00281         if (!cont)
00282             return;
00283         
00284         // remove the data
00285         for (Object o: sels) {
00286             if (o instanceof Entry<?,?>) {
00287                 Entry<?,?> elem = (Entry<?,?>) o;
00288                 data.remove((String) elem.getKey());
00289 
00290                 isModified = true;
00291             }
00292         }
00293         // remove the color table
00294         
00295         // refresh the table
00296         refresh();
00297     }
00298     
00299     
00305     private String getClassName(Object element) {
00306         if (element instanceof Entry<?,?>) {
00307             final Entry<?,?> oLine = (Entry<?, ?>) element;
00308             final Object o = oLine.getValue();
00309             if (o instanceof ProcedureClassData) {
00310                 final ProcedureClassData objValue = (ProcedureClassData) oLine.getValue();
00311                 return objValue.getProcedureClass();
00312             }
00313         }
00314         return UnknownData; 
00315     }
00316     
00317     /***
00318      * retrieve the procedure name
00319      * @param element
00320      * @return
00321      */
00322     private String getProcedureName(Object element) {
00323         if (element instanceof Entry<?,?>) {
00324             final Entry<?,?> oLine = (Entry<?, ?>) element;
00325             return (String) oLine.getKey();
00326         }
00327         return UnknownData;
00328     }
00329     
00330     
00331     
00332     /***
00333      * enumeration type to determine the sorting: ascending or descending 
00334      *
00335      */
00336     static private enum Direction {ASC, DESC};
00337     static private enum COLUMN_ID {CLASS, PROCEDURE};
00338     
00339     /***
00340      * 
00341      * Sorting a column
00342      *
00343      */
00344     private class ColumnViewerSorter extends ViewerComparator
00345     {
00346         private final TableViewerColumn column;
00347         private final TableViewer viewer;
00348         private Direction direction = Direction.ASC;
00349         private final COLUMN_ID colid;
00350         
00357         public ColumnViewerSorter(TableViewer viewer, TableViewerColumn column, COLUMN_ID columnID) {
00358             this.viewer = viewer;
00359             this.column = column;
00360             this.colid = columnID;
00361             
00362             column.getColumn().addSelectionListener( new SelectionAdapter() {
00363 
00364                 public void widgetSelected(SelectionEvent e) {
00365                     ViewerComparator comparator = ColumnViewerSorter.this.viewer.getComparator();
00366                     if ( comparator != null ) {
00367                         if (comparator == ColumnViewerSorter.this) {
00368                             Direction dir = ColumnViewerSorter.this.direction;
00369                             dir = (dir==Direction.ASC? Direction.DESC : Direction.ASC);
00370                             setSorter (ColumnViewerSorter.this, dir);
00371                             return;
00372                         }
00373                     }
00374                     setSorter (ColumnViewerSorter.this, Direction.ASC);
00375                 }
00376             });
00377         }
00378         
00379         /*
00380          * (non-Javadoc)
00381          * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
00382          */
00383         public int compare(Viewer viewer, Object e1, Object e2) {
00384             final String elem1 = (colid == COLUMN_ID.CLASS ? 
00385                     ProcedureClassDialog.this.getClassName(e1) : 
00386                     ProcedureClassDialog.this.getProcedureName(e1));
00387             final String elem2 = (colid == COLUMN_ID.CLASS ? 
00388                     ProcedureClassDialog.this.getClassName(e2) : 
00389                     ProcedureClassDialog.this.getProcedureName(e2));
00390             
00391             int k = (direction == Direction.ASC ? 1 : -1 );
00392             int res = k * super.compare(viewer, elem1, elem2);
00393             return res;
00394         }
00395 
00396         /****
00397          * 
00398          * @param sorter
00399          * @param dir
00400          */
00401         public void setSorter(ColumnViewerSorter sorter, Direction dir) {
00402             column.getColumn().getParent().setSortColumn(column.getColumn());
00403             sorter.direction = dir;
00404             if( direction == Direction.ASC ) {
00405                 column.getColumn().getParent().setSortDirection(SWT.DOWN);
00406             } else {
00407                 column.getColumn().getParent().setSortDirection(SWT.UP);
00408             }
00409             
00410             if( viewer.getComparator() == sorter ) {
00411                 viewer.refresh();
00412             } else {
00413                 viewer.setComparator(sorter);
00414             }
00415             ProcedureClassDialog.this.checkButton();
00416         }
00417     }
00418     
00419     private ImageCache cacheImages;
00420     
00426     private class ClassColumnLabelProvider extends ColumnLabelProvider 
00427     {
00428         
00429         public ClassColumnLabelProvider() {
00430             cacheImages = new ImageCache();
00431         }
00432         
00433         /*
00434          * (non-Javadoc)
00435          * @see org.eclipse.jface.viewers.ColumnLabelProvider#getText(java.lang.Object)
00436          */
00437         public String getText(Object element) {
00438             return ProcedureClassDialog.this.getProcedureName(element);
00439         }
00440         
00441         /*
00442          * (non-Javadoc)
00443          * @see org.eclipse.jface.viewers.ColumnLabelProvider#getImage(java.lang.Object)
00444          */
00445         public Image getImage(Object element) {
00446             String key = ProcedureClassDialog.this.getProcedureName(element);
00447             if (key != UnknownData) {
00448                 // procedure exist
00449                 final ProcedureClassData val = ProcedureClassDialog.this.data.get(key);
00450                 if (val != null) {
00451                     Image image = cacheImages.get(key, val.getRGB());
00452                     return image;
00453                 }
00454             }
00455             return null;
00456         }
00457         
00458         /*
00459          * (non-Javadoc)
00460          * @see org.eclipse.jface.viewers.BaseLabelProvider#dispose()
00461          */
00462         public void dispose() {
00463             // dispose images before disposing the parent
00464             if (cacheImages != null) {
00465                 cacheImages.dispose();
00466             }
00467             // now, dispose the parent
00468             super.dispose();
00469         } 
00470     }
00471     
00472     private class ImageCache {
00473         private HashMap<String,Image> images;
00474 
00475         public ImageCache() {
00476             images = new HashMap<String, Image>(10);
00477         }
00478         
00479         public Image get(String name, RGB rgb) {
00480             Image image = images.get(name);
00481             if (image == null) {
00482                 image = put(name, rgb);
00483             }
00484             return image;
00485         }
00486         
00487         public Image put(String name, RGB rgb) {
00488             Image image = ColorTable.createImage(ProcedureClassDialog.this.getShell().getDisplay(), rgb);
00489             images.put(name, image);
00490             return image;
00491         }
00492         
00493         public void dispose() {
00494             Collection<Image> col = images.values();
00495             Iterator<Image> iterator = col.iterator();
00496             while(iterator.hasNext()) {
00497                 Image img = iterator.next();
00498                 img.dispose();
00499             }
00500         }
00501     }
00502     
00503     /***
00504      * unit test
00505      * 
00506      * @param argv
00507      */
00508     static public void main(String argv[]) {
00509         Display display = new Display ();
00510         Shell shell = new Shell(display);
00511         shell.setLayout(new FillLayout());
00512         
00513         shell.open();
00514         
00515         ProcedureClassMap pcMap = new ProcedureClassMap(display);
00516         ProcedureClassDialog dlg = new ProcedureClassDialog(shell, pcMap );
00517 
00518         if ( dlg.open() == Dialog.OK ) {
00519             if (dlg.isModified()) {
00520                 pcMap.save();
00521             }
00522         }
00523         
00524         while (!shell.isDisposed()) {
00525             if (!display.readAndDispatch())
00526                 display.sleep();
00527         }
00528         
00529         display.dispose();
00530     }
00531 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1