/******************************************************************************* * Copyright (c) 2004, 2008 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * QNX Software Systems - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.debug.internal.ui.propertypages; import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.debug.core.model.ICBreakpointFilterExtension; import org.eclipse.cdt.debug.core.model.ICDebugTarget; import org.eclipse.cdt.debug.core.model.ICThread; import org.eclipse.cdt.debug.ui.CDebugUIPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.model.IDebugElement; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; public class ThreadFilterEditor { /** * Comment for ThreadFilterEditor. */ public class CheckHandler implements ICheckStateListener { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent) */ public void checkStateChanged( CheckStateChangedEvent event ) { Object element = event.getElement(); if ( element instanceof IDebugTarget ) { checkTarget( (IDebugTarget)element, event.getChecked() ); } else if ( element instanceof IThread ) { checkThread( (IThread)element, event.getChecked() ); } } /** * Check or uncheck a debug target in the tree viewer. * When a debug target is checked, attempt to * check all of the target's threads by default. * When a debug target is unchecked, uncheck all * its threads. */ protected void checkTarget( IDebugTarget target, boolean checked ) { getThreadViewer().setChecked( target, checked ); getThreadViewer().setGrayed( target, false ); getThreadViewer().expandToLevel( target, AbstractTreeViewer.ALL_LEVELS ); IThread[] threads; try { threads = target.getThreads(); } catch( DebugException exception ) { CDebugUIPlugin.log( exception ); return; } for( int i = 0; i < threads.length; i++ ) { getThreadViewer().setChecked( threads[i], checked ); getThreadViewer().setGrayed( threads[i], false ); } } /** * Check or uncheck a thread. * Update the thread's debug target. */ protected void checkThread( IThread thread, boolean checked ) { getThreadViewer().setChecked( thread, checked ); IDebugTarget target = (thread).getDebugTarget(); IThread[] threads; try { threads = target.getThreads(); } catch( DebugException exception ) { CDebugUIPlugin.log( exception ); return; } int checkedNumber = 0; for( int i = 0; i < threads.length; i++ ) { if ( getThreadViewer().getChecked( threads[i] ) ) { ++checkedNumber; } } if ( checkedNumber == 0 ) { getThreadViewer().setChecked( target, false ); getThreadViewer().setGrayed( target, false ); } else if ( checkedNumber == threads.length ) { getThreadViewer().setChecked( target, true ); getThreadViewer().setGrayed( target, false ); } else { getThreadViewer().setGrayChecked( target, true ); } } } /** * Comment for ThreadFilterEditor. */ public class ThreadFilterContentProvider implements ITreeContentProvider { /** * Constructor for ThreadFilterContentProvider. */ public ThreadFilterContentProvider() { super(); // TODO Auto-generated constructor stub } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) */ public Object[] getChildren( Object parent ) { if ( parent instanceof IDebugTarget ) { ICDebugTarget target = (ICDebugTarget)((IDebugTarget)parent).getAdapter( ICDebugTarget.class ); if ( target != null ) { try { return ((ICDebugTarget)parent).getThreads(); } catch( DebugException e ) { CDebugUIPlugin.log( e ); } } } if ( parent instanceof ILaunchManager ) { List children = new ArrayList(); ILaunch[] launches = ((ILaunchManager)parent).getLaunches(); IDebugTarget[] targets; ICDebugTarget target; for( int i = 0, numLaunches = launches.length; i < numLaunches; i++ ) { targets = launches[i].getDebugTargets(); for( int j = 0, numTargets = targets.length; j < numTargets; j++ ) { target = (ICDebugTarget)targets[j].getAdapter( ICDebugTarget.class ); if ( target != null && !target.isDisconnected() && !target.isTerminated() ) { children.add( target ); } } } return children.toArray(); } return new Object[0]; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) */ public Object getParent( Object element ) { if ( element instanceof IThread ) { return ((IThread)element).getDebugTarget(); } if ( element instanceof IDebugTarget ) { return ((IDebugElement)element).getLaunch(); } if ( element instanceof ILaunch ) { return DebugPlugin.getDefault().getLaunchManager(); } return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) */ public boolean hasChildren( Object element ) { if ( element instanceof IStackFrame ) { return false; } if ( element instanceof IDebugElement ) { return getChildren( element ).length > 0; } if ( element instanceof ILaunch ) { return true; } if ( element instanceof ILaunchManager ) { return ((ILaunchManager)element).getLaunches().length > 0; } return false; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ public Object[] getElements( Object inputElement ) { return getChildren( inputElement ); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) */ public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) { } } private CBreakpointFilteringPage fPage; private CheckboxTreeViewer fThreadViewer; private ThreadFilterContentProvider fContentProvider; private CheckHandler fCheckHandler; /** * Constructor for ThreadFilterEditor. */ public ThreadFilterEditor( Composite parent, CBreakpointFilteringPage page ) { fPage = page; fContentProvider = new ThreadFilterContentProvider(); fCheckHandler = new CheckHandler(); createThreadViewer( parent ); } protected CBreakpointFilteringPage getPage() { return fPage; } private void createThreadViewer( Composite parent ) { Label label = new Label( parent, SWT.NONE ); label.setText( PropertyPageMessages.getString( "ThreadFilterEditor.0" ) ); //$NON-NLS-1$ label.setFont( parent.getFont() ); label.setLayoutData( new GridData() ); GridData data = new GridData( GridData.FILL_BOTH ); data.heightHint = 100; fThreadViewer = new CheckboxTreeViewer( parent, SWT.BORDER ); fThreadViewer.addCheckStateListener( fCheckHandler ); fThreadViewer.getTree().setLayoutData( data ); fThreadViewer.getTree().setFont( parent.getFont() ); fThreadViewer.setContentProvider( fContentProvider ); fThreadViewer.setLabelProvider( DebugUITools.newDebugModelPresentation() ); fThreadViewer.setInput( DebugPlugin.getDefault().getLaunchManager() ); setInitialCheckedState(); } /** * Returns the debug targets that appear in the tree */ protected IDebugTarget[] getDebugTargets() { Object input = fThreadViewer.getInput(); if ( !(input instanceof ILaunchManager) ) { return new IDebugTarget[0]; } ILaunchManager launchManager = (ILaunchManager)input; return launchManager.getDebugTargets(); } protected CheckboxTreeViewer getThreadViewer() { return fThreadViewer; } /** * Sets the initial checked state of the tree viewer. * The initial state should reflect the current state * of the breakpoint. If the breakpoint has a thread * filter in a given thread, that thread should be * checked. */ protected void setInitialCheckedState() { ICBreakpointFilterExtension filterExtension = fPage.getFilterExtension(); try { ICDebugTarget[] targets = filterExtension.getTargetFilters(); for( int i = 0; i < targets.length; i++ ) { ICThread[] filteredThreads = filterExtension.getThreadFilters( targets[i] ); if ( filteredThreads != null ) { for ( int j = 0; j < filteredThreads.length; ++j ) fCheckHandler.checkThread( filteredThreads[j], true ); } else { fCheckHandler.checkTarget( targets[i], true ); } } } catch( CoreException e ) { CDebugUIPlugin.log( e ); } } protected void doStore() { ICBreakpointFilterExtension filterExtension = fPage.getFilterExtension(); IDebugTarget[] targets = getDebugTargets(); for ( int i = 0; i < targets.length; ++i ) { if ( !(targets[i] instanceof ICDebugTarget) ) continue; try { if ( getThreadViewer().getChecked( targets[i] ) ) { if ( getThreadViewer().getGrayed( targets[i] ) ) { ICThread[] threads = getTargetThreadFilters( (ICDebugTarget)targets[i] ); filterExtension.setThreadFilters( threads ); } else { filterExtension.setTargetFilter( (ICDebugTarget)targets[i] ); } } else { filterExtension.removeTargetFilter( (ICDebugTarget)targets[i] ); } DebugPlugin.getDefault().getBreakpointManager().fireBreakpointChanged( fPage.getBreakpoint() ); } catch( CoreException e ) { CDebugUIPlugin.log( e ); } } } private ICThread[] getTargetThreadFilters( ICDebugTarget target ) { Object[] threads = ((ITreeContentProvider)getThreadViewer().getContentProvider()).getChildren( target ); ArrayList list = new ArrayList( threads.length ); for ( int i = 0; i < threads.length; ++i ) { if ( getThreadViewer().getChecked( threads[i] ) ) list.add( threads[i] ); } return (ICThread[])list.toArray( new ICThread[list.size()] ); } }