Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file GUITLLogicPhasesTrackerWindow.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Oct/Nov 2003
19 : ///
20 : // A window displaying the phase diagram of a tl-logic
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <vector>
25 : #include <iostream>
26 : #include <utils/gui/windows/GUIMainWindow.h>
27 : #include <utils/gui/div/GLHelper.h>
28 : #include "GUITLLogicPhasesTrackerWindow.h"
29 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
30 : #include <microsim/output/MSInductLoop.h>
31 : #include <microsim/MSLink.h>
32 : #include <utils/common/ToString.h>
33 : #include <utils/common/MsgHandler.h>
34 : #include <guisim/GUITrafficLightLogicWrapper.h>
35 : #include <utils/gui/windows/GUIAppEnum.h>
36 : #include <utils/gui/images/GUIIconSubSys.h>
37 : #include <utils/gui/settings/GUIVisualizationSettings.h>
38 : #include <utils/gui/div/GUIDesigns.h>
39 : #include <foreign/fontstash/fontstash.h>
40 : #include <utils/gui/globjects/GLIncludes.h>
41 :
42 :
43 : // ===========================================================================
44 : // static member initialisation
45 : // ===========================================================================
46 : int GUITLLogicPhasesTrackerWindow::myLastY(-1);
47 :
48 : // ===========================================================================
49 : // member method definitions
50 : // ===========================================================================
51 : /* -------------------------------------------------------------------------
52 : * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-callbacks
53 : * ----------------------------------------------------------------------- */
54 : FXDEFMAP(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel) GUITLLogicPhasesTrackerPanelMap[] = {
55 : FXMAPFUNC(SEL_CONFIGURE, 0, GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onConfigure),
56 : FXMAPFUNC(SEL_PAINT, 0, GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onPaint),
57 : FXMAPFUNC(SEL_MOTION, 0, GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onMouseMove),
58 :
59 : };
60 :
61 : // Macro for the GLTestApp class hierarchy implementation
62 0 : FXIMPLEMENT(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel, FXGLCanvas, GUITLLogicPhasesTrackerPanelMap, ARRAYNUMBER(GUITLLogicPhasesTrackerPanelMap))
63 :
64 :
65 :
66 : /* -------------------------------------------------------------------------
67 : * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-methods
68 : * ----------------------------------------------------------------------- */
69 0 : GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::GUITLLogicPhasesTrackerPanel(
70 : FXComposite* c, GUIMainWindow& app,
71 0 : GUITLLogicPhasesTrackerWindow& parent) :
72 0 : FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) nullptr, (FXSelector) 0, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y/*, 0, 0, 300, 200*/),
73 0 : myParent(&parent)
74 0 : {}
75 :
76 :
77 0 : GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::~GUITLLogicPhasesTrackerPanel() {}
78 :
79 :
80 : long
81 0 : GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onConfigure(FXObject*, FXSelector, void*) {
82 0 : if (makeCurrent()) {
83 : int widthInPixels = getWidth();
84 : int heightInPixels = getHeight();
85 0 : if (widthInPixels != 0 && heightInPixels != 0) {
86 0 : glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
87 0 : glClearColor(0, 0, 0, 1);
88 0 : glDisable(GL_DEPTH_TEST);
89 0 : glDisable(GL_LIGHTING);
90 0 : glDisable(GL_LINE_SMOOTH);
91 0 : glEnable(GL_BLEND);
92 0 : glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
93 0 : glEnable(GL_ALPHA_TEST);
94 0 : glDisable(GL_COLOR_MATERIAL);
95 0 : glLineWidth(1);
96 0 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
97 : }
98 : }
99 0 : return 1;
100 : }
101 :
102 :
103 : long
104 0 : GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onPaint(
105 : FXObject*, FXSelector, void*) {
106 0 : if (!isEnabled()) {
107 : return 1;
108 : }
109 0 : if (makeCurrent()) {
110 : int widthInPixels = getWidth();
111 : int heightInPixels = getHeight();
112 0 : if (widthInPixels != 0 && heightInPixels != 0) {
113 0 : glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
114 0 : glClearColor(0, 0, 0, 1);
115 0 : glDisable(GL_DEPTH_TEST);
116 0 : glDisable(GL_LIGHTING);
117 0 : glDisable(GL_LINE_SMOOTH);
118 0 : glEnable(GL_BLEND);
119 0 : glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
120 0 : glEnable(GL_ALPHA_TEST);
121 0 : glDisable(GL_COLOR_MATERIAL);
122 0 : glLineWidth(1);
123 0 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
124 : // draw
125 0 : glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
126 0 : myParent->drawValues(*this);
127 0 : swapBuffers();
128 : }
129 0 : makeNonCurrent();
130 : }
131 : return 1;
132 : }
133 :
134 :
135 : long
136 0 : GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onMouseMove(FXObject*, FXSelector, void* ptr) {
137 : FXEvent* event = (FXEvent*) ptr;
138 0 : myMousePos.setx(event->win_x);
139 0 : myMousePos.sety(event->win_y);
140 0 : onPaint(nullptr, 0, nullptr);
141 0 : return 1;
142 : }
143 :
144 : /* -------------------------------------------------------------------------
145 : * GUITLLogicPhasesTrackerWindow - FOX callback mapping
146 : * ----------------------------------------------------------------------- */
147 : FXDEFMAP(GUITLLogicPhasesTrackerWindow) GUITLLogicPhasesTrackerWindowMap[] = {
148 : FXMAPFUNC(SEL_CONFIGURE, 0, GUITLLogicPhasesTrackerWindow::onConfigure),
149 : FXMAPFUNC(SEL_PAINT, 0, GUITLLogicPhasesTrackerWindow::onPaint),
150 : FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUITLLogicPhasesTrackerWindow::onSimStep),
151 :
152 : };
153 :
154 0 : FXIMPLEMENT(GUITLLogicPhasesTrackerWindow, FXMainWindow, GUITLLogicPhasesTrackerWindowMap, ARRAYNUMBER(GUITLLogicPhasesTrackerWindowMap))
155 :
156 :
157 : /* -------------------------------------------------------------------------
158 : * GUITLLogicPhasesTrackerWindow-methods
159 : * ----------------------------------------------------------------------- */
160 0 : GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerWindow(
161 : GUIMainWindow& app,
162 : MSTrafficLightLogic& logic, GUITrafficLightLogicWrapper& wrapper,
163 0 : ValueSource<std::pair<SUMOTime, MSPhaseDefinition> >* src) :
164 : FXMainWindow(app.getApp(), "TLS-Tracker", nullptr, nullptr, DECOR_ALL, 20, 20, 300, 200),
165 0 : myApplication(&app),
166 0 : myTLLogic(&logic),
167 0 : myAmInTrackingMode(true) {
168 0 : initToolBar();
169 0 : myConnector = new GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >(wrapper, src, this);
170 0 : app.addChild(this);
171 0 : for (int i = 0; i < (int)myTLLogic->getLinks().size(); ++i) {
172 0 : myLinkNames.push_back(toString<int>(i));
173 : }
174 0 : for (auto item : myTLLogic->getDetectorStates()) {
175 : std::string detID = item.first;
176 0 : if (detID.size() > 4) {
177 0 : detID = detID.substr(detID.size() - 4);
178 : }
179 0 : myDetectorNames.push_back(detID);
180 : }
181 0 : for (auto item : myTLLogic->getConditions()) {
182 0 : myConditionNames.push_back(item.first);
183 : }
184 : FXVerticalFrame* glcanvasFrame =
185 : new FXVerticalFrame(this,
186 : FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
187 0 : 0, 0, 0, 0, 0, 0, 0, 0);
188 0 : myPanel = new GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
189 0 : setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str());
190 0 : setIcon(GUIIconSubSys::getIcon(GUIIcon::APP_TLSTRACKER));
191 0 : loadSettings();
192 0 : setHeight(computeHeight());
193 0 : }
194 :
195 :
196 0 : GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerWindow(
197 : GUIMainWindow& app,
198 : MSTrafficLightLogic& logic, GUITrafficLightLogicWrapper& /*wrapper*/,
199 0 : const MSSimpleTrafficLightLogic::Phases& /*phases*/) :
200 : FXMainWindow(app.getApp(), "TLS-Tracker", nullptr, nullptr, DECOR_ALL, 20, 20, 300, 200),
201 0 : myApplication(&app),
202 0 : myTLLogic(&logic),
203 0 : myAmInTrackingMode(false),
204 0 : myToolBarDrag(nullptr),
205 0 : myBeginOffset(nullptr) {
206 0 : myConnector = nullptr;
207 0 : initToolBar();
208 0 : app.addChild(this);
209 0 : for (int i = 0; i < (int)myTLLogic->getLinks().size(); ++i) {
210 0 : myLinkNames.push_back(toString<int>(i));
211 : }
212 : FXVerticalFrame* glcanvasFrame =
213 : new FXVerticalFrame(this,
214 : FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
215 0 : 0, 0, 0, 0, 0, 0, 0, 0);
216 0 : myPanel = new GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
217 0 : setTitle((logic.getID() + " - " + logic.getProgramID() + " - phases").c_str());
218 0 : setIcon(GUIIconSubSys::getIcon(GUIIcon::APP_TLSTRACKER));
219 0 : setHeight(computeHeight());
220 0 : setWidth(700);
221 0 : }
222 :
223 :
224 0 : GUITLLogicPhasesTrackerWindow::~GUITLLogicPhasesTrackerWindow() {
225 0 : if (myAmInTrackingMode) {
226 0 : saveSettings();
227 0 : myLastY = -1;
228 : }
229 0 : myApplication->removeChild(this);
230 0 : delete myConnector;
231 : // just to quit cleanly on a failure
232 0 : if (myLock.locked()) {
233 0 : myLock.unlock();
234 : }
235 0 : delete myToolBarDrag;
236 0 : }
237 :
238 : void
239 0 : GUITLLogicPhasesTrackerWindow::initToolBar() {
240 0 : myToolBarDrag = new FXToolBarShell(this, GUIDesignToolBar);
241 0 : myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
242 0 : new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
243 :
244 0 : if (myAmInTrackingMode) {
245 : // interval manipulation
246 0 : new FXLabel(myToolBar, "range (s):", nullptr, LAYOUT_CENTER_Y);
247 0 : myBeginOffset = new FXRealSpinner(myToolBar, 4, this, MID_SIMSTEP, LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
248 : //myBeginOffset->setFormatString("%.0f");
249 : //myBeginOffset->setIncrements(1, 10, 100);
250 0 : myBeginOffset->setIncrement(10);
251 0 : myBeginOffset->setRange(60, 3600);
252 0 : myBeginOffset->setValue(240);
253 : }
254 :
255 0 : new FXLabel(myToolBar, "time style:", nullptr, LAYOUT_CENTER_Y);
256 0 : myTimeMode = new MFXComboBoxIcon(myToolBar, 11, false, GUIDesignComboBoxVisibleItemsMedium,
257 0 : this, MID_SIMSTEP, GUIDesignViewSettingsComboBox1);
258 0 : myTimeMode->appendIconItem("seconds");
259 0 : myTimeMode->appendIconItem("MM:SS");
260 0 : myTimeMode->appendIconItem("time in cycle");
261 :
262 0 : new FXLabel(myToolBar, "green time", nullptr, LAYOUT_CENTER_Y);
263 0 : myGreenMode = new MFXComboBoxIcon(myToolBar, 6, false, GUIDesignComboBoxVisibleItemsMedium,
264 0 : this, MID_SIMSTEP, GUIDesignViewSettingsComboBox1);
265 0 : myGreenMode->appendIconItem("off");
266 0 : myGreenMode->appendIconItem("phase");
267 0 : myGreenMode->appendIconItem("running");
268 :
269 0 : myIndexMode = new FXCheckButton(myToolBar, TL("phase names"), this, MID_SIMSTEP);
270 :
271 0 : if (myAmInTrackingMode) {
272 0 : myDetectorMode = new FXCheckButton(myToolBar, TL("detectors"), this, MID_SIMSTEP);
273 0 : myConditionMode = new FXCheckButton(myToolBar, TL("conditions"), this, MID_SIMSTEP);
274 : } else {
275 0 : myDetectorMode = nullptr;
276 0 : myConditionMode = nullptr;
277 : }
278 0 : }
279 :
280 :
281 : void
282 0 : GUITLLogicPhasesTrackerWindow::create() {
283 0 : FXMainWindow::create();
284 0 : if (myToolBarDrag != nullptr) {
285 0 : myToolBarDrag->create();
286 : }
287 0 : }
288 :
289 : int
290 0 : GUITLLogicPhasesTrackerWindow::computeHeight() {
291 0 : int newHeight = (int)myTLLogic->getLinks().size() * 20 + 30 + 8 + 30 + 60;
292 0 : if (myAmInTrackingMode) {
293 0 : newHeight += 20; // time bar
294 0 : if (myDetectorMode->getCheck()) {
295 0 : newHeight += (int)myTLLogic->getDetectorStates().size() * 20 + 5;
296 : }
297 0 : if (myConditionMode->getCheck()) {
298 0 : newHeight += (int)myTLLogic->getConditions().size() * 20 + 5;
299 : }
300 : }
301 0 : return newHeight;
302 : }
303 :
304 : void
305 0 : GUITLLogicPhasesTrackerWindow::drawValues(GUITLLogicPhasesTrackerPanel& caller) {
306 : // compute what shall be shown (what is visible)
307 0 : myFirstPhase2Show = 0;
308 0 : myFirstPhaseOffset = 0;
309 : SUMOTime leftOffset = 0;
310 0 : myFirstDet2Show = 0;
311 0 : myFirstDetOffset = 0;
312 0 : myFirstCond2Show = 0;
313 0 : myFirstCondOffset = 0;
314 0 : myFirstTime2Show = 0;
315 0 : if (!myAmInTrackingMode) {
316 0 : myPhases.clear();
317 0 : myDurations.clear();
318 0 : myTimeInCycle.clear();
319 0 : myPhaseIndex.clear();
320 : // insert phases
321 0 : MSSimpleTrafficLightLogic* simpleTLLogic = dynamic_cast<MSSimpleTrafficLightLogic*>(myTLLogic);
322 0 : if (simpleTLLogic == nullptr) {
323 0 : return;
324 : }
325 0 : myLastTime = 0;
326 0 : myBeginTime = 0;
327 : int idx = 0;
328 0 : for (MSPhaseDefinition* const phase : simpleTLLogic->getPhases()) {
329 0 : myPhases.push_back(*phase);
330 0 : myDurations.push_back(phase->duration);
331 0 : myTimeInCycle.push_back(myLastTime);
332 0 : myPhaseIndex.push_back(idx++);
333 0 : myLastTime += phase->duration;
334 : }
335 0 : if (myLastTime <= myBeginTime) {
336 0 : WRITE_ERROR(TL("Overflow in time computation occurred."));
337 0 : return;
338 : }
339 : } else {
340 0 : SUMOTime beginOffset = TIME2STEPS(myBeginOffset->getValue());
341 0 : myBeginTime = myLastTime - beginOffset;
342 0 : myFirstTime2Show = myBeginTime;
343 : // check whether no phases are known at all
344 0 : if (myDurations.size() != 0) {
345 : SUMOTime durs = 0;
346 0 : int phaseOffset = (int)myDurations.size() - 1;
347 : DurationsVector::reverse_iterator i = myDurations.rbegin();
348 0 : while (i != myDurations.rend()) {
349 0 : if (durs + (*i) > beginOffset) {
350 0 : myFirstPhase2Show = phaseOffset;
351 0 : myFirstPhaseOffset = (durs + (*i)) - beginOffset;
352 0 : break;
353 : }
354 : durs += (*i);
355 0 : phaseOffset--;
356 : ++i;
357 : }
358 0 : if (i == myDurations.rend()) {
359 : // there are too few information stored;
360 0 : myFirstPhase2Show = 0;
361 0 : myFirstPhaseOffset = 0;
362 0 : leftOffset = beginOffset - durs;
363 : }
364 : }
365 0 : if (myDetectorDurations.size() != 0) {
366 : SUMOTime durs = 0;
367 0 : int phaseOffset = (int)myDetectorDurations.size() - 1;
368 : DurationsVector::reverse_iterator i = myDetectorDurations.rbegin();
369 0 : while (i != myDetectorDurations.rend()) {
370 0 : if (durs + (*i) > beginOffset) {
371 0 : myFirstDet2Show = phaseOffset;
372 0 : myFirstDetOffset = (durs + (*i)) - beginOffset;
373 0 : break;
374 : }
375 : durs += (*i);
376 0 : phaseOffset--;
377 : ++i;
378 : }
379 0 : if (i == myDetectorDurations.rend()) {
380 : // there are too few information stored;
381 0 : myFirstDet2Show = 0;
382 0 : myFirstDetOffset = 0;
383 : }
384 : }
385 0 : if (myConditionDurations.size() != 0) {
386 : SUMOTime durs = 0;
387 0 : int phaseOffset = (int)myConditionDurations.size() - 1;
388 : DurationsVector::reverse_iterator i = myConditionDurations.rbegin();
389 0 : while (i != myConditionDurations.rend()) {
390 0 : if (durs + (*i) > beginOffset) {
391 0 : myFirstCond2Show = phaseOffset;
392 0 : myFirstCondOffset = (durs + (*i)) - beginOffset;
393 0 : break;
394 : }
395 : durs += (*i);
396 0 : phaseOffset--;
397 : ++i;
398 : }
399 0 : if (i == myConditionDurations.rend()) {
400 : // there are too few information stored;
401 0 : myFirstCond2Show = 0;
402 0 : myFirstCondOffset = 0;
403 : }
404 : }
405 : }
406 : // begin drawing
407 0 : glMatrixMode(GL_PROJECTION);
408 0 : glLoadIdentity();
409 0 : glMatrixMode(GL_MODELVIEW);
410 0 : glLoadIdentity();
411 0 : glTranslated(-1, -1, 0);
412 0 : glScaled(2, 2, 1);
413 0 : glDisable(GL_TEXTURE_2D);
414 : // draw the horizontal lines dividing the signal groups
415 0 : glColor3d(1, 1, 1);
416 : // compute some values needed more than once
417 0 : const double panelHeight = (double) caller.getHeight();
418 0 : const double panelWidth = (double) caller.getWidth();
419 0 : const double barWidth = MAX2(1.0, panelWidth - 31);
420 0 : const double fontHeight = 0.06 * 300. / panelHeight;
421 0 : const double fontWidth = 0.06 * 300. / panelWidth;
422 0 : const double h9 = 9. / panelHeight;
423 0 : const double hTop = 20. / panelHeight;
424 0 : const double h11 = 11. / panelHeight;
425 0 : const double stateHeight = 16. / panelHeight;
426 : const double h20 = 20. / panelHeight;
427 0 : const double h30 = 15. / panelHeight;
428 0 : const double h35 = 34. / panelHeight;
429 0 : const double h60 = 70. / panelHeight;
430 0 : const double h75 = 73. / panelHeight;
431 0 : const double h80 = 90. / panelHeight;
432 0 : const double w30 = 30 / panelWidth;
433 0 : double h = 1. - hTop;
434 : // draw the line below indices
435 0 : glColor3d(1, 1, 1);
436 0 : glBegin(GL_LINES);
437 0 : glVertex2d(0, h);
438 0 : glVertex2d(1, h);
439 0 : glEnd();
440 : // draw the link names and the lines dividing them
441 0 : drawNames(myLinkNames, fontHeight, fontWidth, h20, w30, h, 0);
442 0 : glBegin(GL_LINES);
443 0 : glVertex2d(0, h + h20);
444 0 : glVertex2d(1.0, h + h20);
445 0 : glEnd();
446 :
447 : // draw the names closure (vertical line)
448 0 : h += h20;
449 0 : glColor3d(1, 1, 1);
450 0 : glBegin(GL_LINES);
451 0 : glVertex2d(w30, 1.);
452 0 : glVertex2d(w30, h);
453 0 : glEnd();
454 :
455 0 : if (myAmInTrackingMode) {
456 : // optionally draw detector names
457 0 : h -= h60;
458 0 : if (myDetectorMode->getCheck()) {
459 : const double top = h;
460 0 : glBegin(GL_LINES);
461 0 : glVertex2d(0, h);
462 0 : glVertex2d(1.0, h);
463 0 : glEnd();
464 0 : drawNames(myDetectorNames, fontHeight * 0.7, fontWidth * 0.7, h20, w30, h, 3);
465 0 : glBegin(GL_LINES);
466 0 : glVertex2d(0, h + h20);
467 0 : glVertex2d(1.0, h + h20);
468 0 : glEnd();
469 : // draw the names closure (vertical line)
470 0 : glColor3d(1, 1, 1);
471 0 : glBegin(GL_LINES);
472 0 : glVertex2d(30. / panelWidth, top);
473 0 : glVertex2d(30. / panelWidth, h + h20);
474 0 : glEnd();
475 0 : h -= h30;
476 : }
477 : // optionally draw condition names
478 0 : if (myConditionMode->getCheck()) {
479 0 : const double top = h;
480 0 : glBegin(GL_LINES);
481 0 : glVertex2d(0, h);
482 0 : glVertex2d(1.0, h);
483 0 : glEnd();
484 0 : drawNames(myConditionNames, fontHeight * 0.7, fontWidth * 0.7, h20, w30, h, 3);
485 0 : glBegin(GL_LINES);
486 0 : glVertex2d(0, h + h20);
487 0 : glVertex2d(1.0, h + h20);
488 0 : glEnd();
489 : // draw the names closure (vertical line)
490 0 : glColor3d(1, 1, 1);
491 0 : glBegin(GL_LINES);
492 0 : glVertex2d(30. / panelWidth, top);
493 0 : glVertex2d(30. / panelWidth, h + h20);
494 0 : glEnd();
495 : }
496 : }
497 :
498 : // draw the phases
499 : // disable value addition while drawing
500 0 : myLock.lock();
501 : // determine the initial offset
502 0 : double x = 31. / panelWidth;
503 0 : double ta = (double) leftOffset / panelWidth;
504 0 : ta *= barWidth / ((double)(myLastTime - myBeginTime));
505 0 : x += ta;
506 :
507 : // and the initial phase information
508 0 : PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
509 : IndexVector::iterator ii = myPhaseIndex.begin() + myFirstPhase2Show;
510 :
511 0 : SUMOTime fpo = myFirstPhaseOffset;
512 0 : const bool phaseNames = myIndexMode->getCheck() == TRUE;
513 0 : std::string lastName = "";
514 : double spaceForName = 0;
515 :
516 : // start drawing
517 0 : std::vector<SUMOTime> runningGreen(myTLLogic->getLinks().size(), 0);
518 0 : for (DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show; pd != myDurations.end(); ++pd) {
519 : // the first phase may be drawn incompletely
520 0 : SUMOTime duration = *pd - fpo;
521 : // compute the height and the width of the phase
522 0 : h = 1. - hTop;
523 0 : double a = (double) duration / panelWidth;
524 0 : a *= barWidth / ((double)(myLastTime - myBeginTime));
525 0 : const double x2 = x + a;
526 :
527 : // go through the links
528 0 : for (int j = 0; j < (int) myTLLogic->getLinks().size(); ++j) {
529 : // determine the current link's color
530 0 : LinkState state = pi->getSignalState(j);
531 : // draw the bar (red is drawn as a line)
532 0 : GLHelper::setColor(GUIVisualizationSettings::getLinkColor(state));
533 0 : switch (state) {
534 0 : case LINKSTATE_TL_RED:
535 : case LINKSTATE_TL_REDYELLOW:
536 : // draw a thin line
537 0 : glBegin(GL_QUADS);
538 0 : glVertex2d(x, h - h11);
539 0 : glVertex2d(x, h - h9);
540 0 : glVertex2d(x2, h - h9);
541 0 : glVertex2d(x2, h - h11);
542 0 : glEnd();
543 : break;
544 0 : default:
545 : // draw a thick block
546 0 : glBegin(GL_QUADS);
547 0 : glVertex2d(x, h - stateHeight);
548 0 : glVertex2d(x, h);
549 0 : glVertex2d(x2, h);
550 0 : glVertex2d(x2, h - stateHeight);
551 0 : glEnd();
552 : break;
553 : }
554 0 : if (myGreenMode->getCurrentItem() != 0) {
555 : SUMOTime drawnDuration = 0;
556 : double xOffset = 0;
557 0 : if (state == LINKSTATE_TL_GREEN_MINOR || state == LINKSTATE_TL_GREEN_MAJOR) {
558 0 : if (myGreenMode->getCurrentItem() == 1) {
559 0 : drawnDuration = *pd;
560 : } else {
561 0 : runningGreen[j] += *pd;
562 0 : if (pd + 1 == myDurations.end()) {
563 : drawnDuration = runningGreen[j];
564 0 : xOffset = -(double)(drawnDuration - *pd) / panelWidth * (barWidth / ((double)(myLastTime - myBeginTime)));
565 : }
566 : }
567 : } else {
568 0 : if (runningGreen[j] > 0) {
569 : drawnDuration = runningGreen[j];
570 0 : xOffset = -(double)drawnDuration / panelWidth * (barWidth / ((double)(myLastTime - myBeginTime)));
571 : }
572 0 : runningGreen[j] = 0;
573 : }
574 0 : if (drawnDuration > 0) {
575 0 : GLHelper::drawText(toString((int)STEPS2TIME(drawnDuration)),
576 0 : Position(x + xOffset, h - h9),
577 : 0, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
578 : }
579 : }
580 : // proceed to next link
581 0 : h -= h20;
582 : }
583 :
584 : // draw phase index / name (no names for intermediate)
585 0 : std::string name = phaseNames ? pi->getName() : toString(*ii);
586 0 : if (name != lastName) {
587 0 : const double lastNameWidth = GLHelper::getTextWidth(lastName, fontWidth);
588 0 : if (spaceForName < lastNameWidth) {
589 : // clear space to avoid overdrawn text
590 0 : glColor3d(0, 0, 0);
591 0 : glBegin(GL_QUADS);
592 0 : glVertex2d(x, 1 - fontHeight);
593 0 : glVertex2d(x, 1);
594 0 : glVertex2d(1, 1);
595 0 : glVertex2d(1, 1 - fontHeight);
596 0 : glEnd();
597 : }
598 : spaceForName = a;
599 0 : GLHelper::drawText(name, Position(x, 1 - hTop), 0, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_BOTTOM, fontWidth);
600 : } else {
601 0 : spaceForName += a;
602 : }
603 : lastName = name;
604 : // proceed to next phase
605 : ++pi;
606 : ++ii;
607 : x = x2;
608 : // all further phases are drawn in full
609 : fpo = 0;
610 : }
611 :
612 0 : if (myAmInTrackingMode) {
613 0 : h -= h75;
614 0 : if (myDetectorMode->getCheck()) {
615 0 : glColor3d(0.7, 0.7, 1.0);
616 0 : drawAdditionalStates(caller, myDetectorStates, myDetectorDurations, myFirstDetOffset, myFirstDet2Show, h,
617 : panelWidth, (double)leftOffset, barWidth, stateHeight, h20, h);
618 0 : h -= h35;
619 : }
620 0 : if (myConditionMode->getCheck()) {
621 0 : glColor3d(0.9, 0.6, 0.9);
622 0 : drawAdditionalStates(caller, myConditionStates, myConditionDurations, myFirstCondOffset, myFirstCond2Show, h,
623 : panelWidth, (double)leftOffset, barWidth, stateHeight, h20, h);
624 : }
625 : }
626 : // allow value addition
627 0 : myLock.unlock();
628 :
629 0 : if (myPhases.size() != 0) {
630 0 : const double timeRange = STEPS2TIME(myLastTime - myBeginTime);
631 : SUMOTime tickDist = TIME2STEPS(10);
632 : // patch distances - hack
633 0 : double t = myBeginOffset != nullptr ? myBeginOffset->getValue() : timeRange;
634 0 : while (t > barWidth / 4.) {
635 : tickDist += TIME2STEPS(10);
636 0 : t -= barWidth / 4.;
637 : }
638 : // draw time information
639 : //h = (double)(myTLLogic->getLinks().size() * 20 + 12);
640 0 : double glh = 1. - (double)myTLLogic->getLinks().size() * h20 - hTop;
641 : // current begin time
642 : // time ticks
643 0 : SUMOTime currTime = myFirstTime2Show;
644 : double glpos = 31. / panelWidth;
645 0 : const double ticSize = 4. / panelHeight;
646 0 : if (leftOffset > 0) {
647 0 : const double a = STEPS2TIME(leftOffset) * barWidth / timeRange;
648 0 : glpos += a / panelWidth;
649 0 : currTime += leftOffset;
650 0 : } else if (myFirstPhaseOffset > 0) {
651 0 : const double a = STEPS2TIME(-myFirstPhaseOffset) * barWidth / timeRange;
652 0 : glpos += a / panelWidth;
653 0 : currTime -= myFirstPhaseOffset;
654 : }
655 0 : int ticShift = myFirstPhase2Show;
656 0 : const bool mmSS = myTimeMode->getCurrentItem() == 1;
657 0 : const bool cycleTime = myTimeMode->getCurrentItem() == 2;
658 : SUMOTime lastTimeInCycle = -1;
659 : lastName = "";
660 0 : pi = myPhases.begin() + myFirstPhase2Show;
661 0 : for (DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show; pd != myDurations.end(); ++pd) {
662 0 : const SUMOTime timeInCycle = myTimeInCycle[pd - myDurations.begin()];
663 : // draw times at different heights
664 0 : ticShift = (ticShift % 3) + 1;
665 : const std::string timeStr = (mmSS
666 0 : ? StringUtils::padFront(toString((currTime % 3600000) / 60000), 2, '0') + ":"
667 0 : + StringUtils::padFront(toString((currTime % 60000) / 1000), 2, '0')
668 0 : : toString((int)STEPS2TIME(cycleTime ? timeInCycle : currTime)));
669 0 : const double w = 10 * (double)timeStr.size() / panelWidth;
670 0 : glTranslated(glpos - w / 2., glh - h20 * ticShift, 0);
671 0 : GLHelper::drawText(timeStr, Position(0, 0), 1, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
672 0 : glTranslated(-glpos + w / 2., -glh + h20 * ticShift, 0);
673 :
674 : // draw tic
675 0 : glColor3d(1, 1, 1);
676 0 : glBegin(GL_LINES);
677 0 : glVertex2d(glpos, glh);
678 0 : glVertex2d(glpos, glh - ticSize * ticShift);
679 0 : glEnd();
680 :
681 : // draw vertical lines for names, detectors and conditions on each phase switch
682 0 : if (myAmInTrackingMode) {
683 : double hStart = 1;
684 0 : if (!phaseNames || (pi->getName() != lastName)) {
685 0 : glColor3d(0.4, 0.4, 0.4);
686 0 : glBegin(GL_LINES);
687 0 : glVertex2d(glpos, hStart);
688 : hStart -= h20;
689 0 : glVertex2d(glpos, hStart);
690 0 : glEnd();
691 : }
692 : lastName = pi->getName();
693 :
694 0 : hStart = glh - h60;
695 0 : if (myDetectorMode->getCheck() && glpos >= w30) {
696 0 : glColor3d(0.4, 0.4, 0.4);
697 0 : glBegin(GL_LINES);
698 0 : glVertex2d(glpos, hStart);
699 0 : hStart -= (double)myDetectorNames.size() * h20;
700 0 : glVertex2d(glpos, hStart);
701 0 : glEnd();
702 0 : hStart -= h35;
703 : }
704 0 : if (myConditionMode->getCheck() && glpos >= w30) {
705 0 : glColor3d(0.4, 0.4, 0.4);
706 0 : glBegin(GL_LINES);
707 0 : glVertex2d(glpos, hStart);
708 0 : glVertex2d(glpos, hStart - (double)myConditionNames.size() * h20);
709 0 : glEnd();
710 : }
711 : }
712 :
713 : // draw vertical line for cycle reset
714 0 : if (timeInCycle == 0 || timeInCycle < lastTimeInCycle) {
715 0 : const double cycle0pos = glpos - STEPS2TIME(timeInCycle) * barWidth / timeRange / panelWidth;
716 0 : if (cycle0pos >= 31 / panelWidth) {
717 0 : glColor3d(0.6, 0.6, 0.6);
718 0 : glBegin(GL_LINES);
719 0 : glVertex2d(cycle0pos, 1);
720 0 : glVertex2d(cycle0pos, glh);
721 0 : glEnd();
722 0 : glColor3d(1, 1, 1);
723 : }
724 : }
725 :
726 : lastTimeInCycle = timeInCycle;
727 0 : tickDist = *pd;
728 0 : const double a = STEPS2TIME(tickDist) * barWidth / timeRange;
729 0 : glpos += a / panelWidth;
730 0 : currTime += tickDist;
731 : ++pi;
732 : }
733 :
734 : // draw bottom time bar with fixed spacing
735 0 : if (myAmInTrackingMode && (myDetectorMode->getCheck() || myConditionMode->getCheck()) && glpos >= w30) {
736 0 : glColor3d(1, 1, 1);
737 : tickDist = TIME2STEPS(10);
738 : // patch distances - hack
739 0 : t = myBeginOffset != nullptr ? myBeginOffset->getValue() : STEPS2TIME(myLastTime - myBeginTime);
740 0 : while (t > barWidth / 4.) {
741 0 : tickDist += TIME2STEPS(10);
742 0 : t -= barWidth / 4.;
743 : }
744 0 : glh = 1. - (double)myLinkNames.size() * h20 - h80;
745 0 : glh -= h20 * (double)(myDetectorMode->getCheck() ? myDetectorNames.size() : myConditionNames.size());
746 0 : currTime = myFirstTime2Show;
747 : int pos = 31;
748 : glpos = (double) pos / panelWidth;
749 0 : if (leftOffset > 0) {
750 0 : const double a = STEPS2TIME(leftOffset) * barWidth / timeRange;
751 0 : pos += (int)a;
752 0 : glpos += a / panelWidth;
753 0 : currTime += leftOffset;
754 0 : } else if (myFirstPhaseOffset > 0) {
755 0 : const double a = -STEPS2TIME(myBeginTime % tickDist) * barWidth / timeRange;
756 0 : pos += (int)a;
757 0 : glpos += a / panelWidth;
758 0 : currTime = myBeginTime - (myBeginTime % tickDist);
759 : }
760 0 : while (pos < panelWidth + 50.) {
761 : const std::string timeStr = (mmSS
762 0 : ? StringUtils::padFront(toString((currTime % 3600000) / 60000), 2, '0') + ":"
763 0 : + StringUtils::padFront(toString((currTime % 60000) / 1000), 2, '0')
764 0 : : toString((int)STEPS2TIME(cycleTime ? findTimeInCycle(currTime) : currTime)));
765 0 : const double w = 10. * (double)timeStr.size() / panelWidth;
766 0 : glTranslated(glpos - w / 2., glh - h20, 0);
767 0 : GLHelper::drawText(timeStr, Position(0, 0), 1, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
768 0 : glTranslated(-glpos + w / 2., -glh + h20, 0);
769 :
770 0 : glBegin(GL_LINES);
771 0 : glVertex2d(glpos, glh);
772 0 : glVertex2d(glpos, glh - ticSize);
773 0 : glEnd();
774 :
775 0 : const double a = STEPS2TIME(tickDist) * barWidth / STEPS2TIME(myLastTime - myBeginTime);
776 0 : pos += (int) a;
777 0 : glpos += a / panelWidth;
778 0 : currTime += tickDist;
779 : }
780 : }
781 : }
782 : }
783 :
784 :
785 : void
786 0 : GUITLLogicPhasesTrackerWindow::drawNames(const std::vector<std::string>& names, double fontHeight, double fontWidth, double divHeight, double divWidth, double& h, int extraLines) {
787 : int i = 0;
788 0 : for (const std::string& name : names) {
789 : // draw the bar
790 0 : glBegin(GL_LINES);
791 0 : glVertex2d(0, h);
792 0 : glVertex2d(divWidth, h);
793 0 : glEnd();
794 : // draw the name
795 0 : glTranslated(0, h - divHeight, 0);
796 0 : GLHelper::drawText(name, Position(0, 0), 1, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_BOTTOM, fontWidth);
797 0 : glTranslated(0, -h + divHeight, 0);
798 :
799 0 : if (extraLines > 0 && i > 0 && i % extraLines == 0) {
800 0 : glColor3d(0.4, 0.4, 0.4);
801 0 : glBegin(GL_LINES);
802 0 : glVertex2d(divWidth, h);
803 0 : glVertex2d(1.0, h);
804 0 : glEnd();
805 0 : glColor3d(1, 1, 1);
806 : }
807 0 : h -= divHeight;
808 0 : i++;
809 : }
810 0 : h -= divHeight;
811 0 : }
812 :
813 :
814 : void
815 0 : GUITLLogicPhasesTrackerWindow::drawAdditionalStates(GUITLLogicPhasesTrackerPanel& caller,
816 : const AdditionalStatesVector& states,
817 : const DurationsVector& durations, SUMOTime firstOffset, int first2Show, double hStart,
818 : double panelWidth, double leftOffset, double barWidth, double stateHeight, double h20, double& h) {
819 0 : double x = 31. / panelWidth;
820 0 : double ta = leftOffset / panelWidth;
821 0 : ta *= barWidth / ((double)(myLastTime - myBeginTime));
822 0 : x += ta;
823 : auto di = states.begin() + first2Show;
824 : SUMOTime fpo = firstOffset;
825 :
826 0 : double mx = caller.getMousePos().x() / caller.getWidth();
827 0 : double my = 1 - caller.getMousePos().y() / caller.getHeight();
828 0 : std::string tooltip = "";
829 : // start drawing
830 0 : for (auto pd = durations.begin() + first2Show; pd != durations.end(); ++pd) {
831 : // the first phase may be drawn incompletely
832 0 : SUMOTime duration = *pd - fpo;
833 : // compute the height and the width of the phase
834 0 : h = hStart;
835 0 : double a = (double) duration / panelWidth;
836 0 : a *= barWidth / ((double)(myLastTime - myBeginTime));
837 0 : const double x2 = x + a;
838 0 : const bool tooltipX = x < mx && mx < x2;
839 : //std::cout << SIMTIME << " detStates=" << toString(*di) << "\n";
840 : // go through the detectors
841 0 : for (double j : *di) {
842 0 : if (j != 0) {
843 : // draw a thick block
844 0 : glBegin(GL_QUADS);
845 0 : glVertex2d(x, h - stateHeight);
846 0 : glVertex2d(x, h);
847 0 : glVertex2d(x2, h);
848 0 : glVertex2d(x2, h - stateHeight);
849 0 : glEnd();
850 0 : if (tooltipX) {
851 0 : const bool tooltipY = (h - stateHeight) < my && my < h;
852 : if (tooltipY) {
853 0 : tooltip = toString((int)j);
854 : }
855 : }
856 : }
857 : // proceed to next link
858 0 : h -= h20;
859 : }
860 : // proceed to next phase
861 : ++di;
862 : x = x2;
863 : // all further phases are drawn in full
864 : fpo = 0;
865 : }
866 0 : if (tooltip != "") {
867 : // delay tool tip drawing until all bars are drawn to prevent overwriting
868 0 : GLHelper::drawText(tooltip, Position(mx, my), 0, h20, RGBColor::YELLOW, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, 20 / caller.getWidth());
869 : }
870 0 : }
871 :
872 : SUMOTime
873 0 : GUITLLogicPhasesTrackerWindow::findTimeInCycle(SUMOTime t) {
874 : // find latest cycle reset before t
875 0 : int i = (int)myPhases.size() - 1;
876 0 : SUMOTime lookBack = myLastTime - t - myDurations.back();
877 : //std::cout << SIMTIME << " findTimeInCycle t=" << STEPS2TIME(t)
878 : // << " last=" << STEPS2TIME(myLastTime)
879 : // << " lastDur=" << STEPS2TIME(myDurations.back())
880 : // << " lookBack=" << STEPS2TIME(lookBack)
881 : // << " i0=" << i;
882 : // look backwards through the phases until to the first cycle crossing before t
883 0 : while (lookBack > 0 && i > 1) {
884 0 : i--;
885 0 : lookBack -= myDurations[i];
886 : }
887 0 : SUMOTime timeInCycle = myTimeInCycle[i < 0 ? 0 : i];
888 : //std::cout << " iF=" << i << " lookBack2=" << STEPS2TIME(lookBack) << " tic=" << STEPS2TIME(timeInCycle) << "\n";
889 0 : if (lookBack <= 0) {
890 0 : return timeInCycle - lookBack;
891 : }
892 0 : return myTLLogic->mapTimeInCycle(t);
893 : }
894 :
895 : void
896 0 : GUITLLogicPhasesTrackerWindow::addValue(std::pair<SUMOTime, MSPhaseDefinition> def) {
897 : // do not draw while adding
898 0 : myLock.lock();
899 : // set the first time if not set before
900 0 : if (myPhases.size() == 0) {
901 0 : myBeginTime = def.first;
902 : }
903 : // append or set the phase
904 0 : if (myPhases.size() == 0 || myPhases.back() != def.second) {
905 0 : myPhases.push_back(def.second);
906 0 : myDurations.push_back(DELTA_T);
907 0 : myTimeInCycle.push_back(myTLLogic->mapTimeInCycle(def.first - DELTA_T));
908 0 : myPhaseIndex.push_back(myTLLogic->getCurrentPhaseIndex());
909 : } else {
910 0 : myDurations.back() += DELTA_T;
911 : }
912 : // updated detector states
913 : std::vector<double> detectorStates;
914 0 : for (auto item : myTLLogic->getDetectorStates()) {
915 0 : detectorStates.push_back(item.second);
916 : }
917 0 : if (myDetectorStates.size() == 0 || myDetectorStates.back() != detectorStates) {
918 0 : myDetectorStates.push_back(detectorStates);
919 0 : myDetectorDurations.push_back(DELTA_T);
920 : } else {
921 0 : myDetectorDurations.back() += DELTA_T;
922 : }
923 : // updated condition states
924 : std::vector<double> conditionStates;
925 0 : for (auto item : myTLLogic->getConditions()) {
926 0 : conditionStates.push_back(item.second);
927 : }
928 0 : if (myConditionStates.size() == 0 || myConditionStates.back() != conditionStates) {
929 0 : myConditionStates.push_back(conditionStates);
930 0 : myConditionDurations.push_back(DELTA_T);
931 : } else {
932 0 : myConditionDurations.back() += DELTA_T;
933 : }
934 : // set the last time a phase was added at
935 0 : myLastTime = def.first;
936 : // allow drawing
937 0 : myLock.unlock();
938 0 : }
939 :
940 :
941 : long
942 0 : GUITLLogicPhasesTrackerWindow::onConfigure(FXObject* sender, FXSelector sel, void* ptr) {
943 0 : myPanel->onConfigure(sender, sel, ptr);
944 0 : return FXMainWindow::onConfigure(sender, sel, ptr);
945 : }
946 :
947 :
948 : long
949 0 : GUITLLogicPhasesTrackerWindow::onPaint(FXObject* sender, FXSelector sel, void* ptr) {
950 0 : myPanel->onPaint(sender, sel, ptr);
951 0 : return FXMainWindow::onPaint(sender, sel, ptr);
952 : }
953 :
954 :
955 : long
956 0 : GUITLLogicPhasesTrackerWindow::onSimStep(FXObject* sender, FXSelector, void*) {
957 0 : if (sender == myDetectorMode || sender == myConditionMode) {
958 0 : resize(getWidth(), computeHeight());
959 : }
960 0 : update();
961 0 : return 1;
962 : }
963 :
964 :
965 : void
966 0 : GUITLLogicPhasesTrackerWindow::setBeginTime(SUMOTime time) {
967 0 : myBeginTime = time;
968 0 : }
969 :
970 :
971 : void
972 0 : GUITLLogicPhasesTrackerWindow::saveSettings() {
973 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "x", getX());
974 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "y", getY());
975 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "width", getWidth());
976 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "timeRange", (int)myBeginOffset->getValue());
977 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "timeMode", myTimeMode->getCurrentItem());
978 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "greenMode", (myGreenMode->getCurrentItem()));
979 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "indexMode", (int)(myIndexMode->getCheck()));
980 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "detectorMode", (int)(myDetectorMode->getCheck()));
981 0 : getApp()->reg().writeIntEntry("TL_TRACKER", "conditionMode", (int)(myConditionMode->getCheck()));
982 0 : }
983 :
984 :
985 : void
986 0 : GUITLLogicPhasesTrackerWindow::loadSettings() {
987 : // ensure window is visible after switching screen resolutions
988 : const FXint minSize = 400;
989 : const FXint minTitlebarHeight = 20;
990 0 : setX(MAX2(0, MIN2(getApp()->reg().readIntEntry("TL_TRACKER", "x", 150),
991 : getApp()->getRootWindow()->getWidth() - minSize)));
992 0 : if (myLastY == -1) {
993 0 : myLastY = MAX2(minTitlebarHeight,
994 : MIN2(getApp()->reg().readIntEntry("TL_TRACKER", "y", 150),
995 : getApp()->getRootWindow()->getHeight() - minSize));
996 : } else {
997 0 : myLastY += getHeight() + 20;
998 : }
999 0 : setY(myLastY);
1000 0 : setWidth(MAX2(getApp()->reg().readIntEntry("TL_TRACKER", "width", 700), minSize));
1001 0 : myBeginOffset->setValue(getApp()->reg().readIntEntry("TL_TRACKER", "timeRange", (int)myBeginOffset->getValue()));
1002 0 : myTimeMode->setCurrentItem(getApp()->reg().readIntEntry("TL_TRACKER", "timeMode", myTimeMode->getCurrentItem()));
1003 0 : myGreenMode->setCurrentItem(getApp()->reg().readIntEntry("TL_TRACKER", "greenMode", myGreenMode->getCurrentItem()));
1004 0 : myIndexMode->setCheck((FXbool)getApp()->reg().readIntEntry("TL_TRACKER", "indexMode", (int)(myIndexMode->getCheck())));
1005 0 : myDetectorMode->setCheck((FXbool)getApp()->reg().readIntEntry("TL_TRACKER", "detectorMode", (int)(myDetectorMode->getCheck())));
1006 0 : myConditionMode->setCheck((FXbool)getApp()->reg().readIntEntry("TL_TRACKER", "conditionMode", (int)(myConditionMode->getCheck())));
1007 0 : }
1008 :
1009 : /****************************************************************************/
|