blob: 36738b160190a3d6e7f73ad041b56a79902b30f0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2015 Wind River Systems and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.examples.dsf.timers;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelForeground;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider;
import org.eclipse.cdt.examples.dsf.DsfExamplesPlugin;
import org.eclipse.cdt.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;
import org.eclipse.swt.graphics.RGB;
/**
* 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 TimerDMContext
*/
@SuppressWarnings("restriction")
class TimersVMNode extends AbstractDMVMNode 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 PropertiesBasedLabelProvider fgLabelProvider;
static {
fgLabelProvider = new PropertiesBasedLabelProvider();
LabelColumnInfo idCol = new LabelColumnInfo(
new LabelAttribute[] { new LabelText("Timer #{0}", new String[] { PROP_TIMER_NUMBER }),
new LabelForeground(new RGB(0, 0, 255)), new LabelImage(DsfExamplesPlugin.getDefault()
.getImageRegistry().getDescriptor(DsfExamplesPlugin.IMG_TIMER)) });
fgLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_ID, idCol);
LabelColumnInfo valueCol = new LabelColumnInfo(
new LabelAttribute[] { new LabelText("{0}", new String[] { PROP_TIMER_VALUE }) });
fgLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_VALUE, valueCol);
}
public TimersVMNode(AbstractDMVMProvider provider, DsfSession session) {
super(provider, session, TimerDMContext.class);
}
@Override
public String toString() {
return "TimersVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public void update(ILabelUpdate[] updates) {
fgLabelProvider.update(updates);
}
@Override
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
TimerService timerService = getServicesTracker().getService(TimerService.class, null);
if (timerService == null) {
handleFailedUpdate(update);
return;
}
// Retrieve the timer DMContexts, create the corresponding VMCs array, and
// set them as result.
TimerDMContext[] timers = timerService.getTimers();
fillUpdateWithVMCs(update, timers);
update.done();
}
@Override
public void update(final IPropertiesUpdate[] updates) {
// Switch to the session thread before processing the updates.
try {
getSession().getExecutor().execute(new DsfRunnable() {
@Override
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 timer context in the element being updated
TimerDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), TimerDMContext.class);
TimerService timerService = getServicesTracker().getService(TimerService.class, null);
// If either update or service are not valid, fail the update and exit.
if (dmc == null || timerService == null) {
handleFailedUpdate(update);
return;
}
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();
}
@Override
public int getDeltaFlags(Object e) {
// This node generates delta if the timers have changed, or if the
// label has changed.
if (e instanceof TimerService.TimerTickDMEvent) {
return IModelDelta.STATE;
} else if (e instanceof TimerService.TimersChangedEvent) {
return IModelDelta.CONTENT;
}
return IModelDelta.NO_CHANGE;
}
@Override
public void buildDelta(Object e, VMDelta parentDelta, int nodeOffset, RequestMonitor requestMonitor) {
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
// elements from this node.
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
}
requestMonitor.done();
}
}