/*
 *  netdescg.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 NETDESCG_DOT_H
#define NETDESCG_DOT_H

#include <InterViews/resource.h>
#include <InterViews/coord.h>
#include <InterViews/monoglyph.h>
#include "netdesc.h"
#include "elinlist.h"
#include "portable.h"

class NodeDescription ;
class BufferDescription ;
class LabelDescription ;

class NetGraph ;
class TraverseObj ;
class TopLevelWindow ;
class WidgetKit ;
class LayoutKit ;
class PolyGlyph ;
class Glyph ;
class Style ;
class Adjustable ;
class Canvas ;
class Allocation;

class EdibleSpace ;
class NodeGlyph ;
class NodeConnector ;
class VerticalGlyphs ;
class VerticalPosition ;
class EdibleOutputLabel ;
class EdibleInputLabel ;
class Color ;
class NetworkGlyph ;

struct EditLink ;

class NodeDisplayParameters {
	NodeDescription * the_current_driver ;
	int channel_index ;
	int buffer_channel_index ;
	NodeDescription& the_node ;
	static const char * next_label();
	enum TraverseFlags {none=0,standard=1} the_traverse_flags ;
public:
	NodeDisplayParameters(NodeDescription& nd);
	static void clear_labels();
	void clear();
	void next_channel();
	void next_buffer_channel();
	int channel() const {return channel_index;}
	void channel(int channel) {channel_index = channel;}
	int buffer_channel() const {return buffer_channel_index;}
	void current_driver(NodeDescription * drv)
		{the_current_driver = drv;}
	NodeDescription * current_driver() const {return the_current_driver;}
	void link() ;
	TraverseFlags traverse_flags() const {return the_traverse_flags;}
	void set_traverse_flags(TraverseFlags to_set) {the_traverse_flags = to_set;}
	int traverse_standard() const {return the_traverse_flags == standard;}
	void set_traverse_standard() {(*((int*) &the_traverse_flags)) |= standard;}
	NodeDescription& node() {return the_node;}
	char * node_channel_name() const;
	int current_input_channel() const ;
};



class BufferDescription : public NetBufferDescription{
	NodeDescription ** driven ;
	NodeDescription * the_driver ;
public:
	BufferDescription(GenericArrayElement_LinearList *l):
		NetBufferDescription(l),driven(0){}
	BufferDescription(int drv_chan,const char * drv_nm);
	~BufferDescription();
	void set_nodes(NodeDescription ** d){driven = d;}
	const char * driver() const {return driver_name;}
	int channel_in_driver() const {return driver_channel;}
	const char ** destinations() const {return destination_names;}
	int * destination_channels() const {return destination_input_channels;}
	void traverse(TraverseObj& obj) ;
	void clear_traverse() const ;
	int out() const {return number_outputs;}
	NodeDescription * driver_node() const {return the_driver;}
	void driver_node(NodeDescription * dr) {the_driver = dr;}
	NodeDescription * driven_node(int i);
	int link(EditLink&);
	void change_driven(NodeDescription& old_node, NodeDescription& new_node);
	
};

typedef void (NodeDescription::*NodeMemberFunction)(TraverseObj&) ;

class TraverseObj {
	NodeMemberFunction the_action ;
	WidgetKit& the_kit ;
	LayoutKit& the_layout ;
	Style * the_style ;
	VerticalGlyphs& the_vertical_glyphs ;
	// PolyGlyph * the_hbox ;
	VerticalPosition * the_vertical_position ;
	VerticalPosition * last_vertical_position ;
	NodeConnector * last_connect ;
	int is_in_vertical_glyphs ;

public:
	enum TraverseError {none,fatal} error_state ;
	TraverseObj(NodeMemberFunction act,WidgetKit & kit, LayoutKit& layout,
		Style *s,VerticalGlyphs& vert);
	void vertical_glyphs_append() ;
	// PolyGlyph * hbox() ;
	VerticalPosition * vertical_position() ;
	Glyph * label_to_glyph(const char * name) const;
	void add(EdibleOutputLabel *,EdibleInputLabel *);
	void add(NodeDescription& nd, NodeGlyph * node, NodeConnector *conn);
	void add(NodeDescription& nd);
	int error() const {return error_state >= fatal;}
	NodeMemberFunction action() const {return the_action;}
	WidgetKit& kit() {return the_kit;}
	LayoutKit& layout() {return the_layout;}
	Style * style() const {return the_style;}
	int is_start_line() const {return last_connect == 0 ;}
	void clear_last_connect() {last_connect=0;}
	void make_vertical_position();
	void restore_last();
	void check_in_vertical_glyphs();
	VerticalGlyphs& vertical_glyphs() {return the_vertical_glyphs;}
	EdibleSpace * separator(NodeDescription * node=0);
	int is_room_for(Glyph * a, Glyph *b=0, Glyph *c =0, Glyph *d=0,
		Glyph *e=0,Glyph *f=0);
};
	

class NodeDescription : private NetNodeDescription {
	NodeDisplayParameters * display_param ;
	BufferDescription ** buffers ;
	NodeGlyph * the_node_glyph ;
	EdibleInputLabel * the_next_input ;
	EdibleOutputLabel * the_next_output ;
	NodeConnector * the_displayed_buffer ;
public:
	NodeDescription(GenericArrayElement_LinearList *l);
	NodeDescription(const char * class_name, const char * node_name,
        int inputs, int outputs);
	~NodeDescription();
	void draw_connect_all(Canvas*,const Allocation&,
		const NodeConnector*conn=0)const;
	void set_buffers(BufferDescription ** b){buffers = b;}
	BufferDescription ** get_buffer_array() {return buffers;}
	BufferDescription * buffer(int i) const ;
	void clear_traverse() const ;
	const char * name() const {return element_name;}
	const char * object_class() const {return class_name;}
	int in() const {return input_channels;}
	int out() const {return output_channels;}
	const char ** drivers() const {return driver_names;}
	void display_network(TraverseObj& obj) ;
	void traverse(TraverseObj& obj) ;
	void terminate_branch(TraverseObj& obj) ;
	NodeDisplayParameters * display_parameters() const {return display_param;}
	EdibleOutputLabel * driver_output_label(TraverseObj&) ;

	void next_input(EdibleInputLabel * lab);
	EdibleInputLabel * next_input() const {return the_next_input;}
	void next_output(EdibleOutputLabel * lab);
	EdibleOutputLabel * next_output() const {return the_next_output;}
	void color_input_labels(const Color *color);
	void color_output_labels(const Color *color);
	NodeGlyph * node_glyph() const {return the_node_glyph;}
	void node_glyph(NodeGlyph * node) {the_node_glyph = node;}
	NodeDescription * current_node_driven();
	NodeConnector * displayed_buffer() const {return the_displayed_buffer;}
	void displayed_buffer(NodeConnector * conn) {the_displayed_buffer = conn;}
	int new_buffer_output(EditLink& driver, EditLink& driven);
	int identical_channels(NodeDescription& check);
	void clone_from(NodeDescription&);
	void clear_connections();
	void change_driven(NodeDescription& old_node, NodeDescription& new_node);
	int is_linked() {return !unlinked_flag;}
	void set_linked() {unlinked_flag = 0 ;}
	void clear_linked() {unlinked_flag = 1 ;}
	int in_channel_for(const char * name);
};
	
class NetDescription : private NetworkDescription {
	NodeDescription ** signal_nodes ;
public:
	NetDescription(GenericArrayElement_LinearList *l):
		NetworkDescription(l),signal_nodes(0){}
	NetDescription(const char * nm, const char * cntrl);
	~NetDescription();
	void set_signals(NodeDescription **sig) {signal_nodes=sig;}
	const char * net_name() const {return name;}
	const char * controller() const {return controller_name;}
	void traverse(TraverseObj &obj) ;
	void clear_traverse() const ;
};

declareEditLinearList(NodeDescription)
declareEditLinearList(BufferDescription)

class NetworkDescriptionFull  : public ivResource {
	NetGraph * the_graph ;
	NetDescription& the_net ;
    NodeDescription_LinearList& the_nodes ;
    BufferDescription_LinearList& buffers ;
	int complete_flag ;
	TopLevelWindow * window ;
	NetworkGlyph * the_net_glyph ;
	int now_in_resize ;
	int16 x_size ;
	int16 y_size ;
	int in_map ;
public:
    NetworkDescriptionFull( NetDescription& the_net,
		NodeDescription_LinearList& all_nodes,
		BufferDescription_LinearList& all_buffers, int16 x = -1,
		int16 y = -1);
    NetworkDescriptionFull( NetDescription& the_net,
		NodeDescription_LinearList& edit_nodes);
	virtual ~NetworkDescriptionFull();
	void make_window(ivCoord left, ivCoord bottom, int edit);
	const char * name() const {return the_net.net_name();}
	NetDescription& network() const {return the_net;}
	NetGraph * graph() const {return the_graph;}
	void new_node(NodeDescription * node);
	int complete() const {return complete_flag;}
	NodeDescription_LinearList& nodes() const {return the_nodes;}
	void resize();
	int in_resize() const {return now_in_resize;}
	void change_driven(const char * driver_name, NodeDescription& old_node,
		NodeDescription& new_node);
	void raise_window_node(const char * node_name);
	int using_node(const char * node_name);
	void Remove(NodeDescription& node, int delete_flag = 1);
	void delete_node(const char * name);
	void unmap();
	NetworkGlyph * net_glyph() const {return the_net_glyph;}
	int16 pixel_width() const {return x_size;}
	int16 pixel_height() const {return y_size;}
	TopLevelWindow * win() const {return window;}
	int mapping() const {return in_map;}
	ivCoord width() const ;
	ivCoord height() const ;
	void add_unlinked_node_to_network(NodeDescription * node);
};

declareEditLinearList(NetworkDescriptionFull)

class NetworkDisplayManager: public CommunicateNetworkDescription {
	NetworkDescriptionFull_LinearList the_networks ;
	NetworkDescriptionFull_LinearList the_networks_to_rebuild ;

	NodeDescription_LinearList * nodes_awaiting_network ;

	NodeDescription_LinearList * the_nodes ;
    BufferDescription_LinearList * the_buffers ;
	NetDescription * the_net ;

	GenericArrayElement_LinearList current_list ;
	String_LinearList the_strings ;
	Int_LinearList the_ints ;
	
	StructType type ;
	NetGraph * edit_graph ;
	int16 x_size;
	int16 y_size ;
public:
	NetworkDisplayManager();
	~NetworkDisplayManager();
	DisplayNetworks();
	void network_display(int id,int size,const char *data);
	void network_edit(int id,int size,const char *data);
	void create_edit_node(int size,const char *data);
	void create_edit_network(int size,const char *data);
	void delete_node(int size,const char *data);
	void delete_network(int size,const char *data);
	void new_network(NetworkDescriptionFull * to_add) ;
	void new_network(int16 x, int16 y) ;
	int edit(NetGraph *);
	int unedit(NetGraph *);
	int clear_edit(); // returns 1 not editing or can clear, 0 otherwise
	int editing() const {return edit_graph != 0;}
	int prepare_rebuild(NetGraph * to_prepare);
	void raise_window_node(const char * node_name);
	void set_buffer_descriptor(int size,const char *data);
	void buffer_descriptor_for_net(int size,const char *data);
	const char * where_is_node_being_edited(const char * node_name);
	void removing(NetworkDescriptionFull* rem);
	void dump_nets();
	void check_rebuild();
	void queue_rebuild(NetworkDescriptionFull * net);
	void raise_network(const char * net_name);
};

class NetworkGlyph: public ivMonoGlyph {
	ivCoord last_height ;
	ivCoord last_width ;
	ivCoord the_height ;
	ivCoord the_width ;
	ivCoord max_draw_height ;
	ivCoord max_draw_width ;
	ivCoord rebuild_x ;
	ivCoord rebuild_y ;
	NetworkDescriptionFull * full ;
	ivCanvas * last_canvas ;
	const ivAllocation * last_allocation ;
	int error_out ;
	int check_resize ;
public:
	NetworkGlyph(NetworkDescriptionFull &net) ;
	virtual ~NetworkGlyph();
	static const ivCoord min_width ;
	static const ivCoord min_height ;
	static ivCoord default_width ;
	static ivCoord default_height ;
	static const ivCoord max_width ;
	static const ivCoord max_height ;
	virtual void draw(ivCanvas*, const ivAllocation&) const;
	virtual void allocate(ivCanvas*, const ivAllocation&, ivExtension&) ;
	virtual void request(ivRequisition& r)  const ;
	ivCoord height() const{return the_height;}
	ivCoord width() const{return the_width;}
	void width(ivCoord w) {the_width = w ;}
	void do_damage();
	void clear_full() {full = 0 ;}
	void check_rebuild();
	int rebuild();
	void rebuild(int width, int height);
	void rebuild_current();
	void note_auto_resize();
};

#endif /* #ifdef NETDESCG_DOT_H */
