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 MFXDecalsTable.cpp
15 : /// @author Pablo Alvarez Lopez
16 : /// @date Feb 2023
17 : ///
18 : // Table used for show and edit decal values
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include "MFXDecalsTable.h"
23 :
24 : #include <netedit/GNEViewNet.h>
25 : #include <netedit/GNEViewParent.h>
26 : #include <netedit/GNEApplicationWindow.h>
27 : #include <utils/gui/div/GUIDesigns.h>
28 : #include <utils/gui/images/GUIIconSubSys.h>
29 : #include <utils/gui/windows/GUIAppEnum.h>
30 : #include <utils/gui/windows/GUIDialog_ViewSettings.h>
31 :
32 :
33 : #define EXTRAMARGIN 4
34 :
35 : #define MAXROWS 100
36 :
37 : // ===========================================================================
38 : // FOX callback mapping
39 : // ===========================================================================
40 :
41 : FXDEFMAP(MFXDecalsTable) MFXDecalsTableMap[] = {
42 : FXMAPFUNC(MID_MBTTIP_FOCUS, 0, MFXDecalsTable::onFocusRow),
43 : FXMAPFUNC(SEL_FOCUSIN, MID_DECALSTABLE_TEXTFIELD, MFXDecalsTable::onFocusRow),
44 : FXMAPFUNC(SEL_KEYPRESS, MID_DECALSTABLE_TEXTFIELD, MFXDecalsTable::onCmdKeyPress),
45 : FXMAPFUNC(SEL_COMMAND, MID_DECALSTABLE_TEXTFIELD, MFXDecalsTable::onCmdEditRowString),
46 : FXMAPFUNC(SEL_COMMAND, MID_DECALSTABLE_SPINNER, MFXDecalsTable::onCmdEditRowSpinner),
47 : FXMAPFUNC(SEL_COMMAND, MID_DECALSTABLE_CHECKBOX, MFXDecalsTable::onCmdEditRowCheckBox),
48 : FXMAPFUNC(SEL_COMMAND, MID_DECALSTABLE_OPEN, MFXDecalsTable::onCmdOpenDecal),
49 : FXMAPFUNC(SEL_COMMAND, MID_DECALSTABLE_ADD, MFXDecalsTable::onCmdAddRow),
50 : FXMAPFUNC(SEL_UPDATE, MID_DECALSTABLE_ADD, MFXDecalsTable::onUpdAddRow),
51 : FXMAPFUNC(SEL_COMMAND, MID_DECALSTABLE_REMOVE, MFXDecalsTable::onCmdRemoveRow),
52 : };
53 :
54 : // Object implementation
55 0 : FXIMPLEMENT(MFXDecalsTable, FXVerticalFrame, MFXDecalsTableMap, ARRAYNUMBER(MFXDecalsTableMap))
56 :
57 : // ===========================================================================
58 : // method definitions
59 : // ===========================================================================
60 :
61 : // ---------------------------------------------------------------------------
62 : // MFXDecalsTable - public methods
63 : // ---------------------------------------------------------------------------
64 :
65 0 : MFXDecalsTable::MFXDecalsTable(GUIDialog_ViewSettings* dialogViewSettingsParent, FXComposite* parent) :
66 : FXVerticalFrame(parent, GUIDesignAuxiliarFrameFixHeight),
67 0 : myIndexFont(new FXFont(getApp(), "Segoe UI", 9)),
68 0 : myIndexSelectedFont(new FXFont(getApp(), "Segoe UI", 9, FXFont::Bold)),
69 0 : myDialogViewSettings(dialogViewSettingsParent) {
70 : // create vertical frame for rows
71 0 : myColumnsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarFrame);
72 : // create add button
73 0 : myAddButton = GUIDesigns::buildFXButton(this, "", TL("Add decal"), TL("Add decal."),
74 : GUIIconSubSys::getIcon(GUIIcon::ADD), this, MID_DECALSTABLE_ADD, GUIDesignButtonIcon);
75 0 : }
76 :
77 :
78 0 : MFXDecalsTable::~MFXDecalsTable() {
79 : // delete fonts
80 0 : delete myIndexFont;
81 0 : delete myIndexSelectedFont;
82 0 : }
83 :
84 :
85 : void
86 0 : MFXDecalsTable::clearTable() {
87 : // clear rows (always before columns, because delete row delete also all cells)
88 0 : for (const auto& row : myRows) {
89 0 : delete row;
90 : }
91 : // clear columns
92 0 : for (const auto& column : myColumns) {
93 0 : delete column;
94 : }
95 : // drop rows and columns
96 : myRows.clear();
97 : myColumns.clear();
98 0 : }
99 :
100 :
101 : void
102 0 : MFXDecalsTable::fillTable() {
103 : // first clear table
104 0 : clearTable();
105 : // get decals
106 0 : const auto decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
107 : // create columns
108 0 : std::string columnsType = "ibfsssspscd";
109 0 : for (int i = 0; i < (FXint)columnsType.size(); i++) {
110 0 : myColumns.push_back(new Column(this, i, columnsType.at(i)));
111 : }
112 : // get num decals
113 0 : const int numDecals = decals.size() < MAXROWS ? (int)decals.size() : MAXROWS;
114 : // create rows
115 0 : for (int i = 0; i < numDecals; i++) {
116 : // get decal
117 0 : const auto& decal = decals.at(i);
118 : // create row
119 0 : auto row = new Row(this);
120 : // fill cells
121 0 : row->getCells().at(2)->getTextField()->setText(decal.filename.c_str());
122 0 : row->getCells().at(3)->getTextField()->setText(toString(decal.centerX).c_str());
123 0 : row->getCells().at(4)->getTextField()->setText(toString(decal.centerY).c_str());
124 0 : row->getCells().at(5)->getTextField()->setText(toString(decal.width).c_str());
125 0 : row->getCells().at(6)->getTextField()->setText(toString(decal.height).c_str());
126 0 : row->getCells().at(7)->getSpinner()->setValue(decal.rot);
127 0 : row->getCells().at(8)->getTextField()->setText(toString(decal.layer).c_str());
128 0 : if (decal.screenRelative) {
129 0 : row->getCells().at(9)->getCheckButton()->setCheck(true);
130 0 : row->getCells().at(9)->getCheckButton()->setText("true");
131 : } else {
132 0 : row->getCells().at(9)->getCheckButton()->setCheck(false);
133 0 : row->getCells().at(9)->getCheckButton()->setText("false");
134 : }
135 0 : myRows.push_back(row);
136 : }
137 : // set headers
138 0 : myColumns.at(2)->setColumnLabel("filename", "");
139 0 : myColumns.at(3)->setColumnLabel("centerX", "");
140 0 : myColumns.at(4)->setColumnLabel("centerY", "");
141 0 : myColumns.at(5)->setColumnLabel("width", "");
142 0 : myColumns.at(6)->setColumnLabel("height", "");
143 0 : myColumns.at(7)->setColumnLabel("rotation", "");
144 0 : myColumns.at(8)->setColumnLabel("layer", "");
145 0 : myColumns.at(9)->setColumnLabel("sRel", "screen relative");
146 : // adjust height (header + rows + add button)
147 0 : setHeight((numDecals + 2) * GUIDesignHeight);
148 : // call create to create all row's elements
149 0 : create();
150 0 : }
151 :
152 :
153 : void
154 0 : MFXDecalsTable::setItemText(FXint row, FXint column, const std::string& text) {
155 0 : if ((row >= 0) && (row < (FXint)myRows.size()) &&
156 0 : (column >= 0) && (column < (FXint)myColumns.size())) {
157 0 : myRows.at(row)->setText(column, text);
158 : } else {
159 0 : throw ProcessError(TL("Invalid row or column"));
160 : }
161 0 : }
162 :
163 :
164 : std::string
165 0 : MFXDecalsTable::getItemText(const int row, const int column) const {
166 0 : if ((row >= 0) && (row < (FXint)myRows.size()) &&
167 0 : (column >= 0) && (column < (FXint)myColumns.size())) {
168 0 : return myRows.at(row)->getText(column);
169 : }
170 0 : throw ProcessError(TL("Invalid row or column"));
171 : }
172 :
173 :
174 : int
175 0 : MFXDecalsTable::getNumRows() const {
176 0 : return (int)myRows.size();
177 : }
178 :
179 :
180 : int
181 0 : MFXDecalsTable::getCurrentSelectedRow() const {
182 0 : return myCurrentSelectedRow;
183 : }
184 :
185 :
186 : void
187 0 : MFXDecalsTable::selectRow(const int row) {
188 0 : if ((row >= 0) && (row < (FXint)myRows.size())) {
189 : // update current selected row
190 0 : myCurrentSelectedRow = row;
191 : // update index label
192 0 : updateIndexLabel();
193 : } else {
194 0 : throw ProcessError(TL("Invalid row"));
195 : }
196 0 : }
197 :
198 :
199 : void
200 0 : MFXDecalsTable::setColumnLabel(const int column, const std::string& text, const std::string& tooltip) {
201 0 : if ((column >= 0) && (column < (int)myColumns.size())) {
202 0 : myColumns.at(column)->setColumnLabel(text, tooltip);
203 : } else {
204 0 : throw ProcessError(TL("Invalid column"));
205 : }
206 0 : }
207 :
208 :
209 : long
210 0 : MFXDecalsTable::onFocusRow(FXObject* sender, FXSelector, void*) {
211 : int selectedRow = -1;
212 : // search selected text field
213 0 : for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
214 : // iterate over every cell
215 0 : for (const auto& cell : myRows.at(rowIndex)->getCells()) {
216 0 : if ((cell->getTextField() == sender) || (cell->getButton() == sender)) {
217 : selectedRow = rowIndex;
218 : }
219 : }
220 : }
221 : // update index label
222 0 : updateIndexLabel();
223 : // set new row
224 0 : if (myCurrentSelectedRow != selectedRow) {
225 0 : myCurrentSelectedRow = selectedRow;
226 0 : updateIndexLabel();
227 : }
228 0 : return 0;
229 : }
230 :
231 :
232 : long
233 0 : MFXDecalsTable::onCmdKeyPress(FXObject* sender, FXSelector sel, void* ptr) {
234 : // get FXEvent
235 : FXEvent* eventInfo = (FXEvent*)ptr;
236 : // check code
237 0 : if (eventInfo->code == 65362) {
238 : // move up
239 0 : if (myCurrentSelectedRow > 0) {
240 0 : myCurrentSelectedRow -= 1;
241 : } else {
242 : // we're in the first, then select last
243 0 : myCurrentSelectedRow = ((int)myRows.size() - 1);
244 : }
245 : // update index label
246 0 : updateIndexLabel();
247 : // move focus
248 0 : moveFocus();
249 0 : return 1;
250 0 : } else if (eventInfo->code == 65364) {
251 : // move down
252 0 : if (myCurrentSelectedRow < ((int)myRows.size() - 1)) {
253 0 : myCurrentSelectedRow += 1;
254 : } else {
255 : // we're in the last, then select first
256 0 : myCurrentSelectedRow = 0;
257 : }
258 : // update index label
259 0 : updateIndexLabel();
260 : // move focus
261 0 : moveFocus();
262 0 : return 1;
263 : } else {
264 : // continue handling key pres
265 0 : return sender->handle(sender, sel, ptr);
266 : }
267 : }
268 :
269 :
270 : long
271 0 : MFXDecalsTable::onCmdEditRowString(FXObject* sender, FXSelector, void*) {
272 : // get decals
273 0 : auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
274 : // get value
275 0 : const std::string value = dynamic_cast<FXTextField*>(sender)->getText().text();
276 : // set filename
277 0 : for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
278 : // continue depending of string
279 0 : if (myRows.at(rowIndex)->getCells().at(2)->getTextField() == sender) {
280 0 : decals.at(rowIndex).filename = value;
281 0 : } else if (myRows.at(rowIndex)->getCells().at(3)->getTextField() == sender) {
282 0 : decals.at(rowIndex).centerX = StringUtils::toDouble(value);
283 0 : } else if (myRows.at(rowIndex)->getCells().at(4)->getTextField() == sender) {
284 0 : decals.at(rowIndex).centerY = StringUtils::toDouble(value);
285 0 : } else if (myRows.at(rowIndex)->getCells().at(5)->getTextField() == sender) {
286 0 : decals.at(rowIndex).width = StringUtils::toDouble(value);
287 0 : } else if (myRows.at(rowIndex)->getCells().at(6)->getTextField() == sender) {
288 0 : decals.at(rowIndex).height = StringUtils::toDouble(value);
289 0 : } else if (myRows.at(rowIndex)->getCells().at(8)->getTextField() == sender) {
290 0 : decals.at(rowIndex).layer = StringUtils::toDouble(value);
291 : }
292 : }
293 : // update view
294 0 : myDialogViewSettings->getSUMOAbstractView()->update();
295 0 : return 1;
296 : }
297 :
298 :
299 : long
300 0 : MFXDecalsTable::onCmdEditRowSpinner(FXObject* sender, FXSelector, void*) {
301 : // get decals
302 0 : auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
303 : // get value
304 0 : const auto value = dynamic_cast<FXRealSpinner*>(sender)->getValue();
305 : // set filename
306 0 : for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
307 0 : if (myRows.at(rowIndex)->getCells().at(7)->getSpinner() == sender) {
308 0 : decals.at(rowIndex).rot = value;
309 : }
310 : }
311 : // update view
312 0 : myDialogViewSettings->getSUMOAbstractView()->update();
313 0 : return 1;
314 : }
315 :
316 :
317 : long
318 0 : MFXDecalsTable::onCmdEditRowCheckBox(FXObject* sender, FXSelector, void*) {
319 : // get decals
320 0 : auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
321 : // get check buton
322 0 : auto checkButton = dynamic_cast<FXCheckButton*>(sender);
323 : // update text
324 0 : checkButton->setText((checkButton->getCheck() == TRUE) ? "true" : "false");
325 : // set filename
326 0 : for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
327 0 : if (myRows.at(rowIndex)->getCells().at(9)->getCheckButton() == sender) {
328 0 : decals.at(rowIndex).screenRelative = (checkButton->getCheck() == TRUE) ? true : false;
329 : }
330 : }
331 : // update view
332 0 : myDialogViewSettings->getSUMOAbstractView()->update();
333 0 : return 1;
334 : }
335 :
336 :
337 : long
338 0 : MFXDecalsTable::onCmdOpenDecal(FXObject* sender, FXSelector, void*) {
339 : // configure open dialog
340 0 : FXFileDialog opendialog(this, TL("Open decal"));
341 : // select existing file
342 0 : opendialog.setSelectMode(SELECTFILE_EXISTING);
343 : // set icon and pattern list
344 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN));
345 0 : opendialog.setPatternList(TL("All files (*)"));
346 : // set current folder
347 0 : if (gCurrentFolder.length() != 0) {
348 0 : opendialog.setDirectory(gCurrentFolder);
349 : }
350 : // open dialog
351 0 : opendialog.execute();
352 : // check if file exist
353 0 : if (!opendialog.getFilename().empty()) {
354 : // get decals
355 0 : auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
356 : // set filename
357 0 : for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
358 0 : if (myRows.at(rowIndex)->getCells().at(1)->getButton() == sender) {
359 : // set text in filename
360 0 : myRows.at(rowIndex)->getCells().at(2)->getTextField()->setText(opendialog.getFilename());
361 : // update filename in decal
362 0 : decals.at(rowIndex).filename = opendialog.getFilename().text();
363 : // update view
364 0 : myDialogViewSettings->getSUMOAbstractView()->update();
365 : return 1;
366 : }
367 : }
368 : }
369 : return 1;
370 0 : }
371 :
372 :
373 : long
374 0 : MFXDecalsTable::onCmdAddRow(FXObject*, FXSelector, void*) {
375 : // add a new decal
376 0 : myDialogViewSettings->getSUMOAbstractView()->getDecals().push_back(GUISUMOAbstractView::Decal());
377 : // refill table
378 0 : fillTable();
379 0 : return 1;
380 : }
381 :
382 :
383 : long
384 0 : MFXDecalsTable::onUpdAddRow(FXObject* sender, FXSelector, void* ptr) {
385 0 : if (myDialogViewSettings->getSUMOAbstractView()->getDecals().size() < MAXROWS) {
386 0 : return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
387 : } else {
388 0 : return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
389 : }
390 : }
391 :
392 :
393 : long
394 0 : MFXDecalsTable::onCmdRemoveRow(FXObject* sender, FXSelector, void*) {
395 : // get decals
396 0 : auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
397 : // search row
398 0 : for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
399 0 : if (myRows.at(rowIndex)->getCells().back()->getButton() == sender) {
400 : // remove row
401 : decals.erase(decals.begin() + rowIndex);
402 : // update view
403 0 : myDialogViewSettings->getSUMOAbstractView()->update();
404 : // refill table
405 0 : fillTable();
406 0 : return 1;
407 : }
408 : }
409 : return 1;
410 : }
411 :
412 :
413 : void
414 0 : MFXDecalsTable::updateIndexLabel() {
415 : // update radio buttons checks
416 0 : for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
417 : // iterate over every cell
418 0 : for (const auto& cell : myRows.at(rowIndex)->getCells()) {
419 0 : if (cell->getIndexLabel()) {
420 0 : if (myCurrentSelectedRow == rowIndex) {
421 0 : cell->showIndexLabelBold();
422 : } else {
423 0 : cell->showIndexLabelNormal();
424 : }
425 : }
426 : }
427 : }
428 0 : }
429 :
430 :
431 : bool
432 0 : MFXDecalsTable::moveFocus() {
433 : // first find focus
434 : // update radio buttons checks
435 0 : for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
436 0 : for (int cellIndex = 0; cellIndex < (int)myRows.at(rowIndex)->getCells().size(); cellIndex++) {
437 0 : if (myRows.at(rowIndex)->getCells().at(cellIndex)->hasFocus()) {
438 : // set focus in current row
439 0 : myRows.at(myCurrentSelectedRow)->getCells().at(cellIndex)->setFocus();
440 0 : return true;
441 : }
442 : }
443 : }
444 : return false;
445 : }
446 :
447 : // ---------------------------------------------------------------------------
448 : // MFXDecalsTable::Cell - methods
449 : // ---------------------------------------------------------------------------
450 :
451 0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXTextField* textField, int col, int row) :
452 0 : myDecalsTable(decalsTable),
453 0 : myTextField(textField),
454 0 : myCol(col),
455 0 : myRow(row) {
456 0 : }
457 :
458 :
459 0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXLabel* indexLabel, FXLabel* indexLabelBold, int col, int row) :
460 0 : myDecalsTable(decalsTable),
461 0 : myIndexLabel(indexLabel),
462 0 : myIndexLabelBold(indexLabelBold),
463 0 : myCol(col),
464 0 : myRow(row) {
465 : // hide bold and set background
466 0 : indexLabelBold->hide();
467 0 : indexLabelBold->setBackColor(FXRGBA(210, 233, 255, 255));
468 0 : }
469 :
470 :
471 0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXButton* button, int col, int row) :
472 0 : myDecalsTable(decalsTable),
473 0 : myButton(button),
474 0 : myCol(col),
475 0 : myRow(row) {
476 0 : }
477 :
478 :
479 0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXCheckButton* checkButton, int col, int row) :
480 0 : myDecalsTable(decalsTable),
481 0 : myCheckButton(checkButton),
482 0 : myCol(col),
483 0 : myRow(row) {
484 0 : }
485 :
486 :
487 0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXRealSpinner* spinner, int col, int row) :
488 0 : myDecalsTable(decalsTable),
489 0 : mySpinner(spinner),
490 0 : myCol(col),
491 0 : myRow(row) {
492 0 : }
493 :
494 :
495 0 : MFXDecalsTable::Cell::~Cell() {
496 : // delete all elements
497 0 : if (myTextField) {
498 0 : delete myTextField;
499 : }
500 0 : if (myIndexLabel) {
501 0 : delete myIndexLabel;
502 : }
503 0 : if (myIndexLabelBold) {
504 0 : delete myIndexLabelBold;
505 : }
506 0 : if (myButton) {
507 0 : delete myButton;
508 : }
509 0 : if (myCheckButton) {
510 0 : delete myCheckButton;
511 : }
512 0 : }
513 :
514 :
515 : bool
516 0 : MFXDecalsTable::Cell::hasFocus() const {
517 : // check if one of the cell elements has the focus
518 0 : if (myTextField && myTextField->hasFocus()) {
519 : return true;
520 0 : } else if (myButton && myButton->hasFocus()) {
521 : return true;
522 0 : } else if (myCheckButton && myCheckButton->hasFocus()) {
523 : return true;
524 : } else {
525 0 : return false;
526 : }
527 : }
528 :
529 :
530 : void
531 0 : MFXDecalsTable::Cell::setFocus() {
532 : // set focus
533 0 : if (myTextField) {
534 0 : myTextField->setFocus();
535 0 : } else if (myButton) {
536 0 : myButton->setFocus();
537 0 : } else if (myCheckButton) {
538 0 : myCheckButton->setFocus();
539 : }
540 0 : }
541 :
542 :
543 : FXTextField*
544 0 : MFXDecalsTable::Cell::getTextField() const {
545 0 : return myTextField;
546 : }
547 :
548 :
549 : FXLabel*
550 0 : MFXDecalsTable::Cell::getIndexLabel() const {
551 0 : return myIndexLabel;
552 : }
553 :
554 :
555 : FXButton*
556 0 : MFXDecalsTable::Cell::getButton() {
557 0 : return myButton;
558 : }
559 :
560 :
561 : FXCheckButton*
562 0 : MFXDecalsTable::Cell::getCheckButton() {
563 0 : return myCheckButton;
564 : }
565 :
566 :
567 : FXRealSpinner*
568 0 : MFXDecalsTable::Cell::getSpinner() {
569 0 : return mySpinner;
570 : }
571 :
572 :
573 : void
574 0 : MFXDecalsTable::Cell::showIndexLabelNormal() {
575 0 : myIndexLabel->show();
576 0 : myIndexLabelBold->hide();
577 : // recalc both
578 0 : myIndexLabel->recalc();
579 0 : myIndexLabelBold->recalc();
580 0 : }
581 :
582 :
583 : void
584 0 : MFXDecalsTable::Cell::showIndexLabelBold() {
585 0 : myIndexLabel->hide();
586 0 : myIndexLabelBold->show();
587 : // recalc both
588 0 : myIndexLabel->recalc();
589 0 : myIndexLabelBold->recalc();
590 0 : }
591 :
592 :
593 : int
594 0 : MFXDecalsTable::Cell::getCol() const {
595 0 : return myCol;
596 : }
597 :
598 :
599 : int
600 0 : MFXDecalsTable::Cell::getRow() const {
601 0 : return myRow;
602 : }
603 :
604 :
605 : char
606 0 : MFXDecalsTable::Cell::getType() const {
607 0 : return myDecalsTable->myColumns.at(myCol)->getType();
608 : }
609 :
610 :
611 0 : MFXDecalsTable::Cell::Cell() :
612 0 : myCol(-1),
613 0 : myRow(-1) {
614 0 : }
615 :
616 : // ---------------------------------------------------------------------------
617 : // MFXDecalsTable::Column - methods
618 : // ---------------------------------------------------------------------------
619 :
620 0 : MFXDecalsTable::Column::Column(MFXDecalsTable* table, const int index, const char type) :
621 0 : myTable(table),
622 0 : myIndex(index),
623 0 : myType(type) {
624 : // get static tooltip
625 0 : auto staticTooltip = table->myDialogViewSettings->getSUMOAbstractView()->getGUIGlChildWindow()->getGUIMainWindowParent()->getStaticTooltipMenu();
626 : // create vertical frame
627 0 : if (myType == 'f') {
628 0 : myVerticalFrame = new FXVerticalFrame(table->myColumnsFrame, GUIDesignAuxiliarFrame);
629 : } else {
630 0 : myVerticalFrame = new FXVerticalFrame(table->myColumnsFrame, GUIDesignAuxiliarFrameFixWidth);
631 : }
632 : // create top label
633 0 : switch (myType) {
634 0 : case ('f'): {
635 : // ticked label extended
636 0 : myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL));
637 0 : break;
638 : }
639 0 : case ('p'):
640 : case ('s'): {
641 : // ticked label fixed
642 0 : myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelThickedFixed(0));
643 0 : break;
644 : }
645 0 : case ('c'): {
646 : // ticked label for checkbox
647 0 : myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelThickedFixed(30));
648 0 : break;
649 : }
650 0 : case ('i'): {
651 : // ticked label for index
652 0 : myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelFixed(30));
653 0 : break;
654 : }
655 0 : default: {
656 : // empty label (for buttons)
657 0 : myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelFixed(0));
658 0 : break;
659 : }
660 : }
661 : // create vertical frame for cells
662 0 : if (myType == 'f') {
663 0 : myVerticalCellFrame = new FXVerticalFrame(myVerticalFrame, GUIDesignAuxiliarFrame);
664 : } else {
665 0 : myVerticalCellFrame = new FXVerticalFrame(myVerticalFrame, GUIDesignAuxiliarFrameFixWidth);
666 : }
667 : // create elements
668 0 : myVerticalFrame->create();
669 0 : myTopLabel->create();
670 0 : myVerticalCellFrame->create();
671 : // adjust column width
672 0 : adjustColumnWidth();
673 0 : }
674 :
675 :
676 0 : MFXDecalsTable::Column::~Column() {
677 : // delete vertical frame (this also delete all childrens)
678 0 : delete myVerticalFrame;
679 0 : }
680 :
681 :
682 : FXVerticalFrame*
683 0 : MFXDecalsTable::Column::getVerticalCellFrame() const {
684 0 : return myVerticalCellFrame;
685 : }
686 :
687 :
688 : char
689 0 : MFXDecalsTable::Column::getType() const {
690 0 : return myType;
691 : }
692 :
693 :
694 : FXString
695 0 : MFXDecalsTable::Column::getColumnLabel() const {
696 0 : return myTopLabel->getText();
697 : }
698 :
699 :
700 : void
701 0 : MFXDecalsTable::Column::setColumnLabel(const std::string& text, const std::string& tooltip) {
702 0 : myTopLabel->setText(text.c_str());
703 0 : myTopLabel->setTipText(tooltip.c_str());
704 : // adjust column width
705 0 : adjustColumnWidth();
706 0 : }
707 :
708 :
709 : void
710 0 : MFXDecalsTable::Column::adjustColumnWidth() {
711 : // filename always extended
712 0 : if (myType != 'f') {
713 : // declare columnWidth
714 0 : int columnWidth = GUIDesignHeight;
715 : // adjust depending of label
716 0 : if ((myType == 's') || (myType == 'p') || (myType == 'c')) {
717 : // calculate top label width
718 0 : columnWidth = myTopLabel->getFont()->getTextWidth(myTopLabel->getText().text(), myTopLabel->getText().length() + EXTRAMARGIN);
719 : }
720 : // adjust width in all rows
721 0 : for (const auto& row : myTable->myRows) {
722 0 : if (row->getCells().at(myIndex)->getTextField()) {
723 0 : row->getCells().at(myIndex)->getTextField()->setWidth(columnWidth);
724 0 : } else if (row->getCells().at(myIndex)->getButton()) {
725 0 : row->getCells().at(myIndex)->getButton()->setWidth(columnWidth);
726 0 : } else if (row->getCells().at(myIndex)->getSpinner()) {
727 0 : row->getCells().at(myIndex)->getSpinner()->setWidth(columnWidth);
728 : }
729 : }
730 : // adjust labels and vertical frames
731 0 : myVerticalFrame->setWidth(columnWidth);
732 0 : myTopLabel->setWidth(columnWidth);
733 0 : myVerticalCellFrame->setWidth(columnWidth);
734 : }
735 0 : }
736 :
737 :
738 0 : MFXDecalsTable::Column::Column() :
739 0 : myIndex(0),
740 0 : myType('-') {}
741 :
742 : // ---------------------------------------------------------------------------
743 : // MFXDecalsTable::Row - methods
744 : // ---------------------------------------------------------------------------
745 :
746 0 : MFXDecalsTable::Row::Row(MFXDecalsTable* table) :
747 0 : myTable(table) {
748 : // build textFields
749 0 : for (int columnIndex = 0; columnIndex < (FXint)table->myColumns.size(); columnIndex++) {
750 : // get number of cells
751 0 : const int numCells = (int)myCells.size();
752 : // continue depending of type
753 0 : switch (table->myColumns.at(columnIndex)->getType()) {
754 0 : case ('f'): {
755 : // create textField for filenames
756 0 : auto textField = new FXTextField(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
757 0 : GUIDesignTextFieldNCol, table, MID_DECALSTABLE_TEXTFIELD, GUIDesignTextField);
758 0 : myCells.push_back(new Cell(table, textField, columnIndex, numCells));
759 0 : break;
760 : }
761 0 : case ('s'): {
762 : // create textField for textfiedl real values
763 0 : auto textField = new FXTextField(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
764 0 : GUIDesignTextFieldNCol, table, MID_DECALSTABLE_TEXTFIELD, GUIDesignTextFieldFixedRestricted(0, TEXTFIELD_REAL));
765 0 : myCells.push_back(new Cell(table, textField, columnIndex, numCells));
766 0 : break;
767 : }
768 0 : case ('p'): {
769 : // create spinner for real values
770 0 : auto spinner = new FXRealSpinner(table->myColumns.at(columnIndex)->getVerticalCellFrame(), GUIDesignTextFieldNCol,
771 0 : table, MID_DECALSTABLE_SPINNER, GUIDesignSpinDialDecalsTable);
772 0 : myCells.push_back(new Cell(table, spinner, columnIndex, numCells));
773 0 : break;
774 : }
775 0 : case ('i'): {
776 : // create labels for index
777 0 : auto indexLabel = new FXLabel(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
778 0 : toString(myTable->myRows.size()).c_str(), nullptr, GUIDesignLabelThickedFixed(30));
779 0 : auto indexLabelBold = new FXLabel(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
780 0 : toString(myTable->myRows.size()).c_str(), nullptr, GUIDesignLabelThickedFixed(30));
781 : // set fonts
782 0 : indexLabel->setFont(myTable->myIndexFont);
783 0 : indexLabelBold->setFont(myTable->myIndexSelectedFont);
784 0 : myCells.push_back(new Cell(table, indexLabel, indexLabelBold, columnIndex, numCells));
785 0 : break;
786 : }
787 0 : case ('c'): {
788 : // create checkbox for
789 0 : auto checkableButton = new FXCheckButton(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
790 0 : "false", table, MID_DECALSTABLE_CHECKBOX, GUIDesignMFXCheckableButton);
791 0 : myCells.push_back(new Cell(table, checkableButton, columnIndex, numCells));
792 0 : break;
793 : }
794 0 : case ('b'): {
795 : // create button for open decal
796 0 : auto button = GUIDesigns::buildFXButton(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
797 0 : "", TL("Open decal"), TL("Open decal."),
798 : GUIIconSubSys::getIcon(GUIIcon::OPEN), table, MID_DECALSTABLE_OPEN, GUIDesignButtonIcon);
799 0 : myCells.push_back(new Cell(table, button, columnIndex, numCells));
800 0 : break;
801 : }
802 0 : case ('d'): {
803 : // create button for delete decal
804 0 : auto button = GUIDesigns::buildFXButton(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
805 0 : "", TL("Remove decal"), TL("Remove decal."),
806 : GUIIconSubSys::getIcon(GUIIcon::REMOVE), table, MID_DECALSTABLE_REMOVE, GUIDesignButtonIcon);
807 0 : myCells.push_back(new Cell(table, button, columnIndex, numCells));
808 0 : break;
809 : }
810 0 : default:
811 0 : throw ProcessError("Invalid Cell type");
812 : }
813 : }
814 0 : }
815 :
816 :
817 0 : MFXDecalsTable::Row::~Row() {
818 : // delete all cells
819 0 : for (const auto& cell : myCells) {
820 0 : delete cell;
821 : }
822 0 : }
823 :
824 :
825 : std::string
826 0 : MFXDecalsTable::Row::getText(int index) const {
827 0 : if (myCells.at(index)->getTextField()) {
828 0 : return myCells.at(index)->getTextField()->getText().text();
829 : } else {
830 0 : throw ProcessError("Cell doesn't have a textField");
831 : }
832 : }
833 :
834 :
835 : void
836 0 : MFXDecalsTable::Row::setText(int index, const std::string& text) const {
837 : // set text
838 0 : myCells.at(index)->getTextField()->setText(text.c_str());
839 0 : }
840 :
841 :
842 : const std::vector<MFXDecalsTable::Cell*>&
843 0 : MFXDecalsTable::Row::getCells() const {
844 0 : return myCells;
845 : }
846 :
847 :
848 0 : MFXDecalsTable::Row::Row() {}
849 :
850 : /****************************************************************************/
|