/* * Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved. * * This program and the accompanying materials are made available * under the terms of the Eclipse Public License, Version 1.0, * which accompanies this distribution and is available at * * http://www.eclipse.org/legal/epl-v10.html * */ package net.rim.ejde.internal.ui.views; import java.io.File; import java.util.Iterator; import java.util.Vector; import net.rim.ejde.internal.core.ContextManager; import net.rim.ejde.internal.core.RimIDEUtil; import net.rim.ejde.internal.ui.preferences.PreferenceConstants; import net.rim.ejde.internal.util.Messages; import net.rim.ide.RIA; import net.rim.ide.core.IDEError; import net.rim.ide.core.VarContentsHelper; import net.rim.ide.core.VarContentsHelper.Callback; import net.rim.ide.core.VarContentsHelper.Line; import net.rim.ide.core.VarContentsHelper.MenuItem; import org.apache.log4j.Logger; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.IFileSystem; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ILazyContentProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.IWorkbenchActionConstants; /** * This view is the parent of views which display data from a {@link VarContentsHelper}, e.g. process view, locals view, locks * view,threads view and statics view. * */ public abstract class VarContentDebugView extends BasicDebugView { private static final Logger _log = Logger.getLogger( VarContentDebugView.class ); private TableViewer _tableViewer; private int _selectedColumns = -1; private int _selectedRow = -1; private VarLabelProvider _labelProvider; private int _moveCursorTo; private IProgressMonitor _progressMonitor; DebuggerLiveUpdateJob _liveUpdateJob; /** * Get the instance of the contents helper used by this view. * * @return */ abstract protected VarContentsHelper getContentsHelper(); /** * Constructs an instance of VarContentDebugView. */ public VarContentDebugView( int style ) { super( style ); if( _log.isDebugEnabled() ) { _log.debug( String.format( "Instance [%s] created.", hashCode() ) ); //$NON-NLS-1$ } } synchronized protected void setProgressMonitor( IProgressMonitor monitor ) { _progressMonitor = monitor; } synchronized protected IProgressMonitor getProgressMonitor() { return _progressMonitor; } protected void startLiveupdate() { IPreferenceStore ps = ContextManager.PLUGIN.getPreferenceStore(); boolean startLiveUpdate = ps.getBoolean( PreferenceConstants.NET_RIM_EJDE_UI_VIEWS_LIVE_UPDATE ); if( !startLiveUpdate ) { // if live update is disabled, we cancel the update job if it is available if( _liveUpdateJob != null ) { _liveUpdateJob.cancelUpdate(); } return; } if( _liveUpdateJob == null ) { _liveUpdateJob = new DebuggerLiveUpdateJob( "", this ); _liveUpdateJob.schedule(); } else { if( _liveUpdateJob.getState() == Job.NONE || _liveUpdateJob.isUpdateCanceled() ) { _liveUpdateJob.schedule(); } } } /** * Disposes created image instances. */ public void dispose() { super.dispose(); if( _liveUpdateJob != null ) { _liveUpdateJob.cancelUpdate(); } } /* * (non-Javadoc) Sub-clsses may override this method. * * @see BasicDebugView#refresh() */ public void refresh() throws CoreException { _log.trace( "Refreshing DebugView" ); RIA ria = RIA.getCurrentDebugger(); if( ria != null ) { VarContentsHelper contentHelper = getContentsHelper(); if( contentHelper == null ) { return; } try { contentHelper.updateContents(); Table table = getTableView().getTable(); table.setRedraw( false ); getTableView().setInput( contentHelper ); table.setItemCount( getContentsHelper().getRowCount() ); table.setRedraw( true ); if( _selectedRow >= 0 ) { table.setSelection( _selectedRow ); table.showSelection(); } } catch( IDEError e ) { _log.error( e ); } } } /** * Gets the TableViewer component used in this view. * * @return */ protected TableViewer getTableView() { if( _tableViewer == null ) { _log.error( "The TableViewer component has not been created." ); } return _tableViewer; } /** * Sets the TableViewer component used in this view. <b>This must be called after the TableViewer component is created in the * sub-classes</b>. * * @param view */ protected void setTableView( TableViewer view ) { _tableViewer = view; } /** * Gets the LabelProvider of the TableViewer component used in this view. * * @return */ protected VarLabelProvider getLabelProvider() { return _labelProvider; } /** * Sets the LabelProvider of the TableViewer component used in this view. <b>This must be called after the TableViewer * component is created in the sub-classes</b>. * * @param view */ protected void setLabelProvider( VarLabelProvider labelProvider ) { _labelProvider = labelProvider; } /*************************************************************************** * @link java.lang.Object#finalize() */ @Override protected void finalize() { if( _log.isDebugEnabled() ) { _log.debug( String.format( "Instance [%s] finalized.", hashCode() ) ); //$NON-NLS-1$ } } protected void createContextMenu() { MenuManager menuManager = new MenuManager( "PopupMenu" ); //$NON-NLS-1$ menuManager.setRemoveAllWhenShown( true ); menuManager.addMenuListener( new IMenuListener() { public void menuAboutToShow( IMenuManager m ) { fillContextMenu( m ); } } ); Menu menu = menuManager.createContextMenu( _tableViewer.getControl() ); _tableViewer.getControl().setMenu( menu ); getSite().registerContextMenu( menuManager, _tableViewer ); } protected void fillContextMenu( IMenuManager menuMgr ) { RIA ria = RIA.getCurrentDebugger(); if( ria == null || !ria.isDebuggerSuspended() ) { return; } Vector< MenuItem > menuVector = null; VarContentsHelper helper = getContentsHelper(); if( helper == null ) { return; } try { menuVector = helper.getMenu(); } catch( IDEError e ) { _log.error( e.getMessage(), e ); } if( menuVector == null ) { return; } MenuItem menuItem; for( Iterator< MenuItem > iterator = menuVector.iterator(); iterator.hasNext(); ) { menuItem = iterator.next(); if( menuItem.isSeparator ) { menuMgr.add( new Separator() ); } else { menuMgr.add( new MenuAction( this, menuItem ) ); } } menuMgr.add( new Separator( IWorkbenchActionConstants.MB_ADDITIONS ) ); fillExtraContextMenu( menuMgr ); } /** * Sub-classes need to override this method if they want to add extra context menus. * * @param menuMgr */ protected void fillExtraContextMenu( IMenuManager menuMgr ) { // do nothing here } /** * Gets the index of <code>column</code>. * * @param column * @return index of <code>column</code> or <em>-1</em> if <code>column</code> is not in the table */ private int getColumnIndex( TableColumn column ) { Table table = _tableViewer.getTable(); for( int i = 0; i < table.getColumnCount(); i++ ) { if( table.getColumn( i ).equals( column ) ) { return i; } } return -1; } /** * Display the objects information. */ void displayData() { // clear all items from the table Table table = _tableViewer.getTable(); table.removeAll(); VarContentsHelper contentsHelper = getContentsHelper(); if( null == contentsHelper ) { return; } // update contents (set data to lines) try { contentsHelper.updateContents(); } catch( IDEError e ) { _log.error( e.getMessage(), e ); return; } // table.setRedraw( false ); _tableViewer.setInput( contentsHelper ); table.setItemCount( contentsHelper.getRowCount() ); table.setRedraw( true ); if( _selectedRow >= 0 ) { table.setSelection( _selectedRow ); table.showSelection(); } } /** * Gets the index of selected column in the table. * * @return */ protected int getSelectedColumnIndex() { return _selectedColumns; } /** * Sets the index of selected column in the table. * * @param index */ protected void setSelectedColumnIndex( int index ) { _selectedColumns = index; } /** * Gets the index of selected row in the table. * * @return */ protected int getSelectedRowIndex() { return _selectedRow; } /** * Sets the index of selected row in the table. * * @return */ protected void setSelectedRowIndex( int index ) { _selectedRow = index; } /** * Gets the index of row where the cursor should be moved to. * * @return */ protected int getMoveCursorToIndex() { return _moveCursorTo; } /** * Sets the index of row where the cursor should be moved to. * * @return */ protected void setMoveCursorToIndex( int index ) { _moveCursorTo = index; } // ------ Inner Classes ------ /** * Content provider of objects tree view. */ protected class VarContentProvider implements ILazyContentProvider { private TableViewer _myViewer; private Object[] _models; public VarContentProvider( TableViewer viewer ) { _myViewer = viewer; } public void updateElement( int index ) { _myViewer.replace( _models[ index ], index ); } public void dispose() { // TODO Auto-generated method stub } public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) { if( ( newInput == null ) || !( newInput instanceof VarContentsHelper ) ) { _models = new Object[ 0 ]; } else { VarContentsHelper helper = (VarContentsHelper) newInput; int rowCount = helper.getRowCount(); _models = new Object[ rowCount ]; for( int i = 0; i < rowCount; i++ ) { _models[ i ] = helper.getLine( i ); } } } } /** * (no java doc) * * @see IBasicActions#clear() */ @Override public void clear() { TableViewer tableviewer = getTableView(); if( tableviewer != null ) { tableviewer.getTable().removeAll(); } setHasData( false ); updateToolbar(); } /** * Label provider of objects tree view. */ protected class VarLabelProvider extends AbstractTreeOwnerDrawLabelProvider { public VarLabelProvider( TableViewer viewer ) { super( viewer ); } @Override public boolean findRowAtSameIndent( Object obj, int indent ) { int row = getIndex( obj ) + 1; VarContentsHelper contentsHelper = getContentsHelper(); if( null == contentsHelper ) { return false; } for( int i = row; i < contentsHelper.getRowCount(); i++ ) { Line line = contentsHelper.getLine( i ); if( line == null ) { return false; } int indentOfChild = getIndent( line ); if( indentOfChild < indent ) { return false; } if( indentOfChild == indent ) { return true; } } return false; } @Override public int getIndent( Object obj ) { Line line = (Line) obj; return line.getIndent(); } @Override public int getIndex( Object obj ) { return _tableViewer.getTable().indexOf( (TableItem) obj ); } @Override public boolean hasChildren( Object obj ) { Line line = (Line) obj; return line.getIcon() != Line.ICON_NONE; } @Override public boolean isExpanded( Object obj ) { Line line = (Line) obj; return line.getIcon() == Line.ICON_MINUS; } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.OwnerDrawLabelProvider#measure(Event, Object) */ @Override protected void measure( Event event, Object element ) { if( _tableViewer.getTable().getColumnCount() != 0 ) { event.width = _tableViewer.getTable().getColumn( event.index ).getWidth(); } } /* * (non-Javadoc) * * @see org.eclipse.jface.viewers.OwnerDrawLabelProvider#paint(org.eclipse .swt.widgets.Event, java.lang.Object) */ @Override protected void paint( Event event, Object element ) { // call super method to initiate variables super.paint( event, element ); String text; VarContentsHelper contentsHelper = getContentsHelper(); if( contentsHelper == null ) { return; } Line line = (Line) element; text = ( contentsHelper.getValue( line, event.index ) ).toString(); if( event.index == 0 ) { drawFirstColumn( event, element, text, line.getHilight() ); } else { drawText( event, text, event.x, event.y, line.getHilight() ); } } @Override public int calculateDisplayLevel( Object obj ) { // nothing to do return 0; } } protected class VarMouseAdapter extends MouseAdapter { public VarMouseAdapter() { // TODO Auto-generated constructor stub } @Override public void mouseDown( MouseEvent e ) { int selectionIndex = _tableViewer.getTable().getSelectionIndex(); if( selectionIndex < 0 ) { return; } TableItem selectedItem = _tableViewer.getTable().getItem( selectionIndex ); if( selectedItem == null ) { return; } // If user clicked on the [+] or [-], expand or collapse the item Line line = (Line) selectedItem.getData(); Rectangle rect = _labelProvider.getImageBounds( line, selectedItem.getBounds( 0 ) ); if( rect.contains( e.x, e.y ) ) { switch( line.getIcon() ) { case Line.ICON_PLUS: case Line.ICON_MINUS: { _moveCursorTo = -1; _selectedRow = selectionIndex; VarContentsHelper contentsHelper = getContentsHelper(); if( contentsHelper == null ) { return; } contentsHelper.toggleExpansion( line ); displayData(); break; } } } } } protected class VarTableColumnSelectionListener implements SelectionListener { public VarTableColumnSelectionListener() { // TODO Auto-generated constructor stub } public void widgetDefaultSelected( SelectionEvent e ) { // nothing to do } /** * Sort the content when a column is selected. */ public void widgetSelected( SelectionEvent e ) { TableColumn column = (TableColumn) e.widget; _selectedColumns = getColumnIndex( column ); _moveCursorTo = -1; try { VarContentsHelper contentsHelper = getContentsHelper(); if( contentsHelper == null ) { return; } contentsHelper.sortRows( _selectedColumns ); } catch( IDEError e1 ) { _log.error( e1.getStackTrace(), e1 ); return; } } } protected class VarTableRowSelectionListener implements SelectionListener { public VarTableRowSelectionListener() { // TODO Auto-generated constructor stub } public void widgetDefaultSelected( SelectionEvent e ) { // nothing to do } /** * Sort the content when a column is selected. */ public void widgetSelected( SelectionEvent e ) { _selectedRow = _tableViewer.getTable().getSelectionIndex(); } } protected class VarCallbackAdaptor implements Callback { @Override public int getSelectedRow() { return getSelectedRowIndex(); } @Override public int getSelectedColumn() { return getSelectedColumnIndex(); } @Override public void beep() { // TODO Auto-generated method stub } @Override public void showSource( String fileName, int line ) { IFileSystem fileSystem = EFS.getLocalFileSystem(); IFileStore fileStore = fileSystem.getStore( new Path( fileName ) ); RimIDEUtil.openSourceFile( fileStore, line ); } @Override public void updateAllDebugWindows() { // TODO Auto-generated method stub } @Override public void addWatchExpression( String expr ) throws IDEError { // TODO Auto-generated method stub } @Override public void columnHeadersChanged() { // TODO Auto-generated method stub } @Override public void moveCursorTo( int row, int column ) { setMoveCursorToIndex( row ); } @Override public void reload() { // TODO Auto-generated method stub } @Override public File promptAndCreateFile( String wildCard, String title ) { return RimIDEUtil.openFileForSave( getSite().getShell(), wildCard, new String[] {} ); } @Override public void displayLineAttribute( String toStringValue ) { MessageDialog.openInformation( getSite().getShell(), Messages.ObjectsView_LINE_ATTRIBUTE_DIALOG_TITLE, toStringValue ); } } }