Allow multiple bundles with the same ports in the bundle editor, otherwise sometimes...
[ardour.git] / gtk2_ardour / lineset.cc
1 /*
2     Copyright (C) 2007 Paul Davis
3     This program is free software; you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation; either version 2 of the License, or
6     (at your option) any later version.
7
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12
13     You should have received a copy of the GNU General Public License
14     along with this program; if not, write to the Free Software
15     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 */
17
18 #include "lineset.h"
19 #include "rgb_macros.h"
20
21 #include <libgnomecanvas/libgnomecanvas.h>
22 #include <libgnomecanvasmm/group.h>
23 #include <libgnomecanvasmm/canvas.h>
24
25 #include <algorithm>
26 #include <cmath>
27 #include <iostream>
28
29 using namespace std;
30
31 namespace Gnome {
32 namespace Canvas {
33
34 LineSetClass LineSet::lineset_class;
35
36 //static const char* overlap_error_str = "LineSet error: Line overlap";
37
38 LineSet::Line::Line(double c, double w, uint32_t color)
39         : coord(c)
40         , width(w)
41 {
42         UINT_TO_RGBA (color, &r, &g, &b, &a);
43 }
44
45 /* Constructor for dummy lines that are used only with the coordinate */
46 LineSet::Line::Line(double c)
47         : coord(c)
48 {
49 }
50
51 void
52 LineSet::Line::set_color(uint32_t color)
53 {
54         UINT_TO_RGBA (color, &r, &g, &b, &a);
55 }
56
57 const Glib::Class&
58 LineSetClass::init()
59 {
60         if (!gtype_) {
61                 class_init_func_ = &LineSetClass::class_init_function;
62                 register_derived_type(Item::get_type());
63         }
64
65         return *this;
66 }
67
68 void
69 LineSetClass::class_init_function(void* /*g_class*/, void* /*class_data*/)
70 {
71 }
72
73 LineSet::LineSet(Group& parent, Orientation o)
74         : Glib::ObjectBase("GnomeCanvasLineSet")
75         , Item(Glib::ConstructParams(lineset_class.init()))
76         , cached_pos(lines.end())
77         , orientation(o)
78         , x1(*this, "x1", 0.0)
79         , y1(*this, "y1", 0.0)
80         , x2(*this, "x2", 0.0)
81         , y2(*this, "y2", 0.0)
82         , in_update(false)
83         , update_region1(1.0)
84         , update_region2(0.0)
85         , bounds_changed(false)
86         , covered1(1.0) // covered1 > covered2 ==> nothing's covered
87         , covered2(0.0)
88 {
89
90         item_construct(parent);
91
92         property_x1().signal_changed().connect(mem_fun(*this, &LineSet::bounds_need_update));
93         property_y1().signal_changed().connect(mem_fun(*this, &LineSet::bounds_need_update));
94         property_x2().signal_changed().connect(mem_fun(*this, &LineSet::bounds_need_update));
95         property_y2().signal_changed().connect(mem_fun(*this, &LineSet::bounds_need_update));
96 }
97
98 LineSet::~LineSet()
99 {
100 }
101
102 bool
103 LineSet::line_compare(const Line& a, const Line& b)
104 {
105         return a.coord < b.coord;
106 }
107
108 void
109 LineSet::print_lines()
110 {
111         for (Lines::iterator it = lines.begin(); it != lines.end(); ++it)
112 {
113                 cerr << "   " << it->coord << " " << it->width << " " << (int)it->r << " " << (int)it->g << " " << (int)it->b << " " << (int)it->a << endl;
114         }
115 }
116
117 void
118 LineSet::move_line(double coord, double dest)
119 {
120         if (coord == dest) {
121                 return;
122         }
123
124         Lines::iterator it = line_at(coord);
125
126         if (it != lines.end()) {
127
128                 double width = it->width;
129                 it->coord = dest;
130
131                 Lines::iterator ins = lower_bound(lines.begin(), lines.end(), *it, line_compare);
132
133                 lines.insert(ins, *it);
134                 lines.erase(it);
135
136                 if (coord > dest) {
137                         region_needs_update(dest, coord + width);
138                 } else {
139                         region_needs_update(coord, dest + width);
140                 }
141         }
142 }
143
144 void
145 LineSet::change_line_width(double coord, double width)
146 {
147         Lines::iterator it = line_at(coord);
148
149         if (it != lines.end()) {
150                 Line& l = *it;
151                 ++it;
152
153                 if (it != lines.end()) {
154                         if (l.coord + width > it->coord) {
155                                 //cerr << overlap_error_str << endl;
156                                 return;
157                         }
158                 }
159
160                 l.width = width;
161                 region_needs_update(coord, coord + width);
162         }
163 }
164
165 void
166 LineSet::change_line_color(double coord, uint32_t color)
167 {
168         Lines::iterator it = line_at(coord);
169
170         if (it != lines.end()) {
171                 it->set_color(color);
172                 region_needs_update(it->coord, it->coord + it->width);
173         }
174 }
175
176 void
177 LineSet::add_line(double coord, double width, uint32_t color)
178 {
179         Line l(coord, width, color);
180
181         Lines::iterator it = std::lower_bound(lines.begin(), lines.end(), l, line_compare);
182
183         /* overlap checking */
184         if (it != lines.end()) {
185                 if (l.coord + l.width > it->coord) {
186                         //cerr << overlap_error_str << endl;
187                         return;
188                 }
189         }
190         if (it != lines.begin()) {
191                 --it;
192                 if (l.coord < it->coord + it->width) {
193                         //cerr << overlap_error_str << endl;
194                         return;
195                 }
196                 ++it;
197         }
198
199         lines.insert(it, l);
200         region_needs_update(coord, coord + width);
201 }
202
203 void
204 LineSet::remove_line(double coord)
205 {
206         Lines::iterator it = line_at(coord);
207
208         if (it != lines.end()) {
209                 double start = it->coord;
210                 double end = start + it->width;
211
212                 lines.erase(it);
213
214                 region_needs_update(start, end);
215         }
216 }
217
218 void
219 LineSet::remove_lines(double c1, double c2)
220 {
221         if (!lines.empty()) {
222                 region_needs_update(c1, c2);
223         }
224 }
225
226 void
227 LineSet::remove_until(double coord)
228 {
229         if (!lines.empty()) {
230                 double first = lines.front().coord;
231
232                 // code
233
234                 region_needs_update(first, coord);
235         }
236 }
237
238 void
239 LineSet::remove_from(double coord)
240 {
241         if (!lines.empty()) {
242                 double last = lines.back().coord + lines.back().width;
243
244                 // code
245
246                 region_needs_update(coord, last);
247         }
248 }
249
250 void
251 LineSet::clear()
252 {
253         if (!lines.empty()) {
254                 double coord1 = lines.front().coord;
255                 double coord2 = lines.back().coord + lines.back().width;
256
257                 lines.clear();
258                 region_needs_update(coord1, coord2);
259         }
260 }
261
262 /*
263  * this function is optimized to work faster if we access elements that are adjacent to each other.
264  * so if a large number of lines are modified, it is wise to modify them in sorted order.
265  */
266 LineSet::Lines::iterator
267 LineSet::line_at(double coord)
268 {
269         if (cached_pos != lines.end()) {
270                 if (coord < cached_pos->coord) {
271                         /* backward search */
272                         while (--cached_pos != lines.end()) {
273                                 if (cached_pos->coord <= coord) {
274                                         if (cached_pos->coord + cached_pos->width < coord) {
275                                                 /* coord is between two lines */
276                                                 return lines.end();
277                                         } else {
278                                                 return cached_pos;
279                                         }
280                                 }
281                         }
282                 } else {
283                         /* forward search */
284                         while (cached_pos != lines.end()) {
285                                 if (cached_pos->coord > coord) {
286                                         /* we searched past the line that we want, so now see
287                                            if the previous line includes the coordinate */
288                                         --cached_pos;
289                                         if (cached_pos->coord + cached_pos->width >= coord) {
290                                                 return cached_pos;
291                                         } else {
292                                                 return lines.end();
293                                         }
294                                 }
295                                 ++cached_pos;
296                         }
297                 }
298         } else {
299                 /* initialize the cached position */
300                 Line dummy(coord);
301
302                 cached_pos = lower_bound(lines.begin(), lines.end(), dummy, line_compare);
303
304                 /* The iterator found should point to the element after the one we want. */
305                 --cached_pos;
306
307                 if (cached_pos != lines.end()) {
308                         if (cached_pos->coord <= coord) {
309                                 if (cached_pos->coord + cached_pos->width >= coord) {
310                                         return cached_pos;
311                                 } else {
312                                         return lines.end();
313                                 }
314                         } else {
315                                 return lines.end();
316                         }
317                 } else {
318                         return lines.end();
319                 }
320         }
321
322         return lines.end();
323 }
324
325 void
326 LineSet::redraw_request(ArtIRect& r)
327 {
328         get_canvas()->request_redraw(r.x0, r.y0, r.x1, r.y1);
329 }
330
331 void
332 LineSet::redraw_request(ArtDRect& r)
333 {
334         int x0, y0, x1, y1;
335         Canvas& cv = *get_canvas();
336
337         //cerr << "redraw request: " << r.x0 << " " << r.y0 << " " << r.x1 << " " << r.y1 << endl;
338
339         cv.w2c(r.x0, r.y0, x0, y0);
340         cv.w2c(r.x1, r.y1, x1, y1);
341         cv.request_redraw(x0, y0, x1, y1);
342 }
343
344 void
345 LineSet::update_lines(bool need_redraw)
346 {
347         //cerr << "update_lines need_redraw=" << need_redraw << endl;
348         if (!need_redraw) {
349                 update_region1 = 1.0;
350                 update_region2 = 0.0;
351                 return;
352         }
353
354         if (update_region2 > update_region1) {
355                 ArtDRect redraw;
356                 LineSet::bounds_vfunc(&redraw.x0, &redraw.y0, &redraw.x1, &redraw.y1);
357                 i2w(redraw.x0, redraw.y0);
358                 i2w(redraw.x1, redraw.y1);
359
360                 if (orientation == Vertical) {
361                         redraw.x1 = redraw.x0 + update_region2;
362                         redraw.x0 += update_region1;
363                 } else {
364                         redraw.y1 = redraw.y0 + update_region2;
365                         redraw.y0 += update_region1;
366                 }
367                 redraw_request(redraw);
368                 update_region1 = 1.0;
369                 update_region2 = 0.0;
370         }
371
372         // if we need to calculate what becomes visible, use some of this
373         //cv.c2w (0, 0, world_v[X1], world_v[Y1]);
374         //cv.c2w (cv.get_width(), cv.get_height(), world_v[X2], world_v[Y2]);
375 }
376
377 /*
378  * return false if a full redraw request has been made.
379  * return true if nothing or only parts of the rect area has been requested for redraw
380  */
381 bool
382 LineSet::update_bounds()
383 {
384         GnomeCanvasItem* item = GNOME_CANVAS_ITEM(gobj());
385         ArtDRect old_b;
386         ArtDRect new_b;
387         ArtDRect redraw;
388         Canvas& cv = *get_canvas();
389
390         /* store the old bounding box */
391         old_b.x0 = item->x1;
392         old_b.y0 = item->y1;
393         old_b.x1 = item->x2;
394         old_b.y1 = item->y2;
395         LineSet::bounds_vfunc(&new_b.x0, &new_b.y0, &new_b.x1, &new_b.y1);
396
397         i2w(new_b.x0, new_b.y0);
398         i2w(new_b.x1, new_b.y1);
399
400         item->x1 = new_b.x0;
401         item->y1 = new_b.y0;
402         item->x2 = new_b.x1;
403         item->y2 = new_b.y1;
404
405         /* Update bounding box used in rendering function */
406         cv.w2c(new_b.x0, new_b.y0, bbox.x0, bbox.y0);
407         cv.w2c(new_b.x1, new_b.y1, bbox.x1, bbox.y1);
408
409         /*
410          * if the first primary axis property (x1 for Vertical, y1 for Horizontal) changed, we must redraw everything,
411          * because lines are positioned relative to this coordinate. Please excuse the confusion resulting from
412          * gnome canvas coordinate numbering (1, 2) and libart's (0, 1).
413          */
414         if (orientation == Vertical) {
415                 if (new_b.x0 == old_b.x0) {
416                         /* No need to update everything */
417                         if (new_b.y0 != old_b.y0) {
418                                 redraw.x0 = old_b.x0;
419                                 redraw.y0 = min(old_b.y0, new_b.y0);
420                                 redraw.x1 = old_b.x1;
421                                 redraw.y1 = max(old_b.y0, new_b.y0);
422                                 redraw_request(redraw);
423                         }
424                         if (new_b.y1 != old_b.y1) {
425                                 redraw.x0 = old_b.x0;
426                                 redraw.y0 = min(old_b.y1, new_b.y1);
427                                 redraw.x1 = old_b.x1;
428                                 redraw.y1 = max(old_b.y1, new_b.y1);
429                                 redraw_request(redraw);
430                         }
431
432                         if (new_b.x1 > old_b.x1) {
433                                 // we have a larger area ==> possibly more lines
434                                 request_lines(old_b.x1, new_b.x1);
435                                 redraw.x0 = old_b.x1;
436                                 redraw.y0 = min(old_b.y0, new_b.y0);
437                                 redraw.x1 = new_b.x1;
438                                 redraw.y1 = max(old_b.y1, new_b.y1);
439                                 redraw_request(redraw);
440                         } else if (new_b.x1 < old_b.x1) {
441                                 remove_lines(new_b.x1, old_b.x1);
442                                 redraw.x0 = new_b.x1;
443                                 redraw.y0 = min(old_b.y0, new_b.y0);
444                                 redraw.x1 = old_b.x1;
445                                 redraw.y1 = max(old_b.y1, new_b.y1);
446                                 redraw_request(redraw);
447                         }
448                         return true;
449                 } else {
450                         /* update everything */
451                         //cerr << "update everything" << endl;
452                         art_drect_union(&redraw, &old_b, &new_b);
453                         redraw_request(redraw);
454                         return false;
455                 }
456         } else {
457                 if (new_b.y0 == old_b.y0) {
458                         /* No need to update everything */
459                         if (new_b.x0 != old_b.x0) {
460                                 redraw.y0 = old_b.y0;
461                                 redraw.x0 = min(old_b.x0, new_b.x0);
462                                 redraw.y1 = old_b.y1;
463                                 redraw.x1 = max(old_b.x0, new_b.x0);
464                                 redraw_request(redraw);
465                         }
466                         if (new_b.x1 != old_b.x1) {
467                                 redraw.y0 = old_b.y0;
468                                 redraw.x0 = min(old_b.x1, new_b.x1);
469                                 redraw.y1 = old_b.y1;
470                                 redraw.x1 = max(old_b.x1, new_b.x1);
471                                 redraw_request(redraw);
472                         }
473
474                         if (new_b.y1 > old_b.y1) {
475                                 // we have a larger area ==> possibly more lines
476                                 request_lines(old_b.y1, new_b.y1);
477                                 redraw.y0 = old_b.y1;
478                                 redraw.x0 = min(old_b.x0, new_b.x0);
479                                 redraw.y1 = new_b.y1;
480                                 redraw.x1 = max(old_b.x1, new_b.x1);
481                                 redraw_request(redraw);
482                         } else if (new_b.y1 < old_b.y1) {
483                                 remove_lines(new_b.y1, old_b.y1);
484                                 redraw.y0 = new_b.y1;
485                                 redraw.x0 = min(old_b.x0, new_b.x0);
486                                 redraw.y1 = old_b.y1;
487                                 redraw.x1 = max(old_b.x1, new_b.x1);
488                                 redraw_request(redraw);
489                         }
490                         return true;
491                 } else {
492                         /* update everything */
493                         art_drect_union(&redraw, &old_b, &new_b);
494                         redraw_request(redraw);
495                         return false;
496                 }
497         }
498 }
499
500 /*
501  * what to do here?
502  * 1. find out if any line data has been modified since last update.
503  * N. find out if the item moved. if it moved, the old bbox and the new bbox need to be updated.
504  */
505 void
506 LineSet::update_vfunc(double* /*affine*/, ArtSVP* /*clip_path*/, int /*flags*/)
507 {
508         GnomeCanvasItem* item = GNOME_CANVAS_ITEM(gobj());
509         bool lines_need_redraw = true;
510
511         /*
512          * need to call gnome_canvas_item_update here, to unset the need_update flag.
513          * but a call to Gnome::Canvas::Item::update_vfunc results in infinite recursion.
514          * that function is declared in gnome_canvas.c so no way to call it directly:
515          * Item::update_vfunc(affine, clip_path, flags);
516          * So just copy the code from that function. This has to be a bug or
517          * something I haven't figured out.
518          */
519         GTK_OBJECT_UNSET_FLAGS (item, GNOME_CANVAS_ITEM_NEED_UPDATE);
520         GTK_OBJECT_UNSET_FLAGS (item, GNOME_CANVAS_ITEM_NEED_AFFINE);
521         GTK_OBJECT_UNSET_FLAGS (item, GNOME_CANVAS_ITEM_NEED_CLIP);
522         GTK_OBJECT_UNSET_FLAGS (item, GNOME_CANVAS_ITEM_NEED_VIS);
523
524         //cerr << "update {" << endl;
525         in_update = true;
526
527         // ahh. We must update bounds no matter what. If the group position changed,
528         // there is no way that we are notified of that.
529
530         //if (bounds_changed) {
531         lines_need_redraw = update_bounds();
532         bounds_changed = false;
533                 //}
534
535         update_lines(lines_need_redraw);
536
537         in_update = false;
538         //cerr << "}" << endl;
539 }
540
541 void
542 LineSet::draw_vfunc(const Glib::RefPtr<Gdk::Drawable>& /*drawable*/, int /*x*/, int /*y*/, int /*width*/, int /*height*/)
543 {
544         cerr << "please don't use the GnomeCanvasLineSet item in a non-aa Canvas" << endl;
545         abort();
546 }
547
548 inline void
549 LineSet::paint_vert(GnomeCanvasBuf* buf, LineSet::Line& line, int x1, int y1, int x2, int y2)
550 {
551         if (line.width == 1.0) {
552                 PAINT_VERTA(buf, line.r, line.g, line.b, line.a, x1, y1, y2);
553         } else {
554                 PAINT_BOX(buf, line.r, line.g, line.b, line.a, x1, y1, x2, y2);
555         }
556 }
557
558 inline void
559 LineSet::paint_horiz(GnomeCanvasBuf* buf, LineSet::Line& line, int x1, int y1, int x2, int y2)
560 {
561         if (line.width == 1.0) {
562                 PAINT_HORIZA(buf, line.r, line.g, line.b, line.a, x1, x2, y1);
563         } else {
564                 PAINT_BOX(buf, line.r, line.g, line.b, line.a, x1, y1, x2, y2);
565         }
566 }
567
568 void
569 LineSet::render_vfunc(GnomeCanvasBuf* buf)
570 {
571         ArtIRect rect;
572         int pos0, pos1, offset;
573
574         if (buf->is_bg) {
575                 gnome_canvas_buf_ensure_buf (buf);
576                 buf->is_bg = FALSE;
577         }
578
579         /* get the rect that we are rendering to */
580         art_irect_intersect(&rect, &bbox, &buf->rect);
581
582 #if 0
583         /* DEBUG render bounding box for this region. should result in the full
584            bounding box when all rendering regions are finished */
585         PAINT_BOX(buf, 0xaa, 0xaa, 0xff, 0xbb, rect.x0, rect.y0, rect.x1, rect.y1);
586 #endif
587
588 #if 0
589         /* harlequin debugging, shows the rect that is actually drawn, distinct from
590            rects from other render cycles */
591         gint r, g, b, a;
592         r = random() % 0xff;
593         g = random() % 0xff;
594         b = random() % 0xff;
595         PAINT_BOX(buf, r, g, b, 0x33, rect.x0, rect.y0, rect.x1, rect.y1);
596 #endif
597
598         if (lines.empty()) {
599                 return;
600         }
601
602         Lines::iterator it = lines.begin();
603         Lines::iterator end = --lines.end();
604
605         /**
606          * The first and the last line in this render have to be handled separately from those in between, because those lines
607          * may be cut off at the ends.
608          */
609
610         if (orientation == Vertical) {
611                 offset = bbox.x0;
612
613                 // skip parts of lines that are to the right of the buffer, and paint the last line visible
614                 for (; end != lines.end(); --end) {
615                         pos0 = ((int) floor(end->coord)) + offset;
616
617                         if (pos0 < rect.x1) {
618                                 pos1 = min((pos0 + (int) floor(end->width)), rect.x1);
619                                 if (pos0 < rect.x0 && pos1 < rect.x0) {
620                                         return;
621                                 }
622
623                                 paint_vert(buf, *end, pos0, rect.y0, pos1, rect.y1);
624                                 break;
625                         }
626                 }
627
628                 if (end == lines.end()) {
629                         return;
630                 }
631
632                 // skip parts of lines that are to the left of the buffer
633                 for (; it != end; ++it) {
634                         pos0 = ((int) floor(it->coord)) + offset;
635                         pos1 = pos0 + ((int) floor(it->width));
636
637                         if (pos1 > rect.x0) {
638                                 pos0 = max(pos0, rect.x0);
639                                 paint_vert(buf, *it, pos0, rect.y0, pos1, rect.y1);
640                                 ++it;
641                                 break;
642                         }
643                 }
644
645                 // render what's between the first and last lines
646                 for (; it != end; ++it) {
647                         pos0 = ((int) floor(it->coord)) + offset;
648                         pos1 = pos0 + ((int) floor(it->width));
649
650                         paint_vert(buf, *it, pos0, rect.y0, pos1, rect.y1);
651                 }
652         } else {
653                 offset = bbox.y0;
654
655                 // skip parts of lines that are to the right of the buffer, and paint the last line visible
656                 for (; end != lines.end(); --end) {
657                         pos0 = ((int) floor(end->coord)) + offset;
658
659                         if (pos0 < rect.y1) {
660                                 pos1 = min((pos0 + (int) floor(end->width)), rect.y1);
661                                 if (pos0 < rect.y0 && pos1 < rect.y0) {
662                                         return;
663                                 }
664
665                                 paint_horiz(buf, *end, rect.x0, pos0, rect.x1, pos1);
666                                 break;
667                         }
668                 }
669
670                 if (end == lines.end()) {
671                         return;
672                 }
673
674                 // skip parts of lines that are to the left of the buffer
675                 for (; it != end; ++it) {
676                         pos0 = ((int) floor(it->coord)) + offset;
677                         pos1 = pos0 + ((int) floor(it->width));
678
679                         if (pos1 > rect.y0) {
680                                 pos0 = max(pos0, rect.y0);
681                                 paint_horiz(buf, *it, rect.x0, pos0, rect.x1, pos1);
682                                 ++it;
683                                 break;
684                         }
685                 }
686
687                 // render what's between the first and last lines
688                 for (; it != end; ++it) {
689                         pos0 = ((int) floor(it->coord)) + offset;
690                         pos1 = pos0 + ((int) floor(it->width));
691                         paint_horiz(buf, *it, rect.x0, pos0, rect.x1, pos1);
692                 }
693         }
694 }
695
696 void
697 LineSet::bounds_vfunc(double* _x1, double* _y1, double* _x2, double* _y2)
698 {
699         *_x1 = x1;
700         *_y1 = y1;
701         *_x2 = x2 + 1;
702         *_y2 = y2 + 1;
703 }
704
705
706 double
707 LineSet::point_vfunc(double x, double y, int /*cx*/, int /*cy*/, GnomeCanvasItem** actual_item)
708 {
709         double x1, y1, x2, y2;
710         double dx, dy;
711
712         LineSet::bounds_vfunc(&x1, &y1, &x2, &y2);
713
714         *actual_item = gobj();
715
716         if (x < x1) {
717                 dx = x1 - x;
718         } else if (x > x2) {
719                 dx = x - x2;
720         } else {
721                 dx = 0.0;
722         }
723
724         if (y < y1) {
725                 dy = y1 - y;
726         } else if (y > y2) {
727                 dy = y - y2;
728         } else {
729                 if (dx == 0.0) {
730                         // point is inside
731                         return 0.0;
732                 } else {
733                         dy = 0.0;
734                 }
735         }
736
737         return sqrt (dx * dx + dy * dy);
738 }
739
740 /* If not overrided emit the signal */
741 void
742 LineSet::request_lines(double c1, double c2)
743 {
744         signal_request_lines(*this, c1, c2);
745 }
746
747 void
748 LineSet::bounds_need_update()
749 {
750         bounds_changed = true;
751
752         if (!in_update) {
753                 request_update();
754         }
755 }
756
757 void
758 LineSet::region_needs_update(double coord1, double coord2)
759 {
760         if (update_region1 > update_region2) {
761                 update_region1 = coord1;
762                 update_region2 = coord2;
763         } else {
764                 update_region1 = min(update_region1, coord1);
765                 update_region2 = max(update_region2, coord2);
766         }
767
768         if (!in_update) {
769                 request_update();
770         }
771 }
772
773 /*
774  * These have been defined to avoid endless recursion with gnomecanvasmm.
775  * Don't know why this happens
776  */
777 bool LineSet::on_event(GdkEvent* /*p1*/)
778 {
779         return false;
780 }
781
782 void LineSet::realize_vfunc() { }
783 void LineSet::unrealize_vfunc() { }
784 void LineSet::map_vfunc() { }
785 void LineSet::unmap_vfunc() { }
786
787 } /* namespace Canvas */
788 } /* namespace Gnome */