/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * filename: xzoom.c                                                       *
 *                                                                         *
 * UTIL C-source: Medical Image Conversion Utility                         *
 *                                                                         *
 * purpose      : image zoom routines                                      *
 *                                                                         *
 * project      : (X)MedCon by Erik Nolf                                   *
 *                                                                         *
 * Functions    : XMdcImagesZoomIn()              - Zoom image IN          *
 *                XMdcImagesZoomOut()             - Zoom image OUT         *
 *                XMdcImagesZoomCallbackClicked() - Zoom Clicked  callback *
 *                XMdcImagesZoom()                - Display zoomed image   *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
 */

/*
   Copyright (C) 1997-2026 by Erik Nolf

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

/****************************************************************************
                              H E A D E R S
****************************************************************************/

#include "m-depend.h"

#include <stdio.h>
#ifdef LIBMDC_HAVE_STDLIB_H
#include <stdlib.h>
#endif

#include "xmedcon.h"

/****************************************************************************
                              D E F I N E S
****************************************************************************/

typedef struct ZoomStruct_t {

  int type;
  Uint32 nr;
  GdkPixbuf *im, *cur;
  GtkWidget *darea;

}ZoomStruct;

/****************************************************************************
                            F U N C T I O N S
****************************************************************************/


/* local routine */
static int XMdcGetZoomFactor(ZoomStruct *zoom, int z)
{
  zoom->type += z; /* incr/decr */

  /* prevent zero (= not allowed) and -1 (= 1 original) */
  if (zoom->type == 0 || zoom->type == -1) {
    switch (z) {
      case XMDC_ZOOM_IN : zoom->type =  1; break;
      case XMDC_ZOOM_OUT: zoom->type = -2; break;
      default           : zoom->type =  1;
    }
  }

  return(zoom->type);
}

/* local routine */
static char *XMdcGetStrZoomFactor(int type)
{
  if (type < 0) {
    sprintf(xmdcstr,"[1:%d]",-type);
  }else{
    sprintf(xmdcstr,"[%d:1]",type);
  }

  return(xmdcstr);
}

/* local routine */
static void XMdcSetZoomWindowTitle(GtkWidget *window, ZoomStruct *zoom)
{
  Uint32 nr = zoom->nr + 1;
  char zoomstr[10];

  strncpy(zoomstr,XMdcGetStrZoomFactor(zoom->type),10); zoomstr[9]='\0';
  sprintf(mdcbufr,"%u %s",nr,zoomstr);
  gtk_window_set_title(GTK_WINDOW(window),mdcbufr);
}

/* local routine */
static void XMdcRemoveZoomStruct(GtkWidget *window, gpointer data)
{
  ZoomStruct *zoom = (ZoomStruct *)data;

  if (zoom != NULL) {
    if (zoom->im  != NULL) g_object_unref(zoom->im);
    if (zoom->cur != NULL) g_object_unref(zoom->cur);
    MdcFree(zoom);
  }

}

/* local routine */
static gboolean XMdcImagesZoomCallbackDraw(GtkWidget *widget,
                         GdkEventExpose *event, gpointer window)
{
  GdkWindow *zoom_window;
  GdkDrawingContext *draw_context;
  cairo_region_t *cairo_region;
  cairo_t *cr;
  ZoomStruct *zoom;

  zoom = (ZoomStruct *)g_object_get_data(G_OBJECT(window),"zoomstruct");

  zoom_window = gtk_widget_get_window(widget);

  cairo_region = cairo_region_create();

  draw_context = gdk_window_begin_draw_frame(zoom_window, cairo_region);
  cr = gdk_drawing_context_get_cairo_context(draw_context);

  gdk_cairo_set_source_pixbuf(cr, zoom->cur, 0, 0);
  cairo_paint(cr);

  gdk_window_end_draw_frame(zoom_window, draw_context);
  cairo_region_destroy(cairo_region);

  return(TRUE);

}

void XMdcImagesZoomIn(GtkWidget *window)
{
  GdkPixbuf *new;
  GdkWindow *zoom_window;
  GdkDrawingContext *draw_context;
  cairo_region_t *cairo_region;
  cairo_t *cr;
  ZoomStruct *zoom;
  int w, h, z;

  zoom = (ZoomStruct *)g_object_get_data(G_OBJECT(window),"zoomstruct");

  z = XMdcGetZoomFactor(zoom,XMDC_ZOOM_IN);

  w = gdk_pixbuf_get_width(zoom->im);
  h = gdk_pixbuf_get_height(zoom->im);

  if (z < 0) {
    w /= -z;
    h /= -z;
  }else{
    w *= z;
    h *= z;
  }

  gtk_window_set_resizable(GTK_WINDOW(window), TRUE);

  new = gdk_pixbuf_scale_simple(zoom->im,w,h,sRenderSelection.Interp);
  g_object_unref(zoom->cur); zoom->cur = new;

  gtk_widget_set_size_request(zoom->darea,w,h);

  zoom_window = gtk_widget_get_window(zoom->darea);

  cairo_region = cairo_region_create();

  draw_context = gdk_window_begin_draw_frame(zoom_window, cairo_region);
  cr = gdk_drawing_context_get_cairo_context(draw_context);

  gdk_cairo_set_source_pixbuf(cr, zoom->cur, 0, 0);
  cairo_paint(cr);

  gdk_window_end_draw_frame(zoom_window, draw_context);
  cairo_region_destroy(cairo_region);

  XMdcSetZoomWindowTitle(window,zoom);

  gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

}

void XMdcImagesZoomOut(GtkWidget *window)
{
  GdkPixbuf *new;
  GdkWindow *zoom_window;
  GdkDrawingContext *draw_context;
  cairo_region_t *cairo_region;
  cairo_t *cr;
  ZoomStruct *zoom;
  int w, h, z;

  zoom = (ZoomStruct *)g_object_get_data(G_OBJECT(window),"zoomstruct");

  z = XMdcGetZoomFactor(zoom,XMDC_ZOOM_OUT);

  w = gdk_pixbuf_get_width(zoom->im);
  h = gdk_pixbuf_get_height(zoom->im);

  if (z < 0) {
    w /= -z;
    h /= -z;
  }else{
    w *= z;
    h *= z;
  }

  gtk_window_set_resizable(GTK_WINDOW(window), TRUE);

  new = gdk_pixbuf_scale_simple(zoom->im,w,h,sRenderSelection.Interp);
  g_object_unref(zoom->cur); zoom->cur = new;

  gtk_widget_set_size_request(zoom->darea,w,h);

  zoom_window = gtk_widget_get_window(zoom->darea);

  cairo_region = cairo_region_create();

  draw_context = gdk_window_begin_draw_frame(zoom_window, cairo_region);
  cr = gdk_drawing_context_get_cairo_context(draw_context);

  gdk_cairo_set_source_pixbuf(cr, zoom->cur, 0, 0);
  cairo_paint(cr);

  gdk_window_end_draw_frame(zoom_window, draw_context);
  cairo_region_destroy(cairo_region);

  XMdcSetZoomWindowTitle(window,zoom);

  gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

}

gboolean XMdcImagesZoomCallbackClicked(GtkWidget *widget, GdkEventButton *button, GtkWidget *window)
{

  if (button->button == 3)  gtk_widget_destroy(window);

  if (button->button == 1)  XMdcImagesZoomIn(window);

  if (button->button == 2)  XMdcImagesZoomOut(window);

  return(TRUE);

}

void XMdcImagesZoom(GtkWidget *widget, Uint32 nr)
{
  GtkWidget *window;
  GtkWidget *gridbox;
  GtkWidget *darea;
  ZoomStruct *zoom=NULL;
  int w, h, z, w_zoom, h_zoom;


  /* allocate structure */
  zoom = (ZoomStruct *)malloc(sizeof(ZoomStruct));
  if (zoom == NULL) {
    XMdcDisplayErr("Couldn't allocate zoom struct");
    return;
  }else{
    zoom->nr = my.realnumber[nr];
    zoom->type = sResizeSelection.CurType;
    zoom->im = NULL; zoom->cur = NULL;
  }

  w = (int)XMdcScaleW(my.fi->image[zoom->nr].width);  w_zoom = w;
  h = (int)XMdcScaleH(my.fi->image[zoom->nr].height); h_zoom = h;

  z = XMdcGetZoomFactor(zoom,XMDC_ZOOM_NONE);

  if (z < 0) {
    w_zoom /= -z;
    h_zoom /= -z;
  }else{
    w_zoom *= z;
    h_zoom *= z;
  }

  /* initial pixmap must be original image; so no resize here */
  my.RESIZE = MDC_NO;
  zoom->im  = XMdcBuildGdkPixbufFI(my.fi,zoom->nr,sGbc.mod.vgbc);
  my.RESIZE = MDC_YES;
  zoom->cur = gdk_pixbuf_scale_simple(zoom->im,w,h,sRenderSelection.Interp);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
  gtk_container_set_border_width(GTK_CONTAINER(window),1);
  g_signal_connect(window, "destroy",
                     G_CALLBACK(XMdcRemoveZoomStruct),zoom);
  g_signal_connect(window, "destroy",
                     G_CALLBACK(gtk_widget_destroy),NULL);


  gridbox = gtk_grid_new();
  gtk_container_add(GTK_CONTAINER(window),gridbox);
  gtk_widget_show(gridbox);

  darea = gtk_drawing_area_new(); zoom->darea = darea;
  gtk_grid_attach(GTK_GRID(gridbox),darea,0,0,1,1);
  gtk_widget_show(darea);
  gtk_widget_set_events(darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
  gtk_widget_set_size_request(darea,w,h);

  g_signal_connect(darea, "button_press_event",
                     G_CALLBACK(XMdcImagesZoomCallbackClicked),
                     GTK_WIDGET(window));
  g_signal_connect(darea, "draw",
                     G_CALLBACK(XMdcImagesZoomCallbackDraw),
                     GTK_WIDGET(window));

  XMdcShowWidget(window);

  gdk_window_set_cursor (gtk_widget_get_window(window), zoomcursor);

  g_object_set_data(G_OBJECT(window),"zoomstruct",(gpointer)zoom);

  XMdcSetZoomWindowTitle(window,zoom);

  gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

}

