Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2002-2025 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 GUIParameterTableWindow.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Laura Bieker
17 : /// @author Michael Behrisch
18 : /// @author Jakob Erdmann
19 : /// @author Mirko Barthauer
20 : /// @date Sept 2002
21 : ///
22 : // The window that holds the table of an object's parameter
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #include <string>
27 : #include <utils/foxtools/fxheader.h>
28 : #include "GUIParameterTableWindow.h"
29 : #include <utils/gui/globjects/GUIGlObject.h>
30 : #include <utils/common/MsgHandler.h>
31 : #include <utils/common/ToString.h>
32 : #include <utils/common/Parameterised.h>
33 : #include <utils/gui/div/GUIParam_PopupMenu.h>
34 : #include <utils/gui/windows/GUIAppEnum.h>
35 : #include <utils/gui/windows/GUIMainWindow.h>
36 : #include <utils/gui/images/GUIIconSubSys.h>
37 : #include <utils/gui/tracker/GUIParameterTracker.h>
38 : #include <utils/gui/div/GUIParameterTableItem.h>
39 : #include <utils/gui/div/GUIDesigns.h>
40 :
41 :
42 : // ===========================================================================
43 : // FOX callback mapping
44 : // ===========================================================================
45 : FXDEFMAP(GUIParameterTableWindow) GUIParameterTableWindowMap[] = {
46 : FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUIParameterTableWindow::onSimStep),
47 : FXMAPFUNC(SEL_SELECTED, MID_TABLE, GUIParameterTableWindow::onTableSelected),
48 : FXMAPFUNC(SEL_DESELECTED, MID_TABLE, GUIParameterTableWindow::onTableDeselected),
49 : FXMAPFUNC(SEL_RIGHTBUTTONPRESS, MID_TABLE, GUIParameterTableWindow::onRightButtonPress),
50 : FXMAPFUNC(SEL_LEFTBUTTONPRESS, MID_TABLE, GUIParameterTableWindow::onLeftBtnPress),
51 : };
52 :
53 0 : FXIMPLEMENT(GUIParameterTableWindow, FXMainWindow, GUIParameterTableWindowMap, ARRAYNUMBER(GUIParameterTableWindowMap))
54 :
55 : // ===========================================================================
56 : // static value definitions
57 : // ===========================================================================
58 :
59 : FXMutex GUIParameterTableWindow::myGlobalContainerLock;
60 : std::vector<GUIParameterTableWindow*> GUIParameterTableWindow::myContainer;
61 :
62 : // ===========================================================================
63 : // method definitions
64 : // ===========================================================================
65 : #ifdef _MSC_VER
66 : #pragma warning(push)
67 : #pragma warning(disable: 4355) // mask warning about "this" in initializers
68 : #endif
69 0 : GUIParameterTableWindow::GUIParameterTableWindow(GUIMainWindow& app, GUIGlObject& o, const std::string& title) :
70 0 : FXMainWindow(app.getApp(), ((title == "" ? o.getFullName() : title) + " Parameter").c_str(), nullptr, nullptr, DECOR_ALL, 20, 40, 200, 500),
71 : GUIPersistentWindowPos(this, "DIALOG_PARAMETERS", false, 20, 40),
72 0 : myObject(&o),
73 0 : myApplication(&app),
74 0 : myTrackerY(50),
75 0 : myCurrentPos(0) {
76 0 : myTable = new FXTable(this, this, MID_TABLE, TABLE_COL_SIZABLE | TABLE_ROW_SIZABLE | LAYOUT_FILL_X | LAYOUT_FILL_Y);
77 0 : myTable->setTableSize(1, 3);
78 0 : myTable->setVisibleColumns(3);
79 0 : myTable->setBackColor(FXRGB(255, 255, 255));
80 0 : myTable->setColumnText(0, TL("Name"));
81 0 : myTable->setColumnText(1, TL("Value"));
82 0 : myTable->setColumnText(2, TL("Dynamic"));
83 0 : myTable->getRowHeader()->setWidth(0);
84 0 : FXHeader* header = myTable->getColumnHeader();
85 0 : header->setItemJustify(0, JUSTIFY_CENTER_X);
86 0 : header->setItemSize(0, 240);
87 0 : header->setItemJustify(1, JUSTIFY_CENTER_X);
88 0 : header->setItemSize(1, 120);
89 0 : header->setItemJustify(2, JUSTIFY_CENTER_X);
90 0 : header->setItemSize(2, 60);
91 0 : setIcon(GUIIconSubSys::getIcon(GUIIcon::APP_TABLE));
92 0 : myLock.lock();
93 0 : myObject->addParameterTable(this);
94 0 : myLock.unlock();
95 : FXMutexLock locker(myGlobalContainerLock);
96 0 : myContainer.push_back(this);
97 : // Table cannot be editable
98 0 : myTable->setEditable(FALSE);
99 0 : loadWindowPos();
100 0 : }
101 : #ifdef _MSC_VER
102 : #pragma warning(pop)
103 : #endif
104 :
105 0 : GUIParameterTableWindow::~GUIParameterTableWindow() {
106 0 : myApplication->removeChild(this);
107 0 : myLock.lock();
108 0 : for (std::vector<GUIParameterTableItemInterface*>::iterator i = myItems.begin(); i != myItems.end(); ++i) {
109 0 : delete (*i);
110 : }
111 0 : if (myObject != nullptr) {
112 0 : myObject->removeParameterTable(this);
113 : }
114 0 : myLock.unlock();
115 : FXMutexLock locker(myGlobalContainerLock);
116 0 : std::vector<GUIParameterTableWindow*>::iterator i = std::find(myContainer.begin(), myContainer.end(), this);
117 0 : if (i != myContainer.end()) {
118 : myContainer.erase(i);
119 : }
120 0 : }
121 :
122 :
123 : void
124 0 : GUIParameterTableWindow::removeObject(GUIGlObject* /*i*/) {
125 0 : FXMutexLock locker(myLock);
126 0 : myObject = nullptr;
127 0 : }
128 :
129 :
130 : long
131 0 : GUIParameterTableWindow::onSimStep(FXObject*, FXSelector, void*) {
132 : // table values are updated in GUINet::guiSimulationStep()
133 0 : updateTable();
134 0 : update();
135 0 : return 1;
136 : }
137 :
138 :
139 : long
140 0 : GUIParameterTableWindow::onTableSelected(FXObject*, FXSelector, void*) {
141 0 : return 1;
142 : }
143 :
144 :
145 : long
146 0 : GUIParameterTableWindow::onTableDeselected(FXObject*, FXSelector, void*) {
147 0 : return 1;
148 : }
149 :
150 : long
151 0 : GUIParameterTableWindow::onLeftBtnPress(FXObject* sender, FXSelector sel, void* eventData) {
152 : FXEvent* e = (FXEvent*) eventData;
153 0 : int row = myTable->rowAtY(e->win_y);
154 0 : int col = myTable->colAtX(e->win_x);
155 0 : if (col == 2 && row >= 0 && row < (int)myItems.size()) {
156 0 : GUIParameterTableItemInterface* i = myItems[row];
157 0 : if (i->dynamic() && i->getdoubleSourceCopy() != nullptr) {
158 : // open tracker directly
159 0 : const std::string trackerName = i->getName() + " from " + myObject->getFullName();
160 0 : TrackerValueDesc* newTracked = new TrackerValueDesc(i->getName(), RGBColor::BLACK, myApplication->getCurrentSimTime(), myApplication->getTrackerInterval());
161 0 : if (!GUIParameterTracker::addTrackedMultiplot(*myObject, i->getdoubleSourceCopy(), newTracked)) {
162 0 : GUIParameterTracker* tr = new GUIParameterTracker(*myApplication, trackerName);
163 0 : tr->addTracked(*myObject, i->getdoubleSourceCopy(), newTracked);
164 0 : tr->setX(getX() + getWidth() + 10);
165 0 : tr->setY(myTrackerY);
166 0 : tr->create();
167 0 : tr->show();
168 0 : myTrackerY = (myTrackerY + tr->getHeight() + 20) % getApp()->getRootWindow()->getHeight();
169 : }
170 : }
171 : }
172 0 : return FXMainWindow::onLeftBtnPress(sender, sel, eventData);
173 : }
174 :
175 : long
176 0 : GUIParameterTableWindow::onRightButtonPress(FXObject* /*sender*/, FXSelector /*sel*/, void* eventData) {
177 : // check which value entry was pressed
178 : FXEvent* e = (FXEvent*) eventData;
179 0 : int row = myTable->rowAtY(e->win_y);
180 0 : if (row == -1 || row >= (int)(myItems.size())) {
181 : return 1;
182 : }
183 0 : GUIParameterTableItemInterface* i = myItems[row];
184 0 : if (!i->dynamic()) {
185 : return 1;
186 : }
187 0 : if (myObject == nullptr) {
188 : return 1;
189 : }
190 :
191 0 : ValueSource<double>* doubleSource = i->getdoubleSourceCopy();
192 0 : if (doubleSource != nullptr) {
193 0 : GUIParam_PopupMenuInterface* p = new GUIParam_PopupMenuInterface(*myApplication, *this, *myObject, i->getName(), doubleSource);
194 0 : GUIDesigns::buildFXMenuCommand(p, TL("Open in new Tracker"), nullptr, p, MID_OPENTRACKER);
195 : // set geometry
196 0 : p->setX(static_cast<FXEvent*>(eventData)->root_x);
197 0 : p->setY(static_cast<FXEvent*>(eventData)->root_y);
198 0 : p->create();
199 : // show
200 0 : p->show();
201 : }
202 : return 1;
203 : }
204 :
205 :
206 : void
207 0 : GUIParameterTableWindow::mkItem(const char* name, bool dynamic, std::string value) {
208 0 : myTable->insertRows((int)myItems.size() + 1);
209 0 : GUIParameterTableItemInterface* i = new GUIParameterTableItem<std::string>(myTable, myCurrentPos++, name, dynamic, value);
210 0 : myItems.push_back(i);
211 0 : }
212 :
213 :
214 : void
215 0 : GUIParameterTableWindow::mkItem(const char* name, bool dynamic, double value) {
216 0 : myTable->insertRows((int)myItems.size() + 1);
217 0 : GUIParameterTableItemInterface* i = new GUIParameterTableItem<double>(myTable, myCurrentPos++, name, dynamic, value);
218 0 : myItems.push_back(i);
219 0 : }
220 :
221 :
222 : void
223 0 : GUIParameterTableWindow::mkItem(const char* name, bool dynamic, unsigned value) {
224 0 : myTable->insertRows((int)myItems.size() + 1);
225 0 : GUIParameterTableItemInterface* i = new GUIParameterTableItem<unsigned>(myTable, myCurrentPos++, name, dynamic, value);
226 0 : myItems.push_back(i);
227 0 : }
228 :
229 :
230 : void
231 0 : GUIParameterTableWindow::mkItem(const char* name, bool dynamic, int value) {
232 0 : myTable->insertRows((int)myItems.size() + 1);
233 0 : GUIParameterTableItemInterface* i = new GUIParameterTableItem<int>(myTable, myCurrentPos++, name, dynamic, value);
234 0 : myItems.push_back(i);
235 0 : }
236 :
237 :
238 : void
239 0 : GUIParameterTableWindow::mkItem(const char* name, bool dynamic, long long int value) {
240 0 : myTable->insertRows((int)myItems.size() + 1);
241 0 : GUIParameterTableItemInterface* i = new GUIParameterTableItem<long long int>(myTable, myCurrentPos++, name, dynamic, value);
242 0 : myItems.push_back(i);
243 0 : }
244 :
245 :
246 : void
247 0 : GUIParameterTableWindow::updateTable() {
248 0 : FXMutexLock locker(myLock);
249 0 : if (myObject == nullptr) {
250 : return;
251 : }
252 0 : for (GUIParameterTableItemInterface* const item : myItems) {
253 0 : item->update();
254 : }
255 : }
256 :
257 :
258 : void
259 0 : GUIParameterTableWindow::closeBuilding(const Parameterised* p) {
260 : // add generic parameters if available
261 0 : if (p == nullptr) {
262 0 : p = dynamic_cast<const Parameterised*>(myObject);
263 : }
264 0 : if (p != nullptr) {
265 0 : const Parameterised::Map& map = p->getParametersMap();
266 0 : for (Parameterised::Map::const_iterator it = map.begin(); it != map.end(); ++it) {
267 0 : mkItem(("param:" + it->first).c_str(), false, it->second);
268 : }
269 : }
270 0 : const int rows = (int)myItems.size() + 1;
271 0 : int h = rows * 20 + 40;
272 : // adjust size in case there are higher (multi-line) rows
273 0 : for (int i = 0; i < (int)myItems.size(); i++) {
274 0 : h += MAX2(0, myTable->getRowHeight(i) - 20);
275 : }
276 0 : setHeight(h);
277 0 : myTable->fitColumnsToContents(1);
278 0 : setWidth(myTable->getContentWidth() + 40);
279 0 : myTable->setVisibleRows(rows);
280 0 : myApplication->addChild(this);
281 0 : create();
282 0 : show();
283 0 : }
284 :
285 :
286 : void
287 0 : GUIParameterTableWindow::checkFont(const std::string& text) {
288 : bool missingChar = false;
289 0 : FXString fxs(text.c_str());
290 0 : for (FXint i = 0; i < fxs.length(); i = fxs.inc(i)) {
291 0 : FXwchar wc = fxs.wc(i);
292 0 : if (myTable->getFont()->hasChar(wc) != TRUE) {
293 : missingChar = true;
294 : break;
295 : }
296 : //std::cout << i << ": " << wc << " char:" << (char)(wc) << " has: " << (myTable->getFont()->hasChar(wc) == TRUE) << "\n";
297 : }
298 0 : if (missingChar) {
299 0 : myTable->setFont(myApplication->getFallbackFont());
300 : }
301 0 : }
302 :
303 :
304 : int
305 0 : GUIParameterTableWindow::numParams(const GUIGlObject* obj) {
306 0 : const Parameterised* p = dynamic_cast<const Parameterised*>(obj);
307 0 : return p != nullptr ? (int)p->getParametersMap().size() : 0;
308 : }
309 :
310 :
311 : /****************************************************************************/
|