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