#ifndef shape_h
#define shape_h

#include "scenevie.h"
#include "graph.h"

#undef Rubberband

struct Section;	// neuron section structure
class ShapeSection;
class SectionHandler;
class StandardPicker;
class MyRect;
class Color;
class Brush;
class SectionList;
class Rubberband;
class ColorValue;
class PolyGlyph;
struct Symbol;
class Rotation3d;
class Rotate3Band;
class ShapeChangeObserver;

class ShapeScene : public Graph { // entire neuron
public:
	enum {SECTION=Graph::EXTRAGRAPHTOOL, ROTATE, EXTRASHAPETOOL};
	ShapeScene(SectionList* = NULL);
	virtual ~ShapeScene();
	virtual void erase_all();
	virtual void observe(SectionList* = NULL);
	virtual void flush();
	virtual ShapeSection* selected();
	virtual float arc_selected();
	virtual void selected(ShapeSection*, Coord x = fil, Coord y = fil);
	virtual float nearest(Coord, Coord); // and sets selected
        virtual void wholeplot(Coord& x1, Coord& y1, Coord& x2, Coord& y2)const;
	static ShapeScene* current_pick_scene();
	static ShapeScene* current_draw_scene();
	void color(Section* sec1, Section* sec2, const Color*);
	void color(Section* sec, const Color*);
	void colorseg(Section*, double, const Color*);
	void color(const Color*);
	void color(SectionList*, const Color*);
	ColorValue* color_value();
	virtual void view(Coord);
	virtual void view(Coord*);
	virtual void view(Rubberband*);
	enum {show_diam, show_centroid, show_schematic};
	void shape_type(int);
	int shape_type() {return shape_type_;}
	virtual void section_handler(SectionHandler*);
	virtual SectionHandler* section_handler();
	virtual SectionHandler* section_handler(ShapeSection*);
	PolyGlyph* shape_section_list();
	virtual void transform3d(Rubberband* rb = NULL);
	virtual ShapeSection* shape_section(Section*);
	virtual void name(const char*);
	virtual void save_phase2(ostream&);
	virtual void help();
	void force();
	bool view_all() { return view_all_;}
	void rotate(); // identity
	void rotate(Coord xorg, Coord yorg, Coord zorg,
		float xrad, float yrad, float zrad); //relative
private:
	bool view_all_;
	ShapeSection* selected_;
	Coord x_sel_, y_sel_;
	ColorValue* color_value_;
	int shape_type_;
	SectionHandler* section_handler_;
	PolyGlyph* sg_;
	Rotate3Band* r3b_;
	CopyString* var_name_;
	ShapeChangeObserver* shape_changed_;
};

class FastShape : public Glyph {
public:
	FastShape();
	virtual ~FastShape();
	virtual void fast_draw(Canvas*, Coord x, Coord y, bool)const = 0;
};

class FastGraphItem : public GraphItem {
public:
	FastGraphItem(FastShape* g, bool save = true, bool pick = true);
	virtual bool is_fast() {return true;}
};

class ShapeSection : public FastShape { //single section
public:
	ShapeSection(Section*);
	virtual ~ShapeSection();
	virtual void request(Requisition&) const;
	virtual void allocate(Canvas*, const Allocation&, Extension&);
	virtual void draw(Canvas*, const Allocation&) const;
	virtual void fast_draw(Canvas*, Coord x, Coord y, bool) const;
	virtual void pick(Canvas*, const Allocation&, int depth, Hit&);
	virtual void setColor(const Color*, ShapeScene*);
	virtual void setColorseg(const Color*, double, ShapeScene*);
	const Color* color(){return color_;}
	virtual void set_range_variable(Symbol*);
	virtual void clear_variable();
	virtual void selectMenu();
	virtual bool near_section(Coord, Coord, Coord mineps) const;
	float how_near(Coord, Coord)const;
	float arc_position(Coord, Coord)const;
	int get_coord(double arc, Coord&, Coord&)const;
	Section* section() const;
	bool good() const;
	virtual void damage(ShapeScene*);
//	virtual void update(Observable*);
	virtual void draw_seg(Canvas*, const Color*, int iseg) const;
	virtual void draw_points(Canvas*, const Color*, int, int) const;
	virtual void transform3d(Rotation3d*);
	virtual void size(Coord& l, Coord& b, Coord& r, Coord& t) const;
	void scale(Coord x) { len_scale_ = x; }
	Coord scale() { return len_scale_; }
	void update_ptrs();
private:
	void trapezoid(Canvas*, const Color*, int i) const;
	void trapezoid(Canvas*, const Color*, float, float, float, float,float, float) const;
	void loc(double, Coord&, Coord&);
	void bevel_join(Canvas*, const Color*, int, float) const;
#define FASTIDIOUS 1
#if FASTIDIOUS
	void fastidious_draw(Canvas*, const Color*, int, float, float) const;
#endif
private:
	double** pvar_;
	Section* sec_;
	Coord len_scale_;
	const Color* color_;
	const Color** old_;
	const Color** colorseg_;
	int colorseg_size_; // so know when to unref colorseg_ items.
	Coord xmin_, xmax_, ymin_, ymax_;
	Coord *x_, *y_;
	int n_;
};

#if 1
class ShapeView : public View {
public:
	ShapeView(ShapeScene*);
	ShapeView(ShapeScene*, Coord*);
	virtual ~ShapeView();
};
#endif


class SectionHandler : public Handler {
public:
	SectionHandler();
	virtual ~SectionHandler();
	virtual bool event(Event&);
	void shape_section(ShapeSection*);
	ShapeSection* shape_section();
private:
	ShapeSection* ss_;
};
	
#endif
