AttributesTabControl.java
001 /*
002  *
003  * Licensed to the Apache Software Foundation (ASF) under one
004  * or more contributor license agreements.  See the NOTICE file
005  * distributed with this work for additional information
006  * regarding copyright ownership.  The ASF licenses this file
007  * to you under the Apache License, Version 2.0 (the
008  * "License"); you may not use this file except in compliance
009  * with the License.  You may obtain a copy of the License at
010  
011  *   http://www.apache.org/licenses/LICENSE-2.0
012  
013  * Unless required by applicable law or agreed to in writing,
014  * software distributed under the License is distributed on an
015  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016  * KIND, either express or implied.  See the License for the
017  * specific language governing permissions and limitations
018  * under the License.
019  *
020  */
021 package org.apache.qpid.management.ui.views;
022 
023 import static org.apache.qpid.management.ui.Constants.*;
024 
025 import org.apache.qpid.management.ui.ApplicationRegistry;
026 import org.apache.qpid.management.ui.ManagedBean;
027 import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
028 import org.apache.qpid.management.ui.jmx.MBeanUtility;
029 import org.apache.qpid.management.ui.model.AttributeData;
030 import org.apache.qpid.management.ui.model.ManagedAttributeModel;
031 import org.eclipse.jface.viewers.IColorProvider;
032 import org.eclipse.jface.viewers.IFontProvider;
033 import org.eclipse.jface.viewers.ISelectionChangedListener;
034 import org.eclipse.jface.viewers.IStructuredContentProvider;
035 import org.eclipse.jface.viewers.IStructuredSelection;
036 import org.eclipse.jface.viewers.ITableLabelProvider;
037 import org.eclipse.jface.viewers.LabelProvider;
038 import org.eclipse.jface.viewers.SelectionChangedEvent;
039 import org.eclipse.jface.viewers.TableViewer;
040 import org.eclipse.jface.viewers.Viewer;
041 import org.eclipse.jface.viewers.ViewerSorter;
042 import org.eclipse.swt.SWT;
043 import org.eclipse.swt.events.DisposeEvent;
044 import org.eclipse.swt.events.DisposeListener;
045 import org.eclipse.swt.events.KeyEvent;
046 import org.eclipse.swt.events.KeyListener;
047 import org.eclipse.swt.events.MouseEvent;
048 import org.eclipse.swt.events.MouseListener;
049 import org.eclipse.swt.events.MouseMoveListener;
050 import org.eclipse.swt.events.MouseTrackListener;
051 import org.eclipse.swt.events.PaintEvent;
052 import org.eclipse.swt.events.PaintListener;
053 import org.eclipse.swt.events.SelectionAdapter;
054 import org.eclipse.swt.events.SelectionEvent;
055 import org.eclipse.swt.graphics.Color;
056 import org.eclipse.swt.graphics.Font;
057 import org.eclipse.swt.graphics.Image;
058 import org.eclipse.swt.graphics.Point;
059 import org.eclipse.swt.graphics.Rectangle;
060 import org.eclipse.swt.layout.FillLayout;
061 import org.eclipse.swt.layout.GridData;
062 import org.eclipse.swt.layout.GridLayout;
063 import org.eclipse.swt.widgets.Button;
064 import org.eclipse.swt.widgets.Canvas;
065 import org.eclipse.swt.widgets.Composite;
066 import org.eclipse.swt.widgets.Control;
067 import org.eclipse.swt.widgets.Display;
068 import org.eclipse.swt.widgets.Event;
069 import org.eclipse.swt.widgets.Label;
070 import org.eclipse.swt.widgets.Listener;
071 import org.eclipse.swt.widgets.Shell;
072 import org.eclipse.swt.widgets.TabFolder;
073 import org.eclipse.swt.widgets.Table;
074 import org.eclipse.swt.widgets.TableColumn;
075 import org.eclipse.swt.widgets.TableItem;
076 import org.eclipse.swt.widgets.Text;
077 import org.eclipse.ui.forms.widgets.Form;
078 import org.eclipse.ui.forms.widgets.FormToolkit;
079 
080 
081 /**
082  * Creates controller composite for the attribute's tab. 
083  @author Bhupendra Bhardwaj
084  */
085 public class AttributesTabControl extends TabControl
086 {    
087     private FormToolkit  _toolkit;
088     private Form _form;    
089     private Table _table = null;
090     private TableViewer _tableViewer = null;
091     private static final int[] tableWidths = new int[] {300300};
092     
093     private Composite _tableComposite = null;
094     private Composite _buttonsComposite = null;
095     
096     private DisposeListener tableDisposeListener = new DisposeListenerImpl();
097     final Image image;
098     private Button _detailsButton  = null;
099     private Button _editButton  = null;
100     private Button _graphButton = null;
101     private Button _refreshButton = null;
102     private boolean disableEditing = false;
103     
104     private static final String MAX_VALUE = "MaxValue";
105     private static final String GRAPH_VALUES = "GraphValues";
106     private int GRAPH_WIDTH = 700;
107     private int GRAPH_HEIGHT = 450;
108     private int GRAPH_ITEM_GAP = 100;
109     private int startX = 80;
110     private int startY = 60;
111     
112     public AttributesTabControl(TabFolder tabFolder)
113     {
114         super(tabFolder);
115         _toolkit = new FormToolkit(_tabFolder.getDisplay());
116         _form = _toolkit.createForm(_tabFolder);
117         GridLayout gridLayout = new GridLayout(2false);      
118         gridLayout.marginWidth = 0;
119         gridLayout.marginHeight = 0;       
120         _form.getBody().setLayout(gridLayout);
121         _tableComposite = _toolkit.createComposite(_form.getBody());
122         _tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
123         _tableComposite.setLayout(new GridLayout());
124         _buttonsComposite = _toolkit.createComposite(_form.getBody());
125         _buttonsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true));
126         _buttonsComposite.setLayout(new GridLayout());
127         
128         image = Display.getCurrent().getSystemImage(SWT.ICON_INFORMATION);
129         createWidgets();         
130     }
131     
132     /**
133      @see TabControl#getControl()
134      */
135     public Control getControl()
136     {
137         return _form;
138     }
139     
140     /**
141      * Creates required widgets for Attribute's tab
142      */
143     protected void createWidgets()
144     {
145         createTable();
146         createTableViewer();                
147         createButtons();        
148         addTableListeners();        
149     }
150     
151     /**
152      * Creates table for listing the MBean attributes
153      */
154     private void createTable()
155     {  
156         _table = _toolkit.createTable(_tableComposite,  SWT.FULL_SELECTION)
157         GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
158         _table.setLayoutData(gridData);
159         
160         for (int i = 0; i < ATTRIBUTE_TABLE_TITLES.length; ++i)
161         {
162             final TableColumn column = new TableColumn(_table, SWT.NONE);
163             column.setText(ATTRIBUTE_TABLE_TITLES[i]);
164             column.setWidth(tableWidths[i]);
165             column.setResizable(false);
166         }
167         
168         _table.setLinesVisible (true);
169         _table.setHeaderVisible (true);
170     }
171     
172     /**
173      * Creates tableviewer for the attribute's table
174      */
175     private void createTableViewer()
176     {
177         _tableViewer = new TableViewer(_table);
178         _tableViewer.setUseHashlookup(true);
179         _tableViewer.setColumnProperties(ATTRIBUTE_TABLE_TITLES);
180         _tableViewer.setContentProvider(new ContentProviderImpl());
181         _tableViewer.setLabelProvider(new LabelProviderImpl());
182         _tableViewer.setSorter(new ViewerSorterImpl());
183     }
184     
185     private void createButtons()
186     {
187         addDetailsButton();
188         addEditButton();
189         addGraphButton();
190         addRefreshButton();
191     }
192       
193     private void addDetailsButton()
194     {
195         // Create and configure the button for attribute details
196         _detailsButton = _toolkit.createButton(_buttonsComposite, BUTTON_DETAILS, SWT.PUSH | SWT.CENTER);
197         _detailsButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
198         GridData gridData = new GridData(SWT.CENTER, SWT.TOP, false, false);
199         gridData.widthHint = 80;
200         _detailsButton.setLayoutData(gridData);
201         _detailsButton.addSelectionListener(new SelectionAdapter()
202             {
203                 public void widgetSelected(SelectionEvent e)
204                 {
205                     disableEditing = true;
206                     int index = _table.getSelectionIndex();
207                     TableItem item = _table.getItem(index);                   
208                     createDetailsPopup((AttributeData)item.getData());
209                     disableEditing = false;
210                     setFocus();
211                 }
212             });
213     }
214     
215     /**
216      * Creates the button for editing attributes.
217      */
218     private void addEditButton()
219     {
220         // Create and configure the button for editing attribute
221         _editButton = _toolkit.createButton(_buttonsComposite, BUTTON_EDIT_ATTRIBUTE, SWT.PUSH | SWT.CENTER);
222         _editButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
223         GridData gridData = new GridData(SWT.CENTER, SWT.TOP, false, false);
224         gridData.widthHint = 80;
225         _editButton.setLayoutData(gridData);
226         _editButton.addSelectionListener(new SelectionAdapter()
227             {
228                 public void widgetSelected(SelectionEvent e)
229                 {
230                     int index = _table.getSelectionIndex();
231                     TableItem item = _table.getItem(index);
232                     createDetailsPopup((AttributeData)item.getData());
233                     setFocus();
234                 }
235             });
236     }
237     
238     /**
239      * Creates the button for viewing Graphs
240      */ 
241     private void addGraphButton()
242     {
243         _graphButton = _toolkit.createButton(_buttonsComposite, BUTTON_GRAPH, SWT.PUSH | SWT.CENTER);
244         _graphButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
245         GridData gridData = new GridData(SWT.CENTER, SWT.TOP, false, false);
246         gridData.widthHint = 80;
247         _graphButton.setLayoutData(gridData);
248         _graphButton.addSelectionListener(new SelectionAdapter()
249             {
250                 public void widgetSelected(SelectionEvent event)
251                 {
252                     int selectionIndex = _table.getSelectionIndex();
253                     AttributeData data = (AttributeData)_table.getItem(selectionIndex).getData();
254                     createGraph(data);
255                     setFocus();
256                 }
257             });
258     }
259     
260     /**
261      * Creates the "Refresh" button
262      */
263     private void addRefreshButton()
264     {    
265         _refreshButton = _toolkit.createButton(_buttonsComposite, BUTTON_REFRESH, SWT.PUSH | SWT.CENTER);
266 
267         _refreshButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
268         GridData gridData = new GridData(SWT.CENTER, SWT.TOP, false, false);
269         gridData.widthHint = 80;
270         _refreshButton.setLayoutData(gridData);
271         _refreshButton.addSelectionListener(new SelectionAdapter()
272             {
273                 public void widgetSelected(SelectionEvent e)
274                 {
275                     try
276                     {
277                         // refresh the attributes list                
278                         refresh(_mbean);
279                     }
280                     catch (Exception ex)
281                     {
282                         MBeanUtility.handleException(_mbean, ex);
283                     }
284                     
285                 }
286             });
287     }
288 
289     private void addTableListeners()
290     {
291         _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
292             public void selectionChanged(SelectionChangedEvent evt)
293             {
294                 IStructuredSelection ss = (IStructuredSelection)evt.getSelection();
295                 checkForEnablingButtons((AttributeData)ss.getFirstElement());
296             }
297         });
298         
299         MouseListenerImpl listener = new MouseListenerImpl();
300         _tableViewer.getTable().addMouseTrackListener(listener);
301         _tableViewer.getTable().addMouseMoveListener(listener);
302         _tableViewer.getTable().addMouseListener(listener);
303         
304         _table.addDisposeListener(tableDisposeListener);
305         
306         // _table is equal to _tableViewer.getControl()
307         _table.addListener(SWT.MeasureItem, new Listener() {  
308             public void handleEvent(Event event)
309             {    
310                 event.height = event.gc.getFontMetrics().getHeight()  3/2;
311             }  
312         })
313     }
314     
315     /**
316      * Listeners implementation class for showing table tooltip
317      @author Bhupendra Bhardwaj
318      */
319     private class MouseListenerImpl implements MouseTrackListener, MouseMoveListener, KeyListener, MouseListener                                              
320     {
321         Shell tooltipShell = null;
322         Label tooltipLabel = null;
323         public void mouseHover(MouseEvent event)
324         {
325             TableItem item = _table.getItem (new Point (event.x, event.y));
326             
327             if (item != null)
328             {
329                 AttributeData data = (AttributeData)item.getData();
330                 if (tooltipShell != null  && !tooltipShell.isDisposed ()) tooltipShell.dispose ();
331                 tooltipShell = new Shell(_table.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
332                 tooltipShell.setBackground(event.display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
333                 FillLayout layout = new FillLayout();
334                 layout.marginWidth = 2;
335                 tooltipShell.setLayout(layout);
336                 tooltipLabel = new Label(tooltipShell, SWT.NONE);
337                 tooltipLabel.setForeground(event.display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
338                 tooltipLabel.setBackground(event.display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
339                 tooltipLabel.setText(data.getDescription());
340                 tooltipLabel.setData("_TABLEITEM", item);
341                 tooltipLabel.addListener(SWT.MouseExit, tooltipLabelListener);
342                 tooltipLabel.addListener(SWT.MouseDown, tooltipLabelListener);
343                 Point size = tooltipShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
344                 Rectangle rect = item.getBounds(0);
345                 Point pt = _table.toDisplay(rect.x, rect.y);
346                 tooltipShell.setBounds(pt.x, pt.y, size.x, size.y);
347                 tooltipShell.setVisible(true);
348             }
349         }
350         public void mouseEnter(MouseEvent e)
351         {
352         }
353         public void mouseExit(MouseEvent e)
354         {
355         }
356         
357         // MouseMoveListener implementation
358         public void mouseMove(MouseEvent event)
359         {
360             if (tooltipShell == null)
361                 return;
362             
363             tooltipShell.dispose();
364             tooltipShell = null;
365             tooltipLabel = null;
366         }
367         
368         // KeyListener implementation
369         public void keyPressed(KeyEvent e)
370         {
371             if (tooltipShell == null)
372                 return;
373             
374             tooltipShell.dispose();
375             tooltipShell = null;
376             tooltipLabel = null;
377         }     
378         public void keyReleased(KeyEvent e)
379         {
380             
381         }
382         
383         // MouseListener implementation
384         public void mouseDoubleClick(MouseEvent event)
385         {
386             if (tooltipShell != null)
387             {
388                 tooltipShell.dispose();
389                 tooltipShell = null;
390                 tooltipLabel = null;
391             }
392             Table table = (Table)event.getSource();
393             int selectionIndex = table.getSelectionIndex();
394             AttributeData data = (AttributeData)table.getItem(selectionIndex).getData();
395             createDetailsPopup(data);
396         }
397         public void mouseDown(MouseEvent e)
398         {
399             if (tooltipShell != null)
400             {
401                 tooltipShell.dispose();
402                 tooltipShell = null;
403                 tooltipLabel = null;
404             }
405         }
406         public void mouseUp(MouseEvent e)
407         {
408             
409         }
410     // end of MouseListenerImpl
411     
412     /**
413      * Creates pop-up window for showing attribute details
414      @param data - Selectes attribute
415      */
416     public void createDetailsPopup(AttributeData data)
417     {
418         int width = 500;
419         int height = 250;
420         if (!isSimpleType(data.getValue()))
421         {
422             width = 650;
423             height = 450;
424         }
425         
426         Display display = Display.getCurrent();
427         Shell shell = ViewUtility.createPopupShell(ATTRIBUTE, width, height);
428         createDetailsPopupContents(shell, data);
429 
430         shell.open();
431         while (!shell.isDisposed())
432         {
433             if (!display.readAndDispatch())
434             {
435                 display.sleep();
436             }
437         }
438         shell.dispose();
439     }
440     
441     /**
442      * Listener class for table tooltip label
443      */
444     final Listener tooltipLabelListener = new Listener ()
445     {
446         public void handleEvent (Event event)
447         {
448             Label label = (Label)event.widget;
449             Shell shell = label.getShell();
450             switch (event.type)
451             {
452                 case SWT.MouseDown:
453                     Event e = new Event();
454                     e.item = (TableItem)label.getData ("_TABLEITEM");
455                     _table.setSelection(new TableItem[] {(TableItem)e.item});
456                     shell.dispose();
457                     _table.setFocus();
458                     break;
459                 case SWT.MouseExit:
460                     shell.dispose();
461                     break;
462             }
463         }
464     };
465     
466     
467     /**
468      * Create the contents for the attribute details window pop-up
469      @param shell - The shell that will be filled with details.
470      @param attribute - Selected attribute
471      */
472     private void createDetailsPopupContents(Composite shell, AttributeData attribute)
473     {
474         GridLayout layout = new GridLayout(2false);
475         layout.horizontalSpacing = 10;
476         layout.verticalSpacing = 10;
477         layout.marginHeight = 20;
478         layout.marginWidth = 20;
479         
480         Composite parent = _toolkit.createComposite(shell, SWT.NONE);
481         parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
482         parent.setLayout(layout);
483 
484         // Name
485         Label label = _toolkit.createLabel(parent, ATTRIBUTE_TABLE_TITLES[0], SWT.NONE);       
486         GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false);
487         label.setLayoutData(layoutData);
488         int textStyle = SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY;
489         Text  value = _toolkit.createText(parent, ViewUtility.getDisplayText(attribute.getName()), textStyle);
490         value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
491 
492         
493         // Description
494         label = _toolkit.createLabel(parent, DESCRIPTION, SWT.NONE);
495         label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
496         value = _toolkit.createText(parent, attribute.getDescription(), textStyle);
497         value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
498         
499         // value
500         label = _toolkit.createLabel(parent, ATTRIBUTE_TABLE_TITLES[1], SWT.NONE);
501         label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
502         
503         if (!attribute.isReadable())
504         {
505             value = _toolkit.createText(parent, "", textStyle);
506             value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
507         }
508         else
509         {
510             if (!isSimpleType(attribute.getValue()))
511             {
512                 Composite composite = new Composite(parent, SWT.BORDER);
513                 composite.setLayout(new GridLayout());
514                 composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
515                 ViewUtility.populateCompositeWithData(_toolkit, composite, attribute.getValue());
516             }
517             else
518             {
519                 if (attribute.isWritable())
520                 {
521                     value = _toolkit.createText(parent, "", SWT.BEGINNING | SWT.BORDER);
522                     value.addVerifyListener(new NumberVerifyListener());
523                     
524                     // set data to access in the listener
525                     parent.setData(attribute);
526                 }
527                 else
528                 {
529                     value = _toolkit.createText(parent, "", textStyle);
530                 }
531                 
532                 value.setText(attribute.getValue().toString());
533                 value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
534             }
535         }  
536         
537         
538         // Update button
539         Button updateButton = addUpdateButton(parent);
540         updateButton.setData(value);
541         if (!attribute.isWritable())
542         {
543             updateButton.setVisible(false);
544         }
545         
546         if (disableEditing)
547         {
548             value.setEditable(false);
549             updateButton.setVisible(false);
550         }
551     }
552     
553     /**
554      * Create the button for updating attributes.  This should be enabled for writable attribute
555      */
556     private Button addUpdateButton(Composite parent)
557     {
558         final Button updateButton = new Button(parent, SWT.PUSH | SWT.CENTER);
559         // set the data to access in the listener
560         parent.setData(BUTTON_UPDATE, updateButton);
561         
562         updateButton.setText(BUTTON_UPDATE);
563         GridData gridData = new GridData (SWT.CENTER, SWT.BOTTOM, true, true, 21);
564         gridData.widthHint = 100;
565         updateButton.setLayoutData(gridData);
566         updateButton.addSelectionListener(new SelectionAdapter()
567             {
568                 public void widgetSelected(SelectionEvent event)
569                 {
570                     try
571                     {
572                         Button button = (Button)event.widget;
573                         Text text = (Text)button.getData();
574                         AttributeData data = (AttributeData)button.getParent().getData();
575                         MBeanUtility.updateAttribute(_mbean, data, text.getText());
576                         button.getShell().close();
577                         refresh();
578                     }
579                     catch (Exception ex)
580                     {
581                         MBeanUtility.handleException(_mbean, ex);
582                     }
583                 }
584             });
585         
586         return updateButton;
587     }    
588 
589     // Refresh from the server registry
590     public void refresh()
591     {
592         JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(_mbean);
593         ManagedAttributeModel attributesList = serverRegistry.getAttributeModel(_mbean);
594         _tableViewer.setInput(attributesList);
595     }
596     
597     /**
598      * Refreshes the attribute tab by querying the mbean server for latest values
599      */ 
600     @Override
601     public void refresh(ManagedBean mbean
602     {
603         _mbean = mbean;        
604         if (_mbean == null)
605         {
606             _tableViewer.setInput(null);
607             return;
608         }
609         ManagedAttributeModel attributesList = null;
610         try
611         {
612             attributesList = MBeanUtility.getAttributes(mbean);
613         }
614         catch(Exception ex)
615         {
616             MBeanUtility.handleException(_mbean, ex);
617         }
618         _tableViewer.setInput(attributesList);
619         checkForEnablingButtons(getSelectionAttribute());
620         
621         _form.layout(true);
622         _form.getBody().layout(true, true);
623     }
624     
625     /**
626      @see TabControl#setFocus()
627      */
628     public void setFocus()
629     {
630         _table.setFocus();
631     }
632     
633     /**
634      * Checks which buttons are to be enabled or disabled. The graph button will be enabled only
635      * for readable number attributes.  Editing is enabled for writeable attribtues.
636      @param attribute
637      */
638     private void checkForEnablingButtons(AttributeData attribute)
639     {
640         if (attribute == null)
641         {
642             _detailsButton.setEnabled(false);
643             _editButton.setEnabled(false);
644             _graphButton.setEnabled(false);
645             _refreshButton.setEnabled(false);
646             return;
647         }
648         
649         _detailsButton.setEnabled(true);
650         _refreshButton.setEnabled(true);
651         if (attribute.isWritable())
652         {
653             _editButton.setEnabled(true);
654             _graphButton.setEnabled(false);
655         }
656         else
657         {
658             _editButton.setEnabled(false);
659             // Currently only Queues are having attributes, which are suitable for a graph
660             if (attribute.isNumber() && _mbean.isQueue())
661             {
662                 _graphButton.setEnabled(true);
663             }
664             else
665             {
666                 _graphButton.setEnabled(false);
667             }
668         }
669     }
670     
671     /**
672      * Creates graph in a pop-up window for given attribute.
673      @param data
674      */
675     private void createGraph(final AttributeData data)
676     {       
677         Display display = Display.getCurrent();        
678         Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX);
679         shell.setText(_mbean.getName());
680         int x = display.getBounds().width;
681         int y = display.getBounds().height;
682         shell.setBounds(x/4, y/4, GRAPH_WIDTH, GRAPH_HEIGHT);
683         shell.setLayout(new FillLayout());
684         
685         final Canvas canvas = new Canvas(shell, SWT.NONE);
686         long currentValue = Long.parseLong(data.getValue().toString());
687         long mValue = getGraphMaxValue(currentValue);
688         canvas.setData(MAX_VALUE, mValue)
689         canvas.setData(GRAPH_VALUES, new long[] {0,0,0,0,0,currentValue});
690         
691         canvas.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
692         canvas.addPaintListener(new PaintListener()
693             {
694                 public void paintControl(PaintEvent event)
695                 {
696                     Canvas canvas = (Canvas)event.widget;
697                     int maxX = canvas.getSize().x;
698                     int maxY = canvas.getSize().y;
699                     event.gc.fillRectangle(canvas.getBounds());
700                     event.gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
701                     event.gc.setLineWidth(4);
702                     
703                     Object canvasData = canvas.getData(MAX_VALUE);
704                     String str = canvasData.toString();
705                     long maxValue = Long.parseLong(str);
706                     // Set the graph dimensions
707                     event.gc.drawText("0", startX - 40, maxY - startY - 10);
708                     event.gc.drawText("" + maxValue/2, startX - 40, maxY/2);
709                     event.gc.drawText("" + maxValue, startX - 40, startY);
710                     
711                     // horizontal line
712                     event.gc.drawLine(startX, maxY - startY, maxX - 60, maxY - startY);
713                     // vertical line
714                     event.gc.drawLine(startX, maxY - startY, startX, startY);
715                     // set graph text
716                     event.gc.drawText(data.getName(), startX - 40, startY - 40);
717                     event.gc.drawText("25 sec", startX, maxY - startY + 10);
718                     event.gc.drawText("20 sec", startX + GRAPH_ITEM_GAP, maxY - startY + 10);
719                     event.gc.drawText("15 sec", startX + GRAPH_ITEM_GAP * 2, maxY - startY + 10);
720                     event.gc.drawText("10 sec", startX + GRAPH_ITEM_GAP * 3, maxY - startY + 10);
721                     event.gc.drawText(" 5 sec", startX + GRAPH_ITEM_GAP * 4, maxY - startY + 10);
722                     event.gc.drawText(" 0 sec", startX + GRAPH_ITEM_GAP * 5, maxY - startY + 10);
723                     
724                     // plot the graph now for values
725                     event.gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));
726                     canvasData = canvas.getData(GRAPH_VALUES);
727                     long[] graphValues = (long[]) canvasData;
728                     for (int i = 0; i < graphValues.length; i++)
729                     {
730                         int x = startX + i * GRAPH_ITEM_GAP;
731                         int yTotalLength = (maxY - * startY);
732                         float ratio = ((float)graphValues[i]/(float)maxValue);
733                         int itemlength = (int)(yTotalLength *  ratio);
734                         int y = maxY - startY - itemlength;
735                         event.gc.drawLine(x, maxY- startY, x, y);
736                         event.gc.drawText(String.valueOf(graphValues[i]), x, y - 20);
737                     }
738                 }            
739             });
740         
741         shell.open();
742         
743         // Set up the timer for the animation
744         Runnable runnable = new Runnable()
745         {
746           public void run()
747           {
748             try
749             {
750                 animate(canvas, data);
751                 Display.getCurrent().timerExec(TIMER_INTERVAL, this);
752             }
753             catch(Exception ex)
754             {
755                 MBeanUtility.handleException(ex);
756             }
757           }
758         };
759 
760         // Launch the timer
761         display.timerExec(TIMER_INTERVAL, runnable);
762         
763         while (!shell.isDisposed())
764         {
765             if (!display.readAndDispatch())
766             {
767                 display.sleep();
768             }
769         }
770         
771         // Kill the timer
772         display.timerExec(-1, runnable);
773         shell.dispose();
774     }
775     
776     /**
777      @return selected attribute in the table
778      */
779     public AttributeData getSelectionAttribute()
780     {
781         int index = _table.getSelectionIndex();
782         if (index == -1)
783             return null;
784         
785         return (AttributeData)_table.getItem(index).getData();
786     }
787     
788     /**
789      * checks for newer values of selected attribute to update the graph
790      @param canvas
791      @param data
792      @throws Exception
793      */
794     private void animate(Canvas canvas, AttributeData datathrows Exception
795     {
796         String attribute = data.getName();
797         Object valueObj = MBeanUtility.refreshAttribute(_mbean, attribute);
798         int value = Integer.parseInt(String.valueOf(valueObj));
799         Object canvasData = canvas.getData(GRAPH_VALUES);
800         long[] graphValues = (long[]) canvasData;
801         
802         for (int i = 0; i < graphValues.length -1; i++)
803         {
804             graphValues[i= graphValues[i + 1];            
805         }
806         graphValues[graphValues.length - 1= value;
807         
808         canvasData = canvas.getData(MAX_VALUE);
809         long maxValue = Long.parseLong(String.valueOf(canvasData));
810         if (maxValue < value)
811         {
812             maxValue = getGraphMaxValue(value);
813             canvas.setData(MAX_VALUE, maxValue);
814         }
815         
816         canvas.redraw();
817     }
818     
819     /**
820      @param maxAttributeValue
821      @return dynamically calculated value for y-axis on the graph
822      */
823     private long getGraphMaxValue(long maxAttributeValue)
824     {
825         long maxGraphValue = 100;
826         long temp = maxAttributeValue * 3/2;
827         if (temp > maxGraphValue)
828         {
829             long modulus = temp % 100;
830             maxGraphValue = temp + 100 - modulus);
831         
832         
833         return maxGraphValue;
834     }
835     
836     /**
837      * Content Provider class for the table viewer
838      @author Bhupendra Bhardwaj
839      */
840     private class ContentProviderImpl  implements IStructuredContentProvider
841     {
842         
843         public void inputChanged(Viewer v, Object oldInput, Object newInput)
844         {
845             
846         }
847         
848         public void dispose()
849         {
850             
851         }
852         
853         public Object[] getElements(Object parent)
854         {
855             return ((ManagedAttributeModel)parent).getAttributes();
856         }
857     }
858     
859     /**
860      * Label Provider class for the table viewer
861      @author Bhupendra Bhardwaj
862      */
863     private class LabelProviderImpl extends LabelProvider implements ITableLabelProvider, 
864                                                                      IFontProvider,
865                                                                      IColorProvider
866     {
867         AttributeData attribute = null;
868         public String getColumnText(Object element, int columnIndex)
869         {
870             String result = "";
871             attribute = (AttributeDataelement;
872             
873             switch (columnIndex)
874             {
875                 case // attribute name column 
876                     result = ViewUtility.getDisplayText(attribute.getName());
877                     break;
878                 case // attribute value column 
879                     if (attribute.getValue() != null)
880                         result = String.valueOf(attribute.getValue());
881                     break;
882                 default :
883                     result = "";
884             }
885             
886             return result;
887         }
888         
889         public Image getColumnImage(Object element, int columnIndex)
890         {
891             return null;
892         }
893         
894         public Font getFont(Object element)
895         {
896             return ApplicationRegistry.getFont(FONT_TABLE_CELL);
897         }
898         
899         public Color getForeground(Object element)
900         {
901             attribute = (AttributeDataelement;
902             if (attribute.isWritable())
903                 return Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE);
904             else
905                 return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
906         }
907         public Color getBackground(Object element)
908         {
909             return _form.getBackground();
910         }
911     }
912     
913     private class DisposeListenerImpl implements DisposeListener
914     {
915         public void widgetDisposed(DisposeEvent e)
916         {
917             
918         }
919     }
920 
921     /**
922      * Sorter class for the table viewer. It sorts the table for according to attribute name.
923      @author Bhupendra Bhardwaj
924      *
925      */
926     private class ViewerSorterImpl extends ViewerSorter
927     {
928         public int compare(Viewer viewer, Object o1, Object o2
929         {
930             AttributeData attribtue1 = (AttributeData)o1;
931             AttributeData attribtue2 = (AttributeData)o2;
932             
933             return collator.compare(attribtue1.getName(), attribtue2.getName());
934         }
935     }
936 }