Eclipse SUMO - Simulation of Urban MObility
MFXAddEditTypedTable.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2004-2022 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/****************************************************************************/
18// missing_desc
19/****************************************************************************/
20#include <config.h>
21
25
26
27// Map
28FXDEFMAP(MFXAddEditTypedTable) MFXAddEditTypedTableMap[] = {
29 FXMAPFUNC(SEL_CLICKED, 0, MFXAddEditTypedTable::onClicked),
30 FXMAPFUNC(SEL_DOUBLECLICKED, 0, MFXAddEditTypedTable::onDoubleClicked),
31 FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, MFXAddEditTypedTable::onLeftBtnRelease),
32 FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, MFXAddEditTypedTable::onLeftBtnPress),
33};
34// Object implementation
35FXIMPLEMENT(MFXAddEditTypedTable, FXTable, MFXAddEditTypedTableMap, ARRAYNUMBER(MFXAddEditTypedTableMap))
36
37
38MFXAddEditTypedTable::MFXAddEditTypedTable(FXComposite* p, FXObject* tgt,
39 FXSelector sel, FXuint opts,
40 FXint x, FXint y, FXint w, FXint h,
41 FXint pl, FXint pr, FXint pt, FXint pb)
42 : FXTable(p, tgt, sel, opts, x, y, w, h, pl, pr, pt, pb) {}
43
44
46
47/*
48void
49MFXAddEditTypedTable::editItem(FXTableItem* item,FXint how)
50{
51 if(item==0) {
52 editEnd();
53 return;
54 }
55 if(myWriteProtectedCols.find(myEditedCol)!=myWriteProtectedCols.end()) {
56 editEnd();
57 return;
58 }
59 FXTableItem* it= item;
60 myPreviousText = item->getText();
61 FXint x = getColumnX(myEditedCol) + getRowHeader()->getWidth() + xpos;
62 FXint y = getRowY(myEditedRow) + getColumnHeader()->getHeight() + ypos;
63 FXIcon* icon = item->getIcon();
64 if(icon) x += icon->getWidth() + 4;
65 FXint vw = getViewportWidth();
66 if(vertical->shown()) vw -= vertical->getWidth();
67 if(vw>getColumnWidth(myEditedCol)) {
68 vw = getColumnWidth(myEditedCol) + x;
69 }
70 switch(getCellType(myEditedCol)) {
71 case CT_UNDEFINED:
72 case CT_STRING:
73 myEditor->setText(it->getText());
74 myEditor->move(x, y);
75 myEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1);
76 myEditor->show();
77 myEditor->raise();
78 myEditor->enable();
79 myEditor->setFocus();
80 myEditor->grab();
81 if(how == 'I') {
82 myEditor->killSelection();
83 myEditor->setCursorPos(0);
84 } else if(how == 'A') {
85 myEditor->killSelection();
86 myEditor->setCursorPos(myEditor->getText().length());
87 } else myEditor->selectAll();
88 break;
89 case CT_REAL:
90 {
91 try {
92 myNumberEditor->setValue(
93 TplConvert::_2double(it->getText().text()));
94 } catch (NumberFormatException &) {
95 } catch (EmptyData &) {
96 }
97 NumberCellParams p = getNumberCellParams(myEditedCol);
98 if(p.format!="undefined") {
99 myNumberEditor->setFormatString((char*) p.format.c_str());
100 myNumberEditor->setIncrements(p.steps1, p.steps2, p.steps3);
101 myNumberEditor->setRange(p.min, p.max);
102 }
103 myNumberEditor->move(x, y);
104 myNumberEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1);
105 myNumberEditor->show();
106 myNumberEditor->raise();
107 myNumberEditor->setFocus();
108 myNumberEditor->selectAll();
109 }
110 //myNumberEditor->setRange(0,1000);
111 break;
112 case CT_INT:
113 {
114 try {
115 myNumberEditor->setValue(
116 TplConvert::_2int(it->getText().text()));
117 } catch (NumberFormatException &) {
118 } catch (EmptyData &) {
119 }
120 NumberCellParams p = getNumberCellParams(myEditedCol);
121 if(p.format!="undefined") {
122 myNumberEditor->setFormatString((char*) p.format.c_str());
123 myNumberEditor->setIncrements(p.steps1, p.steps2, p.steps3);
124 myNumberEditor->setRange(p.min, p.max);
125 }
126 myNumberEditor->move(x, y);
127 myNumberEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1);
128 myNumberEditor->show();
129 myNumberEditor->raise();
130 myNumberEditor->setFocus();
131 myNumberEditor->selectAll();
132 }
133 break;
134 case CT_BOOL:
135 try {
136 myBoolEditor->setCheck(
137 TplConvert::_2bool(it->getText().text())
138 ? true : false);
139 } catch (NumberFormatException &) {
140 } catch (EmptyData &) {
141 }
142 myBoolEditor->move(x, y);
143 myBoolEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1);
144 myBoolEditor->show();
145 myBoolEditor->raise();
146 myBoolEditor->setFocus();
147 break;
148 case CT_ENUM:
149 {
150 myEnumEditor->hide();
151 myEnumEditor->clearItems();
152 if(myEnums.size()>myEditedCol) {
153 for(int i=0; i<myEnums[myEditedCol].size(); i++) {
154 myEnumEditor->appendItem(myEnums[myEditedCol][i].c_str());
155 }
156 }
157 if(myEnumEditor->findItem(it->getText())>=0) {
158 myEnumEditor->setCurrentItem(
159 myEnumEditor->findItem(it->getText()));
160 } else {
161 myEnumEditor->setCurrentItem(0);
162 }
163 myEnumEditor->setNumVisible(
164 myEnums[myEditedCol].size()<10
165 ? myEnums[myEditedCol].size()
166 : 10);
167 myEnumEditor->layout();
168 y = getRowY(myEditedRow) + getColumnHeader()->getHeight() + ypos
169 - getRowHeight(myEditedRow);
170 myEnumEditor->move(x, y);
171 myEnumEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1);
172 myEnumEditor->show();
173 myEnumEditor->raise();
174 myEnumEditor->setFocus();
175 }
176 break;
177 default:
178 throw 1;
179 }
180 myEditedItem = it;
181}
182*/
183
184
185FXWindow*
187 FXTableItem* item = cells[r * ncols + c];
188 if (item == nullptr) {
189 return nullptr;
190// cells[r * ncols + c] = item = createItem("", NULL, NULL);
191// if (isItemSelected(r, c)) {
192// item->setSelected(FALSE);
193// }
194 }
195 delete editor;
196 editor = nullptr;
197 switch (getCellType(c)) {
198 case CT_UNDEFINED:
199 case CT_STRING: {
200 FXTextField* field;
201 FXuint justify = 0;
202 field = new FXTextField(this, 1, nullptr, 0, TEXTFIELD_ENTER_ONLY, 0, 0, 0, 0, getMarginLeft(), getMarginRight(), getMarginTop(), getMarginBottom());
203 // !!! if(state&LEFT) justify|=JUSTIFY_LEFT;
204 // !!! if(state&RIGHT) justify|=JUSTIFY_RIGHT;
205 // !!! if(state&TOP) justify|=JUSTIFY_TOP;
206 // !!! if(state&BOTTOM) justify|=JUSTIFY_BOTTOM;
207 field->create();
208 field->setJustify(justify);
209 field->setFont(getFont());
210 field->setBackColor(getBackColor());
211 field->setTextColor(getTextColor());
212 field->setSelBackColor(getSelBackColor());
213 field->setSelTextColor(getSelTextColor());
214 field->setText(item->getText());
215 field->selectAll();
216 return field;
217 }
218 case CT_REAL:
219// return myNumberEditor;
220 case CT_INT: {
221 FXRealSpinner* field;
222 //FXuint justify=0;
223 field = new FXRealSpinner(this, 1, nullptr, 0, TEXTFIELD_ENTER_ONLY, 0, 0, 0, 0, getMarginLeft(), getMarginRight(), getMarginTop(), getMarginBottom());
224 // !!! if(state&LEFT) justify|=JUSTIFY_LEFT;
225 // !!! if(state&RIGHT) justify|=JUSTIFY_RIGHT;
226 // !!! if(state&TOP) justify|=JUSTIFY_TOP;
227 // !!! if(state&BOTTOM) justify|=JUSTIFY_BOTTOM;
228 field->create();
229// field->setJustify(justify);
230 field->setFont(getFont());
231 field->setBackColor(getBackColor());
232 field->setTextColor(getTextColor());
233 field->setSelBackColor(getSelBackColor());
234 field->setSelTextColor(getSelTextColor());
236 if (p.format != "undefined") {
237 //field->setFormatString((char*) p.format.c_str());
238 //field->setIncrements(p.steps1, p.steps2, p.steps3);
239 field->setIncrement(p.steps2);
240 field->setRange(p.min, p.max);
241 }
242 try {
243 if (getCellType(c) == CT_REAL) {
244 field->setValue(StringUtils::toDouble(item->getText().text()));
245 } else {
246 field->setValue(StringUtils::toInt(item->getText().text()));
247 }
248 } catch (NumberFormatException&) {
249 field->setValue(0);
250 }
251 //field->selectAll();
252 return field;
253 }
254 case CT_BOOL:
255// return myBoolEditor;
256 case CT_ENUM:
257// return myEnumEditor;
258 default:
259 throw 1;
260 }
261}
262
263
264// Cancel editing cell
265void
267 if (editor) {
268 delete editor;
269 input.fm.row = -1;
270 input.to.row = -1;
271 input.fm.col = -1;
272 input.to.col = -1;
273 editor = nullptr;
274 }
275}
276
277// Done with editing cell
278void
280 bool set = false;
281 FXTableRange tablerange = input;
282 if (editor) {
283 FXRealSpinner* dial = dynamic_cast<FXRealSpinner*>(editor);
284 if (dial != nullptr) {
285 setItemFromControl_NoRelease(input.fm.row, input.fm.col, editor);
286 }
287 if (dynamic_cast<FXTextField*>(editor) != nullptr) {
288 set = true;
289 }
290 }
291 if (set) {
292 setItemFromControl(input.fm.row, input.fm.col, editor);
293 cancelInput();
294 if (notify && target) {
295 target->tryHandle(this, FXSEL(SEL_REPLACED, message), (void*)&tablerange);
296 }
297 }
298}
299
300
301
302
303void
304MFXAddEditTypedTable::setItemFromControl(FXint r, FXint c, FXWindow* control) {
305 FXTableItem* item = cells[r * ncols + c];
306 if (item == nullptr) {
307 cells[r * ncols + c] = item = createItem("", nullptr, nullptr);
308 if (isItemSelected(r, c)) {
309 item->setSelected(FALSE);
310 }
311 }
312 switch (getCellType(c)) {
313 case CT_UNDEFINED:
314 case CT_STRING:
315 item->setFromControl(control);
316 break;
317 case CT_REAL:
318 item->setText(toString(static_cast<FXRealSpinner*>(control)->getValue()).c_str());
319 break;
320 case CT_INT:
321 item->setText(toString((int) static_cast<FXRealSpinner*>(control)->getValue()).c_str());
322 break;
323 case CT_BOOL:
324// return myBoolEditor;
325 case CT_ENUM:
326// return myEnumEditor;
327 default:
328 throw 1;
329 }
330// current.row = -1;
331// current.col = -1;
332 EditedTableItem edited;
333 edited.item = item;
334 edited.row = r;
335 edited.col = c;
336 edited.updateOnly = false;
337 killSelection(true);
338 bool accepted = true;
339 if (target) {
340 if (!target->handle(this, FXSEL(SEL_CHANGED, ID_TEXT_CHANGED), (void*) &edited)) {
341 accepted = false;
342 // !!! item->setText(myPreviousText);
343 }
344 }
345 if (accepted) {
346 if (edited.row == getNumRows() - 1) {
347 insertRows(getNumRows(), 1, true);
348 for (int i = 0; i < getNumColumns(); i++) {
349 setItemText(getNumRows() - 1, i, "");
350 setItemJustify(getNumRows() - 1, i, JUSTIFY_CENTER_X);
351 }
352 }
353 }
354 mode = MOUSE_NONE;
355}
356
357
358void
359MFXAddEditTypedTable::setItemFromControl_NoRelease(FXint r, FXint c, FXWindow* control) {
360 FXTableItem* item = cells[r * ncols + c];
361 if (item == nullptr) {
362 return;
363 }
364 switch (getCellType(c)) {
365 case CT_UNDEFINED:
366 case CT_STRING:
367 item->setFromControl(control);
368 break;
369 case CT_REAL:
370 item->setText(toString(static_cast<FXRealSpinner*>(control)->getValue()).c_str());
371 break;
372 case CT_INT:
373 item->setText(toString((int) static_cast<FXRealSpinner*>(control)->getValue()).c_str());
374 break;
375 case CT_BOOL:
376// return myBoolEditor;
377 case CT_ENUM:
378// return myEnumEditor;
379 default:
380 throw 1;
381 }
382 EditedTableItem edited;
383 edited.item = item;
384 edited.row = r;
385 edited.col = c;
386 edited.updateOnly = true;
387 if (target) {
388 if (!target->handle(this, FXSEL(SEL_CHANGED, ID_TEXT_CHANGED), (void*) &edited)) {
389 // !!! item->setText(myPreviousText);
390 }
391 }
392}
393
394
395// Released button
396long MFXAddEditTypedTable::onLeftBtnRelease(FXObject*, FXSelector, void* ptr) {
397 FXEvent* event = (FXEvent*)ptr;
398 if (isEnabled()) {
399 ungrab();
400 flags &= ~FLAG_PRESSED;
401 flags |= FLAG_UPDATE;
402 mode = MOUSE_NONE;
403 stopAutoScroll();
404 setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
405 if (target && target->tryHandle(this, FXSEL(SEL_LEFTBUTTONRELEASE, message), ptr)) {
406 return 1;
407 }
408
409 // Scroll to make item visibke
410 makePositionVisible(current.row, current.col);
411
412 // Update anchor
413 //setAnchorItem(current.row,current.col); // FIXME look into the selection stuff
414
415 // Generate clicked callbacks
416 if (event->click_count == 1) {
417 handle(this, FXSEL(SEL_CLICKED, 0), (void*)&current);
418 } else if (event->click_count == 2) {
419 handle(this, FXSEL(SEL_DOUBLECLICKED, 0), (void*)&current);
420 } else if (event->click_count == 3) {
421 handle(this, FXSEL(SEL_TRIPLECLICKED, 0), (void*)&current);
422 }
423
424 // Command callback only when clicked on item
425 if (0 <= current.row && 0 <= current.col && isItemEnabled(current.row, current.col)) {
426 handle(this, FXSEL(SEL_COMMAND, 0), (void*)&current);
427 }
428 return 1;
429 }
430 return 0;
431}
432
433
434// Pressed button
435long
436MFXAddEditTypedTable::onLeftBtnPress(FXObject*, FXSelector, void* ptr) {
437 FXEvent* event = (FXEvent*)ptr;
438 FXTablePos tablepos;
439 flags &= ~FLAG_TIP;
440 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
441 if (isEnabled()) {
442 grab();
443 if (target && target->tryHandle(this, FXSEL(SEL_LEFTBUTTONPRESS, message), ptr)) {
444 return 1;
445 }
446
447 // Cell being clicked on
448 tablepos.row = rowAtY(event->win_y);
449 tablepos.col = colAtX(event->win_x);
450
451 // Outside table
452 if (tablepos.row < 0 || tablepos.row >= nrows || tablepos.col < 0 || tablepos.col >= ncols) {
453 setCurrentItem(-1, -1, TRUE);
454 return 0;
455 }
456
457 // Change current item
458 bool wasEdited = editor != nullptr;
459 setCurrentItem(tablepos.row, tablepos.col, TRUE);
460 if (!wasEdited) {
461
462 // Select or deselect
463 if (event->state & SHIFTMASK) {
464 if (0 <= anchor.row && 0 <= anchor.col) {
465 if (isItemEnabled(anchor.row, anchor.col)) {
466 extendSelection(current.row, current.col, TRUE);
467 }
468 } else {
469 setAnchorItem(current.row, current.col);
470 if (isItemEnabled(current.row, current.col)) {
471 extendSelection(current.row, current.col, TRUE);
472 }
473 }
474 mode = MOUSE_SELECT;
475 } else {
476 if (isItemEnabled(current.row, current.col)) {
477 killSelection(TRUE);
478 setAnchorItem(current.row, current.col);
479 extendSelection(current.row, current.col, TRUE);
480 } else {
481 setAnchorItem(current.row, current.col);
482 }
483 mode = MOUSE_SELECT;
484 }
485 }
486 flags &= ~FLAG_UPDATE;
487 flags |= FLAG_PRESSED;
488 return 1;
489 }
490 return 0;
491}
492
493
494
495// Clicked in list
496long
497MFXAddEditTypedTable::onClicked(FXObject*, FXSelector, void* ptr) {
498 if (editor) {
499 delete editor;
500 input.fm.row = -1;
501 input.to.row = -1;
502 input.fm.col = -1;
503 input.to.col = -1;
504 editor = nullptr;
505 current.row = -1;
506 current.col = -1;
507 }
508 if (target && target->tryHandle(this, FXSEL(SEL_CLICKED, message), ptr)) {
509 return 1;
510 }
511 handle(this, FXSEL(SEL_COMMAND, ID_START_INPUT), nullptr);
512 return 1;
513}
514
515
516// Double clicked in list; ptr may or may not point to an item
517long MFXAddEditTypedTable::onDoubleClicked(FXObject*, FXSelector, void* ptr) {
518 if (editor) {
519 delete editor;
520 input.fm.row = -1;
521 input.to.row = -1;
522 input.fm.col = -1;
523 input.to.col = -1;
524 editor = nullptr;
525 } else {
526 if (target && target->tryHandle(this, FXSEL(SEL_CLICKED, message), ptr)) {
527 return 1;
528 }
529 handle(this, FXSEL(SEL_COMMAND, ID_START_INPUT), nullptr);
530 }
531 return 1;
532}
533
534
537 if ((int)myCellTypes.size() <= pos) {
538 return CT_UNDEFINED;
539 }
540 return myCellTypes[pos];
541}
542
543
544void
546 while ((int)myCellTypes.size() < pos + 1) {
547 myCellTypes.push_back(CT_UNDEFINED);
548 }
549 myCellTypes[pos] = t;
550}
551
552void
553MFXAddEditTypedTable::setNumberCellParams(int pos, double min, double max,
554 double steps1,
555 double steps2,
556 double steps3,
557 const std::string& format) {
558 while ((int)myNumberCellParams.size() <= pos) {
560 np.format = "undefined";
561 myNumberCellParams.push_back(np);
562 }
564 np.pos = (int)(pos);
565 np.min = min;
566 np.max = max;
567 np.steps1 = steps1;
568 np.steps2 = steps2;
569 np.steps3 = steps3;
570 np.format = format;
571 myNumberCellParams[pos] = np;
572}
573
574
577 if ((int)myNumberCellParams.size() <= pos) {
579 np.format = "undefined";
580 return np;
581 }
582 return myNumberCellParams[pos];
583}
584
585
586
587void
589 const std::vector<std::string>& params) {
590 while ((int)myEnums.size() <= pos) {
591 myEnums.push_back(std::vector<std::string>());
592 }
593 myEnums[pos] = params;
594}
595
596
597void
599 const std::string& e) {
600 while ((int)myEnums.size() <= pos) {
601 myEnums.push_back(std::vector<std::string>());
602 }
603 myEnums[pos].push_back(e);
604}
605
606
607const std::vector<std::string>&
609 return myEnums[pos];
610}
611
612
613/****************************************************************************/
FXDEFMAP(MFXAddEditTypedTable) MFXAddEditTypedTableMap[]
@ CT_UNDEFINED
@ CT_STRING
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
std::vector< std::vector< std::string > > myEnums
virtual FXWindow * getControlForItem(FXint r, FXint c)
std::vector< NumberCellParams > myNumberCellParams
long onClicked(FXObject *, FXSelector, void *ptr)
long onLeftBtnRelease(FXObject *, FXSelector, void *ptr)
void addEnum(int pos, const std::string &e)
long onDoubleClicked(FXObject *, FXSelector, void *ptr)
void setCellType(int pos, CellType t)
NumberCellParams getNumberCellParams(int pos) const
void setNumberCellParams(int pos, double min, double max, double steps1, double steps2, double steps3, const std::string &format)
void setItemFromControl_NoRelease(FXint r, FXint c, FXWindow *control)
void setEnums(int pos, const std::vector< std::string > &params)
long onLeftBtnPress(FXObject *, FXSelector, void *ptr)
void acceptInput(FXbool notify)
CellType getCellType(int pos) const
virtual void setItemFromControl(FXint r, FXint c, FXWindow *control)
const std::vector< std::string > & getEnums(int pos) const
std::vector< CellType > myCellTypes
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...