NEURON
graph.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #include <string.h>
4 #include <stdio.h>
5 #include <ivstream.h>
6 #include <math.h>
7 #include <assert.h>
8 
9 extern int hoc_return_type_code;
10 
11 #if HAVE_IV
12 #include <InterViews/glyph.h>
13 #include <InterViews/hit.h>
14 #include <InterViews/event.h>
15 #include <InterViews/color.h>
16 #include <InterViews/brush.h>
17 #include <InterViews/window.h>
18 #include <InterViews/printer.h>
19 #include <InterViews/label.h>
20 #include <InterViews/font.h>
21 #include <InterViews/background.h>
22 #include <InterViews/style.h>
23 #include <InterViews/telltale.h>
24 #include <OS/string.h>
25 #include <InterViews/image.h>
26 extern Image* gif_image(const char*);
27 
28 
29 #include <IV-look/kit.h>
30 
31 #include "apwindow.h"
32 #include "ivoc.h"
33 #include "graph.h"
34 #include "axis.h"
35 #include "hocmark.h"
36 #include "mymath.h"
37 #include "idraw.h"
38 #include "symchoos.h"
39 #include "scenepic.h"
40 #include "oc2iv.h"
41 #include "objcmd.h"
42 #include "ocjump.h"
43 #include "utility.h"
44 #include "cbwidget.h"
45 #include "xmenu.h"
46 #include "ivocvect.h"
47 #endif /* HAVE_IV */
48 
49 #include "classreg.h"
50 #include "gui-redirect.h"
51 
52 extern Object** (*nrnpy_gui_helper_)(const char* name, Object* obj);
53 extern double (*nrnpy_object_to_double_)(Object*);
54 
55 #if HAVE_IV
56 #define Graph_Crosshair_ "Crosshair Graph"
57 #define Graph_Change_label_ "ChangeText Graph"
58 #define Graph_keep_lines_toggle_ "KeepLines Graph"
59 #define Graph_erase_axis_ "AxisType Graph"
60 #define Graph_new_axis_ "NewAxis AxisType Graph"
61 #define Graph_view_axis_ "ViewAxis AxisType Graph"
62 #define Graph_view_box_ "ViewBox AxisType Graph"
63 #define Graph_erase_lines_ "Erase Graph"
64 #define Graph_choose_sym_ "PlotWhat Graph"
65 #define Graph_choose_family_label_ "FamilyLabel Graph"
66 #define Graph_choose_rvp_ "PlotRange Graph"
67 
68 bool GraphItem::is_polyline() { return false; }
69 bool GPolyLineItem::is_polyline() { return true; }
70 bool GraphItem::is_mark() { return false; }
71 
72 
73 /*static*/ class GraphLabelItem : public GraphItem {
74 public:
75  GraphLabelItem(Glyph* g) : GraphItem(g){}
76  virtual ~GraphLabelItem(){};
77  virtual void save(ostream& o, Coord x, Coord y){
78  ((GLabel*)body())->save(o, x, y);}
79  virtual void erase(Scene* s, GlyphIndex i, int type) {
80  if ((type & GraphItem::ERASE_LINE) && ((GLabel*)body())->erase_flag()) {
81  s->remove(i);
82  }
83  };
84 };
85 
86 /*static*/ class GraphAxisItem : public GraphItem {
87 public:
88  GraphAxisItem(Glyph* g) : GraphItem(g){}
89  virtual ~GraphAxisItem(){};
90  virtual void save(ostream& o, Coord, Coord){
91  ((Axis*)body())->save(o);}
92  virtual void erase(Scene* s, GlyphIndex i, int type) {
93  if (type & GraphItem::ERASE_AXIS) {
94  s->remove(i);
95  }
96  }
97 };
98 
99 /*static*/ class GraphMarkItem : public GraphItem {
100 public:
101  GraphMarkItem(Glyph* g) : GraphItem(g){}
102  virtual ~GraphMarkItem(){};
103  virtual void erase(Scene* s, GlyphIndex i, int type) {
104  if (type & GraphItem::ERASE_LINE) {
105  s->remove(i);
106  }
107  }
108  virtual bool is_mark() { return true; }
109 };
110 
111 /*static*/ class VectorLineItem : public GPolyLineItem {
112 public:
113  VectorLineItem(Glyph* g) : GPolyLineItem(g){}
114  virtual ~VectorLineItem(){};
115  virtual void erase(Scene* s, GlyphIndex i, int type){}
116  virtual bool is_graphVector() { return true; }
117 };
118 
119 /*static*/ class LineExtension : public Glyph {
120 public:
121  LineExtension(GPolyLine*);
122  virtual ~LineExtension();
123 
124  void begin();
125  void extend();
126  void damage(Graph*);
127 
128  virtual void request(Requisition&) const;
129  virtual void allocate(Canvas*, const Allocation&, Extension&);
130  virtual void draw(Canvas*, const Allocation&) const;
131 
132  DataVec* xd() const { return (DataVec*)gp_->x_data(); }
133  DataVec* yd() const { return (DataVec*)gp_->y_data(); }
134 private:
135  GPolyLine* gp_;
136  int start_;
137  int previous_;
138 };
139 
140 /*static*/ class NewLabelHandler : public Handler {
141 public:
142  NewLabelHandler(Graph*, Coord, Coord);
143  ~NewLabelHandler();
144  virtual bool event(Event&);
145 private:
146  Graph* g_;
147  Coord x_, y_;
148 };
149 
150 NewLabelHandler::NewLabelHandler(Graph* g, Coord x, Coord y) {
151 // printf("NewLabelHandler\n");
152  g_ = g;
153  x_ = x;
154  y_ = y;
155 }
156 
157 NewLabelHandler::~NewLabelHandler(){
158 // printf("~NewLabelHandler\n");
159 }
160 bool NewLabelHandler::event(Event& e) {
161  char buf[200];
162  buf[0] = '\0';
163  GLabel* gl = g_->new_proto_label();
164  gl->ref();
165  if (Graph::label_chooser("Enter new label", buf, gl,
166  e.pointer_root_x(), e.pointer_root_y())) {
167  if (gl->fixed()) {
168  g_->fixed(gl->scale());
169  }else{
170  g_->vfixed(gl->scale());
171  }
172  if (g_->labeltype() == 2) {
173  XYView::current_pick_view()->s2o().inverse_transform(x_, y_);
175  }
176  g_->label(x_, y_, buf);
177  }
178  gl->unref();
179  return true;
180 }
181 
182 // Graph registration for oc
183 static void gr_axis(Graph* g, DimensionName d) { IFGUI
184  int ntic = -1;
185  int nminor = 0;
186  int invert = 0;
187  bool number = true;
188  float x1 = 0;
189  float x2 = -1;
190  float pos = 0.;
191  if (!ifarg(2)) {
192  int i=0;
193  if (ifarg(1)) {
194  i = int(chkarg(1,0,3));
195  }
196  switch (i) {
197  case 0:
198  g->view_axis();
199  break;
200  case 1:
201  g->erase_axis();
202 g->axis(Dimension_X, x1, x2, pos, ntic, nminor, invert, number);
203 g->axis(Dimension_Y, x1, x2, pos, ntic, nminor, invert, number);
204  break;
205  case 2:
206  g->view_box();
207  break;
208  case 3:
209  g->erase_axis();
210  break;
211  }
212  return;
213  }
214  if (ifarg(3)) {
215  pos = *getarg(3);
216  }
217  if (ifarg(4)) {
218  ntic = int(chkarg(4, -1, 100));
219  }
220  if (ifarg(2)) {
221  x1 = *getarg(1);
222  x2 = *getarg(2);
223  }
224  if (ifarg(5)) {
225  nminor = int(chkarg(5, 0, 100));
226  }
227  if (ifarg(6)) {
228  invert = int(chkarg(6,-1,1));
229  }
230  if (ifarg(7) && !int(chkarg(7, 0, 1))) {
231  number = false;
232  }
233  g->axis(d, x1, x2, pos, ntic, nminor, invert, number);
234 ENDGUI
235 }
236 #endif /* HAVE_IV */
237 
238 static double gr_xaxis(void* v) {
239  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.xaxis", v);
240 #if HAVE_IV
241  gr_axis((Graph*)v, Dimension_X);
242  return 1.;
243 #else
244  return 0.;
245 #endif /* HAVE_IV */
246 }
247 static double gr_yaxis(void* v) {
248  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.yaxis", v);
249 #if HAVE_IV
250  gr_axis((Graph*)v, Dimension_Y);
251  return 1.;
252 #else
253  return 0.;
254 #endif /* HAVE_IV */
255 }
256 static double gr_save_name(void* v) {
257  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.save_name", v);
258 #if HAVE_IV
259 IFGUI
260  Graph* g = (Graph*)v;
261  g->name(gargstr(1));
262  if (ifarg(2) && (chkarg(2,0,1) == 1.) && Oc::save_stream) {
263  char buf[80];
264  *Oc::save_stream << "{\nsave_window_=" << gargstr(1) << endl;
265  *Oc::save_stream << "save_window_.size("
266  << g->x1() << "," << g->x2() << ","
267  << g->y1() << "," << g->y2() << ")\n";
268  long i = Scene::scene_list_index(g);
269  sprintf(buf, "scene_vector_[%ld] = save_window_", i);
270  *Oc::save_stream << buf << endl;
271  g->save_phase2(*Oc::save_stream);
272  g->Scene::mark(true);
273  }
274 ENDGUI
275  return 1.;
276 #else
277  return 0.;
278 #endif /* HAVE_IV */
279 }
280 #if HAVE_IV
281 
282 static void move_label(Graph* g, const GLabel* lab, int ioff = 0) {
283  float x, y;
284  if (ifarg(4+ioff) && lab) {
285  x = *getarg(4+ioff);
286  y = *getarg(5+ioff);
287  g->move(g->glyph_index(lab), x, y);
288  }
289 }
290 #endif /* HAVE_IV */
291 
292 static double gr_family(void* v) {
293  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.family", v);
294 #if HAVE_IV
295 IFGUI
296  if (hoc_is_str_arg(1)) {
297  ((Graph*)v)->family(gargstr(1));
298  }else{
299  ((Graph*)v)->family(int(chkarg(1,0,1)));
300  }
301 ENDGUI
302  return 1.;
303 #else
304  return 0.;
305 #endif /* HAVE_IV */
306 }
307 
308 double ivoc_gr_menu_action(void* v) {
309  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.menu_action", v);
310 #if HAVE_IV
311 IFGUI
312  HocCommand* hc;
313  if (hoc_is_object_arg(2)) {
314  hc = new HocCommand(*hoc_objgetarg(2));
315  }else{
316  hc = new HocCommand(gargstr(2));
317  }
318  ((Scene*)v)->picker()->add_menu(gargstr(1), new HocCommandAction(hc));
319 ENDGUI
320  return 1.;
321 #else
322  return 0.;
323 #endif /* HAVE_IV */
324 }
325 
326 double ivoc_gr_menu_tool(void* v) {
327  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.menu_tool", v);
328 #if HAVE_IV
329 IFGUI
330  if (hoc_is_object_arg(2)) { // python style
331  HocPanel::paneltool(gargstr(1), NULL, NULL, ((Scene*)v)->picker(),
332  *hoc_objgetarg(2), ifarg(3) ? *hoc_objgetarg(3) : NULL);
333  }else{
334  HocPanel::paneltool(gargstr(1), gargstr(2),
335  ifarg(3) ? gargstr(3) : NULL, ((Scene*)v)->picker());
336  }
337 ENDGUI
338  return 1.;
339 #else
340  return 0.;
341 #endif /* HAVE_IV */
342 }
343 
344 double ivoc_view_info(void* v) {
345  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.view_info", v);
346 #if HAVE_IV
347 IFGUI
348  int i;
349  Scene* s = (Scene*)v;
350  XYView* view;
351  if (!ifarg(1)) {
352  view = XYView::current_pick_view();
353  for (i=0; i < s->view_count(); ++i) {
354  if (s->sceneview(i) == view) {
355  return double(i);
356  }
357  }
358  return -1.;
359  }
360  view = s->sceneview(int(chkarg(1, 0, s->view_count()-1)));
361  float x1,y1,x2,y2;
362  i = int(chkarg(2,1,15));
363  switch (i) {
364  case 1: // width
365  return view->width();
366  case 2: // height
367  return view->height();
368  case 3: // point width
369  view->view_ratio(0., 0., x1, y1);
370  view->view_ratio(1., 1., x2, y2);
371  return x2 - x1;
372  case 4: // point height
373  view->view_ratio(0., 0., x1, y1);
374  view->view_ratio(1., 1., x2, y2);
375  return y2 - y1;
376  case 5: // left
377  return view->left();
378  case 6: // right
379  return view->right();
380  case 7: // bottom
381  return view->bottom();
382  case 8: // top
383  return view->top();
384  case 9: // model x distance for one point
385  view->view_ratio(0., 0., x1, y1);
386  view->view_ratio(1., 1., x2, y2);
387  if (x2 > x1) {
388  return view->width()/(x2 - x1);
389  }else{
390  return 1.;
391  }
392  case 10: // model y distance for one point
393  view->view_ratio(0., 0., x1, y1);
394  view->view_ratio(1., 1., x2, y2);
395  if (y2 > y1) {
396  return view->height()/(y2 - y1);
397  }else{
398  return 1.;
399  }
400  case 11: // relative x location (from x model coord)
401  return (*getarg(3) - view->left())/view->width();
402  case 12: // relative y location (from y model coord)
403  return (*getarg(3) - view->bottom())/view->height();
404  case 13: // points from left (from x model coord)
405  x1 = (*getarg(3) - view->left())/view->width();
406  view->view_ratio(x1, 1., x2, y2);
407  view->view_ratio(0., 1., x1, y1);
408  return x2 - x1;
409  case 14: // points from top (from y model coord)
410  y1 = (*getarg(3) - view->bottom())/view->height();
411  view->view_ratio(1., y1, x2, y2);
412  view->view_ratio(1., 1., x1, y1);
413  return y1 - y2;
414  case 15: // label height in points
415  //return WidgetKit::instance()->font()->size();
416  {FontBoundingBox b;
417  WidgetKit::instance()->font()->font_bbox(b);
418  return b.ascent() + b.descent();
419  }
420 
421  }
422 ENDGUI
423 #endif /* HAVE_IV */
424  return -1.;
425 }
426 
427 double ivoc_view_size(void* v) {
428  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.view_size", v);
429 #if HAVE_IV
430 IFGUI
431  int i;
432  Scene* s = (Scene*)v;
433  XYView* view;
434  view = s->sceneview(int(chkarg(1, 0, s->view_count()-1)));
435  view->size(*getarg(2), *getarg(4), *getarg(3), *getarg(5));
436  view->damage_all();
437 ENDGUI
438 #endif /* HAVE_IV */
439  return 0.;
440 }
441 
442 double gr_line_info(void* v) {
443  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.line_info", v);
444 #if HAVE_IV
445 IFGUI
446  Graph* g = (Graph*)v;
447  GlyphIndex i, cnt;
448  double* p;
449  cnt = g->count();
450  i = (int)chkarg(1, -1, cnt);
451  if (i < 0 || i > cnt-1) {
452  i = -1;
453  }
454  Vect* x = vector_arg(2);
455  for (i += 1; i < cnt; ++i) {
456  GraphItem* gi = (GraphItem*)g->component(i);
457  if (gi->is_polyline()) {
458  GPolyLine* gpl = (GPolyLine*)gi->body();
459  x->resize(5);
460  p = vector_vec(x);
461  p[0] = colors->color(gpl->color());
462  p[1] = brushes->brush(gpl->brush());
463  if (gpl->label()) {
464  Coord a, b;
465  x->label(gpl->label()->text());
466  g->location(g->glyph_index(gpl->label()), a, b);
467  p[2] = a; p[3] = b;
468  p[4] = gpl->label()->fixtype();
469  }
470  return (double)i;
471  }
472  }
473 ENDGUI
474 #endif /* HAVE_IV */
475  return -1.;
476 }
477 
478 #if HAVE_IV
479 static void gr_add(void* v, bool var) {
480 IFGUI
481  Graph* g = (Graph*)v;
482  GraphLine* gl;
483  Object* obj = NULL;
484  char* lab = NULL;
485  char* expr = NULL;
486  int ioff = 0; // deal with 0, 1, or 2 optional arguments after first
487  double* pd = NULL; // pointer to varname if second arg is varname string
488  int fixtype = g->labeltype();
489  // organize args for backward compatibility and the new
490  // addexpr("label, "expr", obj,.... style
491  if (ifarg(2)) {
492  if (var) {// if string or address then variable and 1 was label
493  expr = gargstr(1);
494  if (hoc_is_str_arg(2)) {
495  pd = hoc_val_pointer(gargstr(2));
496  ioff += 1;
497  }else if (hoc_is_pdouble_arg(2)) {
498  pd = hoc_pgetarg(2);
499  ioff += 1;
500  }
501  }else if (hoc_is_str_arg(2)) { // 1 label, 2 expression
502  lab = gargstr(1);
503  expr = gargstr(2);
504  ioff += 1;
505  if (ifarg(3) && hoc_is_object_arg(3)) { // object context
506  obj = *hoc_objgetarg(3);
507  ioff += 1;
508  }
509  }else if (hoc_is_object_arg(2)) { // 1 expr, 2 object context
510  expr = gargstr(1);
511  obj = *hoc_objgetarg(2);
512  ioff += 1;
513  }else{
514  expr = gargstr(1);
515  }
516  }else{
517  expr = gargstr(1);
518  }
519  if (ifarg(3+ioff)) {
520  if (ifarg(6+ioff)) {
521  fixtype = int(chkarg(6+ioff,0,2));
522  }else if (ifarg(4+ioff)) {
523  // old versions did not have the fixtype and for
524  // backward compatibility it must therefore be
525  // fixed.
526  fixtype = 1;
527  }
528  gl = g->add_var(expr,
529  colors->color(int(*getarg(2+ioff))),
530  brushes->brush(int(*getarg(3+ioff))),
531  var, fixtype, pd, lab, obj);
532  }else{
533  gl = g->add_var(expr, g->color(), g->brush(),
534  var, fixtype, pd, lab, obj);
535  }
536  move_label(g, gl->label(), ioff);
537 ENDGUI
538 }
539 #endif /* HAVE_IV */
540 static double gr_addvar(void* v) {
541  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.addvar", v);
542 #if HAVE_IV
543  gr_add(v, 1);
544  return 1.;
545 #else
546  return 0.;
547 #endif /* HAVE_IV */
548 }
549 static double gr_addexpr(void* v) {
550  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.addexpr", v);
551 #if HAVE_IV
552  gr_add(v, 0);
553  return 1.;
554 #else
555  return 0.;
556 #endif /* HAVE_IV */
557 }
558 static double gr_addobject(void* v) {
559  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.addobject", v);
560 #if HAVE_IV
561 IFGUI
562  Graph* g = (Graph*)v;
563  Object* obj = *hoc_objgetarg(1);
564  if (is_obj_type(obj, "RangeVarPlot")) {
565  GraphVector* gv = (GraphVector*)obj->u.this_pointer;
566  if (ifarg(3)) {
567  gv->color(colors->color(int(*getarg(2))));
568  gv->brush(brushes->brush(int(*getarg(3))));
569  }else{
570  gv->color(g->color());
571  gv->brush(g->brush());
572  }
573  g->append(new VectorLineItem(gv));
574  GLabel* glab = g->label(gv->name());
575  gv->label(glab);
576  ((GraphItem*)g->component(g->glyph_index(glab)))->save(false);
577  g->see_range_plot(gv);
578  move_label(g, glab);
579  }else{
580  hoc_execerror("Don't know how to plot this object type", 0);
581  }
582 ENDGUI
583  return 1.;
584 #else
585  return 0.;
586 #endif /* HAVE_IV */
587 }
588 
589 static double gr_vector(void* v) {
590  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.vector", v);
591 #if HAVE_IV
592 IFGUI
593  Graph* g = (Graph*)v;
594  int n = int(chkarg(1, 1., 1.e5));
595  double* x = hoc_pgetarg(2);
596  double* y = hoc_pgetarg(3);
597  GraphVector* gv = new GraphVector("");
598  if (ifarg(4)) {
599  gv->color(colors->color(int(*getarg(4))));
600  gv->brush(brushes->brush(int(*getarg(5))));
601  }else{
602  gv->color(g->color());
603  gv->brush(g->brush());
604  }
605  for (int i=0; i < n; ++i) {
606  gv->add(x[i], y + i);
607  }
608 // GLabel* glab = g->label(gv->name());
609 // ((GraphItem*)g->component(g->glyph_index(glab)))->save(false);
610  g->append(new GPolyLineItem(gv));
611 ENDGUI
612  return 1.;
613 #else
614  return 0.;
615 #endif /* HAVE_IV */
616 }
617 
618 static double gr_xexpr(void* v) {
619  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.xexpr", v);
620 #if HAVE_IV
621 IFGUI
622  Graph* g = (Graph*)v;
623  int i = 0;
624  if (ifarg(2)) {
625  i = int(chkarg(2,0,1));
626  }
627  g->x_expr(gargstr(1), i);
628 ENDGUI
629  return 1.;
630 #else
631  return 0.;
632 #endif /* HAVE_IV */
633 }
634 
635 static double gr_begin(void* v) {
636  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.begin", v);
637 #if HAVE_IV
638 IFGUI
639  ((Graph*)v)->begin();
640 ENDGUI
641  return 1.;
642 #else
643  return 0.;
644 #endif /* HAVE_IV */
645 }
646 
647 static double gr_plot(void* v) {
648  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.plot", v);
649 #if HAVE_IV
650 IFGUI
651  ((Graph*)v)->plot(*getarg(1));
652 ENDGUI
653  return 1.;
654 #else
655  return 0.;
656 #endif /* HAVE_IV */
657 }
658 
659 static double gr_simgraph(void* v) {
660  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.simgraph", v);
661 #if HAVE_IV
662 IFGUI
663  ((Graph*)v)->simgraph();
664 ENDGUI
665  return 1.;
666 #else
667  return 0.;
668 #endif /* HAVE_IV */
669 }
670 
671 double ivoc_gr_begin_line(void* v) {
672  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.beginline", v);
673 #if HAVE_IV
674 IFGUI
675  Graph* g = (Graph*)v;
676  int i = 1;
677  char* s = NULL;
678  if (ifarg(i) && hoc_is_str_arg(1)) {
679  s = gargstr(i++);
680  }
681  if (ifarg(i)) {
682  g->begin_line(
683  colors->color(int(*getarg(i))),
684  brushes->brush(int(*getarg(i+1))), s);
685  }else{
686  g->begin_line(s);
687  }
688 ENDGUI
689  return 1.;
690 #else
691  return 0.;
692 #endif /* HAVE_IV */
693 }
694 double ivoc_gr_line(void* v) {
695  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.line", v);
696 #if HAVE_IV
697 IFGUI
698  ((Graph*)v)->line(*getarg(1), *getarg(2));
699 ENDGUI
700  return 1.;
701 #else
702  return 0.;
703 #endif /* HAVE_IV */
704 }
705 static double gr_flush(void* v) {
706  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.flush", v);
707 
708 #if HAVE_IV
709 IFGUI
710  ((Graph*)v)->flush();
711 ENDGUI
712  return 1.;
713 #else
714  return 0.;
715 #endif /* HAVE_IV */
716 }
717 static double gr_fast_flush(void* v) {
718  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.fast_flush", v);
719 
720 #if HAVE_IV
721 IFGUI
722  ((Graph*)v)->fast_flush();
723 ENDGUI
724  return 1.;
725 #else
726  return 0.;
727 #endif /* HAVE_IV */
728 }
729 double ivoc_gr_erase(void* v) {
730  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.erase", v);
731 #if HAVE_IV
732 IFGUI
733  ((Graph*)v)->erase_lines();
734 ENDGUI
735  return 1.;
736 #else
737  return 0.;
738 #endif /* HAVE_IV */
739 }
740 
741 double ivoc_erase_all(void* v) {
742  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.erase_all", v);
743 #if HAVE_IV
744 IFGUI
745  ((Graph*)v)->erase_all();
746 ENDGUI
747  return 1.;
748 #else
749  return 0.;
750 #endif /* HAVE_IV */
751 }
752 
753 double ivoc_gr_gif(void* v) {
754  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.gif", v);
755 #if HAVE_IV
756 IFGUI
757  Graph* g = (Graph*)v;
758  Glyph* i = gif_image(gargstr(1));
759  if (i) {
760  Transformer t;
761  if (ifarg(4)) {
762  Coord x = *getarg(4);
763  Coord y = *getarg(5);
764  Requisition r;
765  i->request(r);
766  t.scale(x/r.x_requirement().natural(), y/r.y_requirement().natural());
767  i = new TransformSetter(i, t);
768  }
769  if (!ifarg(2)) { // resize if smaller than gif
770  Requisition r;
771  i->request(r);
772  if (r.x_requirement().natural() > (g->x2() - g->x1())
773  || r.y_requirement().natural() > (g->y2() - g->y1())) {
774  g->new_size(0, 0, r.x_requirement().natural(),
775  r.y_requirement().natural());
776  }
777  }
778  g->append(new GraphItem(i, false, false));
779  if (ifarg(2)) {
780  g->move(g->count() - 1, *getarg(2), *getarg(3));
781  }
782  return 1.;
783  }
784 ENDGUI
785 #endif /* HAVE_IV */
786  return 0.;
787 }
788 
789 double ivoc_gr_size(void* v) {
790  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.size", v);
791 #if HAVE_IV
792 IFGUI
793  Coord x1, y1, x2, y2;
794  Graph* g = (Graph*)v;
795  XYView* view = g->sceneview(0);
796  if (ifarg(2)) {
797  g->new_size(*getarg(1), *getarg(3), *getarg(2), *getarg(4));
798  }
799  if (hoc_is_pdouble_arg(1)) {
800  g->wholeplot(x1, y1, x2, y2);
801  double *x = hoc_pgetarg(1);
802  x[0] = x1;
803  x[1] = x2;
804  x[2] = y1;
805  x[3] = y2;
806  return 0.;
807  }
808  if (!view) {
809  return 0.;
810  }
811 
812  if (ifarg(2)) {
813  view->zout(x1, y1, x2, y2);
814  view->size(x1, y1, x2, y2);
815  return 1.;
816  }else{
817  view->zin(x1, y1, x2, y2);
818  double x = 0.;
819  switch (int(chkarg(1, 1., 4.))) {
820  case 1:
821  x = x1;
822  break;
823  case 2:
824  x = x2;
825  break;
826  case 3:
827  x = y1;
828  break;
829  case 4:
830  x = y2;
831  break;
832  }
833  return x;
834  }
835 ENDGUI
836  return 0.;
837 #else
838  return 0.;
839 #endif /* HAVE_IV */
840 }
841 
842 double ivoc_gr_label(void* v) {
843  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.label", v);
844 #if HAVE_IV
845 IFGUI
846  Graph* g = (Graph*)v;
847  if (ifarg(8)) {
848  g->label(*getarg(1), *getarg(2), gargstr(3),
849  int(*getarg(4)), *getarg(5), *getarg(6), *getarg(7),
850  colors->color(int(*getarg(8))));
851  }else if (ifarg(2)) {
852  char* s = NULL;
853  if (ifarg(3)) {
854  s = gargstr(3);
855  }
856  g->label(*getarg(1), *getarg(2), s);
857  }else{
858  g->label(gargstr(1));
859  }
860 ENDGUI
861  return 1.;
862 #else
863  return 0.;
864 #endif /* HAVE_IV */
865 }
866 static double gr_fixed(void* v) {
867  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.fixed", v);
868 #if HAVE_IV
869 IFGUI
870  float scale = 1;
871  if (ifarg(1)) {
872  scale = chkarg(1, .01, 100);
873  }
874  ((Graph*)v)->fixed(scale);
875 ENDGUI
876  return 1.;
877 #else
878  return 0.;
879 #endif /* HAVE_IV */
880 }
881 static double gr_vfixed(void* v) {
882  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.vfixed", v);
883 #if HAVE_IV
884 IFGUI
885  float scale = 1;
886  if (ifarg(1)) {
887  scale = chkarg(1, .01, 100);
888  }
889  ((Graph*)v)->vfixed(scale);
890 ENDGUI
891  return 1.;
892 #else
893  return 0.;
894 #endif /* HAVE_IV */
895 }
896 static double gr_relative(void* v) {
897  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.relative", v);
898 #if HAVE_IV
899 IFGUI
900  float scale = 1.;
901  if (ifarg(1)) {
902  scale = chkarg(1, .01, 100.);
903  }
904  ((Graph*)v)->relative(scale);
905 ENDGUI
906  return 1.;
907 #else
908  return 0.;
909 #endif /* HAVE_IV */
910 }
911 static double gr_align(void* v) {
912  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.align", v);
913 #if HAVE_IV
914 IFGUI
915  float x=0,y=0;
916  if (ifarg(1)) {
917  x = chkarg(1,-10,10);
918  }
919  if (ifarg(2)) {
920  y = chkarg(2,-10,10);
921  }
922  ((Graph*)v)->align(x, y);
923 ENDGUI
924  return 1.;
925 #else
926  return 0.;
927 #endif /* HAVE_IV */
928 }
929 static double gr_color(void* v) {
930  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.color", v);
931 #if HAVE_IV
932 IFGUI
933  int i=1;
934  if (ifarg(2)) {
936  return 1.;
937  }
938  if (ifarg(1)) {
939  i = int(chkarg(1,-1,ColorPalette::COLOR_SIZE-1));
940  }
941  ((Graph*)v)->color(i);
942 ENDGUI
943  return 1.;
944 #else
945  return 0.;
946 #endif /* HAVE_IV */
947 }
948 static double gr_brush(void* v) {
949  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.brush", v);
950 #if HAVE_IV
951 IFGUI
952  int i=0;
953  if (ifarg(3)) {
955  int(*getarg(2)), float(chkarg(3, 0, 1000)));
956  return 1.;
957  }
958  if (ifarg(1)) {
959  i = int(chkarg(1,-1,20));
960  }
961  ((Graph*)v)->brush(i);
962 ENDGUI
963  return 1.;
964 #else
965  return 0.;
966 #endif /* HAVE_IV */
967 }
968 
969 static double gr_view(void* v) {
970  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.view", v);
971 #if HAVE_IV
972 IFGUI
973  Graph* g = (Graph*)v;
974  if (ifarg(8)) {
975  Coord x[8]; int i;
976  for (i=0; i < 8; ++i) {
977  x[i] = *getarg(i+1);
978  }
979  XYView* view = new XYView(x[0], x[1], x[2], x[3],
980  g,
981  x[6], x[7]
982  );
983  Coord x1, x2, y1, y2;
984  view->zout(x1, y1, x2, y2);
985  view->size(x1, y1, x2, y2);
986 //printf("%g %g %g %g\n", view->left(), view->bottom(), view->right(), view->top());
987  ViewWindow* w = new ViewWindow(view, hoc_object_name(g->hoc_obj_ptr()));
988  w->xplace(int(x[4]), int(x[5]));
989  w->map();
990  }else if (ifarg(1) && *getarg(1) == 2.) {
991  View* view = new View(g);
992  ViewWindow* w = new ViewWindow(view, hoc_object_name(g->hoc_obj_ptr()));
993  w->map();
994  }
995 ENDGUI
996 
997  return 1.;
998 #else
999  return 0.;
1000 #endif /* HAVE_IV */
1001 }
1002 
1003 double ivoc_gr_mark(void* v) {
1004  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.mark", v);
1005 #if HAVE_IV
1006 IFGUI
1007  Graph* g = (Graph*)v;
1008  Coord x = *getarg(1);
1009  Coord y = *getarg(2);
1010  char style = '+';
1011  if (ifarg(3)) {
1012  if (hoc_is_str_arg(3)) {
1013  style = *gargstr(3);
1014  } else {
1015  style = char(chkarg(3,0,10));
1016  }
1017  }
1018  if (!ifarg(4)) {
1019  g->mark(x, y, style);
1020  }else if (!ifarg(5)) {
1021  g->mark(x, y, style, chkarg(4, .1, 100.),
1022  g->color(), g->brush());
1023  }else{
1024  g->mark(x, y, style, chkarg(4, .1, 100.),
1025  colors->color(int(*getarg(5))),
1026  brushes->brush(int(*getarg(6)))
1027  );
1028  }
1029 ENDGUI
1030  return 1.;
1031 #else
1032  return 0.;
1033 #endif /* HAVE_IV */
1034 }
1035 
1036 static double gr_view_count(void* v) {
1037  hoc_return_type_code = 1; // integer
1038  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.view_count", v);
1039 #if HAVE_IV
1040  int n = 0;
1041 IFGUI
1042  n = ((Scene*)v)->view_count();
1043 ENDGUI
1044  return double(n);
1045 #else
1046  return 0.;
1047 #endif /* HAVE_IV */
1048 }
1049 
1050 static double gr_unmap(void*v) {
1051  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.unmap", v);
1052 #if HAVE_IV
1053 IFGUI
1054  Graph* g = (Graph*)v;
1055  g->dismiss();
1056 ENDGUI
1057  return 0.;
1058 #else
1059  return 0.;
1060 #endif /* HAVE_IV */
1061 }
1062 
1063 static double gr_set_cross_action(void* v) {
1064  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.crosshair_action", v);
1065 #if HAVE_IV
1066 IFGUI
1067  Graph* g = (Graph*)v;
1068  bool vector_copy = false;
1069  if (ifarg(2)) {
1070  vector_copy = int(chkarg(2, 0, 1));
1071  }
1072  if (hoc_is_str_arg(1)) {
1073  g->set_cross_action(gargstr(1), NULL, vector_copy);
1074  }else{
1075  g->set_cross_action(NULL, *hoc_objgetarg(1), vector_copy);
1076  }
1077 ENDGUI
1078  return 0.;
1079 #else
1080  return 0.;
1081 #endif /* HAVE_IV */
1082 }
1083 
1084 static double gr_printfile(void* v) {
1085  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.printfile", v);
1086 #if HAVE_IV
1087 IFGUI
1088  Graph* g = (Graph*)v;
1089  g->printfile(gargstr(1));
1090 ENDGUI
1091  return 1.;
1092 #else
1093  return 0.;
1094 #endif /* HAVE_IV */
1095 }
1096 
1097 static double exec_menu(void* v) {
1098  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.exec_menu", v);
1099 #if HAVE_IV
1100 IFGUI
1101  ((Scene*)v)->picker()->exec_item(gargstr(1));
1102 ENDGUI
1103 #endif
1104  return 0.;
1105 }
1106 
1107 double ivoc_gr_menu_remove(void* v) {
1108  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Graph.menu_remove", v);
1109 #if HAVE_IV
1110 IFGUI
1111  ((Scene*)v)->picker()->remove_item(gargstr(1));
1112 ENDGUI
1113 #endif
1114  return 0.;
1115 }
1116 
1117 #if HAVE_IV
1118 extern double gr_getline(void*);
1119 #endif
1120 extern double gr_addglyph(void*);
1121 
1123  "plot", gr_plot,
1124  "fastflush", gr_fast_flush,
1125  "flush", gr_flush,
1126  "xaxis", gr_xaxis,
1127  "yaxis", gr_yaxis,
1128  "addvar", gr_addvar,
1129  "addexpr", gr_addexpr,
1130  "addobject", gr_addobject,
1131  "glyph", gr_addglyph,
1132  "vector", gr_vector,
1133  "xexpr", gr_xexpr,
1134  "begin", gr_begin,
1135  "erase", ivoc_gr_erase,
1136  "size", ivoc_gr_size,
1137  "label", ivoc_gr_label,
1138  "fixed", gr_fixed,
1139  "vfixed", gr_vfixed,
1140  "relative", gr_relative,
1141  "align", gr_align,
1142  "color", gr_color,
1143  "brush", gr_brush,
1144  "view", gr_view,
1145  "save_name", gr_save_name,
1146  "beginline", ivoc_gr_begin_line,
1147  "line", ivoc_gr_line,
1148  "mark", ivoc_gr_mark,
1149  "simgraph", gr_simgraph,
1150  "view_count", gr_view_count,
1151  "erase_all", ivoc_erase_all,
1152  "unmap", gr_unmap,
1153  "crosshair_action", gr_set_cross_action,
1154  "printfile", gr_printfile,
1155  "family", gr_family,
1156  "menu_action", ivoc_gr_menu_action,
1157  "menu_tool", ivoc_gr_menu_tool,
1158  "view_info", ivoc_view_info,
1159  "view_size", ivoc_view_size,
1160 #if HAVE_IV
1161  "getline", gr_getline,
1162 #endif
1163  "exec_menu", exec_menu,
1164  "gif", ivoc_gr_gif,
1165  "menu_remove", ivoc_gr_menu_remove,
1166  "line_info", gr_line_info,
1167  0,0
1168 };
1169 
1170 static void* gr_cons(Object* ho) {
1171  TRY_GUI_REDIRECT_OBJ("Graph", NULL);
1172 #if HAVE_IV
1173  Graph* g = NULL;
1174 IFGUI
1175  int i = 1;
1176  if (ifarg(1)) {
1177  i = (int)chkarg(1, 0, 1);
1178  }
1179  g = new Graph(i);
1180  g->ref();
1181  g->hoc_obj_ptr(ho);
1182 ENDGUI
1183  return (void*)g;
1184 #else
1185  return (void*)0;
1186 #endif /* HAVE_IV */
1187 }
1188 static void gr_destruct(void* v) {
1189  TRY_GUI_REDIRECT_NO_RETURN("~Graph", v);
1190 #if HAVE_IV
1191 IFGUI
1192  Graph* g = (Graph*)v;
1193  g->dismiss();
1194  Resource::unref(g);
1195 ENDGUI
1196 #endif /* HAVE_IV */
1197 }
1198 void Graph_reg() {
1199 //printf("Graph_reg\n");
1200  class2oc("Graph", gr_cons, gr_destruct, gr_members, NULL, NULL, NULL);
1201 #if HAVE_IV
1202 IFGUI
1203  colors = new ColorPalette();
1204  brushes = new BrushPalette();
1205 ENDGUI
1206 #endif
1207 }
1208 #if HAVE_IV
1209 static const char* colorname[] = { "white", "black", "red", "blue", "green",
1210 "orange", "brown", "violet", "yellow", "gray",
1211 0};
1212 
1214  int i;
1215  for (i=0; i < COLOR_SIZE && colorname[i]; ++i) {
1216  color_palette[i] = NULL;
1217  color(i, colorname[i]);
1218  }
1219 
1222 
1223  int j;
1224  for (j=0; i < COLOR_SIZE; ++i, ++j) {
1225 // color_palette[i] = color_palette[j];
1226 // ZFM fix to allow more colors (COLOR_SIZE > 20)
1227  color_palette[i] = color_palette[j%10];
1228  Resource::ref(color_palette[i]);
1229  }
1230 };
1232  for (int i=0; i < COLOR_SIZE; ++i) {
1233  Resource::unref(color_palette[i]);
1234  }
1235 }
1236 
1237 const Color* ColorPalette::color(int i)const {
1238 IFGUI
1239  if (i < 0) i = 1;
1240  i = i%COLOR_SIZE;
1241  return color_palette[i];
1242 ENDGUI else return NULL;
1243 }
1244 const Color* ColorPalette::color(int i, const char* name) {
1245 const Color* c = Color::lookup(Session::instance()->default_display(), name);
1246  if (c == NULL) {
1247  printf("couldn't lookup color \"%s\", you must be missing the\n\
1248 colormap.ini file or else the name isn't in it\n", name);
1249  }
1250  return color(i, c);
1251 }
1252 const Color* ColorPalette::color(int i, const Color* c) {
1253  if (c) {
1254  Resource::ref(c);
1255  Resource::unref(color_palette[i]);
1256  color_palette[i] = c;
1257  }
1258  return color_palette[i];
1259 }
1260 
1261 int ColorPalette::color(const Color* c) const {
1262  for (int i=0; i < COLOR_SIZE; ++i) {
1263  if (color_palette[i] == c) {
1264  return i;
1265  }
1266  }
1267  return 1;
1268 }
1269 
1270 static int brush_pattern[] = {
1271  0x0,
1272  0xcccc,
1273  0xfff0,
1274  0xff00,
1275  0xf000
1276 };
1277 
1279  int i;
1280  for (i=0; i < BRUSH_SIZE; ++i) {
1281  brush_palette[i] = NULL;
1282  }
1283  i = 0;
1284  for (int j=0; j < 5; ++j) {
1285  for (int k=0; k < 5; ++k) {
1286  if (i < BRUSH_SIZE) {
1287  brush(i++, brush_pattern[j], k);
1288  }
1289  }
1290  }
1291 }
1293  for (int i=0; i < BRUSH_SIZE; ++i) {
1294  Resource::unref(brush_palette[i]);
1295  }
1296 }
1297 
1298 const Brush* BrushPalette::brush(int i)const {
1299 IFGUI
1300  if (i < 0) i = 1;
1301  i = i%BRUSH_SIZE;
1302  return brush_palette[i];
1303 ENDGUI else return NULL;
1304 }
1305 const Brush* BrushPalette::brush(int i, int pattern, Coord width) {
1306  Brush* b;
1307  if (pattern) {
1308  b = new Brush(pattern, width);
1309  }else{
1310  b = new Brush(width);
1311  }
1312  Resource::ref(b);
1313  Resource::unref(brush_palette[i]);
1314  brush_palette[i] = b;
1315  return b;
1316 }
1317 
1318 int BrushPalette::brush(const Brush* b) const {
1319  for (int i=0; i < BRUSH_SIZE; ++i) {
1320  if (brush_palette[i] == b) {
1321  return i;
1322  }
1323  }
1324  return 0;
1325 }
1326 
1327 
1330 
1331 GraphItem::GraphItem(Glyph* g, bool s, bool p) : MonoGlyph(g){
1332  save_ = s;
1333  pick_ = p;
1334 }
1336 void GraphItem::save(ostream&, Coord, Coord) {
1337 }
1338 void GraphItem::erase(Scene*, GlyphIndex, int) {
1339 }
1340 void GraphItem::pick(Canvas* c, const Allocation& a, int depth, Hit& h) {
1341  if (pick_) {
1342  MonoGlyph::pick(c, a, depth, h);
1343  }
1344 }
1345 
1346 //Graph
1347 implementPtrList(LineList, GraphLine);
1348 declareActionCallback(Graph);
1349 implementActionCallback(Graph);
1350 
1351 #define XSCENE 300.
1352 #define YSCENE 200.
1353 Graph::Graph(bool b) : Scene(0,0,XSCENE,YSCENE) {
1354  loc_ = 0;
1355  x_expr_ = NULL;
1356  x_pval_ = NULL;
1357  var_name_ = NULL;
1358  rvp_ = NULL;
1359  cross_action_ = NULL;
1360  vector_copy_ = false;
1361  family_on_ = false;
1362  family_label_ = NULL;
1363  family_cnt_ = 0;
1364  current_polyline_ = NULL;
1365  label_fixtype_ = 2;
1366  label_scale_ = 1.;
1367  label_x_align_ = 0;
1368  label_y_align_ = 0;
1369  label_x_ = 0;
1370  label_y_ = 1;
1371  label_n_ = 0;
1372  picker();
1373  picker()->bind_select((OcHandler*)NULL);
1374  MenuItem* mi = picker()->add_radio_menu("Crosshair",(OcHandler*)NULL, CROSSHAIR);
1375  mi->state()->set(TelltaleState::is_chosen, true);
1376  tool(CROSSHAIR);
1377  picker()->add_menu("Plot what?",
1378  new ActionCallback(Graph)(this, &Graph::choose_sym));
1379  picker()->add_radio_menu("Pick Vector",(OcHandler*)NULL, PICK);
1380  picker()->add_radio_menu("Color/Brush",
1381  new ActionCallback(Graph)(this, &Graph::change_prop));
1382 #if 1
1383  WidgetKit& wk = *WidgetKit::instance();
1384  Menu* m = wk.pullright();
1385 picker()->add_menu("View Axis", new ActionCallback(Graph)(this, &Graph::view_axis), m);
1386 picker()->add_menu("New Axis", new ActionCallback(Graph)(this, &Graph::new_axis), m);
1387 picker()->add_menu("View Box", new ActionCallback(Graph)(this, &Graph::view_box), m);
1388 picker()->add_menu("Erase Axis", new ActionCallback(Graph)(this, &Graph::erase_axis), m);
1389  mi = K::menu_item("Axis Type");
1390  mi->menu(m);
1391  picker()->add_menu(mi);
1392 #else
1393  picker()->add_menu("New Axis",
1394  new ActionCallback(Graph)(this, &Graph::new_axis));
1395 #endif
1396  mi = WidgetKit::instance()->check_menu_item("Keep Lines");
1397  mi->action(new ActionCallback(Graph)(this, &Graph::keep_lines_toggle));
1398  keep_lines_toggle_ = mi->state();
1399  keep_lines_toggle_->ref();
1400  picker()->add_menu("Keep Lines", mi);
1401  picker()->add_menu("Family Label?",
1402  new ActionCallback(Graph)(this, &Graph::family_label_chooser));
1403  picker()->add_menu("Erase",
1404  new ActionCallback(Graph)(this, &Graph::erase_lines));
1405  picker()->add_radio_menu("Move Text",(OcHandler*)NULL, Scene::MOVE);
1406  picker()->add_radio_menu("Change Text",(OcHandler*)NULL, Graph::CHANGELABEL);
1407  picker()->add_radio_menu("Delete", (OcHandler*)NULL, Scene::DELETE);
1408  sc_ = NULL;
1409  if (!colors) {
1410  colors = new ColorPalette();
1411  }
1412  if (!brushes) {
1413  brushes = new BrushPalette();
1414  }
1415  color_ = NULL;
1416  color(1);
1417  brush_ = NULL;
1418  brush(1);
1419  x_ = new DataVec(200);
1420  x_->ref();
1421  extension_flushed_ = true;
1422  symlist_ = NULL;
1423  if (b) {
1424  XYView* v = new XYView((Scene*)this, XSCENE, YSCENE);
1425  Window* w = new ViewWindow(v, "Graph");
1426  w->map();
1427  }
1428  long i=3;
1429  if (WidgetKit::instance()->style()->find_attribute("graph_axis_default",
1430  i)) {
1431  switch (i) {
1432  case 0:
1433  view_axis();
1434  break;
1435  case 2:
1436  view_box();
1437  break;
1438  }
1439  }
1440 }
1441 
1442 extern "C" {
1443  extern void hoc_free_list(Symlist**);
1444  extern double* nrn_recalc_ptr(double*);
1445 } // extern "C";
1446 
1447 Graph::~Graph() {
1448 //printf("~Graph\n");
1449  for (long i=0; i < line_list_.count(); ++i) {
1450  Resource::unref(line_list_.item(i));
1451  }
1452  Resource::unref(keep_lines_toggle_);
1454  hoc_free_list(&symlist_);
1455  Resource::unref(color_);
1456  Resource::unref(brush_);
1457  Resource::unref(rvp_);
1458  Resource::unref(sc_);
1459  Resource::unref(current_polyline_);
1460  Resource::unref(family_label_);
1461  if (var_name_) {
1462  delete var_name_;
1463  }
1464  if (cross_action_) {
1465  delete cross_action_;
1466  }
1467 }
1468 
1469 void Graph::name(char* s) {
1470  if (var_name_) {
1471  *var_name_ = s;
1472  }else{
1473  var_name_ = new CopyString(s);
1474  }
1475 }
1476 
1477 void Graph::help() {
1478  switch (tool()) {
1479  case CROSSHAIR:
1480  Oc::help(Graph_Crosshair_);
1481  break;
1482  case CHANGELABEL:
1483  Oc::help(Graph_Change_label_);
1484  break;
1485  default:
1486  Scene::help();
1487  break;
1488  }
1489 }
1490 
1491 void Graph::delete_label(GLabel* glab) {
1492  GraphLine* glin = NULL;
1493  GlyphIndex i, cnt;
1494  cnt = line_list_.count();
1495  for (i = 0; i < cnt; ++i) {
1496  if (line_list_.item(i)->label() == glab) {
1497  glin = line_list_.item(i);
1498  break;
1499  }
1500  }
1501  if (glin) {
1502  line_list_.remove(i);
1503  glin->unref();
1504  i = glyph_index(glin);
1505  remove(i);
1506  }
1507  if (!glin) { // but possibly a vector line
1508  cnt = count();
1509  for (i=0; i < cnt; ++i) {
1510  GraphItem* gi = (GraphItem*)component(i);
1511  if (gi->is_polyline()) {
1512  GPolyLine* gpl = (GPolyLine*)gi->body();
1513  if (gpl->label() == glab) {
1514  remove(i);
1515  break;
1516  }
1517  }
1518  }
1519  }
1520  i = glyph_index(glab);
1521  remove(i);
1522 }
1523 
1524 GLabel* Graph::new_proto_label() const {
1525  return new GLabel("", color_, label_fixtype_, label_scale_,
1526  label_x_align_, label_y_align_);
1527 }
1528 
1529 bool Graph::change_label(GLabel* glab, const char* text, GLabel* gl) {
1530  GlyphIndex i, cnt = line_list_.count();
1531  if (strcmp(glab->text(), text)) {
1532  for (i=0; i < cnt; ++i) {
1533  if (line_list_.item(i)->label() == glab) {
1534  if (! line_list_.item(i)->change_expr(text, &symlist_)) {
1535  return false;
1536  }
1537  }
1538  }
1539  glab->text(text);
1540  }
1541  i = glyph_index(glab);
1542  if (glab->fixtype() != gl->fixtype()) {
1543  if (gl->fixed()) {
1544  glab->fixed(gl->scale());
1545  change_to_fixed(i, XYView::current_pick_view());
1546  }else{
1547  glab->vfixed(gl->scale());
1548  change_to_vfixed(i, XYView::current_pick_view());
1549  }
1550  }
1551  change(i);
1552  return true;
1553 }
1554 
1555 void Graph::change_label_color(GLabel* glab) {
1556  glab->color(color());
1557  damage(glyph_index(glab));
1558  if (glab->labeled_line()) {
1559  glab->labeled_line()->brush(brush());
1560  damage(glyph_index(glab->labeled_line()));
1561  }
1562 }
1563 
1564 void Graph::change_line_color(GPolyLine* glin) {
1565  glin->color(color());
1566  glin->brush(brush());
1567  damage(glyph_index(glin));
1568  if (glin->label()) {
1569  damage(glyph_index(glin->label()));
1570  }
1571 }
1572 
1573 GlyphIndex Graph::glyph_index(const Glyph* gl) {
1574  GlyphIndex i, cnt = count();
1575  for (i=0; i < cnt; ++i) {
1576  Glyph* g = ((GraphItem*)component(i))->body();
1577  if (g == gl) {
1578  return i;
1579  }
1580  }
1581  return -1;
1582 }
1583 
1584 ostream* Graph::ascii_;
1586 
1587 void Graph::ascii(ostream* o) {
1588  ascii_ = o;
1589 }
1590 ostream* Graph::ascii() {
1591  return ascii_;
1592 }
1593 
1594 void Graph::draw(Canvas* c, const Allocation& a) const {
1595  long i, cnt = line_list_.count();
1596 //if (!extension_flushed_) {
1597  Scene::draw(c, a);
1598 //}
1599  if (extension_flushed_) {
1600  for (i = 0; i < cnt; ++i) {
1601  line_list_.item(i)->extension()->draw(c, a);
1602  }
1603  }
1604  if (ascii_) {
1605  ascii_save(*ascii_);
1606  }
1607 }
1608 
1609 void Graph::ascii_save(ostream& o) const {
1610  long line, lcnt = line_list_.count();
1611  int i, dcnt;
1612  if (lcnt == 0 || !x_ || family_label_) {
1613  // tries to print in matrix form is labels and each line the same
1614  // size.
1615  o << "PolyLines" << endl;
1616  if (x_expr_) {
1617  o << "x expression: " << x_expr_->name;
1618  }
1619  if (lcnt) {
1620  o << lcnt << " addvar/addexpr lines:";
1621  for (i=0; i < lcnt; ++i) {
1622  o << " " << line_list_.item(i)->name();
1623  }
1624  o << endl;
1625  }
1626 
1627 
1628  lcnt = count();
1629  // check to see if all y_data has same count and a label.
1630  // If so print as matrix. (Assumption that all x_data same is
1631  // dangerous.)
1632  bool matrix_form = true;
1633  int col=0;
1634  int xcnt = 0;
1635  const DataVec* xvec = NULL;
1636  for (i=0; i < lcnt; ++i) {
1637  GraphItem* gi = (GraphItem*)component(i);
1638  if (gi->is_polyline()) {
1639  GPolyLine* gpl = (GPolyLine*)gi->body();
1640  if (gpl->label() && (xcnt == 0 || gpl->x_data()->count() == xcnt)) {
1641  xcnt = gpl->x_data()->count();
1642  xvec = gpl->x_data();
1643  if (gpl->y_data()->count() == xcnt) {
1644  ++col;
1645  }
1646  }else{
1647  matrix_form = false;
1648  break;
1649  }
1650  }
1651  }
1652  if (matrix_form) {
1653  if (x_expr_) {
1654  o << x_expr_->name;
1655  }else{
1656  o << "x";
1657  }
1658  for (i=0; i < lcnt; ++i) {
1659  GraphItem* gi = (GraphItem*)component(i);
1660  if (gi->is_polyline()) {
1661  GPolyLine* gpl = (GPolyLine*)gi->body();
1662  if (gpl->y_data()->count() == xcnt) {
1663  o << " " << gpl->label()->text();
1664  }
1665  }
1666  }
1667  o << endl;
1668  o << xcnt << " rows, " << col+1 << " columns" << endl;
1669  int j;
1670  for (j=0; j < xcnt; ++j) {
1671  o << xvec->get_val(j);
1672  for (i=0; i < lcnt; ++i) {
1673  GraphItem* gi = (GraphItem*)component(i);
1674  if (gi->is_polyline()) {
1675  GPolyLine* gpl = (GPolyLine*)gi->body();
1676  if (gpl->y_data()->count() == xcnt) {
1677  o << "\t" << gpl->y(j);
1678  }
1679  }
1680  }
1681  o << endl;
1682  }
1683  }
1684  if (!matrix_form) {
1685  o << "Line Manifest:" << endl;
1686  for (i = 0; i < lcnt; ++i) {
1687  GraphItem* gi = (GraphItem*)component(i);
1688  if (gi->is_polyline()) {
1689  GPolyLine* gpl = (GPolyLine*)gi->body();
1690  int j, jcnt;
1691  jcnt = gpl->y_data()->count();
1692  if (jcnt && family_label_ && gpl->label()) {
1693 o << jcnt << " " << family_label_->text() << "=" << gpl->label()->text() << endl;
1694  }else{
1695  o << jcnt << endl;
1696  }
1697  }
1698  }
1699  o << "End of Line Manifest" << endl;
1700  for (i = 0; i < lcnt; ++i) {
1701  GraphItem* gi = (GraphItem*)component(i);
1702  if (gi->is_polyline()) {
1703  GPolyLine* gpl = (GPolyLine*)gi->body();
1704  int j, jcnt;
1705  jcnt = gpl->y_data()->count();
1706  if (jcnt && family_label_ && gpl->label()) {
1707 o << jcnt << " " << family_label_->text() << "=" << gpl->label()->text() << endl;
1708  }else{
1709  o << jcnt << endl;
1710  }
1711  for (j=0; j < jcnt; ++j) {
1712  o << gpl->x(j) << "\t" << gpl->y(j) << "\n";
1713  }
1714  }
1715  }
1716  }
1717  return;
1718  }
1719  o << "Graph addvar/addexpr lines" << endl;
1720  o << lcnt << " " << x_->count() << endl;
1721  if (x_expr_) {
1722  o << x_expr_->name;
1723  }else{
1724  o << "x";
1725  }
1726  for (line=0; line < lcnt; ++line) {
1727  o << " " << line_list_.item(line)->name();
1728  }
1729  o << endl;
1730  dcnt = x_->count();
1731  for (i = 0; i < dcnt; ++i) {
1732  o << x_->get_val(i);
1733  for (line=0; line < lcnt; ++line) {
1734  o << "\t" << line_list_.item(line)->y(i);
1735  }
1736  o << endl;
1737  }
1738  // print the remaining unlabeled polylines. i.e. saved with KeepLines
1739  lcnt = count();
1740  int n = 0;
1741  for (i=0; i < lcnt; ++i) {
1742  GraphItem* gi = (GraphItem*)component(i);
1743  if (gi->is_polyline()) {
1744  GPolyLine* gpl = (GPolyLine*)gi->body();
1745  if (!gpl->label()) {
1746  ++n;
1747  }
1748  }
1749  }
1750  o << n << " unlabeled lines" << endl;
1751  for (i=0; i < lcnt; ++i) {
1752  GraphItem* gi = (GraphItem*)component(i);
1753  if (gi->is_polyline()) {
1754  GPolyLine* gpl = (GPolyLine*)gi->body();
1755  if (!gpl->label()) {
1756  int n = gpl->x_data()->count();
1757  o << n << endl;
1758  int j;
1759  for (j=0; j < n; ++j) {
1760  o << gpl->x(j) << "\t" << gpl->y(j) << endl;
1761  }
1762  }
1763  }
1764  }
1765 }
1766 
1767 void Graph::pick(Canvas* c, const Allocation& a, int depth, Hit& h) {
1768 #if 1
1769  Scene::pick(c, a, depth, h);
1770  if (tool() == CHANGELABEL && !menu_picked() && h.event()
1771  && h.event()->type() == Event::down
1772  && h.event()->pointer_button() == Event::left
1773  && h.count() < 2
1774  ){
1775  h.target(depth, this, 0,
1776  new NewLabelHandler(this, h.left(), h.bottom())
1777  );
1778  }
1779 #else
1780  if (h.event() && h.event()->type() == Event::down) {
1781  if (h.event()->pointer_button() == Event::right) {
1782  h.target(depth, this, 0,
1783  new RubberRect(c, new NewView(this))
1784  );
1785  }else if (h.event()->pointer_button() == Event::middle) {
1786  choose_sym(c->window());
1787  }else{
1788  Scene::pick(c, a, depth, h);
1789  }
1790  }else{
1791  Scene::pick(c, a, depth, h);
1792  }
1793 #endif
1794 }
1795 
1796 void Graph::new_size(Coord x1, Coord y1, Coord x2, Coord y2) {
1797  Scene::new_size(x1, y1, x2, y2);
1798  if (label_fixtype_ == 1) {
1799  label_x_ = x2 - .2*(x2 - x1);
1800  label_y_ = y2 - .1*(y2 - y1);
1801  }else if (label_fixtype_ == 2) {
1802  label_x_ = .8;
1803  label_y_ = .9;
1804  }
1805  label_n_ = 0;
1806 }
1807 
1808 void Graph::wholeplot(Coord& l, Coord& b, Coord& r, Coord& t) const {
1809  GlyphIndex i, cnt;
1810  GraphLine* gl;
1811  l = b = 1e9;
1812  r = t = -1e9;
1813 #if 0
1814  cnt = line_list_.count();
1815  if (!cnt) {
1816 #endif
1817  cnt = count();
1818  for (i=0; i < cnt; ++i) {
1819  GraphItem* gi = (GraphItem*)component(i);
1820  if (gi->is_polyline()){
1821  GPolyLine* gpl = (GPolyLine*)gi->body();
1822  if (gpl->x_data()->count() > 1) {
1823  l = Math::min(l, gpl->x_data()->min());
1824  b = Math::min(b, gpl->y_data()->min());
1825  r = Math::max(r, gpl->x_data()->max());
1826  t = Math::max(t, gpl->y_data()->max());
1827  }
1828  }
1829  if (gi->is_mark()) {
1830  Coord x, y;
1831  location(i, x, y);
1832  l = Math::min(l, x);
1833  b = Math::min(b, y);
1834  r = Math::max(r, x);
1835  t = Math::max(t, y);
1836  }
1837  }
1838  if (l >= r || b >= t) {
1839  Coord x1,y1,x2,y2;
1840  Scene::wholeplot(x1, y1, x2, y2);
1841  if (l >= r) { l = x1; r = x2; }
1842  if (b >= t) { b = y1; t = y2; }
1843  }
1844  if (t > 1e30) { t = 1e30; }
1845  if (b < -1e30) { t = -1e30; }
1846  return;
1847 #if 0
1848  }
1849  for (i = 0; i < cnt; ++i) {
1850  gl = line_list_.item(i);
1851  l = Math::min(l, gl->x_data()->min());
1852  b = Math::min(b, gl->y_data()->min());
1853  r = Math::max(r, gl->x_data()->max());
1854  t = Math::max(t, gl->y_data()->max());
1855  }
1856  if (l >= r || b >= t) {
1857  Scene::wholeplot(l, b, r, t);
1858  }
1859 #endif
1860 }
1861 
1862 void Graph::axis(DimensionName d, float x1, float x2, float pos,
1863  int ntic, int nminor, int invert, bool number) {
1864 //printf("%d %g %g %g %d %d %d %d %g\n", d, x1, x2, pos, ntic, nminor, invert, number);
1865  Axis* a;
1866  if (x2 < x1) {
1867  a = new Axis(this, d);
1868  }else if ( ntic < 0) {
1869  a = new Axis(this, d, x1, x2);
1870  }else{
1871  a = new Axis(this, d, x1, x2, pos, ntic, nminor, invert, number );
1872  }
1873  append_fixed(new GraphAxisItem(a));
1874 }
1875 void Graph::color(int i) {
1876  const Color* color = colors->color(i);
1877  Resource::ref(color);
1878  Resource::unref(color_);
1879  color_ = color;
1880 }
1881 void Graph::brush(int i) {
1882  const Brush* b = brushes->brush(i);
1883  Resource::ref(b);
1884  Resource::unref(brush_);
1885  brush_ = b;
1886 }
1887 GraphLine* Graph::add_var(const char* expr, const Color* color, const Brush* brush,
1888  bool usepointer, int fixtype, double* pd, const char* lab, Object* obj) {
1889  GraphLine* gl = new GraphLine(expr, x_, &symlist_, color, brush, usepointer,
1890  pd, obj);
1891  GLabel* glab;
1892  if (lab) {
1893  glab = label(lab, fixtype);
1894  }else{
1895  glab = label(expr, fixtype);
1896  }
1897  GlyphIndex i = glyph_index(glab);
1898  ((GraphItem*)component(i))->save(false);
1899  glab->color(color);
1900  gl->label(glab);
1901  line_list_.append(gl);
1902  gl->ref();
1903  Scene::append(new GPolyLineItem(gl));
1904  return gl;
1905 }
1906 
1907 void Graph::add_polyline(GPolyLine* gp) {
1908  Scene::append(new GPolyLineItem(gp));
1909 }
1910 
1912  Scene::append(new VectorLineItem(gv));
1913 }
1914 
1915 void Graph::x_expr(const char* expr, bool usepointer) {
1916  Oc oc;
1917  x_expr_ = oc.parseExpr(expr, &symlist_);
1918  if (!x_expr_) {
1919  hoc_execerror(expr, "not an expression");
1920  }
1921  if (usepointer) {
1922  x_pval_ = hoc_val_pointer(expr);
1923  if (!x_pval_) {
1924 hoc_execerror(expr, "is invalid left hand side of assignment statement");
1925  }
1926  }else{
1927  x_pval_ = 0;
1928  }
1929 }
1930 
1931 extern int hoc_execerror_messages;
1932 void Graph::begin() {
1933  if (keep_lines_toggle_->test(TelltaleState::is_chosen)) {
1934  keep_lines();
1935  family_value();
1936  }
1937  long count = line_list_.count();
1938  int hem = hoc_execerror_messages;
1939  for (long i=0; i < count; ++i) {
1940  GraphLine* gl = line_list_.item(i);
1941  gl->erase();
1942  if (family_on_) {
1943  ((GPolyLine*)gl)->color(color());
1944  ((GPolyLine*)gl)->brush(brush());
1945  }
1946  hoc_execerror_messages = false;
1947  if (gl->valid(true) == false) {
1948  printf("Graph:: presently invalid expression: %s\n",
1949  gl->name());
1950  }
1951  }
1952  hoc_execerror_messages = hem;
1953  x_->erase();
1954  extension_start();
1955 }
1956 void Graph::plot(float x) {
1957  if (extension_flushed_) {
1958  extension_continue();
1959  }
1960  if (x_expr_) {
1961  if (x_pval_) {
1962  x_->add(float(*x_pval_));
1963  }else{
1964  Oc oc;
1965  x_->add(oc.runExpr(x_expr_));
1966  }
1967  }else{
1968  x_->add(x);
1969  }
1970  long count = line_list_.count();
1971  for (long i=0; i < count; ++i) {
1972  line_list_.item(i)->plot();
1973  }
1974 }
1975 void Graph::begin_line(const char* s) {
1976  begin_line(color_, brush_, s);
1977 }
1978 void Graph::begin_line(const Color* c, const Brush* b, const char* s) {
1979  Resource::unref(current_polyline_);
1980  current_polyline_ = new GPolyLine(new DataVec(2), c, b);
1981  Resource::ref(current_polyline_);
1982  if (s && s[0]) {
1983  GLabel* glab = label(s);
1984  current_polyline_->label(glab);
1985  ((GraphItem*)component(glyph_index(glab)))->save(false);
1986  }
1987  Scene::append(new GPolyLineItem(current_polyline_));
1988 }
1989 void Graph::line(Coord x, Coord y) {
1990  if (!current_polyline_) {
1991  begin_line();
1992  }
1993  current_polyline_->plot(x, y);
1994 }
1995 void Graph::flush() {
1996  extension_start();
1997  long i, cnt = count();
1998  for (i=0; i < cnt; ++i) {
1999  modified(i);
2000  }
2001 // damage_all();//too conservative. plots everything every time
2002 }
2003 void Graph::fast_flush() {
2004 #if 0
2005  long i, cnt = line_list_.count();
2006  for (i=0; i < cnt; ++i) {
2007  modified(
2008  glyph_index(
2009  line_list_.item(i)->extension()
2010  )
2011  );
2012  }
2013 #else
2014  long i, cnt = line_list_.count();
2015  for (i=0; i < cnt; ++i) {
2016  line_list_.item(i)->extension()->damage(this);
2017  }
2018 #endif
2019  extension_flushed_ = true;
2020 }
2021 
2022 void Graph::extension_start() {
2023  x_->running_start();
2024  long i, cnt = line_list_.count();
2025  for (i = 0; i < cnt; ++i) {
2026  line_list_.item(i)->extension_start();
2027  }
2028  extension_flushed_ = false;
2029 }
2031  x_->running_start();
2032  long i, cnt = line_list_.count();
2033  for (i = 0; i < cnt; ++i) {
2034  line_list_.item(i)->extension_continue();
2035  }
2036  extension_flushed_ = false;
2037 }
2038 
2039 void Graph::mark(Coord x, Coord y, char style, float size,
2040  const Color* c, const Brush* b)
2041 {
2042  HocMark* m = HocMark::instance(style, size, c, b);
2043  append_fixed(new GraphMarkItem(m));
2044  move(Scene::count() - 1, x, y);
2045 }
2046 
2047 void Graph::set_cross_action(const char* cp, Object* pyact, bool vector_copy) {
2048  if (cross_action_) {
2049  delete cross_action_;
2050  cross_action_ = NULL;
2051  }
2052  if (cp && strlen(cp) > 0) {
2053  cross_action_ = new HocCommand(cp);
2054  }else if (pyact) {
2055  cross_action_ = new HocCommand(pyact);
2056  }
2057  vector_copy_ = vector_copy;
2058 }
2059 
2060 void Graph::cross_action(char c, GPolyLine* gpl, int i) {
2061  if (cross_action_) {
2062  char buf[256];
2063  if (vector_copy_) {
2064  Object* op1 = *(gpl->x_data()->new_vect());
2065  Object* op2 = *(gpl->y_data()->new_vect(gpl->label()));
2066  hoc_pushx(double(i));
2067  hoc_pushx(double(c));
2068  hoc_push_object(op1);
2069  hoc_push_object(op2);
2070  cross_action_->func_call(4);
2071  hoc_obj_unref(op1);
2072  hoc_obj_unref(op2);
2073  }else{
2074  hoc_pushx(double(gpl->x_data()->get_val(i)));
2075  hoc_pushx(double(gpl->y_data()->get_val(i)));
2076  hoc_pushx(double(c));
2077  cross_action_->func_call(3);
2078  }
2079  }else{
2080  printf("{x=%g y=%g}\n", gpl->x(i), gpl->y(i));
2081  }
2082 }
2083 
2084 void Graph::cross_action(char c, Coord x, Coord y) {
2085  if (cross_action_) {
2086  char buf[256];
2087  if (vector_copy_) {
2088  }else{
2089  sprintf(buf, "%s(%g, %g, %d)", cross_action_->name(),
2090  x, y, c);
2091  cross_action_->execute(buf);
2092  }
2093  }else{
2094  printf("{x=%g y=%g}\n", x, y);
2095  }
2096 }
2097 void Graph::erase() {
2098  long count = line_list_.count();
2099  for (long i=0; i < count; ++i) {
2100  line_list_.item(i)->erase();
2101  }
2102  damage_all();
2103 }
2104 
2105 void Graph::erase_all() {
2106  int i;
2107 #if 0
2108  while(count()) {
2109  remove(0);
2110  }
2111 #else
2112  for ( i = count()-1; i >= 0; --i) {
2113  remove(i);
2114  }
2115 #endif
2116  while (line_list_.count()) {
2117  Resource::unref(line_list_.item(0));
2118  line_list_.remove(0);
2119  }
2120  label_n_ = 0;
2121 }
2122 void Graph::family_value() {
2123  if (family_label_) {
2124  char buf[256];
2125  sprintf(buf, "hoc_ac_ = %s\n", family_label_->text());
2126  Oc oc;
2127  oc.run(buf);
2128  family_val_ = hoc_ac_;
2129  }
2130 }
2131 
2132 void Graph::keep_lines_toggle() {
2133  if (Oc::helpmode()) {
2134  Oc::help(Graph_keep_lines_toggle_);
2135  keep_lines_toggle_->set(TelltaleState::is_chosen,
2136  !keep_lines_toggle_->test(TelltaleState::is_chosen));
2137  return;
2138  }
2139  family_value();
2140  if (!keep_lines_toggle_->test(TelltaleState::is_chosen)) { // keep the ones already there
2141  keep_lines();
2142  }
2143 }
2144 
2145 void Graph::keep_lines() {
2146  char buf[256];
2147  int fi;
2148  Coord x, y;
2149  GLabel* f = family_label_;
2150  if (f) {
2151  fi = glyph_index(f);
2152  location(fi, x, y);
2153  sprintf(buf, "%g", family_val_);
2154  }
2155  long lcnt = count();
2156  for (long i = lcnt-1; i >= 0; --i) {
2157  GraphItem* gi = (GraphItem*)component(i);
2158  if (gi->is_polyline()) {
2159  GPolyLine* gpl = (GPolyLine*)gi->body();
2160  if (gpl->keepable() && gpl->y_data()->count() > 1) {
2161  GPolyLine* g2 =
2162  new GPolyLine(new DataVec(gpl->x_data()), new DataVec(gpl->y_data()),
2163  gpl->color(), gpl->brush());
2164 
2165  if (f) {
2166  GLabel* gl = label(x, y, buf,
2167  f->fixtype(), f->scale(),
2168  0, family_cnt_, gpl->color());
2169  family_cnt_++;
2170  g2->label(gl);
2171  ((GraphItem*)component(glyph_index(gl)))->save(false);
2172  }
2173  Scene::insert(i, new GPolyLineItem(g2));
2174  modified(i);
2175  gpl->erase();
2176  }
2177  }
2178  }
2179  flush();
2180 }
2181 
2182 void Graph::family(bool i) {
2183  if (i) {
2184  erase_lines();
2185  family_on_ = true;
2186  keep_lines_toggle_->set(TelltaleState::is_chosen, true);
2187  }else{
2188  family_on_ = false;
2189  keep_lines_toggle_->set(TelltaleState::is_chosen, false);
2190  long count = line_list_.count();
2191  for (long i=0; i < count; ++i) {
2192  GraphLine* gl = line_list_.item(i);
2193  gl->color(gl->save_color());
2194  gl->brush(gl->save_brush());
2195  }
2196  }
2197 }
2198 
2199 void Graph::family(const char* s) {
2200  if (family_label_) {
2201  if (s && s[1]) {
2202  family_label_->text(s);
2203  modified(glyph_index(family_label_));
2204  }else{
2205  remove(glyph_index(family_label_));
2206  family_label_->unref();
2207  family_label_ = NULL;
2208  }
2209  }else if (s && s[1]) {
2210  family_label_ = label(.95, .95, s, 2, 1, 1, 0, color_);
2211  family_label_->ref();
2212  ((GraphItem*)component(glyph_index(family_label_)))->save(false);
2213  }
2214 }
2215 
2216 void Graph::erase_axis() {
2217  if (Oc::helpmode()) {
2218  Oc::help(Graph_erase_axis_);
2219  return;
2220  }
2221  GlyphIndex i, cnt;
2222  cnt = count();
2223  for (i=cnt-1; i >= 0; --i) {
2224  ((GraphItem*)component(i))->erase(this, i, GraphItem::ERASE_AXIS);
2225  }
2227  damage_all();
2228 }
2229 
2230 void Graph::new_axis() {
2231  if (Oc::helpmode()) {
2232  Oc::help(Graph_new_axis_);
2233  return;
2234  }
2236  erase_axis();
2237  Coord x1, x2, y1, y2;
2238  if (v) {v->zin(x1, y1, x2, y2);}
2239  Axis* a = new Axis(this, Dimension_X, x1, x2);
2240  append_fixed(new GraphAxisItem(a));
2241  a = new Axis(this, Dimension_Y, y1, y2);
2242  append_fixed(new GraphAxisItem(a));
2243 }
2244 
2245 void Graph::view_axis() {
2246  if (Oc::helpmode()) {
2247  Oc::help(Graph_view_axis_);
2248  return;
2249  }
2250  erase_axis();
2252  damage_all();
2253 }
2254 
2255 void Graph::view_box() {
2256  if (Oc::helpmode()) {
2257  Oc::help(Graph_view_box_);
2258  return;
2259  }
2260  erase_axis();
2262  damage_all();
2263 }
2264 
2265 #if 0
2266 void Graph::spec_axis() {
2268  Coord x1, x2, y1, y2;
2269  v->zin(x1, y1, x2, y2);
2270  bool bx = var_pair_chooser("X-Axis", x1, x2);
2271  bool by = var_pair_chooser("Y-Axis", y1, y2);
2272  v->size(x1, y1, x2, y2);
2273  erase_axis();
2274  if (bx) {
2275  Axis* a = new Axis(this, Dimension_X, x1, x2);
2276  append_fixed(new GraphAxisItem(a));
2277  }
2278  if (by) {
2279  Axis* a = new Axis(this, Dimension_Y, y1, y2);
2280  append_fixed(new GraphAxisItem(a));
2281  }
2282 }
2283 #endif
2284 
2285 void Graph::erase_lines() {
2286  if (Oc::helpmode()) {
2287  Oc::help(Graph_erase_lines_);
2288  return;
2289  }
2290  // when labels are attached to lines some get erased and some do not
2291  // the issue invalid pointers is also a problem (delete when removed
2292  // from scene which screws up the GlyphIndex iterators. For this reason
2293  // we just unshow all gpolyline labels,
2294  // then show the labels for line list and GraphVector then
2295  // remove all unshow.
2296  GlyphIndex i, cnt = count();
2297  for (i=0; i < cnt; ++i) {
2298  GraphItem* gi = (GraphItem*)component(i);
2299  if (gi->is_polyline() && !gi->is_graphVector()) {
2300  GLabel* gl = ((GPolyLine*)(gi->body()))->label();
2301  if (gl) {
2302  gl->erase_flag(true);
2303  }
2304  }
2305  }
2306  cnt = line_list_.count();
2307  for (i = 0; i < cnt; ++i) {
2308  GraphLine* gl = line_list_.item(i);
2309  gl->label()->erase_flag(false);
2310  }
2311  cnt = count();
2312  for (i=cnt-1; i >= 0; --i) {
2313  ((GraphItem*)component(i))->erase(this, i, GraphItem::ERASE_LINE);
2314  }
2315  cnt = line_list_.count();
2316  for (i = 0; i < cnt; ++i) {
2317  GraphLine* gl = line_list_.item(i);
2318  Scene::append(new GPolyLineItem(gl));
2319  }
2320  erase();
2321  if (family_label_) {
2322  family_cnt_ = 0;
2323  }
2324 }
2325 GLabel* Graph::label(float x, float y, const char* s, int fixtype,
2326  float scale, float x_align, float y_align, const Color* color)
2327 {
2328  GLabel* l = new GLabel(s, color, fixtype, scale, x_align, y_align);
2329  if (fixtype == 1) {
2330  append_fixed(new GraphLabelItem(l));
2331  }else if (fixtype == 2) {
2332  append_viewfixed(new GraphLabelItem(l));
2333  }else if (fixtype == 0) {
2334  append(new GraphLabelItem(l));
2335  }
2336  move(count()-1, x, y);
2337  return l;
2338 }
2339 GLabel* Graph::label(float x, float y, const char* s, float n, int fixtype) {
2340  label_x_ = x;
2341  label_y_ = y;
2342  label_n_ = n;
2343  if (!s) {
2344  return NULL;
2345  }
2346  return label(x, y, s, (fixtype != -1) ? fixtype : label_fixtype_,
2347  label_scale_, label_x_align_, label_y_align_ + label_n_, color_);
2348 }
2349 GLabel* Graph::label(const char* s, int fixtype) {
2350  label_n_ += 1.;
2351  return label(label_x_, label_y_, s, label_n_, fixtype);
2352 }
2353 void Graph::fixed(float scale) {
2354  label_fixtype_ = 1;
2355  label_scale_ = scale;
2356 }
2357 void Graph::vfixed(float scale) {
2358  label_fixtype_ = 2;
2359  label_scale_ = scale;
2360 }
2361 void Graph::relative(float fraction) {
2362  label_fixtype_ = 0;
2363  label_scale_ = fraction;
2364 }
2365 void Graph::align(float x, float y) {
2366  label_x_align_ = x;
2367  label_y_align_ = y;
2368 }
2369 
2371  if (rvp_) {
2372  rvp_->unref();
2373  }
2374  rvp_ = rvp;
2375  Resource::ref(rvp);
2376 }
2377 
2378 void Graph::save_phase1(ostream& o) {
2379  o << "{" << endl;
2380  save_class(o, "Graph");
2381 }
2382 
2383 static Graph* current_save_graph;
2384 
2385 void Graph::save_phase2(ostream& o) {
2386  char buf[256];
2387  if (family_label_) {
2388  sprintf(buf, "save_window_.family(\"%s\")", family_label_->text());
2389  o << buf << endl;
2390  }
2391  if (var_name_) {
2392  if ((var_name_->string())[var_name_->length() - 1] == '.') {
2393  sprintf(buf, "%sappend(save_window_)", var_name_->string());
2394  }else{
2395  sprintf(buf, "%s = save_window_", var_name_->string());
2396  }
2397  o << buf << endl;
2398  sprintf(buf, "save_window_.save_name(\"%s\")",
2399  var_name_->string());
2400  o << buf << endl;
2401  }
2402  if (x_expr_) {
2403  sprintf(buf, "save_window_.xexpr(\"%s\", %d)",
2404  x_expr_->name, x_pval_ ? 1:0);
2405  o << buf << endl;
2406  }
2407  long cnt = count();
2408  current_save_graph = this;
2409  for (long i=0; i < cnt; ++i) {
2410  GraphItem* g = (GraphItem*)component(i);
2411  Coord x, y;
2412  location(i, x, y);
2413  if (g->save()) {
2414  g->save(o, x, y);
2415  }
2416  }
2417  o << "}" << endl;
2418 }
2419 
2420 
2422  // it is a range variable plot where we get a different result
2423  return false;
2424 }
2425 
2426 void Graph::choose_sym() {
2427  Oc oc;
2428  if (Oc::helpmode()) {
2429  if (rvp_) {
2430  Oc::help(Graph_choose_rvp_);
2431  }else{
2432  Oc::help(Graph_choose_sym_);
2433  }
2434  }
2435  if (rvp_ && rvp_->choose_sym((Graph*)this)) {
2436  return;
2437  }
2438  if (!sc_) {
2439  Style* style = new Style(Session::instance()->style());
2440  style->attribute("caption", "Variable to graph");
2441  sc_ = new SymChooser(NULL, WidgetKit::instance(), style);
2442  sc_->ref();
2443  }
2444  Window* w = NULL;
2446  if (!v || v->scene() != (Scene*)this || !v->canvas() || !v->canvas()->window()) {
2447  if (view_count() > 0 && sceneview(0)->canvas()
2448  && sceneview(0)->canvas()->window()) {
2449  w = sceneview(0)->canvas()->window();
2450  }
2451  }else{
2452  w = v->canvas()->window();
2453  }
2454  while ((w && sc_->post_for_aligned(w, .5, 1.)) || (!w && sc_->post_at(300,300))) {
2455 //printf("Graph selected %s\n", sc_->selected()->string());
2456  char buf[256];
2457 double* pd = sc_->selected_var();
2458 if (sc_->selected_vector_count()) {
2459  sprintf(buf, "%s", sc_->selected()->string());
2460  GraphVector* gv = new GraphVector(buf);
2461  gv->color(color());
2462  gv->brush(brush());
2463  int n = sc_->selected_vector_count();
2464  for (int i=0; i < n; ++i) {
2465  gv->add(double(i), pd + i);
2466  }
2467  GLabel* glab = label(gv->name());
2468  ((GraphItem*)component(glyph_index(glab)))->save(false);
2469  gv->label(glab);
2470  append(new VectorLineItem(gv));
2471  flush();
2472  break;
2473 }else if (pd) {
2474 // add_var(sc_->selected()->string(), color(), brush(), 1, 2, pd);
2475  add_var(sc_->selected()->string(), color(), brush(), 1, 2);
2476  break;
2477 }else{
2478  CopyString s(*sc_->selected());
2479  // above required due to bug in mswindows version in which
2480  // sc_->selected seems volatile under some kinds of hoc
2481  // executions.
2482  sprintf(buf, "hoc_ac_ = %s\n", s.string());
2483  if (oc.run(buf) == 0) {
2484  add_var(s.string(), color(), brush(), 0, 2);
2485  break;
2486  }
2487  hoc_warning(s.string(), "is not an expression.");
2488 }
2489  }
2490 // sc_->unref();
2491 }
2492 
2494  Oc oc;
2495  if (Oc::helpmode()) {
2496  Oc::help(Graph_choose_family_label_);
2497  }
2498  if (!fsc_) {
2499  Style* style = new Style(Session::instance()->style());
2500  style->attribute("caption", "Family label variable");
2501  fsc_ = new SymChooser(NULL, WidgetKit::instance(), style);
2502  fsc_->ref();
2503  }
2504  while (fsc_->post_for_aligned(XYView::current_pick_view()->canvas()->window(), .5, 1.)) {
2505  char buf[256];
2506  sprintf(buf, "hoc_ac_ = %s\n", fsc_->selected()->string());
2507  if (oc.run(buf) == 0) {
2508  family(fsc_->selected()->string());
2509  break;
2510  }
2511  hoc_warning(sc_->selected()->string(), "is not an expression.");
2512  }
2513 }
2514 
2515 //GraphLine and GPolyLine
2516 GraphLine::GraphLine(const char* expr, DataVec* x, Symlist** symlist, const Color* c, const Brush* b,
2517  bool usepointer, double* pd, Object* obj)
2518  : GPolyLine(x, c, b)
2519 {
2520  Oc oc;
2521  valid_ = true;
2522  obj_ = NULL;
2523  simgraph_x_sav_ = NULL;
2524  if (usepointer) {
2525  if (pd) {
2526  //char buf[256];
2527  //sprintf(buf, "%s", expr);
2528  //expr_ = oc.parseExpr(buf, symlist);
2529  expr_ = NULL;
2530  pval_ = pd;
2531  }else{
2532  expr_ = oc.parseExpr(expr, symlist);
2533  pval_ = hoc_val_pointer(expr);
2534  if (!pval_) {
2535 hoc_execerror(expr, "is invalid left hand side of assignment statement");
2536  }
2537  }
2538  oc.notify_when_freed(pval_, this);
2539  }else{
2540  if (obj) {
2541  obj_ = obj;
2542  oc.notify_when_freed((void*)obj_, this);
2543  ObjectContext objc(obj_);
2544  expr_ = oc.parseExpr(expr, symlist);
2545  objc.restore();
2546  }else{
2547  expr_ = oc.parseExpr(expr, symlist);
2548  }
2549  pval_ = 0;
2550  }
2551  if (!pval_ && !expr_) {
2552  hoc_execerror(expr, "not an expression");
2553  }
2554  save_color_ = c;
2555  Resource::ref(c);
2556  save_brush_ = b;
2557  Resource::ref(b);
2558  extension_ = new LineExtension(this);
2559  extension_->ref();
2560  keepable_ = true;
2561 }
2562 
2563 GPolyLine::GPolyLine(DataVec* x, const Color* c, const Brush* b) {
2564  init(x, new DataVec(x->size()), c, b);
2565 }
2566 
2567 GPolyLine::GPolyLine(DataVec* x, DataVec* y, const Color* c, const Brush* b) {
2568  init(x, y, c, b);
2569 }
2570 
2572  init(new DataVec(gp->x_data()), new DataVec(gp->y_data()),
2573  gp->color(), gp->brush());
2574 }
2575 
2576 void GPolyLine::init(DataVec* x, DataVec* y, const Color* c, const Brush* b) {
2577  keepable_ = false;
2578  glabel_ = NULL;
2579  x_ = x;
2580  x_->ref();
2581  y_ = y;
2582  y_->ref();
2583  color_ = NULL;
2584  color(c);
2585  brush_ = NULL;
2586  brush(b);
2587  Resource::ref(b);
2588 }
2589 
2590 void GPolyLine::pick_vector() {
2591  Object* op1 = *(x_data()->new_vect());
2592  Object* op2 = *(y_data()->new_vect(label()));
2593  hoc_obj_set(1, op1);
2594  hoc_obj_set(0, op2);
2595  hoc_obj_unref(op1);
2596  hoc_obj_unref(op2);
2597 }
2598 
2599 extern void graphLineRecDeleted(GraphLine*);
2600 
2602  // expr_ deleted when its symlist is deleted
2603 // printf("~GraphLine %s\n", name());
2604  simgraph_activate(false);
2605  graphLineRecDeleted(this);
2606  Resource::unref(extension_);
2607  Oc oc;
2608  if (pval_ || obj_) {
2609 //printf("~graphline notify disconnect\n");
2610  oc.notify_pointer_disconnect(this);
2611  }
2612 }
2613 
2614 void GraphLine::simgraph_activate(bool act_) {
2615  if (act_) {
2616  if (!simgraph_x_sav_) {
2617  simgraph_x_sav_ = x_;
2618  x_ = new DataVec(x_->size());
2619  Resource::ref(x_);
2620 //printf("simgraph activate %s x_->size = %d\n", name(), x_->size());
2621  }
2622  }else{
2623  if (simgraph_x_sav_) {
2625  x_ = simgraph_x_sav_;
2626  simgraph_x_sav_ = NULL;
2627 //printf("simgraph inactivate %s x_->size = %d\n", name(), x_->size());
2628  }
2629  }
2630 }
2631 
2632 void GraphLine::simgraph_init() {
2633  x_->erase();
2634  erase();
2635 }
2636 
2637 void GraphLine::simgraph_continuous(double tt) {
2638  x_->add(tt);
2639  plot();
2640 }
2641 
2642 void GraphLine::update(Observable*) { // *pval_ has been freed
2643 //printf("GraphLine::update pval_ has been freed\n");
2644  pval_ = NULL;
2645  if (obj_) {
2646  expr_ = NULL;
2647  }
2648  obj_ = NULL;
2649 }
2650 
2651 bool GraphLine::change_expr(const char* expr, Symlist** symlist) {
2652  Oc oc;
2653  if (pval_ || obj_) {
2654  printf("Can't change.\n");
2655  return false;
2656  }
2657  Symbol* sym = oc.parseExpr(expr, symlist);
2658  if (sym) {
2659  expr_ = sym;
2660  if (pval_) {
2661  Oc oc;
2662  oc.notify_pointer_disconnect(this);
2663  pval_ = NULL;
2664  }
2665  return true;
2666  }else{
2667  return false;
2668  }
2669 }
2670 
2671 void GPolyLine::label(GLabel* l) {
2672  Resource::ref(l);
2673  if (l && l->gpl_ && l->gpl_->label()) {
2674  l->gpl_->label(NULL);
2675  }
2676  if (glabel_) {
2677  glabel_->gpl_ = NULL;
2678  }
2679  Resource::unref(glabel_);
2680  glabel_ = l;
2681  if (glabel_) {
2682  glabel_->color(color());
2683  glabel_->gpl_ = (GPolyLine*)this;
2684  }
2685 }
2686 
2688  Resource::unref(color_);
2689  Resource::unref(brush_);
2692  label(NULL);
2693 }
2695  GLabel* gl = label();
2696  s->remove(i);
2697  if (gl) {
2698  s->remove(s->glyph_index(gl));
2699  }
2700 }
2701 const char* GraphLine::name() const {
2702  Oc oc;
2703  if (label()) {
2704  return label()->text();
2705  }else if (expr_) {
2706  return oc.name(expr_);
2707  }else{
2708  return "no name";
2709  }
2710 }
2711 
2713  extension_->begin();
2714 }
2715 
2717  extension_->extend();
2718 }
2719 
2720 void GraphLine::save(ostream& o) {
2721  char buf[256];
2722  float x, y;
2723  if (!label()) {
2724  return;
2725  }
2726  GlyphIndex i = current_save_graph->glyph_index(label());
2727  current_save_graph->location(i, x, y);
2728  if (pval_) {
2729  sprintf(buf, "save_window_.addvar(\"%s\", %d, %d, %g, %g, %d)",
2730  name(), colors->color(color_), brushes->brush(brush_),
2731  x, y, label()->fixtype()
2732  );
2733  }else{
2734  // following is not exactly correct if the label or object args were
2735  // used but it is expected that in that case the graph is
2736  // encapsulated in an object and this info is incorrect anyway.
2737  // Can revisit later if this is a problem.
2738  sprintf(buf, "save_window_.addexpr(\"%s\", %d, %d, %g, %g, %d)",
2739  name(), colors->color(color_), brushes->brush(brush_),
2740  x, y, label()->fixtype()
2741  );
2742  }
2743  o << buf << endl;
2744 }
2745 
2746 void GPolyLine::save(ostream&) {
2747 }
2748 
2749 void GPolyLine::label_loc(Coord& x, Coord& y)const {
2750  if (label()) {
2751  GlyphIndex i = current_save_graph->glyph_index(label());
2752  current_save_graph->location(i, x, y);
2753  }else{
2754  x = 0.;
2755  y = 0.;
2756  }
2757 }
2758 
2759 void GPolyLine::request(Requisition& req)const {
2760 //printf("GPolyLine::request\n");
2761  Coord x, span;
2762  const float eps = 1e-4;
2763  x = x_->min(); span = x_->max() - x + eps;
2764  x = (span > 0)? x/span : 0;
2765  Requirement rx(span, 0, 0, -x);
2766  x = y_->min(); span = y_->max() - x + eps;
2767  x = (span > 0)? x/span : 0;
2768  Requirement ry(span, 0, 0, -x);
2769  req.require_x(rx);
2770  req.require_y(ry);
2771 }
2772 void GPolyLine::allocate(Canvas* c, const Allocation& a, Extension& e) {
2773 //printf("GPolyLine::allocate\n");
2774  e.set(c, a);
2775  MyMath::extend(e, brush()->width()/2 + 1);
2776 }
2777 void GPolyLine::draw(Canvas* c, const Allocation& a)const {
2778  draw_specific(c, a, 0, y_->count());
2779 }
2780 
2781 void GPolyLine::draw_specific(Canvas* c, const Allocation&, int begin, int end)const {
2782 //printf("GPolyLine::draw %d %g %g\n", y_->count(), a.x(), a.y());
2783  int i, cnt = end;
2784  if (cnt - begin < 2) {
2785  return;
2786  }
2787 #if 0
2788  Coord x1, y1, x2, y2;
2789  XYView::current_draw_view()->damage_area(x1, y1, x2, y2);
2790 
2791 #define GPIN(arg) \
2792 MyMath::inside(x_->get_val(arg), y_->get_val(arg), x1, y1, x2, y2)
2793 
2794  /* this works most of the time in preventing extraneous lines during
2795  very large zoom but can fail */
2796  for (i=begin; i > 0; --i) { // begin plotting outside of damage
2797  if (!GPIN(i)) {
2798  break;
2799  }
2800  }
2801  for (; i < cnt; ++i) {
2802  if (GPIN(i)) {
2803  if (i > 0) {
2804  --i;
2805  }
2806  break;
2807  }
2808  }
2809  int j;
2810  for (j=cnt-1 ; i < j; --j) {
2811  if (GPIN(j)) {
2812  if (j < cnt-1) {
2813  ++j;
2814  }
2815  break;
2816  }
2817  }
2818  cnt = j + 1;
2819  if (cnt - i < 2) {
2820  return;
2821  }
2822 #else
2823  i = begin;
2824 #endif
2825 
2826  // xwindows limited to 65000 point polylines and mswindows
2827  // limited even more. So split into max 8000 point polylines for drawing
2828  // with large fonts on windows 98 there is a 6000 point limit so
2829  // change to 4000. If the problem recurs we will need to have a property
2830  // option
2831  long cnt1;
2832  while (i < cnt) {
2833 #ifdef WIN32
2834  cnt1 = i + 4000;
2835 #else
2836  cnt1 = i + 8000;
2837 #endif
2838  if (cnt1 > cnt - 2) {// the -2 prevents a one point final polyline
2839  cnt1 = cnt;
2840  }
2841  c->new_path();
2842  c->move_to(x_->get_val(i), y_->get_val(i));
2843  for (++i; i < cnt1; ++i) {
2844  c->line_to(x_->get_val(i), y_->get_val(i));
2845  }
2846  c->stroke(color_, brush_);
2847  }
2848  IfIdraw(mline(c, cnt, x_->vec(), y_->vec(), color_, brush_));
2849 }
2850 
2851 void GPolyLine::print(Printer* c, const Allocation&)const {
2852  int i, cnt = y_->count();
2853  if (cnt < 2) {
2854  return;
2855  }
2856 #if 1
2857  float xmax,xmin,ymax,ymin;
2859  xmax = v->right();
2860  xmin = v->left();
2861  ymax = v->top();
2862  ymin = v->bottom();
2863 
2864  /* this works most of the time in preventing extraneous lines during
2865  very large zoom but can fail */
2866  for (i=0; i < cnt; ++i) {
2867  if (MyMath::inside(x_->get_val(i), y_->get_val(i), xmin, ymin, xmax, ymax)) {
2868  if (i > 0) {
2869  --i;
2870  }
2871  break;
2872  }
2873  }
2874  int j;
2875  for (j=cnt-1 ; i < j; --j) {
2876  if (MyMath::inside(x_->get_val(j), y_->get_val(j), xmin, ymin, xmax, ymax)) {
2877  if (j < cnt-1) {
2878  ++j;
2879  }
2880  break;
2881  }
2882  }
2883  cnt = j + 1;
2884  if (cnt - i < 2) {
2885  return;
2886  }
2887 #else
2888  i=0;
2889 #endif
2890 
2891  const Transformer& t = XYView::current_draw_view()->s2o();
2892  //Scene::view_transform((Canvas*)c, 1, t); //2 would keep fixed width
2893  // line even after scaling by Print Window Manager
2894 
2895  c->new_path();
2896  c->move_to(x_->get_val(i), y_->get_val(i));
2897 #if 0
2898  for (++i; i < cnt; ++i) {
2899  c->line_to(x_->get_val(i), y_->get_val(i));
2900  }
2901 // some printers can't take very long lines
2902 // from alain@helmholtz.sdsc.edu
2903 #else
2904  char counter=0;
2905  for (++i; i < cnt; ++i) {
2906  c->line_to(x_->get_val(i), y_->get_val(i));
2907  if(!++counter) {
2908  c->push_transform();
2909  c->transform(t);
2910  c->stroke(color_, brush_);
2911  c->pop_transform();
2912  c->new_path();
2913  c->move_to(x_->get_val(i), y_->get_val(i));
2914  }
2915  }
2916 #endif
2917  c->push_transform();
2918  c->transform(t);
2919  c->stroke(color_, brush_);
2920  c->pop_transform();
2921 }
2922 
2923 void GraphLine::plot(){
2924  if ( pval_ ) {
2925  y_->add(*pval_);
2926  }else{
2927  Oc oc;
2928  nrn_hoc_lock();
2929  if (obj_) {
2930  ObjectContext obc(obj_);
2931  y_->add(oc.runExpr(expr_));
2932  obc.restore();
2933  }else if (valid()) {
2934  y_->add(oc.runExpr(expr_));
2935  }
2936  nrn_hoc_unlock();
2937  }
2938 //printf("GPolyLine::plot(%d) value = %g\n", loc, y_->value(loc));
2939 }
2940 
2941 bool GraphLine::valid(bool check) {
2942  if (check && ! pval_) {
2943  Oc oc;
2944  valid_ = oc.valid_expr(expr_);
2945  }
2946  return valid_;
2947 }
2948 
2949 void GPolyLine::plot(Coord x, Coord y) {
2950  x_->add(x);
2951  y_->add(y);
2952 }
2953 
2954 void GPolyLine::color(const Color* col) {
2955  const Color* c = col;
2956  if (!c) {
2957  c = colors->color(1);
2958  }
2959  Resource::ref(c);
2960  Resource::unref(color_);
2961  color_ = c;
2962  if (glabel_ && glabel_->color() != color()) {
2963  glabel_->color(color());
2964  }
2965 }
2966 
2967 void GPolyLine::brush(const Brush* brush) {
2968  const Brush* b = brush;
2969  if (!b) {
2970  b = brushes->brush(1);
2971  }
2972  Resource::ref(b);
2973  Resource::unref(brush_);
2974  brush_ = b;
2975 }
2976 
2977 void GraphLine::save_color(const Color* color) {
2978  const Color* c = color;
2979  if (!c) {
2980  c = colors->color(1);
2981  }
2982  Resource::ref(c);
2983  Resource::unref(color_);
2984  save_color_ = c;
2985  GPolyLine::color(c);
2986 }
2987 
2988 void GraphLine::save_brush(const Brush* brush) {
2989  const Brush* b = brush;
2990  if (!b) {
2991  b = brushes->brush(1);
2992  }
2993  Resource::ref(b);
2994  Resource::unref(brush_);
2995  save_brush_ = b;
2996  GPolyLine::brush(b);
2997 }
2998 
2999 //GLabel
3000 GLabel::GLabel(const char* s, const Color* color, int fixtype, float size, float x_align, float y_align)
3001 {
3002  gpl_ = NULL;
3003  WidgetKit& kit = *WidgetKit::instance();
3004  label_ = new Label(s, kit.font(), color);
3005  label_->ref();
3006  erase_flag_ = false;
3007  color_ = color;
3008  color_->ref();
3009  text_ = s;
3010  if (fixtype == 2) {
3011  vfixed(size);
3012  }else if (fixtype == 1) {
3013  fixed(size);
3014  }else{
3015  relative(size);
3016  }
3017  align(x_align, y_align);
3018 }
3019 GLabel::~GLabel() {
3020 // printf("~GLabel %s\n", text());
3021  Resource::unref(label_);
3022  Resource::unref(color_);
3023  assert(!labeled_line());
3024 }
3025 
3026 Glyph* GLabel::clone() const {
3027  return new GLabel(text_.string(), color_, fixtype_, scale_,
3028  x_align_, y_align_);
3029 }
3030 
3031 void GLabel::save(ostream& o, Coord x, Coord y) {
3032  if (labeled_line()) {
3033  return;
3034  }
3035  char buf[256];
3036  sprintf(buf, "save_window_.label(%g, %g, \"%s\", %d, %g, %g, %g, %d)",
3037  x, y, text_.string(), fixtype_, scale_, x_align_, y_align_,
3038  colors->color(color_)
3039  );
3040  o << buf << endl;
3041 }
3042 
3043 void GLabel::fixed(float scale) {
3044  fixtype_ = 1;
3045  scale_ = scale;
3046 }
3047 void GLabel::vfixed(float scale) {
3048  fixtype_ = 2;
3049  scale_ = scale;
3050 }
3051 void GLabel::relative(float scale) {
3052  fixtype_ = 0;
3053  scale_ = scale;
3054 }
3055 void GLabel::align(float x, float y) {
3056  x_align_ = x;
3057  y_align_ = y;
3058 }
3059 void GLabel::color(const Color* c) {
3060  Resource::unref(label_);
3061  WidgetKit& kit = *WidgetKit::instance();
3062  label_ = new Label(text_, kit.font(), c);
3063  label_->ref();
3064  Resource::ref(c);
3065  Resource::unref(color_);
3066  color_ = c;
3067  if (gpl_ && gpl_->color() != color()) {
3068  gpl_->color(color());
3069  }
3070 }
3071 
3072 void GLabel::text(const char* t) {
3073  Resource::unref(label_);
3074  WidgetKit& kit = *WidgetKit::instance();
3075  text_ = t;
3076  label_ = new Label(text_, kit.font(), color_);
3077  label_->ref();
3078 }
3079 
3080 void GLabel::request(Requisition& req)const {
3081  label_->request(req);
3082  Requirement& rx = req.x_requirement();
3083  Requirement& ry = req.y_requirement();
3084  rx.natural(rx.natural()*scale_);
3085  ry.natural(ry.natural()*scale_);
3086 //printf("ry.alignment=%g\n", ry.alignment());
3087  rx.alignment(x_align_);
3088  ry.alignment(y_align_ + ry.alignment());
3089 }
3090 void GLabel::allocate(Canvas* c, const Allocation& a, Extension& e) {
3091  e.set(c, a);
3092 }
3093 
3094 void GLabel::draw(Canvas* c, const Allocation& a1)const {
3095 //printf("GLabel::draw\n");
3096  Transformer t;
3097  Coord width = a1.x_allotment().span();
3098  Coord height = a1.y_allotment().span();
3099  Coord x = a1.x() - width*x_align_;
3100  Coord y = a1.y() - height*y_align_;
3101 //printf("x=%g y=%g\n", x, y);
3102  Allotment ax(0, width, 0);
3103  Allotment ay(0, height, 0);
3104  Allocation a2;
3105  a2.allot_x(ax);
3106  a2.allot_y(ay);
3107 
3108 //printf("xend = %g, yend=%g\n", a2.right(), a2.top());
3109  c->push_transform();
3110  t.scale(scale_, scale_);
3111  t.translate(x, y);
3112  c->transform(t);
3113 //float a00, a01, a10,a11,a20,a21;
3114 //c->transformer().matrix(a00,a01,a10,a11,a20,a21);
3115 //printf("transformer %g %g %g %g %g %g\n", a00, a01, a10, a11, a20, a21);
3116  label_->draw(c, a2);
3117  c->pop_transform();
3118  IfIdraw(text(c, text_.string(), t, NULL, color()));
3119 }
3120 
3121 //DataVec------------------
3122 
3123 DataVec::DataVec(int size) {
3124  y_ = new float[size];
3125  y_[0] = 0.;
3126  size_ = size;
3127  count_ = 0;
3128  iMinLoc_ = iMaxLoc_ = -1;
3129  running_min_loc_ = running_max_loc_ = -1;
3130 }
3131 
3132 DataVec::DataVec(const DataVec* v) {
3133  size_ = v->size_;
3134  y_ = new float[size_];
3135  count_ = v->count_;
3136  y_[0] = 0.;
3137  for (int i=0; i < count_; ++i) {
3138  y_[i] = v->y_[i];
3139  }
3140  iMinLoc_ = v->iMinLoc_;
3141  iMaxLoc_ = v->iMaxLoc_;
3142  running_min_loc_ = v->running_min_loc_;
3143  running_max_loc_ = v->running_max_loc_;
3144 }
3145 
3147  delete [] y_;
3148 }
3149 
3150 void DataVec::running_start() {
3151  if (count_) {
3152  running_min_loc_ = running_max_loc_ = count_ - 1;
3153  }else{
3154  running_min_loc_ = running_max_loc_ = 0;
3155  }
3156 }
3157 
3158 void DataVec::add(float x) {
3159  if ( count_ == size_) {
3160  size_ *= 2;
3161  float* y = new float[size_];
3162  for (int i=0; i<count_; i++) {
3163  y[i] = y_[i];
3164  }
3165  delete [] y_;
3166  y_ = y;
3167  }
3168  if (x > 1e30) { x = 1e32;}else if (x < -1e32) {x = -1e32;}
3169  y_[count_] = x;
3170  if (running_min_loc_ >= 0) {
3171  if ( x < get_val(running_min_loc_)) {
3172  running_min_loc_ = count_;
3173  }
3174  if ( x > get_val(running_max_loc_)) {
3175  running_max_loc_ = count_;
3176  }
3177  }
3178  ++count_;
3179  iMinLoc_ = iMaxLoc_ = -1;
3180 }
3181 
3182 float DataVec::max()const {return get_val(loc_max());}
3183 float DataVec::min()const {return get_val(loc_min());}
3184 
3185 float DataVec::running_max() {
3186  if (running_max_loc_ < 0) {
3187  return max();
3188  }else{
3189  return get_val(running_max_loc_);
3190  }
3191 }
3192 
3193 float DataVec::running_min() {
3194  if (running_min_loc_ < 0) {
3195  return min();
3196  }else{
3197  return get_val(running_min_loc_);
3198  }
3199 }
3200 
3201 int DataVec::loc_max()const {
3202  DataVec* dv = (DataVec*)this;
3203  if (iMaxLoc_ < 0) {
3204  int i; float m;
3205  for (i=0, dv->iMaxLoc_ = 0, m = y_[i++]; i < count_; i++) {
3206  if (m < y_[i]) {
3207  m = y_[i];
3208  dv->iMaxLoc_ = i;
3209  }
3210  }
3211  }
3212  return iMaxLoc_;
3213 }
3214 
3215 int DataVec::loc_min()const {
3216  DataVec* dv = (DataVec*)this;
3217  if (iMinLoc_ < 0) {
3218  int i; float m;
3219  for (i=0, dv->iMinLoc_ = 0, m = y_[i++]; i < count_; i++) {
3220  if (m > y_[i]) {
3221  m = y_[i];
3222  dv->iMinLoc_ = i;
3223  }
3224  }
3225  }
3226  return iMinLoc_;
3227 }
3228 
3229 float DataVec::max(int low, int high) {
3230  int imax = loc_max();
3231  if (imax >= low && imax < high) {
3232  return get_val(imax);
3233  }
3234  float m;
3235  for (m = y_[low++]; low < high; low++) {
3236  if (m < y_[low]) {
3237  m = y_[low];
3238  }
3239  }
3240  return m;
3241 }
3242 
3243 float DataVec::min(int low, int high) {
3244  int imin = loc_min();
3245  if (imin >= low && imin < high) {
3246  return get_val(imin);
3247  }
3248  float m;
3249  for (m = y_[low++]; low < high; low++) {
3250  if (m > y_[low]) {
3251  m = y_[low];
3252  }
3253  }
3254  return m;
3255 }
3256 
3257 void DataVec::erase() {
3258  count_ = 0;
3259  iMinLoc_ = iMaxLoc_ = -1;
3260  running_min_loc_ = running_max_loc_ = -1;
3261 }
3262 
3263 void DataVec::write() {
3264 #if 0
3265  cout << get_name() << endl;
3266  cout << count_ << endl;
3267  for (int i=0; i<count_; i++) {
3268  cout << y_[i] << endl;
3269  }
3270 #endif
3271 }
3272 
3273 DataPointers::DataPointers(int size) {
3274  count_ = 0;
3275  size_ = size;
3276  px_ = new double*[size];
3277 }
3279  delete [] px_;
3280 }
3281 void DataPointers::add(double* pd) {
3282  if ( count_ == size_) {
3283  size_ *= 2;
3284  double** px = new double*[size_];
3285  for (int i=0; i<count_; i++) {
3286  px[i] = px_[i];
3287  }
3288  delete [] px_;
3289  px_ = px;
3290  }
3291  px_[count_++] = pd;
3292 }
3293 
3294 GraphVector::GraphVector(const char* name, const Color* color, const Brush* brush)
3295  : GPolyLine(new DataVec(50), color, brush)
3296 {
3297  dp_ = new DataPointers();
3298  dp_->ref();
3299  name_ = name;
3300  keepable_ = true;
3301  disconnect_defer_ = false;
3302  record_install();
3303 }
3305  Oc oc;
3306  oc.notify_pointer_disconnect(this);
3307  dp_->unref();
3308  record_uninstall();
3309 }
3310 
3311 const char* GraphVector::name()const {
3312  return name_.string();
3313 }
3314 
3315 void GraphVector::save(ostream&) {
3316 }
3317 
3318 void GraphVector::begin() {
3319  dp_->erase();
3320  y_->erase();
3321  x_->erase();
3322 }
3323 
3324 static double zero;
3325 
3327  // cant notify_pointer_disconnect from here, it will screw up list
3328  disconnect_defer_ = true;
3329  begin();
3330 }
3331 
3332 void GraphVector::add(float x, double* py) {
3333  if (disconnect_defer_) {
3334  Oc oc;
3335  oc.notify_pointer_disconnect(this);
3336  disconnect_defer_ = false;
3337  }
3338  if (dp_->count() == 0 || py != dp_->p(dp_->count()-1) + 1){
3339  Oc oc;
3340  oc.notify_when_freed(py, this);
3341  }
3342  x_->add(x);
3343  double* p = &zero;
3344  if (py) {
3345  p = py;
3346  }
3347  dp_->add(p);
3348  y_->add(float(*p));
3349 }
3350 
3351 bool GraphVector::trivial() const {
3352  for (int i=0; i < dp_->count(); ++i) {
3353  if (dp_->p(i) != &zero) {
3354  return false;
3355  }
3356  }
3357  return true;
3358 }
3359 
3360 void GraphVector::request(Requisition& req)const {
3361  y_->erase();
3362  for (int i=0; i < dp_->count(); ++i) {
3363  y_->add(*dp_->p(i));
3364  }
3365  GPolyLine::request(req);
3366 }
3367 
3368 //LineExtension
3369 LineExtension::LineExtension(GPolyLine* gp) {
3370  gp_ = gp; // don't ref since this is referenced by the polyline
3371  start_ = previous_ = -1;
3372 }
3373 LineExtension::~LineExtension(){}
3374 
3375 void LineExtension::begin() {
3376  previous_ = yd()->count() -1;
3377  start_ = yd()->count() - 1;
3378  yd()->running_start();
3379 }
3380 void LineExtension::extend() {
3381  previous_ = start_;
3382  start_ = yd()->count() - 1;
3383  yd()->running_start();
3384 }
3385 
3386 
3387 void LineExtension::request(Requisition& req) const {
3388  Coord x, span;
3389  Coord x1, x2;
3390  const float eps = 1e-4;
3391  x1 = xd()->running_min(); x2= xd()->running_max();
3392  span = (x2 - x1);
3393  x = (x1);
3394  x = (span > 0)? x/span : 0;
3395  Requirement rx(span, 0, 0, -x);
3396  x1 = yd()->running_min(); x2= yd()->running_max();
3397  span = (x2 - x1)/2;
3398  x = (x1);
3399  x = (span > 0)? x/span : 0;
3400  Requirement ry(span, 0, 0, -x);
3401  req.require_x(rx);
3402  req.require_y(ry);
3403 }
3404 
3405 void LineExtension::allocate(Canvas* c, const Allocation& a, Extension& e) {
3406  e.set(c, a);
3407 // MyMath::extend(e, gp_->brush()->width()/2 + 1);
3408 }
3409 
3410 void LineExtension::draw(Canvas* c, const Allocation& a) const {
3411 #if 0
3412  if (previous_ >= 0) {
3413  gp_->draw_specific(c, a, previous_, xd()->count());
3414  }else
3415 #endif
3416  if (start_ >= 0) {
3417  gp_->draw_specific(c, a, start_, xd()->count());
3418  }
3419 }
3420 
3421 void LineExtension::damage(Graph* g) {
3422  g->damage(xd()->running_min(), yd()->running_min(),
3423  xd()->running_max(), yd()->running_max()
3424  );
3425 }
3426 
3427 void Graph::change_prop() {
3428  picker()->bind_select((OcHandler*)NULL);
3429  picker()->set_scene_tool(CHANGECOLOR);
3431  if (Oc::helpmode()) {
3432  help();
3433  }
3434 }
3435 
3436 void Graph::update_ptrs() {
3437  if (x_pval_) {
3438  x_pval_ = nrn_recalc_ptr(x_pval_);
3439  }
3440  if (rvp_) { rvp_->update_ptrs(); }
3441  GlyphIndex i, cnt = count();
3442  for (i=0; i < cnt; ++i) {
3443  GraphItem* gi = (GraphItem*)component(i);
3444  if (gi->is_graphVector()) {
3445  GraphVector* gv = (GraphVector*)(gi->body());
3446  if (gv) {
3447  gv->update_ptrs();
3448  }
3449  }
3450  }
3451  cnt = line_list_.count();
3452  for (i=0; i < line_list_.count(); ++i) {
3453  line_list_.item(i)->update_ptrs();
3454  }
3455 }
3456 
3458  int i;
3459  for (i=0; i < count_; ++i) {
3460  px_[i] = nrn_recalc_ptr(px_[i]);
3461  }
3462 }
3463 
3464 void GraphLine::update_ptrs() {
3465  if (pval_) {
3466  pval_ = nrn_recalc_ptr(pval_);
3467  }
3468 }
3469 
3470 void GraphVector::update_ptrs() {
3471  if (dp_) { dp_->update_ptrs(); }
3472 }
3473 
3474 #endif /* HAVE_IV */
o
Definition: seclist.cpp:180
void allot_x(const Allotment &)
Definition: geometry.h:282
static MenuItem * menu_item(const char *)
virtual void damage_all()
virtual void request(Requisition &) const
void update_ptrs()
static double gr_view_count(void *v)
Definition: graph.cpp:1036
Definition: hocdec.h:84
virtual void delete_label(GLabel *)
void axis(DimensionName, float min, float max, float pos=0., int ntics=-1, int nminor=0, int invert=0, bool number=true)
virtual ~GPolyLine()
virtual ~ColorPalette()
void flush()
double max(double a, double b)
Definition: geometry3d.cpp:22
#define assert(ex)
Definition: hocassrt.h:26
static double gr_addvar(void *v)
Definition: graph.cpp:540
Coord x(int index) const
Definition: graph.h:228
virtual Coord bottom() const
static HocMark * instance(char style, float size, const Color *, const Brush *)
virtual void printfile(const char *)
short type
Definition: cabvars.h:10
static bool helpmode()
Definition: ivoc.h:66
virtual int view_count() const
int hoc_is_str_arg(int narg)
Definition: code.cpp:741
void set(Canvas *, const Allocation &)
static double gr_begin(void *v)
Definition: graph.cpp:635
void hoc_free_list(Symlist **)
Coord x() const
Definition: geometry.h:290
void keep_lines_toggle()
void family(bool)
float running_max()
#define text
Definition: plot.cpp:81
static char * pattern
Definition: regexp.cpp:82
const Transformer & s2o() const
Definition: scenevie.h:132
GPolyLine * gpl_
Definition: graph.h:370
#define Vect
Definition: ivocvect.h:14
#define TRY_GUI_REDIRECT_NO_RETURN(name, obj)
Definition: gui-redirect.h:44
void write()
#define WidgetKit
Definition: _defines.h:331
if(status)
virtual ~GraphLine()
static double gr_fixed(void *v)
Definition: graph.cpp:866
double ivoc_gr_size(void *v)
Definition: graph.cpp:789
void begin()
virtual void append(Glyph *)
#define min(a, b)
Definition: matrix.h:157
GraphVector(const char *, const Color *=NULL, const Brush *=NULL)
void plot(float)
void erase_axis()
virtual bool is_mark()
Definition: ivoc.h:36
#define g
Definition: passive0.cpp:23
virtual void save_phase2(std::ostream &)
void extension_start()
double ivoc_gr_begin_line(void *v)
Definition: graph.cpp:671
bool trivial() const
#define TransformSetter
Definition: _defines.h:315
#define Glyph
Definition: _defines.h:132
#define Coord
Definition: _defines.h:19
int running_max_loc_
Definition: graph.h:184
void extension_continue()
GLabel * new_proto_label() const
static double valid(void *v)
Definition: linmod1.cpp:52
void begin()
#define Brush
Definition: _defines.h:59
void * this_pointer
Definition: hocdec.h:231
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:84
size_t p
#define Color
Definition: _defines.h:74
static double gr_yaxis(void *v)
Definition: graph.cpp:247
bool valid(bool check=false)
static double gr_vfixed(void *v)
Definition: graph.cpp:881
void relative(float scale)
double runExpr(Symbol *)
#define Scene
Definition: _defines.h:251
#define RubberRect
Definition: _defines.h:240
virtual Coord top() const
float get_val(int i) const
Definition: graph.h:175
static double gr_color(void *v)
Definition: graph.cpp:929
virtual void save_phase1(std::ostream &)
static void help(const char *)
Definition: graph.h:163
void add_graphVector(GraphVector *)
#define IfIdraw(arg)
Definition: idraw.h:61
bool keepable()
Definition: graph.h:241
static double location(void *v)
Definition: impedanc.cpp:82
const char * name() const
const Brush * save_brush() const
Definition: graph.h:269
#define Handler
Definition: _defines.h:146
void fast_flush()
void init(DataVec *, DataVec *, const Color *, const Brush *)
GLabel * label(float x, float y, const char *s, int fixtype, float scale, float x_align, float y_align, const Color *)
#define v
Definition: md1redef.h:4
GraphLine * add_var(const char *, const Color *, const Brush *, bool usepointer, int fixtype=1, double *p=NULL, const char *lab=NULL, Object *obj=NULL)
const char * text() const
Definition: graph.h:351
#define Image
Definition: _defines.h:150
Coord y() const
Definition: geometry.h:291
static double gr_fast_flush(void *v)
Definition: graph.cpp:717
int count() const
Definition: graph.h:173
const Requirement & x_requirement() const
Definition: geometry.h:249
virtual void pick_vector()
virtual void save(std::ostream &)
virtual void allocate(Canvas *, const Allocation &, Extension &)
virtual void ref() const
Definition: resource.cpp:47
static philox4x32_key_t k
Definition: nrnran123.cpp:11
void keep_lines()
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
static double gr_vector(void *v)
Definition: graph.cpp:589
const Color * color() const
Definition: graph.h:225
static bool inside(Coord x, Coord min, Coord max)
Definition: mymath.h:97
ColorPalette * colors
#define TRY_GUI_REDIRECT_ACTUAL_DOUBLE(name, obj)
Definition: gui-redirect.h:66
void size(Coord x1, Coord y1, Coord x2, Coord y2)
void simgraph_continuous(double)
float scale() const
Definition: graph.h:350
virtual GlyphIndex glyph_index(const Glyph *)
void nrn_hoc_lock()
Definition: multicore.cpp:1064
#define e
Definition: passive0.cpp:24
virtual void draw(Canvas *, const Allocation &) const
const DataVec * x_data() const
Definition: graph.h:230
#define gargstr
Definition: hocdec.h:14
void choose_sym()
static double gr_view(void *v)
Definition: graph.cpp:969
double * hoc_pgetarg(int narg)
Definition: code.cpp:1604
void family_label_chooser()
void restore()
Definition: ocjump.cpp:303
int iMinLoc_
Definition: graph.h:183
#define FontBoundingBox
Definition: _defines.h:121
Definition: graph.h:48
virtual bool is_graphVector()
Definition: graph.h:42
void plot()
void init()
Definition: init.cpp:169
void add_polyline(GPolyLine *)
virtual void request(Requisition &) const
static const Color * default_foreground()
void change_line_color(GPolyLine *)
int loc_min() const
virtual void wholeplot(Coord &x1, Coord &y1, Coord &x2, Coord &y2) const
bool var_pair_chooser(const char *, float &x, float &y, Window *w=NULL, Coord x1=400., Coord y1=400.)
virtual void map()
Symbol * parseExpr(const char *, Symlist **=NULL)
double ivoc_gr_menu_remove(void *v)
Definition: graph.cpp:1107
void brush(const Brush *)
#define implementPtrList(PtrList, T)
void text(const char *)
const char * name(Symbol *)
virtual void save(std::ostream &)
int hoc_is_pdouble_arg(int narg)
Definition: code.cpp:737
void append(Item *ql, Item *q)
Definition: list.cpp:348
void erase()
void hoc_obj_set(int i, Object *obj)
Definition: hoc_oop.cpp:77
bool mark()
Definition: scenevie.h:265
int loc_max() const
void allot_y(const Allotment &)
Definition: geometry.h:283
static bool label_chooser(const char *, char *, GLabel *, Coord x=400., Coord y=400.)
static double gr_flush(void *v)
Definition: graph.cpp:705
static double gr_set_cross_action(void *v)
Definition: graph.cpp:1063
virtual void new_size(Coord x1, Coord y1, Coord x2, Coord y2)
static double gr_addexpr(void *v)
Definition: graph.cpp:549
double(* nrnpy_object_to_double_)(Object *)
Definition: xmenu.cpp:14
static double gr_printfile(void *v)
Definition: graph.cpp:1084
int const size_t const size_t n
Definition: nrngsl.h:12
#define color
Definition: rbtqueue.cpp:50
#define Menu
Definition: _defines.h:176
static double check(double t, Daspk *ida)
Definition: nrndaspk.cpp:214
Object ** new_vect(GLabel *g=NULL) const
#define Printer
Definition: _defines.h:211
int count_
Definition: graph.h:183
int hoc_execerror_messages
Definition: hoc.cpp:666
virtual ~DataVec()
const Requirement & y_requirement() const
Definition: geometry.h:250
const char * name() const
static ostream * save_stream
Definition: ivoc.h:71
void notify_pointer_disconnect(Observer *)
virtual void damage(GlyphIndex)
_CONST char * s
Definition: system.cpp:74
float running_min()
virtual void background(Glyph *bg=NULL)
virtual void help()
static std::ostream * ascii()
virtual void view_ratio(float xratio, float yratio, Coord &x, Coord &y) const
void line(Coord x, Coord y)
void class2oc(const char *, void *(*cons)(Object *), void(*destruct)(void *), Member_func *, int(*checkpoint)(void **), Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1581
void hoc_obj_unref(Object *obj)
Definition: hoc_oop.cpp:1998
void plot(Coord x, Coord y)
static double gr_align(void *v)
Definition: graph.cpp:911
virtual Coord left() const
void add(float)
int fixtype() const
Definition: graph.h:352
void update_ptrs()
static void gr_destruct(void *v)
Definition: graph.cpp:1188
static double gr_brush(void *v)
Definition: graph.cpp:948
static double gr_unmap(void *v)
Definition: graph.cpp:1050
#define printf
Definition: mwprefix.h:26
void family_value()
static N_Vector x_
Coord y(int index) const
Definition: graph.h:229
double ivoc_gr_label(void *v)
Definition: graph.cpp:842
GPolyLine(DataVec *x, const Color *=NULL, const Brush *=NULL)
void alignment(float)
Definition: geometry.h:241
void change_prop()
virtual void erase_all()
int
Definition: nrnmusic.cpp:71
virtual void help()
void running_start()
void hoc_warning(const char *, const char *)
static void start(Graph *)
#define CopyString
Definition: _defines.h:2
static std::ostream * ascii_
Definition: graph.h:160
virtual void save(std::ostream &, Coord, Coord)
Definition: axis.h:9
bool erase_flag()
Definition: graph.h:356
virtual void save(std::ostream &, Coord, Coord)
float max() const
static XYView * current_draw_view()
#define ENDGUI
Definition: hocdec.h:352
#define GlyphIndex
Definition: _defines.h:23
static void help(const char *)
Definition: hel2mos.cpp:104
void view_axis()
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
double ivoc_view_info(void *v)
Definition: graph.cpp:344
void location(GlyphIndex, Coord &x, Coord &y) const
double gr_line_info(void *v)
Definition: graph.cpp:442
static double gr_addobject(void *v)
Definition: graph.cpp:558
#define cnt
Definition: spt2queue.cpp:19
#define Canvas
Definition: _defines.h:65
void require_y(const Requirement &)
Definition: geometry.h:248
static double exec_menu(void *v)
Definition: graph.cpp:1097
const Brush * brush(int) const
static Member_func gr_members[]
Definition: graph.cpp:1122
int iMaxLoc_
Definition: graph.h:183
virtual void draw(Canvas *, const Allocation &) const
size_t j
virtual XYView * sceneview(int) const
virtual void draw(Canvas *, const Allocation &) const
void move(GlyphIndex, Coord x, Coord y)
Definition: model.h:57
virtual void insert(GlyphIndex, Glyph *)
static void extend(Extension &, Coord)
Definition: mymath.h:89
void hoc_push_object(Object *d)
Definition: code.cpp:657
virtual void unref() const
Definition: resource.cpp:52
void align(float x, float y)
GraphItem(Glyph *g, bool=true, bool pick=true)
const Color * color() const
Definition: graph.h:355
virtual void zout(Coord &x1, Coord &y1, Coord &x2, Coord &y2) const
char * name
Definition: init.cpp:16
void erase()
Definition: graph.h:220
virtual void new_size(Coord x1, Coord y1, Coord x2, Coord y2)
void erase()
bool save()
Definition: graph.h:37
inode< _nt-> end
Definition: multicore.cpp:985
static N_Vector y_
bool pick_
Definition: graph.h:45
bool fixed() const
Definition: graph.h:349
BrushPalette * brushes
double ivoc_gr_menu_action(void *v)
Definition: graph.cpp:308
unsigned int DimensionName
Definition: geometry.h:40
void change_label_color(GLabel *)
virtual void update(Observable *)
void color(const Color *)
#define left
Definition: rbtqueue.cpp:45
const Brush * brush() const
Definition: graph.h:90
virtual void move(const Event &e)
Definition: ocinput.h:19
#define Event
Definition: _defines.h:107
void xplace(int left, int top)
Definition: ivocmac.cpp:229
virtual ~BrushPalette()
void relative(float scale)
void label_loc(Coord &x, Coord &y) const
void extension_start()
bool save_
Definition: graph.h:44
int size() const
Definition: graph.h:176
const Brush * brush() const
Definition: graph.h:226
int ifarg(int)
Definition: code.cpp:1562
void add(double *)
double ivoc_gr_line(void *v)
Definition: graph.cpp:694
void color(const Color *)
#define lookup
Definition: redef.h:90
#define right
Definition: rbtqueue.cpp:46
virtual ~GraphItem()
static double gr_relative(void *v)
Definition: graph.cpp:896
virtual bool choose_sym(Graph *)
void update_ptrs()
void cross_action(char, GPolyLine *, int)
GPolyLine * labeled_line() const
Definition: graph.h:359
void vfixed(float scale)
void hoc_pushx(double)
virtual void save(std::ostream &)
double ivoc_view_size(void *v)
Definition: graph.cpp:427
void require_x(const Requirement &)
Definition: geometry.h:247
GLabel(const char *s, const Color *, int fixtype=1, float size=12, float x_align=0., float y_align=0.)
virtual void see_range_plot(GraphVector *)
virtual void pick(Canvas *, const Allocation &, int depth, Hit &)
Graph(bool=true)
virtual ~GLabel()
#define TRY_GUI_REDIRECT_OBJ(name, obj)
Definition: gui-redirect.h:12
void nrn_hoc_unlock()
Definition: multicore.cpp:1072
Canvas * canvas()
virtual Scene * scene() const
Vect * vector_arg(int i)
Definition: ivocvect.cpp:332
#define Transformer
Definition: _defines.h:316
void notify_when_freed(void *p, Observer *)
void span(Coord)
Definition: geometry.h:269
static double gr_xexpr(void *v)
Definition: graph.cpp:618
double ivoc_erase_all(void *v)
Definition: graph.cpp:741
static double gr_family(void *v)
Definition: graph.cpp:292
static SymChooser * fsc_
Definition: graph.h:138
static int component(PyHocObject *po)
Definition: nrnpy_hoc.cpp:448
#define symlist
Definition: cabcode.cpp:17
void Graph_reg()
Definition: graph.cpp:1198
double gr_addglyph(void *)
Definition: grglyph.cpp:31
Definition: hocdec.h:226
static const Color * default_background()
void align(float x, float y)
void simgraph_init()
#define getarg
Definition: hocdec.h:15
virtual void remove(GlyphIndex)
#define Label
Definition: _defines.h:159
static double gr_plot(void *v)
Definition: graph.cpp:647
float min() const
virtual Coord width() const
virtual void pick(Canvas *, const Allocation &, int depth, Hit &)
double * hoc_val_pointer(const char *s)
Definition: code2.cpp:699
int hoc_return_type_code
Definition: code.cpp:41
void add(float, double *)
Definition: scenevie.h:185
GraphLine(const char *, DataVec *x, Symlist **, const Color *=NULL, const Brush *=NULL, bool usepointer=0, double *pd=NULL, Object *obj=NULL)
virtual ~Graph()
DataVec(int size)
virtual void update(Observable *)
#define i
Definition: md1redef.h:12
double ivoc_gr_mark(void *v)
Definition: graph.cpp:1003
int is_obj_type(Object *obj, const char *type_name)
Definition: hoc_oop.cpp:2223
#define c
void fixed(float scale)
void x_expr(const char *, bool usepointer)
void simgraph_activate(bool)
double * vector_vec(Vect *v)
Definition: ivocvect.cpp:271
void fixed(float scale)
virtual bool is_polyline()
static char line[MAXLINE]
Definition: ivecop.c:35
int size_
Definition: graph.h:183
DataPointers(int size=50)
Object * hoc_obj_ptr()
Definition: scenevie.h:275
Allotment & x_allotment()
Definition: geometry.h:285
Definition: graph.h:329
virtual ~DataPointers()
virtual void ratio_view(Coord x, Coord y, float &xratio, float &yratio) const
void new_axis()
#define Window
Definition: _defines.h:333
char buf[512]
Definition: init.cpp:13
double ivoc_gr_gif(void *v)
Definition: graph.cpp:753
#define Style
Definition: _defines.h:281
virtual void damage_area(Coord &x1, Coord &y1, Coord &x2, Coord &y2) const
virtual GlyphIndex count() const
double ivoc_gr_menu_tool(void *v)
Definition: graph.cpp:326
bool change_expr(const char *, Symlist **)
virtual bool change_label(GLabel *, const char *, GLabel *gl=NULL)
GLabel * label() const
Definition: graph.h:233
#define relative(pc)
Definition: cabcode.cpp:2149
#define MenuItem
Definition: _defines.h:179
void name(char *)
virtual GlyphIndex glyph_index(const Glyph *)
int hoc_is_object_arg(int narg)
Definition: code.cpp:745
virtual void allocate(Canvas *, const Allocation &, Extension &)
#define imax
double ivoc_gr_erase(void *v)
Definition: graph.cpp:729
void erase_lines()
virtual void pick(Canvas *, const Allocation &, int depth, Hit &)
void begin_line(const char *s=NULL)
virtual void wholeplot(Coord &x1, Coord &y1, Coord &x2, Coord &y2) const
double hoc_ac_
Definition: hoc_init.cpp:261
static double gr_simgraph(void *v)
Definition: graph.cpp:659
Allotment & y_allotment()
Definition: geometry.h:286
float * y_
Definition: graph.h:185
#define MonoGlyph
Definition: _defines.h:181
virtual void erase(Scene *, GlyphIndex, int erase_type)
virtual void draw_specific(Canvas *, const Allocation &, int, int) const
union Object::@54 u
void view_box()
#define IFGUI
Definition: hocdec.h:351
double t
Definition: init.cpp:123
const DataVec * y_data() const
Definition: graph.h:231
int running_min_loc_
Definition: graph.h:184
static XYView * current_pick_view()
virtual void draw(Canvas *, const Allocation &) const
int run(int argc, const char **argv)
const Color * save_color() const
Definition: graph.h:268
virtual Coord height() const
void update_ptrs()
const Color * color() const
Definition: graph.h:89
#define begin
Definition: redef.h:32
void ascii_save(std::ostream &o) const
Object ** hoc_objgetarg(int)
Definition: code.cpp:1568
virtual Coord right() const
virtual void zin(Coord &x1, Coord &y1, Coord &x2, Coord &y2) const
static long scene_list_index(Scene *)
virtual bool is_polyline()
const Color * color(int) const
double var(InputIterator begin, InputIterator end)
Definition: ivocvect.h:93
invert
Definition: extdef.h:3
void vfixed(float scale)
return NULL
Definition: cabcode.cpp:461
void set_cross_action(const char *, Object *, bool vectorcopy=false)
virtual ~GraphVector()
double chkarg(int, double low, double high)
Definition: code2.cpp:608
static void * gr_cons(Object *ho)
Definition: graph.cpp:1170
virtual void request(Requisition &) const
double * nrn_recalc_ptr(double *)
Definition: treeset.cpp:2158
static double gr_save_name(void *v)
Definition: graph.cpp:256
virtual Glyph * clone() const
void natural(Coord)
Definition: geometry.h:235
void extension_continue()
static double gr_xaxis(void *v)
Definition: graph.cpp:238
static bool valid_expr(Symbol *)
#define Hit
Definition: _defines.h:147
virtual void print(Printer *, const Allocation &) const
virtual void dismiss()
virtual void erase_line(Scene *, GlyphIndex)