/* DiaCanvas -- A technical drawing canvas.
 * Copyright (C) 1999, Arjan Molenaar
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
/* Original license:
 * Dia -- an diagram creation/manipulation program
 * Copyright (C) 1998 Alexander Larsson
 *
 * 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.
 */

/* diadisplay.h
 * ------------
 * Displays are used to visualize diagrams on the screen. Tools are used to
 * modify the diagram (or the display, like the magnify tool).
 */

#ifndef __DIA_DISPLAY_H__
#define __DIA_DISPLAY_H__

#include <gtk/gtk.h>
#include <diacanvas/geometry.h>
#include <diacanvas/diadefs.h>
#include <diacanvas/diaevent.h>

DIA_OPEN

#define DIA_TYPE_DISPLAY            (dia_display_get_type ())
#define DIA_DISPLAY(obj)            (GTK_CHECK_CAST ((obj), DIA_TYPE_DISPLAY, DiaDisplay))
#define DIA_DISPLAY_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), DIA_TYPE_DISPLAY, DiaDisplayClass))
#define DIA_IS_DISPLAY(obj)         (GTK_CHECK_TYPE ((obj), DIA_TYPE_DISPLAY))
#define DIA_IS_DISPLAY_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), DIA_TYPE_DISPLAY))

typedef struct _DiaDisplay DiaDisplay;
typedef struct _DiaDisplayClass DiaDisplayClass;

#include <diacanvas/diagrid.h>
#include <diacanvas/diadiagram.h>
#include <diacanvas/diarenderergdk.h>

#define DIA_DISPLAY_MAX_ZOOM 500.0
#define DIA_DISPLAY_NORMAL_ZOOM 20.0
#define DIA_DISPLAY_MIN_ZOOM 1.0

struct _DiaDisplay
{
  GtkTable      table;            /* parent */

  /* data objects: */
  /* Pointer to the associated diagram. */
  DiaDiagram   *diagram;
  /* Active layer (from DiaDiagram). only one layer can be modified at
   * one time. */
  DiaLayer     *active_layer;
  /* All selected items. Selection is a state of an object, but depends
   * on the display it is drawn in. */
  GList        *selected;
  /* Object on the canvas that has the focus (more than one objects can
   * be selected, but only one object can have the focus). */
  DiaObject    *focus;
  /* Object that has the grab (recieves all events). Otherwise events
   * are send to the object under the mouse. */
  DiaObject    *grab;

  /* Layout widgets: */
  GtkWidget      *canvas;          /* canvas widget for this ddisplay   */
  GtkWidget      *hsb, *vsb;       /* widgets for scroll bars           */
  GtkWidget      *hrule, *vrule;   /* widgets for rulers                */
  GtkWidget      *origin;          /* widgets for rulers                */

  GtkAdjustment  *hsbdata;         /* horizontal data information       */
  GtkAdjustment  *vsbdata;         /* vertical data information         */
  
  gint            redraw_handler;  /* handler to the idle function that *
				    * takes care of redraws.            */
  
  /* misc: */
  Point           origo;           /* The origo (upper left) position   */
  gfloat          zoom_factor;     /* zoom, 20.0 means 20 pixel == 1 cm */
  Rectangle       visible;         /* The part visible in this display  */
  gint            cursor;
  
  DiaGrid         grid;            /* the grid in this display          */

  gboolean        autoscroll;      /* should auto-scrolls be performed? */
  gboolean        is_autoscrolled;
   
  /* the selection box: */
  gboolean        drawing_box;      /* is a box being drawn? */
  Point           start_box;
  Point           end_box;
  
  DiaRendererGdk *renderer;
  Rectangle       update_box;       /* box to update. If left == right
				     * or top == bottom no update has to
				     * be done. */
};

struct _DiaDisplayClass
{
  GtkTableClass parent_class;

  void (*select_object)   (DiaDisplay *display, DiaObject *object);
  void (*unselect_object) (DiaDisplay *display, DiaObject *object);
  void (*focus_object)    (DiaDisplay *display, DiaObject *object);
  void (*unfocus_object)  (DiaDisplay *display, DiaObject *object);
  void (*grab_object)     (DiaDisplay *display, DiaObject *object);
  void (*ungrab_object)   (DiaDisplay *display, DiaObject *object);

  /* This event is fired if the active display changes (the last edited display
   * can be retrieved using dia_display_get_last_edited_display ()). */
  void (*active_display_change) (DiaDisplay *display);
};

void dia_object_set_default_cursor (guint32 cursor);

GtkType     dia_display_get_type ();

/* create a DiaCanvas Display Widget... width and height are the width and
 * height of the canvas. */
GtkWidget*  dia_display_new (DiaDiagram *dia, gint width, gint height);

/* Create a DiaCanvas and place it in a window. TITLE may be NULL.
 * The canvas can be retrieved with:
 *  GtkWidget *display = GTK_WIDGET (gtk_object_get_data (<window>,
 *                                   "display"));
 * The (real) canvas can by found with:
 *  GtkWidget *canvas = GTK_WIDGET (gtk_object_get_data (<window>, "canvas"));
 * This means that display->canvas == canvas.
 */
GtkWidget*  dia_display_new_in_window (DiaDiagram *dia, gint width,
				       gint height, gchar *title);

/* Add/remove an object from the diagram */
//void dia_display_add_object (DiaDisplay *ddisp, DiaObject *object);
//void dia_display_remove_object (DiaDisplay *ddisp, DiaObject *object);

/* select an object, use ADD=TRUE if you want to exand the selection list.
 * ADD=FALSE will unselect all selected objects first. */
void dia_display_select (DiaDisplay *ddisp, DiaObject *object, gboolean add);
gboolean dia_display_is_selected (DiaDisplay *ddisp, DiaObject *object);
void dia_display_unselect (DiaDisplay *ddisp, DiaObject *object);
void dia_display_unselect_all (DiaDisplay *ddisp);

/* OBJECT may be NULL (no object has focus). */
void dia_display_set_focus (DiaDisplay *ddisp, DiaObject *object);
DiaObject* dia_display_get_focus (DiaDisplay *ddisp);
gboolean dia_display_is_focused (DiaDisplay *ddisp, DiaObject *object);
//void dia_display_unfocus (DiaDisplay *ddisp);

/* returns TRUE if the grab is successful */
gboolean dia_display_grab (DiaDisplay *ddisp, DiaObject *object);
void dia_display_ungrab (DiaDisplay *ddisp, DiaObject *object);

/* Conversion: convert a position to display coordinates */
void dia_display_transform_coords (DiaDisplay *ddisp,
				gfloat x, gfloat y,
				gint *xi, gint *yi);
/* invers: */
void dia_display_untransform_coords (DiaDisplay *ddisp,
				  gint xi, gint yi,
				  gfloat *x, gfloat *y);
/* convert from world-length to pixel-length */
gint dia_display_transform_length (DiaDisplay *ddisp, gfloat len);
/* Takes pixel length and returns real length */
gfloat dia_display_untransform_length (DiaDisplay *ddisp, gint len);

/* add update boxes to the display */
void dia_display_add_update_all (DiaDisplay *ddisp);
void dia_display_add_update (DiaDisplay *ddisp, Rectangle *rect);
void dia_display_add_update_list (DiaDisplay *ddisp, GList *list_to_update);
void dia_display_add_update_object (DiaDisplay *ddisp, DiaObject *object);

/* force the display to redraw itself: */
void dia_display_flush (DiaDisplay *ddisp);

void dia_display_update_scrollbars (DiaDisplay *ddisp);
void dia_display_set_origo (DiaDisplay *ddisp,
			    gfloat x, gfloat y);
void dia_display_zoom (DiaDisplay *ddisp, Point *point,
		       gfloat zoom_factor);
void dia_display_zoom_box (DiaDisplay *ddisp, Point *origo,
			   gfloat width, gfloat height);

/* The state of an object depends on the display it is drawn in... */
void dia_display_update_object_state (DiaDisplay *disp, DiaObject *obj);

void dia_display_resize_canvas (DiaDisplay *ddisp,
				gint width,
				gint height);

void dia_display_render_pixmap (DiaDisplay *ddisp, GdkRectangle *ir);

void dia_display_close (DiaDisplay *ddisp);

/* scroll functions. Returns TRUE if a scroll is done.
 */
gboolean dia_display_scroll (DiaDisplay *ddisp, Point *delta);

/* Call this one to automatically scroll over the canvas and stay within the
 * range of the objects. FALSE is returned if no scroll action is done.
 * scroll actions are not buffered.
 */
gboolean dia_display_autoscroll (DiaDisplay *ddisp, gint x, gint y);

void dia_display_scroll_up (DiaDisplay *ddisp);
void dia_display_scroll_down (DiaDisplay *ddisp);
void dia_display_scroll_left (DiaDisplay *ddisp);
void dia_display_scroll_right (DiaDisplay *ddisp);

/* cursor functions:
 */
/* Set the default cursor for displays that will be created (not the
 * already created ones!).
 */
void dia_display_set_default_cursor (int cursor);
void dia_display_set_cursor (DiaDisplay *ddisp, int cursor);
/* Force all displays to use CURSOR as cursor. */
void dia_display_set_all_cursor (int cursor);
/* reset the cursor to the default cursor */
void dia_display_default_cursor (DiaDisplay *ddisp);

/* ruler visibility functions
 */
void dia_display_set_rulers_visibility (DiaDisplay *ddisp, gboolean visible);
gboolean dia_display_rulers_visible (DiaDisplay *ddisp);

/* in: GDK_EVENT, DISP.
 * out: DIA_EVENT (note that you can't use a NULL-pointer for this!)
 */
void dia_display_convert_gdk_event (DiaDisplay *disp, GdkEvent *gdk_event, 
				    DiaEvent *dia_event);

/* A nice convenience function if you need to focus another window to perform
 * an action on the display (for example a control window). It can return NULL
 * which means that 1. there hasn't been any display selected or 2. the last
 * selected display is destroyed. The Last-edited-display is the display that
 * was the last recieveing a button-press event.
 * Take notice that some users might be using the focus-follow-mouse option!
 */
DiaDisplay* dia_display_get_last_edited_display ();

DIA_CLOSE

#endif /* __DIA_DISPLAY_H__ */







