NEURON
xmenu.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #include "oc2iv.h"
4 #include "classreg.h"
5 #include "gui-redirect.h"
6 #include "utils/enumerate.h"
7 
8 #if HAVE_IV // to end of file except for a few small fragments.
9 
10 #include <cstdio>
11 #include <cstring>
12 #include <cmath>
13 #include <cctype>
14 #include <cerrno>
15 #include <string>
16 
17 #include <InterViews/box.h>
18 #include <IV-look/kit.h>
19 #include <InterViews/event.h>
20 #include <InterViews/layout.h>
21 #include <InterViews/style.h>
22 #include <InterViews/background.h>
23 #include <InterViews/border.h>
24 #include <InterViews/dialog.h>
25 #include <InterViews/printer.h>
26 #include <InterViews/geometry.h>
27 #include <InterViews/transformer.h>
28 #include <InterViews/patch.h>
29 #include <InterViews/color.h>
30 #include <InterViews/telltale.h>
31 #include <InterViews/hit.h>
32 #include <InterViews/resource.h>
33 
34 #include <InterViews/display.h>
35 #include "mymath.h"
36 #include "xmenu.h"
37 #include "datapath.h"
38 #include "ivoc.h"
39 #include "bndedval.h"
40 #include "nrnpy.h"
41 #include "objcmd.h"
42 #include "parse.hpp"
43 #include "utility.h"
44 #include "scenepic.h"
45 
46 // The problem this overcomes is that the pick of an input handler normally
47 // succeeds for a keystroke only if the mouse is over one of the child
48 // handlers. We want it to succeed whenever it is inside the panel.
49 class PanelInputHandler: public InputHandler {
50  public:
51  PanelInputHandler(Glyph*, Style*);
52  virtual ~PanelInputHandler();
53  virtual void pick(Canvas*, const Allocation&, int depth, Hit&);
54  virtual void focus(InputHandler*);
55  static bool has_old_focus() {
56  bool old = sema_;
57  sema_ = false;
58  return old;
59  }
60  static void handle_old_focus();
61 
62  private:
63  static InputHandler* focus_;
64  static bool sema_;
65 };
66 
67 void handle_old_focus() {
69 }
70 
71 InputHandler* PanelInputHandler::focus_ = NULL;
72 bool PanelInputHandler::sema_ = false;
73 
74 PanelInputHandler::PanelInputHandler(Glyph* g, Style* s)
75  : InputHandler(g, s) {}
76 PanelInputHandler::~PanelInputHandler() {}
77 void PanelInputHandler::pick(Canvas* c, const Allocation& a, int depth, Hit& h) {
78  const Event* e = h.event();
79  if (focus_ && e && e->type() == Event::key && focus_->handler()) {
80  h.target(depth, this, 0, focus_->handler());
81  } else {
82  InputHandler::pick(c, a, depth, h);
83  }
84 }
85 void PanelInputHandler::focus(InputHandler* h) {
86  if (focus_ && focus_ != h) {
87  if (h) {
88  sema_ = true;
89  }
90  InputHandler* f = focus_;
91  focus_ = NULL;
92  f->focus_out();
93  }
94  focus_ = h;
95  InputHandler::focus(h);
96 }
97 
99  if (focus_) {
100  // printf("handle_old_focus %p\n", focus_);
101  sema_ = true;
102  InputHandler* f = focus_;
103  focus_ = NULL;
104  f->focus_out();
105  }
106 }
107 
108 class ValEdLabel: public MonoGlyph {
109  public:
110  ValEdLabel(Glyph*);
111  virtual ~ValEdLabel();
112  virtual void draw(Canvas*, const Allocation&) const;
113  void state(bool);
114  void tts(TelltaleState*);
115 
116  private:
117  static const Color* color_;
118  bool state_;
119  TelltaleState* tts_;
120 };
121 
122 const Color* ValEdLabel::color_;
123 
124 ValEdLabel::ValEdLabel(Glyph* g)
125  : MonoGlyph(g) {
126  state_ = false;
127  if (!color_) {
128  color_ = Color::lookup(Session::instance()->default_display(), "yellow");
129  Resource::ref(color_);
130  }
131  tts_ = NULL;
132 }
133 
134 ValEdLabel::~ValEdLabel() {}
135 void ValEdLabel::draw(Canvas* c, const Allocation& a) const {
136  if (state_) {
137  c->fill_rect(a.left(), a.bottom(), a.right(), a.top(), color_);
138  }
139  MonoGlyph::draw(c, a);
140 }
141 void ValEdLabel::state(bool s) {
142  if (state_ != s) {
143  state_ = s;
144  tts_->notify();
145  }
146 }
147 
148 void ValEdLabel::tts(TelltaleState* t) {
149  tts_ = t; // not reffed
150 }
151 
152 static void hoc_ivpanelPlace(Coord, Coord, int scroll = -1);
153 
154 static String* xvalue_format;
155 
156 #define Editor_Default "DefaultValueEditor"
157 #define Editor_Stepper "DefaultValueEditor"
158 
159 
160 extern int units_on_flag_;
162 void hoc_notify_value() {
163  Oc oc;
164  oc.notify();
165 }
166 
167 void hoc_xpanel() {
168  TRY_GUI_REDIRECT_DOUBLE("xpanel", NULL);
169  if (hoc_usegui) {
170  if (ifarg(1) && hoc_is_str_arg(1)) { // begin spec
171  bool h = false;
172  if (ifarg(2)) {
173  h = (int) chkarg(2, 0, 1) ? true : false;
174  }
175  hoc_ivpanel(gargstr(1), h);
176  } else { // map
177  int scroll = -1; // leave up to panel_scroll attribute
178  if (ifarg(2)) {
179  if (ifarg(3)) {
180  scroll = (int) chkarg(3, -1, 1);
181  }
182  hoc_ivpanelPlace((Coord) *getarg(1), (Coord) *getarg(2), scroll);
183  } else {
184  if (ifarg(1)) {
185  scroll = (int) chkarg(1, -1, 1);
186  }
187  hoc_ivpanelmap(scroll);
188  }
189  }
190  }
191 
192  hoc_ret();
193  hoc_pushx(0.);
194 }
195 
196 void hoc_xmenu() {
197  TRY_GUI_REDIRECT_DOUBLE("xmenu", NULL);
198  if (hoc_usegui) {
199  bool add2menubar = false;
200  char* mk = NULL;
201  Object* pyact = NULL;
202  int i = 2;
203  if (ifarg(i)) {
204  if (hoc_is_str_arg(i)) {
205  mk = gargstr(i);
206  ++i;
207  } else if (hoc_is_object_arg(i)) {
208  pyact = *hoc_objgetarg(i);
209  ++i;
210  }
211  if (ifarg(i)) {
212  add2menubar = int(chkarg(i, 0, 1));
213  }
214  }
215  if (ifarg(1)) {
216  if (mk || pyact) {
217  hoc_ivvarmenu(gargstr(1), mk, add2menubar, pyact);
218  } else {
219  hoc_ivmenu(gargstr(1), add2menubar);
220  }
221  } else {
222  hoc_ivmenu((char*) 0);
223  }
224  }
225  hoc_ret();
226  hoc_pushx(0.);
227 }
228 
229 void hoc_xbutton() {
230  TRY_GUI_REDIRECT_DOUBLE("xbutton", NULL);
231 
232  if (hoc_usegui) {
233  char* s1;
234  s1 = gargstr(1);
235  if (ifarg(2)) {
236  if (hoc_is_object_arg(2)) {
237  hoc_ivbutton(s1, NULL, *hoc_objgetarg(2));
238  } else {
239  hoc_ivbutton(s1, gargstr(2));
240  }
241  } else {
242  hoc_ivbutton(s1, s1);
243  }
244  }
245  hoc_ret();
246  hoc_pushx(0.);
247 }
248 
249 static void hoc_state_or_checkbox(int style) {
250  if (hoc_usegui) {
251  char* sname = gargstr(1);
253  Object* ho2 = NULL;
254  char* s3 = NULL;
255  Object* ho3 = NULL;
256 
257  if (hoc_is_object_arg(2)) {
258  ho2 = *hoc_objgetarg(2);
259  } else {
260  ptr2 = hoc_hgetarg<double>(2);
261  }
262 
263  if (ifarg(3)) {
264  if (hoc_is_object_arg(3)) {
265  ho3 = *hoc_objgetarg(3);
266  } else {
267  s3 = gargstr(3);
268  }
269  }
270 
271  hoc_ivstatebutton(ptr2, sname, s3, style, ho2, ho3);
272  }
273 }
274 
275 /*
276 xstatebutton("prompt",&var [,"action" or ,pyact])
277  like xbutton, but var is set to 0 or 1 depending to match the
278  telltale state of the button
279 */
280 
281 void hoc_xstatebutton() {
282  TRY_GUI_REDIRECT_DOUBLE("xstatebutton", NULL);
283  hoc_state_or_checkbox(HocStateButton::PALETTE);
284  hoc_ret();
285  hoc_pushx(0.);
286 }
287 
288 /*
289 xcheckbox("prompt",&var [,"action" or ,pyact])
290  like xbutton, but var is set to 0 or 1 depending to match the
291  telltale state of the button
292 */
293 
294 void hoc_xcheckbox() {
295  TRY_GUI_REDIRECT_DOUBLE("xcheckbox", NULL);
296  hoc_state_or_checkbox(HocStateButton::CHECKBOX);
297  hoc_ret();
298  hoc_pushx(0.);
299 }
300 
301 void hoc_xradiobutton() {
302  TRY_GUI_REDIRECT_DOUBLE("xradiobutton", NULL);
303 
304  if (hoc_usegui) {
305  char *s1, *s2 = (char*) 0;
306  Object* po = NULL;
307  bool activate = false;
308  s1 = gargstr(1);
309  if (ifarg(2)) {
310  if (hoc_is_object_arg(2)) {
311  po = *hoc_objgetarg(2);
312  } else {
313  s2 = gargstr(2);
314  }
315  if (ifarg(3)) {
316  activate = (chkarg(3, 0, 1) != 0.);
317  }
318  } else {
319  s2 = s1;
320  }
321  if (po) {
322  hoc_ivradiobutton(s1, NULL, activate, po);
323  } else {
324  hoc_ivradiobutton(s1, s2, activate);
325  }
326  }
327  hoc_ret();
328  hoc_pushx(0.);
329 }
330 
331 static void hoc_xvalue_helper() {
332  if (hoc_usegui) { // prompt, variable, deflt,action,canrun,usepointer
333  char *s1, *s2, *s3;
334  // allow variable arg2 to be data_handle
336  Object* pyvar = NULL;
337  Object* pyact = NULL;
338  s2 = s3 = NULL;
339  s1 = gargstr(1);
340  if (ifarg(2)) {
341  if (hoc_is_object_arg(2)) {
342  pyvar = *hoc_objgetarg(2);
343  } else if (hoc_is_pdouble_arg(2)) {
344  ptr2 = hoc_hgetarg<double>(2);
345  } else {
346  s2 = gargstr(2);
347  }
348  } else {
349  s2 = s1;
350  }
351  bool deflt = false;
352  if (ifarg(3) && *getarg(3)) {
353  if (*getarg(3) == 2.) {
354  if (pyvar) {
355  hoc_ivvalue_keep_updated(s1, NULL, pyvar);
356  } else {
357  hoc_ivvalue_keep_updated(s1, s2);
358  }
359  return;
360  }
361  deflt = true;
362  }
363  bool canRun = false, usepointer = false;
364  if (ifarg(4)) {
365  if (hoc_is_object_arg(4)) {
366  pyact = *hoc_objgetarg(4);
367  } else {
368  s3 = gargstr(4);
369  }
370  if (ifarg(5) && *getarg(5)) {
371  canRun = true;
372  }
373  if (ifarg(6) && *getarg(6)) {
374  usepointer = true;
375  }
376  }
377  hoc_ivvaluerun_ex(s1, s2, ptr2, pyvar, s3, pyact, deflt, canRun, usepointer);
378  }
379 }
380 
381 void hoc_xfixedvalue() {
382  TRY_GUI_REDIRECT_DOUBLE("xfixedvalue", NULL);
383 
384  if (hoc_usegui) { // prompt, variable, deflt,action,canrun,usepointer
385  char *s1, *s2;
386  s1 = gargstr(1);
387  if (ifarg(2)) {
388  s2 = gargstr(2);
389  } else {
390  s2 = s1;
391  }
392  bool deflt = false;
393  if (ifarg(3) && *getarg(3)) {
394  deflt = true;
395  }
396  bool usepointer = false;
397  if (ifarg(4) && *getarg(4)) {
398  usepointer = true;
399  }
400  hoc_ivfixedvalue(s1, s2, deflt, usepointer);
401  }
402  hoc_ret();
403  hoc_pushx(0.);
404 }
405 
406 static void hoc_xpvalue_helper() {
407  if (hoc_usegui) { // prompt,variable,deflt,action,canrun
408  char *s1, *s3;
410  HocSymExtension* extra = NULL;
411  Symbol* sym;
412  s1 = gargstr(1);
413  if (ifarg(2)) {
414  pd = hoc_hgetarg<double>(2);
416  } else {
417  pd = hoc_val_handle(s1);
418  sym = hoc_get_symbol(s1);
419  }
420  if (sym) {
421  extra = sym->extra;
422  }
423  bool deflt = false;
424  if (ifarg(3) && *getarg(3)) {
425  deflt = true;
426  }
427  if (ifarg(4)) {
428  s3 = gargstr(4);
429  bool canRun = false;
430  if (ifarg(5) && *getarg(5)) {
431  canRun = true;
432  }
433  hoc_ivpvaluerun(s1, pd, s3, deflt, canRun, extra);
434  } else {
435  hoc_ivpvalue(s1, pd, deflt, extra);
436  }
437  }
438 }
439 
440 void hoc_xvalue() {
441  TRY_GUI_REDIRECT_DOUBLE("xvalue", NULL);
442 
443  hoc_xvalue_helper();
444  hoc_ret();
445  hoc_pushx(0.);
446 }
447 
448 void hoc_xpvalue() {
449  TRY_GUI_REDIRECT_DOUBLE("xpvalue", NULL);
450  hoc_xpvalue_helper();
451  hoc_ret();
452  hoc_pushx(0.);
453 }
454 
455 void hoc_xlabel() {
456  TRY_GUI_REDIRECT_DOUBLE("xlabel", NULL);
457  if (hoc_usegui) {
458  char* s1;
459  s1 = gargstr(1);
460  hoc_ivlabel(s1);
461  }
462  hoc_ret();
463  hoc_pushx(0.);
464 }
465 
466 void hoc_xvarlabel() {
468  if (hoc_usegui) {
469  if (hoc_is_object_arg(1)) {
471  } else {
473  }
474  }
475  hoc_ret();
476  hoc_pushx(0.);
477 }
478 
479 // ZFM modified to add vertical vs. horizontal
480 void hoc_xslider() {
481  TRY_GUI_REDIRECT_DOUBLE("xslider", NULL);
482  if (hoc_usegui) {
483  float low = 0, high = 100;
484  float resolution = 1;
485  int nsteps = 10;
486  char* send = NULL;
487  Object* pysend = NULL;
489  Object* pyvar = NULL;
490  bool vert = 0;
491  if (ifarg(3)) {
492  low = *getarg(2);
493  high = *getarg(3);
494  resolution = (high - low) / 100.;
495  }
496  int iarg = 4;
497  if (ifarg(iarg)) {
498  if (hoc_is_str_arg(iarg)) {
499  send = gargstr(4);
500  ++iarg;
501  } else if (hoc_is_object_arg(iarg)) {
502  pysend = *hoc_objgetarg(iarg);
503  ++iarg;
504  }
505  }
506  if (ifarg(iarg)) {
507  vert = int(chkarg(iarg, 0, 1));
508  }
509  bool slow = false;
510  if (ifarg(++iarg)) {
511  slow = int(chkarg(iarg, 0, 1));
512  }
513  if (hoc_is_object_arg(1)) {
514  pyvar = *hoc_objgetarg(1);
515  } else {
516  pval = hoc_hgetarg<double>(1);
517  }
518  hoc_ivslider(pval, low, high, resolution, nsteps, send, vert, slow, pyvar, pysend);
519  }
520  hoc_ret();
521  hoc_pushx(0.);
522 }
523 
524 
525 class HocButton: public Button {
526  public:
527  HocButton(const char*, Glyph*, Style*, TelltaleState*, Action*);
528  virtual ~HocButton();
529  static HocButton* instance(const char*, Action*);
530  virtual void print(Printer*, const Allocation&) const;
531 
532  private:
533  Glyph* l_;
534 };
535 HocButton::HocButton(const char* text, Glyph* g, Style* s, TelltaleState* t, Action* a)
536  : Button(g, s, t, a) {
537  l_ = WidgetKit::instance()->label(text);
538  l_->ref();
539 }
540 HocButton::~HocButton() {
541  Resource::unref(l_);
542 }
543 HocButton* HocButton::instance(const char* s, Action* a) {
544  Button* b = WidgetKit::instance()->push_button(s, a);
545  b->ref();
546  HocButton* hb = new HocButton(s, b->body(), b->style(), b->state(), b->action());
547  b->unref();
548  return hb;
549 }
550 void HocButton::print(Printer* pr, const Allocation& a) const {
551  l_->print(pr, a);
552 }
553 
554 static std::vector<HocPanel*>* hoc_panel_list;
555 static HocPanel* curHocPanel;
556 static HocValEditor* last_fe_constructed_;
557 static void checkOpenPanel() {
558  if (!curHocPanel) {
559  hoc_execerror("No panel is open", NULL);
560  }
561 }
562 
563 /*static*/ class MenuStack {
564  public:
565  bool isEmpty() {
566  return l_.empty();
567  }
568  void push(HocMenu* m);
569  void pop() {
570  if (!l_.empty()) {
571  l_.front()->unref();
572  l_.erase(l_.begin());
573  }
574  }
575  Menu* top() {
576  return (l_.empty()) ? nullptr : l_.front()->menu();
577  }
578  HocItem* hoc_item() {
579  return (l_.empty()) ? nullptr : l_.front();
580  }
581  void clean();
582 
583  private:
584  std::vector<HocMenu*> l_;
585 };
586 void MenuStack::push(HocMenu* m) {
587  m->ref();
588  l_.insert(l_.begin(), m);
589 }
590 void MenuStack::clean() {
591  for (auto& item: l_) {
592  item->unref();
593  }
594  l_.clear();
595 }
596 static MenuStack* menuStack;
597 static Menu* hocmenubar;
598 
599 class OcTelltaleGroup: public TelltaleGroup {
600  public:
601  OcTelltaleGroup();
602  virtual ~OcTelltaleGroup();
603  virtual void update(TelltaleState*);
604  virtual void remove(TelltaleState*);
605  virtual void restore();
606 
607  private:
608  TelltaleState* previous_;
609  TelltaleState* current_;
610 };
611 
612 OcTelltaleGroup::OcTelltaleGroup() {
613  previous_ = NULL;
614  current_ = NULL;
615 }
616 OcTelltaleGroup::~OcTelltaleGroup() {}
618  if (t != current_ && t->test(TelltaleState::is_chosen)) {
619  previous_ = current_;
620  current_ = t;
621  }
623 }
625  if (previous_ == t) {
626  previous_ = NULL;
627  }
628  if (current_ == t) {
629  current_ = NULL;
630  }
632 }
634  if (previous_) {
635  previous_->set(TelltaleState::is_chosen, true);
636  } else if (current_) {
637  TelltaleGroup::update(current_);
638  current_->set(TelltaleState::is_chosen, false);
639  current_ = NULL;
640  }
641 }
642 
643 class HocRadioAction: public HocAction {
644  public:
645  HocRadioAction(const char* action, OcTelltaleGroup*, Object* pyact = NULL);
646  virtual ~HocRadioAction();
647  virtual void help();
648 
649  private:
650  OcTelltaleGroup* tg_;
651 };
652 
653 HocRadioAction::HocRadioAction(const char* action, OcTelltaleGroup* tg, Object* pyact)
654  : HocAction(action, pyact) {
655  tg_ = tg;
656  Resource::ref(tg_);
657 }
658 
659 HocRadioAction::~HocRadioAction() {
660  Resource::unref(tg_);
661 }
662 void HocRadioAction::help() {
663  tg_->restore();
664  HocAction::help();
665 }
666 
667 /*static*/ class HocRadio {
668  public:
669  HocRadio();
670  virtual ~HocRadio();
671 
672  OcTelltaleGroup* group() {
673  return g_;
674  }
675  void start();
676  void stop();
677 
678  private:
679  OcTelltaleGroup* g_;
680 };
681 
682 HocRadio::HocRadio() {
683  g_ = NULL;
684 }
685 HocRadio::~HocRadio() {
686  Resource::unref(g_);
687 }
688 void HocRadio::start() {
689  Resource::unref(g_);
690  g_ = new OcTelltaleGroup();
691  g_->ref();
692 }
693 
694 void HocRadio::stop() {
695  Resource::unref(g_);
696  g_ = NULL;
697 }
698 
699 static HocRadio* hoc_radio;
700 
701 void hoc_ivpanel(const char* name, bool h) {
702  if (!hoc_radio) {
703  hoc_radio = new HocRadio();
704  }
705  if (curHocPanel) {
706  fprintf(stderr, "%s not closed\n", curHocPanel->getName());
707  if (menuStack) {
708  menuStack->clean();
709  }
710  curHocPanel->unref();
711  curHocPanel = NULL;
712  hoc_execerror("Didn't close the previous panel", NULL);
713  } else {
714  curHocPanel = new HocPanel(name, h);
715  curHocPanel->ref();
716  }
717  hoc_radio->stop();
718 }
719 
720 void hoc_ivpanelmap(int scroll) {
721  checkOpenPanel();
722  curHocPanel->map_window(scroll);
723  curHocPanel->unref();
724  curHocPanel = NULL;
725  if (menuStack && !menuStack->isEmpty()) {
726  fprintf(stderr, "%s menu not closed\n", menuStack->hoc_item()->getStr());
727  menuStack->clean();
728  hoc_execerror("A menu is still open", 0);
729  }
730  hoc_radio->stop();
731 }
732 
733 void hoc_ivpanelPlace(Coord left, Coord bottom, int scroll) {
734  checkOpenPanel();
735  curHocPanel->left_ = left;
736  curHocPanel->bottom_ = bottom;
737  hoc_ivpanelmap(scroll);
738 }
739 
740 void hoc_ivbutton(const char* name, const char* action, Object* pyact) {
741  checkOpenPanel();
742  hoc_radio->stop();
743  if (menuStack && !menuStack->isEmpty()) {
744  menuStack->top()->append_item(curHocPanel->menuItem(name, action, false, pyact));
745  } else {
746  curHocPanel->pushButton(name, action, false, pyact);
747  }
748 }
749 
751  const char* name,
752  const char* action,
753  int style,
754  Object* pyvar,
755  Object* pyact) {
756  checkOpenPanel();
757  hoc_radio->stop();
758  if (menuStack && !menuStack->isEmpty()) {
759  menuStack->top()->append_item(curHocPanel->menuStateItem(pd, name, action, pyvar, pyact));
760  } else {
761  curHocPanel->stateButton(pd, name, action, style, pyvar, pyact);
762  }
763 }
764 
765 void hoc_ivradiobutton(const char* name, const char* action, bool activate, Object* pyact) {
766  checkOpenPanel();
767  if (!hoc_radio->group()) {
768  hoc_radio->start();
769  }
770  if (menuStack && !menuStack->isEmpty()) {
771  menuStack->top()->append_item(curHocPanel->menuItem(name, action, activate, pyact));
772  } else {
773  curHocPanel->pushButton(name, action, activate, pyact);
774  }
775 }
776 
777 void hoc_ivmenu(const char* name, bool add2menubar) {
778  if (!menuStack) {
779  menuStack = new MenuStack();
780  }
781  checkOpenPanel();
782  hoc_radio->stop();
783  if (name) {
784  HocMenu* m = curHocPanel->menu(name, add2menubar);
785  menuStack->push(m);
786  } else {
787  curHocPanel->itemAppend("xmenu()");
788  menuStack->pop();
789  }
790 }
791 
792 void hoc_ivvarmenu(const char* name, const char* action, bool add2menubar, Object* pyvar) {
793  if (!menuStack) {
794  menuStack = new MenuStack();
795  }
796  checkOpenPanel();
797  hoc_radio->stop();
798  HocMenu* m = curHocPanel->menu(name, add2menubar);
799  HocMenuAction* hma = new HocMenuAction(action, pyvar, m);
800  m->item()->action(hma);
801 }
802 
803 void hoc_ivvalue_keep_updated(const char* name, const char* variable, Object* pyvar) {
804  checkOpenPanel();
805  hoc_radio->stop();
806  Symbol* s = hoc_get_symbol(variable);
807  curHocPanel->valueEd(name,
808  variable,
809  NULL,
810  false,
811  hoc_val_handle(variable),
812  false,
813  true,
814  (s ? s->extra : NULL),
815  pyvar);
816 }
817 
818 void hoc_ivvalue(const char* name, const char* variable, bool deflt, Object* pyvar) {
819  hoc_ivvaluerun(name, variable, NULL, deflt, false, false);
820 }
821 
822 void hoc_ivfixedvalue(const char* name, const char* variable, bool deflt, bool usepointer) {
823  hoc_ivvaluerun(name, variable, NULL, deflt, false, usepointer);
824 }
825 
826 void hoc_ivpvalue(const char* name,
828  bool deflt,
829  HocSymExtension* extra) {
830  hoc_ivpvaluerun(name, pd, 0, deflt, false, extra);
831 }
832 
833 void hoc_ivvaluerun(const char* name,
834  const char* variable,
835  const char* action,
836  bool deflt,
837  bool canRun,
838  bool usepointer,
839  Object* pyvar,
840  Object* pyact) {
841  hoc_ivvaluerun_ex(name, variable, {}, pyvar, action, pyact, deflt, canRun, usepointer);
842 }
843 
845  CChar* variable,
847  Object* pyvar,
848  CChar* action,
849  Object* pyact,
850  bool deflt,
851  bool canrun,
852  bool usepointer,
853  HocSymExtension* extra) {
854  checkOpenPanel();
855  hoc_radio->stop();
856  Symbol* s = NULL;
857  if (!pvar && !pyvar) {
858  s = hoc_get_symbol(variable);
859  if (usepointer) {
860  pvar = hoc_val_handle(variable);
861  }
862  }
863  HocSymExtension* xtra = extra;
864  if (!xtra) {
865  xtra = s ? s->extra : NULL;
866  }
867  curHocPanel->valueEd(name, variable, action, canrun, pvar, deflt, false, xtra, pyvar, pyact);
868 }
869 
870 void hoc_ivpvaluerun(const char* name,
872  const char* action,
873  bool deflt,
874  bool canRun,
875  HocSymExtension* extra) {
876  checkOpenPanel();
877  hoc_radio->stop();
878  curHocPanel->valueEd(name, 0, action, canRun, pd, deflt, false, extra);
879 }
880 
881 void hoc_ivlabel(const char* s) {
882  checkOpenPanel();
883  hoc_radio->stop();
884  curHocPanel->label(s);
885 }
886 
887 void hoc_ivvarlabel(char** s, Object* pyvar) {
888  checkOpenPanel();
889  hoc_radio->stop();
890  curHocPanel->var_label(s, pyvar);
891 }
892 
893 // ZFM added vert
895  float low,
896  float high,
897  float resolution,
898  int nsteps,
899  const char* s,
900  bool vert,
901  bool slow,
902  Object* pyvar,
903  Object* pyact) {
904  checkOpenPanel();
905  curHocPanel->slider(pd, low, high, resolution, nsteps, s, vert, slow, pyvar, pyact);
906 }
907 
908 static char* hideQuote(const char* s) {
909  static char buf[200];
910  const char* cp1;
911  char* cp2;
912 
913  cp2 = buf;
914  if (s)
915  for (cp1 = s; *cp1; cp1++, cp2++) {
916  if (*cp1 == '"') {
917  *cp2++ = '\\';
918  }
919  *cp2 = *cp1;
920  }
921  *cp2 = '\0';
922  return buf;
923 }
924 
925 static void saveMenuFile() {}
926 
927 void HocPanel::save_all(std::ostream&) {
928  if (!hoc_panel_list)
929  return;
930 
931  long i, cnt;
932 
933  HocDataPaths* data_paths = new HocDataPaths();
934  if (hoc_panel_list) {
935  for (auto& item: *hoc_panel_list) {
936  item->data_path(data_paths, true);
937  }
938  }
939  data_paths->search();
940  if (hoc_panel_list) {
941  for (auto& item: *hoc_panel_list) {
942  item->data_path(data_paths, false);
943  }
944  }
945  delete data_paths;
946 }
947 
948 void HocPanel::map_window(int scroll) {
949  // switch to scrollbox if too many items
950  static GlyphIndex maxcnt = -1;
951  if (1 || maxcnt == -1) {
952  maxcnt = 12;
953  Style* s = WidgetKit::instance()->style();
954  s->find_attribute("panel_scroll", maxcnt);
955  }
956  if ((scroll == -1 && box_->count() > maxcnt) || scroll == 1) {
957  LayoutKit& lk = *LayoutKit::instance();
958  WidgetKit& wk = *WidgetKit::instance();
959  ScrollBox* vsb = lk.vscrollbox(box_->count());
960  while (box_->count()) {
961  vsb->append(box_->component(0));
962  box_->remove(0);
963  }
964  box_->append(lk.hbox(vsb, lk.hspace(4), wk.vscroll_bar(vsb)));
965  }
966 
968  w->style(new Style(WidgetKit::instance()->style()));
969  w->style()->attribute("name", getName());
970  w->map();
971 }
972 
973 // HocPanel
974 static void var_freed(void* pd, int size) {
975  if (hoc_panel_list) {
976  for (auto&& elem: reverse(*hoc_panel_list)) {
977  elem->check_valid_pointers(pd, size);
978  }
979  }
980 }
981 
982 HocPanel::HocPanel(const char* name, bool h)
983  : OcGlyph(NULL) {
984  LayoutKit& lk = *LayoutKit::instance();
985  WidgetKit& wk = *WidgetKit::instance();
986  horizontal_ = h;
987  hocmenubar = NULL;
988  if (h) {
989  box_ = lk.hbox();
990  } else {
991  box_ = lk.vbox();
992  }
993  box_->ref();
994  body(ih_ = new PanelInputHandler(
995  new Background(new Border(lk.margin(lk.hflexible(box_, fil, 0), 3), wk.foreground()),
996  wk.background()),
997  wk.style()));
998  if (!hoc_panel_list) {
999  hoc_panel_list = new std::vector<HocPanel*>;
1000  Oc oc;
1001  oc.notify_freed(var_freed);
1002  }
1003  hoc_panel_list->push_back(this);
1004  item_append(new HocItem(name));
1005  left_ = -1000.;
1006  bottom_ = -1000.;
1007  errno = 0;
1008 }
1009 
1011  box_->unref();
1012  for (auto& item: ilist_) {
1013  item->HocItem::unref();
1014  }
1015  for (auto& item: elist_) {
1016  item->HocItem::unref();
1017  }
1018  erase_first(*hoc_panel_list, this);
1019  ilist_.clear();
1020  ilist_.shrink_to_fit();
1021  elist_.clear();
1022  elist_.shrink_to_fit();
1023  // printf("~HocPanel\n");
1024 }
1025 
1026 // HocUpdateItem
1027 HocUpdateItem::HocUpdateItem(const char* name, HocItem* hi)
1028  : HocItem(name, hi) {}
1030  HocPanel::keep_updated(this, false);
1031 }
1033 void HocUpdateItem::check_pointer(void*, int) {}
1034 void HocUpdateItem::data_path(HocDataPaths*, bool) {}
1035 
1036 // ones that get updated on every doEvents()
1037 std::vector<HocUpdateItem*>* HocPanel::update_list_;
1038 
1039 void HocPanel::keep_updated() {
1040  static int cnt = 0;
1041  if (update_list_ && (++cnt % 10 == 0)) {
1042  for (auto& item: *update_list_) {
1043  item->update_hoc_item();
1044  }
1045  }
1046 }
1047 void HocPanel::keep_updated(HocUpdateItem* hui, bool add) {
1048  if (!update_list_) {
1049  update_list_ = new std::vector<HocUpdateItem*>();
1050  }
1051  if (add) {
1052  update_list_->push_back(hui);
1053  } else {
1054  erase_first(*update_list_, hui);
1055  }
1056 }
1057 
1058 void HocPanel::paneltool(const char* name,
1059  const char* proc,
1060  const char* selact,
1061  ScenePicker* sp,
1062  Object* pycallback,
1063  Object* pyselact) {
1064  HocCommand* hc = pycallback ? new HocCommand(pycallback) : new HocCommand(proc);
1065  HocCommandTool* hct = new HocCommandTool(hc);
1066  HocAction* ha = NULL;
1067  if (selact || pyselact) {
1068  ha = new HocAction(selact, pyselact);
1069  }
1070  if (curHocPanel && (!menuStack || menuStack->isEmpty())) {
1071  Button* b = sp->radio_button(name, hct, ha);
1072  curHocPanel->box()->append(b);
1073  } else {
1074  sp->add_radio_menu(gargstr(1), hct, ha);
1075  }
1076 }
1077 
1078 void HocPanel::itemAppend(const char* str) {
1079  item_append(new HocItem(str));
1080 }
1081 
1083  // return (PolyGlyph*)(((MonoGlyph*)body())->body());
1084  return box_;
1085 }
1086 
1087 const char* HocPanel::getName() {
1088  return ilist_.front()->getStr();
1089 }
1090 
1092  return ilist_.front();
1093 }
1094 
1095 void HocPanel::pushButton(const char* name, const char* action, bool activate, Object* pyact) {
1096  if (hoc_radio->group()) {
1097  HocRadioAction* a = new HocRadioAction(action, hoc_radio->group(), pyact);
1098  Button* b = WidgetKit::instance()->radio_button(hoc_radio->group(), name, a);
1099  box()->append(b);
1101  if (activate) {
1102  TelltaleState* tts = b->state();
1103  tts->set(TelltaleState::is_chosen, true);
1104  hoc_radio->group()->update(tts);
1105  }
1106  } else {
1107  HocAction* a = new HocAction(action, pyact);
1108  box()->append(WidgetKit::instance()->push_button(name, a));
1109  item_append(new HocPushButton(name, a, hoc_item()));
1110  }
1111 }
1112 
1113 HocPushButton::HocPushButton(const char* name, HocAction* a, HocItem* hi)
1114  : HocItem(name, hi) {
1115  a_ = a;
1116  Resource::ref(a);
1117  a->hoc_item(this);
1118 }
1121 }
1122 void HocPushButton::write(std::ostream& o) {
1123  char buf[200];
1124  nrn_assert(snprintf(buf, 200, "xbutton(\"%s\",\"%s\")", getStr(), hideQuote(a_->name())) < 200);
1125  o << buf << std::endl;
1126 }
1127 
1128 HocRadioButton::HocRadioButton(const char* name, HocRadioAction* a, HocItem* hi)
1129  : HocItem(name, hi) {
1130  a_ = a;
1131  Resource::ref(a);
1132  a->hoc_item(this);
1133 }
1136 }
1137 void HocRadioButton::write(std::ostream& o) {
1138  char buf[200];
1139  nrn_assert(snprintf(buf, 200, "xradiobutton(\"%s\",\"%s\")", getStr(), hideQuote(a_->name())) <
1140  200);
1141  o << buf << std::endl;
1142 }
1143 
1144 void HocPanel::label(const char* name) {
1145  box()->append(LayoutKit::instance()->margin(WidgetKit::instance()->label(name), 3));
1146  item_append(new HocLabel(name));
1147 }
1148 
1149 void HocPanel::var_label(char** name, Object* pyvar) {
1150  HocVarLabel* l = new HocVarLabel(name, box(), pyvar);
1151  item_append(l);
1152  elist_.push_back(l);
1153  l->ref();
1154 }
1155 
1156 // ZFM added vert
1158  float low,
1159  float high,
1160  float resolution,
1161  int nsteps,
1162  const char* send,
1163  bool vert,
1164  bool slow,
1165  Object* pyvar,
1166  Object* pysend) {
1167  OcSlider* s = new OcSlider(pd, low, high, resolution, nsteps, send, vert, slow, pyvar, pysend);
1168  LayoutKit* lk = LayoutKit::instance();
1169  WidgetKit* wk = WidgetKit::instance();
1170  if (slow) {
1171  wk->begin_style("SlowSlider");
1172  }
1173  if (vert) {
1174  box()->append(lk->hflexible(WidgetKit::instance()->vscroll_bar(s->adjustable())));
1175  } else {
1176  box()->append(lk->hflexible(WidgetKit::instance()->hscroll_bar(s->adjustable())));
1177  }
1178  if (slow) {
1179  wk->end_style();
1180  }
1181  item_append(s);
1182  elist_.push_back(s);
1183  s->ref();
1184 }
1185 
1186 HocMenu* HocPanel::menu(const char* name, bool add2menubar) {
1187  WidgetKit* wk = WidgetKit::instance();
1188  Menu* m = wk->pulldown();
1189  MenuItem* mi;
1190  HocMenu* hm;
1191  if (menuStack->isEmpty()) {
1192  Menu* m0;
1193  if (!add2menubar) {
1194  hocmenubar = NULL;
1195  }
1196  if (hocmenubar) {
1197  m0 = hocmenubar;
1198  } else {
1199  m0 = wk->menubar();
1200  hocmenubar = m0;
1201  LayoutKit* lk = LayoutKit::instance();
1202  box()->append(lk->hbox(m0, lk->hglue()));
1203  }
1204  mi = wk->menubar_item(name);
1205  m0->append_item(mi);
1206  hm = new HocMenu(name, m, mi, hoc_item(), add2menubar);
1207  } else {
1208  mi = K::menu_item(name);
1209  menuStack->top()->append_item(mi);
1210  hm = new HocMenu(name, m, mi, menuStack->hoc_item());
1211  }
1212  item_append(hm);
1213  mi->menu(m);
1214  return hm;
1215 }
1216 
1217 MenuItem* HocPanel::menuItem(const char* name, const char* act, bool activate, Object* pyact) {
1218  MenuItem* mi;
1219  if (hoc_radio->group()) {
1220  HocRadioAction* a = new HocRadioAction(act, hoc_radio->group(), pyact);
1221  mi = K::radio_menu_item(hoc_radio->group(), name);
1222  mi->action(a);
1223  item_append(new HocRadioButton(name, a, menuStack->hoc_item()));
1224  if (activate) {
1225  TelltaleState* tts = mi->state();
1226  tts->set(TelltaleState::is_chosen, true);
1227  hoc_radio->group()->update(tts);
1228  }
1229  } else {
1230  HocAction* a = new HocAction(act, pyact);
1231  mi = K::menu_item(name);
1232  mi->action(a);
1233  item_append(new HocPushButton(name, a, menuStack->hoc_item()));
1234  }
1235  return mi;
1236 }
1237 
1238 HocMenu::HocMenu(const char* name, Menu* m, MenuItem* mi, HocItem* hi, bool add2menubar)
1239  : HocItem(name, hi) {
1240  menu_ = m;
1241  mi_ = mi;
1242  add2menubar_ = add2menubar;
1243  m->ref();
1244 }
1246  menu_->unref();
1247 }
1248 void HocMenu::write(std::ostream& o) {
1249  o << "xmenu(\"" << getStr() << "\", " << int(add2menubar_) << ")" << std::endl;
1250 }
1251 
1252 static Coord xvalue_field_size;
1253 
1254 void HocPanel::valueEd(const char* prompt,
1255  Object* pyvar,
1256  Object* pyact,
1257  bool canrun,
1258  bool deflt,
1259  bool keep_updated) {
1260  valueEd(prompt, NULL, NULL, canrun, {}, deflt, keep_updated, NULL, pyvar, pyact);
1261 }
1262 
1263 void HocPanel::valueEd(const char* name,
1264  const char* variable,
1265  const char* action,
1266  bool canrun,
1268  bool deflt,
1269  bool keep_updated,
1270  HocSymExtension* extra,
1271  Object* pyvar,
1272  Object* pyact) {
1273  HocValAction* act;
1274  if (pyact || action) {
1275  act = new HocValAction(action, pyact);
1276  } else {
1277  act = new HocValAction("");
1278  }
1279  ValEdLabel* vel;
1280  float* limits = 0;
1281  if (extra && extra->parmlimits) {
1282  limits = extra->parmlimits;
1283  }
1284  if (extra && extra->units && units_on_flag_) {
1285  char nu[256];
1286  Sprintf(nu, "%s (%s)", name, extra->units);
1287  vel = new ValEdLabel(WidgetKit::instance()->label(nu));
1288  } else {
1289  vel = new ValEdLabel(WidgetKit::instance()->label(name));
1290  }
1291  Button* prompt;
1292  if (canrun) {
1293  prompt = WidgetKit::instance()->default_button(vel, act);
1294  } else {
1295  prompt = WidgetKit::instance()->push_button(vel, act);
1296  }
1297  vel->tts(prompt->state());
1298  HocValEditor* fe;
1299  Button* def;
1300  if (deflt) {
1301  HocDefaultValEditor* dve =
1302  new HocDefaultValEditor(name, variable, vel, act, pd, canrun, hoc_item(), pyvar);
1303  def = dve->checkbox();
1304  fe = dve;
1305  } else if (keep_updated) {
1306  fe = new HocValEditorKeepUpdated(name, variable, vel, act, pd, hoc_item(), pyvar);
1307  } else {
1308  fe = new HocValEditor(name, variable, vel, act, pd, canrun, hoc_item(), pyvar);
1309  }
1310  ih_->append_input_handler(fe->field_editor());
1311  elist_.push_back(fe);
1312  fe->ref();
1313  act->setFieldSEditor(fe); // so button can change the editor
1314  LayoutKit* lk = LayoutKit::instance();
1315  // from mike_neubig_ivoc_xmenu
1316  float fct;
1317  Style* s = WidgetKit::instance()->style();
1318  if (!s->find_attribute("stepper_size", fct)) {
1319  fct = 20;
1320  }
1321  if (deflt) {
1322  box()->append(lk->hbox(lk->vcenter(prompt),
1323  lk->vcenter(def),
1324  lk->vcenter(lk->h_fixed_span(fe->field_editor(), xvalue_field_size)),
1325  lk->vcenter(lk->fixed(fe->stepper(), (int) fct, (int) fct))));
1326  } else {
1327  box()->append(
1328  lk->hbox(prompt,
1329  lk->h_fixed_span(fe->field_editor(), xvalue_field_size),
1330  (fe->stepper() ? lk->fixed(fe->stepper(), int(fct), int(fct)) : NULL)));
1331  }
1332  item_append(fe);
1333  if (limits) {
1334  fe->setlimits(limits);
1335  }
1336  last_fe_constructed_ = fe;
1337 }
1338 
1339 void HocPanel::save(std::ostream& o) {
1340  o << "{" << std::endl;
1341  write(o);
1342  o << "}" << std::endl;
1343 }
1344 
1345 void HocPanel::write(std::ostream& o) {
1346  Oc oc;
1347  o << "xpanel(\"" << getName() << "\", " << (int) horizontal_ << ")" << std::endl;
1348  if (ilist_.size() > 1) {
1349  for (std::size_t i = 1; i < ilist_.size(); ++i) {
1350  ilist_[i]->write(o);
1351  }
1352  }
1353  if (has_window()) {
1354  o << "xpanel(" << double(window()->save_left()) << "," << double(window()->save_bottom())
1355  << ")" << std::endl;
1356  } else {
1357  o << "xpanel()" << std::endl;
1358  }
1359 }
1360 
1361 void HocPanel::item_append(HocItem* hi) {
1362  hi->ref();
1363  ilist_.push_back(hi);
1364 }
1365 
1366 // HocItem
1367 HocItem::HocItem(const char* str, HocItem* hi)
1368  : str_(str) {
1369  help_parent_ = hi;
1370 }
1372  // printf("~HocItem %s\n", str_.string());
1373 }
1374 void HocItem::write(std::ostream& o) {
1375  o << str_.string() << std::endl;
1376 }
1377 
1378 const char* HocItem::getStr() {
1379  return str_.string();
1380 }
1381 
1382 void HocItem::help_parent(HocItem* hi) {
1383  help_parent_ = hi; // not reffed
1384 }
1385 
1386 void HocItem::help(const char* child) {
1387  const char* c1;
1388  char buf[200], *c2 = buf;
1389  char path[512];
1390  for (c1 = getStr(); *c1; ++c1) {
1391  if (isalnum(*c1)) {
1392  *c2++ = *c1;
1393  }
1394  }
1395  *c2 = '\0';
1396  if (child) {
1397  Sprintf(path, "%s %s", child, buf);
1398  } else {
1399  strcpy(path, buf);
1400  }
1401  if (help_parent_) {
1402  help_parent_->help(path);
1403  } else {
1404  Oc::help(path);
1405  }
1406 }
1407 
1408 // HocLabel
1409 HocLabel::HocLabel(const char* s)
1410  : HocItem(s) {}
1412 void HocLabel::write(std::ostream& o) {
1413  o << "xlabel(\"" << hideQuote(getStr()) << "\")" << std::endl;
1414 }
1415 
1416 #if 0
1417 extern void purify_watch_rw_4(char**);
1418 #endif
1419 
1420 // HocVarLabel
1421 HocVarLabel::HocVarLabel(char** cpp, PolyGlyph* pg, Object* pyvar)
1422  : HocUpdateItem("") {
1423  // purify_watch_rw_4(cpp);
1424  pyvar_ = pyvar;
1425  cpp_ = cpp;
1426  cp_ = NULL;
1427  if (pyvar_) {
1428  hoc_obj_ref(pyvar_);
1429  neuron::python::methods.guigetstr(pyvar_, &cp_);
1430  } else {
1431  cp_ = *cpp_;
1432  }
1433  p_ = new Patch(LayoutKit::instance()->margin(WidgetKit::instance()->label(cp_), 3));
1434  p_->ref();
1435  pg->append(p_);
1436 }
1437 
1439  p_->unref();
1440  if (pyvar_) {
1442  if (cp_) {
1443  delete[] cp_;
1444  }
1445  }
1446 }
1447 
1448 void HocVarLabel::write(std::ostream& o) {
1449  if (!variable_.empty() && cpp_) {
1450  o << "xvarlabel(" << variable_ << ")" << std::endl;
1451  } else {
1452  o << "xlabel(\"<can't retrieve>\")" << std::endl;
1453  }
1454 }
1455 
1457  if (pyvar_) {
1459  p_->body(LayoutKit::instance()->margin(WidgetKit::instance()->label(cp_), 3));
1460  p_->redraw();
1461  p_->reallocate();
1462  p_->redraw();
1463  }
1464  } else if (cpp_) {
1465  // printf("update %s\n", cp_);
1466  if (*cpp_ != cp_) {
1467  cp_ = *cpp_;
1468  // printf("replacing with %s\n", cp_);
1469  p_->body(LayoutKit::instance()->margin(WidgetKit::instance()->label(cp_), 3));
1470  p_->redraw();
1471  p_->reallocate();
1472  p_->redraw();
1473  }
1474  } else if (cp_) {
1475  cp_ = 0;
1476  // printf("HocVarLabel::update() freed\n");
1477  p_->body(LayoutKit::instance()->margin(WidgetKit::instance()->label("Free'd"), 3));
1478  p_->redraw();
1479  p_->reallocate();
1480  p_->redraw();
1481  }
1482 }
1483 
1484 HocMenuAction::HocMenuAction(const char* action, Object* pyact, HocMenu* hm)
1485  : HocAction(action, pyact) {
1486  hm_ = hm;
1487  hp_ = NULL;
1488 }
1491 }
1492 void HocMenuAction::execute() {
1493  while (hm_->menu()->item_count()) {
1494  hm_->menu()->remove_item(0);
1495  }
1497  hp_ = NULL;
1498  hoc_ivpanel("");
1499  menuStack->push(hm_);
1501  menuStack->pop();
1502  checkOpenPanel();
1503  hp_ = curHocPanel;
1504  curHocPanel = NULL;
1505  hm_->item()->menu(hm_->menu());
1506 }
1507 
1508 // HocAction
1509 HocAction::HocAction(const char* action, Object* pyact) {
1510  hi_ = NULL;
1511  if (pyact) {
1512  action_ = new HocCommand(pyact);
1513  } else if (action && action[0] != '\0') {
1514  action_ = new HocCommand(action);
1515  } else {
1516  action_ = NULL;
1517  }
1518 }
1519 
1521  if (action_) {
1522  delete action_;
1523  }
1524 }
1525 
1526 void HocAction::hoc_item(HocItem* hi) {
1527  hi_ = hi;
1528 }
1529 
1530 void HocAction::execute() {
1531  if (Oc::helpmode()) {
1532  help();
1533  return;
1534  }
1536  if (action_) {
1537  action_->audit();
1538  action_->execute();
1539  } else {
1540  Oc oc;
1541  oc.notify();
1542  }
1543 }
1544 
1545 void HocAction::help() {
1546  if (hi_) {
1547  hi_->help();
1548  }
1549 }
1550 
1551 const char* HocAction::name() const {
1552  if (action_) {
1553  return action_->name();
1554  } else {
1555  return "";
1556  }
1557 }
1558 
1559 #if UseFieldEditor
1560 declareFieldEditorCallback(HocValAction)
1561 implementFieldEditorCallback(HocValAction)
1562 #else
1565 #endif
1566 // HocValAction
1567 HocValAction::HocValAction(const char* action, Object* pyact)
1568  : HocAction(action, pyact) {
1569  fe_ = NULL;
1570 #if UseFieldEditor
1571  fea_ = new FieldEditorCallback(HocValAction)(
1572 #else
1573  fea_ = new FieldSEditorCallback(HocValAction)(
1574 #endif
1575  this, &HocValAction::accept, NULL);
1576  fea_->ref();
1577 }
1578 
1580  // printf("~HocValAction\n");
1581  fea_->unref();
1582 }
1583 
1585  fe_ = fe; // but not referenced since this action is referenced by fe
1586 }
1587 
1589  if (fe_->active()) {
1590  fe_->field_editor()->parent()->focus(NULL);
1591  } else {
1592  fe_->evalField();
1593  }
1594  fe_->audit();
1596 }
1597 
1598 void HocValAction::execute() {
1599  if (Oc::helpmode()) {
1600  fe_->help();
1601  return;
1602  }
1603  accept(fe_->field_editor());
1604 }
1605 
1606 class HocDefaultCheckbox: public Button {
1607  public:
1608  HocDefaultCheckbox(HocDefaultValEditor*, Glyph*, Style*, TelltaleState*, Action*);
1609  virtual ~HocDefaultCheckbox();
1610  static HocDefaultCheckbox* instance(HocDefaultValEditor*);
1611  virtual void release(const Event&);
1612 
1613  private:
1614  HocDefaultValEditor* dve_;
1615 };
1616 
1617 HocDefaultCheckbox::HocDefaultCheckbox(HocDefaultValEditor* dve,
1618  Glyph* g,
1619  Style* s,
1620  TelltaleState* t,
1621  Action* a)
1622  : Button(g, s, t, a) {
1623  dve_ = dve;
1624 }
1625 
1626 HocDefaultCheckbox::~HocDefaultCheckbox() {}
1627 
1628 HocDefaultCheckbox* HocDefaultCheckbox::instance(HocDefaultValEditor* dve) {
1629  Glyph* g;
1630  TelltaleState* t;
1631  WidgetKit& k = *WidgetKit::instance();
1632  Style* s;
1633  k.begin_style("ToggleButton", "Button");
1634  t = new TelltaleState(TelltaleState::is_enabled | TelltaleState::is_toggle);
1635  g = k.check_box_look(NULL, t);
1636  s = k.style();
1637  HocDefaultCheckbox* cb = new HocDefaultCheckbox(dve, g, s, t, NULL);
1638  k.end_style();
1639  return cb;
1640 }
1641 
1642 void HocDefaultCheckbox::release(const Event& e) {
1643  if (Oc::helpmode()) {
1644  Button::release(e);
1645  }
1646  if (e.pointer_button() == Event::right) {
1647  dve_->def_change(e.pointer_root_x(), e.pointer_root_y());
1648  }
1649  Button::release(e);
1650 }
1651 
1652 declareActionCallback(HocDefaultValEditor);
1653 implementActionCallback(HocDefaultValEditor);
1654 
1655 // HocDefaultValEditor
1657  const char* variable,
1658  ValEdLabel* prompt,
1659  HocValAction* a,
1661  bool canrun,
1662  HocItem* hi,
1663  Object* pyvar)
1664  : HocValEditor(name, variable, prompt, a, pd, canrun, hi, pyvar) {
1665  checkbox_ = HocDefaultCheckbox::instance(this);
1666  checkbox_->ref();
1667  checkbox_->action(
1668  new ActionCallback(HocDefaultValEditor)(this, &HocDefaultValEditor::def_action));
1669  evalField();
1670  deflt_ = most_recent_ = get_val();
1671  vs_ = HocValStepper::instance(this);
1672  Resource::ref(vs_);
1673 }
1674 
1676  checkbox_->unref();
1677  vs_->unref();
1678 }
1679 
1680 void HocDefaultValEditor::def_change(float x0, float y0) {
1681  evalField();
1682  double x = get_val();
1683  if (x != deflt_) {
1684  char form[200], buf[200];
1685  Sprintf(form,
1686  "Permanently replace default value %s with %s",
1687  xvalue_format->string(),
1688  xvalue_format->string());
1689  Sprintf(buf, form, deflt_, x);
1690  if (boolean_dialog(buf, "Replace", "Cancel", NULL, x0, y0)) {
1691  deflt_ = x;
1692  most_recent_ = x;
1693  }
1694  }
1695 }
1696 
1699  TelltaleState* t = checkbox_->state();
1700  // printf("telltale flag %x\n", t->flags());
1701  bool same = (hoc_ac_ == deflt_);
1702  bool chosen = t->test(TelltaleState::is_chosen);
1703  if (same && chosen) {
1704  t->set(TelltaleState::is_chosen, false);
1705  } else if (!same) {
1707  if (!chosen) {
1708  t->set(TelltaleState::is_chosen, true);
1709  }
1710  }
1711 }
1712 
1713 void HocDefaultValEditor::deflt(double d) {
1714  deflt_ = d;
1715 }
1716 
1718  if (Oc::helpmode()) {
1719  checkbox_->state()->set(TelltaleState::is_chosen,
1720  !checkbox_->state()->test(TelltaleState::is_chosen));
1721  Oc::help(Editor_Default);
1722  return;
1723  }
1724  bool chosen = checkbox_->state()->test(TelltaleState::is_chosen);
1725  if (chosen) {
1726  if (most_recent_ != deflt_) {
1728  }
1729  } else {
1730  double x = get_val();
1731  if (deflt_ != x) {
1732  most_recent_ = x;
1733  set_val(deflt_);
1734  }
1735  }
1736  // Oc oc;
1737  // oc.notifyHocValue();
1738  updateField();
1739  exec_action();
1740 }
1741 
1742 // HocValEditorKeepUpdated
1744  const char* variable,
1745  ValEdLabel* prompt,
1746  HocValAction* act,
1748  HocItem* hi,
1749  Object* pyvar)
1750  : HocValEditor(name, variable, prompt, act, pd, false, hi, pyvar) {
1751  // printf("~HocValEditorKeepUpdated\n");
1752  HocPanel::keep_updated(this, true);
1753 }
1755  // printf("~HocValEditorKeepUpdated\n");
1756  HocPanel::keep_updated(this, false);
1757 }
1758 
1759 // HocEditorForItem g++ doesn't do multiple inheritance of same base classes.
1760 
1762  : FieldSEditor("", WidgetKit::instance(), Session::instance()->style(), a->fea()) {
1763  hve_ = he;
1764 #ifdef WIN32
1766 #endif
1767  // hve_->ref();
1768 }
1770  // hve_->unref();
1771 }
1772 
1773 
1774 static void set_format() {
1775  static Coord len;
1776  if (!xvalue_format) {
1777  xvalue_format = new String("%.5g");
1778  WidgetKit::instance()->style()->find_attribute("xvalue_format", *xvalue_format);
1779  char buf[100];
1780  Sprintf(buf, xvalue_format->string(), -8.888888888888888e-18);
1781  Glyph* g = WidgetKit::instance()->label(buf);
1782  g->ref();
1783  Requisition r;
1784  g->request(r);
1785 
1786  // mike_neubig_ivoc_xmenu
1787  float fct;
1788  Style* s = WidgetKit::instance()->style();
1789  if (!s->find_attribute("xvalue_field_size_increase", fct)) {
1790  fct = 10;
1791  }
1792  xvalue_field_size = r.x_requirement().natural() + fct;
1793  g->unref();
1794  }
1795 }
1796 
1797 double MyMath::resolution(double x) {
1798  if (!xvalue_format) {
1799  set_format();
1800  }
1801  char buf[100];
1802  Sprintf(buf, xvalue_format->string(), std::abs(x));
1803  char* cp;
1804  char* least = NULL;
1805  for (cp = buf; *cp; ++cp) {
1806  if (isdigit(*cp)) {
1807  least = cp;
1808  break;
1809  }
1810  }
1811  for (; *cp; ++cp) {
1812  if (*cp >= '1' && *cp <= '9') {
1813  *cp = '0';
1814  least = cp;
1815  }
1816  if (isalpha(*cp)) {
1817  break;
1818  }
1819  }
1820  assert(least);
1821  *least = '1';
1822  double y;
1823  sscanf(buf, "%lf", &y);
1824  return y;
1825 }
1826 
1827 // HocValEditor
1828 HocValEditor::HocValEditor(const char* name,
1829  const char* variable,
1830  ValEdLabel* prompt,
1831  HocValAction* a,
1833  bool canrun,
1834  HocItem* hi,
1835  Object* pyvar)
1836  : HocUpdateItem(name, hi)
1837  , pval_{pd} {
1838  if (!xvalue_format) {
1839  set_format();
1840  }
1841  action_ = a;
1842  fe_ = new HocEditorForItem(this, a);
1843  fe_->ref();
1844  Resource::ref(a);
1845  prompt_ = prompt;
1846  prompt->ref();
1847  canrun_ = canrun;
1848  active_ = false;
1849  domain_limits_ = NULL;
1850  pyvar_ = pyvar;
1851  if (pyvar) {
1852  hoc_obj_ref(pyvar);
1853  } else if (variable) {
1854  variable_ = variable;
1855  Symbol* sym = hoc_get_symbol(variable);
1856  if (sym && sym->extra) {
1857  domain_limits_ = sym->extra->parmlimits;
1858  }
1859  }
1861  fe_->focus_out();
1862 }
1863 
1865  // printf("~HocValEditor\n");
1866  if (pyvar_) {
1868  }
1871  fe_->unref();
1872 }
1873 
1874 void HocValEditor::setlimits(float* limits) {
1876 }
1877 
1879  updateField();
1880 }
1881 
1883  if (action_) {
1884  action_->execute();
1885  } else {
1886  Oc oc;
1887  oc.notify();
1888  }
1889 }
1890 
1891 void HocValEditor::print(Printer* p, const Allocation& a) const {
1892  // printf("HocvalEditor::print\n");
1893  Glyph* l = WidgetKit::instance()->label(*fe_->text());
1894  l->ref();
1895  l->print(p, a);
1896  l->unref();
1897 }
1898 
1899 void HocValEditor::set_val(double x) {
1900  if (pyvar_) {
1902  return;
1903  }
1904  hoc_ac_ = x;
1905  Oc oc;
1906  if (pval_) {
1907  *pval_ = hoc_ac_;
1908  } else if (!variable_.empty()) {
1909  oc.run(variable_ + " = hoc_ac_\n");
1910  }
1911 }
1912 
1913 double HocValEditor::get_val() {
1914  if (pyvar_) {
1916  } else if (pval_) {
1917  return *pval_;
1918  } else if (!variable_.empty()) {
1919  Oc oc;
1920  oc.run(std::string("hoc_ac_ = ") + variable_ + "\n");
1921  return hoc_ac_;
1922  } else {
1923  return 0.;
1924  }
1925 }
1926 
1927 double HocValEditor::domain_limits(double val) {
1928  return check_domain_limits(domain_limits_, val);
1929 }
1930 
1931 void HocValEditor::evalField() {
1932  Oc oc;
1933  oc.run(std::string("hoc_ac_ = ") + fe_->text()->string() + "\n");
1935  set_val(hoc_ac_);
1936  // prompt_->state()->set(TelltaleState::is_active, false);
1937  prompt_->state(false);
1938 }
1939 
1940 void HocValEditor::audit() {
1941  auto sout = std::stringstream{};
1942  if (pyvar_) {
1943  return;
1944  } else if (!variable_.empty()) {
1945  sout << variable_ << " = " << fe_->text()->string();
1946  } else if (pval_) {
1947  sout << "// " << pval_ << " set to " << fe_->text()->string();
1948  }
1949  auto buf = sout.str();
1950  hoc_audit_command(buf.c_str());
1951 }
1952 
1954  if (active_)
1955  return;
1956  char buf[200];
1957  if (pyvar_) {
1958  hoc_ac_ = get_val();
1959  Sprintf(buf, xvalue_format->string(), hoc_ac_);
1960  } else if (pval_) {
1961  Sprintf(buf, xvalue_format->string(), *pval_);
1962  hoc_ac_ = *pval_;
1963  } else if (!variable_.empty()) {
1964  Oc oc;
1965  Sprintf(buf, "hoc_ac_ = %s\n", variable_.c_str());
1966  if (oc.run(buf, 0)) {
1967  strcpy(buf, "Doesn't exist");
1968  } else {
1969  Sprintf(buf, xvalue_format->string(), hoc_ac_);
1970  }
1971  } else {
1972  Sprintf(buf, "Free'd");
1973  }
1974  if (strcmp(buf, fe_->text()->string()) != 0) {
1975  fe_->field(buf);
1976  }
1977 }
1978 
1979 void HocValEditor::write(std::ostream& o) {
1980  char buf[200];
1981  Oc oc;
1982  if (!variable_.empty()) {
1983  Sprintf(buf, "hoc_ac_ = %s\n", variable_.c_str());
1984  oc.run(buf);
1985  Sprintf(buf, "%s = %g", variable_.c_str(), hoc_ac_);
1986  } else if (pval_) {
1987  Sprintf(buf, "/* don't know the hoc path to %g", *pval_);
1988  return;
1989  } else {
1990  Sprintf(buf, "/* variable freed */");
1991  return;
1992  }
1993  o << buf << std::endl;
1994 
1995  int usepointer;
1996  if (pval_) {
1997  usepointer = 1;
1998  } else {
1999  usepointer = 0;
2000  }
2001  nrn_assert(snprintf(buf,
2002  200,
2003  "xvalue(\"%s\",\"%s\", %d,\"%s\", %d, %d )",
2004  getStr(),
2005  variable_.c_str(),
2007  hideQuote(action_->name()),
2008  (int) canrun_,
2009  usepointer) < 200);
2010  o << buf << std::endl;
2011 }
2012 
2013 const char* HocValEditor::variable() const {
2014  if (!variable_.empty()) {
2015  return variable_.c_str();
2016  } else {
2017  return NULL;
2018  }
2019 }
2020 
2021 
2022 void HocValEditorKeepUpdated::write(std::ostream& o) {
2023  char buf[200];
2024  Oc oc;
2025  Sprintf(buf, "hoc_ac_ = %s\n", variable());
2026  oc.run(buf);
2027  Sprintf(buf, "%s = %g", variable(), hoc_ac_);
2028  o << buf << std::endl;
2029  Sprintf(buf, "xvalue(\"%s\",\"%s\", 2 )", getStr(), variable());
2030  o << buf << std::endl;
2031 }
2032 
2033 void HocEditorForItem::keystroke(const Event& e) {
2034  bool unfocus = false;
2035  if (!hve_->active_) {
2036  return;
2037  }
2038  if (Oc::helpmode()) {
2039  hve_->help();
2040  return;
2041  }
2042  char buf[2];
2043  if (e.mapkey(buf, 1) > 0)
2044  switch (buf[0]) {
2045  case '\n':
2046  case '\r':
2047  unfocus = true;
2048  break;
2049  case '\033':
2050  hve_->active_ = false;
2051  hve_->updateField();
2052  hve_->active_ = true;
2053  parent()->focus(NULL);
2054  return;
2055  case '\007':
2056  hve_->active_ = false;
2057  hve_->updateField();
2058  hve_->active_ = true;
2059  return;
2060  default:
2061  break;
2062  }
2064  if (unfocus) {
2065  parent()->focus(NULL);
2066  }
2067 }
2068 class HocEditorTempData {
2069  public:
2070  void init(const Event&);
2071  int sn(const Event&);
2072 #if 0
2073  Coord x_, y_;
2074  Coord xd_, yd_;
2075 #endif
2076  int sn_;
2077  int index_;
2078  EventButton b_;
2079 };
2080 
2081 static HocEditorTempData etd;
2082 
2083 void HocEditorTempData::init(const Event& e) {
2084 #if 0
2085  x_ = e.pointer_x();
2086  y_ = e.pointer_y();
2087  xd_ = 1.;
2088  yd_ = 1.;
2089 #endif
2090  b_ = e.pointer_button();
2091  if (b_ == Event::right) {
2092  sn_ = -1;
2093  } else {
2094  sn_ = 1;
2095  }
2096 }
2097 
2098 int HocEditorTempData::sn(const Event&) {
2099 #if 0
2100  float xnew = e.pointer_x();
2101  float ynew = e.pointer_y();
2102 #undef RES
2103 #define RES 3
2104  if (Math::equal(x_, xnew, float(RES)) && Math::equal(y_, ynew, float(RES))) {
2105  return 0;
2106  }
2107  sn_ = ( ((xnew - x_)*xd_ + (ynew - y_)*yd_ >= 0.)) ? sn_ : -sn_;
2108  xd_ = xnew - x_;
2109  yd_ = ynew - y_;
2110  x_ = xnew;
2111  y_ = ynew;
2112 #endif
2113  return sn_;
2114 }
2115 
2116 void HocEditorForItem::press(const Event& e) {
2117  if (Oc::helpmode()) {
2118  hve_->help();
2119  return;
2120  }
2121  // if (!hve_->active_) {
2122  // focus_in();
2123  // }
2125 #if !UseFieldEditor
2126  int start;
2128  etd.init(e);
2129 #endif
2130 }
2131 
2132 void HocEditorForItem::drag(const Event& e) {
2133 #ifdef WIN32
2134  FieldSEditor::drag(e);
2135 #else
2136  if (etd.b_ == Event::left) {
2137  FieldSEditor::drag(e);
2138  } else {
2139  val_inc(e);
2140  }
2141 #endif
2142 }
2143 
2144 void HocEditorForItem::val_inc(const Event& e) {
2145  int index = index_;
2146  int i, sn;
2147  i = index;
2148  sn = etd.sn(e);
2149  if (sn == 0) {
2150  return;
2151  }
2152  const char* s = text()->string();
2153  char abuf[100];
2154  char* buf = abuf + 1;
2155  strcpy(buf, s);
2156  if (i == strlen(buf)) {
2157  buf[i] = '0';
2158  buf[i + 1] = '\0';
2159  }
2160  while (i >= 0) {
2161  if (isdigit(buf[i])) {
2162  buf[i] = (((buf[i] - '0') + sn + 100) % 10) + '0';
2163  if (sn == 1 && buf[i] != '0') {
2164  break;
2165  } else if (sn == -1 && buf[i] != '9') {
2166  break;
2167  }
2168  }
2169  --i;
2170  }
2171  if (i < 0) {
2172  if (buf[0] == '-') {
2173  if (sn == 1) {
2174  buf[0] = '1';
2175  abuf[0] = '-';
2176  buf = abuf;
2177  ++index_;
2178  } else {
2179  strcpy(buf, s);
2180  }
2181  } else {
2182  if (sn == 1) {
2183  abuf[0] = '1';
2184  buf = abuf;
2185  ++index_;
2186  } else {
2187  strcpy(buf, s);
2188  }
2189  }
2190  }
2191  field(buf);
2192 }
2193 
2194 void HocEditorForItem::release(const Event& e) {
2196 }
2197 
2198 
2200  // printf("HocEditorForItem::focus_in()\n");
2201  if (Oc::helpmode()) {
2202  return NULL;
2203  }
2204  if (!hve_->active_) {
2205  // hve_->prompt_->state()->set(TelltaleState::is_active, true);
2206  hve_->prompt_->state(true);
2207  hve_->active_ = true;
2208  return FieldSEditor::focus_in();
2209  } else {
2210  return InputHandler::focus_in();
2211  }
2212 }
2213 
2215  if (hve_->active_) {
2216  hve_->active_ = false;
2217  // hve_->prompt_->state()->set(TelltaleState::is_active, false);
2218  hve_->prompt_->state(false);
2219  hve_->evalField();
2220  }
2222  if (PanelInputHandler::has_old_focus()) {
2223  // printf("old focus out %p\n", (InputHandler*)this);
2224  hve_->exec_action();
2225  }
2226 }
2227 
2228 void Oc::notifyHocValue() {
2229  // static int j=0;
2230  // printf("notifyHocValue %d\n", ++j);
2231  ParseTopLevel ptl;
2232  ptl.save();
2233  if (hoc_panel_list) {
2234  for (auto&& e: reverse(*hoc_panel_list)) {
2235  e->notifyHocValue();
2236  }
2237  }
2238  ptl.restore();
2239 }
2240 
2241 void HocPanel::notifyHocValue() {
2242  for (auto&& e: reverse(elist_)) {
2243  e->update_hoc_item();
2244  }
2245 }
2246 
2247 void HocPanel::check_valid_pointers(void* v, int size) {
2248  for (auto&& e: reverse(elist_)) {
2249  e->check_pointer(v, size);
2250  }
2251 }
2252 
2253 void HocValEditor::check_pointer(void* v, int size) {
2254  auto* const pval_raw = static_cast<double const*>(pval_);
2255  if (pval_raw) {
2256  auto* const pd = static_cast<double*>(v);
2257  if (size == 1) {
2258  if (pd != pval_raw) {
2259  return;
2260  }
2261  } else {
2262  if (pval_raw < pd || pval_raw >= pd + size)
2263  return;
2264  }
2265  pval_ = {};
2266  }
2267 }
2268 void HocVarLabel::check_pointer(void* v, int) {
2269  char** cpp = (char**) v;
2270  if (cpp_ == cpp) {
2271  cpp_ = 0;
2272  }
2273 }
2274 
2275 void HocPanel::data_path(HocDataPaths* hdp, bool append) {
2276  for (auto&& e: reverse(elist_)) {
2277  e->data_path(hdp, append);
2278  }
2279 }
2280 
2281 void HocValEditor::data_path(HocDataPaths* hdp, bool append) {
2282  if (variable_.empty()) {
2283  auto* const pval_raw = static_cast<double*>(pval_);
2284  if (append) {
2285  hdp->append(pval_raw);
2286  } else {
2287  variable_ = hdp->retrieve(pval_raw);
2288  }
2289  }
2290 }
2291 
2292 void HocVarLabel::data_path(HocDataPaths* hdp, bool append) {
2293  if (cpp_ && variable_.empty()) {
2294  if (append) {
2295  hdp->append(cpp_);
2296  } else {
2297  variable_ = hdp->retrieve(cpp_);
2298  }
2299  }
2300 }
2301 
2302 class StepperMenuAction: public Action {
2303  public:
2304  StepperMenuAction(bool, double);
2305  virtual ~StepperMenuAction();
2306  virtual void execute();
2307 
2308  private:
2309  double x_;
2310  bool geometric_;
2311 };
2312 
2313 class StepperMenu: public PopupMenu {
2314  public:
2315  StepperMenu();
2316  virtual ~StepperMenu();
2317  void stepper(HocValStepper* vs) {
2318  vs_ = vs;
2319  }
2320  HocValStepper* stepper() {
2321  return vs_;
2322  }
2323  virtual bool event(Event&);
2324  void active(bool b) {
2325  active_ = b;
2326  }
2327  bool active() {
2328  return active_;
2329  }
2330 
2331  private:
2332  bool active_;
2333  HocValStepper* vs_;
2334 };
2335 
2336 StepperMenu* HocValStepper::menu_;
2337 
2338 StepperMenuAction::StepperMenuAction(bool b, double x) {
2339  x_ = x;
2340  geometric_ = b;
2341 }
2342 StepperMenuAction::~StepperMenuAction() {}
2343 void StepperMenuAction::execute() {
2344  HocValStepper::menu()->stepper()->default_inc(geometric_, x_);
2345 }
2346 StepperMenu::StepperMenu() {
2347  WidgetKit& k = *WidgetKit::instance();
2348  char buf[50];
2349  active_ = false;
2350  vs_ = NULL;
2351  MenuItem* m;
2352  m = K::menu_item("Res");
2353  m->action(new StepperMenuAction(false, 0));
2354  append_item(m);
2355  m = K::menu_item("*10");
2356  m->action(new StepperMenuAction(true, 10));
2357  append_item(m);
2358  m = K::menu_item("*10^.1");
2359  m->action(new StepperMenuAction(true, pow(10., .1)));
2360  append_item(m);
2361  m = K::menu_item("*e");
2362  m->action(new StepperMenuAction(true, exp(1.)));
2363  append_item(m);
2364  m = K::menu_item("*e^.1");
2365  m->action(new StepperMenuAction(true, exp(.1)));
2366  append_item(m);
2367  m = K::menu_item("*2");
2368  m->action(new StepperMenuAction(true, 2));
2369  append_item(m);
2370  m = K::menu_item("*2^.1");
2371  m->action(new StepperMenuAction(true, pow(2., .1)));
2372  append_item(m);
2373  for (double x = 1000; x > .0005; x /= 10.) {
2374  Sprintf(buf, "+%g", x);
2375  m = K::menu_item(buf);
2376  m->action(new StepperMenuAction(false, x));
2377  append_item(m);
2378  }
2379 }
2380 StepperMenu::~StepperMenu() {}
2381 bool StepperMenu::event(Event& e) {
2382  PopupMenu::event(e);
2383  if (e.type() == Event::up) {
2384  vs_->menu_up(e);
2385  }
2386  return true;
2387 }
2388 
2389 /* static */ class NrnUpDown: public Glyph {
2390  public:
2391  static NrnUpDown* instance();
2392  virtual ~NrnUpDown();
2393  virtual void request(Requisition&) const;
2394  virtual void draw(Canvas*, const Allocation&) const;
2395 
2396  private:
2397  NrnUpDown(const Color*);
2398  static NrnUpDown* instance_;
2399  const Color* color_;
2400 };
2401 
2402 NrnUpDown* NrnUpDown::instance_;
2403 
2404 NrnUpDown::NrnUpDown(const Color* c)
2405  : Glyph() {
2406  color_ = c;
2407  Resource::ref(c);
2408 }
2409 
2410 NrnUpDown::~NrnUpDown() {
2411  Resource::unref(color_);
2412 }
2413 
2414 NrnUpDown* NrnUpDown::instance() {
2415  if (!instance_) {
2416  instance_ = new NrnUpDown(WidgetKit::instance()->foreground());
2417  instance_->ref();
2418  }
2419  return instance_;
2420 }
2421 
2422 #if 1
2423 void NrnUpDown::request(Requisition& r) const {
2424  Requirement x(10);
2425  Requirement y(20);
2426  r.require_x(x);
2427  r.require_y(y);
2428 }
2429 #endif
2430 
2431 void NrnUpDown::draw(Canvas* c, const Allocation& a) const {
2432  Coord x1 = a.left();
2433  Coord y1 = a.bottom();
2434  Coord x2 = a.right();
2435  Coord y2 = a.top();
2436  // printf("draw %g %g %g %g\n", x1, y1, x2, y2);
2437  Coord x = (x1 + x2) * .5;
2438  Coord y = (y1 + y2) * .5;
2439 
2440  c->new_path();
2441  c->move_to(x1, y + 1);
2442  c->line_to(x, y2);
2443  c->line_to(x2, y + 1);
2444  c->close_path();
2445  c->fill(color_);
2446 
2447 #if 1
2448  c->new_path();
2449  c->move_to(x1, y - 1);
2450  c->line_to(x, y1);
2451  c->line_to(x2, y - 1);
2452  c->close_path();
2453  c->fill(color_);
2454 #endif
2455 }
2456 
2457 static Glyph* up_down_mover_look(TelltaleState* t) {
2458  return WidgetKit::instance()->push_button_look(NrnUpDown::instance(), t);
2459 }
2460 
2462  Glyph* g;
2463  TelltaleState* t;
2464  WidgetKit& k = *WidgetKit::instance();
2465  Style* s;
2466  k.begin_style("UpMover", "Button");
2467  t = new TelltaleState(TelltaleState::is_enabled);
2468  g = up_down_mover_look(t);
2469  // g = k.up_mover_look(t);
2470  s = k.style();
2471  HocValStepper* vs = new HocValStepper(ve, g, s, t);
2472  k.end_style();
2473  return vs;
2474 }
2475 
2477  : Stepper(g, s, t) {
2478  if (!menu_) {
2479  menu_ = new StepperMenu();
2480  menu_->ref();
2481  }
2482  hve_ = ve;
2483  default_inc_ = MyMath::resolution(hve_->get_val());
2484  geometric_ = false;
2485 }
2487 void HocValStepper::press(const Event& e) {
2488  steps_ = 0;
2489  inc_ = default_inc_;
2490  menu_->active(false);
2491  if (Oc::helpmode()) {
2492  return;
2493  }
2494  switch (e.pointer_button()) {
2495  case Event::left:
2496  case Event::middle: {
2497  const Allocation& a = allocation();
2498  if (e.pointer_y() < (a.bottom() + a.top()) * .5) {
2499  if (geometric_) {
2500  inc_ = 1. / default_inc_;
2501  } else {
2502  inc_ *= -1;
2503  }
2504  }
2505  menu_->stepper(this);
2506  Stepper::press(e);
2507  break;
2508  }
2509  case Event::right: {
2510  menu_->active(true);
2511  menu_->stepper(this);
2512  Event e1(e);
2513  menu_->event(e1);
2514  } break;
2515  }
2516 }
2517 void HocValStepper::default_inc(bool g, double x) {
2518  if (x == 0.) {
2520  geometric_ = false;
2521  } else {
2522  default_inc_ = x;
2523  geometric_ = g;
2524  }
2525 }
2526 
2527 void HocValStepper::release(const Event& e) {
2528  if (Oc::helpmode()) {
2529  Oc::help(Editor_Stepper);
2530  return;
2531  }
2532  if (menu_->active()) {
2533  menu_->active(false);
2534  Button::release(e);
2535  return;
2536  }
2537  Stepper::release(e);
2538  Oc oc;
2539  hve_->exec_action();
2540  oc.notify();
2541 }
2542 void HocValStepper::menu_up(Event& e) {
2543  menu_->active(true);
2544 #ifdef WIN32
2545  handler()->event(e);
2546 #else
2547  e.unread();
2548 #endif
2549 }
2550 
2551 void HocValStepper::adjust() {
2552  double x, y;
2553  x = hve_->get_val();
2554  if (geometric_) {
2555  y = x * inc_;
2556  } else {
2557  y = x + inc_;
2558  }
2559  y = hve_->domain_limits(y);
2560  if (steps_ > 0 && x * y <= 0.) {
2561  y = 0.;
2562  inc_ = 0.;
2563  }
2564  hve_->set_val(y);
2565  hve_->updateField();
2566  if (!geometric_ && ((++steps_) % 20) == 0) {
2567  inc_ *= 10.;
2568  }
2569 }
2570 void HocValStepper::left() {
2571  inc_ = default_inc_;
2572 }
2573 void HocValStepper::middle() {
2574  inc_ = default_inc_;
2575 }
2576 void HocValStepper::right() {}
2577 
2578 // OcSlider
2579 
2580 // ZFM added vert_
2582  float low,
2583  float high,
2584  float resolution,
2585  int nsteps,
2586  const char* send,
2587  bool vert,
2588  bool slow,
2589  Object* pyvar,
2590  Object* pysend)
2591  : HocUpdateItem("") {
2592  resolution_ = resolution;
2593  pval_ = pd;
2594  pyvar_ = pyvar;
2595  if (pyvar_) {
2596  hoc_obj_ref(pyvar_);
2597  }
2598  vert_ = vert;
2599  slow_ = slow;
2600  bv_ = new BoundedValue(low, high);
2601  bv_->scroll_incr((high - low) / nsteps);
2602  if (send) {
2603  send_ = new HocCommand(send);
2604  } else if (pysend) {
2605  send_ = new HocCommand(pysend);
2606  } else {
2607  send_ = NULL;
2608  }
2609  bv_->attach(Dimension_X, this);
2610  scrolling_ = false;
2611 }
2613  if (send_) {
2614  delete send_;
2615  }
2616  delete bv_;
2617  if (pyvar_) {
2619  }
2620 }
2622  return bv_;
2623 }
2624 
2625 static double last_send;
2627  double x = slider_val();
2628  if (pval_) {
2629  *pval_ = x;
2630  } else if (pyvar_) {
2632  } else {
2633  return;
2634  }
2635  if (!scrolling_) {
2636  scrolling_ = true;
2637  while (Coord(x) != last_send) {
2638  audit();
2639  last_send = Coord(x);
2640  if (send_) {
2641  send_->execute();
2642  } else {
2643  Oc oc;
2644  oc.notify();
2645  }
2646  }
2647  scrolling_ = false;
2648  }
2649 }
2650 
2651 void OcSlider::audit() {
2652  auto sout = std::stringstream{};
2653  char buf[200];
2654  Sprintf(buf, "%g", *pval_);
2655  if (!variable_.empty()) {
2656  sout << variable_.c_str() << " = " << buf << "\n";
2657  } else if (pval_) {
2658  sout << "// " << pval_ << " set to " << buf << "\n";
2659  }
2660  auto str = sout.str();
2661  hoc_audit_command(str.c_str());
2662  if (send_) {
2663  send_->audit();
2664  }
2665 }
2666 
2667 double OcSlider::slider_val() {
2668  double x = double(bv_->cur_lower(Dimension_X));
2669  x = MyMath::anint(x / resolution_);
2670  x = x * resolution_;
2671  if (x > bv_->upper(Dimension_X) - resolution_ / 2.)
2672  x = bv_->upper(Dimension_X);
2673  if (x < bv_->lower(Dimension_X) + resolution_ / 2.)
2674  x = bv_->lower(Dimension_X);
2675 
2676  return x;
2677 }
2678 
2680  Coord x = 0.;
2681  if (pyvar_) {
2683  } else if (pval_) {
2684  x = Coord(*pval_);
2685  } else {
2686  pval_ = {};
2687  return;
2688  }
2689  if (x != bv_->cur_lower(Dimension_X)) {
2690  bool old = scrolling_;
2691  scrolling_ = true;
2692  bv_->scroll_to(Dimension_X, x);
2693  scrolling_ = old;
2694  }
2695 }
2696 void OcSlider::check_pointer(void* v, int size) {
2697  auto* const pval_raw = static_cast<double const*>(pval_);
2698  if (pval_raw) {
2699  auto* const pd = static_cast<double*>(v);
2700  if (size == 1) {
2701  if (pd != pval_raw)
2702  return;
2703  } else {
2704  if (pval_raw < pd || pval_raw >= pd + size)
2705  return;
2706  }
2707  pval_ = {};
2708  }
2709 }
2710 void OcSlider::data_path(HocDataPaths* hdp, bool append) {
2711  if (variable_.empty() && pval_) {
2712  auto* const pval_raw = static_cast<double*>(pval_);
2713  if (append) {
2714  hdp->append(pval_raw);
2715  } else {
2716  variable_ = hdp->retrieve(pval_raw);
2717  }
2718  }
2719 }
2720 void OcSlider::write(std::ostream& o) {
2721  if (!variable_.empty()) {
2722  char buf[256];
2723  if (send_) {
2724  Sprintf(buf,
2725  "xslider(&%s, %g, %g, \"%s\", %d, %d)",
2726  variable_.c_str(),
2727  bv_->lower(Dimension_X),
2728  bv_->upper(Dimension_X),
2729  hideQuote(send_->name()),
2730  vert_,
2731  slow_);
2732  } else {
2733  Sprintf(buf,
2734  "xslider(&%s, %g, %g, %d, %d)",
2735  variable_.c_str(),
2736  bv_->lower(Dimension_X),
2737  bv_->upper(Dimension_X),
2738  vert_,
2739  slow_);
2740  }
2741  o << buf << std::endl;
2742  }
2743 }
2744 
2745 
2746 // Button with state
2747 
2749  const char* name,
2750  const char* action,
2751  int style,
2752  Object* pyvar,
2753  Object* pyact) {
2754  HocAction* act = new HocAction(action, pyact);
2755  Button* button;
2756  if (style == HocStateButton::PALETTE) {
2757  button = WidgetKit::instance()->palette_button(name, act);
2758  } else {
2759  button = WidgetKit::instance()->check_box(name, act);
2760  }
2761  box()->append(button);
2762  HocStateButton* hsb = new HocStateButton(pd, name, button, act, style, hoc_item(), pyvar);
2763  item_append(hsb);
2764  elist_.push_back(hsb);
2765  hsb->ref();
2766 }
2767 
2768 declareActionCallback(HocStateButton);
2769 implementActionCallback(HocStateButton);
2770 
2772  const char* text,
2773  Button* button,
2774  HocAction* action,
2775  int style,
2776  HocItem* hi,
2777  Object* pyvar)
2778  : HocUpdateItem("", hi) {
2779  style_ = style;
2780  pval_ = pd;
2781  pyvar_ = pyvar;
2782  if (pyvar_) {
2783  hoc_obj_ref(pyvar_);
2784  }
2785  name_ = new CopyString(text);
2786  action_ = action;
2787  action->hoc_item(this);
2788  Resource::ref(action_);
2789 
2790  b_ = button;
2791  // b_->ref(); // mutually reffed so don't
2792  b_->action(new ActionCallback(HocStateButton)(this, &HocStateButton::button_action));
2793 }
2794 
2795 
2797  if (pyvar_) {
2799  }
2800  delete name_;
2802  // only come here when b is being deleted
2803  // Resource::unref(b_);
2804  // delete b_;
2805 }
2806 
2807 void HocStateButton::print(Printer* pr, const Allocation& a) const {
2808  Glyph* l = WidgetKit::instance()->label(name_->string());
2809  l->ref();
2810  l->print(pr, a);
2811  l->unref();
2812 }
2813 
2814 bool HocStateButton::chosen() {
2815  return b_->state()->test(TelltaleState::is_chosen);
2816 }
2817 
2819  if (Oc::helpmode()) {
2820  help();
2821  b_->state()->set(TelltaleState::is_chosen, !chosen());
2822  return;
2823  }
2824  if (pyvar_) {
2825  TelltaleState* t = b_->state();
2826  if (chosen() != bool(neuron::python::methods.guigetval(pyvar_))) {
2828  }
2829  } else if (pval_) {
2830  TelltaleState* t = b_->state();
2831  if (chosen() != bool(*pval_)) {
2832  *pval_ = double(chosen());
2833  }
2834  }
2835  if (action_) {
2836  action_->execute();
2837  } else {
2838  Oc oc;
2839  oc.notify();
2840  }
2841 }
2842 
2843 
2844 // set state of button to match variable
2846  double x = 0.;
2847  if (pyvar_) {
2849  } else if (pval_) {
2850  x = *pval_;
2851  } else { // not (no longer) valid
2852  pval_ = {};
2853  b_->state()->set(TelltaleState::is_enabled_visible_active_chosen, false);
2854  return;
2855  }
2856  if (x) {
2857  b_->state()->set(TelltaleState::is_chosen, true);
2858  } else {
2859  b_->state()->set(TelltaleState::is_chosen, false);
2860  }
2861 }
2862 
2863 void HocStateButton::check_pointer(void* v, int size) {
2864  auto* const pval_raw = static_cast<double const*>(pval_);
2865  if (pval_raw) {
2866  auto* const pd = static_cast<double*>(v);
2867  if (size == 1) {
2868  if (pd != pval_raw)
2869  return;
2870  } else {
2871  if (pval_raw < pd || pval_raw >= pd + size)
2872  return;
2873  }
2874  pval_ = {};
2875  }
2876 }
2877 
2879  if (variable_.empty() && pval_) {
2880  auto* const pval_raw = static_cast<double*>(pval_);
2881  if (append) {
2882  hdp->append(pval_raw);
2883  } else {
2884  variable_ = hdp->retrieve(pval_raw);
2885  }
2886  }
2887 }
2888 void HocStateButton::write(std::ostream& o) {
2889  if (!variable_.empty()) {
2890  char buf[256];
2891  if (style_ == PALETTE) {
2892  Sprintf(buf,
2893  "xstatebutton(\"%s\",&%s,\"%s\")",
2894  name_->string(),
2895  variable_.c_str(),
2896  hideQuote(action_->name()));
2897  } else {
2898  Sprintf(buf,
2899  "xcheckbox(\"%s\",&%s,\"%s\")",
2900  name_->string(),
2901  variable_.c_str(),
2902  hideQuote(action_->name()));
2903  }
2904  o << buf << std::endl;
2905  }
2906 }
2907 
2908 
2909 // menu item with state
2910 
2911 
2913  const char* name,
2914  const char* action,
2915  Object* pyvar,
2916  Object* pyact) {
2917  MenuItem* mi = WidgetKit::instance()->check_menu_item(name);
2918  HocAction* act = new HocAction(action, pyact);
2919  HocStateMenuItem* hsb = new HocStateMenuItem(pd, name, mi, act, hoc_item(), pyvar);
2920  item_append(hsb);
2921  elist_.push_back(hsb);
2922  hsb->ref();
2923  return mi;
2924 }
2925 
2926 
2927 declareActionCallback(HocStateMenuItem);
2928 implementActionCallback(HocStateMenuItem);
2929 
2931  const char* text,
2932  MenuItem* mi,
2933  HocAction* action,
2934  HocItem* hi,
2935  Object* pyvar)
2936  : HocUpdateItem("", hi) {
2937  pval_ = pd;
2938  pyvar_ = pyvar;
2939  if (pyvar_) {
2940  hoc_obj_ref(pyvar_);
2941  }
2942  name_ = new CopyString(text);
2943  action_ = action;
2944  action->hoc_item(this);
2945  Resource::ref(action_);
2946 
2947  b_ = mi;
2948  // Resource::ref(b_);
2949  b_->action(new ActionCallback(HocStateMenuItem)(this, &HocStateMenuItem::button_action));
2950 }
2951 
2952 
2954  delete name_;
2955  if (pyvar_) {
2957  }
2959  // Resource::unref(b_);
2960  // delete b_;
2961 }
2962 
2963 void HocStateMenuItem::print(Printer* pr, const Allocation& a) const {
2964  Glyph* l = WidgetKit::instance()->label(name_->string());
2965  l->ref();
2966  l->print(pr, a);
2967  l->unref();
2968 }
2969 
2970 bool HocStateMenuItem::chosen() {
2971  return b_->state()->test(TelltaleState::is_chosen);
2972 }
2973 
2974 
2976  if (Oc::helpmode()) {
2977  help();
2978  b_->state()->set(TelltaleState::is_chosen, !chosen());
2979  return;
2980  }
2981  if (pval_) {
2982  TelltaleState* t = b_->state();
2983  if (chosen() != bool(*pval_)) {
2984  *pval_ = double(chosen());
2985  }
2986  }
2987  if (pyvar_) {
2988  TelltaleState* t = b_->state();
2989  if (chosen() != bool(neuron::python::methods.guigetval(pyvar_))) {
2991  }
2992  }
2993  if (action_) {
2994  action_->execute();
2995  } else {
2996  Oc oc;
2997  oc.notify();
2998  }
2999 }
3000 
3001 
3002 // set state of button to match variable
3004  double x = 0.;
3005  if (pyvar_) {
3007  } else if (pval_) {
3008  x = *pval_;
3009  } else { // not (no longer) valid
3010  pval_ = {};
3011  b_->state()->set(TelltaleState::is_enabled_visible_active_chosen, false);
3012  return;
3013  }
3014  if (x) {
3015  b_->state()->set(TelltaleState::is_chosen, true);
3016  } else {
3017  b_->state()->set(TelltaleState::is_chosen, false);
3018  }
3019 }
3020 
3021 void HocStateMenuItem::check_pointer(void* v, int size) {
3022  auto* const pval_raw = static_cast<double const*>(pval_);
3023  if (pval_raw) {
3024  auto* const pd = static_cast<double*>(v);
3025  if (size == 1) {
3026  if (pd != pval_raw)
3027  return;
3028  } else {
3029  if (pval_raw < pd || pval_raw >= pd + size)
3030  return;
3031  }
3032  pval_ = {};
3033  }
3034 }
3035 
3037  if (variable_.empty() && pval_) {
3038  auto* const pval_raw = static_cast<double*>(pval_);
3039  if (append) {
3040  hdp->append(pval_raw);
3041  } else {
3042  variable_ = hdp->retrieve(pval_raw);
3043  }
3044  }
3045 }
3046 
3047 void HocStateMenuItem::write(std::ostream& o) {
3048  if (!variable_.empty()) {
3049  char buf[256];
3050  Sprintf(buf,
3051  "xcheckbox(\"%s\",&%s,\"%s\")",
3052  name_->string(),
3053  variable_.c_str(),
3054  hideQuote(action_->name()));
3055 
3056  o << buf << std::endl;
3057  }
3058 }
3059 
3060 
3061 #endif // HAVE_IV
3062 static void* vfe_cons(Object*) {
3063  TRY_GUI_REDIRECT_OBJ("ValueFieldEditor", NULL);
3064 #if HAVE_IV
3065  if (hoc_usegui) {
3066  if (!ifarg(2) || hoc_is_str_arg(2)) {
3067  hoc_xvalue_helper();
3068  } else {
3069  hoc_xpvalue_helper();
3070  }
3071  HocValEditor* fe = last_fe_constructed_;
3072  Resource::ref(fe);
3073  return (void*) fe;
3074  }
3075 #endif
3076  return 0;
3077 }
3078 static void vfe_destruct(void* v) {
3079  TRY_GUI_REDIRECT_NO_RETURN("~ValueFieldEditor", v);
3080 #if HAVE_IV
3081  if (hoc_usegui) {
3082  HocValEditor* fe = (HocValEditor*) v;
3083  Resource::unref(fe);
3084  }
3085 #endif
3086 }
3087 static double vfe_default(void* v) {
3088  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("ValueFieldEditor.default", v);
3089  double x = 0.;
3090 #if HAVE_IV
3091  if (hoc_usegui) {
3092  if (((HocValEditor*) v)->hoc_default_val_editor()) {
3094  dfe->deflt(x = dfe->get_val());
3095  }
3096  }
3097 #endif
3098  return x;
3099 }
3100 static Member_func vfe_members[] = {{"default", vfe_default}, {nullptr, nullptr}};
3102  class2oc("ValueFieldEditor", vfe_cons, vfe_destruct, vfe_members, nullptr, nullptr);
3103 }
#define InputHandler
Definition: _defines.h:149
#define Patch
Definition: _defines.h:199
#define TelltaleState
Definition: _defines.h:293
#define Background
Definition: _defines.h:41
#define Color
Definition: _defines.h:72
#define Menu
Definition: _defines.h:174
#define ScrollBox
Definition: _defines.h:250
#define Border
Definition: _defines.h:47
#define Canvas
Definition: _defines.h:63
#define Style
Definition: _defines.h:278
#define Coord
Definition: _defines.h:17
#define Adjustable
Definition: _defines.h:27
#define Hit
Definition: _defines.h:145
#define WidgetKit
Definition: _defines.h:328
#define Printer
Definition: _defines.h:209
#define MonoGlyph
Definition: _defines.h:179
#define GlyphIndex
Definition: _defines.h:21
#define MenuItem
Definition: _defines.h:177
#define Event
Definition: _defines.h:105
#define Button
Definition: _defines.h:60
#define EventButton
Definition: _defines.h:19
#define PolyGlyph
Definition: _defines.h:205
#define TelltaleGroup
Definition: _defines.h:292
#define Stepper
Definition: _defines.h:272
#define LayoutKit
Definition: _defines.h:159
#define Action
Definition: _defines.h:25
#define Glyph
Definition: _defines.h:130
static double restore(void *v)
Coord right() const
Definition: geometry.h:289
Coord top() const
Definition: geometry.h:291
Coord left() const
Definition: geometry.h:288
Coord bottom() const
Definition: geometry.h:290
virtual Coord lower(DimensionName) const
virtual void scroll_to(DimensionName, Coord position)
virtual Coord cur_lower(DimensionName) const
virtual Coord upper(DimensionName) const
virtual void focus_out()
virtual void release(const Event &)
virtual const String * text() const
virtual void selection(int &start, int &index) const
virtual void press(const Event &)
virtual void keystroke(const Event &)
virtual void drag(const Event &)
virtual InputHandler * focus_in()
virtual void field(const char *)
virtual ~HocAction()
const char * name() const
HocAction(const char *action, Object *pyact=NULL)
virtual void help()
HocItem * hi_
Definition: xmenu.h:224
virtual void execute()
void hoc_item(HocItem *)
HocCommand * action_
Definition: xmenu.h:223
virtual void audit()
Definition: objcmd.cpp:81
int execute(bool notify=true)
Definition: objcmd.cpp:94
const char * name()
Definition: objcmd.cpp:73
void append(double *)
Definition: datapath.cpp:84
std::string retrieve(double *) const
Definition: datapath.cpp:103
void search()
Definition: datapath.cpp:92
void deflt(double)
HocDefaultValEditor(const char *name, const char *variable, ValEdLabel *, HocValAction *, neuron::container::data_handle< double > pd={}, bool canrun=false, HocItem *parent=NULL, Object *pyvar=NULL)
virtual ~HocDefaultValEditor()
double most_recent_
Definition: xmenu.h:369
Button * checkbox()
Definition: xmenu.h:362
HocValStepper * vs_
Definition: xmenu.h:370
virtual void updateField()
Button * checkbox_
Definition: xmenu.h:367
void def_change(float, float)
HocEditorForItem(HocValEditor *, HocValAction *)
virtual void release(const Event &)
virtual void val_inc(const Event &)
virtual void press(const Event &)
virtual void keystroke(const Event &)
virtual ~HocEditorForItem()
virtual void focus_out()
virtual void drag(const Event &)
HocValEditor * hve_
Definition: xmenu.h:253
virtual InputHandler * focus_in()
Definition: xmenu.h:128
virtual void write(std::ostream &)
CopyString str_
Definition: xmenu.h:138
HocItem * help_parent_
Definition: xmenu.h:139
virtual void help_parent(HocItem *)
HocItem(const char *, HocItem *parent=NULL)
virtual ~HocItem()
virtual void help(const char *childpath=NULL)
const char * getStr()
HocLabel(const char *)
virtual ~HocLabel()
virtual void write(std::ostream &)
virtual ~HocMenuAction()
HocPanel * hp_
Definition: xmenu.h:235
virtual void execute()
HocMenuAction(const char *action, Object *pyact, HocMenu *)
HocMenu * hm_
Definition: xmenu.h:234
Definition: xmenu.h:162
HocMenu(const char *, Menu *, MenuItem *, HocItem *parent=NULL, bool add2menubar=false)
virtual ~HocMenu()
virtual void write(std::ostream &)
virtual Menu * menu()
Definition: xmenu.h:167
bool add2menubar_
Definition: xmenu.h:177
Menu * menu_
Definition: xmenu.h:176
virtual MenuItem * item()
Definition: xmenu.h:170
Definition: xmenu.h:45
void label(const char *)
void item_append(HocItem *)
void notifyHocValue()
PolyGlyph * box()
void data_path(HocDataPaths *, bool)
void valueEd(const char *prompt, const char *variable, const char *action=0, bool canrun=false, neuron::container::data_handle< double > pd={}, bool deflt=false, bool keep_updated=false, HocSymExtension *extra=NULL, Object *pyvar=NULL, Object *pyact=NULL)
virtual void map_window(int scroll=-1)
HocMenu * menu(const char *name, bool add2menubar=false)
static std::vector< HocUpdateItem * > * update_list_
Definition: xmenu.h:123
void var_label(char **, Object *pyvar=NULL)
virtual HocItem * hoc_item()
static void save_all(std::ostream &)
std::vector< HocItem * > ilist_
Definition: xmenu.h:122
static void paneltool(const char *name, const char *procname, const char *action, ScenePicker *, Object *pycallback=NULL, Object *pyselact=NULL)
MenuItem * menuItem(const char *name, const char *action, bool activate=false, Object *pyact=0)
void slider(neuron::container::data_handle< double >, float low=0, float high=100, float resolution=1, int steps=10, const char *send_cmd=NULL, bool vert=false, bool slow=false, Object *pyvar=NULL, Object *pysend=NULL)
static void keep_updated()
virtual void save(std::ostream &)
std::vector< HocUpdateItem * > elist_
Definition: xmenu.h:121
void stateButton(neuron::container::data_handle< double > pd, const char *name, const char *action, int style, Object *pyvar=NULL, Object *pyact=NULL)
bool horizontal_
Definition: xmenu.h:124
HocPanel(const char *name, bool horizontal=false)
virtual void write(std::ostream &)
void check_valid_pointers(void *, int)
const char * getName()
InputHandler * ih_
Definition: xmenu.h:125
Coord bottom_
Definition: xmenu.h:106
virtual ~HocPanel()
void pushButton(const char *name, const char *action, bool activate=false, Object *pyact=0)
PolyGlyph * box_
Definition: xmenu.h:120
Coord left_
Definition: xmenu.h:106
MenuItem * menuStateItem(neuron::container::data_handle< double > pd, const char *name, const char *action, Object *pyvar=NULL, Object *pyact=NULL)
void itemAppend(const char *)
virtual void write(std::ostream &)
HocAction * a_
Definition: xmenu.h:149
HocPushButton(const char *, HocAction *, HocItem *parent=NULL)
virtual ~HocPushButton()
HocRadioAction * a_
Definition: xmenu.h:159
virtual void write(std::ostream &)
HocRadioButton(const char *, HocRadioAction *, HocItem *parent=NULL)
virtual ~HocRadioButton()
void button_action()
virtual void update_hoc_item()
virtual ~HocStateButton()
neuron::container::data_handle< double > pval_
Definition: xmenu.h:479
HocAction * action_
Definition: xmenu.h:482
Button * b_
Definition: xmenu.h:481
virtual void data_path(HocDataPaths *, bool)
virtual void check_pointer(void *, int)
std::string variable_
Definition: xmenu.h:477
CopyString * name_
Definition: xmenu.h:478
virtual void print(Printer *, const Allocation &) const
virtual void write(std::ostream &)
int style_
Definition: xmenu.h:476
HocStateButton(neuron::container::data_handle< double >, const char *, Button *, HocAction *, int, HocItem *parent=NULL, Object *pyvar=NULL)
Object * pyvar_
Definition: xmenu.h:480
MenuItem * b_
Definition: xmenu.h:510
virtual void check_pointer(void *, int)
neuron::container::data_handle< double > pval_
Definition: xmenu.h:508
std::string variable_
Definition: xmenu.h:506
virtual void write(std::ostream &)
HocStateMenuItem(neuron::container::data_handle< double >, const char *, MenuItem *, HocAction *, HocItem *parent=NULL, Object *pyvar=NULL)
virtual void data_path(HocDataPaths *, bool)
virtual void update_hoc_item()
HocAction * action_
Definition: xmenu.h:511
CopyString * name_
Definition: xmenu.h:507
Object * pyvar_
Definition: xmenu.h:509
virtual void print(Printer *, const Allocation &) const
virtual ~HocStateMenuItem()
virtual void update_hoc_item()
HocUpdateItem(const char *, HocItem *parent=NULL)
virtual void check_pointer(void *, int vector_size)
virtual ~HocUpdateItem()
virtual void data_path(HocDataPaths *, bool)
FieldSEditorAction * fea_
Definition: xmenu.h:408
void accept(FieldSEditor *)
HocValAction(const char *action, Object *pyact=0)
HocValEditor * fe_
Definition: xmenu.h:404
virtual ~HocValAction()
void execute()
void setFieldSEditor(HocValEditor *)
HocValEditor(const char *name, const char *variable, ValEdLabel *, HocValAction *, neuron::container::data_handle< double > pd={}, bool canrun=false, HocItem *parent=NULL, Object *pvar=NULL)
Object * pyvar_
Definition: xmenu.h:338
neuron::container::data_handle< double > pval_
Definition: xmenu.h:335
HocAction * action_
Definition: xmenu.h:333
virtual void updateField()
virtual void write(std::ostream &)
virtual int hoc_default_val_editor()
Definition: xmenu.h:314
virtual void update_hoc_item()
virtual void print(Printer *, const Allocation &) const
double get_val()
virtual ~HocValEditor()
bool canrun_
Definition: xmenu.h:332
const char * variable() const
virtual void exec_action()
virtual Stepper * stepper()
Definition: xmenu.h:303
ValEdLabel * prompt_
Definition: xmenu.h:336
virtual void setlimits(float *)
void evalField()
virtual void data_path(HocDataPaths *, bool)
void set_val(double)
bool active_
Definition: xmenu.h:331
std::string variable_
Definition: xmenu.h:334
FieldSEditor * field_editor()
Definition: xmenu.h:300
virtual void check_pointer(void *, int)
float * domain_limits_
Definition: xmenu.h:337
virtual double domain_limits(double)
HocEditorForItem * fe_
Definition: xmenu.h:330
bool active()
Definition: xmenu.h:323
virtual ~HocValEditorKeepUpdated()
HocValEditorKeepUpdated(const char *name, const char *variable, ValEdLabel *, HocValAction *, neuron::container::data_handle< double >, HocItem *parent=NULL, Object *pyvar=NULL)
virtual void write(std::ostream &)
float inc_
Definition: xmenu.h:284
HocValStepper(HocValEditor *, Glyph *, Style *, TelltaleState *)
virtual void menu_up(Event &)
virtual ~HocValStepper()
double default_inc()
static HocValStepper * instance(HocValEditor *)
virtual void release(const Event &)
float default_inc_
Definition: xmenu.h:283
HocValEditor * hve_
Definition: xmenu.h:285
bool geometric_
Definition: xmenu.h:281
virtual void adjust()
virtual void press(const Event &)
static StepperMenu * menu_
Definition: xmenu.h:286
int steps_
Definition: xmenu.h:282
static StepperMenu * menu()
Definition: xmenu.h:268
virtual void data_path(HocDataPaths *, bool)
std::string variable_
Definition: xmenu.h:209
virtual ~HocVarLabel()
Object * pyvar_
Definition: xmenu.h:210
char ** cpp_
Definition: xmenu.h:207
char * cp_
Definition: xmenu.h:208
virtual void write(std::ostream &)
Patch * p_
Definition: xmenu.h:206
HocVarLabel(char **, PolyGlyph *, Object *pyvar=NULL)
virtual void check_pointer(void *, int)
virtual void update_hoc_item()
static MenuItem * radio_menu_item(TelltaleGroup *, const char *)
static MenuItem * menu_item(const char *)
static double anint(double)
Definition: mymath.cpp:81
static double resolution(double)
virtual PrintableWindow * make_window(Coord left=-1, Coord bottom=-1, Coord width=-1, Coord height=-1)
virtual PrintableWindow * window()
virtual bool has_window()
Definition: ivoc.h:36
static void help(const char *)
void notify()
int run(int argc, const char **argv)
void notify_freed(void(*pf)(void *, int))
void notifyHocValue()
static bool helpmode()
Definition: ivoc.h:70
virtual void write(std::ostream &)
void audit()
virtual void data_path(HocDataPaths *, bool)
bool vert_
Definition: xmenu.h:449
std::string variable_
Definition: xmenu.h:447
neuron::container::data_handle< double > pval_
Definition: xmenu.h:445
virtual double slider_val()
float resolution_
Definition: xmenu.h:442
virtual void update(Observable *)
bool slow_
Definition: xmenu.h:450
OcSlider(neuron::container::data_handle< double >, float low, float high, float resolution, int nsteps, const char *send_cmd, bool vert, bool slow=false, Object *pyvar=NULL, Object *pysend=NULL)
BoundedValue * bv_
Definition: xmenu.h:443
Object * pyvar_
Definition: xmenu.h:446
virtual void update_hoc_item()
virtual void check_pointer(void *, int vector_size)
Adjustable * adjustable()
bool scrolling_
Definition: xmenu.h:448
virtual ~OcSlider()
HocCommand * send_
Definition: xmenu.h:444
void save()
Definition: oc2iv.cpp:53
void restore()
Definition: oc2iv.cpp:71
virtual bool event(Event &)
virtual void map()
void natural(Coord)
Definition: geometry.h:231
void require_x(const Requirement &)
Definition: geometry.h:243
const Requirement & x_requirement() const
Definition: geometry.h:245
void require_y(const Requirement &)
Definition: geometry.h:244
virtual void ref() const
Definition: resource.cpp:42
virtual void unref() const
Definition: resource.cpp:47
MenuItem * add_radio_menu(const char *, Action *, Menu *=NULL)
Button * radio_button(const char *, Action *)
void class2oc(const char *, ctor_f *cons, dtor_f *destruct, Member_func *, Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1631
char * gargstr(int narg)
Definition: code2.cpp:227
#define fil
Definition: coord.h:41
#define cnt
Definition: tqueue.hpp:44
#define key
Definition: tqueue.hpp:45
#define pval
Definition: md1redef.h:40
#define v
Definition: md1redef.h:11
#define i
Definition: md1redef.h:19
#define b_(arg)
Definition: crout.hpp:137
#define y_(arg)
Crout matrix decomposition : Forward/Backward substitution.
Definition: crout.hpp:136
Symbol * hoc_get_last_pointer_symbol()
Definition: code.cpp:1789
static double active(void *v)
Definition: cvodeobj.cpp:192
void erase_first(T &&iterable, value_type &&value)
Definition: enumerate.h:22
constexpr auto reverse(T &&iterable)
Definition: enumerate.h:62
static HocParmLimits limits[]
Definition: extcelln.cpp:36
double chkarg(int, double low, double high)
Definition: code2.cpp:626
#define FieldSEditorCallback(T)
Definition: field.h:57
#define declareFieldSEditorCallback(T)
Definition: field.h:62
#define implementFieldSEditorCallback(T)
Definition: field.h:80
@ Dimension_X
Definition: geometry.h:39
static RNG::key_type k
Definition: nrnran123.cpp:9
char buf[512]
Definition: init.cpp:13
int hoc_is_object_arg(int narg)
Definition: code.cpp:876
void hoc_audit_command(const char *buf)
Definition: audit.cpp:122
Symbol * hoc_get_symbol(const char *var)
Definition: code.cpp:1768
neuron::container::data_handle< double > hoc_val_handle(std::string_view s)
Definition: code2.cpp:715
void hoc_ret()
double check_domain_limits(float *limits, double val)
Definition: code2.cpp:116
int hoc_is_str_arg(int narg)
Definition: code.cpp:872
double hoc_ac_
Definition: hoc_init.cpp:222
void hoc_obj_ref(Object *obj)
Definition: hoc_oop.cpp:1844
int hoc_is_pdouble_arg(int narg)
Definition: code.cpp:868
void hoc_obj_unref(Object *obj)
Definition: hoc_oop.cpp:1881
char ** hoc_pgargstr(int narg)
Definition: code.cpp:1623
#define TRY_GUI_REDIRECT_ACTUAL_DOUBLE(name, obj)
Definition: gui-redirect.h:55
#define TRY_GUI_REDIRECT_DOUBLE(name, obj)
Definition: gui-redirect.h:47
#define TRY_GUI_REDIRECT_NO_RETURN(name, obj)
Definition: gui-redirect.h:40
#define TRY_GUI_REDIRECT_OBJ(name, obj)
Definition: gui-redirect.h:10
#define TRY_GUI_REDIRECT_DOUBLE_SEND_STRREF(name, obj)
Definition: gui-redirect.h:79
static int c
Definition: hoc.cpp:169
int hoc_usegui
Definition: hoc.cpp:121
#define assert(ex)
Definition: hocassrt.h:24
#define getarg
Definition: hocdec.h:17
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
int units_on_flag_
Definition: code2.cpp:20
#define Session
Definition: ivocmain.cpp:9
void hoc_notify_value()
Definition: ivocmain.cpp:764
void hoc_pushx(double)
Definition: code.cpp:779
Symbol * lookup(const char *)
exp
Definition: extdef.h:5
pow
Definition: extdef.h:4
void init()
Definition: init.cpp:141
const char * name
Definition: init.cpp:16
void append(Item *ql, Item *q)
Definition: list.cpp:289
void update(NrnThread *_nt)
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
impl_ptrs methods
Collection of pointers to functions with python-version-specific implementations.
Definition: nrnpy.cpp:21
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Definition: wrap_sprintf.h:14
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
size_t p
s
Definition: multisend.cpp:521
static int active_
Definition: netpar.cpp:204
int ifarg(int)
Definition: code.cpp:1607
short index
Definition: cabvars.h:11
static int guigetstr(Object *ho, char **cpp)
Definition: nrnpy_p2h.cpp:488
static double guigetval(Object *ho)
Definition: nrnpy_p2h.cpp:468
static void pr(N_Vector x)
static realtype a_
static N_Vector x_
#define CChar
Definition: oc2iv.h:9
void hoc_ivvarlabel(char **, Object *pyvar=0)
void hoc_ivvalue(CChar *name, CChar *variable, bool deflt=false, Object *pyvar=0)
void hoc_ivpvalue(CChar *name, neuron::container::data_handle< double >, bool deflt=false, HocSymExtension *extra=NULL)
void hoc_ivpvaluerun(CChar *name, neuron::container::data_handle< double >, CChar *action, bool deflt=false, bool canrun=false, HocSymExtension *extra=NULL)
void hoc_ivbutton(CChar *name, CChar *action, Object *pyact=0)
void hoc_ivstatebutton(neuron::container::data_handle< double >, CChar *name, CChar *action, int style, Object *pyvar=0, Object *pyact=0)
void hoc_ivmenu(CChar *, bool add2menubar=false)
void hoc_ivvalue_keep_updated(CChar *name, CChar *variable, Object *pyvar=0)
void hoc_ivradiobutton(CChar *name, CChar *action, bool activate=false, Object *pyact=0)
void hoc_ivpanelmap(int scroll=-1)
void hoc_ivslider(neuron::container::data_handle< double >, float low=0, float high=100, float resolution=1, int steps=10, const char *send_cmd=NULL, bool vert=false, bool slow=false, Object *pyvar=0, Object *pyact=0)
void hoc_ivfixedvalue(CChar *name, CChar *variable, bool deflt=false, bool usepointer=false)
void hoc_ivvaluerun(CChar *name, CChar *variable, CChar *action, bool deflt=false, bool canrun=false, bool usepointer=false, Object *pyvar=0, Object *pyact=0)
void hoc_ivvaluerun_ex(CChar *name, CChar *var, neuron::container::data_handle< double > pvar, Object *pyvar, CChar *action, Object *pyact, bool deflt=false, bool canrun=false, bool usepointer=false, HocSymExtension *extra=NULL)
void hoc_ivpanel(CChar *, bool h=false)
void hoc_ivlabel(CChar *)
void hoc_ivvarmenu(CChar *, CChar *, bool add2menubar=false, Object *pyvar=NULL)
static double remove(void *v)
Definition: ocdeck.cpp:205
void handle_old_focus()
void hoc_xpanel()
Definition: ocnoiv1.cpp:57
void hoc_xvalue()
Definition: ocnoiv1.cpp:52
void hoc_xbutton()
Definition: ocnoiv1.cpp:32
void hoc_xfixedvalue()
Definition: ocnoiv1.cpp:67
void hoc_xlabel()
Definition: ocnoiv1.cpp:27
void hoc_xstatebutton()
Definition: ocnoiv1.cpp:42
void hoc_xmenu()
Definition: ocnoiv1.cpp:47
void hoc_xpvalue()
Definition: ocnoiv1.cpp:22
void hoc_xvarlabel()
Definition: ocnoiv1.cpp:72
void hoc_xslider()
Definition: ocnoiv1.cpp:79
void hoc_xradiobutton()
Definition: ocnoiv1.cpp:62
void hoc_xcheckbox()
Definition: ocnoiv1.cpp:37
#define text
Definition: plot.cpp:60
static void activate()
#define NULL
Definition: spdefs.h:105
static int equal(const char *c1, const char *c2)
Definition: units.cpp:776
float * parmlimits
Definition: hocdec.h:98
char * units
Definition: hocdec.h:99
Definition: hocdec.h:173
Definition: model.h:47
HocSymExtension * extra
Definition: hocdec.h:131
int(* guigetstr)(Object *, char **)
Definition: nrnpy.h:31
double(* guigetval)(Object *)
Definition: nrnpy.h:32
void(* guisetval)(Object *, double)
Definition: nrnpy.h:36
bool boolean_dialog(const char *label, const char *accept, const char *cancel, Window *w=NULL, Coord x=400., Coord y=400.)
static Member_func vfe_members[]
Definition: xmenu.cpp:3100
static void vfe_destruct(void *v)
Definition: xmenu.cpp:3078
static double vfe_default(void *v)
Definition: xmenu.cpp:3087
void ValueFieldEditor_reg()
Definition: xmenu.cpp:3101
static void * vfe_cons(Object *)
Definition: xmenu.cpp:3062