/*
 *  iv_graph.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 IV_GRAPH_DOT_H
#define IV_GRAPH_DOT_H
/*
 * Graph.h
 */

#include <InterViews/observe.h>
#include "com_input.h"
#include "bound_val.h"

#include "portable.h"

class Window ;
class Axis;
class XAxis;
class YAxis;
class Color;
class Patch;
class Plot;
class String;
class XYMarker;
class DataPlot ;
class PlotChannelPointer ;
class DataPlotHeader ;
class AxisLabelX;
class AxisLabelY;
class Font ;
class RelativePosition ;
class AbsolutePosition ;
class LayoutKit ;
class WidgetKit ;
class Glyph ;
class MonoGlyph ;
class MenuKeyboard ;
class Graph ;

class Graph : public DspActiveHandler, public Observer {
	BoundedValue box ;
	int in_update ;
	int in_adjust_adjuster;
public:
    Graph( float w, float h, const Color*, DataPlot *plt, ivStyle *s);
/*
 *  Graph(
 *      float w, float h, float x_begin, float x_end, 
 *      float y_begin, float y_end, const Color*, DataPlot *plt, ivStyle *s
 * );
 */
	void add_point(double *pt, int channel);
	void add_points(int chan, int element, RelativePosition * pos);
	void new_page();
    virtual void request(Requisition&) const;
    virtual void allocate(Canvas*, const Allocation&, Extension&);


	virtual void focus_out();
	virtual InputHandler * focus_in();

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

	virtual void enter();
	virtual void leave();

    virtual void update(Observable*);
	void adjust_adjuster();
	void update_size();
    virtual Adjustable* adjustable() ;

	void redraw_x() const ;
	void redraw_y() const ;
	void check_axis_redraw() const ;

	int32 get_plot_pixel_width() const ;
	Coord get_plot_width() const ;
	void send_complete_after_draw();
	void complete() ;
	void set_x_tick_spacing();
	void set_y_tick_spacing();
	void reset();
	void home();
	void shift_home();
private:
	DataPlot * data_plot ;

	double y_min_relative_displayed ;
	double y_diff_relative_displayed ;
	int y_scale_flag ;

	double x_min_relative_displayed ;
	double x_diff_relative_displayed ;

	double orig_sample_width ;
	double prev_sample_width ;
	double curr_sample_width ;
	int x_scale_flag ;		// only used for eye plots

	AxisLabelX * x_labels ;
	AxisLabelY * y_labels ;
    int x_ticks ;
    int y_ticks ;

	int32 NoXTicksPerLabel;
	int32 NoYTicksPerLabel;

	const Font * _font ;
	long resize_key_stroke;
	Coord first_pos_x ;
	Coord first_pos_y ;
	double x_min_this_plot ;
	double x_max_this_plot ; // only used for eye plots

	double y_min_this_plot ;
	double y_max_this_plot ;
	Canvas * last_canvas ;
	Allocation * last_allocation ;

	double prompt_value_return;
	int got_value ;
public:
	enum RescaleState {no_data,data_sent,no_fetch_remote,no_rescaling}
		_rescale_x, _rescale_y;
	void set_allow_rescale_x();
	void set_allow_rescale_y();
	int allow_rescale_x() const {return _rescale_x != no_rescaling;}
	int allow_rescale_y() const {return _rescale_y != no_rescaling;}
	int allow_fetch_remote_y() {return _rescale_y < no_fetch_remote;}
	int allow_fetch_remote_x() {return _rescale_x < no_fetch_remote;}
	int check_do_rescale_x() ;
	int check_do_rescale_y() ;
	void update_x_limits();
	void update_y_limits();
	void rescale_x() ;
	void rescale_y() ;
	double get_y_max_this_plot() {update_y_limits(); return y_max_this_plot;}
	double get_y_min_this_plot() {update_y_limits(); return y_min_this_plot;}
	void do_damage() ; // scaling has changed update if needed
	void background_draw(Canvas *c, const Allocation & a) const;
/*
 *	Absolute canvas is in points and is a position on the screen.
 *	Absolute value is the value displayed on the axis labeling
 *	Relative is a value from 0 to 1 that is the realative position
 *		of this point to the entire x (or y) range of values.
 */

	double sample_width() const {return curr_sample_width;}
	void set_sample_width(double width) ;
	void draw_new_width(double width);
	void resize(long key, long cursor) ;

	void eye_plot_samples();
	double y_min() const ;
	double y_max() const ;
	double x_min() const ;
	double x_max() const ;

	int absolute(AbsolutePosition&,const RelativePosition&);
	int relative(RelativePosition&,const AbsolutePosition&);

	void list_pos(RelativePosition& pos) ;

	double x_abs_value(float x_rel);
	float x_rel(Coord x_abs);
	float x_rel(double x_abs);
	Coord x_coord(float x_rel);

	int is_eye_plot() const ;

	double y_abs_value(float y_rel);
	float y_rel(Coord y_abs);
	float y_rel(double y_abs);
	Coord y_coord(float y_rel);

	Coord x_to_coord(double x);
	Coord y_to_coord(double x);
	double coord_to_x(Coord x_c);
	double coord_to_y(Coord x_c);

	int x_scaling() const {return x_scale_flag;}
	int y_scaling() const {return y_scale_flag;}
	float x_scale(float x) const ;
	float y_scale(float y) const ;

	void restore_x_scale() {x_scale_flag =0;}
	void restore_y_scale() {y_scale_flag =0;}
	int rescale_y_more_detail(Coord abs_top, Coord abs_bottom);
	int rescale_y_less_detail(Coord abs_top, Coord abs_bottom);
	int rescale_x_more_detail(Coord abs_right, Coord abs_left);
	int rescale_x_less_detail(Coord abs_right, Coord abs_left);

	void check_clear_prev_x();
	void check_clear_prev_y();

	void end_rescale() ;


	const Font * font() const {return _font;}
	PlotChannelPointer * get_data_plot_channel(int i) const ;
	DataPlot * get_data_plot() const {return data_plot;}
	DataPlotHeader * get_data_plot_header()
		const {return (DataPlotHeader *) data_plot;}
	boolean is_mapped() const ;
	void mark(RelativePosition& pos);
	void mark (Coord x, Coord y, long key);
    virtual void mark (int);
	void redraw() const ;
	void new_sample_width();
	const Allocation* plot_allocation() const ;
	MenuKeyboard * build_menu(WidgetKit*, const LayoutKit&, Style * style,
		DataPlot * plt);
	void save_plot();
	void save_plot(const char * name);

	int prompt_for_value(const char * msg) ;
	void prompt_value(const char * value) ;
	void to_time();
    void to_sample();
    void ahead_time();
    void ahead_samples();

protected:
    virtual ~Graph();

    boolean _init;
    int _current;
    double _w, _h;
    double _x_range, _y_range;
    double _x_origin, _y_origin;
    Plot* _plot;
    XYMarker* _marker;
    XAxis* _xaxis;
    Patch* _xpatch;
    YAxis* _yaxis;
    Patch* _ypatch;
    String* _symbol;
    Patch* _ppatch;
	Patch* _caption_patch ;
	Patch* background_patch ;
	WidgetKit * kit ;
	LayoutKit * layout ;
	MenuKeyboard * the_menu_keyboard ;

	double InternalToUserTime(double InternalTime) ;
public:
	XAxis& x_axis() const {return *_xaxis;}
	YAxis& y_axis() const {return *_yaxis;}
	MenuKeyboard * menu_keyboard() const { return the_menu_keyboard;}
	Plot* plot() const {return _plot;}
	void raise_window();
	void make_caption() const ;
	XYMarker* marker() const {return _marker;}
private:
    double rel_max ;
    double rel_min ;
    double cur_min ;
    double cur_max ;
    double cur_diff ;
    double rel_diff ;
    double min_val ;
    double max_val ;
	double diff ;

	long save_key ;
	long save_cursor ;
	int is_inside ;

	int y_setup_rescale(Coord abs_top, Coord abs_bottom);
	int x_setup_rescale(Coord abs_right, Coord abs_left);
	int rescale_x_less_detail();
	int rescale_x_more_detail();
	int rescale_y_less_detail();
	int rescale_y_more_detail();

};

#define XK_FUNCTION_FLAG 0x10000

extern const Color* color (const char* name) ;
#endif /* #ifdef IV_GRAPH_DOT_H */
