fix crash when copy'ing latent plugins
[ardour.git] / libs / canvas / tracking_text.cc
1 /*
2     Copyright (C) 2011-2013 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <algorithm>
20
21 #include "canvas/canvas.h"
22 #include "canvas/tracking_text.h"
23
24 using namespace ArdourCanvas;
25
26 TrackingText::TrackingText (Canvas* c)
27         : Text (c)
28         , track_x (true)
29         , track_y (true)
30         , offset (Duple (10, 10))
31 {
32         init ();
33 }
34
35 TrackingText::TrackingText (Item* p)
36         : Text (p)
37         , track_x (true)
38         , track_y (true)
39         , offset (Duple (10, 10))
40 {
41         init ();
42 }
43
44 void
45 TrackingText::init ()
46 {
47         _canvas->MouseMotion.connect (sigc::mem_fun (*this, &TrackingText::pointer_motion));
48         set_ignore_events (true);
49         set_outline (true);
50         hide ();
51 }
52
53 void
54 TrackingText::pointer_motion (Duple const & winpos)
55 {
56         if (!_visible) {
57                 return;
58         }
59
60         Duple pos (_parent->window_to_item (winpos));
61
62         if (!track_x) {
63                 pos.x = position().x;
64         }
65
66         if (!track_y) {
67                 pos.y = position().y;
68         }
69
70         pos = pos.translate (offset);
71
72         /* keep inside the window */
73
74         Rect r (0, 0, _canvas->width(), _canvas->height());
75
76         /* border of 200 pixels on the right, and 50 on all other sides */
77
78         const double border = 50.0;
79
80         r.x0 += border;
81         r.x1 = std::max (r.x0, (r.x1 - 200.0));
82         r.y0 += border;
83         r.y1 = std::max (r.y0, (r.y1 - border));
84
85         /* clamp */
86
87         if (pos.x < r.x0) {
88                 pos.x = r.x0;
89         } else if (pos.x > r.x1) {
90                 pos.x = r.x1;
91         }
92
93         if (pos.y < r.y0) {
94                 pos.y = r.y0;
95         } else if (pos.y > r.y1) {
96                 pos.y = r.y1;
97         }
98
99         /* move */
100
101         set_position (pos);
102 }
103
104 void
105 TrackingText::show_and_track (bool tx, bool ty)
106 {
107         track_x = tx;
108         track_y = ty;
109
110         bool was_visible = _visible;
111         show ();
112
113         if (!was_visible) {
114                 /* move to current pointer location. do this after show() so that
115                  * _visible is true, and thus ::pointer_motion() will do
116                  * something.
117                  */
118                 Duple winpos;
119
120                 if (!_canvas->get_mouse_position (winpos)) {
121                         return;
122                 }
123
124                 pointer_motion (winpos);
125         }
126 }
127
128 void
129 TrackingText::set_x_offset (double o)
130 {
131         begin_change ();
132         offset.x = o;
133         end_change ();
134 }
135
136 void
137 TrackingText::set_y_offset (double o)
138 {
139         begin_change ();
140         offset.y = o;
141         end_change ();
142 }
143
144 void
145 TrackingText::set_offset (Duple const & d)
146 {
147         begin_change ();
148         offset = d;
149         end_change ();
150 }