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