/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * filename: ximages.c                                                     *
 *                                                                         *
 * UTIL C-source: Medical Image Conversion Utility                         *
 *                                                                         *
 * purpose      : image routines                                           *
 *                                                                         *
 * project      : (X)MedCon by Erik Nolf                                   *
 *                                                                         *
 * Functions    : XMdcRemovePreviousImages()   - Remove old X images       *
 *                XMdcImagesSetCursor()        - Set cursor over X images  *
 *                XMdcImagesCallbackDraw()     - Images Draw callback      *
 *                XMdcImagesCallbackClicked()  - Images Clicked callback   *
 *                XMdcBuildCurrentImages()     - Build images for display  *
 *                XMdcDisplayImages()          - Display the images        *
 *                XMdcImagesView()             - Show the images (viewer)  *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
 */

/*
   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 <stdio.h>

#include "xmedcon.h"

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

void XMdcRemovePreviousImages(void)
{
  Uint32 i;

  for (i=0; i<my.real_images_on_page; i++) {
     gtk_widget_hide(my.image[i]);
     g_object_unref(my.im[i]); my.im[i] = NULL;
  }
}

void XMdcImagesSetCursor(GtkWidget *widget, gpointer data)
{
  GdkWindow *window = gtk_widget_get_window(widget);

  if (window != NULL)
    gdk_window_set_cursor (window, handcursor);
}


gboolean XMdcImagesCallbackDraw(GtkWidget *widget, GdkEventExpose *event, Uint32 *nr)
{
  GdkWindow *window;
  GdkDrawingContext *draw_context;
  cairo_region_t *cairo_region;
  cairo_t *cr;

  Uint32 i = (Uint32)(*nr);

  if ( my.im[i] == NULL ) return(TRUE);

  window = gtk_widget_get_window(widget);

  cairo_region = cairo_region_create();

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

  /* repaint the polluted cairo context */
  gdk_cairo_set_source_pixbuf(cr, my.im[i], 0, 0);
  cairo_paint(cr);

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

  /* print labels */
  if (sLabelSelection.CurState == MDC_YES) {
    XMdcPrintImageLabelIndex(widget,i);
    XMdcPrintImageLabelTimes(widget,i);
  }

  return(TRUE);
}

gboolean XMdcImagesCallbackClicked(GtkWidget *widget, GdkEventButton *button, Uint32 *nr)
{

  if (button->button == 1) {
    /* zoom the image */
    XMdcImagesZoom(widget,(Uint32)(*nr));
  }

  if (button->button == 2) {
    /* print image info */
    XMdcImagesInfo(widget,(Uint32)(*nr));
  }

  if (button->button == 3) {
    /* color correction */
    XMdcColGbcCorrectSel(widget,(Uint32)(*nr));
  }

  return(TRUE);

}

void XMdcBuildCurrentImages(void)
{
  Uint32 i, r, c, ri;
  Uint32 real_images;
  float progress;

  MdcDebugPrint("Building current images ...");

  real_images = XMdcPagesGetNrImages();

  /* get real_images_per_page and number of the beginning image */
  if (real_images < my.images_per_page) {
    /* always lesser images on page */
    my.real_images_on_page = real_images;
    my.startimage = my.curpage * real_images;
  }else{
    if (my.curpage == my.number_of_pages - 1) {
      /* last page, probably less images on it */
      my.real_images_on_page = my.fi->number - (my.curpage*my.images_per_page);
      my.startimage = my.curpage * my.images_per_page;
    }else{
      /* other pages completely filled out */
      my.real_images_on_page = my.images_per_page;
      my.startimage = my.curpage * my.images_per_page;
    }
  }

  progress = 1./(float)(my.real_images_on_page + 1);

  /* build the images */
  i = my.startimage; ri=0;
  for (r=0; r<my.images_vertical; r++)
  for (c=0; c<my.images_horizontal; c++,i++, ri++) {

     progress += 1./(float)(my.real_images_on_page + 1);

     if (ri == my.real_images_on_page) break; /* get OUT, got all images */

     my.realnumber[ri] = i;

     my.im[ri] = XMdcBuildGdkPixbufFI(my.fi,i,sGbc.mod.vgbc);

     if (my.image[ri] == NULL) {

       my.image[ri] = gtk_drawing_area_new();

       gtk_widget_set_size_request(my.image[ri]
           ,(gint)(XMdcScaleW(my.fi->mwidth)  + XMDC_IMAGE_BORDER)
           ,(gint)(XMdcScaleH(my.fi->mheight) + XMDC_IMAGE_BORDER));

       gtk_widget_set_events (my.image[ri], GDK_EXPOSURE_MASK
           | GDK_BUTTON_PRESS_MASK
#ifdef MDC_USE_SIGNAL_BLOCKER
           | GDK_ENTER_NOTIFY_MASK
           | GDK_LEAVE_NOTIFY_MASK
#endif
           );

       gtk_grid_attach(GTK_GRID(my.imgsgrid),my.image[ri],c,r,1,1);

       g_signal_connect (my.image[ri], "button_press_event",
                           G_CALLBACK(XMdcImagesCallbackClicked),
                           (Uint32 *)&my.imagenumber[ri]);

       g_signal_connect (my.image[ri], "draw",
                           G_CALLBACK(XMdcImagesCallbackDraw),
                           (Uint32 *)&my.imagenumber[ri]);

       XMdcImagesSetCursor(my.image[ri],NULL);

     }

     gtk_widget_show(my.image[ri]);


     if (gtk_widget_get_visible(my.viewwindow)) {
       if (my.images_horizontal < 10) {
         /* update after each two rows */
         if (((ri+1)%(my.images_horizontal*2)) == 0)
           XMdcProgressBar(MDC_PROGRESS_SET,progress,NULL);
       }else{
         /* update after each five rows */
         if (((ri+1)%(my.images_horizontal*5)) == 0)
           XMdcProgressBar(MDC_PROGRESS_SET,progress,NULL);
       }
     }else{
       /* update after each image */
        XMdcProgressBar(MDC_PROGRESS_SET,progress,NULL);
     }
  }
}

void XMdcSetFixedImagesGridSize(void)
{
  /* MARK: table() preserved fixed size ... grid() doesn't,
   * MARK: but needed to keep buttons on the same place */
  gint wcel, hcel, wfixed, hfixed;

  wcel = XMdcScaleW(my.fi->mwidth)  + XMDC_IMAGE_BORDER;
  wfixed = wcel * my.images_horizontal;

  hcel = XMdcScaleH(my.fi->mheight) + XMDC_IMAGE_BORDER;
  hfixed = hcel * my.images_vertical;

  gtk_widget_set_size_request(my.imgsbox, wfixed, hfixed);

}

void XMdcDisplayImages(void)
{
  XMdcProgressBar(MDC_PROGRESS_BEGIN,0.,"Preparing Viewer:");
  XMdcSetImageScales();
  XMdcGetBoardDimensions();
  XMdcHandleBoardDimensions();
  XMdcBuildViewerWindow();
  XMdcBuildColorMap();
  XMdcBuildCurrentImages();
  XMdcResizeNeeded();
  XMdcSetFixedImagesGridSize();
}

void XMdcImagesView(GtkWidget *widget, gpointer data)
{
  if (XMdcNoFileOpened()) return;
  XMdcViewerShow();
}

