/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 * * XMdcImagesCallbackExpose() - Images Expose callback * * XMdcImagesCallbackClicked() - Images Clicked callback * * XMdcBuildCurrentImages() - Build images for display * * XMdcDisplayImages() - Display the images * * XMdcImagesView() - Show the images (viewer) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* $Id: ximages.c,v 1.23 2007/05/21 20:16:17 enlf Exp $ */ /* Copyright (C) 1997-2007 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 #include "xmedcon.h" /**************************************************************************** F U N C T I O N S ****************************************************************************/ #ifdef MDC_USE_SIGNAL_BLOCKER /* * MARK: dirty fix of bad button-press-event behaviour in _WIN32 * * The button-press-events of our image's drawing areas seems to be * "propagated" over all our widgets ... We got for example zoom or info * windows by clicking on places we wouldn't expect this to happen. * * So we 're blocking this button-press-event whenever we leave the * corresponding drawing area (and ofcourse, reallowing when entering) * * However, the gtk_signal_handler_block() function increments a number * instead of using a simple boolean. Whenever the "enter_notify_event" * is missed ... this number will never drop to zero again. And it does * happen when widgets come in front of our drawing areas which are rebuild * because of a color correction or colormap change. * * Our SignalBlocker struct should prevent the gtk_signal_handler_block() * function being called several times ... * * Actual struct defined in xdefs.h: typedef struct SignalBlocker_t{ guint id; gboolean blocked; }SignalBlocker; * */ static gboolean XMdcSignalBlock(GtkWidget *widget, gpointer data) { SignalBlocker *signal; signal = (SignalBlocker *)gtk_object_get_data(GTK_OBJECT(widget),"signal"); if (!signal->blocked) { gtk_signal_handler_block(GTK_OBJECT(widget),signal->id); signal->blocked = TRUE; } return(TRUE); } static gboolean XMdcSignalUnblock(GtkWidget *widget, gpointer data) { SignalBlocker *signal; signal = (SignalBlocker *)gtk_object_get_data(GTK_OBJECT(widget),"signal"); if (signal->blocked) { gtk_signal_handler_unblock(GTK_OBJECT(widget),signal->id); signal->blocked = FALSE; } return(TRUE); } #endif void XMdcRemovePreviousImages(void) { Uint32 i; for (i=0; iwindow != NULL) gdk_window_set_cursor (widget->window, handcursor); } gboolean XMdcImagesCallbackExpose(GtkWidget *widget, GdkEventExpose *event, Uint32 *nr) { GdkGC *gc = widget->style->white_gc; Uint32 i = (Uint32)(*nr); gint ex, ey, ew, eh, iw, ih, rw, rh; if ( my.im[i] == NULL ) return(TRUE); /* repaint the polluted drawable */ iw = gdk_pixbuf_get_width(my.im[i]); ih = gdk_pixbuf_get_height(my.im[i]); ex = event->area.x; ey = event->area.y; ew = event->area.width; eh = event->area.height; if ((ex < iw) && (ey < ih)) { rw = iw - ex; rh = ih - ey; gdk_pixbuf_render_to_drawable(my.im[i], widget->window, gc, ex, ey, ex, ey, rw, rh, sRenderSelection.Dither, 0, 0); } if ((ex + ew) > iw) { rw = (ex + ew) - iw; rh = eh; gdk_window_clear_area(widget->window, iw, ey, rw, rh); } if ((ey + eh) > ih) { rh = (ey + eh) - ih; rw = ew; gdk_window_clear_area(widget->window, ex, ih, rw, rh); } 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; rmwidth) + 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_table_attach(GTK_TABLE(my.imgstable),my.image[ri],c,c+1,r,r+1, GTK_FILL,GTK_FILL, 0, 0); #ifdef MDC_USE_SIGNAL_BLOCKER signal->id = #endif gtk_signal_connect (GTK_OBJECT(my.image[ri]), "button_press_event", GTK_SIGNAL_FUNC(XMdcImagesCallbackClicked), (Uint32 *)&my.imagenumber[ri]); gtk_signal_connect (GTK_OBJECT(my.image[ri]),"expose_event", GTK_SIGNAL_FUNC(XMdcImagesCallbackExpose), (Uint32 *)&my.imagenumber[ri]); #ifdef MDC_USE_SIGNAL_BLOCKER gtk_signal_connect (GTK_OBJECT(my.image[ri]),"enter_notify_event", GTK_SIGNAL_FUNC(XMdcSignalUnblock), NULL); gtk_signal_connect (GTK_OBJECT(my.image[ri]),"leave_notify_event", GTK_SIGNAL_FUNC(XMdcSignalBlock), NULL); gtk_object_set_data(GTK_OBJECT(my.image[ri]),"signal",signal); XMdcSignalBlock(my.image[ri],NULL); #endif XMdcImagesSetCursor(my.image[ri],NULL); } gtk_widget_show(my.image[ri]); if (GTK_WIDGET_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 XMdcDisplayImages(void) { XMdcProgressBar(MDC_PROGRESS_BEGIN,0.,"Preparing Viewer:"); XMdcSetImageScales(); XMdcGetBoardDimensions(); XMdcHandleBoardDimensions(); XMdcBuildViewerWindow(); XMdcBuildColorMap(); XMdcBuildCurrentImages(); XMdcResizeNeeded(); gtk_container_foreach(GTK_CONTAINER(my.imgstable), (GtkCallback)XMdcImagesSetCursor,NULL); } void XMdcImagesView(GtkWidget *widget, gpointer data) { if (XMdcNoFileOpened()) return; XMdcViewerShow(); }