/*******************************************************************************
* Copyright (c) 2006, 2009 Wind River 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.examples.dsf.timers;
import java.util.concurrent.ExecutionException;
import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.cdt.examples.dsf.DsfExamplesPlugin;
import org.eclipse.cdt.examples.dsf.timers.TimerService.TimerDMContext;
import org.eclipse.cdt.examples.dsf.timers.TimersVMProvider.ViewLayout;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory;
import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;
/**
* Example view which displays data from timers and alarms services. It starts
* a new DSF session and configures the services for it. Then it configures
* a data model provider to process the service data and display it in a
* flexible-hierarchy asynchronous viewer.
*/
@SuppressWarnings("restriction")
public class TimersView extends ViewPart {
/** Timers view ID */
public static final String ID_VIEW_TIMERS = "org.eclipse.cdt.examples.dsf.TimersView";
/** Asynchronous tree viewer from the platform debug.ui plugin. */
private TreeModelViewer fViewer;
/** Presentation context of the timers viewer */
private PresentationContext fPresentationContext;
/** DSF executor to use for a new session with timers and alarms services */
private DsfExecutor fExecutor;
/** DSF session */
private DsfSession fSession;
/** DSF services tracker used by actions in the viewer. */
private DsfServicesTracker fServices;
/** Adapter used to provide view model for flexible-hierarchy viewer */
private TimersVMAdapter fTimersVMAdapter;
/** Action which toggles the layout in the viewer */
private Action fToggleLayoutAction;
/** Action that adds a new timer */
private Action fAddTimerAction;
/** Action that adds a new trigger */
private Action fAddTriggerAction;
/** Action that removes the selected trigger or timer */
private Action fRemoveAction;
public TimersView() {}
/**
* This is a call-back that will allow us to create the viewer and
* initialize it. For this view, it creates the DSF session, along
* with its services. Then it creates the viewer model adapter and
* registers it with the session.
*/
@Override
public void createPartControl(Composite parent) {
// Create the Flexible Hierarchy viewer. Also create a presentation
// context which will be given to the content/label provider adapters
// to distinguish this view from other flexible-hierarchy views.
fPresentationContext = new PresentationContext(ID_VIEW_TIMERS);
fViewer = new TreeModelViewer(
parent, SWT.VIRTUAL | SWT.FULL_SELECTION, fPresentationContext);
// Create the executor, which will be used exclusively with this view,
// as well as a session and a services tracker for managing references
// to services.
fExecutor = new DefaultDsfExecutor();
fSession = DsfSession.startSession(fExecutor, "Timers(DSF Example)");
fServices = new DsfServicesTracker(
DsfExamplesPlugin.getBundleContext(), fSession.getId());
// Start the services using a sequence. The sequence runs in the
// session executor thread, therefore the thread calling this method
// has to block using Future.get() until the sequence it completes.
// The Future.get() will throw an exception if the sequence fails.
ServicesStartupSequence startupSeq = new ServicesStartupSequence(fSession);
fSession.getExecutor().execute(startupSeq);
try {
startupSeq.get();
} catch (InterruptedException e) { assert false;
} catch (ExecutionException e) { assert false;
}
// Create the flexible hierarchy content/label adapter. Then register
// it with the session.
fTimersVMAdapter = new TimersVMAdapter(fSession, fPresentationContext);
fSession.registerModelAdapter(IElementContentProvider.class, fTimersVMAdapter);
fSession.registerModelAdapter(IModelProxyFactory.class, fTimersVMAdapter);
fSession.registerModelAdapter(IColumnPresentationFactory.class, fTimersVMAdapter);
// Create the input object for the view. This object needs to return
// the VM adapter through the IAdaptable interface when queried for the
// flexible hierarchy adapters.
final IAdaptable viewerInputObject =
new IAdaptable() {
/**
* The input object provides the viewer access to the viewer model adapter.
*/
@SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
if ( adapter.isInstance(fTimersVMAdapter) ) {
return fTimersVMAdapter;
}
return null;
}
@Override
public String toString() {
return "Timers View Root"; //$NON-NLS-1$
}
};
fViewer.setInput(viewerInputObject);
makeActions();
contributeToActionBars();
}
@Override
public void dispose() {
try {
// First dispose the view model, which is the client of services.
// This operation needs to be performed in the session executor
// thread. Block using Future.get() until this call completes.
fSession.getExecutor().submit(new Runnable() {
public void run() {
fSession.unregisterModelAdapter(IElementContentProvider.class);
fSession.unregisterModelAdapter(IModelProxyFactory.class);
fSession.unregisterModelAdapter(IColumnPresentationFactory.class);
}}).get();
// Dispose the VM adapter.
fTimersVMAdapter.dispose();
fTimersVMAdapter = null;
// Next invoke the shutdown sequence for the services. Sequence
// class also implements Future.get()...
ServicesShutdownSequence shutdownSeq =
new ServicesShutdownSequence(fSession);
fSession.getExecutor().execute(shutdownSeq);
try {
shutdownSeq.get();
} catch (InterruptedException e) { assert false;
} catch (ExecutionException e) { assert false;
}
// Finally end the session and the executor.
fSession.getExecutor().submit(new Runnable() {
public void run() {
DsfSession.endSession(fSession);
fSession = null;
fExecutor.shutdown();
fExecutor = null;
}}).get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
super.dispose();
}
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalToolBar(bars.getToolBarManager());
}
private void fillLocalToolBar(IToolBarManager manager) {
manager.add(fToggleLayoutAction);
manager.add(fAddTimerAction);
manager.add(fAddTriggerAction);
manager.add(fRemoveAction);
manager.add(new Separator());
}
private void makeActions() {
fToggleLayoutAction = new Action("Toggle Layout", IAction.AS_CHECK_BOX) { //$NON-NLS-1$
@Override
public void run() {
// Get the toggle state of the action while on UI thread.
final ViewLayout layout = isChecked() ? ViewLayout.TRIGGERS_AT_TOP : ViewLayout.TIMERS_AT_TOP;
IVMProvider provider = fTimersVMAdapter.getVMProvider(fPresentationContext);
((TimersVMProvider)provider).setViewLayout(layout);
}
};
fToggleLayoutAction.setToolTipText("Toggle Layout"); //$NON-NLS-1$
fToggleLayoutAction.setImageDescriptor(DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(
DsfExamplesPlugin.IMG_LAYOUT_TOGGLE));
fAddTimerAction = new Action("Add New Timer") {
@Override
public void run() {
fExecutor.execute(new Runnable() {
public void run() {
// Only need to create the new timer, the events will
// cause the view to refresh.
fServices.getService(TimerService.class).startTimer();
}
});
}
};
fAddTimerAction.setToolTipText("Add a new timer");
fAddTimerAction.setImageDescriptor(
getImage(DsfExamplesPlugin.IMG_TIMER));
fAddTriggerAction = new Action("Add New Trigger") {
@Override
public void run() {
// Ask user for the new trigger value.
InputDialog inputDialog = new InputDialog(
getSite().getShell(),
"New Trigger",
"Please enter trigger value",
"",
new IInputValidator() {
public String isValid(String input) {
try {
int i= Integer.parseInt(input);
if (i <= 0)
return "Please enter a positive integer";
} catch (NumberFormatException x) {
return "Please enter a positive integer";
}
return null;
}
}
);
if (inputDialog.open() != Window.OK) return;
int tmpTriggerValue = -1;
try {
tmpTriggerValue = Integer.parseInt(inputDialog.getValue());
} catch (NumberFormatException x) { assert false; }
final int triggerValue = tmpTriggerValue;
fExecutor.execute(new Runnable() {
public void run() {
// Create the new trigger
fServices.getService(AlarmService.class).
createTrigger(triggerValue);
}
});
}
};
fAddTriggerAction.setToolTipText("Add a new trigger");
fAddTriggerAction.setImageDescriptor(
getImage(DsfExamplesPlugin.IMG_ALARM));
fRemoveAction = new Action("Remove") {
@Override
public void run() {
final Object selectedElement =
((IStructuredSelection)fViewer.getSelection()).getFirstElement();
if (!(selectedElement instanceof IDMVMContext)) return;
final IDMContext selectedCtx =
((IDMVMContext)selectedElement).getDMContext();
// Based on the context from the selection, call the
// appropriate service to remove the item.
if (selectedCtx instanceof TimerDMContext) {
fExecutor.execute(new Runnable() { public void run() {
fServices.getService(TimerService.class).killTimer(
((TimerDMContext)selectedCtx));
}});
} else if (selectedCtx instanceof AlarmService.TriggerDMContext) {
fExecutor.execute(new Runnable() { public void run() {
fServices.getService(AlarmService.class).deleteTrigger(
(AlarmService.TriggerDMContext)selectedCtx);
}});
}
}
};
fRemoveAction.setToolTipText("Remove selected item");
fRemoveAction.setImageDescriptor( getImage(DsfExamplesPlugin.IMG_REMOVE) );
}
private ImageDescriptor getImage(String key) {
return DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(key);
}
/**
* Passing the focus request to the viewer's control.
*/
@Override
public void setFocus() {
fViewer.getControl().setFocus();
}
}