From 76b9ad229460e1876ad0ebee8047d47c417efdc8 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 11 Jun 2014 12:24:43 -0400 Subject: [PATCH] add initial (untested) implementation of canvas ruler item --- libs/canvas/canvas/ruler.h | 80 +++++++++++++++++++++++++ libs/canvas/ruler.cc | 117 +++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 libs/canvas/canvas/ruler.h create mode 100644 libs/canvas/ruler.cc diff --git a/libs/canvas/canvas/ruler.h b/libs/canvas/canvas/ruler.h new file mode 100644 index 0000000000..ac72245c0f --- /dev/null +++ b/libs/canvas/canvas/ruler.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2014 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __CANVAS_RULER_H__ +#define __CANVAS_RULER_H__ + +#include +#include + +#include "canvas/item.h" +#include "canvas/fill.h" +#include "canvas/outline.h" + +namespace ArdourCanvas +{ + +class LIBCANVAS_API Ruler : virtual public Item, public Fill, public Outline +{ +public: + struct Mark { + enum Style { + Major, + Minor, + Micro + }; + std::string label; + double position; + Style style; + }; + + struct Metric { + Metric () : units_per_pixel (0) {} + virtual ~Metric() {} + + double units_per_pixel; + + /* lower and upper and sample positions, which are also canvas coordinates + */ + + virtual int get_marks (std::vector&, double lower, double upper, int maxchars) const = 0; + }; + + Ruler (Group *, const Metric& m); + + void set_range (double lower, double upper); + void set_size (Rect const&); + + void render (Rect const & area, Cairo::RefPtr) const; + void compute_bounding_box () const; + +private: + const Metric& _metric; + Rect _rect; + + /* lower and upper and sample positions, which are also canvas coordinates + */ + + Coord _lower; + Coord _upper; +}; + +} + + +#endif diff --git a/libs/canvas/ruler.cc b/libs/canvas/ruler.cc new file mode 100644 index 0000000000..ac46249001 --- /dev/null +++ b/libs/canvas/ruler.cc @@ -0,0 +1,117 @@ +/* + Copyright (C) 2014 Paul Davis + Author: Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include "pbd/compose.h" +#include "canvas/ruler.h" +#include "canvas/types.h" +#include "canvas/debug.h" +#include "canvas/utils.h" +#include "canvas/canvas.h" + +using namespace std; +using namespace ArdourCanvas; + +Ruler::Ruler (Group *p, const Metric& m) + : Item (p) + , Fill (p) + , Outline (p) + , _metric (m) +{ +} + +void +Ruler::set_range (double l, double u) +{ + _lower = l; + _upper = u; +} + +void +Ruler::set_size (Rect const & area) +{ + if (_rect != area) { + begin_visual_change (); + _rect = area; + _bounding_box_dirty = true; + end_visual_change (); + } +} + +void +Ruler::compute_bounding_box () const +{ + if (!_rect.empty()) { + _bounding_box = _rect; + } + + _bounding_box_dirty = false; +} + +void +Ruler::render (Rect const & area, Cairo::RefPtr cr) const +{ + Rect self (item_to_window (_rect)); + boost::optional i = self.intersection (area); + if (!i) { + return; + } + + Rect intersection (i.get()); + + vector marks; + Distance height = self.height(); + + _metric.get_marks (marks, _lower, _upper, 50); + + /* draw background */ + + setup_fill_context (cr); + cr->rectangle (intersection.x0, intersection.y0, intersection.width(), intersection.height()); + cr->fill (); + + /* draw ticks */ + + setup_outline_context (cr); + + for (vector::const_iterator m = marks.begin(); m != marks.end(); ++m) { + Duple pos; + + pos.x = self.x0 + ((m->position - _lower) / _metric.units_per_pixel); + pos.y = self.y1; /* bottom edge */ + + cr->move_to (pos.x, pos.y); + + switch (m->style) { + case Mark::Major: + cr->rel_move_to (0, -height); + break; + case Mark::Minor: + cr->rel_move_to (0, -(height/2.0)); + break; + case Mark::Micro: + cr->rel_move_to (0, pos.y-(height/4.0)); + break; + } + cr->stroke (); + } + + /* done! */ +}