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