* @brief Implementation of the Arrow canvas object.
*/
+#include "pbd/compose.h"
+
#include "canvas/arrow.h"
+#include "canvas/debug.h"
#include "canvas/polygon.h"
#include "canvas/line.h"
/** Construct an Arrow.
* @param parent Parent canvas group.
*/
-Arrow::Arrow (Group* parent)
- : Group (parent)
+Arrow::Arrow (Canvas* c)
+ : Container (c)
{
- assert (parent);
+ setup ();
+}
+Arrow::Arrow (Item* parent)
+ : Container (parent)
+{
+ setup ();
+}
+
+void
+Arrow::setup ()
+{
/* set up default arrow heads at each end */
for (int i = 0; i < 2; ++i) {
_heads[i].polygon = new Polygon (this);
- _heads[i].show = true;
_heads[i].outward = true;
_heads[i].width = 4;
_heads[i].height = 4;
setup_polygon (i);
+ CANVAS_DEBUG_NAME (_heads[i].polygon, string_compose ("arrow head %1", i));
}
_line = new Line (this);
+ CANVAS_DEBUG_NAME (_line, "arrow line");
+}
+
+void
+Arrow::compute_bounding_box () const
+{
+ /* Compute our bounding box manually rather than using the default
+ container algorithm, since having the bounding box with origin other
+ than zero causes strange problems for mysterious reasons. */
+
+ const double outline_pad = 0.5 + (_line->outline_width() / 2.0);
+ const double head_width = std::max(_heads[0].width, _heads[1].width);
+
+ _bounding_box = Rect(0,
+ 0,
+ _line->x1() + (head_width / 2.0) + outline_pad,
+ _line->y1());
+
+ _bounding_box_dirty = false;
}
/** Set whether to show an arrow head at one end or other
begin_change ();
- _heads[which].show = show;
+ if (!show) {
+ delete _heads[which].polygon;
+ _heads[which].polygon = 0;
+ } else {
+ setup_polygon (which);
+ }
- setup_polygon (which);
_bounding_box_dirty = true;
end_change ();
}
Arrow::set_outline_width (Distance width)
{
_line->set_outline_width (width);
- _heads[0].polygon->set_outline_width (width);
- _heads[1].polygon->set_outline_width (width);
+ if (_heads[0].polygon) {
+ _heads[0].polygon->set_outline_width (width);
+ }
+ if (_heads[1].polygon) {
+ _heads[1].polygon->set_outline_width (width);
+ }
+ _bounding_box_dirty = true;
}
/** Set the x position of our line.
_line->set_x0 (x);
_line->set_x1 (x);
for (int i = 0; i < 2; ++i) {
- _heads[i].polygon->set_x_position (x - _heads[i].width / 2);
+ if (_heads[i].polygon) {
+ _heads[i].polygon->set_x_position (x - _heads[i].width / 2);
+ }
}
-
+ _bounding_box_dirty = true;
}
/** Set the y position of end 0 of our line.
Arrow::set_y0 (Coord y0)
{
_line->set_y0 (y0);
- _heads[0].polygon->set_y_position (y0);
+ if (_heads[0].polygon) {
+ _heads[0].polygon->set_y_position (y0);
+ }
+ _bounding_box_dirty = true;
}
/** Set the y position of end 1 of our line.
Arrow::set_y1 (Coord y1)
{
_line->set_y1 (y1);
- _heads[1].polygon->set_y_position (y1 - _heads[1].height);
+ if (_heads[1].polygon) {
+ _heads[1].polygon->set_y_position (y1 - _heads[1].height);
+ }
+ _bounding_box_dirty = true;
}
/** @return x position of our line in pixels (in our coordinate system) */
{
_line->set_outline_color (color);
for (int i = 0; i < 2; ++i) {
- _heads[i].polygon->set_outline_color (color);
- _heads[i].polygon->set_fill_color (color);
+ if (_heads[i].polygon) {
+ _heads[i].polygon->set_outline_color (color);
+ _heads[i].polygon->set_fill_color (color);
+ }
}
}