/*
 *  netplot.h from ObjectProDSP 0.2
 *  Copyright (C) 1994 1995, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  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 version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, libraries and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
#ifndef NETPLOT_DOT_H
#define NETPLOT_DOT_H
#include "com_input.h"
#include <InterViews/monoglyph.h>
#include <InterViews/glue.h>
#include <InterViews/layout.h>
#include <InterViews/patch.h>
#include <InterViews/observe.h>
#include "portable.h"
#include "elinlist.h"
#include "netdescg.h"

class NodeDescription ;
class BufferDescription ;
class WidgetKit ;
class LayoutKit ;
class Requisition ;
class MenuKeyboard ;
class Canvas ;
class Allocation;

class NetworkDescriptionFull;
class Style ;
class Button ;
class Blinker ;
class Color ;

class NodeGlyph ;
class NodeConnector ;
class EdibleInputLabel ;
class EdibleOutputLabel ;
class EdibleSpace ;
class VerticalPosition ;
class HorizontalPosition ;
class TraverseObj ;
class BoundedValue ;
struct EditLink ;

class NetGraph ;
class EdibleGlyph ; // Its easier to type then `EditableGlyph'

declareEditLinearList(VerticalPosition)

struct LastPosition {
	Coord left ;
	Coord right ;
	Coord top ;
	Coord bottom ;
	LastPosition() ;
	void set(const Allocation& a);
	Coord center_x() const ;
	Coord center_y() const ;
};

class VerticalGlyphs {
	PolyGlyph * the_vbox ;
	VerticalPosition_LinearList edible_graph ;
	NetGraph & the_graph ;
	GlyphIndex the_first_visible ;

	void update_indicies(GlyphIndex first);
public:
	VerticalGlyphs(LayoutKit & layout, NetGraph& g);
	enum Flavor {node_,connector_,input_label_,output_label_,space_};
	virtual ~VerticalGlyphs();
	void append(VerticalPosition & pos);
	PolyGlyph* vbox() {return the_vbox;}
	void vbox(PolyGlyph * vb) {the_vbox = vb;}
	void copy_vbox(LayoutKit& layout);
	NetGraph & graph() {return the_graph;}
	const NetGraph & graph() const {return the_graph;}
	void insert(GlyphIndex after, VerticalPosition *a);
	void add_edit_node(NodeGlyph& g);
	void add_first_fit(EdibleGlyph *a, EdibleGlyph *b=0, EdibleGlyph *c=0);
	void add_new_line(EdibleGlyph *a, EdibleGlyph *b=0, EdibleGlyph *c=0);
	EdibleGlyph * select_home() ;
	EdibleGlyph * select_end() ;
	VerticalPosition_LinearList& vertical_list() {return edible_graph;}
	VerticalPosition * get(GlyphIndex ix);
	GlyphIndex number() const {return edible_graph.number();}

	int scroll_mode();
	int is_room_for(VerticalPosition &pos);
	void update();
	GlyphIndex first_visible() const {return the_first_visible;}
	void make_visible(EdibleGlyph * to_see);
	void make_visible(GlyphIndex ix);
	GlyphIndex is_visible(GlyphIndex ix) const; // returns -1 if not visible
	GlyphIndex visible_size() const; 
	EdibleGlyph * select(const char * name) ;
	Coord height() const ;
	void dump() ;
	void draw_connect(Canvas*, const Allocation&) const ;
};

class NetGraph: public DspActiveHandler, public Observer {
	NetworkDescriptionFull& description ;
	LayoutKit& the_layout;
	WidgetKit& the_kit ;
	Style& the_style ;
	VerticalGlyphs glyphs ; // the_layout must be before this
	Button * button ;
	TraverseObj object ; // must be last
	NodeGlyph * to_connect ;
	NodeGlyph * second_connect ;
	NodeGlyph * the_other_action ;
	EdibleGlyph * the_selection ;
	EdibleGlyph * the_mouse_selection ;
	EdibleGlyph * the_label_selection ;
	int prefer_mouse ;
	int edit_flag ;
	int do_show_label_links ;

	Patch * patch ;
	TopLevelWindow * the_window ;
	MenuKeyboard * the_menu_keyboard ;

	BoundedValue * the_adjustable ;
	Glyph * the_adjustable_body ;
	int changing_size ;

	void prefer_mouse_selection() {prefer_mouse=1;}
	void prefer_keyboard_selection() {prefer_mouse=0;}
public:
	enum OtherEditOptions {no_operation,set_buffer_descriptor,disconnect_node,
		buffer_descriptor_menu};
private:
	OtherEditOptions the_other_edit_operation ;

	PolyGlyph* vbox() {return glyphs.vbox();}
	void clear_edit_base();
	void set_edit_base();
public:
	NetGraph(NetworkDescriptionFull& desc, Style * st);
	virtual ~NetGraph();

	virtual void keystroke(const Event&);
	virtual void press(const Event&);
	virtual void release(const Event&);
	virtual void enter();
	virtual void leave();

	virtual void draw(Canvas*, const Allocation&) const ;

	void make_body();
	MenuKeyboard * build_menu(WidgetKit& kit, const LayoutKit& layout,
    	Style * style, NetGraph&) ;
	MenuKeyboard * menu_keyboard() const {return the_menu_keyboard;}
	void edit();
	int clear_edit();
	void set_edit();
	int is_edit_window();
	void new_node(NodeDescription * node);
	void edit_new_node(NodeDescription * node);
	LayoutKit& layout() {return the_layout;}
	WidgetKit& kit() {return the_kit;}
	void patch_redraw() ;
	void copy_vbox() ;
	void set_edit_node(NodeGlyph*);
	void set_second_edit_node(NodeGlyph*);
	NodeGlyph * edit_node() {return to_connect;}
	NodeGlyph * second_edit_node() {return second_connect;}
	void clear_edit_node();
	const char * network_name() const {return description.name();}
	NetworkDescriptionFull& network_description() {return description;}
	void complete_edit();
	void complete_other_edit_operation();
	void error_edit();
	void reset_edit();
	void display_link(EditLink& from, EditLink& to);
	void add_edit_node(NodeGlyph * g) ;
	void add_first_fit(EdibleGlyph *a, EdibleGlyph *b=0, EdibleGlyph *c=0)
		{glyphs.add_first_fit(a,b,c);}
	void add_new_line(EdibleGlyph *a, EdibleGlyph *b=0, EdibleGlyph *c=0)
		{glyphs.add_new_line(a,b,c);}
	void resize();
	void complete_replacement(EditLink& first, EditLink& second);
	void other_action(NodeGlyph * g) {the_other_action = g;}
	NodeGlyph * other_action() const {return the_other_action ;}
	int other_edit_operation(OtherEditOptions) ;
		// returns 0 if we cannot set this
	int is_other_edit_operation()
		{return the_other_edit_operation != no_operation;}
	int is_other_edit_operation_warn(); // prints a warning if operation active
	void other_edit_operation_complete()
		{the_other_edit_operation= no_operation ; other_action(0);}
	void delete_node(NodeGlyph * node,int flag = 0);
	void add_unlinked_nodes();
	void new_selection(EdibleGlyph * selected);

	int enable_edit();
	int disable_edit();

	void select_home();
	void select_end();
	void select_left();
	void select_right();
	void select_up();
	void select_down();
	void select_none();
	void clear_selection();

	void show_selected_inputs();
	void show_selected_outputs();
	void clear_show_selected_links();

	void connect_selected_input();
	void connect_selected_output();
	void connect_selected_buffer();

	void disconnect_selected();
	void replace_selected();
	void remove_selected();

	void selected_node_menu();
	void selected_node_class_menu();

	void raise_output_windows();
	void network_menu();
	void controller_menu();
	void buffer_descriptor_for_net(int size, const char * data);
	void show_buffer_descriptor_menu();
	EdibleGlyph * selection() ;
	void set_mouse_selection(EdibleGlyph *);
	void set_label_selection(EdibleGlyph *);
	void clear_mouse_selection() {the_label_selection=the_mouse_selection = 0;}
	
	int edit_allowed() ;
	int check_busy();

	int scroll_mode() {return the_adjustable != 0;}
	void set_scroll_mode() ;
	void set_scroll_size();
	virtual void update(Observable*);
	BoundedValue * adjustable() {return the_adjustable;}

	void make_selection_visible();
	GlyphIndex current_value();
	void current_value(GlyphIndex ix);
	GlyphIndex visible_size() const;

	virtual void act_select(const char * sel);
	virtual void act_deselect();
	static const enable_edit_key ;
	static const disable_edit_key ;
	Coord width() const ;
	Coord height() const ;
	NetworkGlyph * net_glyph() const { return description.net_glyph();}
	void redraw_dim();

	void show_label_links();
	void clear_show_label_links();

	void dump();
};

class HorizontalPosition {
	GlyphIndex the_index ;
	EdibleGlyph * the_cookie ;
public:
	HorizontalPosition(EdibleGlyph * ed, GlyphIndex ix = -1);
	virtual ~HorizontalPosition();
	void draw_connect(Canvas*, const Allocation&) const ;
	EdibleGlyph * cookie() const {return the_cookie;}
	GlyphIndex index() const {return the_index;}
	void index(GlyphIndex ix) {the_index = ix;}
	virtual Glyph * glyph() ;
	void remove_from(VerticalPosition * from);
	void move(GlyphIndex index) {the_index = index;}
	VerticalGlyphs::Flavor flavor() ;
	EdibleGlyph * select_right();
	EdibleGlyph * select_left();
	EdibleGlyph * select(const char * name);
	void dump();
};

declareEditLinearList(HorizontalPosition);

class VerticalPosition {
	GlyphIndex the_index ;
	HorizontalPosition_LinearList the_glyphs ;
	PolyGlyph *  the_hbox ;
	VerticalGlyphs& the_vertical_glyphs ;
	Patch& the_patch ; // must be after the_hbox
	GlyphIndex insert_one(GlyphIndex after, EdibleGlyph *a);
	void update_indicies(GlyphIndex first);
	void copy_hbox();
	Coord middle_location(HorizontalPosition& pos);
public:
	VerticalPosition(LayoutKit& layout,VerticalGlyphs& vert,GlyphIndex ix = -1);
	virtual ~VerticalPosition();
	HorizontalPosition * position(GlyphIndex ix) {return the_glyphs.get(ix);}
	GlyphIndex number() const {return the_glyphs.number();}
	void replace(HorizontalPosition * pos, GlyphIndex ix= -1) ;
	void Remove(GlyphIndex ix, int redraw_flag=1);
	void move(GlyphIndex new_index) {the_index = new_index;}
	void insert(GlyphIndex after, EdibleGlyph *a, EdibleGlyph *b=0,
		EdibleGlyph *c=0);

	void draw_connect(Canvas*, const Allocation&) const ;

	PolyGlyph * hbox() const {return the_hbox;}
	GlyphIndex index() const {return the_index;}
	void index(GlyphIndex ix) {the_index = ix;}
	int size() {return the_glyphs.number();}
	void append(HorizontalPosition& pos);
	void append(EdibleGlyph& glyph);
	void append(EdibleGlyph *a) ;
	NetGraph& graph() {return the_vertical_glyphs.graph();}
	const NetGraph& graph() const {return the_vertical_glyphs.graph();}
	void redraw() {the_patch.redraw();}
	Patch& patch() {return the_patch;}
	int is_room_for(Glyph * a, Glyph * b=0, Glyph * c=0, Glyph * d=0,
		Glyph * e=0, Glyph * f=0) ;
	int is_room_for(EdibleGlyph * a, EdibleGlyph * b=0, EdibleGlyph * c=0,
		EdibleGlyph * d=0, EdibleGlyph * e=0, EdibleGlyph * f=0) ;
	void insert_horizontal(EdibleGlyph *a,EdibleGlyph *b=0, EdibleGlyph *c=0);
	enum Termination {empty,open_link,unlinked_node,terminated_link};
	Termination termination();
	static void set_width_limit(Coord new_width) ;
	EdibleGlyph * select_home();
	EdibleGlyph * select_end();
	EdibleGlyph * select_up(HorizontalPosition& pos);
	EdibleGlyph * select_down(HorizontalPosition& pos);
	EdibleGlyph * select_location(Coord where);
	EdibleGlyph * select(const char *);
	Coord width() const ;
	void dump();
};


class EdibleGlyph {
	HorizontalPosition& the_horizontal_position ;
	VerticalPosition * the_vertical_position ;
	VerticalGlyphs::Flavor the_flavor;
public:
	EdibleGlyph(VerticalGlyphs::Flavor flavor);
	virtual ~EdibleGlyph();
	void draw_connect(Canvas*, const Allocation&) const ;
	HorizontalPosition& horizontal_position() {return the_horizontal_position;}
	VerticalPosition * vertical_position() const {return the_vertical_position;}
	virtual void vertical_position(VerticalPosition * vertical)
		{the_vertical_position = vertical;}

	NodeGlyph * node() ;
	NodeConnector * connector() ;
	EdibleInputLabel * input_label();
	EdibleOutputLabel * output_label();
	EdibleSpace * space() ;
	virtual Glyph * glyph() ;
	VerticalGlyphs::Flavor flavor() const {return the_flavor;}
	NetGraph& graph();
	NetGraph * get_graph() ;
	void base_enter() ;
	void base_leave() ;
	void remove_me();
	void move_horizontal(GlyphIndex index){the_horizontal_position.move(index);}
	void modified() ;
	void unselect();
	EdibleGlyph * select() ;
	EdibleGlyph * select_up() ;
	EdibleGlyph * select_down() ;
	EdibleGlyph * select_left() ;
	EdibleGlyph * select_right() ;
	int selectable() const ;
	void show_inputs();
	void show_outputs();
	void show_none();
	virtual const char * name() {return 0;}
	virtual void dump();
};

class EdibleSpace : public MonoGlyph, public EdibleGlyph {
public:
	EdibleSpace(Coord natural);
	virtual ~EdibleSpace(){}
	virtual Glyph * glyph() {return this;}
	virtual void dump();
};

class EdibleInputLabel : public DspActiveHandler , public EdibleGlyph {
	NodeDescription* the_node ;
	char * text ;
	int the_channel ;
	EdibleInputLabel * the_next_input ;
	LastPosition pos ;
	Patch patch ;
	void make_body(LayoutKit& layout);
public:
	EdibleInputLabel(TraverseObj& obj,  NodeDescription& node,int node_chan =0);
	EdibleInputLabel(NetGraph& graph, EditLink& link);
	virtual ~EdibleInputLabel() {delete text;}
	void draw(Canvas*, const Allocation&) const ;
	virtual Glyph * glyph() {return this;}
	int channel() const {return the_channel;}
	void next_input(EdibleInputLabel * lab) {the_next_input = lab;}
	EdibleInputLabel * next_input() const {return the_next_input;}
	void color_label(const Color *col);
	void color_input_labels(const Color *color);
	NodeDescription& node() {return *the_node;}
	NodeGlyph& node_glyph() ;
	virtual void press(const Event&e) {graph().press(e);}
    virtual void release(const Event&e) {graph().release(e);}
	void mark_inputs_used();
	virtual void enter() {base_enter();}
	virtual void leave() {base_leave();}
	void new_node(NodeDescription& node);
	void new_node_kernel();
	void new_node();
	void make_label();
	void show_inputs();
	void show_outputs();
	void show_none();
	virtual const char * name() {return text;}
	virtual void dump();
	void to_position(Coord& x, Coord& y) const;
	void from_position(Coord& x, Coord& y) const;
	void draw_from(Canvas * c) const ;
};

class EdibleOutputLabel : public DspActiveHandler , public EdibleGlyph {
	NodeDescription * the_node ;
	char * text ;
	int the_channel ;
	int the_buffer_channel ;
	EdibleOutputLabel * the_next_output ;
	NodeConnector * the_displayed_buffer ;
	Patch patch ;
	LastPosition pos ;
	void make_body(LayoutKit& layout, WidgetKit& kit);
public:
	EdibleOutputLabel(TraverseObj& obj, NodeDescription& node);
	EdibleOutputLabel(NetGraph& graph, EditLink& link, int buffer_chan);
	virtual ~EdibleOutputLabel() {delete text;}
	void draw(Canvas*, const Allocation&) const ;
	virtual Glyph * glyph() {return this;}
	int channel() const {return the_channel;}
	int buffer_channel() const {return the_buffer_channel;}
	void next_output(EdibleOutputLabel * lab) {the_next_output = lab;}
    EdibleOutputLabel * next_output() const {return the_next_output;}
	void color_label(const Color *color);
	void color_output_labels(const Color *color);
	NodeDescription& node() {return *the_node;}
	NodeGlyph& node_glyph() ;
	virtual void press(const Event&e) {graph().press(e);}
    virtual void release(const Event&e) {graph().release(e);}
	void mark_outputs_used();
	virtual void enter() {base_enter();}
	virtual void leave() {base_leave();}
	NodeConnector * get_node_connector(int channel);
	NodeConnector * displayed_buffer() const {return the_displayed_buffer;}
    void displayed_buffer(NodeConnector * conn) {the_displayed_buffer = conn;}
	void new_node(NodeDescription& node);
	void new_node_kernel();
	void new_node();
	void make_label();
	void show_inputs();
	void show_outputs();
	void show_none();
	virtual const char * name() {return text;}
	virtual void vertical_position(VerticalPosition * vertical);
	virtual void dump();
	void to_position(Coord& x, Coord& y) const;
	void from_position(Coord& x, Coord& y) const;
	void draw_to(Canvas *c, const NodeConnector * conn = 0) const ;
};

struct EditConnection {
	enum ConnectType {connect_bad,connect_input,connect_output,connect_buffer,
		connect_replace} connection ;
	int channel ;
	EditConnection():connection(connect_bad),channel(-1){}
	EditConnection(int chan,ConnectType type):connection(type),channel(chan){}
	EditConnection(const EditConnection& clone):channel(clone.channel),
        connection(clone.connection){}

};

struct EditLink {
	EditConnection link ;
	NodeGlyph& glyph ;
	EditLink(NodeGlyph& gl, const EditConnection& conn):glyph(gl),link(conn){}
	EditConnection::ConnectType type() const {return link.connection;}
	int channel() const {return link.channel;}
	int in_network();
	void set_channel();
};

class NodeGlyph: public ActiveHandler, public EdibleGlyph {
	NodeDescription & the_node ;
	Glyph * class_label ;
	// Glyph * element_label ;
	Blinker * element_label ;
	int input_connect ;
	int output_connect ;
	int buffer_connect ;
	EditConnection first_connect ;
	EditConnection second_connect ;
	
	Glyph * kernel ;
	Glyph * framed_kernel ;
	Glyph * input_index_glyph ;
	Patch patch ;

	LayoutKit& the_layout ;
	WidgetKit& the_kit ;

	int * inputs_used ;
	int * outputs_used ;

	LastPosition pos ;

	int input_available();
	int output_available();
	int buffer_available();
	int unlinked(const char * cannot_do);
	int unlinked_replace();
	int network_linked();
	int network_linked_or_signal();
	void mark_inputs_used();
	void mark_outputs_used();
	void make_mark_arrays();
	void display_node_error();
	void set_edit(int channel,EditConnection::ConnectType type) ;
	void set_second_edit(int channel,EditConnection::ConnectType type) ;
	const char * connect_name(EditConnection::ConnectType type);
	int compatible(EditConnection::ConnectType type);
public:
	NodeGlyph(NodeDescription& desc, WidgetKit& kit,
		LayoutKit& layout, Style*);
	virtual ~NodeGlyph();
	virtual void draw(Canvas*, const Allocation&) const ;
	void draw_connect_all(Canvas*, const Allocation&,
		const NodeConnector *conn=0)const;
	virtual void request (Requisition& r) const;
	virtual void press(const Event&e) {graph().press(e);}
    virtual void release(const Event&e) {graph().release(e);}
	void press_kernel(const Event&);
	void release_kernel(const Event&);
	virtual Glyph * glyph() {return this;}
	void replace_node(unsigned button);
	void link(unsigned button, int chan = -1);
	void do_replace(unsigned button);
	void do_link(unsigned button);
	void color_input_labels(const Color *color) ;
    void color_output_labels(const Color *color) ;
	NodeDescription& node() {return the_node;}
	void draw_bright_frame();
	void draw_normal_frame();
	void bright_frame();
	void normal_frame();
	Glyph * input_index();
	void kernel_patch();
	void mark_input(int i );
	void mark_output(int i);
	void do_connect_buffer(int channel);
	int edit_in_progress() ;
	int is_linked() const ;
	virtual void enter() {base_enter();}
	virtual void leave() {base_leave();}
	const EditConnection& first_selection() {return first_connect;}
	const EditConnection& second_selection() {return second_connect;}
	char * make_expression(EditConnection&);
	char * make_expression() 
		{return make_expression(first_connect);}
	int in_network();
	int new_buffer_output(EditLink& driver, EditLink& driven);
	NodeConnector * get_node_connector(int channel);
	LayoutKit& layout() {return the_layout;}
	WidgetKit& kit() {return the_kit;}
	void set_input_channel(int chan) {input_connect = chan;}
	void set_output_channel(int chan) {output_connect = chan; buffer_connect=0;}
	int glyph_output_connect()const{return output_connect;}
	int glyph_input_connect()const{return input_connect;}
	int glyph_buffer_connect()const{return buffer_connect;}
	void append_to_net(EditLink& link, NodeConnector& conn, EdibleGlyph& to);
	int identical_channels(NodeGlyph * first);
	int edit_allowed() ;
	void clone_from(NodeGlyph& from);
	void exchange_positions(NodeGlyph& exch);
	void clear_connections();
	int remove_from_graph(int warn_flag=1);
	virtual const char * name() {return the_node.name();}
	void do_disconnect(const char * response);
	void complete_disconnect();
	NodeGlyph * select();
	void unselect();
	void show_inputs();
	void show_outputs();
	void show_none();
	int raise_output_windows();
	void disconnect_node();
	static const Coord hmargin_size ;
	static const Coord vmargin_size ;
	virtual void dump();
	void to_position(Coord& x, Coord& y) const ;
	void from_position(Coord& x, Coord& y) const;
};

class NodeConnector: public MonoGlyph, public EdibleGlyph {
	const NodeDescription & the_node;
	NodeDescription * const driven ;
	int channel ;
	const BufferDescription & the_buf ;
	int buffer_channel ;
	int from_label ;
	Blinker * blinking_widget ;
	static Coord min_width ;
	char * the_name ;
	LastPosition pos ;
	

	void make_body(LayoutKit& layout, WidgetKit &kit, Style *, int buf_size);
	void add_from_index(Glyph * hbox,LayoutKit& layout, WidgetKit &kit) ;
	void make_name();

public:
	NodeConnector(int channel, TraverseObj& obj, const NodeDescription& nd,
		NodeDescription * driven_node);
	NodeConnector(NodeGlyph& glyph); // for editing
	NodeConnector(EdibleOutputLabel& label); // for editing
	virtual ~NodeConnector();
	virtual void draw(Canvas*, const Allocation&) const ;
	void ctor_from_graph();
	const NodeDescription& node() const {return the_node;}
	virtual Glyph * glyph() {return this;}
	void connect_buffer();
	void new_buffer_size();
	NodeConnector * select();
	void unselect();
	void show_inputs();
	void show_outputs();
	void show_none();
	virtual const char * name() {return the_name;}
	int get_channel() const {return channel;}
	virtual void dump();
	void from_position(Coord& x, Coord& y) const;
	void draw_connect_all(Canvas*, const Allocation&) const ;
};


class ArrowWidget: public MonoGlyph {
public:
	static const Coord min_width ;
	const enum ArrowType
		{line,right_arrow,right_arrow_source,right_arrow_sink} type;
	ArrowWidget(WidgetKit&kit, LayoutKit& layout,
		ArrowType typ=right_arrow, const char * label = 0);
	virtual ~ArrowWidget();
};

inline VerticalGlyphs::Flavor HorizontalPosition::flavor()
	{return the_cookie->flavor();} 

#endif /* #ifdef NETPLOT_DOT_H */
