/** File "gg_page_dimensions.c" 
 *
 *   Copyright (c) 2011 P. Vincent.    See GNU GPL ../LICENSE
 */

#include <gtk/gtk.h>


#include "globals.h"
#include "device.h"
#include "utils.h"

#include "gw_list.h"

#include "gg_gtkinc.h"
#include "gg_protos.h"
#include "ge_protos.h"


#include "gg_page_dimensions.h" 

extern GdkColor  bleuciel ,wheat;

static int block_callbacks = FALSE;

static void orient_CB (GtkWidget *w ,gpointer p);
static void format_CB (GtkWidget *w ,gpointer p);
static void units_CB  (GtkWidget *w ,gpointer p);

static void set_sensitive (PageDimensions *pdim ,int custom);
static void display_size (PageDimensions *pdim ,int wpp ,int hpp ,int is72dpi);

void gg_page_dimensions_new (GtkWidget *w_parent ,PageDimensions *pdim)
{
  GtkWidget *fr ,*hb;
  int nb_page_std_size;
  gg_frame_connect (NULL);
  fr = gg_frame (w_parent ,"Page dimensions " ,&bleuciel ,0 ,1);
  pdim->w_psync = gg_check_new (fr ,"Change x/y ratio on page size change");

  hb = gg_CreateHContainer(fr);
  pdim->w_orient = gg_combo_new (hb ,"Orientation: " ,3
				 ,"Landscape"      /* PAGE_ORIENT_LANDSCAPE = 0 */
				 ,"Portrait");     /* PAGE_ORIENT_PORTRAIT  = 1 */
  nb_page_std_size = NB_OF_PAGE_STD_FMT;

  pdim->w_format = gg_combo_fun (hb ,"Format:" ,&nb_page_std_size ,page_dimensions_get_name ,6);
  gtk_combo_box_set_wrap_width (GTK_COMBO_BOX (pdim->w_format) ,2);

  hb = gg_CreateHContainer(fr);
  pdim->w_page_x     = gg_entry_new (hb ,"Dimensions:" ,7);
  pdim->w_page_y     = gg_entry_new (hb ,"x "          ,7);
  pdim->w_page_units = gg_combo_new (hb ," " ,4 ,"pix" ,"in" ,"cm");
  pdim->w_dev_dpi    = gg_entry_new (fr ,"Resolution (dpi):"  ,4);
  /* Initialisation */
  gg_set_int (pdim->w_psync ,TRUE);
  pdim->page_units = PAGE_UNITS_PIXELS;
  gg_set_int (pdim->w_page_units ,pdim->page_units);
  /* Callbacks */
  g_signal_connect (pdim->w_orient     ,"changed" ,G_CALLBACK (orient_CB) ,pdim);
  g_signal_connect (pdim->w_format     ,"changed" ,G_CALLBACK (format_CB) ,pdim);
  g_signal_connect (pdim->w_page_units ,"changed" ,G_CALLBACK (units_CB)  ,pdim);
}

void gg_page_dimensions_update (PageDimensions *pdim)
{
  int 	       	pformat;
  Device_entry 	dev;
  Page_geometry pg;
  char          buf[32];
  if (pdim == NULL)        return;
  if (pdim->device_id < 0) return;
  if (block_callbacks) 	   return;
  /* update menu */
  block_callbacks = TRUE;
  dev = get_device_props (pdim->device_id);
  pg  = dev.pg;
  gg_set_int 	(pdim->w_orient ,pg.width < pg.height ?
	     	PAGE_ORIENT_PORTRAIT : PAGE_ORIENT_LANDSCAPE);
  pformat 	= check_page_dimensions_std (pg);
  gg_set_int 	(pdim->w_format ,pformat);
  set_sensitive (pdim ,pformat == PAGE_FORMAT_CUSTOM);
  gg_setstr_d 	(pdim->w_dev_dpi ,"%.0f" ,(double)pg.dpi ,buf);
  display_size  (pdim ,(int)pg.width ,(int)pg.height ,FALSE);
  block_callbacks = FALSE;
}

void gg_page_dimensions_apply (PageDimensions *pdim)
{
  int 	       	page_units ,pformat ,custom ,orientation;
  int           wpp ,hpp ,wpp72 ,hpp72 ,rescale;
  double       	dpi ,px ,py;
  Device_entry 	dev;
  if (gg_evalexpr  (pdim->w_dev_dpi, &dpi) != RETURN_SUCCESS || dpi <= 0.0) {
    errmsg("Invalid dpi  (1)");
    return;
  }
  dev = get_device_props (pdim->device_id);
  rescale    = gg_get_int (pdim->w_psync);
  page_units = gg_get_int (pdim->w_page_units);
  pformat    = gg_get_int  (pdim->w_format);
  custom     = (pformat == PAGE_FORMAT_CUSTOM);
  set_sensitive (pdim ,custom);
  px = gg_get_dble (pdim->w_page_x);
  py = gg_get_dble (pdim->w_page_y);
  if (custom) {
    if (page_units_to_pix (page_units ,dpi ,px ,py ,&wpp ,&hpp) == RETURN_FAILURE) {
      return;
    }
    wpp72 = (int) rint((double)wpp * 72.0 / dpi);    /* convert in 72 dpi */
    hpp72 = (int) rint((double)hpp * 72.0 / dpi);    /* convert in 72 dpi */
  } else {
    orientation = gg_get_int (pdim->w_orient);
    calc_page_dimensions_std (pformat ,orientation ,&wpp72 ,&hpp72);
    wpp = rint((double)wpp72 * dpi / 72.0 );    /* convert in device dpi */
    hpp = rint((double)hpp72 * dpi / 72.0 );    /* convert in device dpi */
  }
  if (rescale) set_page_dimensions (wpp72 ,hpp72 ,TRUE);
  dev.pg.dpi    = dpi;
  dev.pg.width  = wpp;
  dev.pg.height = hpp;
  set_device_props (pdim->device_id ,dev);
  if (instant_update) {
    set_dirtystate ();
    gg_drawgraph ();
  }
}



/**************** C A L L B A C K S ****************/

static void orient_CB (GtkWidget *w ,gpointer p)
{
  PageDimensions *pdim = (PageDimensions *) p;
  double px ,py;
  char buf[32];
  if (block_callbacks) return;
  block_callbacks = TRUE;
  if (pdim == NULL) return;
  int orientation = gg_get_int (pdim->w_orient);
  if (gg_evalexpr (pdim->w_page_x ,&px) != RETURN_SUCCESS  ||
      gg_evalexpr (pdim->w_page_y ,&py) != RETURN_SUCCESS  ) {
    errmsg("Invalid page dimension(s) (1)");
    return;
  }
  if ((orientation == PAGE_ORIENT_LANDSCAPE && px > py) ||
      (orientation == PAGE_ORIENT_PORTRAIT  && px < py) ) {
    gg_setstr_d (pdim->w_page_x ,"%.2f", px ,buf);
    gg_setstr_d (pdim->w_page_y ,"%.2f", py ,buf);
  } else {
    gg_setstr_d (pdim->w_page_x ,"%.2f", py ,buf);
    gg_setstr_d (pdim->w_page_y ,"%.2f", px ,buf);
  }
  gg_page_dimensions_apply (pdim);
  block_callbacks = FALSE;
}

static void format_CB (GtkWidget *w ,gpointer p)
{
  PageDimensions *pdim = (PageDimensions *) p;
  int pformat ,orientation ,wpp72 ,hpp72;
  if (block_callbacks) return;
  block_callbacks = TRUE;
  pformat     = gg_get_int  (pdim->w_format);
  if (pformat != PAGE_FORMAT_CUSTOM) {
    orientation = gg_get_int (pdim->w_orient);
    calc_page_dimensions_std (pformat ,orientation ,&wpp72 ,&hpp72);
    display_size 		   (pdim ,wpp72 ,hpp72 ,TRUE);
  }
  gg_page_dimensions_apply (pdim);
  block_callbacks = FALSE;   
}



static void units_CB (GtkWidget *w ,gpointer p)
{
  PageDimensions *pdim = (PageDimensions *) p;
  int 	 	wpp ,hpp;
  double       	dpi ,px ,py;
  if (block_callbacks) return;
  /* Read menu values and compute size in pixels */
  if (gg_evalexpr (pdim->w_dev_dpi, &dpi) != RETURN_SUCCESS || dpi <= 0.0) {
    errmsg("Invalid dpi  (2)");
    return;
  }
  if (gg_evalexpr (pdim->w_page_x ,&px) != RETURN_SUCCESS  ||
      gg_evalexpr (pdim->w_page_y ,&py) != RETURN_SUCCESS  ) {
    errmsg("Invalid page dimension(s) (2)");
    return;
  }
  if (page_units_to_pix (pdim->page_units ,dpi ,px ,py ,&wpp ,&hpp) == RETURN_FAILURE) {
    return;
  }
  /* Get new page_units and display new values of px and py */
  pdim->page_units = gg_get_int (pdim->w_page_units);
  block_callbacks  = TRUE;
  display_size 	   (pdim ,wpp ,hpp ,FALSE);
  /* Nothing else to do since graph aspect is unchanged */
  block_callbacks = FALSE;
}


/**************** U T I L I T I E S ****************/

static void set_sensitive (PageDimensions *pdim ,int custom)
{
  gtk_widget_set_sensitive (pdim->w_page_x ,custom);
  gtk_widget_set_sensitive (pdim->w_page_y ,custom);
  gtk_widget_set_sensitive (pdim->w_orient ,!custom);
}

/* Given "wpp" and "hpp" in pixels units or 72 dpi, display actual size */
static void display_size (PageDimensions *pdim ,int wpp ,int hpp ,int is72dpi)
{
  Device_entry 	dev;
  Page_geometry pg;
  double        px ,py;
  char 	        buf[32];
  dev = get_device_props (pdim->device_id);
  pg.dpi    = dev.pg.dpi;
  if (is72dpi) {         /* wpp and hpp are in 72 dpi */
    wpp = rint((double)wpp * pg.dpi / 72.0 );    /* convert in device dpi */
    hpp = rint((double)hpp * pg.dpi / 72.0 );    /* convert in device dpi */
  }
  pg.width  = (unsigned long) wpp;
  pg.height = (unsigned long) hpp;
  pix_to_page_units (pdim->page_units ,pg ,&px ,&py);
  gg_setstr_d (pdim->w_page_x ,"%.2f" ,px  ,buf);
  gg_setstr_d (pdim->w_page_y ,"%.2f" ,py  ,buf);  
}
