NEURON
utility.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #if HAVE_IV // to end of file
3 
4 #include <string.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <fstream>
8 
9 #include <InterViews/dialog.h>
10 #include <InterViews/session.h>
11 #include <InterViews/display.h>
12 #include <InterViews/action.h>
13 #include <InterViews/layout.h>
14 #include <InterViews/style.h>
15 #include <InterViews/hit.h>
16 #include <InterViews/event.h>
17 #include <IV-look/kit.h>
18 #include <IV-look/dialogs.h>
19 #include <OS/string.h>
20 
21 #include "graph.h"
22 #include "utility.h"
23 #include "oc2iv.h"
24 #include "ivoc.h"
25 
26 bool nrn_spec_dialog_pos(Coord& x, Coord& y) {
27  Style* s = Session::instance()->style();
28  if (s->value_is_on("dialog_spec_position")) {
29  s->find_attribute("dialog_left_position", x);
30  s->find_attribute("dialog_bottom_position", y);
31  return true;
32  }
33  return false;
34 }
35 
36 bool oc_post_dialog(Dialog* d, Coord x, Coord y) {
37  if (nrn_spec_dialog_pos(x, y)) {
38  return d->post_at_aligned(x, y, 0.0, 0.0);
39  }
40  if (x != 400. || y != 400.) {
41  return d->post_at_aligned(x, y, .5, .5);
42  } else {
43  Display* dis = Session::instance()->default_display();
44  return d->post_at_aligned(dis->width() / 2, dis->height() / 2, .5, .5);
45  }
46 }
47 
48 bool ok_to_write(const String& s, Window* w) {
49  return ok_to_write(s.string(), w);
50 }
51 bool ok_to_read(const String& s, Window* w) {
52  return ok_to_read(s.string(), w);
53 }
54 
55 class OcGlyphDialog: public Dialog {
56  public:
57  OcGlyphDialog(Glyph*, Style*);
58  virtual ~OcGlyphDialog();
59  virtual void pick(Canvas*, const Allocation&, int depth, Hit&);
60 };
61 
62 /*static*/ class DialogAction: public Action {
63  public:
64  DialogAction(Dialog*, bool);
65  virtual ~DialogAction();
66  virtual void execute() {
67  d_->dismiss(accept_);
68  }
69 
70  private:
71  Dialog* d_;
72  bool accept_;
73 };
74 DialogAction::DialogAction(Dialog* d, bool accept) {
75  accept_ = accept;
76  d_ = d;
77 }
78 DialogAction::~DialogAction() {
79  // printf("~DialogAction\n");
80 }
81 
82 bool boolean_dialog(const char* label,
83  const char* accept,
84  const char* cancel,
85  Window* w,
86  Coord x,
87  Coord y) {
88  WidgetKit& k = *WidgetKit::instance();
89  LayoutKit& l = *LayoutKit::instance();
90  PolyGlyph* vbox = l.vbox();
91  bool ok;
92  Dialog* d = new Dialog(k.outset_frame(l.margin(vbox, 5)), Session::instance()->style());
93  d->ref();
94  vbox->append(l.hcenter(k.inset_frame(l.margin(k.label(label), 10))));
95  vbox->append(l.hcenter(l.hbox(k.push_button(accept, new DialogAction(d, true)),
96  l.hspace(10),
97  k.push_button(cancel, new DialogAction(d, false)))));
98  if (w) {
99  ok = d->post_for(w);
100  } else {
101  ok = oc_post_dialog(d, x, y);
102  }
103  d->unref();
104  return ok;
105 }
106 
107 void continue_dialog(const char* label, Window* w, Coord x, Coord y) {
108  WidgetKit& k = *WidgetKit::instance();
109  LayoutKit& l = *LayoutKit::instance();
110  PolyGlyph* vbox = l.vbox();
111  Dialog* d = new Dialog(k.outset_frame(l.margin(vbox, 5)), Session::instance()->style());
112  d->ref();
113  vbox->append(l.hcenter(k.inset_frame(l.margin(k.label(label), 10))));
114  vbox->append(l.hcenter(k.push_button("Continue", new DialogAction(d, true))));
115  if (w) {
116  d->post_for(w);
117  } else {
118  oc_post_dialog(d, x, y);
119  }
120  d->unref();
121 }
122 
123 static bool ok_if_already_exists(const char* s, Window* w) {
124  char buf[256];
125  Sprintf(buf, "%s already exists: Write?", s);
126  return boolean_dialog(buf, "Go Ahead", "Don't", w);
127 }
128 
129 static void open_fail(const char* s, Window* w, const char* io) {
130  char buf[256];
131  Sprintf(buf, "Couldn't open %s for %sing", s, io);
132  continue_dialog(buf, w);
133 }
134 
135 bool ok_to_write(const char* s, Window* w) {
136  std::filebuf obuf;
137  if (obuf.open(s, std::ios::in)) {
138  obuf.close();
139  if (!ok_if_already_exists(s, w)) {
140  errno = 0;
141  return false;
142  }
143  }
144  if (obuf.open(s, std::ios::app | std::ios::out)) {
145  obuf.close();
146  } else {
147  open_fail(s, w, "writ");
148  errno = 0;
149  return false;
150  }
151  errno = 0;
152  return true;
153 }
154 
155 bool ok_to_read(const char* s, Window* w) {
156  std::filebuf obuf;
157  if (obuf.open(s, std::ios::in)) {
158  obuf.close();
159  errno = 0;
160  return true;
161  } else {
162  open_fail(s, w, "read");
163  errno = 0;
164  return false;
165  }
166 }
167 
168 bool var_pair_chooser(const char* caption, float& x, float& y, Window* w, Coord x2, Coord y2) {
169  char buf[200];
170  float x1 = x, y1 = y;
171  for (;;) {
172  Sprintf(buf, "%g %g", x, y);
173  if (str_chooser(caption, buf, w, x2, y2)) {
174  if (sscanf(buf, "%f%f", &x1, &y1) == 2) {
175  x = x1;
176  y = y1;
177  return true;
178  } else {
179  continue_dialog("Invalid entry: Enter pair of numbers separated by space.", w);
180  }
181  } else {
182  return false;
183  }
184  }
185 }
186 
187 bool str_chooser(const char* caption, char* buf, Window* w, Coord x, Coord y) {
188  WidgetKit& k = *WidgetKit::instance();
189  LayoutKit& l = *LayoutKit::instance();
190  Style* style = new Style(k.style());
191  style->attribute("caption", caption);
192  bool ok;
194  d->ref();
195  if (w) {
196  ok = d->post_for(w);
197  } else {
198  ok = oc_post_dialog(d, x, y);
199  }
200  if (ok) {
201  strcpy(buf, d->text()->string());
202  }
203  d->unref();
204  return ok;
205 }
206 
207 declareFieldEditorCallback(FieldDialog);
208 implementFieldEditorCallback(FieldDialog);
209 
211  : Dialog(g, s) {}
212 
215 }
216 
217 bool FieldDialog::run() {
218  fe_->select(0, fe_->text()->length());
219  return Dialog::run();
220 }
221 void FieldDialog::dismiss(bool accept) {
222  if (accept) {
223  s_ = *fe_->text();
224  } else {
225  fe_->field(s_);
226  }
227  Dialog::dismiss(accept);
228 }
229 
230 FieldDialog* FieldDialog::field_dialog_instance(const char* str, Style* style, Glyph* extra) {
231  Glyph* g;
232  WidgetKit& widgets = *WidgetKit::instance();
233  DialogKit& dialogs = *DialogKit::instance();
234  LayoutKit& layout = *LayoutKit::instance();
235 
236  String caption("");
237  String accept("Accept");
238  String cancel("Cancel");
239  style->find_attribute("caption", caption);
240  style->find_attribute("accept", accept);
241  style->find_attribute("cancel", cancel);
242  PolyGlyph* hb = layout.hbox(5);
243  PolyGlyph* vb = layout.vbox(5);
244  g = widgets.inset_frame(layout.margin(layout.flexible(vb, fil, 0), 10.0));
245 
246  FieldDialog* fd = new FieldDialog(g, style);
247  FieldEditor* fe = dialogs.field_editor(
248  str,
249  style,
250  new FieldEditorCallback(FieldDialog)(fd, &FieldDialog::accept, &FieldDialog::cancel));
251 
252  fd->fe_ = fe;
253  Resource::ref(fe);
254  fd->s_ = *fe->text();
255 
256  vb->append(layout.flexible(widgets.label(caption)));
257  vb->append(layout.vglue(10));
258  vb->append(fd->fe_);
259  if (extra) {
260  vb->append(layout.vglue(10));
261  vb->append(extra);
262  }
263  vb->append(layout.vglue(10));
264  vb->append(hb);
265 
266  hb->append(layout.hglue(20, fil, 20));
267  hb->append(widgets.default_button(accept, new DialogAction(fd, true)));
268  hb->append(layout.hglue(5));
269  hb->append(widgets.push_button(cancel, new DialogAction(fd, false)));
270  hb->append(layout.hglue(20, fil, 20));
271 
272  return fd;
273 }
274 
276  dismiss(true);
277 }
279  dismiss(false);
280 }
281 
282 
283 void hoc_boolean_dialog() {
284  bool b = false;
285  if (auto* const result = neuron::python::methods.try_gui_helper("boolean_dialog", nullptr)) {
286  hoc_ret();
287  hoc_pushx(neuron::python::methods.object_to_double(*result));
288  return;
289  }
290  if (hoc_usegui) {
291  if (ifarg(3)) {
292  b = boolean_dialog(gargstr(1), gargstr(2), gargstr(3));
293  } else {
294  b = boolean_dialog(gargstr(1), "Yes", "No");
295  }
296  }
297  hoc_ret();
298  hoc_pushx(double(b));
299 }
300 void hoc_continue_dialog() {
301  TRY_GUI_REDIRECT_DOUBLE("continue_dialog", NULL);
302  if (hoc_usegui) {
304  }
305  hoc_ret();
306  hoc_pushx(1.);
307 }
308 void hoc_string_dialog() {
309  TRY_GUI_REDIRECT_DOUBLE_SEND_STRREF("string_dialog", NULL);
310  bool b = false;
311  if (hoc_usegui) {
312  char buf[256];
313  Sprintf(buf, "%s", gargstr(2));
314  b = str_chooser(gargstr(1), buf);
315  if (b) {
317  }
318  }
319  hoc_ret();
320  hoc_pushx(double(b));
321 }
322 
323 
324 /*static*/ class LabelChooserAction: public Action {
325  public:
326  LabelChooserAction(GLabel*);
327  virtual ~LabelChooserAction();
328  void state(TelltaleState*);
329  virtual void execute();
330 
331  private:
332  TelltaleState* ts_;
333  GLabel* gl_;
334 };
335 
336 bool Graph::label_chooser(const char* caption, char* buf, GLabel* gl, Coord x, Coord y) {
337  WidgetKit& k = *WidgetKit::instance();
338  LayoutKit& l = *LayoutKit::instance();
339  Style* style = new Style(k.style());
340  style->attribute("caption", caption);
341  bool ok;
342  LabelChooserAction* lca = new LabelChooserAction(gl);
343  Button* b = k.check_box("vfixed", lca);
344  lca->state(b->state());
345 
347 
348  d->ref();
349  ok = oc_post_dialog(d, x, y);
350  if (ok) {
351  strcpy(buf, d->text()->string());
352  }
353  d->unref();
354  return ok;
355 }
356 
357 LabelChooserAction::LabelChooserAction(GLabel* gl) {
358  gl_ = gl;
359  gl->ref();
360  ts_ = NULL;
361 }
362 LabelChooserAction::~LabelChooserAction() {
363  gl_->unref();
364  ts_->unref();
365 }
366 void LabelChooserAction::state(TelltaleState* t) {
367  t->ref();
368  ts_ = t;
369  if (gl_->fixed()) {
370  ts_->set(TelltaleState::is_chosen, false);
371  } else {
372  ts_->set(TelltaleState::is_chosen, true);
373  }
374 }
375 
376 void LabelChooserAction::execute() {
377  if (ts_->test(TelltaleState::is_chosen)) {
378  if (gl_->fixed()) {
379  gl_->vfixed(gl_->scale());
380  }
381  } else {
382  if (!gl_->fixed()) {
383  gl_->fixed(gl_->scale());
384  }
385  }
386 }
387 
388 bool OcGlyph::dialog_dismiss(bool accept) {
389  if (d_) {
390  d_->dismiss(accept);
391  return true;
392  }
393  return false;
394 }
395 
396 bool OcGlyph::dialog(const char* label, const char* accept, const char* cancel) {
397  WidgetKit& k = *WidgetKit::instance();
398  LayoutKit& l = *LayoutKit::instance();
399  PolyGlyph* vbox = l.vbox();
400  bool ok;
401  d_ = new OcGlyphDialog(k.outset_frame(l.margin(vbox, 5)), Session::instance()->style());
402  d_->ref();
403  vbox->append(l.hcenter(l.hflexible(l.margin(k.label(label), 10), fil, 0)));
404  vbox->append(l.hcenter(this));
405  vbox->append(l.hcenter(l.hflexible(l.hbox(k.push_button(accept, new DialogAction(d_, true)),
406  l.hspace(10),
407  k.push_button(cancel, new DialogAction(d_, false))),
408  fil,
409  0)));
411  ok = oc_post_dialog(d_, 400., 400.);
413  d_->unref();
414  d_ = NULL;
415  return ok;
416 }
417 
418 OcGlyphDialog::OcGlyphDialog(Glyph* g, Style* s)
419  : Dialog(g, s) {}
420 OcGlyphDialog::~OcGlyphDialog() {}
421 void OcGlyphDialog::pick(Canvas* c, const Allocation& a, int depth, Hit& h) {
422  const Event* e = h.event();
423  EventType t = (e == NULL) ? Event::undefined : e->type();
424  switch (t) {
425  case Event::key:
426  if (e && inside(*e)) {
427  body()->pick(c, a, depth + 1, h);
428  }
429  break;
430  default:
431  Dialog::pick(c, a, depth, h);
432  }
433 }
434 #endif
#define EventType
Definition: _defines.h:18
#define Window
Definition: _defines.h:330
#define TelltaleState
Definition: _defines.h:293
#define Canvas
Definition: _defines.h:63
#define Style
Definition: _defines.h:278
#define Coord
Definition: _defines.h:17
#define Hit
Definition: _defines.h:145
#define Display
Definition: _defines.h:95
#define Dialog
Definition: _defines.h:92
#define WidgetKit
Definition: _defines.h:328
#define DialogKit
Definition: _defines.h:93
#define Event
Definition: _defines.h:105
#define Button
Definition: _defines.h:60
#define PolyGlyph
Definition: _defines.h:205
#define FieldEditor
Definition: _defines.h:109
#define LayoutKit
Definition: _defines.h:159
#define Action
Definition: _defines.h:25
#define Glyph
Definition: _defines.h:130
FieldDialog(Glyph *, Style *)
virtual void cancel(FieldEditor *)
CopyString s_
Definition: utility.h:36
virtual bool run()
virtual void accept(FieldEditor *)
virtual void dismiss(bool accept)
static FieldDialog * field_dialog_instance(const char *, Style *, Glyph *extra=NULL)
const String * text() const
Definition: utility.h:23
virtual ~FieldDialog()
FieldEditor * fe_
Definition: utility.h:35
Definition: graph.h:418
static bool label_chooser(const char *, char *, GLabel *, Coord x=400., Coord y=400.)
virtual bool dialog(const char *label, const char *accept, const char *cancel)
bool dialog_dismiss(bool b)
Dialog * d_
Definition: ocglyph.h:43
virtual void ref() const
Definition: resource.cpp:42
virtual void unref() const
Definition: resource.cpp:47
char * gargstr(int narg)
Definition: code2.cpp:227
#define fil
Definition: coord.h:41
#define key
Definition: tqueue.hpp:45
static RNG::key_type k
Definition: nrnran123.cpp:9
char buf[512]
Definition: init.cpp:13
void hoc_ret()
void hoc_assign_str(char **cpp, const char *buf)
Definition: code.cpp:2263
char ** hoc_pgargstr(int narg)
Definition: code.cpp:1623
#define TRY_GUI_REDIRECT_DOUBLE(name, obj)
Definition: gui-redirect.h:47
#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
void hoc_pushx(double)
Definition: code.cpp:779
static double inside(void *)
Definition: mymath.cpp:28
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
s
Definition: multisend.cpp:521
int ifarg(int)
Definition: code.cpp:1607
void handle_old_focus()
void hoc_continue_dialog()
Definition: ocnoiv1.cpp:93
void hoc_boolean_dialog()
Definition: ocnoiv1.cpp:84
void hoc_string_dialog()
Definition: ocnoiv1.cpp:98
#define NULL
Definition: spdefs.h:105
bool var_pair_chooser(const char *, float &x, float &y, Window *w=NULL, Coord x1=400., Coord y1=400.)
bool nrn_spec_dialog_pos(Coord &x, Coord &y)
true if Style 'dialog_spec_position: on' and fills x,y with dialog_left_position and dialog_bottom_po...
bool str_chooser(const char *, char *, Window *w=NULL, Coord x=400., Coord y=400.)
bool ok_to_write(const String &, Window *w=NULL)
bool ok_to_read(const String &, Window *w=NULL)
bool boolean_dialog(const char *label, const char *accept, const char *cancel, Window *w=NULL, Coord x=400., Coord y=400.)
void continue_dialog(const char *label, Window *w=NULL, Coord x=400., Coord y=400.)