/* Copyright (C) 2007 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 __gnome_canvas_lineset_h__ #define __gnome_canvas_lineset_h__ #include namespace Gnome { namespace Canvas { class LinesetClass : public Glib::Class { public: const Glib::Class& init(); static void class_init_function(void* g_class, void* class_data); }; /** * A canvas item that displays a list of lines vertically or horizontally, * spanning the entire size of the item. */ class Lineset : public Item { public: enum Orientation { Vertical, Horizontal }; Lineset(Group& parent, Orientation); virtual ~Lineset(); Glib::PropertyProxy property_x1() { return x1.get_proxy(); } Glib::PropertyProxy property_y1() { return y1.get_proxy(); } Glib::PropertyProxy property_x2() { return x2.get_proxy(); } Glib::PropertyProxy property_y2() { return y2.get_proxy(); } /* * Note: every line operation takes a coord parameter, as an index to * the line it modifies. The index will identify a line if it is between * line.coord and line.coord + line.width. */ /** * Move a line to a new position * for this to work (to move the desired line) it is important that * lines have unique coordinates. This also applies to every line * accessing functions below */ void move_line(double coord, double dest); /** * Change the width of a line. Only allow it if the new width doesn't * overlap the next line (see below) */ void change_line_width(double coord, double width); /** * Change the color of a line */ void change_line_color(double coord, uint32_t color); /** * this function adds a line to draw. * width is an offset, so that coord + width specifies the end of the line. * lines should not overlap, as no layering information is provided. * however, line_coord[i] + line_width[i] == line_coord[i+1] is * be legal, as the coordinates are real numbers and represents * real world coordinates. Two real world object sharing coordinates for start * and end are not overlapping. */ void add_line(double coord, double width, uint32_t color); /** * remove the line at coord */ void remove_line(double coord); /** * remove all lines in a coordinate range */ void remove_lines(double c1, double c2); /** * remove all lines with a coordinate lower than coord */ void remove_until(double coord); /** * remove all lines with a coordinate equal to or higher than coord */ void remove_from(double coord); /** * remove all lines */ void clear(); /** * this is a request of information on lines in a coordinate range. * for every line visible in the provided coordinate range, * call add_line() on it. * This is called when the area between c1 and c2 becomes visible, when * previously outside any possible view. So the number of calls to this * function will be kept at a minimum. */ virtual void request_lines(double c1, double c2); /** * instead of overriding the update_lines function one can connect to this * and add lines externally instead. If add_lines() is overrided, this * signal will not be emitted. */ sigc::signal signal_request_lines; /* overrided from Gnome::Canvas::Item */ void update_vfunc(double* affine, ArtSVP* clip_path, int flags); void realize_vfunc(); void unrealize_vfunc(); void map_vfunc(); void unmap_vfunc(); void draw_vfunc(const Glib::RefPtr& drawable, int x, int y, int width, int height); void render_vfunc(GnomeCanvasBuf* buf); double point_vfunc(double x, double y, int cx, int cy, GnomeCanvasItem** actual_item); void bounds_vfunc(double* x1, double* y1, double* x2, double* y2); bool on_event(GdkEvent* p1); /* debug */ void print_lines(); protected: struct Line { Line(double c, double w, uint32_t color); Line(double c); void set_color(uint32_t color); double coord; double width; unsigned char r; unsigned char g; unsigned char b; unsigned char a; }; static inline void paint_vert(GnomeCanvasBuf* buf, Lineset::Line& line, int x1, int y1, int x2, int y2); static inline void paint_horiz(GnomeCanvasBuf* buf, Lineset::Line& line, int x1, int y1, int x2, int y2); static bool line_compare(const Line& a, const Line& b); typedef std::list Lines; void bounds_need_update(); void region_needs_update(double coord1, double coord2); bool update_bounds(); void update_lines(bool need_redraw); void redraw_request(ArtIRect&); void redraw_request(ArtDRect&); Lines::iterator line_at(double coord); /* store that last accessed line so adjacent lines are found faster */ Lines::iterator cached_pos; static LinesetClass lineset_class; Orientation orientation; Lines lines; /* properties */ Glib::Property x1; Glib::Property y1; Glib::Property x2; Glib::Property y2; /* cached bounding box in canvas coordinates*/ ArtIRect bbox; private: Lineset(); Lineset(const Lineset&); bool in_update; /* a range that needs update update1 > update2 ==> no update needed */ double update_region1; double update_region2; bool bounds_changed; double covered1; double covered2; }; } /* namespace Canvas */ } /* namespace Gnome */ #endif /* __gnome_canvas_lineset_h__ */