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