NEURON
grmanip.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #if HAVE_IV // to end of file
3 
4 #include <InterViews/canvas.h>
5 #include <InterViews/transformer.h>
6 #include <InterViews/label.h>
7 #include <InterViews/hit.h>
8 #include <InterViews/cursor.h>
9 #include <IV-look/kit.h>
10 
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include "ivoc.h"
15 #include "mymath.h"
16 #include "rubband.h"
17 #include "graph.h"
18 #include "hocmark.h"
19 #include "utility.h"
20 
21 #define LineRubberMarker_event_ "Crosshair Graph"
22 #define DeleteLabelHandler_event_ "Delete Graph"
23 #define ChangeLabelHandler_event_ "ChangeText"
24 #define DeleteLineHandler_event_ "Delete Graph"
25 #define LinePicker_event_ "Pick Graph"
26 #define MoveLabelBand_press_ "MoveText Graph"
27 
28 extern double hoc_cross_x_, hoc_cross_y_;
29 
30 class LineRubberMarker: public Rubberband {
31  public:
32  LineRubberMarker(GPolyLine*, RubberAction*, Canvas* c = NULL);
33  LineRubberMarker(Coord, Coord, RubberAction*, Canvas* c = NULL);
34  virtual ~LineRubberMarker();
35  virtual bool event(Event&);
36  virtual void undraw(Coord, Coord);
37  virtual void draw(Coord, Coord);
38  int index() {
39  return index_;
40  }
41 
42  private:
43  GPolyLine* gl_;
44  Label* label_;
45  Coord x_, y_;
46  int index_;
47 #if defined(WIN32)
48  CopyString def_str_;
49 #endif
50 };
51 
52 class MoveLabelBand: public Rubberband {
53  public:
54  MoveLabelBand(GLabel*, RubberAction*, Canvas* = NULL);
55  virtual ~MoveLabelBand();
56  virtual void draw(Coord, Coord);
57  virtual void press(Event&);
58  virtual void release(Event&);
59 
60  private:
61  GLabel* gl_;
62  GLabel* label_;
63  GlyphIndex index_;
64  Allocation a_;
65  Coord x0_, y0_;
66 };
67 
68 /*static*/ class DeleteLabelHandler: public Handler {
69  public:
70  DeleteLabelHandler(GLabel*);
71  ~DeleteLabelHandler();
72  virtual bool event(Event&);
73 
74  private:
75  GLabel* gl_;
76 };
77 
78 /*static*/ class ChangeLabelHandler: public Handler {
79  public:
80  ChangeLabelHandler(GLabel*);
81  ~ChangeLabelHandler();
82  virtual bool event(Event&);
83 
84  private:
85  GLabel* gl_;
86 };
87 
88 /*static*/ class DeleteLineHandler: public Handler {
89  public:
90  DeleteLineHandler(GPolyLine*);
91  ~DeleteLineHandler();
92  virtual bool event(Event&);
93 
94  private:
95  GPolyLine* gpl_;
96 };
97 
98 /*static*/ class LinePicker: public Rubberband {
99  public:
100  LinePicker(GPolyLine*);
101  ~LinePicker();
102  virtual void press(Event&);
103  virtual void release(Event&);
104 
105  private:
106  void common();
107 
108  private:
109  GPolyLine* gpl_;
110  const Color* c_;
111 };
112 
113 void GraphLine::pick(Canvas* c, const Allocation& a, int depth, Hit& h) {
114  GPolyLine::pick(c, a, depth, h);
115 }
116 
117 void GPolyLine::pick(Canvas* c, const Allocation&, int depth, Hit& h) {
118  if (h.count() && h.target(depth, 0)) {
119  return;
120  }
121  if (h.event() && h.event()->type() == Event::down &&
122  h.event()->pointer_button() == Event::left) {
123  Coord x = h.left(), y = h.bottom();
124  switch (XYView::current_pick_view()->scene()->tool()) {
125  case Graph::CROSSHAIR:
126  if (near(x, y, 10, c->transformer())) {
127  h.target(depth, this, 0, new LineRubberMarker(this, NULL, c));
128  }
129  break;
130  case Scene::DELETE:
131  if (near(x, y, 10, c->transformer())) {
132  h.target(depth, this, 0, new DeleteLineHandler(this));
133  }
134  break;
135  case Graph::CHANGECOLOR:
136  if (near(x, y, 10, c->transformer())) {
138  }
139  break;
140  case Graph::PICK:
141  if (near(x, y, 5, c->transformer())) {
142  h.target(depth, this, 0, new LinePicker(this));
143  }
144  break;
145  }
146  }
147 }
148 void HocMark::pick(Canvas* c, const Allocation& a, int depth, Hit& h) {
149  if (h.count() && h.target(depth, 0)) {
150  return;
151  }
152  if (h.event() && h.event()->type() == Event::down &&
153  h.event()->pointer_button() == Event::left) {
154  Coord x = h.left(), y = h.bottom();
155  switch (XYView::current_pick_view()->scene()->tool()) {
156  case Graph::CROSSHAIR:
157  h.target(depth, this, 0, new LineRubberMarker(a.x(), a.y(), NULL, c));
158  break;
159  }
160  }
161 }
162 
163 bool GPolyLine::near(Coord xcm, Coord ycm, float epsilon, const Transformer& t) const {
164  if (x_->count() <= 0) {
165  return false;
166  }
167  int index = nearest(xcm, ycm, t);
168  Coord xc, yc, x1, x2, y1, y2;
169  x1 = x(index);
170  y1 = y(index);
171  if (index < x_->count() - 1) {
172  x2 = x(index + 1);
173  y2 = y(index + 1);
174  } else {
175  x2 = x1;
176  y2 = y1;
177  }
178  // printf("nearest model %g %g to mouse %g %g\n", x1, y1, xcm, ycm);
179  t.transform(xcm, ycm, xc, yc);
180  t.transform(x1, y1);
181  t.transform(x2, y2);
182  // printf("nearest mouse %g %g box %g %g %g %g\n", xc, yc, x1, y1, x2, y2);
183  return MyMath::near_line(xc, yc, x1, y1, x2, y2, epsilon);
184 }
185 
186 int GPolyLine::nearest(Coord x1, Coord y1, const Transformer& t, int index_begin) const {
187  int index, i;
188  int count = x_->count();
189  Coord x, y, xt, yt;
190  t.transform(x1, y1, x, y);
191 
192 #define Norm2(lval, arg) \
193  t.transform(x_->get_val(arg), y_->get_val(arg), xt, yt); \
194  lval = MyMath::norm2(x - xt, y - yt);
195 
196  float dxmin, dx;
197  if (index_begin < 0) {
198  index = 0;
199  Norm2(dxmin, 0);
200  for (i = 1; i < count; ++i) {
201  Norm2(dx, i);
202  if (dx < dxmin) {
203  dxmin = dx;
204  index = i;
205  }
206  }
207  } else {
208  float dxleft, dxright;
209  i = index = index_begin;
210  Norm2(dxmin, i);
211  dxleft = dxright = dxmin;
212  if (i - 1 >= 0) {
213  Norm2(dxleft, i - 1);
214  }
215  if (i + 1 > count) {
216  Norm2(dxright, i + 1);
217  }
218  if (dxright < dxleft) {
219  while (++i < count) {
220  Norm2(dx, i);
221  if (dx < dxmin) {
222  dxmin = dx;
223  index = i;
224  } else {
225  break;
226  }
227  }
228  } else {
229  while (--i >= 0) {
230  Norm2(dx, i);
231  if (dx < dxmin) {
232  dxmin = dx;
233  index = i;
234  } else {
235  break;
236  }
237  }
238  }
239  }
240  return index;
241 }
242 
243 LineRubberMarker::LineRubberMarker(GPolyLine* gl, RubberAction* ra, Canvas* c)
244  : Rubberband(ra, c) {
245  // printf("LineRubberMarker\n");
246  gl_ = gl;
247  Resource::ref(gl);
248  label_ = NULL;
249  index_ = -1;
250 }
251 LineRubberMarker::LineRubberMarker(Coord x, Coord y, RubberAction* ra, Canvas* c)
252  : Rubberband(ra, c) {
253  // printf("LineRubberMarker\n");
254  gl_ = NULL;
255  label_ = NULL;
256  index_ = -1;
257  x_ = x;
258  y_ = y;
259 }
260 LineRubberMarker::~LineRubberMarker() {
261  // printf("~LineRubberMarker\n");
262  Resource::unref(gl_);
263  Resource::unref(label_);
264 }
265 bool LineRubberMarker::event(Event& e) {
266  if (Oc::helpmode()) {
267  if (e.type() == Event::down) {
268  Oc::help(LineRubberMarker_event_);
269  }
270  return true;
271  }
272  if (e.type() == Event::key) {
273  char buf[2];
274  if (e.mapkey(buf, 1) > 0) {
275  if (gl_) {
276  ((Graph*) XYView::current_pick_view()->scene())->cross_action(buf[0], gl_, index_);
277  } else {
278  ((Graph*) XYView::current_pick_view()->scene())->cross_action(buf[0], x_, y_);
279  }
280  }
281  return true;
282  } else {
283 #if defined(WIN32)
284  if (e.type() == Event::down) {
285  def_str_ = ((DismissableWindow*) canvas()->window())->name();
286  } else if (e.type() == Event::up) {
287  ((DismissableWindow*) canvas()->window())->name(def_str_.string());
288  }
289 #endif
290  return Rubberband::event(e);
291  }
292 }
293 void LineRubberMarker::undraw(Coord, Coord) {
294  Coord x, y;
295  transformer().transform(x_, y_, x, y);
296  Canvas* c = canvas();
297  Transformer identity;
298  c->push_transform();
299  c->transformer(identity);
300 #if !defined(WIN32)
301  Allocation a;
302  a.allot_x(Allotment(x + 20, 0, 0));
303  a.allot_y(Allotment(y, 0, 0));
304  label_->draw(c, a);
305 #endif
306  c->line(x - 10, y, x + 10, y, Rubberband::color(), Rubberband::brush());
307  c->line(x, y - 10, x, y + 10, Rubberband::color(), Rubberband::brush());
308  c->pop_transform();
309 }
310 void LineRubberMarker::draw(Coord x, Coord y) {
311  // printf("draw %g %g", x, y);
312  Coord x1, y1;
313  transformer().inverse_transform(x, y, x1, y1);
314  // printf(" model %g %g", x1, y1);
315  if (gl_) {
316  index_ = gl_->nearest(x1, y1, transformer(), index_);
317  x_ = gl_->x(index_);
318  y_ = gl_->y(index_);
319  // printf(" on line %g %g\n", x_, y_);
320  }
321  char s[50];
322 
323 #if defined(WIN32)
324  Sprintf(s, "crosshair x=%g y=%g", x_, y_);
325  ((DismissableWindow*) canvas()->window())->name(s);
326 #else
327  Sprintf(s, "(%g,%g)", x_, y_);
328  Resource::unref(label_);
329  label_ = new Label(s, WidgetKit::instance()->font(), Rubberband::color());
330 #endif
331  hoc_cross_x_ = x_;
332  hoc_cross_y_ = y_;
333  undraw(0, 0);
334 }
335 
336 void GLabel::pick(Canvas* c, const Allocation&, int depth, Hit& h) {
337  if (h.count() && h.target(depth, 0)) {
338  return;
339  }
340  if (h.event() && h.event()->type() == Event::down &&
341  h.event()->pointer_button() == Event::left) {
342  // printf("GLabel picked %s\n", text_.string());
343  switch (XYView::current_pick_view()->scene()->tool()) {
344  case Scene::MOVE:
345  h.target(depth, this, 0, new MoveLabelBand(this, NULL, c));
346  break;
347  case Scene::DELETE:
348  h.target(depth, this, 0, new DeleteLabelHandler(this));
349  break;
350  case Scene::CHANGECOLOR:
352  break;
353  case Graph::CHANGELABEL:
354  h.target(depth, this, 0, new ChangeLabelHandler(this));
355  }
356  }
357 }
358 
359 DeleteLabelHandler::DeleteLabelHandler(GLabel* gl) {
360  // printf("DeleteLabelHandler\n");
361  gl_ = gl;
362 }
363 
364 DeleteLabelHandler::~DeleteLabelHandler() {
365  // printf("~DeleteLabelHandler\n");
366 }
367 bool DeleteLabelHandler::event(Event& e) {
368  if (Oc::helpmode()) {
369  if (e.type() == Event::down) {
370  Oc::help(DeleteLabelHandler_event_);
371  }
372  return true;
373  }
375  return true;
376 }
377 
378 ChangeLabelHandler::ChangeLabelHandler(GLabel* gl) {
379  // printf("ChangeLabelHandler\n");
380  gl_ = gl;
381 }
382 
383 ChangeLabelHandler::~ChangeLabelHandler() {
384  // printf("~ChangeLabelHandler\n");
385 }
386 bool ChangeLabelHandler::event(Event& e) {
387  if (Oc::helpmode()) {
388  if (e.type() == Event::down) {
389  Oc::help(ChangeLabelHandler_event_);
390  }
391  return true;
392  }
393  char buf[200];
394  strcpy(buf, gl_->text());
395  GLabel* gl = (GLabel*) gl_->clone();
396  gl->ref();
397  if (Graph::label_chooser("Modify Label", buf, gl, e.pointer_root_x(), e.pointer_root_y())) {
398  ((Graph*) (XYView::current_pick_view()->scene()))->change_label(gl_, buf, gl);
399  }
400  gl->unref();
401  return true;
402 }
403 
405  printf("No method for changeing label color %s\n", gl->text());
406 }
407 
409  printf("No method for changeing line color \n");
410 }
411 
412 void Scene::delete_label(GLabel* gl) {
413  printf("No method for deleting label %s\n", gl->text());
414 }
415 
416 DeleteLineHandler::DeleteLineHandler(GPolyLine* gpl) {
417  // printf("DeleteLineHandler\n");
418  gpl_ = gpl;
419 }
420 
421 DeleteLineHandler::~DeleteLineHandler() {
422  // printf("~DeleteLineHandler\n");
423 }
424 bool DeleteLineHandler::event(Event& e) {
425  if (Oc::helpmode()) {
426  if (e.type() == Event::down) {
427  Oc::help(DeleteLineHandler_event_);
428  }
429  return true;
430  }
432  GlyphIndex i = s->glyph_index(gpl_);
433  s->modified(i);
434  s->damage(i);
435  gpl_->erase_line(s, i);
436  return true;
437 }
438 
439 LinePicker::LinePicker(GPolyLine* gpl)
440  : Rubberband() {
441  // printf("LinePicker\n");
442  gpl_ = gpl;
443 }
444 
445 LinePicker::~LinePicker() {
446  // printf("~LinePicker\n");
447 }
448 void LinePicker::press(Event&) {
449  const Color* c;
450  if (Oc::helpmode()) {
451  Oc::help(LinePicker_event_);
452  return;
453  }
454  c_ = gpl_->color();
455  c = colors->color(2);
456  if (c == c_) {
457  c = colors->color(3);
458  }
459  gpl_->color(c);
460  gpl_->pick_vector();
461  common();
462 }
463 void LinePicker::release(Event&) {
464  gpl_->color(c_);
465  common();
466 }
467 
468 void LinePicker::common() {
470  GlyphIndex i = s->glyph_index(gpl_);
471  s->modified(i);
472  s->damage(i);
473  if (gpl_->label() && (i = s->glyph_index(gpl_->label())) >= 0) {
474  s->modified(i);
475  s->damage(i);
476  }
477 }
478 
479 MoveLabelBand::MoveLabelBand(GLabel* gl, RubberAction* ra, Canvas* c)
480  : Rubberband(ra, c) {
481  // printf("MoveLabelBand\n");
482  gl_ = gl;
483  gl_->ref();
484  label_ = (GLabel*) gl_->clone();
485  label_->ref();
486  label_->color(Rubberband::color());
488  index_ = gr->glyph_index(gl);
489  gr->location(index_, x0_, y0_);
490  if (gl_->fixed()) {
491  transformer().transform(x0_, y0_);
492  } else {
493  XYView::current_pick_view()->view_ratio(x0_, y0_, x0_, y0_);
494  }
495  // printf("MoveLabelBand label index %d (%g, %g)\n", index_, x0_, y0_);
496  Allotment ax, ay;
497  gr->allotment(index_, Dimension_X, ax);
498  gr->allotment(index_, Dimension_Y, ay);
499  a_.allot_x(ax);
500  a_.allot_y(ay);
501 }
502 
503 MoveLabelBand::~MoveLabelBand() {
504  // printf("~MoveLabelBand\n");
505  Resource::unref(label_);
506  Resource::unref(gl_);
507 }
508 
509 void MoveLabelBand::press(Event&) {
510  if (Oc::helpmode()) {
511  Oc::help(MoveLabelBand_press_);
512  return;
513  }
514  x0_ -= x_begin();
515  y0_ -= y_begin();
516 #if !defined(WIN32)
517  undraw(x(), y()); // so initial draw does not make it disappear
518 #endif
519 }
520 
521 void MoveLabelBand::release(Event&) {
522  if (Oc::helpmode()) {
523  return;
524  }
526  Coord x1, y1, x2, y2;
527  if (gl_->fixed()) {
528  transformer().inverse_transform(x(), y(), x2, y2);
529  transformer().inverse_transform(x_begin(), y_begin(), x1, y1);
530  } else {
531  x2 = x();
532  y2 = y();
533  x1 = x_begin();
534  y1 = y_begin();
535  }
536  gr->location(index_, x0_, y0_);
537  if (gl_->fixed()) {
538  x1 = x0_ + x2 - x1;
539  y1 = y0_ + y2 - y1;
540  } else {
541  XYView::current_pick_view()->view_ratio(x0_, y0_, x0_, y0_);
542  XYView::current_pick_view()->ratio_view(x0_ + x2 - x1, y0_ + y2 - y1, x1, y1);
543  }
544  // printf("move to %g %g\n", x1, y1);
545  gr->move(index_, x1, y1);
546 }
547 
548 void MoveLabelBand::draw(Coord x, Coord y) {
549  if (Oc::helpmode()) {
550  return;
551  }
552  Canvas* c = canvas();
553  // printf("MoveLabelBand::draw(%g, %g)\n", x, y);
554  a_.x_allotment().origin(x + x0_);
555  a_.y_allotment().origin(y + y0_);
556 #if defined(WIN32)
557  c->rect(a_.x_allotment().begin(),
558  a_.y_allotment().begin(),
559  a_.x_allotment().end(),
560  a_.y_allotment().end(),
563 #else
564  label_->draw(c, a_);
565 #endif
566 }
567 #endif
#define Handler
Definition: _defines.h:144
#define Color
Definition: _defines.h:72
#define Transformer
Definition: _defines.h:313
#define Canvas
Definition: _defines.h:63
#define Label
Definition: _defines.h:157
#define Allotment
Definition: _defines.h:36
#define Coord
Definition: _defines.h:17
#define Hit
Definition: _defines.h:145
#define GlyphIndex
Definition: _defines.h:21
#define Event
Definition: _defines.h:105
Coord x() const
Definition: geometry.h:286
void allot_y(const Allotment &)
Definition: geometry.h:279
Coord y() const
Definition: geometry.h:287
void allot_x(const Allotment &)
Definition: geometry.h:278
const Color * color(int) const
int count() const
Definition: graph.h:206
Definition: graph.h:418
void text(const char *)
virtual void pick(Canvas *, const Allocation &, int depth, Hit &)
virtual Glyph * clone() const
Coord x(int index) const
Definition: graph.h:285
virtual void pick(Canvas *, const Allocation &, int depth, Hit &)
Coord y(int index) const
Definition: graph.h:288
bool near(Coord, Coord, float, const Transformer &) const
int nearest(Coord, Coord, const Transformer &, int index=-1) const
DataVec * x_
Definition: graph.h:317
Definition: graph.h:54
virtual GlyphIndex glyph_index(const Glyph *)
static bool label_chooser(const char *, char *, GLabel *, Coord x=400., Coord y=400.)
@ CROSSHAIR
Definition: graph.h:56
@ PICK
Definition: graph.h:56
@ CHANGELABEL
Definition: graph.h:56
virtual void pick(Canvas *, const Allocation &, int depth, Hit &)
virtual void pick(Canvas *, const Allocation &, int depth, Hit &)
static bool near_line(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2, float epsilon)
Definition: mymath.cpp:110
static void help(const char *)
static bool helpmode()
Definition: ivoc.h:70
virtual void ref() const
Definition: resource.cpp:42
virtual void unref() const
Definition: resource.cpp:47
const Event & event() const
Definition: rubband.h:51
virtual void undraw(Coord x, Coord y)
virtual void release(Event &)
static const Color * color()
Coord x_
Definition: rubband.h:77
static const Brush * brush()
virtual void press(Event &)
Coord y_
Definition: rubband.h:77
virtual void draw(Coord x, Coord y)
virtual void change_label_color(GLabel *)
void move(GlyphIndex, Coord x, Coord y)
@ MOVE
Definition: scenevie.h:256
@ CHANGECOLOR
Definition: scenevie.h:256
@ DELETE
Definition: scenevie.h:256
virtual void delete_label(GLabel *)
void location(GlyphIndex, Coord &x, Coord &y) const
virtual void change_line_color(GPolyLine *)
virtual void allotment(GlyphIndex, DimensionName, Allotment &) const
virtual void view_ratio(float xratio, float yratio, Coord &x, Coord &y) const
virtual Scene * scene() const
virtual void ratio_view(Coord x, Coord y, float &xratio, float &yratio) const
static XYView * current_pick_view()
#define key
Definition: tqueue.hpp:45
#define i
Definition: md1redef.h:19
#define y_(arg)
Crout matrix decomposition : Forward/Backward substitution.
Definition: crout.hpp:136
@ Dimension_Y
Definition: geometry.h:39
@ Dimension_X
Definition: geometry.h:39
ColorPalette * colors
char buf[512]
Definition: init.cpp:13
static int c
Definition: hoc.cpp:169
double hoc_cross_x_
Definition: hoc_init.cpp:224
double hoc_cross_y_
Definition: hoc_init.cpp:224
printf
Definition: extdef.h:5
const char * name
Definition: init.cpp:16
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Definition: wrap_sprintf.h:14
s
Definition: multisend.cpp:521
short index
Definition: cabvars.h:11
static realtype c_
static realtype a_
static N_Vector x_
#define NULL
Definition: spdefs.h:105