gimpdisplay-ops.c 7.93 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* 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
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
17
 */
Sven Neumann's avatar
Sven Neumann committed
18

19
#include "config.h"
Michael Natterer's avatar
Michael Natterer committed
20

Sven Neumann's avatar
Sven Neumann committed
21 22
#include <gtk/gtk.h>

23 24
#include "libgimpwidgets/gimpwidgets.h"

Michael Natterer's avatar
Michael Natterer committed
25
#include "core/core-types.h"
Sven Neumann's avatar
Sven Neumann committed
26

27
#include "core/gimp.h"
28 29
#include "core/gimpimage.h"

Elliot Lee's avatar
Elliot Lee committed
30 31 32 33
#include "colormaps.h"
#include "gdisplay_ops.h"
#include "gimprc.h"

34
#include "libgimp/gimpintl.h"
Elliot Lee's avatar
Elliot Lee committed
35

36

37 38 39 40 41
static void gdisplay_close_warning_callback  (GtkWidget   *widget,
					      gboolean     close,
					      gpointer     data);
static void gdisplay_close_warning_dialog    (const gchar *image_name,
					      GDisplay    *gdisp);
Elliot Lee's avatar
Elliot Lee committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

/*
 *  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;
}


72
void
73 74
gdisplay_xserver_resolution (gdouble *xres,
			     gdouble *yres)
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
{
  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
   */

95 96
  *xres = (width  * 25.4) / ((gdouble) widthMM);
  *yres = (height * 25.4) / ((gdouble) heightMM);
97 98 99
}


Elliot Lee's avatar
Elliot Lee committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
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,
Michael Natterer's avatar
Michael Natterer committed
115
		       gboolean  kill_it)
Elliot Lee's avatar
Elliot Lee committed
116
{
117 118 119
  /*  FIXME: gimp_busy HACK not really appropriate here because we only
   *  want to prevent the busy image and display to be closed.  --Mitch
   */
120
  if (gdisp->gimage->gimp->busy)
121 122
    return;

Elliot Lee's avatar
Elliot Lee committed
123 124
  /*  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
125
   *  to an image canvas.  (a gimage with disp_count = 1)
Elliot Lee's avatar
Elliot Lee committed
126
   */
Michael Natterer's avatar
Michael Natterer committed
127 128 129
  if (! kill_it &&
      (gdisp->gimage->disp_count == 1) &&
      gdisp->gimage->dirty &&
130
      gimprc.confirm_on_close)
131 132
    {
      gdisplay_close_warning_dialog
133
	(g_basename (gimp_image_filename (gdisp->gimage)), gdisp);
134
    }
Elliot Lee's avatar
Elliot Lee committed
135 136 137 138 139 140 141 142 143 144
  else
    {
      gtk_widget_destroy (gdisp->shell);
    }
}


void
gdisplay_shrink_wrap (GDisplay *gdisp)
{
145
  /* 
146 147
   * I'm pretty sure this assumes that the current size is < display size
   * Is this a valid assumption? 
148
   */
Michael Natterer's avatar
Michael Natterer committed
149
  GtkAllocation allocation;
Elliot Lee's avatar
Elliot Lee committed
150 151
  gint disp_width, disp_height;
  gint width, height;
152
  gint shell_x, shell_y;
Elliot Lee's avatar
Elliot Lee committed
153 154 155
  gint shell_width, shell_height;
  gint max_auto_width, max_auto_height;
  gint border_x, border_y;
Michael Natterer's avatar
Michael Natterer committed
156
  gint s_width, s_height;
Elliot Lee's avatar
Elliot Lee committed
157

158 159
  gboolean resize = FALSE;

Michael Natterer's avatar
Michael Natterer committed
160
  s_width  = gdk_screen_width ();
Elliot Lee's avatar
Elliot Lee committed
161 162
  s_height = gdk_screen_height ();

Michael Natterer's avatar
Michael Natterer committed
163
  width  = SCALEX (gdisp, gdisp->gimage->width);
164
  height = SCALEY (gdisp, gdisp->gimage->height);
Elliot Lee's avatar
Elliot Lee committed
165

Michael Natterer's avatar
Michael Natterer committed
166
  disp_width  = gdisp->disp_width;
Elliot Lee's avatar
Elliot Lee committed
167 168
  disp_height = gdisp->disp_height;

Michael Natterer's avatar
Michael Natterer committed
169
  shell_width  = gdisp->shell->allocation.width;
Elliot Lee's avatar
Elliot Lee committed
170 171
  shell_height = gdisp->shell->allocation.height;

Michael Natterer's avatar
Michael Natterer committed
172
  border_x = shell_width  - disp_width;
Elliot Lee's avatar
Elliot Lee committed
173 174
  border_y = shell_height - disp_height;

Michael Natterer's avatar
Michael Natterer committed
175
  max_auto_width  = (s_width  - border_x) * 0.75;
Elliot Lee's avatar
Elliot Lee committed
176 177
  max_auto_height = (s_height - border_y) * 0.75;

Michael Natterer's avatar
Michael Natterer committed
178 179 180
  allocation.x = 0;
  allocation.y = 0;

181 182
  /* If one of the display dimensions has changed and one of the
   * dimensions fits inside the screen
Elliot Lee's avatar
Elliot Lee committed
183 184 185 186
   */
  if (((width + border_x) < s_width || (height + border_y) < s_height) &&
      (width != disp_width || height != disp_height))
    {
Michael Natterer's avatar
Michael Natterer committed
187
      width  = ((width  + border_x) < s_width)  ? width  : max_auto_width;
Elliot Lee's avatar
Elliot Lee committed
188 189
      height = ((height + border_y) < s_height) ? height : max_auto_height;

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
      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)
    {
206 207 208 209
      if (width < gdisp->statusarea->requisition.width) 
        { 
          width = gdisp->statusarea->requisition.width; 
        }
210

211 212
#undef RESIZE_DEBUG
#ifdef RESIZE_DEBUG
Michael Natterer's avatar
Michael Natterer committed
213 214 215 216 217
      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);
218
#endif /* RESIZE_DEBUG */
Elliot Lee's avatar
Elliot Lee committed
219

220
      gdisp->disp_width  = width;
Elliot Lee's avatar
Elliot Lee committed
221
      gdisp->disp_height = height;
Michael Natterer's avatar
Michael Natterer committed
222 223 224 225

      allocation.width  = width  + border_x;
      allocation.height = height + border_y;

226 227 228 229 230
      /*  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);

Michael Natterer's avatar
Michael Natterer committed
231 232 233 234 235
      gtk_widget_size_allocate (gdisp->shell, &allocation);

      gdk_window_resize (gdisp->shell->window,
			 allocation.width,
			 allocation.height);
236

237 238 239
      /*  let Gtk/X/WM position the window  */
      while (gtk_events_pending ())
	gtk_main_iteration ();
Elliot Lee's avatar
Elliot Lee committed
240

241
      gdk_window_get_origin (gdisp->shell->window, &shell_x, &shell_y);
242

243 244 245 246 247 248
      /*  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;
249

250 251
	  gdk_window_move (gdisp->shell->window, shell_x, shell_y);
	}
252

253
      gtk_signal_handler_unblock_by_data (GTK_OBJECT (gdisp->canvas), gdisp);
254 255
    }

Elliot Lee's avatar
Elliot Lee committed
256 257 258
  /*  If the width or height of the display has changed, recalculate
   *  the display offsets...
   */
Michael Natterer's avatar
Michael Natterer committed
259
  if (disp_width  != gdisp->disp_width ||
Elliot Lee's avatar
Elliot Lee committed
260 261
      disp_height != gdisp->disp_height)
    {
Michael Natterer's avatar
Michael Natterer committed
262
      gdisp->offset_x += (disp_width  - gdisp->disp_width) / 2;
Elliot Lee's avatar
Elliot Lee committed
263 264 265 266 267 268 269 270 271
      gdisp->offset_y += (disp_height - gdisp->disp_height) / 2;
    }
}

/********************************************************
 *   Routines to query before closing a dirty image     *
 ********************************************************/

static void
272
gdisplay_close_warning_callback (GtkWidget *widget,
Michael Natterer's avatar
Michael Natterer committed
273 274
				 gboolean   close,
				 gpointer   data)
Elliot Lee's avatar
Elliot Lee committed
275 276 277
{
  GDisplay *gdisp;

Michael Natterer's avatar
Michael Natterer committed
278
  gdisp = (GDisplay *) data;
Elliot Lee's avatar
Elliot Lee committed
279

280
  gdisp->warning_dialog = NULL;
Elliot Lee's avatar
Elliot Lee committed
281

Michael Natterer's avatar
Michael Natterer committed
282 283
  if (close)
    gtk_widget_destroy (gdisp->shell);
Elliot Lee's avatar
Elliot Lee committed
284 285 286
}

static void
287 288
gdisplay_close_warning_dialog (const gchar *image_name,
			       GDisplay    *gdisp)
Elliot Lee's avatar
Elliot Lee committed
289
{
290
  GtkWidget *mbox;
Michael Natterer's avatar
Michael Natterer committed
291
  gchar     *warning_buf;
292

293
  if (gdisp->warning_dialog != NULL)
Elliot Lee's avatar
Elliot Lee committed
294
    {
295
      gdk_window_raise (gdisp->warning_dialog->window);
Elliot Lee's avatar
Elliot Lee committed
296 297 298
      return;
    }

Michael Natterer's avatar
Michael Natterer committed
299 300
  warning_buf =
    g_strdup_printf (_("Changes were made to %s.\nClose anyway?"), image_name);
301

302
  gdisp->warning_dialog = mbox =
Michael Natterer's avatar
Michael Natterer committed
303 304 305
    gimp_query_boolean_box (image_name,
			    gimp_standard_help_func,
			    "dialogs/really_close.html",
306
			    FALSE,
Michael Natterer's avatar
Michael Natterer committed
307 308 309 310 311
			    warning_buf,
			    _("Close"), _("Cancel"),
			    NULL, NULL,
			    gdisplay_close_warning_callback,
			    gdisp);
312

Michael Natterer's avatar
Michael Natterer committed
313
  g_free (warning_buf);
Elliot Lee's avatar
Elliot Lee committed
314 315 316

  gtk_widget_show (mbox);
}