Path: blob/main/src/utils/gui/div/GUIParameterTableWindow.cpp
169684 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2002-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GUIParameterTableWindow.cpp14/// @author Daniel Krajzewicz15/// @author Laura Bieker16/// @author Michael Behrisch17/// @author Jakob Erdmann18/// @author Mirko Barthauer19/// @date Sept 200220///21// The window that holds the table of an object's parameter22/****************************************************************************/23#include <config.h>2425#include <string>26#include <utils/foxtools/fxheader.h>27#include "GUIParameterTableWindow.h"28#include <utils/gui/globjects/GUIGlObject.h>29#include <utils/common/MsgHandler.h>30#include <utils/common/ToString.h>31#include <utils/common/Parameterised.h>32#include <utils/gui/div/GUIParam_PopupMenu.h>33#include <utils/gui/windows/GUIAppEnum.h>34#include <utils/gui/windows/GUIMainWindow.h>35#include <utils/gui/images/GUIIconSubSys.h>36#include <utils/gui/tracker/GUIParameterTracker.h>37#include <utils/gui/div/GUIParameterTableItem.h>38#include <utils/gui/div/GUIDesigns.h>394041// ===========================================================================42// FOX callback mapping43// ===========================================================================44FXDEFMAP(GUIParameterTableWindow) GUIParameterTableWindowMap[] = {45FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUIParameterTableWindow::onSimStep),46FXMAPFUNC(SEL_SELECTED, MID_TABLE, GUIParameterTableWindow::onTableSelected),47FXMAPFUNC(SEL_DESELECTED, MID_TABLE, GUIParameterTableWindow::onTableDeselected),48FXMAPFUNC(SEL_RIGHTBUTTONPRESS, MID_TABLE, GUIParameterTableWindow::onRightButtonPress),49FXMAPFUNC(SEL_LEFTBUTTONPRESS, MID_TABLE, GUIParameterTableWindow::onLeftBtnPress),50};5152FXIMPLEMENT(GUIParameterTableWindow, FXMainWindow, GUIParameterTableWindowMap, ARRAYNUMBER(GUIParameterTableWindowMap))5354// ===========================================================================55// static value definitions56// ===========================================================================5758FXMutex GUIParameterTableWindow::myGlobalContainerLock;59std::vector<GUIParameterTableWindow*> GUIParameterTableWindow::myContainer;6061// ===========================================================================62// method definitions63// ===========================================================================64#ifdef _MSC_VER65#pragma warning(push)66#pragma warning(disable: 4355) // mask warning about "this" in initializers67#endif68GUIParameterTableWindow::GUIParameterTableWindow(GUIMainWindow& app, GUIGlObject& o, const std::string& title) :69FXMainWindow(app.getApp(), ((title == "" ? o.getFullName() : title) + " parameter").c_str(), nullptr, nullptr, DECOR_ALL, 20, 40, 200, 500),70GUIPersistentWindowPos(this, "DIALOG_PARAMETERS", false, 20, 40),71myObject(&o),72myApplication(&app),73myTrackerY(50),74myCurrentPos(0) {75myTable = new FXTable(this, this, MID_TABLE, TABLE_COL_SIZABLE | TABLE_ROW_SIZABLE | LAYOUT_FILL_X | LAYOUT_FILL_Y);76myTable->setTableSize(1, 3);77myTable->setVisibleColumns(3);78myTable->setBackColor(GUIDesignBackgroundColorWhite);79myTable->setColumnText(0, TL("Name"));80myTable->setColumnText(1, TL("Value"));81myTable->setColumnText(2, TL("Dynamic"));82myTable->getRowHeader()->setWidth(0);83FXHeader* header = myTable->getColumnHeader();84header->setItemJustify(0, JUSTIFY_CENTER_X);85header->setItemSize(0, 240);86header->setItemJustify(1, JUSTIFY_CENTER_X);87header->setItemSize(1, 120);88header->setItemJustify(2, JUSTIFY_CENTER_X);89header->setItemSize(2, 60);90setIcon(GUIIconSubSys::getIcon(GUIIcon::APP_TABLE));91myLock.lock();92myObject->addParameterTable(this);93myLock.unlock();94FXMutexLock locker(myGlobalContainerLock);95myContainer.push_back(this);96// Table cannot be editable97myTable->setEditable(FALSE);98loadWindowPos();99}100#ifdef _MSC_VER101#pragma warning(pop)102#endif103104GUIParameterTableWindow::~GUIParameterTableWindow() {105myApplication->removeChild(this);106myLock.lock();107for (std::vector<GUIParameterTableItemInterface*>::iterator i = myItems.begin(); i != myItems.end(); ++i) {108delete (*i);109}110if (myObject != nullptr) {111myObject->removeParameterTable(this);112}113myLock.unlock();114FXMutexLock locker(myGlobalContainerLock);115std::vector<GUIParameterTableWindow*>::iterator i = std::find(myContainer.begin(), myContainer.end(), this);116if (i != myContainer.end()) {117myContainer.erase(i);118}119}120121122void123GUIParameterTableWindow::removeObject(GUIGlObject* /*i*/) {124FXMutexLock locker(myLock);125myObject = nullptr;126}127128129long130GUIParameterTableWindow::onSimStep(FXObject*, FXSelector, void*) {131// table values are updated in GUINet::guiSimulationStep()132updateTable();133update();134return 1;135}136137138long139GUIParameterTableWindow::onTableSelected(FXObject*, FXSelector, void*) {140return 1;141}142143144long145GUIParameterTableWindow::onTableDeselected(FXObject*, FXSelector, void*) {146return 1;147}148149long150GUIParameterTableWindow::onLeftBtnPress(FXObject* sender, FXSelector sel, void* eventData) {151FXEvent* e = (FXEvent*) eventData;152int row = myTable->rowAtY(e->win_y);153int col = myTable->colAtX(e->win_x);154if (col == 2 && row >= 0 && row < (int)myItems.size()) {155GUIParameterTableItemInterface* i = myItems[row];156if (i->dynamic() && i->getdoubleSourceCopy() != nullptr) {157// open tracker directly158const std::string trackerName = i->getName() + " of " + myObject->getFullName();159TrackerValueDesc* newTracked = new TrackerValueDesc(i->getName(), RGBColor::BLACK, myApplication->getCurrentSimTime(), myApplication->getTrackerInterval());160if (!GUIParameterTracker::addTrackedMultiplot(*myObject, i->getdoubleSourceCopy(), newTracked)) {161GUIParameterTracker* tr = new GUIParameterTracker(*myApplication, trackerName);162tr->addTracked(*myObject, i->getdoubleSourceCopy(), newTracked);163tr->setX(getX() + getWidth() + 10);164tr->setY(myTrackerY);165tr->create();166tr->show();167myTrackerY = (myTrackerY + tr->getHeight() + 20) % getApp()->getRootWindow()->getHeight();168}169}170}171return FXMainWindow::onLeftBtnPress(sender, sel, eventData);172}173174long175GUIParameterTableWindow::onRightButtonPress(FXObject* /*sender*/, FXSelector /*sel*/, void* eventData) {176// check which value entry was pressed177FXEvent* e = (FXEvent*) eventData;178int row = myTable->rowAtY(e->win_y);179if (row == -1 || row >= (int)(myItems.size())) {180return 1;181}182GUIParameterTableItemInterface* i = myItems[row];183if (!i->dynamic()) {184return 1;185}186if (myObject == nullptr) {187return 1;188}189190ValueSource<double>* doubleSource = i->getdoubleSourceCopy();191if (doubleSource != nullptr) {192GUIParam_PopupMenuInterface* p = new GUIParam_PopupMenuInterface(*myApplication, *this, *myObject, i->getName(), doubleSource);193GUIDesigns::buildFXMenuCommand(p, TL("Open in new Tracker"), nullptr, p, MID_OPENTRACKER);194// set geometry195p->setX(static_cast<FXEvent*>(eventData)->root_x);196p->setY(static_cast<FXEvent*>(eventData)->root_y);197p->create();198// show199p->show();200}201return 1;202}203204205void206GUIParameterTableWindow::mkItem(const char* name, bool dynamic, std::string value) {207myTable->insertRows((int)myItems.size() + 1);208GUIParameterTableItemInterface* i = new GUIParameterTableItem<std::string>(myTable, myCurrentPos++, name, dynamic, value);209myItems.push_back(i);210}211212213void214GUIParameterTableWindow::mkItem(const char* name, bool dynamic, double value) {215myTable->insertRows((int)myItems.size() + 1);216GUIParameterTableItemInterface* i = new GUIParameterTableItem<double>(myTable, myCurrentPos++, name, dynamic, value);217myItems.push_back(i);218}219220221void222GUIParameterTableWindow::mkItem(const char* name, bool dynamic, unsigned value) {223myTable->insertRows((int)myItems.size() + 1);224GUIParameterTableItemInterface* i = new GUIParameterTableItem<unsigned>(myTable, myCurrentPos++, name, dynamic, value);225myItems.push_back(i);226}227228229void230GUIParameterTableWindow::mkItem(const char* name, bool dynamic, int value) {231myTable->insertRows((int)myItems.size() + 1);232GUIParameterTableItemInterface* i = new GUIParameterTableItem<int>(myTable, myCurrentPos++, name, dynamic, value);233myItems.push_back(i);234}235236237void238GUIParameterTableWindow::mkItem(const char* name, bool dynamic, long long int value) {239myTable->insertRows((int)myItems.size() + 1);240GUIParameterTableItemInterface* i = new GUIParameterTableItem<long long int>(myTable, myCurrentPos++, name, dynamic, value);241myItems.push_back(i);242}243244245void246GUIParameterTableWindow::updateTable() {247FXMutexLock locker(myLock);248if (myObject == nullptr) {249return;250}251for (GUIParameterTableItemInterface* const item : myItems) {252item->update();253}254}255256257void258GUIParameterTableWindow::closeBuilding(const Parameterised* p) {259// add generic parameters if available260if (p == nullptr) {261p = dynamic_cast<const Parameterised*>(myObject);262}263if (p != nullptr) {264const Parameterised::Map& map = p->getParametersMap();265for (Parameterised::Map::const_iterator it = map.begin(); it != map.end(); ++it) {266mkItem(("param:" + it->first).c_str(), false, it->second);267}268}269const int rows = (int)myItems.size() + 1;270int h = rows * 20 + 40;271// adjust size in case there are higher (multi-line) rows272for (int i = 0; i < (int)myItems.size(); i++) {273h += MAX2(0, myTable->getRowHeight(i) - 20);274}275setHeight(h);276myTable->fitColumnsToContents(1);277setWidth(myTable->getContentWidth() + 40);278myTable->setVisibleRows(rows);279myApplication->addChild(this);280create();281show();282}283284285void286GUIParameterTableWindow::checkFont(const std::string& text) {287bool missingChar = false;288FXString fxs(text.c_str());289for (FXint i = 0; i < fxs.length(); i = fxs.inc(i)) {290FXwchar wc = fxs.wc(i);291if (myTable->getFont()->hasChar(wc) != TRUE) {292missingChar = true;293break;294}295//std::cout << i << ": " << wc << " char:" << (char)(wc) << " has: " << (myTable->getFont()->hasChar(wc) == TRUE) << "\n";296}297if (missingChar) {298myTable->setFont(myApplication->getFallbackFont());299}300}301302303int304GUIParameterTableWindow::numParams(const GUIGlObject* obj) {305const Parameterised* p = dynamic_cast<const Parameterised*>(obj);306return p != nullptr ? (int)p->getParametersMap().size() : 0;307}308309310/****************************************************************************/311312313