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

cmpack_time_scale_view.h (C-Munipack project)
Widget which can draw a time scale (derived from GtkWidget)
Copyright (C) 2011 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.

$Id: cmpack_time_scale_view.h,v 1.1 2016/02/21 10:32:08 dmotl Exp $

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

#ifndef CMPACK_TIME_SCALE_VIEW_H
#define CMPACK_TIME_SCALE_VIEW_H

#include <gtk/gtk.h>

#include "cmpack_time_scale_data.h"

G_BEGIN_DECLS

#define CMPACK_TYPE_TIME_SCALE_VIEW            (cmpack_time_scale_view_get_type ())
#define CMPACK_TIME_SCALE_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), CMPACK_TYPE_TIME_SCALE_VIEW, CmpackTimeScaleView))
#define CMPACK_TIME_SCALE_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), CMPACK_TYPE_TIME_SCALE_VIEW, CmpackTimeScaleViewClass))
#define CMPACK_IS_TIME_SCALE_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CMPACK_TYPE_TIME_SCALE_VIEW))
#define CMPACK_IS_TIME_SCALE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CMPACK_TYPE_TIME_SCALE_VIEW))
#define CMPACK_TIME_SCALE_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CMPACK_TYPE_TIME_SCALE_VIEW, CmpackTimeScaleViewClass))

typedef struct _CmpackTimeScaleView				CmpackTimeScaleView;
typedef struct _CmpackTimeScaleViewClass		CmpackTimeScaleViewClass;
typedef struct _CmpackTimeScaleViewAxis			CmpackTimeScaleViewAxis;
typedef struct _CmpackTimeScaleViewItem			CmpackTimeScaleViewItem;

typedef void (*CmpackTimeScaleViewForeachFunc)(CmpackTimeScaleView *icon_view, gint row, gpointer data); 

/* Scale format */
typedef enum {
	TIME_SCALE_JD,		// Decimal numbers
	TIME_SCALE_UTC		// Time format
} CmpackTimeScaleFormat;

/* Mouse control mode */
typedef enum {
	TIME_SCALE_MOUSE_NONE,
	TIME_SCALE_MOUSE_ZOOM,
	TIME_SCALE_MOUSE_SELECT,
	TIME_SCALE_MOUSE_SHIFT,
	TIME_SCALE_MOUSE_MOVE_CX
} CmpackTimeScaleMouseMode;

/* Cursor definition */
typedef struct _CmpackTimeScaleCursor
{
	gchar		*caption;
	gint		width, height;
	gdouble		xproj;
} CmpackTimeScaleCursor;

/* Time scale axis parameters */
struct _CmpackTimeScaleViewAxis
{
};

/* Time scale view */
struct _CmpackTimeScaleView
{
	GtkWidget parent;

	/* Private data */
	gint width, height;
	GtkSelectionMode selection_mode;
	CmpackActivationMode activation_mode;
	gboolean mouse_ctrl;

	guint timer_id;
	guint cursor_phase;

	gboolean dirty;
	GdkPixmap *offscreen_pixmap;

	CmpackTimeScaleData *model;

	CmpackTimeScaleViewItem *items;
	gint item_count, item_capacity;
	gint focused_item;
	gint last_single_clicked; 

	GtkAdjustment *hadjustment;
	GtkAdjustment *vadjustment;

	CmpackTimeScaleMouseMode mouse_mode;
	gint mouse_param;				// Cursor index
	gint mouse_x1, mouse_y1;
	gint mouse_x2, mouse_y2;
	gdouble mouse_posx;
	gint last_mouse_x, last_mouse_y;
	GdkCursorType mouse_cursor;

	gdouble		zoom_base;			// Zoom base
	gchar		*label;				// Axis name
	gdouble		min, max;			// Zoom limits
	gdouble		eps;				// Minimum viewfield
	gboolean	show_labels;		// Show labels
	gboolean	show_grid;			// Show grid lines
	gboolean	labels_opposite;	// Labels are on the top/right side
	CmpackTimeScaleFormat format;	// Format of labels
	gint		min_prec;			// Minimum number of decimal places
	gint		max_prec;			// Maximum number of decimal places
	gdouble		zoom_pos;			// Actual zoom position
	gdouble		zoom_max;			// Zoom position limits
	gdouble		pxl_size;			// Size of device unit in projection units
	gdouble		pos;				// Center of viewfield in projection units
	gdouble		center;				// Center of viewfield in device units
	gint		cursor_count;		// Number of cursors 
	gint		cursor_space;		// Number of allocated items 
	CmpackTimeScaleCursor *cursors;	// Cursors

	GdkRectangle canvas_rc;
	GdkRectangle graph_rc;
	GdkRectangle xscale_rc;
	GdkRectangle xname_rc;
	GdkRectangle xcursor_rc;

	GdkColor	*int_colors;
};

/* Time scale view class */
struct _CmpackTimeScaleViewClass
{
  GtkWidgetClass parent_class;

  /* Signals */
  void (*set_scroll_adjustments)(CmpackTimeScaleView *view, 
	  GtkAdjustment *hadjustment, GtkAdjustment *vadjustment);
  void (*item_activated)(CmpackTimeScaleView *view, gint row);
  void (*selection_changed)(CmpackTimeScaleView *view);
  void (*mouse_moved)(CmpackTimeScaleView *view);
  void (*mouse_left)(CmpackTimeScaleView *view);
  void (*cursor_moved)(CmpackTimeScaleView *view, gint cursor);
};

GType cmpack_time_scale_view_get_type(void) G_GNUC_CONST;

/* -------------------------   PUBLIC FUNCTIONS   --------------------------------- */

/* Create a new time scale view (makes a new data model) 
 * Returns floating reference to the time scale view
 */
GtkWidget *cmpack_time_scale_view_new(void);

/* Create a new time scale view and link it to given data model
 * params:
 *	data					- [in] data model
 * Returns floating reference to the time scale view
 */
GtkWidget *cmpack_time_scale_view_new_with_model(CmpackTimeScaleData *data);

/* Change the data model which the view is connected to
 * params:
 *	view					- [in] graph view
 *	data					- [in] new data model
 */
void cmpack_time_scale_view_set_model(CmpackTimeScaleView *view, CmpackTimeScaleData *data);

/* Get the data model with the view is connected to
 * params:
 *	view					- [in] graph view
 * Returns borrowed reference to the current data model
 */
CmpackTimeScaleData* cmpack_time_scale_view_get_model(CmpackTimeScaleView *view);

/* Set data channel and for independent axis
 * params:
 *	view					- [in] graph view
 *	min, max				- [in] physical limits of the scroll area
 *	eps						- [in] minimum resolution in projection units (zoom limit)
 *	format					- [in] format of displayed numbers
 *	minprec					- [in] minimum number of decimal places
 *	maxprec					- [in] maximum number of decimal places
 *	name 					- [in] displayed name
 */
void cmpack_time_scale_view_set(CmpackTimeScaleView *view, gdouble min, gdouble max, gdouble eps, 
	CmpackTimeScaleFormat format, gint minprec, gint maxprec, const gchar *caption);

/* Set scale visibility and position for specified axis
 * params:
 *	view					- [in] graph view
 *	visible					- [in] show JD/UTC values
 */
void cmpack_time_scale_view_set_labels(CmpackTimeScaleView *view, gboolean visible);

/* Set grid visibility for specified axis
 * params:
 *	view					- [in] graph view
 *	visible					- [in] show vertical lines
 */
void cmpack_time_scale_view_set_grid(CmpackTimeScaleView *view, gboolean visible);

/* Change zoom
 * params:
 *	view					- [in] graph view
 *	zoom					- [in] new zoom coefficient
 */
void cmpack_time_scale_view_set_zoom(CmpackTimeScaleView *view, gdouble zoom);

/* Get current zoom
 * params:
 *	view					- [in] graph view
 * Returns current zoom coefficient
 */
gdouble cmpack_time_scale_view_get_zoom(CmpackTimeScaleView *view);

/* Change zoom to given size
 * params:
 *	view					- [in] graph view
 *	viewfield				- [in] new viewfield in projection units
 */
void cmpack_time_scale_view_set_viewfield(CmpackTimeScaleView *view, 
	gdouble viewfield);

/* Get current width of viewfield
 * params:
 *	view					- [in] graph view
 * Returns current width of viewfield in projection units
 */
gdouble cmpack_time_scale_view_get_viewfield(CmpackTimeScaleView *view);

/* Move graph
 * params:
 *	view					- [in] graph view
 *	center					- [in] new position of the center of the viewfield
 */
void cmpack_time_scale_view_set_center(CmpackTimeScaleView *view, 
	gdouble center);

/* Get position
 * params:
 *	view					- [in] graph view
 *	axis					- [in] axis in question
 * Returns current position of the center of the viewfield in physical units
 */
gdouble cmpack_time_scale_view_get_center(CmpackTimeScaleView *view);

/* Auto zoom the view to available data
 * params:
 *	view					- [in] graph view
 */
void cmpack_time_scale_view_auto_zoom(CmpackTimeScaleView *view);

/* Enable/disable changing of zoom by mouse wheel or area selection 
 * params:
 *	view					- [in] graph view
 *	enable					- [in] TRUE=enable, FALSE=disable
 */
void cmpack_time_scale_view_set_mouse_control(CmpackTimeScaleView *view, gboolean enable);

/* Set zoom to show the whole projection area
 * params:
 *	view					- [in] graph view
 */
void cmpack_time_scale_view_reset_zoom(CmpackTimeScaleView *view);

/* Set selection mode
 * params:
 *	view					- [in] graph view
 *	mode					- [in] new selection mode
*/
void cmpack_time_scale_view_set_selection_mode(CmpackTimeScaleView *view, 
	GtkSelectionMode mode);

/* Get current selection mode
 * params:
 *	view					- [in] graph view
 * Returns one of GTK_SELECTION_xxx constants
*/
GtkSelectionMode cmpack_time_scale_view_get_selection_mode(CmpackTimeScaleView *view);

/* Set activation mode. Items can be activated by single or double click. The default
 * is double-click activation.
 * params:
 *	view					- [in] graph view
 *	mode					- [in] activation mode, one of CmpackActivationXXX constants
 */
void cmpack_time_scale_view_set_activation_mode(CmpackTimeScaleView *view, CmpackActivationMode mode);

/* Get current activation mode.
 * params:
 *	view					- [in] graph view
 * Returns one of CmpackActivationXXX constants
 */
CmpackActivationMode cmpack_time_scale_view_get_activation_mode(CmpackTimeScaleView *view);

/* Get number of selected rows
 * params:
 *	view					- [in] graph view
 * Returns number of selected rows
*/
gint cmpack_time_scale_view_get_selected_count(CmpackTimeScaleView *view);

/* Get list of selected rows
 * params:
 *	view					- [in] graph view
 * Returns list of item indices
*/
GList *cmpack_time_scale_view_get_selected_rows(CmpackTimeScaleView *view);

/* Get index of selected item (meaningful in single selection mode)
 * params:
 *	view					- [in] graph view
 * Returns index of item or negative value if no item is selected
*/
gint cmpack_time_scale_view_get_selected(CmpackTimeScaleView *view);

/* Get index of focused item
 * params:
 *	view					- [in] graph view
 * Returns index of item or negative value if no item is focused
*/
gint cmpack_time_scale_view_get_focused(CmpackTimeScaleView *view);

/* Emits the signal that an item was activated.
 * params:
 *	view					- [in] graph view
 *	row						- [in] row index
*/
void cmpack_time_scale_view_item_activate(CmpackTimeScaleView *view, gint row);

/* Call user function for each selected item
 * params:
 *	view					- [in] graph view
 *	func					- [in] function to be called
 *	data					- [in] data passed to the function
*/
void cmpack_time_scale_view_selected_foreach(CmpackTimeScaleView *view,
	CmpackTimeScaleViewForeachFunc func, gpointer data);

/* Select an item / add item to selection
 * params:
 *	view					- [in] graph view
 *	row						- [in] row index
*/
void cmpack_time_scale_view_select(CmpackTimeScaleView *view, gint row);

/* Unselect an item / remove item from selection
 * params:
 *	view					- [in] graph view
 *	row						- [in] row index
*/
void cmpack_time_scale_view_unselect(CmpackTimeScaleView *view, gint row);

/* Returns nonzero if the item is selected
 * params:
 *	view					- [in] graph view
 *	row						- [in] row index
*/
gboolean cmpack_time_scale_view_is_selected(CmpackTimeScaleView *view, gint row);

/* Select all items
 * params:
 *	view					- [in] graph view
*/
void cmpack_time_scale_view_select_all(CmpackTimeScaleView *view);

/* Unselect all items
 * params:
 *	view					- [in] graph view
*/
void cmpack_time_scale_view_unselect_all(CmpackTimeScaleView *view);

/* Get coordinates of mouse position
 * params:
 * view						- [in] graph view
 *  x						- [out] physical coordinates
*/
gboolean cmpack_time_scale_view_mouse_pos(CmpackTimeScaleView *view, gdouble *x);

/* Export image into a file in PNG format
 * params:
 * view						- [in] graph view
 * filepath					- [in] target file path
 * format					- [in] description of the file format
*/
gboolean cmpack_time_scale_view_write_to_file(CmpackTimeScaleView *view,
	const gchar *filepath, const gchar *format);

/* Define/remove cursors
 * params:
 * view						- [in] graph view
 * count					- [in] number of cursors defined
*/
void cmpack_time_scale_view_set_cursors(CmpackTimeScaleView *view, 
	gint count);

/* Set cursor position
 * params:
 * view						- [in] graph view
 * cursor					- [in] cursor index (0 = first, ...)
 * pos						- [in] new position
*/
void cmpack_time_scale_view_set_cursor_pos(CmpackTimeScaleView *view, 
	gint cursor, gdouble pos);

/* Get cursor position
 * params:
 * view						- [in] graph view
 * cursor					- [in] cursor index (0 = first, ...)
*/
gdouble cmpack_time_scale_view_get_cursor_pos(CmpackTimeScaleView *view, 
	gint cursor);

/* Set cursor caption
 * params:
 * view						- [in] graph view
 * cursor					- [in] cursor index (0 = first, ...)
 * caption					- [in] new caption
*/
void cmpack_time_scale_view_set_cursor_caption(CmpackTimeScaleView *view, 
	gint cursor, const gchar *caption);

G_END_DECLS

#endif
