mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-09 18:56:02 +02:00
[220446] Updated the timers example for use with the "DSF Common Patterns" document.
This commit is contained in:
parent
8868398cc9
commit
abc958a96a
19 changed files with 916 additions and 1049 deletions
|
@ -13,7 +13,7 @@
|
|||
icon="icons/timer.gif"
|
||||
category="org.eclipse.dd.examples.dsf"
|
||||
class="org.eclipse.dd.examples.dsf.timers.TimersView"
|
||||
id="org.eclipse.dd.dsf.examples.model.TimersAlarmsView">
|
||||
id="org.eclipse.dd.examples.dsf.TimersView">
|
||||
</view>
|
||||
</extension>
|
||||
<extension
|
||||
|
|
|
@ -64,6 +64,7 @@ public class FileBrowserVMProvider extends AbstractVMProvider
|
|||
addChildNodes(root, new IVMNode[] { fileSystemRoots });
|
||||
IVMNode files = new FileVMNode(this);
|
||||
addChildNodes(fileSystemRoots, new IVMNode[] { files });
|
||||
addChildNodes(files, new IVMNode[] { files });
|
||||
setRootNode(root);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,4 +34,9 @@ class FileVMContext extends AbstractVMContext {
|
|||
public int hashCode() {
|
||||
return fFile.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fFile.toString();
|
||||
}
|
||||
}
|
|
@ -190,7 +190,7 @@ class FileVMNode
|
|||
}
|
||||
|
||||
public void getContextsForEvent(VMDelta parentDelta, Object event, DataRequestMonitor<IVMContext[]> rm) {
|
||||
rm.setStatus(new Status(IStatus.OK, DsfUIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,163 +11,114 @@
|
|||
package org.eclipse.dd.examples.dsf.timers;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMData;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMService;
|
||||
import org.eclipse.dd.dsf.service.AbstractDsfService;
|
||||
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerDMC;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerData;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerTickEvent;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerDMContext;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerTickDMEvent;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* Alarm service tracks a set of alarm objects which are occacionally
|
||||
* triggered by the timers from the TimerService.
|
||||
* The alarm service tracks triggers and alarms. Triggers have a specified
|
||||
* value and can be created and removed independently. Alarms are created
|
||||
* for a specific timer and a trigger, and can indicate whether an alarm is
|
||||
* triggered.
|
||||
* <p>
|
||||
* This service depends on the TimerService, so the TimerService has to be
|
||||
* running before this service is initialized. However, the alarm objects
|
||||
* themeselves do not depend on the timers, they can be listed, created,
|
||||
* removed without any timers present. So a separate context object exists
|
||||
* to track alarm status, which requires both an alarm and a timer in order
|
||||
* to exist.
|
||||
* initialized before this service is initialized.
|
||||
* </p>
|
||||
*/
|
||||
public class AlarmService extends AbstractDsfService
|
||||
implements IDMService
|
||||
{
|
||||
/**
|
||||
* Event indicating that the list of alarms is changed and the clients
|
||||
* which display alarms should re-query this list.
|
||||
*/
|
||||
public class AlarmsChangedEvent extends AbstractDMEvent<IDMContext> {
|
||||
AlarmsChangedEvent() { super(fAlarmsContext); }
|
||||
}
|
||||
/** Event indicating that the list of triggers is changed. */
|
||||
@Immutable
|
||||
public static class TriggersChangedEvent {}
|
||||
|
||||
/**
|
||||
* Context representing an alarm tracked by this service.
|
||||
*/
|
||||
public static class AlarmDMC extends AbstractDMContext {
|
||||
/** Context representing an alarm tracked by this service. */
|
||||
@Immutable
|
||||
public static class TriggerDMContext extends AbstractDMContext {
|
||||
/** Alarm number, also index into alarm map */
|
||||
final int fAlarm;
|
||||
final int fNumber;
|
||||
|
||||
public AlarmDMC(AlarmService service, int alarm) {
|
||||
super(service, new IDMContext[] { service.fAlarmsContext });
|
||||
fAlarm = alarm;
|
||||
private TriggerDMContext(String sessionId, int number) {
|
||||
super(sessionId, new IDMContext[0]);
|
||||
fNumber = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return baseEquals(other) && ((AlarmDMC)other).fAlarm == fAlarm;
|
||||
return baseEquals(other) &&
|
||||
((TriggerDMContext)other).fNumber == fNumber;
|
||||
}
|
||||
|
||||
public int getTriggerNumber() {
|
||||
return fNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() { return baseHashCode() + fAlarm; }
|
||||
public int hashCode() {
|
||||
return baseHashCode() + fNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return baseToString() + ".alarm[" + fAlarm + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
|
||||
public String toString() {
|
||||
return baseToString() + ".trigger[" + fNumber + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data object containing information about the alarm. This object
|
||||
* references internal service data, so it has to guard agains this data
|
||||
* being obsolete.
|
||||
*/
|
||||
public class AlarmData implements IDMData {
|
||||
private int fAlarmNumber;
|
||||
|
||||
AlarmData(int alarmNumber) { fAlarmNumber = alarmNumber; }
|
||||
public boolean isValid() { return fAlarms.containsKey(fAlarmNumber); }
|
||||
public int getAlarmNumber() { return fAlarmNumber; }
|
||||
|
||||
public int getTriggeringValue() {
|
||||
if (!isValid()) return -1;
|
||||
return fAlarms.get(fAlarmNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Context representing the "triggered" status of an alarm with respect to
|
||||
* a specific timer. Having this object separate from the alarm itself
|
||||
* allows the alarm object to exist independently of the timers.
|
||||
* a specific timer.
|
||||
*/
|
||||
public class AlarmStatusContext extends AbstractDMContext {
|
||||
/**
|
||||
* An alarm status requires both a timer and alarm context, both of which
|
||||
* become parents of the status context.
|
||||
*/
|
||||
public AlarmStatusContext(AbstractDsfService service, TimerDMC timerCtx, AlarmDMC alarmCtx) {
|
||||
super(service.getSession().getId(), new IDMContext[] { timerCtx, alarmCtx });
|
||||
@Immutable
|
||||
public static class AlarmDMContext extends AbstractDMContext {
|
||||
// An alarm requires both a timer and alarm context, both of which
|
||||
// become parents of the alarm context.
|
||||
// Note: beyond the parent contexts this context does not contain
|
||||
// any other data, because no other data is needed.
|
||||
private AlarmDMContext(String sessionId,
|
||||
TimerDMContext timerCtx, TriggerDMContext alarmCtx)
|
||||
{
|
||||
super(sessionId, new IDMContext[] { timerCtx, alarmCtx });
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) { return baseEquals(other); }
|
||||
|
||||
@Override
|
||||
public int hashCode() { return baseHashCode(); }
|
||||
public int hashCode() { return baseHashCode(); }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return baseToString() + ":alarm_status"; //$NON-NLS-1$
|
||||
return baseToString() + ":alarm"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data about alarm status. No surprises here.
|
||||
*
|
||||
* Event indicating that an alarm has been triggered by a timer.
|
||||
*/
|
||||
public class AlarmStatusData implements IDMData {
|
||||
private boolean fIsTriggered;
|
||||
|
||||
public boolean isValid() { return true; }
|
||||
AlarmStatusData(boolean triggered) { fIsTriggered = triggered; }
|
||||
public boolean isTriggered() { return fIsTriggered; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Event indicating that an alarm has been triggered by a timer. The
|
||||
* status context object's parents indicate which alarm and timer are
|
||||
* involved.
|
||||
*/
|
||||
public class AlarmTriggeredEvent extends AbstractDMEvent<AlarmStatusContext> {
|
||||
public AlarmTriggeredEvent(AlarmStatusContext context) {
|
||||
public class AlarmTriggeredEvent extends AbstractDMEvent<AlarmDMContext> {
|
||||
public AlarmTriggeredEvent(AlarmDMContext context) {
|
||||
super(context);
|
||||
}
|
||||
}
|
||||
|
||||
private int fTriggerNumberCounter = 1;
|
||||
private Map<TriggerDMContext, Integer> fTriggers =
|
||||
new LinkedHashMap<TriggerDMContext, Integer>();
|
||||
|
||||
/** Parent context for all alarms */
|
||||
private final IDMContext fAlarmsContext;
|
||||
|
||||
/** Counter for generating alarm numbers */
|
||||
private int fAlarmCounter = 1;
|
||||
|
||||
/** Map holding the alarms */
|
||||
private Map<Integer,Integer> fAlarms = new TreeMap<Integer,Integer>();
|
||||
|
||||
/** Constructor requires only the session for this service */
|
||||
AlarmService(DsfSession session) {
|
||||
super(session);
|
||||
fAlarmsContext = new AbstractDMContext(this, new IDMContext[0]) {
|
||||
private final Object fHashObject = new Object();
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) { return (this == obj); };
|
||||
|
||||
@Override
|
||||
public int hashCode() { return fHashObject.hashCode(); }
|
||||
|
||||
@Override
|
||||
public String toString() { return "#alarms"; } //$NON-NLS-1$
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -181,17 +132,20 @@ public class AlarmService extends AbstractDsfService
|
|||
new RequestMonitor(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
// After super-class is finished initializing
|
||||
// perform TimerService initialization.
|
||||
doInitialize(requestMonitor);
|
||||
}});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization routine registers the service, and adds it as a listener
|
||||
* to service events.
|
||||
*/
|
||||
private void doInitialize(RequestMonitor requestMonitor) {
|
||||
// Add this class as a listener for service events, in order to receive
|
||||
// TimerTickEvent events.
|
||||
getSession().addServiceEventListener(this, null);
|
||||
|
||||
// Register service
|
||||
register(new String[]{AlarmService.class.getName()}, new Hashtable<String,String>());
|
||||
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
|
@ -204,158 +158,95 @@ public class AlarmService extends AbstractDsfService
|
|||
|
||||
public boolean isValid() { return true; }
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
|
||||
if (dmc instanceof AlarmDMC) {
|
||||
getAlarmData((AlarmDMC)dmc, (DataRequestMonitor<AlarmData>)rm);
|
||||
return;
|
||||
} else if (dmc instanceof AlarmStatusContext) {
|
||||
getAlarmStatusData((AlarmStatusContext)dmc, (DataRequestMonitor<AlarmStatusData>)rm);
|
||||
return;
|
||||
} else if (dmc == fAlarmsContext) {
|
||||
((DataRequestMonitor<AlarmService>)rm).setData(this);
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for timer ticks events. If a timer triggers an alarm, this
|
||||
* service needs to issue an alarm triggered event.
|
||||
* @param event
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(TimerTickEvent event) {
|
||||
final TimerDMC timerContext = event.getDMContext();
|
||||
public void eventDispatched(TimerTickDMEvent event) {
|
||||
final TimerDMContext timerContext = event.getDMContext();
|
||||
|
||||
getServicesTracker().getService(TimerService.class).getTimerData(
|
||||
event.getDMContext(),
|
||||
new DataRequestMonitor<TimerData>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!getStatus().isOK()) return;
|
||||
checkAlarmsForTimer(timerContext, getData().getTimerValue());
|
||||
}
|
||||
@Override public String toString() { return "Got timer data: " + getData(); } //$NON-NLS-1$
|
||||
});
|
||||
int timerValue = getServicesTracker().getService(TimerService.class).
|
||||
getTimerValue(event.getDMContext());
|
||||
|
||||
// If a timer triggers an alarm, this service needs to issue an alarm
|
||||
// triggered event.
|
||||
checkAlarmsForTimer(timerContext, timerValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the existing alarms for whether they are triggered by given timer.
|
||||
* @param timerContext Context of the timer that is changed.
|
||||
* @param timerValue Current value of the timer.
|
||||
*/
|
||||
private void checkAlarmsForTimer(TimerDMC timerContext, int timerValue) {
|
||||
for (Map.Entry<Integer,Integer> entry : fAlarms.entrySet()) {
|
||||
private void checkAlarmsForTimer(TimerDMContext timerContext, int timerValue) {
|
||||
// Check the existing alarms for whether they are triggered by given
|
||||
// timer.
|
||||
for (Map.Entry<TriggerDMContext, Integer> entry : fTriggers.entrySet()) {
|
||||
if (timerValue == entry.getValue()) {
|
||||
getSession().dispatchEvent(new AlarmTriggeredEvent(
|
||||
new AlarmStatusContext(this, timerContext, new AlarmDMC(this, entry.getKey()))),
|
||||
getProperties());
|
||||
// Generate the AlarmTriggeredEvent
|
||||
AlarmDMContext alarmCtx = new AlarmDMContext(
|
||||
getSession().getId(), timerContext, entry.getKey());
|
||||
getSession().dispatchEvent(
|
||||
new AlarmTriggeredEvent(alarmCtx), getProperties());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the list of alarm contexts.
|
||||
*
|
||||
* <br>Note: this method doesn't need to be asynchronous, because all the
|
||||
* data is stored locally. But using an asynchronous method makes this a
|
||||
* more applicable example.
|
||||
*
|
||||
* @param rm Return data token.
|
||||
*/
|
||||
public void getAlarms(DataRequestMonitor<AlarmDMC[]> rm) {
|
||||
AlarmDMC[] alarmContexts = new AlarmDMC[fAlarms.size()];
|
||||
int i = 0;
|
||||
for (int alarm : fAlarms.keySet()) {
|
||||
alarmContexts[i++] = new AlarmDMC(this, alarm);
|
||||
/** Returns the list of triggers. */
|
||||
public TriggerDMContext[] getTriggers() {
|
||||
return fTriggers.keySet().toArray(new TriggerDMContext[fTriggers.size()]);
|
||||
}
|
||||
|
||||
/** Returns the trigger value. */
|
||||
public int getTriggerValue(TriggerDMContext alarmCtx) {
|
||||
Integer value = fTriggers.get(alarmCtx);
|
||||
if (value != null) {
|
||||
return value;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
rm.setData(alarmContexts);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the data object for given alarm context.
|
||||
*
|
||||
* <br>Note: likewise this method doesn't need to be asynchronous.
|
||||
*/
|
||||
public void getAlarmData(AlarmDMC alarmCtx, DataRequestMonitor<AlarmData> rm) {
|
||||
if (!fAlarms.containsKey(alarmCtx.fAlarm)) {
|
||||
rm.setStatus(new Status(
|
||||
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, INVALID_HANDLE, "Alarm context invalid", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
/** Returns the alarm context for given timer and trigger contexts. */
|
||||
public AlarmDMContext getAlarmS(TriggerDMContext alarmCtx, TimerDMContext timerCtx) {
|
||||
return new AlarmDMContext(getSession().getId(), timerCtx, alarmCtx);
|
||||
}
|
||||
|
||||
/** Returns true if the given alarm is triggered */
|
||||
public boolean isAlarmTriggered(AlarmDMContext alarmCtx) {
|
||||
// Extract the timer and trigger contexts. They should always be part
|
||||
// of the alarm.
|
||||
TimerService.TimerDMContext timerCtx = DMContexts.getAncestorOfType(
|
||||
alarmCtx, TimerService.TimerDMContext.class);
|
||||
TriggerDMContext triggerCtx = DMContexts.getAncestorOfType(
|
||||
alarmCtx, TriggerDMContext.class);
|
||||
|
||||
assert triggerCtx != null && timerCtx != null;
|
||||
|
||||
// Find the trigger and check whether the timers value has surpassed it.
|
||||
if (fTriggers.containsKey(triggerCtx)) {
|
||||
int timerValue = getServicesTracker().getService(TimerService.class).
|
||||
getTimerValue(timerCtx);
|
||||
|
||||
return timerValue >= fTriggers.get(triggerCtx);
|
||||
}
|
||||
rm.setData(new AlarmData(alarmCtx.fAlarm));
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the alarm status context object, for given timer and alarms.
|
||||
*
|
||||
* <br>Note: this method is synchronous... for variety.
|
||||
*/
|
||||
public AlarmStatusContext getAlarmStatus(AlarmDMC alarmCtx, TimerDMC timerCtx) {
|
||||
return new AlarmStatusContext(this, timerCtx, alarmCtx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data object for given alarm status object.
|
||||
*/
|
||||
public void getAlarmStatusData(AlarmStatusContext alarmStatusCtx, final DataRequestMonitor<AlarmStatusData> rm) {
|
||||
final TimerService.TimerDMC timerCtx = DMContexts.getAncestorOfType(
|
||||
alarmStatusCtx, TimerService.TimerDMC.class);
|
||||
final AlarmDMC alarmCtx = DMContexts.getAncestorOfType(
|
||||
alarmStatusCtx, AlarmDMC.class);
|
||||
|
||||
assert alarmCtx != null && timerCtx != null;
|
||||
|
||||
getServicesTracker().getService(TimerService.class).getTimerData(
|
||||
timerCtx,
|
||||
new DataRequestMonitor<TimerData>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
if (!fAlarms.containsKey(alarmCtx.fAlarm)) {
|
||||
rm.setStatus(new Status(
|
||||
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, INVALID_HANDLE, "Alarm context invalid", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
boolean isTriggered = getData().getTimerValue() >= fAlarms.get(alarmCtx.fAlarm);
|
||||
rm.setData(new AlarmStatusData(isTriggered));
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new alarm object with given value.
|
||||
* @return context of the new alarm.
|
||||
*/
|
||||
public AlarmDMC createAlarm(int value) {
|
||||
int newAlarm = fAlarmCounter++;
|
||||
fAlarms.put(newAlarm, value);
|
||||
getSession().dispatchEvent(new AlarmsChangedEvent(), getProperties());
|
||||
return new AlarmDMC(this, newAlarm);
|
||||
/** Creates a new alarm object with given value. */
|
||||
public TriggerDMContext createTrigger(int value) {
|
||||
TriggerDMContext triggerCtx =
|
||||
new TriggerDMContext(getSession().getId(), fTriggerNumberCounter++);
|
||||
fTriggers.put(triggerCtx, value);
|
||||
getSession().dispatchEvent(new TriggersChangedEvent(), getProperties());
|
||||
return triggerCtx;
|
||||
}
|
||||
|
||||
/** Removes given alarm from service. */
|
||||
public void deleteAlarm(AlarmDMC alarmCtx) {
|
||||
fAlarms.remove(alarmCtx.fAlarm);
|
||||
getSession().dispatchEvent(new AlarmsChangedEvent(), getProperties());
|
||||
public void deleteTrigger(TriggerDMContext alarmCtx) {
|
||||
fTriggers.remove(alarmCtx);
|
||||
getSession().dispatchEvent(new TriggersChangedEvent(), getProperties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the value of the given alarm.
|
||||
* @param dmc Alarm to change
|
||||
* @param newValue New alarm value.
|
||||
*/
|
||||
public void setAlarmValue(AlarmDMC dmc, int newValue) {
|
||||
if (fAlarms.containsKey(dmc.fAlarm)) {
|
||||
fAlarms.put(dmc.fAlarm, newValue);
|
||||
/** Changes the value of the given trigger. */
|
||||
public void setTriggerValue(TriggerDMContext ctx, int newValue) {
|
||||
if (fTriggers.containsKey(ctx)) {
|
||||
fTriggers.put(ctx, newValue);
|
||||
}
|
||||
getSession().dispatchEvent(new AlarmsChangedEvent(), getProperties());
|
||||
getSession().dispatchEvent(new TriggersChangedEvent(), getProperties());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.examples.dsf.timers;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.AlarmDMC;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.AlarmStatusContext;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.AlarmStatusData;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerDMC;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
|
||||
/**
|
||||
* View model node that determines whether an "alarm triggered" indicator is
|
||||
* shown in the tree. This indicator is only shown if a given alarm is
|
||||
* triggered for a given timer.
|
||||
*
|
||||
* @see AlarmStatusContext
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
class AlarmStatusVMNode extends AbstractDMVMNode
|
||||
implements IElementLabelProvider
|
||||
{
|
||||
public AlarmStatusVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, AlarmStatusContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
if (!checkService(AlarmService.class, null, update)) return;
|
||||
if (!checkService(TimerService.class, null, update)) return;
|
||||
|
||||
AlarmDMC alarmDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), AlarmDMC.class);
|
||||
TimerDMC timerDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), TimerDMC.class);
|
||||
if (alarmDmc == null || timerDmc == null) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Required elements not found in path")); //$NON-NLS-1$
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the alarm status DMC then check the triggered value to make sure it's triggered.
|
||||
final AlarmStatusContext alarmStatusDmc = getServicesTracker().getService(AlarmService.class).
|
||||
getAlarmStatus(alarmDmc, timerDmc);
|
||||
getServicesTracker().getService(AlarmService.class).getAlarmStatusData(
|
||||
alarmStatusDmc,
|
||||
new DataRequestMonitor<AlarmStatusData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
if (!getStatus().isOK()) {
|
||||
update.setStatus(getStatus());
|
||||
} else {
|
||||
if (getData().isTriggered()) {
|
||||
update.setChild(createVMContext(alarmStatusDmc), 0);
|
||||
}
|
||||
}
|
||||
update.done();
|
||||
}});
|
||||
}
|
||||
|
||||
public void update(ILabelUpdate[] updates) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
update.setLabel("ALARM TRIGGERED", 0); //$NON-NLS-1$
|
||||
update.setImageDescriptor(
|
||||
DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(
|
||||
DsfExamplesPlugin.IMG_ALARM_TRIGGERED),
|
||||
0);
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getDeltaFlags(Object e) {
|
||||
// This node generates delta if the timers have changed, or if the
|
||||
// label has changed.
|
||||
if (e instanceof AlarmService.AlarmTriggeredEvent) {
|
||||
return IModelDelta.ADDED | IModelDelta.SELECT | IModelDelta.EXPAND;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
public void buildDelta(Object e, VMDelta parentDelta, int nodeOffset, RequestMonitor requestMonitor) {
|
||||
// An element is added when and selected upon a triggered event.
|
||||
// Parent element is also expanded allow element to be selected.
|
||||
if (e instanceof AlarmService.AlarmTriggeredEvent) {
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.EXPAND);
|
||||
parentDelta.addNode(
|
||||
createVMContext( ((AlarmService.AlarmTriggeredEvent)e).getDMContext() ),
|
||||
0,
|
||||
IModelDelta.ADDED | IModelDelta.SELECT);
|
||||
}
|
||||
requestMonitor.done();
|
||||
}
|
||||
}
|
|
@ -10,203 +10,96 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.dsf.timers;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelAttribute;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelColumnInfo;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelImage;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.PropertyBasedLabelProvider;
|
||||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.AlarmDMC;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.AlarmData;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.AlarmDMContext;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.TriggerDMContext;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerDMContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.CellEditor;
|
||||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
|
||||
/**
|
||||
* View model node that defines how alarm DMContexts are displayed in the view. Alarm
|
||||
* nodes are fairly static, once they are created their label doesn't change.
|
||||
* @see AlarmDMC
|
||||
* View model node that determines whether an "alarm triggered" indicator is
|
||||
* shown in the tree. This indicator is only shown if a given alarm is
|
||||
* triggered for a given timer.
|
||||
*
|
||||
* @see AlarmDMContext
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
class AlarmsVMNode extends AbstractDMVMNode
|
||||
implements IElementEditor, IElementPropertiesProvider, IElementLabelProvider
|
||||
implements IElementLabelProvider
|
||||
{
|
||||
public static final String PROP_ALARM_NUMBER = "alarmNumber"; //$NON-NLS-1$
|
||||
public static final String PROP_ALARM_TRIGGER_VALUE = "alarmTriggerValue"; //$NON-NLS-1$
|
||||
|
||||
private AlarmCellModifier fAlarmCellModifier;
|
||||
private PropertyBasedLabelProvider fLabelProvider;
|
||||
|
||||
|
||||
public AlarmsVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, AlarmDMC.class);
|
||||
|
||||
fLabelProvider = new PropertyBasedLabelProvider();
|
||||
|
||||
LabelColumnInfo idCol = new LabelColumnInfo(
|
||||
new LabelAttribute[] {
|
||||
new LabelText(new MessageFormat("Alarm #{0}"), new String[] { PROP_ALARM_NUMBER }), //$NON-NLS-1$
|
||||
new LabelImage(DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(DsfExamplesPlugin.IMG_ALARM))
|
||||
});
|
||||
fLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_ID, idCol);
|
||||
|
||||
LabelText valueText = new LabelText(new MessageFormat("{0}"), new String[] { PROP_ALARM_TRIGGER_VALUE }); //$NON-NLS-1$
|
||||
LabelColumnInfo valueCol = new LabelColumnInfo(
|
||||
new LabelAttribute[] {
|
||||
new LabelText(new MessageFormat("{0}"), new String[] { PROP_ALARM_TRIGGER_VALUE }) //$NON-NLS-1$
|
||||
});
|
||||
fLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_VALUE, valueCol);
|
||||
|
||||
super(provider, session, AlarmDMContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
// Check that the services are available
|
||||
if (!checkService(AlarmService.class, null, update)) return;
|
||||
if (!checkService(TimerService.class, null, update)) return;
|
||||
|
||||
// Retrieve the alarm DMContexts, create the corresponding VMCs array, and
|
||||
// set them as result.
|
||||
getServicesTracker().getService(AlarmService.class).getAlarms(
|
||||
new DataRequestMonitor<AlarmDMC[]>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
update.setStatus(getStatus());
|
||||
} else {
|
||||
fillUpdateWithVMCs(update, getData());
|
||||
}
|
||||
update.done();
|
||||
}});
|
||||
// Find the trigger and timer contexts. If not found, fail.
|
||||
TriggerDMContext alarmDmc = findDmcInPath(
|
||||
update.getViewerInput(), update.getElementPath(), TriggerDMContext.class);
|
||||
TimerDMContext timerDmc = findDmcInPath(
|
||||
update.getViewerInput(), update.getElementPath(), TimerDMContext.class);
|
||||
if (alarmDmc == null || timerDmc == null) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Required elements not found in path"));
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the alarm context then check the triggered value.
|
||||
final AlarmDMContext alarmStatusDmc = getServicesTracker().getService(AlarmService.class).
|
||||
getAlarmS(alarmDmc, timerDmc);
|
||||
boolean triggered = getServicesTracker().getService(AlarmService.class).
|
||||
isAlarmTriggered(alarmStatusDmc);
|
||||
|
||||
// Only return the alarm in list of elements if it is triggered.
|
||||
if (triggered) {
|
||||
update.setChild(createVMContext(alarmStatusDmc), 0);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
|
||||
public void update(ILabelUpdate[] updates) {
|
||||
fLabelProvider.update(updates);
|
||||
}
|
||||
|
||||
public void update(final IPropertiesUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
updatePropertiesInSessionThread(update);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IViewerUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
for (ILabelUpdate update : updates) {
|
||||
update.setLabel("ALARM TRIGGERED", 0);
|
||||
update.setImageDescriptor(
|
||||
DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(
|
||||
DsfExamplesPlugin.IMG_ALARM_TRIGGERED),
|
||||
0);
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
@ConfinedToDsfExecutor("getSession#getExecutor")
|
||||
protected void updatePropertiesInSessionThread(final IPropertiesUpdate update) {
|
||||
final AlarmDMC dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), AlarmDMC.class);
|
||||
if (!checkDmc(dmc, update) || !checkService(AlarmService.class, null, update)) return;
|
||||
|
||||
getDMVMProvider().getModelData(
|
||||
this, update,
|
||||
getServicesTracker().getService(AlarmService.class, null),
|
||||
dmc,
|
||||
new DataRequestMonitor<AlarmData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
/*
|
||||
* Check that the request was evaluated and data is still
|
||||
* valid. The request could fail if the state of the
|
||||
* service changed during the request, but the view model
|
||||
* has not been updated yet.
|
||||
*/
|
||||
if (!getStatus().isOK() || !getData().isValid()) {
|
||||
assert getStatus().isOK() ||
|
||||
getStatus().getCode() != IDsfService.INTERNAL_ERROR ||
|
||||
getStatus().getCode() != IDsfService.NOT_SUPPORTED;
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
update.setProperty(PROP_ALARM_NUMBER, getData().getAlarmNumber());
|
||||
update.setProperty(PROP_ALARM_TRIGGER_VALUE, getData().getTriggeringValue());
|
||||
update.done();
|
||||
}
|
||||
},
|
||||
getExecutor());
|
||||
}
|
||||
|
||||
public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
|
||||
if (TimersViewColumnPresentation.COL_VALUE.equals(columnId)) {
|
||||
return new TextCellEditor(parent);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Note: this method is synchronized because IElementEditor.getCellModifier can be called
|
||||
// on any thread, even though in practice it should be only called on the UI thread.
|
||||
public synchronized ICellModifier getCellModifier(IPresentationContext context, Object element) {
|
||||
if (fAlarmCellModifier == null) {
|
||||
fAlarmCellModifier = new AlarmCellModifier(getSession());
|
||||
}
|
||||
return fAlarmCellModifier;
|
||||
}
|
||||
|
||||
public int getDeltaFlags(Object e) {
|
||||
// Since the label for alarms doesn't change, this node will generate
|
||||
// delta info only if the list of alarms is changed.
|
||||
if (e instanceof AlarmService.AlarmsChangedEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
if (e instanceof AlarmService.AlarmTriggeredEvent) {
|
||||
return IModelDelta.ADDED | IModelDelta.SELECT | IModelDelta.EXPAND;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
|
||||
public void buildDelta(Object event, VMDelta parentDelta, int nodeOffset, RequestMonitor requestMonitor) {
|
||||
if (event instanceof AlarmService.AlarmsChangedEvent) {
|
||||
// The list of alarms has changed, which means that the parent
|
||||
// node needs to refresh its contents, which in turn will re-fetch the
|
||||
// elements from this node.
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
|
||||
public void buildDelta(Object e, VMDelta parentDelta, int nodeOffset, RequestMonitor requestMonitor) {
|
||||
// The alarm element is added when and selected upon a triggered event.
|
||||
// Parent element is also expanded allow the alarm to be selected.
|
||||
if (e instanceof AlarmService.AlarmTriggeredEvent) {
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.EXPAND);
|
||||
parentDelta.addNode(
|
||||
createVMContext( ((AlarmService.AlarmTriggeredEvent)e).getDMContext() ),
|
||||
0,
|
||||
IModelDelta.ADDED | IModelDelta.SELECT);
|
||||
}
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void dispose() {
|
||||
synchronized(this) {
|
||||
if (fAlarmCellModifier != null) {
|
||||
fAlarmCellModifier.dispose();
|
||||
}
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public String getPropertyDescription(String property) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPropertyName(String property) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,15 +20,19 @@ import org.eclipse.dd.dsf.service.IDsfService;
|
|||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
|
||||
/**
|
||||
* Shutdown sequence that stops the services in the timers session.
|
||||
*
|
||||
* Sequence that stops the services in the timers session.
|
||||
*/
|
||||
class ServicesShutdownSequence extends Sequence {
|
||||
public class ServicesShutdownSequence extends Sequence {
|
||||
|
||||
DsfSession fSession;
|
||||
// Session to that the services are running in.
|
||||
final private DsfSession fSession;
|
||||
|
||||
// DSF Services is created as the first step of the sequence. It
|
||||
// cannot be created by the constructor because it can only be called
|
||||
// in the session thread.
|
||||
DsfServicesTracker fTracker;
|
||||
|
||||
ServicesShutdownSequence(DsfSession session) {
|
||||
public ServicesShutdownSequence(DsfSession session) {
|
||||
super(session.getExecutor());
|
||||
fSession = session;
|
||||
}
|
||||
|
@ -43,6 +47,8 @@ class ServicesShutdownSequence extends Sequence {
|
|||
|
||||
@Override
|
||||
public void rollBack(RequestMonitor requestMonitor) {
|
||||
// Dispose the tracker in case shutdown sequence is aborted
|
||||
// and is rolled back.
|
||||
fTracker.dispose();
|
||||
fTracker = null;
|
||||
requestMonitor.done();
|
||||
|
@ -63,6 +69,7 @@ class ServicesShutdownSequence extends Sequence {
|
|||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor requestMonitor) {
|
||||
// Dispose the tracker after the services are shut down.
|
||||
fTracker.dispose();
|
||||
fTracker = null;
|
||||
requestMonitor.done();
|
||||
|
@ -73,18 +80,18 @@ class ServicesShutdownSequence extends Sequence {
|
|||
@Override
|
||||
public Step[] getSteps() { return fSteps; }
|
||||
|
||||
/**
|
||||
* Convenience method that shuts down given service. Only service class
|
||||
* is used to identify the service.
|
||||
*/
|
||||
// A convenience method that shuts down given service. Only service class
|
||||
// is used to identify the service.
|
||||
private <V extends IDsfService> void shutdownService(Class<V> clazz, RequestMonitor requestMonitor) {
|
||||
IDsfService service = fTracker.getService(clazz);
|
||||
if (service != null) {
|
||||
service.shutdown(requestMonitor);
|
||||
}
|
||||
else {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
|
||||
"Service '" + clazz.getName() + "' not found.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
requestMonitor.setStatus(new Status(
|
||||
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||
IDsfService.INTERNAL_ERROR,
|
||||
"Service '" + clazz.getName() + "' not found.", null));
|
||||
requestMonitor.done();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,16 +16,18 @@ import org.eclipse.dd.dsf.service.DsfSession;
|
|||
|
||||
/**
|
||||
* Startup sequence for the timers session. With only two services, this is
|
||||
* a very simple sequence. Last step creates the first timer and alarm.
|
||||
* a very simple sequence.
|
||||
*/
|
||||
class ServicesStartupSequence extends Sequence {
|
||||
public class ServicesStartupSequence extends Sequence {
|
||||
|
||||
DsfSession fSession;
|
||||
final private DsfSession fSession;
|
||||
|
||||
// The reference to the services are saved to use in the last step.
|
||||
private TimerService fTimerService = null;
|
||||
private AlarmService fAlarmService = null;
|
||||
|
||||
|
||||
ServicesStartupSequence(DsfSession session) {
|
||||
public ServicesStartupSequence(DsfSession session) {
|
||||
super(session.getExecutor());
|
||||
fSession = session;
|
||||
}
|
||||
|
@ -46,8 +48,9 @@ class ServicesStartupSequence extends Sequence {
|
|||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor requestMonitor) {
|
||||
// Create the first timer and trigger.
|
||||
fTimerService.startTimer();
|
||||
fAlarmService.createAlarm(5);
|
||||
fAlarmService.createTrigger(5);
|
||||
requestMonitor.done();
|
||||
}}
|
||||
};
|
||||
|
|
|
@ -10,21 +10,18 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.dsf.timers;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMData;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMService;
|
||||
import org.eclipse.dd.dsf.service.AbstractDsfService;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
|
@ -32,121 +29,73 @@ import org.osgi.framework.BundleContext;
|
|||
|
||||
/**
|
||||
* Timer service tracks a set of timers, which are created per user request.
|
||||
* The timers and their data are provided by the service using the DSF data
|
||||
* model interfaces.
|
||||
* <p>
|
||||
* When each timer is created, an event is issued that the service contents are
|
||||
* changed, and clients should re-query the list of timers. The timers
|
||||
* increment their value at rate of one per second (but they are not synchronous),
|
||||
* and an event is issued for every tick.
|
||||
* The timers are represented using a Data Model context object, which
|
||||
* implements {@link IDMContext}. Each timers value, which can be retrieved
|
||||
* by calling {@link #getTimerValue(TimerDMContext)}, is incremented every
|
||||
* second. When a timer value is incremented the TimerService issues a
|
||||
* {@link TimerTickDMEvent}.
|
||||
*/
|
||||
public class TimerService extends AbstractDsfService
|
||||
implements IDMService
|
||||
{
|
||||
/**
|
||||
* Event indicating that the list of timers is changed and the clients
|
||||
* which display timers should re-query this list.
|
||||
*/
|
||||
public class TimersChangedEvent extends AbstractDMEvent<IDMContext> {
|
||||
TimersChangedEvent() { super(fTimersContext); }
|
||||
}
|
||||
/** Event indicating that the list of timers is changed. */
|
||||
@Immutable
|
||||
public static class TimersChangedEvent {}
|
||||
|
||||
/**
|
||||
* Timer context represents a timer in this service. Clients can use this
|
||||
* context to retrieve timer data. This class implements the <code>Comaparable</code>
|
||||
* interfaces so that the objects can be stored in a TreeMap, which keeps them sorted.
|
||||
*/
|
||||
public static class TimerDMC extends AbstractDMContext
|
||||
implements Comparable<TimerDMC>
|
||||
{
|
||||
/**
|
||||
* Timer number, which is also index to timers map.
|
||||
*/
|
||||
final int fTimer;
|
||||
/** Data Model context representing a timer. */
|
||||
@Immutable
|
||||
public static class TimerDMContext extends AbstractDMContext {
|
||||
final int fNumber;
|
||||
|
||||
public TimerDMC(TimerService service, int timer) {
|
||||
super(service, new IDMContext[] { service.fTimersContext });
|
||||
fTimer = timer;
|
||||
public TimerDMContext(String sessionId, int timer) {
|
||||
super(sessionId, new IDMContext[0]);
|
||||
fNumber = timer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer context objects are created as needed and not cached, so the
|
||||
* equals method implementation is critical.
|
||||
*/
|
||||
/** Returns the sequential creation number of this timer. */
|
||||
public int getTimerNumber() {
|
||||
return fNumber;
|
||||
}
|
||||
|
||||
// Timer context objects are created as needed and not cached, so the
|
||||
// equals method implementation is critical.
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return baseEquals(other) && ((TimerDMC)other).fTimer == fTimer;
|
||||
return baseEquals(other) &&
|
||||
((TimerDMContext)other).fNumber == fNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() { return baseHashCode() + fTimer; }
|
||||
public int hashCode() { return baseHashCode() + fNumber; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return baseToString() + ".timer[" + fTimer + "]"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
public int compareTo(TimerDMC other) {
|
||||
TimerDMC otherTimer = other;
|
||||
return (fTimer < otherTimer.fTimer ? -1 : (fTimer == otherTimer.fTimer ? 0 : 1));
|
||||
return baseToString() + ".timer[" + fNumber + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data about the timer in the service. This object references internal
|
||||
* service data, so it has to guard agains this data being obsolete.
|
||||
*/
|
||||
public class TimerData implements IDMData {
|
||||
TimerDMC fTimerDMC;
|
||||
|
||||
TimerData(TimerDMC timer) { fTimerDMC = timer; }
|
||||
public boolean isValid() { return fTimers.containsKey(fTimerDMC); }
|
||||
public int getTimerNumber() { return fTimerDMC.fTimer; }
|
||||
|
||||
public int getTimerValue() {
|
||||
if (!isValid()) return -1;
|
||||
return fTimers.get(fTimerDMC);
|
||||
}
|
||||
|
||||
@Override public String toString() { return "Timer " + fTimerDMC.fTimer + " = " + getTimerValue(); } //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
/**
|
||||
* Event indicating that a timer's value has incremented. The context in
|
||||
* the event points to the timer that has changed.
|
||||
*/
|
||||
public class TimerTickEvent extends AbstractDMEvent<TimerDMC> {
|
||||
public TimerTickEvent(TimerDMC context) {
|
||||
public class TimerTickDMEvent extends AbstractDMEvent<TimerDMContext> {
|
||||
public TimerTickDMEvent(TimerDMContext context) {
|
||||
super(context);
|
||||
}
|
||||
}
|
||||
|
||||
/** Parnet context for all timers */
|
||||
private final IDMContext fTimersContext;
|
||||
|
||||
/** Counter for generating timer numbers */
|
||||
private int fTimerCounter = 1;
|
||||
private int fTimerNumberCounter = 1;
|
||||
|
||||
/** Map holding the timers */
|
||||
private Map<TimerDMC, Integer> fTimers = new TreeMap<TimerDMC, Integer>();
|
||||
// Use a linked hash in order to be able to return an ordered list of timers.
|
||||
private Map<TimerDMContext, Integer> fTimers =
|
||||
new LinkedHashMap<TimerDMContext, Integer>();
|
||||
|
||||
private Map<TimerDMContext, Future<?>> fTimerFutures =
|
||||
new HashMap<TimerDMContext, Future<?>>();
|
||||
|
||||
private Map<TimerDMC, Future<?>> fTimerFutures = new TreeMap<TimerDMC, Future<?>>();
|
||||
|
||||
/** Constructor requires only the session for this service */
|
||||
TimerService(DsfSession session) {
|
||||
super(session);
|
||||
fTimersContext = new AbstractDMContext(this, new IDMContext[0]) {
|
||||
private final Object fHashObject = new Object();
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) { return (this == obj); };
|
||||
|
||||
@Override
|
||||
public int hashCode() { return fHashObject.hashCode(); }
|
||||
|
||||
@Override
|
||||
public String toString() { return "#timers"; } //$NON-NLS-1$
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -160,97 +109,72 @@ public class TimerService extends AbstractDsfService
|
|||
new RequestMonitor(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
public void handleOK() {
|
||||
// After super-class is finished initializing
|
||||
// perform TimerService initialization.
|
||||
doInitialize(requestMonitor);
|
||||
}});
|
||||
}
|
||||
|
||||
private void doInitialize(RequestMonitor requestMonitor) {
|
||||
// Register service
|
||||
register( new String[]{ TimerService.class.getName() },
|
||||
new Hashtable<String,String>() );
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown(RequestMonitor requestMonitor) {
|
||||
/*
|
||||
* Go through all the timer futures and cancel them, so that they
|
||||
* don't fire any more events.
|
||||
*/
|
||||
// Cancel timer futures to avoid firing more events.
|
||||
for (Future<?> future : fTimerFutures.values()) {
|
||||
future.cancel(false);
|
||||
}
|
||||
unregister();
|
||||
super.shutdown(requestMonitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the relevant initialization for this service: registering and
|
||||
* scheduling the timer.
|
||||
* @param requestMonitor
|
||||
*/
|
||||
private void doInitialize(RequestMonitor requestMonitor) {
|
||||
register(new String[]{TimerService.class.getName()}, new Hashtable<String,String>());
|
||||
requestMonitor.done();
|
||||
|
||||
/** Retrieves the list of timer contexts. */
|
||||
public TimerDMContext[] getTimers() {
|
||||
return fTimers.keySet().toArray(new TimerDMContext[fTimers.size()]);
|
||||
}
|
||||
|
||||
public boolean isValid() { return true; }
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
|
||||
if (dmc instanceof TimerDMC) {
|
||||
getTimerData((TimerDMC)dmc, (DataRequestMonitor<TimerData>)rm);
|
||||
return;
|
||||
} else if (dmc == fTimersContext) {
|
||||
((DataRequestMonitor<TimerService>)rm).setData(this);
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
|
||||
}
|
||||
rm.done();
|
||||
/** Retrieves the timer value for the given context. */
|
||||
public int getTimerValue(TimerDMContext context) {
|
||||
Integer value = fTimers.get(context);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of timer contexts.
|
||||
*
|
||||
* <br>Note: this method doesn't need to be asynchronous, because all the
|
||||
* data is stored locally. But using an asynchronous method makes this a
|
||||
* more applicable example.
|
||||
*
|
||||
* @param rm Return data token.
|
||||
*/
|
||||
public void getTimers(DataRequestMonitor<TimerDMC[]> rm) {
|
||||
rm.setData( fTimers.keySet().toArray(new TimerDMC[fTimers.size()]) );
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the data object for given timer context.
|
||||
*
|
||||
* <br>Note: likewise this method doesn't need to be asynchronous.
|
||||
*/
|
||||
public void getTimerData(TimerDMC context, DataRequestMonitor<TimerData> rm) {
|
||||
rm.setData(new TimerData(context));
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new timer and returns its context.
|
||||
*/
|
||||
public TimerDMC startTimer() {
|
||||
final TimerDMC newTimer = new TimerDMC(this, fTimerCounter++);
|
||||
/** Creates a new timer and returns its context. */
|
||||
public TimerDMContext startTimer() {
|
||||
// Create a new timer context and add it to the internal list.
|
||||
final TimerDMContext newTimer =
|
||||
new TimerDMContext(getSession().getId(), fTimerNumberCounter++);
|
||||
fTimers.put(newTimer, 0);
|
||||
|
||||
// Create a new runnable that will execute every second and increment
|
||||
// the timer value. The returned future is the handle that allows
|
||||
// for canceling the scheduling of the runnable.
|
||||
Future<?> timerFuture = getExecutor().scheduleAtFixedRate(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
fTimers.put(newTimer, fTimers.get(newTimer) + 1);
|
||||
getSession().dispatchEvent(new TimerTickEvent(newTimer), getProperties());
|
||||
getSession().dispatchEvent(new TimerTickDMEvent(newTimer), getProperties());
|
||||
}
|
||||
@Override
|
||||
public String toString() { return "Scheduled timer runnable for timer " + newTimer; } //$NON-NLS-1$
|
||||
},
|
||||
1, 1, TimeUnit.SECONDS);
|
||||
fTimerFutures.put(newTimer, timerFuture);
|
||||
fTimerFutures.put(newTimer, timerFuture);
|
||||
|
||||
// Issue an event to allow clients to update the list of timers.
|
||||
getSession().dispatchEvent(new TimersChangedEvent(), getProperties());
|
||||
return newTimer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes given timer from list of timers.
|
||||
*/
|
||||
public void killTimer(TimerDMC timerContext) {
|
||||
/** Removes given timer from list of timers. */
|
||||
public void killTimer(TimerDMContext timerContext) {
|
||||
if (fTimers.containsKey(timerContext)) {
|
||||
fTimers.remove(timerContext);
|
||||
fTimerFutures.remove(timerContext).cancel(false);
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 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.dd.examples.dsf.timers;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.RootDMVMNode;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimersVMProvider.TimersViewLayoutChanged;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class TimersRootVMNode extends RootDMVMNode {
|
||||
|
||||
public TimersRootVMNode(AbstractVMProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeltaEvent(Object rootObject, Object e) {
|
||||
if (e instanceof TimersViewLayoutChanged) {
|
||||
return true;
|
||||
}
|
||||
return super.isDeltaEvent(rootObject, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeltaFlags(Object e) {
|
||||
if (e instanceof TimersViewLayoutChanged) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createRootDelta(Object rootObject, Object event, final DataRequestMonitor<VMDelta> rm) {
|
||||
rm.setData(new VMDelta(rootObject, 0, IModelDelta.NO_CHANGE));
|
||||
int flags = IModelDelta.NO_CHANGE;
|
||||
if (event instanceof TimersViewLayoutChanged) {
|
||||
flags |= IModelDelta.CONTENT;
|
||||
}
|
||||
rm.setData( new VMDelta(rootObject, 0, flags) );
|
||||
rm.done();
|
||||
}
|
||||
|
||||
}
|
|
@ -14,49 +14,28 @@ import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
|||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
/**
|
||||
* This is the adapter that implements the flexible hierarchy viewer interfaces
|
||||
* for providing content, labels, and event proxy-ing for the viewer. This
|
||||
* for providing content, labels, and event processing for the viewer. This
|
||||
* adapter is registered with the DSF Session object, and is returned by the
|
||||
* IDMContext.getAdapter() and IVMContext.getAdapter() methods,
|
||||
* which both call {@link DsfSession#getModelAdapter(Class)}.
|
||||
* <p>
|
||||
* The adapter implementation for this excercise is hard-coded to provide
|
||||
* contents for only one view. In turn the view contens are determined using
|
||||
* the configurable ViewModelProvider. For demonstration purposes, this model
|
||||
* adapter has two different layout configurations that can be used. These
|
||||
* layout configurations can be set by calling the {@link #setViewLayout} method.
|
||||
* <p>
|
||||
* This class is primarily accessed by the flexible hierarchy viewer from a
|
||||
* non-executor thread. So the class is thread-safe, except for a view methods
|
||||
* which must be called on the executor thread.
|
||||
*
|
||||
* @see AbstractDMVMProvider
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
@ThreadSafe
|
||||
public class TimersModelAdapter extends AbstractDMVMAdapter
|
||||
public class TimersVMAdapter extends AbstractDMVMAdapter
|
||||
{
|
||||
TimersVMProvider fViewModelProvider;
|
||||
|
||||
@Override
|
||||
protected IVMProvider createViewModelProvider(IPresentationContext context) {
|
||||
/*
|
||||
* In this example there is only one viewer, so there is only one
|
||||
* VMProvider.
|
||||
*/
|
||||
return fViewModelProvider;
|
||||
if ( TimersView.ID_VIEW_TIMERS.equals(context.getId()) ) {
|
||||
return new TimersVMProvider(this, context, getSession());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public TimersModelAdapter(DsfSession session, IPresentationContext presentationContext) {
|
||||
public TimersVMAdapter(DsfSession session, IPresentationContext presentationContext) {
|
||||
super(session);
|
||||
fViewModelProvider = new TimersVMProvider(this, presentationContext, getSession());
|
||||
}
|
||||
|
||||
TimersVMProvider getTimersVMProvider() {
|
||||
return fViewModelProvider;
|
||||
}
|
||||
}
|
|
@ -10,38 +10,76 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.dsf.timers;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelAttribute;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelColumnInfo;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelImage;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.PropertyBasedLabelProvider;
|
||||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerDMC;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerData;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerDMContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
|
||||
|
||||
/**
|
||||
* View model node that defines how timer DMContexts are displayed in the view. Timers
|
||||
* change with every tick of the timer, so the label has to be repained
|
||||
* upon timer tick events.
|
||||
* @see TimerDMC
|
||||
* @see TimerDMContext
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
class TimersVMNode extends AbstractDMVMNode
|
||||
implements IElementLabelProvider
|
||||
implements IElementLabelProvider, IElementPropertiesProvider
|
||||
{
|
||||
private static final String PROP_TIMER_NUMBER = "alarmNumber";
|
||||
private static final String PROP_TIMER_VALUE = "alarmTriggerValue";
|
||||
|
||||
// Create and configure the label provider.
|
||||
private static final PropertyBasedLabelProvider fgLabelProvider;
|
||||
static {
|
||||
fgLabelProvider = new PropertyBasedLabelProvider();
|
||||
|
||||
LabelColumnInfo idCol = new LabelColumnInfo(
|
||||
new LabelAttribute[] {
|
||||
new LabelText(new MessageFormat("Timer #{0}"),
|
||||
new String[] { PROP_TIMER_NUMBER }),
|
||||
new LabelImage(DsfExamplesPlugin.getDefault().getImageRegistry().
|
||||
getDescriptor(DsfExamplesPlugin.IMG_ALARM))
|
||||
});
|
||||
fgLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_ID, idCol);
|
||||
|
||||
LabelColumnInfo valueCol = new LabelColumnInfo(
|
||||
new LabelAttribute[] {
|
||||
new LabelText(new MessageFormat("{0}"),
|
||||
new String[] { PROP_TIMER_VALUE })
|
||||
});
|
||||
fgLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_VALUE,
|
||||
valueCol);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public TimersVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, TimerDMC.class);
|
||||
super(provider, session, TimerDMContext.class);
|
||||
}
|
||||
|
||||
public void update(ILabelUpdate[] updates) {
|
||||
fgLabelProvider.update(updates);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,93 +88,60 @@ class TimersVMNode extends AbstractDMVMNode
|
|||
|
||||
// Retrieve the timer DMContexts, create the corresponding VMCs array, and
|
||||
// set them as result.
|
||||
getServicesTracker().getService(TimerService.class).getTimers(
|
||||
new DataRequestMonitor<TimerDMC[]>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
update.setStatus(getStatus());
|
||||
} else {
|
||||
fillUpdateWithVMCs(update, getData());
|
||||
}
|
||||
update.done();
|
||||
}});
|
||||
TimerDMContext[] timers =
|
||||
getServicesTracker().getService(TimerService.class).getTimers();
|
||||
fillUpdateWithVMCs(update, timers);
|
||||
update.done();
|
||||
}
|
||||
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
public void update(final IPropertiesUpdate[] updates) {
|
||||
// Switch to the session thread before processing the updates.
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateLabelInSessionThread(updates);
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
updatePropertiesInSessionThread(update);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
for (IViewerUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
final TimerDMC dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), TimerDMC.class);
|
||||
if (!checkDmc(dmc, update) || !checkService(TimerService.class, null, update)) continue;
|
||||
|
||||
getDMVMProvider().getModelData(
|
||||
this, update,
|
||||
getServicesTracker().getService(TimerService.class, null),
|
||||
dmc,
|
||||
new DataRequestMonitor<TimerData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
/*
|
||||
* Check that the request was evaluated and data is still
|
||||
* valid. The request could fail if the state of the
|
||||
* service changed during the request, but the view model
|
||||
* has not been updated yet.
|
||||
*/
|
||||
if (!getStatus().isOK() || !getData().isValid()) {
|
||||
assert getStatus().isOK() ||
|
||||
getStatus().getCode() != IDsfService.INTERNAL_ERROR ||
|
||||
getStatus().getCode() != IDsfService.NOT_SUPPORTED;
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If columns are configured, call the protected methods to
|
||||
* fill in column values.
|
||||
*/
|
||||
String[] localColumns = update.getPresentationContext().getColumns();
|
||||
if (localColumns == null) localColumns = new String[] { null };
|
||||
|
||||
for (int i = 0; i < localColumns.length; i++) {
|
||||
fillColumnLabel(dmc, getData(), localColumns[i], i, update);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
},
|
||||
getExecutor());
|
||||
@ConfinedToDsfExecutor("getSession#getExecutor")
|
||||
private void updatePropertiesInSessionThread(final IPropertiesUpdate update) {
|
||||
// Find the timer context in the element being updated
|
||||
final TimerDMContext dmc = findDmcInPath(
|
||||
update.getViewerInput(), update.getElementPath(), TimerDMContext.class);
|
||||
|
||||
// If either update or service are not valid, fail the update and exit.
|
||||
if (!checkDmc(dmc, update) ||
|
||||
!checkService(TimerService.class, null, update))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TimerService timerService =
|
||||
getServicesTracker().getService(TimerService.class, null);
|
||||
int value = timerService.getTimerValue(dmc);
|
||||
|
||||
if (value == -1) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
update.setProperty(PROP_TIMER_NUMBER, dmc.getTimerNumber());
|
||||
update.setProperty(PROP_TIMER_VALUE, value);
|
||||
update.done();
|
||||
}
|
||||
|
||||
protected void fillColumnLabel(TimerDMC dmContext, TimerData dmData, String columnId, int idx,
|
||||
ILabelUpdate update)
|
||||
{
|
||||
if (TimersViewColumnPresentation.COL_ID.equals(columnId)) {
|
||||
update.setLabel( Integer.toString(dmData.getTimerNumber()), idx );
|
||||
update.setImageDescriptor(
|
||||
DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(DsfExamplesPlugin.IMG_TIMER), idx);
|
||||
} else if (TimersViewColumnPresentation.COL_VALUE.equals(columnId)) {
|
||||
update.setLabel( Integer.toString(dmData.getTimerValue()), idx);
|
||||
}
|
||||
}
|
||||
|
||||
public int getDeltaFlags(Object e) {
|
||||
// This node generates delta if the timers have changed, or if the
|
||||
// label has changed.
|
||||
if (e instanceof TimerService.TimerTickEvent) {
|
||||
if (e instanceof TimerService.TimerTickDMEvent) {
|
||||
return IModelDelta.STATE;
|
||||
} else if (e instanceof TimerService.TimersChangedEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
|
@ -145,10 +150,9 @@ class TimersVMNode extends AbstractDMVMNode
|
|||
}
|
||||
|
||||
public void buildDelta(Object e, VMDelta parentDelta, int nodeOffset, RequestMonitor requestMonitor) {
|
||||
if (e instanceof TimerService.TimerTickEvent) {
|
||||
// Add delta indicating that the VMC for the given timer context
|
||||
// has changed.
|
||||
parentDelta.addNode( createVMContext(((TimerService.TimerTickEvent)e).getDMContext()), IModelDelta.STATE );
|
||||
if (e instanceof TimerService.TimerTickDMEvent) {
|
||||
// Add delta indicating that the given timer has changed.
|
||||
parentDelta.addNode( createVMContext(((TimerService.TimerTickDMEvent)e).getDMContext()), IModelDelta.STATE );
|
||||
} else if (e instanceof TimerService.TimersChangedEvent) {
|
||||
// The list of timers has changed, which means that the parent
|
||||
// node needs to refresh its contents, which in turn will re-fetch the
|
||||
|
@ -157,4 +161,14 @@ class TimersVMNode extends AbstractDMVMNode
|
|||
}
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
|
||||
public String getPropertyDescription(String property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPropertyName(String property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,60 +10,42 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.dsf.timers;
|
||||
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.RootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.DefaultVMModelProxyStrategy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.TriggersChangedEvent;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimersChangedEvent;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* The View Model provider for the Timers view. This provider allows for
|
||||
* switching between two different view layouts:
|
||||
* <ol>
|
||||
* <li>Timers -> Triggers -> Alarms</li>
|
||||
* <li>Triggers -> Timers -> Alarms</li>
|
||||
* </ol>
|
||||
* A special event is sent when the layout is changed in order to generate
|
||||
* a proper delta to refresh the view.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class TimersVMProvider extends AbstractDMVMProvider {
|
||||
|
||||
/**
|
||||
* The object to be set to the viewer that shows contents supplied by this provider.
|
||||
* @see org.eclipse.jface.viewers.TreeViewer#setInput(Object)
|
||||
*/
|
||||
private final IAdaptable fViewerInputObject =
|
||||
new IAdaptable() {
|
||||
/**
|
||||
* The input object provides the viewer access to the viewer model adapter.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getAdapter(Class adapter) {
|
||||
if ( adapter.isInstance(getVMAdapter()) ) {
|
||||
return getVMAdapter();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Timers View Root"; //$NON-NLS-1$
|
||||
}
|
||||
};
|
||||
|
||||
private DefaultVMModelProxyStrategy fModelProxyStrategy;
|
||||
|
||||
|
||||
/** Event indicating that the timers view layout has changed */
|
||||
public static class TimersViewLayoutChanged {}
|
||||
|
||||
/** Enumeration of possible layouts for the timers view model */
|
||||
public enum ViewLayout { ALARMS_AT_TOP, TIMERS_AT_TOP }
|
||||
public enum ViewLayout { TRIGGERS_AT_TOP, TIMERS_AT_TOP }
|
||||
|
||||
public TimersVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session) {
|
||||
super(adapter, presentationContext, session);
|
||||
setViewLayout(ViewLayout.ALARMS_AT_TOP);
|
||||
}
|
||||
|
||||
|
||||
public Object getViewerInputObject() {
|
||||
return fViewerInputObject;
|
||||
// Set the initial view layout.
|
||||
setViewLayout(ViewLayout.TIMERS_AT_TOP);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,33 +53,30 @@ public class TimersVMProvider extends AbstractDMVMProvider {
|
|||
* @param layout New layout to use.
|
||||
*/
|
||||
public void setViewLayout(ViewLayout layout) {
|
||||
if (layout == ViewLayout.ALARMS_AT_TOP) {
|
||||
IRootVMNode root = new RootVMNode(this);
|
||||
IVMNode alarmsNode = new AlarmsVMNode(this, getSession());
|
||||
IVMNode timersNode0 = new TimersVMNode(this, getSession());
|
||||
addChildNodes(root, new IVMNode[] { alarmsNode, timersNode0 });
|
||||
clearNodes();
|
||||
if (layout == ViewLayout.TRIGGERS_AT_TOP) {
|
||||
IRootVMNode root = new TimersRootVMNode(this);
|
||||
IVMNode alarmsNode = new TriggersVMNode(this, getSession());
|
||||
addChildNodes(root, new IVMNode[] { alarmsNode });
|
||||
IVMNode timersNode = new TimersVMNode(this, getSession());
|
||||
addChildNodes(alarmsNode, new IVMNode[] { timersNode });
|
||||
IVMNode alarmStatusNode = new AlarmStatusVMNode(this, getSession());
|
||||
IVMNode alarmStatusNode = new AlarmsVMNode(this, getSession());
|
||||
addChildNodes(timersNode, new IVMNode[] { alarmStatusNode });
|
||||
setRootNode(root);
|
||||
} else if (layout == ViewLayout.TIMERS_AT_TOP) {
|
||||
IRootVMNode root = new RootVMNode(this);
|
||||
IRootVMNode root = new TimersRootVMNode(this);
|
||||
IVMNode timersNode = new TimersVMNode(this, getSession());
|
||||
addChildNodes(root, new IVMNode[] { timersNode });
|
||||
IVMNode alarmsNode = new AlarmsVMNode(this, getSession());
|
||||
IVMNode alarmsNode = new TriggersVMNode(this, getSession());
|
||||
addChildNodes(timersNode, new IVMNode[] { alarmsNode });
|
||||
IVMNode alarmStatusNode = new AlarmStatusVMNode(this, getSession());
|
||||
IVMNode alarmStatusNode = new AlarmsVMNode(this, getSession());
|
||||
addChildNodes(alarmsNode, new IVMNode[] { alarmStatusNode });
|
||||
setRootNode(root);
|
||||
}
|
||||
|
||||
/* TODO: replace with an event
|
||||
fModelProxyStrategy.fireModelChanged(
|
||||
new ModelDelta(getRootElement(), IModelDelta.CONTENT));
|
||||
*/
|
||||
handleEvent(new TimersViewLayoutChanged());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
|
||||
return new TimersViewColumnPresentation();
|
||||
|
@ -107,5 +86,36 @@ public class TimersVMProvider extends AbstractDMVMProvider {
|
|||
public String getColumnPresentationId(IPresentationContext context, Object element) {
|
||||
return TimersViewColumnPresentation.ID;
|
||||
}
|
||||
|
||||
|
||||
// Add a handler for the triggers and timers changed events. The
|
||||
// AbstractDMVMProvider superclass automatically registers this provider
|
||||
// for all IDMEvent events, however these two events do not implement
|
||||
// IDMEvent
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(final TriggersChangedEvent event) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
handleEvent(event);
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {}
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(final TimersChangedEvent event) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
handleEvent(event);
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,19 +12,20 @@ package org.eclipse.dd.examples.dsf.timers;
|
|||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.dd.dsf.concurrent.DefaultDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerDMC;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimerService.TimerDMContext;
|
||||
import org.eclipse.dd.examples.dsf.timers.TimersVMProvider.ViewLayout;
|
||||
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.IPresentationContext;
|
||||
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;
|
||||
|
@ -33,6 +34,7 @@ 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;
|
||||
|
@ -42,17 +44,23 @@ import org.eclipse.ui.part.ViewPart;
|
|||
|
||||
|
||||
/**
|
||||
* Example view which displays data from timers and alarms DSF services. This
|
||||
* 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.
|
||||
* 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.dd.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;
|
||||
|
||||
|
@ -63,7 +71,7 @@ public class TimersView extends ViewPart {
|
|||
private DsfServicesTracker fServices;
|
||||
|
||||
/** Adapter used to provide view model for flexible-hierarchy viewer */
|
||||
private TimersModelAdapter fTimersModelAdapter;
|
||||
private TimersVMAdapter fTimersVMAdapter;
|
||||
|
||||
/** Action which toggles the layout in the viewer */
|
||||
private Action fToggleLayoutAction;
|
||||
|
@ -71,45 +79,41 @@ public class TimersView extends ViewPart {
|
|||
/** Action that adds a new timer */
|
||||
private Action fAddTimerAction;
|
||||
|
||||
/** Action that adds a new alarm */
|
||||
private Action fAddAlarmAction;
|
||||
/** Action that adds a new trigger */
|
||||
private Action fAddTriggerAction;
|
||||
|
||||
/** Action that removes the selected alarm or timer */
|
||||
/** Action that removes the selected trigger or timer */
|
||||
private Action fRemoveAction;
|
||||
|
||||
public TimersView() {}
|
||||
|
||||
/**
|
||||
* This is a callback that will allow us to create the viewer and
|
||||
* 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 flex-hierarchy views.
|
||||
*/
|
||||
final IPresentationContext presentationContext = new PresentationContext("org.eclipse.dd.examples.dsf.timers"); //$NON-NLS-1$
|
||||
fViewer = new TreeModelViewer(parent, SWT.VIRTUAL | SWT.FULL_SELECTION, presentationContext);
|
||||
// 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.
|
||||
*/
|
||||
// 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, "org.eclipse.dd.examples.dsf.timers"); //$NON-NLS-1$
|
||||
fServices = new DsfServicesTracker(DsfExamplesPlugin.getBundleContext(), fSession.getId());
|
||||
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
|
||||
* dispatch thread, so we have to block this thread using Future.get()
|
||||
* until it completes. The Future.get() will throw an exception if
|
||||
* the sequence fails.
|
||||
*/
|
||||
// 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 {
|
||||
|
@ -118,20 +122,38 @@ public class TimersView extends ViewPart {
|
|||
} catch (ExecutionException e) { assert false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the flexible hierarchy content/label adapter. Then register
|
||||
* it with the session.
|
||||
*/
|
||||
fTimersModelAdapter = new TimersModelAdapter(fSession, presentationContext);
|
||||
fSession.registerModelAdapter(IElementContentProvider.class, fTimersModelAdapter);
|
||||
fSession.registerModelAdapter(IModelProxyFactory.class, fTimersModelAdapter);
|
||||
fSession.registerModelAdapter(IColumnPresentationFactory.class, fTimersModelAdapter);
|
||||
// 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);
|
||||
|
||||
/*
|
||||
* Set the root element for the timers tree viewer. The root element
|
||||
* comes from the content provider.
|
||||
*/
|
||||
fViewer.setInput(fTimersModelAdapter.getTimersVMProvider().getViewerInputObject());
|
||||
// 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();
|
||||
|
@ -140,21 +162,24 @@ public class TimersView extends ViewPart {
|
|||
@Override
|
||||
public void dispose() {
|
||||
try {
|
||||
/*
|
||||
* First dispose the view model, which is the client of services.
|
||||
* We are not in the dispatch thread
|
||||
*/
|
||||
// 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);
|
||||
fTimersModelAdapter.dispose();
|
||||
fTimersModelAdapter = null;
|
||||
}}).get();
|
||||
|
||||
// Then invoke the shutdown sequence for the services.
|
||||
ServicesShutdownSequence shutdownSeq = new ServicesShutdownSequence(fSession);
|
||||
|
||||
// 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();
|
||||
|
@ -162,7 +187,7 @@ public class TimersView extends ViewPart {
|
|||
} catch (ExecutionException e) { assert false;
|
||||
}
|
||||
|
||||
// Finally end the session and the executor:
|
||||
// Finally end the session and the executor.
|
||||
fSession.getExecutor().submit(new Runnable() {
|
||||
public void run() {
|
||||
DsfSession.endSession(fSession);
|
||||
|
@ -173,7 +198,6 @@ public class TimersView extends ViewPart {
|
|||
} catch (InterruptedException e) {
|
||||
} catch (ExecutionException e) {
|
||||
}
|
||||
//fViewer.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
@ -185,7 +209,7 @@ public class TimersView extends ViewPart {
|
|||
private void fillLocalToolBar(IToolBarManager manager) {
|
||||
manager.add(fToggleLayoutAction);
|
||||
manager.add(fAddTimerAction);
|
||||
manager.add(fAddAlarmAction);
|
||||
manager.add(fAddTriggerAction);
|
||||
manager.add(fRemoveAction);
|
||||
manager.add(new Separator());
|
||||
}
|
||||
|
@ -195,97 +219,105 @@ public class TimersView extends ViewPart {
|
|||
@Override
|
||||
public void run() {
|
||||
// Get the toggle state of the action while on UI thread.
|
||||
final ViewLayout layout = isChecked() ? ViewLayout.ALARMS_AT_TOP : ViewLayout.TIMERS_AT_TOP;
|
||||
final ViewLayout layout = isChecked() ? ViewLayout.TRIGGERS_AT_TOP : ViewLayout.TIMERS_AT_TOP;
|
||||
|
||||
// Switch to executor thread to perform the change in layout.
|
||||
fExecutor.submit(new Runnable() { public void run() {
|
||||
fTimersModelAdapter.getTimersVMProvider().setViewLayout(layout);
|
||||
}});
|
||||
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") { //$NON-NLS-1$
|
||||
fAddTimerAction = new Action("Add New Timer") {
|
||||
@Override
|
||||
public void run() {
|
||||
fExecutor.submit(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();
|
||||
}});
|
||||
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 new timer"); //$NON-NLS-1$
|
||||
fAddTimerAction.setImageDescriptor(DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(
|
||||
DsfExamplesPlugin.IMG_TIMER));
|
||||
fAddTimerAction.setToolTipText("Add a new timer");
|
||||
fAddTimerAction.setImageDescriptor(
|
||||
getImage(DsfExamplesPlugin.IMG_TIMER));
|
||||
|
||||
fAddAlarmAction = new Action("Add New Alarm") { //$NON-NLS-1$
|
||||
fAddTriggerAction = new Action("Add New Trigger") {
|
||||
@Override
|
||||
public void run() {
|
||||
// Ask user for the new alarm value.
|
||||
// Ask user for the new trigger value.
|
||||
InputDialog inputDialog = new InputDialog(
|
||||
fViewer.getControl().getShell(),
|
||||
"New Alarm", //$NON-NLS-1$
|
||||
"Please enter alarm time", //$NON-NLS-1$
|
||||
"", //$NON-NLS-1$
|
||||
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"; //$NON-NLS-1$
|
||||
return "Please enter a positive integer";
|
||||
|
||||
} catch (NumberFormatException x) {
|
||||
return "Please enter a positive integer"; //$NON-NLS-1$
|
||||
return "Please enter a positive integer";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
if (inputDialog.open() != Window.OK) return;
|
||||
int tmpAlarmValue = -1;
|
||||
int tmpTriggerValue = -1;
|
||||
try {
|
||||
tmpAlarmValue = Integer.parseInt(inputDialog.getValue());
|
||||
tmpTriggerValue = Integer.parseInt(inputDialog.getValue());
|
||||
} catch (NumberFormatException x) { assert false; }
|
||||
final int alarmValue = tmpAlarmValue;
|
||||
fExecutor.submit(new Runnable() { public void run() {
|
||||
// Create the new alarm.
|
||||
fServices.getService(AlarmService.class).createAlarm(alarmValue);
|
||||
}});
|
||||
final int triggerValue = tmpTriggerValue;
|
||||
fExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
// Create the new trigger
|
||||
fServices.getService(AlarmService.class).
|
||||
createTrigger(triggerValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
fAddAlarmAction.setToolTipText("Add new alarm"); //$NON-NLS-1$
|
||||
fAddAlarmAction.setImageDescriptor(DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(
|
||||
DsfExamplesPlugin.IMG_ALARM));
|
||||
fAddTriggerAction.setToolTipText("Add a new trigger");
|
||||
fAddTriggerAction.setImageDescriptor(
|
||||
getImage(DsfExamplesPlugin.IMG_ALARM));
|
||||
|
||||
fRemoveAction = new Action("Remove") { //$NON-NLS-1$
|
||||
fRemoveAction = new Action("Remove") {
|
||||
@Override
|
||||
public void run() {
|
||||
final Object selectedElement = ((IStructuredSelection)fViewer.getSelection()).getFirstElement();
|
||||
final Object selectedElement =
|
||||
((IStructuredSelection)fViewer.getSelection()).getFirstElement();
|
||||
if (!(selectedElement instanceof IDMVMContext)) return;
|
||||
final IDMContext selectedDmc = ((IDMVMContext)selectedElement).getDMContext();
|
||||
// Based on the DMC from the selection, call the appropriate service to
|
||||
// remove the item.
|
||||
if (selectedDmc instanceof TimerDMC) {
|
||||
fExecutor.submit(new Runnable() { public void run() {
|
||||
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(
|
||||
((TimerDMC)selectedDmc));
|
||||
((TimerDMContext)selectedCtx));
|
||||
}});
|
||||
} else if (selectedDmc instanceof AlarmService.AlarmDMC) {
|
||||
fExecutor.submit(new Runnable() { public void run() {
|
||||
fServices.getService(AlarmService.class).deleteAlarm(
|
||||
(AlarmService.AlarmDMC)selectedDmc);
|
||||
} 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"); //$NON-NLS-1$
|
||||
fRemoveAction.setImageDescriptor(DsfExamplesPlugin.getDefault().getImageRegistry().getDescriptor(
|
||||
DsfExamplesPlugin.IMG_REMOVE));
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -25,18 +25,14 @@ public class TimersViewColumnPresentation implements IColumnPresentation {
|
|||
public static final String COL_ID = ID + ".COL_ID"; //$NON-NLS-1$
|
||||
public static final String COL_VALUE = ID + ".COL_VALUE"; //$NON-NLS-1$
|
||||
|
||||
// @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#init(org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext)
|
||||
public void init(IPresentationContext context) {}
|
||||
|
||||
// @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#dispose()
|
||||
public void dispose() {}
|
||||
|
||||
// @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getAvailableColumns()
|
||||
public String[] getAvailableColumns() {
|
||||
return new String[] { COL_ID, COL_VALUE };
|
||||
}
|
||||
|
||||
// @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getHeader(java.lang.String)
|
||||
public String getHeader(String id) {
|
||||
if (COL_ID.equals(id)) {
|
||||
return "ID"; //$NON-NLS-1$
|
||||
|
@ -46,22 +42,18 @@ public class TimersViewColumnPresentation implements IColumnPresentation {
|
|||
return null;
|
||||
}
|
||||
|
||||
// @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getId()
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
// @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getImageDescriptor(java.lang.String)
|
||||
public ImageDescriptor getImageDescriptor(String id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getInitialColumns()
|
||||
public String[] getInitialColumns() {
|
||||
return getAvailableColumns();
|
||||
}
|
||||
|
||||
// @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#isOptional()
|
||||
public boolean isOptional() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
package org.eclipse.dd.examples.dsf.timers;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
|
@ -23,8 +24,7 @@ import org.eclipse.dd.dsf.service.DsfServices;
|
|||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.AlarmDMC;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.AlarmData;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.TriggerDMContext;
|
||||
import org.eclipse.jface.dialogs.MessageDialog;
|
||||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
@ -32,58 +32,56 @@ import org.osgi.framework.InvalidSyntaxException;
|
|||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
/**
|
||||
*
|
||||
* Cell modifier used to edit the trigger value.
|
||||
*/
|
||||
@ThreadSafeAndProhibitedFromDsfExecutor("")
|
||||
public class AlarmCellModifier implements ICellModifier {
|
||||
@ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()")
|
||||
public class TriggerCellModifier implements ICellModifier {
|
||||
|
||||
private final DsfSession fSession;
|
||||
|
||||
/**
|
||||
* Need to use the OSGi service tracker here (instead of DsfServiceTracker),
|
||||
* because we're accessing it in non-dispatch thread. DsfServiceTracker is not
|
||||
* thread-safe.
|
||||
*/
|
||||
// Need to use the OSGi service tracker (instead of DsfServiceTracker),
|
||||
// because it's being accessed on multiple threads.
|
||||
@ThreadSafe
|
||||
private ServiceTracker fServiceTracker;
|
||||
|
||||
/**
|
||||
* Constructor for the modifier requires a valid DSF session in order to
|
||||
* Constructor for the modifier requires a valid session in order to
|
||||
* initialize the service tracker.
|
||||
* @param session DSF session this modifier will use.
|
||||
*/
|
||||
public AlarmCellModifier(DsfSession session) {
|
||||
public TriggerCellModifier(DsfSession session) {
|
||||
fSession = session;
|
||||
}
|
||||
|
||||
public boolean canModify(Object element, String property) {
|
||||
return TimersViewColumnPresentation.COL_VALUE.equals(property) && getAlarmDMC(element) != null;
|
||||
return TimersViewColumnPresentation.COL_VALUE.equals(property) &&
|
||||
getAlarmDMC(element) != null;
|
||||
}
|
||||
|
||||
public Object getValue(Object element, String property) {
|
||||
if (!TimersViewColumnPresentation.COL_VALUE.equals(property)) return ""; //$NON-NLS-1$
|
||||
if (!TimersViewColumnPresentation.COL_VALUE.equals(property)) return "";
|
||||
|
||||
// Get the DMC and the session. If element is not an alarm DMC, or
|
||||
// session is stale, then bail out.
|
||||
AlarmDMC dmc = getAlarmDMC(element);
|
||||
if (dmc == null) return ""; //$NON-NLS-1$
|
||||
DsfSession session = DsfSession.getSession(dmc.getSessionId());
|
||||
if (session == null) return ""; //$NON-NLS-1$
|
||||
// Get the context and the session. If element is not an trigger
|
||||
// context or if the session is stale then bail out.
|
||||
TriggerDMContext triggerCtx = getAlarmDMC(element);
|
||||
if (triggerCtx == null) return "";
|
||||
DsfSession session = DsfSession.getSession(triggerCtx.getSessionId());
|
||||
if (session == null) return "";
|
||||
|
||||
/*
|
||||
* Create the query to request the value from service.
|
||||
* Note: no need to guard against RejectedExecutionException, because
|
||||
* DsfSession.getSession() above would only return an active session.
|
||||
*/
|
||||
GetValueQuery query = new GetValueQuery(dmc);
|
||||
session.getExecutor().execute(query);
|
||||
// Create the query to request the value from service.
|
||||
GetValueQuery query = new GetValueQuery(triggerCtx);
|
||||
try {
|
||||
session.getExecutor().execute(query);
|
||||
} catch (RejectedExecutionException e) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return query.get().toString();
|
||||
} catch (InterruptedException e) {
|
||||
assert false;
|
||||
return ""; //$NON-NLS-1$
|
||||
return "";
|
||||
} catch (ExecutionException e) {
|
||||
return ""; //$NON-NLS-1$
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +89,7 @@ public class AlarmCellModifier implements ICellModifier {
|
|||
public void modify(Object element, String property, Object value) {
|
||||
if (!TimersViewColumnPresentation.COL_VALUE.equals(property)) return;
|
||||
|
||||
AlarmDMC dmc = getAlarmDMC(element);
|
||||
TriggerDMContext dmc = getAlarmDMC(element);
|
||||
if (dmc == null) return;
|
||||
DsfSession session = DsfSession.getSession(dmc.getSessionId());
|
||||
if (session == null) return;
|
||||
|
@ -105,31 +103,32 @@ public class AlarmCellModifier implements ICellModifier {
|
|||
try {
|
||||
intValue = new Integer(((String)value).trim());
|
||||
} catch (NumberFormatException e) {
|
||||
MessageDialog.openError(shell, "Invalid Value", "Please enter a positive integer"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
MessageDialog.openError(shell, "Invalid Value",
|
||||
"Please enter a positive integer");
|
||||
return;
|
||||
}
|
||||
if (intValue.intValue() <= 0) {
|
||||
MessageDialog.openError(shell, "Invalid Value", "Please enter a positive integer"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
MessageDialog.openError(shell, "Invalid Value",
|
||||
"Please enter a positive integer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the query to write the value to the service.
|
||||
* Note: no need to guard against RejectedExecutionException, because
|
||||
* DsfSession.getSession() above would only return an active session.
|
||||
*/
|
||||
// Create the query to write the value to the service.
|
||||
SetValueQuery query = new SetValueQuery(dmc, intValue);
|
||||
|
||||
session.getExecutor().execute(query);
|
||||
|
||||
try {
|
||||
session.getExecutor().execute(query);
|
||||
} catch (RejectedExecutionException e) {
|
||||
// View must be shutting down, no need to show error dialog.
|
||||
}
|
||||
try {
|
||||
// Return value is irrelevant, any error would come through with an exception.
|
||||
query.get().toString();
|
||||
} catch (InterruptedException e) {
|
||||
assert false;
|
||||
} catch (ExecutionException e) {
|
||||
// View must be shutting down, no need to show erro dialog.
|
||||
// View must be shutting down, no need to show error dialog.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,15 +150,16 @@ public class AlarmCellModifier implements ICellModifier {
|
|||
return null;
|
||||
}
|
||||
|
||||
private AlarmDMC getAlarmDMC(Object element) {
|
||||
private TriggerDMContext getAlarmDMC(Object element) {
|
||||
if (element instanceof IAdaptable) {
|
||||
return (AlarmDMC)((IAdaptable)element).getAdapter(AlarmDMC.class);
|
||||
return (TriggerDMContext)((IAdaptable)element).getAdapter(TriggerDMContext.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
private synchronized AlarmService getService(AlarmDMC dmc) {
|
||||
private synchronized AlarmService getService(TriggerDMContext dmc) {
|
||||
// Create and initialize the service tracker if needed.
|
||||
String serviceId = DsfServices.createServiceFilter( AlarmService.class, fSession.getId() );
|
||||
if (fServiceTracker == null) {
|
||||
try {
|
||||
|
@ -172,26 +172,25 @@ public class AlarmCellModifier implements ICellModifier {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
// Get the service.
|
||||
return (AlarmService)fServiceTracker.getService();
|
||||
}
|
||||
|
||||
|
||||
private class GetValueQuery extends Query<Integer> {
|
||||
final TriggerDMContext fDmc;
|
||||
|
||||
final AlarmDMC fDmc;
|
||||
|
||||
private GetValueQuery(AlarmDMC dmc) {
|
||||
private GetValueQuery(TriggerDMContext dmc) {
|
||||
super();
|
||||
fDmc = dmc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(final DataRequestMonitor<Integer> rm) {
|
||||
/*
|
||||
* Guard against the session being disposed. If session is disposed
|
||||
* it could mean that the executor is shut-down, which in turn
|
||||
* could mean that we can't execute the "done" argument.
|
||||
* In that case, cancel to notify waiting thread.
|
||||
*/
|
||||
// Guard against the session being disposed. If session is disposed
|
||||
// it could mean that the executor is shut-down, which in turn
|
||||
// could mean that we can't execute the "done" argument.
|
||||
// In that case, cancel to notify waiting thread.
|
||||
final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
|
||||
if (session == null) {
|
||||
cancel(false);
|
||||
|
@ -201,34 +200,30 @@ public class AlarmCellModifier implements ICellModifier {
|
|||
AlarmService service = getService(fDmc);
|
||||
if (service == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, IDsfService.INVALID_STATE,
|
||||
"Service not available", null)); //$NON-NLS-1$
|
||||
"Service not available", null));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
service.getAlarmData(fDmc, new DataRequestMonitor<AlarmData>(session.getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
// We're in another dispatch, so we must guard against executor shutdown again.
|
||||
if (DsfSession.isSessionActive(session.getId())) {
|
||||
super.handleCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
rm.setData(getData().getTriggeringValue());
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
int value = service.getTriggerValue(fDmc);
|
||||
if (value == -1) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE,
|
||||
"Invalid context", null));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
rm.setData(value);
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
private class SetValueQuery extends Query<Object> {
|
||||
|
||||
AlarmDMC fDmc;
|
||||
TriggerDMContext fDmc;
|
||||
int fValue;
|
||||
|
||||
SetValueQuery(AlarmDMC dmc, int value) {
|
||||
SetValueQuery(TriggerDMContext dmc, int value) {
|
||||
super();
|
||||
fDmc = dmc;
|
||||
fValue = value;
|
||||
|
@ -247,13 +242,13 @@ public class AlarmCellModifier implements ICellModifier {
|
|||
AlarmService service = getService(fDmc);
|
||||
if (service == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, IDsfService.INVALID_STATE,
|
||||
"Service not available", null)); //$NON-NLS-1$
|
||||
"Service not available", null));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally set the value and return.
|
||||
service.setAlarmValue(fDmc, fValue);
|
||||
service.setTriggerValue(fDmc, fValue);
|
||||
|
||||
// Return value is irrelevant.
|
||||
rm.setData(new Object());
|
|
@ -0,0 +1,203 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.examples.dsf.timers;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelAttribute;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelColumnInfo;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelImage;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.PropertyBasedLabelProvider;
|
||||
import org.eclipse.dd.examples.dsf.DsfExamplesPlugin;
|
||||
import org.eclipse.dd.examples.dsf.timers.AlarmService.TriggerDMContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.CellEditor;
|
||||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
|
||||
/**
|
||||
* View model node that defines how alarm DMContexts are displayed in the view. Alarm
|
||||
* nodes are fairly static, once they are created their label doesn't change.
|
||||
* @see TriggerDMContext
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
class TriggersVMNode extends AbstractDMVMNode
|
||||
implements IElementEditor, IElementPropertiesProvider, IElementLabelProvider
|
||||
{
|
||||
private static final String PROP_TRIGGER_NUMBER = "alarmNumber";
|
||||
private static final String PROP_TRIGGER_VALUE = "alarmTriggerValue";
|
||||
|
||||
// Create and configure the label provider.
|
||||
private static final PropertyBasedLabelProvider fgLabelProvider;
|
||||
static {
|
||||
fgLabelProvider = new PropertyBasedLabelProvider();
|
||||
|
||||
LabelColumnInfo idCol = new LabelColumnInfo(
|
||||
new LabelAttribute[] {
|
||||
new LabelText(new MessageFormat("Trigger #{0}"),
|
||||
new String[] { PROP_TRIGGER_NUMBER }),
|
||||
new LabelImage(DsfExamplesPlugin.getDefault().getImageRegistry().
|
||||
getDescriptor(DsfExamplesPlugin.IMG_ALARM))
|
||||
});
|
||||
fgLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_ID, idCol);
|
||||
|
||||
LabelColumnInfo valueCol = new LabelColumnInfo(
|
||||
new LabelAttribute[] {
|
||||
new LabelText(new MessageFormat("{0}"),
|
||||
new String[] { PROP_TRIGGER_VALUE })
|
||||
});
|
||||
fgLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_VALUE,
|
||||
valueCol);
|
||||
}
|
||||
|
||||
private TriggerCellModifier fAlarmCellModifier;
|
||||
|
||||
public TriggersVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, TriggerDMContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
if (!checkService(AlarmService.class, null, update)) return;
|
||||
|
||||
TriggerDMContext[] triggers =
|
||||
getServicesTracker().getService(AlarmService.class).getTriggers();
|
||||
fillUpdateWithVMCs(update, triggers);
|
||||
update.done();
|
||||
}
|
||||
|
||||
public void update(ILabelUpdate[] updates) {
|
||||
fgLabelProvider.update(updates);
|
||||
}
|
||||
|
||||
public void update(final IPropertiesUpdate[] updates) {
|
||||
// Switch to the session thread before processing the updates.
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
updatePropertiesInSessionThread(update);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IViewerUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ConfinedToDsfExecutor("getSession#getExecutor")
|
||||
private void updatePropertiesInSessionThread(final IPropertiesUpdate update) {
|
||||
// Find the trigger context in the element being updated
|
||||
TriggerDMContext triggerCtx = findDmcInPath(
|
||||
update.getViewerInput(), update.getElementPath(), TriggerDMContext.class);
|
||||
|
||||
// If either update or service are not valid, fail the update and exit.
|
||||
if (!checkDmc(triggerCtx, update) ||
|
||||
!checkService(AlarmService.class, null, update))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate and set the update properties.
|
||||
AlarmService alarmService =
|
||||
getServicesTracker().getService(AlarmService.class, null);
|
||||
int value = alarmService.getTriggerValue(triggerCtx);
|
||||
|
||||
if (value == -1) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
update.setProperty(PROP_TRIGGER_NUMBER, triggerCtx.getTriggerNumber());
|
||||
update.setProperty(PROP_TRIGGER_VALUE, value);
|
||||
update.done();
|
||||
}
|
||||
|
||||
public CellEditor getCellEditor(IPresentationContext context, String columnId,
|
||||
Object element, Composite parent)
|
||||
{
|
||||
// Create a cell editor to modify the trigger value.
|
||||
if (TimersViewColumnPresentation.COL_VALUE.equals(columnId)) {
|
||||
return new TextCellEditor(parent);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Note: this method is synchronized because IElementEditor.getCellModifier can be called
|
||||
// on any thread, even though in practice it should be only called on the UI thread.
|
||||
public ICellModifier getCellModifier(IPresentationContext context,
|
||||
Object element)
|
||||
{
|
||||
// Create the cell modifier if needed.
|
||||
if (fAlarmCellModifier == null) {
|
||||
fAlarmCellModifier = new TriggerCellModifier(getSession());
|
||||
}
|
||||
return fAlarmCellModifier;
|
||||
}
|
||||
|
||||
public int getDeltaFlags(Object e) {
|
||||
// Since the label for triggers doesn't change, this node will generate
|
||||
// delta info only if the list of alarms is changed.
|
||||
if (e instanceof AlarmService.TriggersChangedEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
|
||||
public void buildDelta(Object event, VMDelta parentDelta, int nodeOffset,
|
||||
RequestMonitor requestMonitor)
|
||||
{
|
||||
if (event instanceof AlarmService.TriggersChangedEvent) {
|
||||
// The list of alarms has changed, which means that the parent
|
||||
// node needs to refresh its contents, which in turn will re-fetch the
|
||||
// elements from this node.
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (fAlarmCellModifier != null) {
|
||||
fAlarmCellModifier.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public String getPropertyDescription(String property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPropertyName(String property) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=ISO-8859-1"
|
||||
http-equiv="content-type">
|
||||
<title>Eclipse Device Debug - Debugger Services Framework - Data Model</title>
|
||||
</head>
|
||||
<body>
|
||||
Example demostrationg use of Debugger Services Framework (DSF) data
|
||||
model interfaces.<br>
|
||||
<h2>Package Specification</h2>
|
||||
The example consists of two services, one that monitors a set of timers
|
||||
(TimerService), and another that tracks a set of alarms
|
||||
(AlarmService). The timers are incremented at a rate of one per
|
||||
second, although for visual interest, timers are not synchronous as
|
||||
each timer is incremented at a slightly different moment. There
|
||||
is also a "Timers" view that displays the timers and alarms, and has
|
||||
actions for adding and removing new timers and alarms. Most
|
||||
interestingly, the view has a toggle action, which switches the layout
|
||||
of the view from having timers at the root level, with alarms listed
|
||||
below each timer, to having alarms at the root level with timers listed
|
||||
below each alarm.<br>
|
||||
<br>
|
||||
<img alt="" title="Example diagram" src="doc-files%5Cpackage-1.png"
|
||||
style="width: 1014px; height: 643px;"><br>
|
||||
<br>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue