/**************************************************************

mv_graph.h (C-Munipack project)
Display graph class
Copyright (C) 2012 David Motl, dmotl@volny.cz

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

**************************************************************/

#ifndef CCD_GRAPH_H
#define CCD_GRAPH_H

#include "mv_class.h"
#include "mv_channels.h"
#include <cmunipack.h>

class TCCD_Graph:public TCCD_Interface 
{
public:
	// Check if the buffer contains beginning of an image
	static bool Test(const char *buf, int bytes);

public:
	// Constructor
	TCCD_Graph(void);
		
	// Destructor
	virtual ~TCCD_Graph(void);
		
	// Load a file
	virtual bool Load(const char *filename);

	// Makes preview and returns the HBITMAP
	virtual HBITMAP MakePreview(int max_width, int max_height);

	// Get pointer to the table
	CmpackTable *Handle(void) { return m_Tab; }

	// Get image format name
	const char *FormatName(void) const;

	// Get image format name
	CmpackTableType TableType(void) const { return m_Type; }

	// Optical filter name
	const char *Filter(void) const { return m_Filter; }

protected:
	// Adjust scroll bars
	virtual void OnSizeChanged(void);

	// Draw a bitmap, image, chart, ...
	virtual void OnRender(HDC hdc);

	// HSB changed
	virtual void OnHSBChanged(int nPos);
		
	// VSB changed
	virtual void OnVSBChanged(int nPos);

	// Keyboard event handler
	virtual void OnKeyDown(int vKey);

	// Create menu 
	virtual HMENU CreateCtxMenu(void);

	// Context menu commands
	virtual void OnMenuCommand(int iCmd);

	// Get topic id (help page opened)
	virtual int GetTopicId(void);

private:
	// Scale format 
	enum GraphFormat 
	{
		FORMAT_FIXED,		// Decimal numbers
		FORMAT_INT,			// Integer numbers
		FORMAT_EXP,			// Exponential numbers
		FORMAT_TIME			// Time format
	};

	// Graph item 
	struct GraphItem 
	{
		double		xproj, yproj;		// Position in projection units
		double		error;				// Error estimation in projection units
	}; 

	// Graph axis parameters 
	struct GraphAxis
	{
		char		*Caption;			// Axis name
		bool		Log;				// Log mapping
		bool		Reverse;			// Reverse mapping
		double		Min, Max;			// Limits in physical units
		double		ProjMin, ProjMax;	// Limits in projection units
		double		ProjEps;			// Minimum viewfield in projection units
		bool		ShowLabels;			// Show labels
		bool		ShowGrid;			// Show grid lines
		bool		LabelsOpposite;		// Labels are on the top/right side
		GraphFormat Format;				// Format of labels
		int			MinPrec;			// Minimum number of decimal places
		int			MaxPrec;			// Maximum number of decimal places
		double		ZoomPos;			// Actual zoom position
		double		ZoomMax;			// Zoom position limits
		double		PxlSize;			// Size of device unit in projection units
		double		ProjPos;			// Center of viewfield in projection units
		double		Center;				// Center of viewfield in device units
		RECT		ScaleRc;
		RECT		LabelRc;
	};
	
	CmpackTable		*m_Tab;				// Table data
	CmpackTableType	m_Type;				// Type of the table
	char			*m_Filter;			// Optical filter name

	GraphItem		*m_Data;			// Graph data
	int				m_Count, m_Capacity;	// Number of items, allocated space
	CChannels		m_ChannelsX, m_ChannelsY;
	int				m_ChannelX, m_ChannelY;
	int				m_PtSize;			// Size of a point
	int				m_ClientWidth, m_ClientHeight;		// Client area size
	int				m_GraphWidth, m_GraphHeight;		// Graph area size
	RECT			m_CanvasRc;
	RECT			m_GraphRc;
	bool			m_ShowErrors;		// Show error bars
	double			m_ZoomBase;			// Zoom base
	GraphAxis		m_X, m_Y;			// Axis parameters
	HFONT			m_hFont;
	char			*m_Title;
	
	void Clear();
	void UpdateParams();
	void UpdateTitle();
	void UpdateChannels();
	void UpdateData();

	void RenderGraph(HDC hDC, int left, int top, int width, int height, bool for_print);

	// Show image properties
	void ShowProperties(void);

	// Copy image to clipboard
	void CopyToClipboard(void);

	void SetTitle(const char *caption);
	void SelectChannel(int channel);
	void SetPointSize(int size);
	void SetAxisX(bool log_scale, bool reverse, double min, double max, double eps, 
		GraphFormat format, int minprec, int maxprec, const char *caption);
	void SetAxisY(bool log_scale, bool reverse, double min, double max, double eps, 
		GraphFormat format, int minprec, int maxprec, const char *caption);
	void SetScales(bool x_axis, bool y_axis);
	void SetGrid(bool x_axis, bool y_axis);
		
	void update_rectangles(void);
	void update_x_pxlsize(void);
	void restrict_x_to_limits(void);
	void update_y_pxlsize(void);
	void restrict_y_to_limits(void);
	void update_hsb(void) const;
	void update_vsb(void) const;
	bool set_x_axis(double zoom, double center);
	bool set_auto_zoom_x(void);
	bool set_y_axis(double zoom, double center);
	bool set_auto_zoom_y(void);

	double x_to_proj(double x) const;
	double proj_to_x(double u) const;
	double xproj_to_view(double x) const;
	double view_to_xproj(double u) const;
	double x_to_view(double x) const;
	double view_to_x(double u) const;
	double y_to_proj(double y) const;
	double proj_to_y(double v) const;
	double yproj_to_view(double y) const;
	double view_to_yproj(double v) const;
	double y_to_view(double y) const;
	double view_to_y(double v) const;

	void paint_data(HDC hDC);
	void paint_x_scale(HDC hDC);
	void paint_y_scale(HDC hDC);
	void paint_x_grid(HDC hDC);
	void paint_y_grid(HDC hDC);
	void paint_title(HDC hDC);
	
	void format_label(char *buf, size_t buflen, double value, GraphFormat format, int prec);
	int compute_label_width(HDC hDC, GraphAxis *axis, int prec);
	int compute_label_height(HDC hDC, GraphAxis *axis);
	void compute_x_grid_step(HDC hDC, double minval, double maxval, double *step, int *minprec);
	void compute_y_grid_step(HDC hDC, double minval, double maxval, double *step, int *minprec);
	void draw_text(HDC hDC, int x, int y, const char *buf, double halign, double valign);
	void text_extents(HDC hDC, const char *buf, SIZE *size);
	int text_width(HDC hDC, const char *buf);
	int	text_height(HDC hDC, const char *buf);
};

#endif
