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
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
00057
00058
00059 public ProcedureClassDialog(Shell parentShell, ProcedureClassMap data ) {
00060 super(parentShell);
00061 this.data = data;
00062 }
00063
00064
00065
00066
00067
00068
00069 public boolean isModified() {
00070 return isModified;
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 private void updateData(String proc, String procClass, RGB rgb) {
00082
00083 data.put(proc, procClass, rgb);
00084
00085
00086 cacheImages.put(proc, rgb);
00087
00088 isModified = true;
00089 tableViewer.setInput(data.getEntrySet());
00090 }
00091
00092
00093
00094
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
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
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
00153
00154 ProcedureClassDialog.this.data.remove(proc);
00155
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
00178
00179
00180 tableViewer = new TableViewer(composite, SWT.MULTI | SWT.VIRTUAL);
00181
00182
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
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
00237
00238
00239 protected void setShellStyle(int newShellStyle) {
00240
00241 super.setShellStyle(newShellStyle | SWT.RESIZE );
00242 }
00243
00244
00245
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
00257
00258 private void refresh() {
00259 tableViewer.setInput(data.getEntrySet());
00260 tableViewer.refresh();
00261 checkButton();
00262 }
00263
00264
00265
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
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
00294
00295
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
00319
00320
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
00334
00335
00336 static private enum Direction {ASC, DESC};
00337 static private enum COLUMN_ID {CLASS, PROCEDURE};
00338
00339
00340
00341
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
00381
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
00399
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
00435
00436
00437 public String getText(Object element) {
00438 return ProcedureClassDialog.this.getProcedureName(element);
00439 }
00440
00441
00442
00443
00444
00445 public Image getImage(Object element) {
00446 String key = ProcedureClassDialog.this.getProcedureName(element);
00447 if (key != UnknownData) {
00448
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
00460
00461
00462 public void dispose() {
00463
00464 if (cacheImages != null) {
00465 cacheImages.dispose();
00466 }
00467
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
00505
00506
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 }