1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
9 * Contributors: Alvaro Sanchez-Leon - Initial implementation
10 *******************************************************************************/
11 package org
.eclipse
.linuxtools
.lttng
.ui
.views
.resources
;
13 import java
.util
.Arrays
;
14 import java
.util
.Vector
;
16 import org
.eclipse
.jface
.action
.Action
;
17 import org
.eclipse
.jface
.action
.IMenuListener
;
18 import org
.eclipse
.jface
.action
.IMenuManager
;
19 import org
.eclipse
.jface
.action
.IToolBarManager
;
20 import org
.eclipse
.jface
.action
.MenuManager
;
21 import org
.eclipse
.jface
.action
.Separator
;
22 import org
.eclipse
.linuxtools
.lttng
.event
.LttngTimestamp
;
23 import org
.eclipse
.linuxtools
.lttng
.state
.IStateDataRequestListener
;
24 import org
.eclipse
.linuxtools
.lttng
.state
.RequestCompletedSignal
;
25 import org
.eclipse
.linuxtools
.lttng
.state
.RequestStartedSignal
;
26 import org
.eclipse
.linuxtools
.lttng
.state
.StateDataRequest
;
27 import org
.eclipse
.linuxtools
.lttng
.state
.StateManager
;
28 import org
.eclipse
.linuxtools
.lttng
.state
.evProcessor
.EventProcessorProxy
;
29 import org
.eclipse
.linuxtools
.lttng
.state
.experiment
.StateExperimentManager
;
30 import org
.eclipse
.linuxtools
.lttng
.state
.experiment
.StateManagerFactory
;
31 import org
.eclipse
.linuxtools
.lttng
.ui
.TraceDebug
;
32 import org
.eclipse
.linuxtools
.lttng
.ui
.model
.trange
.TimeRangeComponent
;
33 import org
.eclipse
.linuxtools
.lttng
.ui
.model
.trange
.TimeRangeEventResource
;
34 import org
.eclipse
.linuxtools
.lttng
.ui
.model
.trange
.TimeRangeViewerProvider
;
35 import org
.eclipse
.linuxtools
.lttng
.ui
.views
.common
.ParamsUpdater
;
36 import org
.eclipse
.linuxtools
.lttng
.ui
.views
.resources
.evProcessor
.ResourcesTRangeUpdateFactory
;
37 import org
.eclipse
.linuxtools
.lttng
.ui
.views
.resources
.model
.ResourceModelFactory
;
38 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
39 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalHandler
;
40 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalManager
;
41 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfTimeSynchSignal
;
42 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.TmfViewerFactory
;
43 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.timeAnalysis
.ITimeAnalysisViewer
;
44 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.timeAnalysis
.ITmfTimeScaleSelectionListener
;
45 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.timeAnalysis
.ITmfTimeSelectionListener
;
46 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.timeAnalysis
.TmfTimeScaleSelectionEvent
;
47 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.timeAnalysis
.TmfTimeSelectionEvent
;
48 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.timeAnalysis
.model
.ITmfTimeAnalysisEntry
;
49 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
50 import org
.eclipse
.swt
.SWT
;
51 import org
.eclipse
.swt
.layout
.FillLayout
;
52 import org
.eclipse
.swt
.widgets
.Composite
;
53 import org
.eclipse
.swt
.widgets
.Display
;
54 import org
.eclipse
.swt
.widgets
.Menu
;
55 import org
.eclipse
.ui
.IActionBars
;
56 import org
.eclipse
.ui
.IWorkbenchActionConstants
;
57 import org
.eclipse
.ui
.PlatformUI
;
58 import org
.eclipse
.ui
.plugin
.AbstractUIPlugin
;
64 public class ResourcesView
extends TmfView
implements
65 ITmfTimeSelectionListener
, ITmfTimeScaleSelectionListener
,
66 IStateDataRequestListener
{
68 // ========================================================================
70 // ========================================================================
71 public static final String ID
= "org.eclipse.linuxtools.lttng.ui.views.resources";
72 private Vector
<StateDataRequest
> pendingDataRequests
= new Vector
<StateDataRequest
>();
74 // private int totalNumItems = 0;
76 private Action resetScale
;
77 private Action nextEvent
;
78 private Action prevEvent
;
79 private Action nextTrace
;
80 private Action prevTrace
;
81 private Action showLegend
;
82 private Action filterTraces
;
83 private Action zoomIn
;
84 private Action zoomOut
;
87 private ITimeAnalysisViewer tsfviewer
;
88 private Composite top
;
90 // private static SimpleDateFormat stimeformat = new SimpleDateFormat(
91 // "yy/MM/dd HH:mm:ss");
93 // private TraceModelImplFactory fact;
95 // ========================================================================
97 // ========================================================================
102 public ResourcesView() {
106 * This is a callback that will allow us to create the viewer and initialize
110 public void createPartControl(Composite parent
) {
111 top
= new Composite(parent
, SWT
.BORDER
);
113 top
.setLayout(new FillLayout());
114 tsfviewer
= TmfViewerFactory
.createViewer(top
,
115 new TimeRangeViewerProvider());
117 tsfviewer
.addWidgetSelectionListner(this);
118 tsfviewer
.addWidgetTimeScaleSelectionListner(this);
120 // Traces shall not be grouped to allow synchronization
121 tsfviewer
.groupTraces(true);
122 tsfviewer
.setAcceptSelectionAPIcalls(true);
124 // Viewer to notify selection to this class
125 // This class will synchronize selections with table.
126 tsfviewer
.addWidgetSelectionListner(this);
127 tsfviewer
.addWidgetTimeScaleSelectionListner(this);
129 // Create the help context id for the viewer's control
130 // TODO: Associate with help system
131 PlatformUI
.getWorkbench().getHelpSystem().setHelp(
132 tsfviewer
.getControl(),
133 "org.eclipse.linuxtools.lttng.ui.views.resource.view"); //$NON-NLS-1$
137 contributeToActionBars();
139 // Register the updater in charge to refresh elements as we update the
141 // FlowParamsUpdater listener = FlowModelFactory.getParamsUpdater();
142 // tsfviewer.addWidgetTimeScaleSelectionListner(listener);
144 // TODO: refactor regitration / notificatio process
145 // Register this view to receive updates when the model is updated with
147 // ModelListenFactory.getRegister().addFlowModelUpdatesListener(this);
149 // Register the event processor factory in charge of event handling
150 EventProcessorProxy
.getInstance().addEventProcessorFactory(
151 ResourcesTRangeUpdateFactory
.getInstance());
153 // set the initial view parameter values
154 // Experiment start and end time
155 // as well as time space width in pixels, used by the time analysis
157 ParamsUpdater paramUpdater
= ResourceModelFactory
.getParamsUpdater();
158 StateExperimentManager experimentManger
= StateManagerFactory
159 .getExperimentManager();
160 // Read relevant values
161 int timeSpaceWidth
= tsfviewer
.getTimeSpace();
162 TmfTimeRange timeRange
= experimentManger
.getExperimentTimeRange();
163 if (timeRange
!= null) {
164 long time0
= timeRange
.getStartTime().getValue();
165 long time1
= timeRange
.getEndTime().getValue();
166 paramUpdater
.update(time0
, time1
, timeSpaceWidth
);
169 // Read current data if any available
170 StateManagerFactory
.getExperimentManager().readExperiment(
171 "resourceView", this);
174 private void hookContextMenu() {
175 MenuManager menuMgr
= new MenuManager("#PopupMenu"); //$NON-NLS-1$
176 menuMgr
.setRemoveAllWhenShown(true);
177 menuMgr
.addMenuListener(new IMenuListener() {
178 public void menuAboutToShow(IMenuManager manager
) {
179 ResourcesView
.this.fillContextMenu(manager
);
183 Menu menu
= menuMgr
.createContextMenu(tsfviewer
.getControl());
184 tsfviewer
.getControl().setMenu(menu
);
186 .registerContextMenu(menuMgr
, tsfviewer
.getSelectionProvider());
189 private void contributeToActionBars() {
190 IActionBars bars
= getViewSite().getActionBars();
191 fillLocalPullDown(bars
.getMenuManager());
192 fillLocalToolBar(bars
.getToolBarManager());
195 private void fillLocalPullDown(IMenuManager manager
) {
196 manager
.add(new Separator());
197 // manager.add(showLegend);
198 manager
.add(new Separator());
199 manager
.add(resetScale
);
200 manager
.add(nextEvent
);
201 manager
.add(prevEvent
);
202 manager
.add(nextTrace
);
203 manager
.add(prevTrace
);
204 // manager.add(filterTraces);
206 manager
.add(zoomOut
);
208 manager
.add(new Separator());
211 private void fillContextMenu(IMenuManager manager
) {
212 // manager.add(showLegend);
213 manager
.add(new Separator());
214 manager
.add(resetScale
);
215 manager
.add(nextEvent
);
216 manager
.add(prevEvent
);
217 manager
.add(nextTrace
);
218 manager
.add(prevTrace
);
219 // manager.add(showLegend);
220 // manager.add(filterTraces);
222 manager
.add(zoomOut
);
224 manager
.add(new Separator());
225 manager
.add(new Separator(IWorkbenchActionConstants
.MB_ADDITIONS
));
228 private void fillLocalToolBar(IToolBarManager manager
) {
229 // manager.add(showLegend);
230 manager
.add(new Separator());
231 manager
.add(resetScale
);
232 manager
.add(nextEvent
);
233 manager
.add(prevEvent
);
234 manager
.add(nextTrace
);
235 manager
.add(prevTrace
);
236 // manager.add(filterTraces);
238 manager
.add(zoomOut
);
240 manager
.add(new Separator());
243 private void makeActions() {
245 resetScale
= new Action() {
248 if (tsfviewer
!= null) {
249 tsfviewer
.resetStartFinishTime();
254 resetScale
.setText(Messages
.getString("ResourcesView.Action.Reset")); //$NON-NLS-1$
255 resetScale
.setToolTipText(Messages
256 .getString("ResourcesView.Action.Reset.ToolTip")); //$NON-NLS-1$
257 resetScale
.setImageDescriptor(AbstractUIPlugin
258 .imageDescriptorFromPlugin(Messages
259 .getString("ResourcesView.tmf.UI"),
260 "icons/home_nav.gif"));
263 nextEvent
= new Action() {
266 if (tsfviewer
!= null) {
267 tsfviewer
.selectNextEvent();
271 nextEvent
.setText(Messages
.getString("ResourcesView.Action.NextEvent")); //$NON-NLS-1$
272 nextEvent
.setToolTipText(Messages
273 .getString("ResourcesView.Action.NextEvent.Tooltip")); //$NON-NLS-1$
274 nextEvent
.setImageDescriptor(AbstractUIPlugin
275 .imageDescriptorFromPlugin(Messages
276 .getString("ResourcesView.tmf.UI"),
277 "icons/next_event.gif"));
280 prevEvent
= new Action() {
283 if (tsfviewer
!= null) {
284 tsfviewer
.selectPrevEvent();
288 prevEvent
.setText(Messages
.getString("ResourcesView.Action.PrevEvent")); //$NON-NLS-1$
289 prevEvent
.setToolTipText(Messages
290 .getString("ResourcesView.Action.PrevEvent.Tooltip")); //$NON-NLS-1$
291 prevEvent
.setImageDescriptor(AbstractUIPlugin
292 .imageDescriptorFromPlugin(Messages
293 .getString("ResourcesView.tmf.UI"),
294 "icons/prev_event.gif"));
297 nextTrace
= new Action() {
300 if (tsfviewer
!= null) {
301 tsfviewer
.selectNextTrace();
305 nextTrace
.setText(Messages
306 .getString("ResourcesView.Action.NextResource")); //$NON-NLS-1$
307 nextTrace
.setToolTipText(Messages
308 .getString("ResourcesView.Action.NextResource.ToolTip")); //$NON-NLS-1$
309 nextTrace
.setImageDescriptor(AbstractUIPlugin
310 .imageDescriptorFromPlugin(Messages
311 .getString("ResourcesView.tmf.UI"),
312 "icons/next_item.gif"));
315 prevTrace
= new Action() {
318 if (tsfviewer
!= null) {
319 tsfviewer
.selectPrevTrace();
323 prevTrace
.setText(Messages
324 .getString("ResourcesView.Action.PreviousResource")); //$NON-NLS-1$
325 prevTrace
.setToolTipText(Messages
326 .getString("ResourcesView.Action.PreviousResource.Tooltip")); //$NON-NLS-1$
327 prevTrace
.setImageDescriptor(AbstractUIPlugin
328 .imageDescriptorFromPlugin(Messages
329 .getString("ResourcesView.tmf.UI"),
330 "icons/prev_item.gif"));
333 showLegend
= new Action() {
336 if (tsfviewer
!= null) {
337 tsfviewer
.showLegend();
341 showLegend
.setText(Messages
.getString("ResourcesView.Action.Legend")); //$NON-NLS-1$
342 showLegend
.setToolTipText(Messages
343 .getString("ResourcesView.Action.Legend.ToolTip")); //$NON-NLS-1$
346 filterTraces
= new Action() {
349 if (tsfviewer
!= null) {
350 tsfviewer
.filterTraces();
354 filterTraces
.setText(Messages
.getString("ResourcesView.Action.Filter")); //$NON-NLS-1$
355 filterTraces
.setToolTipText(Messages
356 .getString("ResourcesView.Action.Filter.ToolTip")); //$NON-NLS-1$
357 filterTraces
.setImageDescriptor(AbstractUIPlugin
358 .imageDescriptorFromPlugin(Messages
359 .getString("ResourcesView.tmf.UI"),
360 "icons/filter_items.gif"));
363 zoomIn
= new Action() {
366 if (tsfviewer
!= null) {
371 zoomIn
.setText(Messages
.getString("ResourcesView.Action.ZoomIn")); //$NON-NLS-1$
372 zoomIn
.setToolTipText(Messages
373 .getString("ResourcesView.Action.ZoomIn.Tooltip")); //$NON-NLS-1$
374 zoomIn
.setImageDescriptor(AbstractUIPlugin
.imageDescriptorFromPlugin(
375 Messages
.getString("ResourcesView.tmf.UI"),
376 "icons/zoomin_nav.gif"));
379 zoomOut
= new Action() {
382 if (tsfviewer
!= null) {
387 zoomOut
.setText(Messages
.getString("ResourcesView.Action.ZoomOut")); //$NON-NLS-1$
388 zoomOut
.setToolTipText(Messages
389 .getString("ResourcesView.Action.ZoomOut.tooltip")); //$NON-NLS-1$
390 zoomOut
.setImageDescriptor(AbstractUIPlugin
.imageDescriptorFromPlugin(
391 Messages
.getString("ResourcesView.tmf.UI"),
392 "icons/zoomout_nav.gif"));
395 synch
= new Action() {
398 // Note: No action since the synch flag is used by Control flow
400 // the actual viewer is set to accept api selections in
401 // createpartcontrol.
403 // if (synch.isChecked()) {
404 // tsfviewer.setAcceptSelectionAPIcalls(true);
406 // tsfviewer.setAcceptSelectionAPIcalls(false);
410 synch
.setText(Messages
.getString("ResourcesView.Action.Synchronize")); //$NON-NLS-1$
411 synch
.setToolTipText(Messages
412 .getString("ResourcesView.Action.Synchronize.ToolTip")); //$NON-NLS-1$
413 synch
.setChecked(false);
414 synch
.setImageDescriptor(AbstractUIPlugin
.imageDescriptorFromPlugin(
415 Messages
.getString("ResourcesView.tmf.UI"),
416 "icons/synced.gif"));
417 // PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_SYNCED);
421 * Passing the focus request to the viewer's control.
424 public void setFocus() {
425 tsfviewer
.getControl().setFocus();
428 public void tsfTmProcessSelEvent(TmfTimeSelectionEvent event
) {
429 Object source
= event
.getSource();
430 if (source
== null) {
434 // TmfTimeAnalysisViewer rViewer = (TmfTimeAnalysisViewer)
435 // event.getSource();
436 // TmfTimeAnalysisViewer synchViewer = null;
437 // Synchronize viewer selections if Enabled,
438 // make sure the selection does not go in loops
439 // if (tsfviewer == rViewer) {
440 // synchViewer = tsfviewer2;
442 // synchViewer = tsfviewer;
444 // Notify listener views.
446 ParamsUpdater paramUpdater
= ResourceModelFactory
.getParamsUpdater();
447 Long savedSelTime
= paramUpdater
.getSelectedTime();
449 long selTimens
= event
.getSelectedTime();
451 // make sure the new selected time is different than saved before
453 if (savedSelTime
== null || savedSelTime
!= selTimens
) {
454 // Notify listener views.
455 synchTimeNotification(selTimens
);
457 // Update the parameter updater to save the selected time
458 paramUpdater
.setSelectedTime(selTimens
);
460 if (TraceDebug
.isDEBUG()) {
461 // Object selection = event.getSelection();
462 TraceDebug
.debug("Selected Time in Resource View: "
463 + new LttngTimestamp(selTimens
));
468 public void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event
) {
469 // source needed to keep track of source values
470 Object source
= event
.getSource();
472 if (source
!= null) {
473 // Update the parameter updater before carrying out a read request
474 ParamsUpdater paramUpdater
= ResourceModelFactory
476 boolean newParams
= paramUpdater
.processTimeScaleEvent(event
);
479 // Read the updated time window
480 TmfTimeRange trange
= paramUpdater
.getTrange();
481 if (trange
!= null) {
482 StateManagerFactory
.getExperimentManager()
483 .readExperimentTimeWindow(trange
, "resourceView",
491 * Obtains the remainder fraction on unit Seconds of the entered value in
492 * nanoseconds. e.g. input: 1241207054171080214 ns The number of seconds can
493 * be obtain by removing the last 9 digits: 1241207054 the fractional
494 * portion of seconds, expressed in ns is: 171080214
499 public String
formatNs(long v
) {
500 StringBuffer str
= new StringBuffer();
507 String strVal
= String
.valueOf(v
);
508 if (v
< 1000000000) {
512 // Extract the last nine digits (e.g. fraction of a S expressed in ns
513 return strVal
.substring(strVal
.length() - 9);
517 // public void resourceModelUpdates(ModelUpdatesEvent event) {
518 // ITmfTimeAnalysisEntry[] items = event.getItems();
519 // resourceModelUpdates(items, event.getStartTime(), event.getEndTime());
522 public void resourceModelUpdates(final ITmfTimeAnalysisEntry
[] items
,
523 final long startTime
, final long endTime
) {
524 tsfviewer
.getControl().getDisplay().asyncExec(new Runnable() {
527 tsfviewer
.display(items
, startTime
, endTime
);
528 tsfviewer
.resizeControls();
534 public void dispose() {
535 // dispose parent resources
537 // Remove the event processor factory
538 EventProcessorProxy
.getInstance().removeEventProcessorFactory(
539 ResourcesTRangeUpdateFactory
.getInstance());
541 tsfviewer
.removeWidgetSelectionListner(this);
542 tsfviewer
.removeWidgetTimeScaleSelectionListner(this);
549 * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener#
550 * processingStarted(org.eclipse.linuxtools.lttng.state.StateDataRequest)
553 public void processingStarted(RequestStartedSignal startSignal
) {
554 StateDataRequest request
= startSignal
.getRequest();
555 cancelPendingRequests();
556 if (request
!= null) {
557 // make sure there are no duplicates
558 if (!pendingDataRequests
.contains(request
)) {
559 pendingDataRequests
.add(request
);
562 StateManager smanager
= request
.getStateManager();
563 // Clear the children on the Processes related to this manager.
564 // Leave the GUI in charge of the updated data.
565 String traceId
= smanager
.getEventLog().getName();
566 ResourceModelFactory
.getResourceContainer().clearChildren(traceId
);
568 ResourceModelFactory
.getParamsUpdater().setEventsDiscarded(0);
573 * Orders cancellation of any pending data requests
575 private void cancelPendingRequests() {
576 for (StateDataRequest request
: pendingDataRequests
) {
579 pendingDataRequests
.clear();
585 * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener#
586 * processingCompleted(org.eclipse.linuxtools.lttng.state.StateDataRequest)
589 public void processingCompleted(
590 RequestCompletedSignal completedSignal
) {
591 StateDataRequest request
= completedSignal
.getRequest();
593 if (request
== null) {
596 // Remove from the pending requests record
597 pendingDataRequests
.remove(request
);
600 // No data refresh actions for cancelled requests.
601 if (request
.isCancelled() || request
.isFailed()) {
602 if (TraceDebug
.isDEBUG()) {
603 TmfTimeRange range
= request
.getRange();
604 TraceDebug
.debug("Request cancelled: "
605 + range
.getStartTime().toString() + " - "
606 + range
.getEndTime().toString());
611 StateManager smanager
= request
.getStateManager();
612 long experimentStartTime
= -1;
613 long experimentEndTime
= -1;
614 TmfTimeRange experimentTimeRange
= smanager
.getExperimentTimeWindow();
615 if (experimentTimeRange
!= null) {
616 experimentStartTime
= experimentTimeRange
.getStartTime().getValue();
617 experimentEndTime
= experimentTimeRange
.getEndTime().getValue();
620 // Obtain the current resource list
621 TimeRangeEventResource
[] resourceArr
= ResourceModelFactory
622 .getResourceContainer().readResources();
624 // Sort the array by pid
625 Arrays
.sort(resourceArr
);
627 // Update the view part
628 resourceModelUpdates(resourceArr
, experimentStartTime
,
631 // reselect to original time
632 ParamsUpdater paramUpdater
= ResourceModelFactory
.getParamsUpdater();
633 final Long selTime
= paramUpdater
.getSelectedTime();
634 if (selTime
!= null) {
635 Display display
= tsfviewer
.getControl().getDisplay();
636 display
.asyncExec(new Runnable() {
638 tsfviewer
.setSelectedTime(selTime
, false, this);
643 if (TraceDebug
.isDEBUG()) {
644 Long count
= smanager
.getEventCount();
646 for (TimeRangeEventResource resource
: resourceArr
) {
647 eventCount
+= resource
.getTraceEvents().size();
650 int discarded
= ResourceModelFactory
.getParamsUpdater()
651 .getEventsDiscarded();
652 int discardedOutofOrder
= ResourceModelFactory
.getParamsUpdater()
653 .getEventsDiscardedWrongOrder();
655 .debug("Events handled: "
657 + " Events loaded in Resource view: "
659 + " Number of events discarded: "
661 + "\n\tNumber of events discarded with start time earlier than next good time: "
662 + discardedOutofOrder
);
667 public void newTimeRange(TimeRangeComponent trange
) {
668 // TODO Auto-generated method stub
673 * Trigger time synchronisation to other views this method shall be called
674 * when a check has been performed to note that an actual change of time has
675 * been performed vs a pure re-selection of the same time
679 private void synchTimeNotification(long time
) {
680 // if synchronisation selected
681 if (synch
.isChecked()) {
682 // Notify other views
683 TmfSignalManager
.dispatchSignal(new TmfTimeSynchSignal(this,
684 new LttngTimestamp(time
)));
689 * Registers as listener of time selection from other tmf views
694 public void synchToTime(TmfTimeSynchSignal signal
) {
695 if (synch
.isChecked()) {
696 Object source
= signal
.getSource();
697 if (signal
!= null && source
!= null && source
!= this) {
698 // Internal value is expected in nano seconds.
699 long selectedTime
= signal
.getCurrentTime().getValue();
700 if (tsfviewer
!= null) {
701 tsfviewer
.setSelectedTime(selectedTime
, true, source
);