/*******************************************************************************
* Copyright (c) 2011, 2013 Wind River Systems, Inc. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.processes.ui.search;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNode;
import org.eclipse.tcf.te.tcf.processes.ui.nls.Messages;
import org.eclipse.tcf.te.ui.search.TreeViewerSearchDialog;
/**
* The searchable that provides a UI to collect and test
* the state of a process during searching.
* <p>
* Note the state of a process is expressed using a character from
* "RSDZTW" where R is running, S is
* sleeping in an interruptible wait, D is waiting in uninterruptible
* disk sleep, Z is zombie, T is traced or stopped (on a signal), and W
* is paging.
*/
public class ProcessStateSearchable extends ProcessBaseSearchable {
// Constant values of state options
private static final int OPTION_NOT_REMEMBER = 0;
private static final int OPTION_SPECIFIED = 1;
// The choice selected
private int choice;
// UI elements for input
private Button fBtnNotRem;
private Button fBtnSpecified;
private Button fBtnR;
private Button fBtnS;
private Button fBtnD;
private Button fBtnZ;
private Button fBtnT;
private Button fBtnW;
// The flags indicating if a certain state is included.
private boolean fIncludeR;
private boolean fIncludeS;
private boolean fIncludeD;
private boolean fIncludeZ;
private boolean fIncludeT;
private boolean fIncludeW;
// The current selected states expressed in the above characters.
private String fStates;
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#createAdvancedPart(org.eclipse.tcf.te.ui.search.TreeViewerSearchDialog, org.eclipse.swt.widgets.Composite)
*/
@Override
public void createAdvancedPart(TreeViewerSearchDialog dialog, Composite parent) {
SelectionListener l = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
optionChecked(e);
}
};
Composite stateComposite = createGroup(parent);
stateComposite.setLayout(new GridLayout());
fBtnNotRem = new Button(stateComposite, SWT.RADIO);
fBtnNotRem.setText(Messages.ProcessStateSearchable_NotSure);
fBtnNotRem.setSelection(true);
GridData data = new GridData();
fBtnNotRem.setLayoutData(data);
fBtnNotRem.addSelectionListener(l);
fBtnSpecified = new Button(stateComposite, SWT.RADIO);
fBtnSpecified.setText(Messages.ProcessStateSearchable_SpecifyState);
data = new GridData();
fBtnSpecified.setLayoutData(data);
fBtnSpecified.addSelectionListener(l);
Composite cmpStates = new Composite(stateComposite, SWT.NONE);
data = new GridData(GridData.FILL_HORIZONTAL);
cmpStates.setLayoutData(data);
GridLayout layout = new GridLayout(3, true);
layout.marginLeft = 20;
cmpStates.setLayout(layout);
fBtnR = new Button(cmpStates, SWT.CHECK);
fBtnR.setText(Messages.ProcessStateSearchable_StateRunning);
fBtnR.setEnabled(false);
data = new GridData();
fBtnR.setLayoutData(data);
fBtnR.addSelectionListener(l);
fBtnS = new Button(cmpStates, SWT.CHECK);
fBtnS.setText(Messages.ProcessStateSearchable_StateSleeping);
fBtnS.setEnabled(false);
data = new GridData();
fBtnS.setLayoutData(data);
fBtnS.addSelectionListener(l);
fBtnD = new Button(cmpStates, SWT.CHECK);
fBtnD.setText(Messages.ProcessStateSearchable_StateWaiting);
fBtnD.setEnabled(false);
data = new GridData();
fBtnD.setLayoutData(data);
fBtnD.addSelectionListener(l);
fBtnZ = new Button(cmpStates, SWT.CHECK);
fBtnZ.setText(Messages.ProcessStateSearchable_StateZombie);
fBtnZ.setEnabled(false);
data = new GridData();
fBtnZ.setLayoutData(data);
fBtnZ.addSelectionListener(l);
fBtnT = new Button(cmpStates, SWT.CHECK);
fBtnT.setText(Messages.ProcessStateSearchable_StateTraced);
fBtnT.setEnabled(false);
data = new GridData();
fBtnT.setLayoutData(data);
fBtnT.addSelectionListener(l);
fBtnW = new Button(cmpStates, SWT.CHECK);
fBtnW.setText(Messages.ProcessStateSearchable_StatePaging);
fBtnW.setEnabled(false);
data = new GridData();
fBtnW.setLayoutData(data);
fBtnW.addSelectionListener(l);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.processes.ui.search.ProcessBaseSearchable#getSectionTitle()
*/
@Override
protected String getGroupTitle() {
return Messages.ProcessStateSearchable_SectionChooseState;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#isInputValid()
*/
@Override
public boolean isInputValid() {
if(choice == OPTION_SPECIFIED) {
boolean valid = fIncludeR || fIncludeS || fIncludeD || fIncludeZ || fIncludeT || fIncludeW;
return valid;
}
return true;
}
/**
* The method handling the selection event.
*
* @param e The selection event.
*/
protected void optionChecked(SelectionEvent e) {
Object src = e.getSource();
if(src == fBtnNotRem) {
choice = OPTION_NOT_REMEMBER;
setButtonStates(false);
}
else if(src == fBtnSpecified) {
choice = OPTION_SPECIFIED;
setButtonStates(true);
fStates = getSelectedStates();
}
else if(src == fBtnR) {
fIncludeR = fBtnR.getSelection();
fStates = getSelectedStates();
}
else if(src == fBtnS) {
fIncludeS = fBtnS.getSelection();
fStates = getSelectedStates();
}
else if(src == fBtnD) {
fIncludeD = fBtnD.getSelection();
fStates = getSelectedStates();
}
else if(src == fBtnZ) {
fIncludeZ = fBtnZ.getSelection();
fStates = getSelectedStates();
}
else if(src == fBtnT) {
fIncludeT = fBtnT.getSelection();
fStates = getSelectedStates();
}
else if(src == fBtnW) {
fIncludeW = fBtnW.getSelection();
fStates = getSelectedStates();
}
fireOptionChanged();
}
/**
* Get the current state strings expressed in the character set
* mentioned above.
*
* @return A string that contains all the selected states.
*/
private String getSelectedStates() {
StringBuilder builder = new StringBuilder();
if(fIncludeR) {
builder.append("R"); //$NON-NLS-1$
}
if(fIncludeS) {
builder.append("S"); //$NON-NLS-1$
}
if(fIncludeD) {
builder.append("D"); //$NON-NLS-1$
}
if(fIncludeZ) {
builder.append("Z"); //$NON-NLS-1$
}
if(fIncludeT) {
builder.append("T"); //$NON-NLS-1$
}
if(fIncludeW) {
builder.append("W"); //$NON-NLS-1$
}
return builder.toString();
}
/**
* Enable the state buttons using the specified
* enablement flag.
*
* @param enabled the enablement flag.
*/
private void setButtonStates(boolean enabled) {
fBtnR.setEnabled(enabled);
fBtnS.setEnabled(enabled);
fBtnD.setEnabled(enabled);
fBtnZ.setEnabled(enabled);
fBtnT.setEnabled(enabled);
fBtnW.setEnabled(enabled);
}
/*
* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.interfaces.ISearchMatcher#match(java.lang.Object)
*/
@Override
public boolean match(Object element) {
if (element instanceof IProcessContextNode) {
switch (choice) {
case OPTION_NOT_REMEMBER:
return true;
case OPTION_SPECIFIED:
final IProcessContextNode node = (IProcessContextNode) element;
final AtomicReference<String> state = new AtomicReference<String>();
Runnable runnable = new Runnable() {
@Override
public void run() {
state.set(node.getSysMonitorContext().getState());
}
};
Assert.isTrue(!Protocol.isDispatchThread());
Protocol.invokeAndWait(runnable);
if(state.get() != null && state.get().length() > 0) {
state.set(state.get().toUpperCase());
return fStates.indexOf(state.get()) != -1;
}
}
}
return false;
}
}