/* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * 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. */ #include "config.h" #include #include "libgimpwidgets/gimpwidgets.h" #include "apptypes.h" #include "colormaps.h" #include "cursorutil.h" #include "gdisplay_ops.h" #include "gimpimage.h" #include "gimprc.h" #include "libgimp/gimpintl.h" static void gdisplay_close_warning_callback (GtkWidget *widget, gboolean close, gpointer data); static void gdisplay_close_warning_dialog (gchar *image_name, GDisplay *gdisp); /* * This file is for operations on the gdisplay object */ gulong gdisplay_white_pixel (GDisplay *gdisp) { return g_white_pixel; } gulong gdisplay_gray_pixel (GDisplay *gdisp) { return g_gray_pixel; } gulong gdisplay_black_pixel (GDisplay *gdisp) { return g_black_pixel; } gulong gdisplay_color_pixel (GDisplay *gdisp) { return g_color_pixel; } void gdisplay_xserver_resolution (gdouble *xres, gdouble *yres) { gint width, height; gint widthMM, heightMM; width = gdk_screen_width (); height = gdk_screen_height (); widthMM = gdk_screen_width_mm (); heightMM = gdk_screen_height_mm (); /* * From xdpyinfo.c: * * there are 2.54 centimeters to an inch; so there are 25.4 millimeters. * * dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch)) * = N pixels / (M inch / 25.4) * = N * 25.4 pixels / M inch */ *xres = (width * 25.4) / ((gdouble) widthMM); *yres = (height * 25.4) / ((gdouble) heightMM); } void gdisplay_new_view (GDisplay *gdisp) { GDisplay *new_gdisp; /* make sure the image has been fully loaded... */ if (gdisp->gimage) { new_gdisp = gdisplay_new (gdisp->gimage, gdisp->scale); } } void gdisplay_close_window (GDisplay *gdisp, gboolean kill_it) { /* FIXME: gimp_busy HACK not really appropriate here because we only * want to prevent the busy image and display to be closed. --Mitch */ if (gimp_busy) return; /* If the image has been modified, give the user a chance to save * it before nuking it--this only applies if its the last view * to an image canvas. (a gimage with disp_count = 1) */ if (! kill_it && (gdisp->gimage->disp_count == 1) && gdisp->gimage->dirty && confirm_on_close) { gdisplay_close_warning_dialog (g_basename (gimp_image_filename (gdisp->gimage)), gdisp); } else { gtk_widget_destroy (gdisp->shell); } } void gdisplay_shrink_wrap (GDisplay *gdisp) { /* * I'm pretty sure this assumes that the current size is < display size * Is this a valid assumption? */ GtkAllocation allocation; gint disp_width, disp_height; gint width, height; gint shell_x, shell_y; gint shell_width, shell_height; gint max_auto_width, max_auto_height; gint border_x, border_y; gint s_width, s_height; gboolean resize = FALSE; s_width = gdk_screen_width (); s_height = gdk_screen_height (); width = SCALEX (gdisp, gdisp->gimage->width); height = SCALEY (gdisp, gdisp->gimage->height); disp_width = gdisp->disp_width; disp_height = gdisp->disp_height; shell_width = gdisp->shell->allocation.width; shell_height = gdisp->shell->allocation.height; border_x = shell_width - disp_width; border_y = shell_height - disp_height; max_auto_width = (s_width - border_x) * 0.75; max_auto_height = (s_height - border_y) * 0.75; allocation.x = 0; allocation.y = 0; /* If one of the display dimensions has changed and one of the * dimensions fits inside the screen */ if (((width + border_x) < s_width || (height + border_y) < s_height) && (width != disp_width || height != disp_height)) { width = ((width + border_x) < s_width) ? width : max_auto_width; height = ((height + border_y) < s_height) ? height : max_auto_height; resize = TRUE; } /* If the projected dimension is greater than current, but less than * 3/4 of the screen size, expand automagically */ else if ((width > disp_width || height > disp_height) && (disp_width < max_auto_width || disp_height < max_auto_height)) { width = MIN (max_auto_width, width); height = MIN (max_auto_height, height); resize = TRUE; } if (resize) { if (width < gdisp->statusarea->requisition.width) { width = gdisp->statusarea->requisition.width; } #undef RESIZE_DEBUG #ifdef RESIZE_DEBUG g_print ("1w:%d/%d d:%d/%d s:%d/%d b:%d/%d\n", width, height, disp_width, disp_height, shell_width, shell_height, border_x, border_y); #endif /* RESIZE_DEBUG */ gdisp->disp_width = width; gdisp->disp_height = height; allocation.width = width + border_x; allocation.height = height + border_y; /* don't call gdisplay_canvas_events() on any of the following * changes because our caller has to do a full display update anyway */ gtk_signal_handler_block_by_data (GTK_OBJECT (gdisp->canvas), gdisp); gtk_widget_size_allocate (gdisp->shell, &allocation); gdk_window_resize (gdisp->shell->window, allocation.width, allocation.height); /* let Gtk/X/WM position the window */ while (gtk_events_pending ()) gtk_main_iteration (); gdk_window_get_origin (gdisp->shell->window, &shell_x, &shell_y); /* if the window is offscreen, center it... */ if (shell_x > s_width || shell_y > s_height || (shell_x + width + border_x) < 0 || (shell_y + height + border_y) < 0) { shell_x = (s_width - width - border_x) >> 1; shell_y = (s_height - height - border_y) >> 1; gdk_window_move (gdisp->shell->window, shell_x, shell_y); } gtk_signal_handler_unblock_by_data (GTK_OBJECT (gdisp->canvas), gdisp); } /* If the width or height of the display has changed, recalculate * the display offsets... */ if (disp_width != gdisp->disp_width || disp_height != gdisp->disp_height) { gdisp->offset_x += (disp_width - gdisp->disp_width) / 2; gdisp->offset_y += (disp_height - gdisp->disp_height) / 2; } } /******************************************************** * Routines to query before closing a dirty image * ********************************************************/ static void gdisplay_close_warning_callback (GtkWidget *widget, gboolean close, gpointer data) { GDisplay *gdisp; gdisp = (GDisplay *) data; gdisp->warning_dialog = NULL; if (close) gtk_widget_destroy (gdisp->shell); } static void gdisplay_close_warning_dialog (gchar *image_name, GDisplay *gdisp) { GtkWidget *mbox; gchar *warning_buf; if (gdisp->warning_dialog != NULL) { gdk_window_raise (gdisp->warning_dialog->window); return; } warning_buf = g_strdup_printf (_("Changes were made to %s.\nClose anyway?"), image_name); gdisp->warning_dialog = mbox = gimp_query_boolean_box (image_name, gimp_standard_help_func, "dialogs/really_close.html", FALSE, warning_buf, _("Close"), _("Cancel"), NULL, NULL, gdisplay_close_warning_callback, gdisp); g_free (warning_buf); gtk_widget_show (mbox); }