gtkstatusbar.c 19 KB
Newer Older
1 2 3 4 5
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 * GtkStatusbar Copyright (C) 1998 Shawn T. Amundson
 *
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7 8 9 10 11 12
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16 17 18
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
19 20
 */

21
/*
22
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23 24 25 26 27
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

28 29
#include "gtkframe.h"
#include "gtklabel.h"
30
#include "gtkmarshalers.h"
31
#include "gtkstatusbar.h"
Owen Taylor's avatar
Owen Taylor committed
32
#include "gtkwindow.h"
33
#include "gtkintl.h"
34

35 36 37 38 39 40 41 42
typedef struct _GtkStatusbarMsg GtkStatusbarMsg;

struct _GtkStatusbarMsg
{
  gchar *text;
  guint context_id;
  guint message_id;
};
43 44 45 46 47 48 49 50

enum
{
  SIGNAL_TEXT_PUSHED,
  SIGNAL_TEXT_POPPED,
  SIGNAL_LAST
};

Owen Taylor's avatar
Owen Taylor committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
static void     gtk_statusbar_class_init     (GtkStatusbarClass *class);
static void     gtk_statusbar_init           (GtkStatusbar      *statusbar);
static void     gtk_statusbar_destroy        (GtkObject         *object);
static void     gtk_statusbar_update         (GtkStatusbar      *statusbar,
					      guint              context_id,
					      const gchar       *text);
static void     gtk_statusbar_size_allocate  (GtkWidget         *widget,
					      GtkAllocation     *allocation);
static void     gtk_statusbar_realize        (GtkWidget         *widget);
static void     gtk_statusbar_unrealize      (GtkWidget         *widget);
static void     gtk_statusbar_map            (GtkWidget         *widget);
static void     gtk_statusbar_unmap          (GtkWidget         *widget);
static gboolean gtk_statusbar_button_press   (GtkWidget         *widget,
					      GdkEventButton    *event);
static gboolean gtk_statusbar_expose_event   (GtkWidget         *widget,
					      GdkEventExpose    *event);
67 68 69 70
static void     gtk_statusbar_size_request   (GtkWidget         *widget,
                                              GtkRequisition    *requisition);
static void     gtk_statusbar_size_allocate  (GtkWidget         *widget,
                                              GtkAllocation     *allocation);
Owen Taylor's avatar
Owen Taylor committed
71 72 73
static void     gtk_statusbar_create_window  (GtkStatusbar      *statusbar);
static void     gtk_statusbar_destroy_window (GtkStatusbar      *statusbar);

74
static GtkContainerClass *parent_class;
75
static guint              statusbar_signals[SIGNAL_LAST] = { 0 };
76

Manish Singh's avatar
Manish Singh committed
77
GType      
78
gtk_statusbar_get_type (void)
79
{
Manish Singh's avatar
Manish Singh committed
80
  static GType statusbar_type = 0;
81 82 83

  if (!statusbar_type)
    {
Manish Singh's avatar
Manish Singh committed
84
      static const GTypeInfo statusbar_info =
85 86
      {
        sizeof (GtkStatusbarClass),
Manish Singh's avatar
Manish Singh committed
87 88 89 90 91 92 93 94
	NULL,		/* base_init */
	NULL,		/* base_finalize */
        (GClassInitFunc) gtk_statusbar_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
        sizeof (GtkStatusbar),
	0,		/* n_preallocs */
        (GInstanceInitFunc) gtk_statusbar_init,
95 96
      };

97
      statusbar_type = g_type_register_static (GTK_TYPE_HBOX, "GtkStatusbar",
Manish Singh's avatar
Manish Singh committed
98
					       &statusbar_info, 0);
99 100 101
    }

  return statusbar_type;
102
}
103 104 105 106 107 108 109 110 111 112 113 114

static void
gtk_statusbar_class_init (GtkStatusbarClass *class)
{
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;

  object_class = (GtkObjectClass *) class;
  widget_class = (GtkWidgetClass *) class;
  container_class = (GtkContainerClass *) class;

Manish Singh's avatar
Manish Singh committed
115
  parent_class = g_type_class_peek_parent (class);
116 117 118
  
  object_class->destroy = gtk_statusbar_destroy;

Owen Taylor's avatar
Owen Taylor committed
119 120 121 122 123 124 125
  widget_class->realize = gtk_statusbar_realize;
  widget_class->unrealize = gtk_statusbar_unrealize;
  widget_class->map = gtk_statusbar_map;
  widget_class->unmap = gtk_statusbar_unmap;
  
  widget_class->button_press_event = gtk_statusbar_button_press;
  widget_class->expose_event = gtk_statusbar_expose_event;
126 127 128

  widget_class->size_request = gtk_statusbar_size_request;
  widget_class->size_allocate = gtk_statusbar_size_allocate;
Owen Taylor's avatar
Owen Taylor committed
129
  
130
  class->messages_mem_chunk = g_mem_chunk_new ("GtkStatusbar messages mem chunk",
131 132 133 134 135 136
					       sizeof (GtkStatusbarMsg),
					       sizeof (GtkStatusbarMsg) * 64,
					       G_ALLOC_AND_FREE);

  class->text_pushed = gtk_statusbar_update;
  class->text_popped = gtk_statusbar_update;
Owen Taylor's avatar
Owen Taylor committed
137
  
138
  statusbar_signals[SIGNAL_TEXT_PUSHED] =
Manish Singh's avatar
Manish Singh committed
139 140 141 142 143 144 145 146 147
    g_signal_new ("text_pushed",
		  G_OBJECT_CLASS_TYPE (class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkStatusbarClass, text_pushed),
		  NULL, NULL,
		  _gtk_marshal_VOID__UINT_STRING,
		  G_TYPE_NONE, 2,
		  G_TYPE_UINT,
		  G_TYPE_STRING);
148
  statusbar_signals[SIGNAL_TEXT_POPPED] =
Manish Singh's avatar
Manish Singh committed
149 150 151 152 153 154 155 156 157
    g_signal_new ("text_popped",
		  G_OBJECT_CLASS_TYPE (class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkStatusbarClass, text_popped),
		  NULL, NULL,
		  _gtk_marshal_VOID__UINT_STRING,
		  G_TYPE_NONE, 2,
		  G_TYPE_UINT,
		  G_TYPE_STRING);
158 159 160 161 162 163 164 165

  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_enum ("shadow_type",
                                                              _("Shadow type"),
                                                              _("Style of bevel around the statusbar text"),
                                                              GTK_TYPE_SHADOW_TYPE,
                                                              GTK_SHADOW_IN,
                                                              G_PARAM_READABLE));
166 167 168 169 170
}

static void
gtk_statusbar_init (GtkStatusbar *statusbar)
{
171
  GtkBox *box;
172 173
  GtkShadowType shadow_type;
  
174 175 176 177
  box = GTK_BOX (statusbar);

  box->spacing = 2;
  box->homogeneous = FALSE;
178

Owen Taylor's avatar
Owen Taylor committed
179
  statusbar->has_resize_grip = TRUE;
180 181

  gtk_widget_style_get (GTK_WIDGET (statusbar), "shadow_type", &shadow_type, NULL);
Owen Taylor's avatar
Owen Taylor committed
182
  
183
  statusbar->frame = gtk_frame_new (NULL);
184
  gtk_frame_set_shadow_type (GTK_FRAME (statusbar->frame), shadow_type);
185
  gtk_box_pack_start (box, statusbar->frame, TRUE, TRUE, 0);
186
  gtk_widget_show (statusbar->frame);
187

188 189
  statusbar->label = gtk_label_new ("");
  gtk_misc_set_alignment (GTK_MISC (statusbar->label), 0.0, 0.0);
190 191 192
  /* don't expand the size request for the label; if we
   * do that then toplevels weirdly resize
   */
Manish Singh's avatar
Manish Singh committed
193
  gtk_widget_set_size_request (statusbar->label, 1, -1);
194
  gtk_container_add (GTK_CONTAINER (statusbar->frame), statusbar->label);
195
  gtk_widget_show (statusbar->label);
196

197 198
  statusbar->seq_context_id = 1;
  statusbar->seq_message_id = 1;
199
  statusbar->messages = NULL;
200
  statusbar->keys = NULL;
201 202 203
}

GtkWidget* 
204
gtk_statusbar_new (void)
205
{
Manish Singh's avatar
Manish Singh committed
206
  return g_object_new (GTK_TYPE_STATUSBAR, NULL);
207 208 209 210
}

static void
gtk_statusbar_update (GtkStatusbar *statusbar,
211
		      guint	    context_id,
212 213 214
		      const gchar  *text)
{
  g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
215

216 217
  if (!text)
    text = "";
218

219
  gtk_label_set_text (GTK_LABEL (statusbar->label), text);
220 221
}

222 223 224 225 226 227 228 229 230 231 232 233 234
guint
gtk_statusbar_get_context_id (GtkStatusbar *statusbar,
			      const gchar  *context_description)
{
  gchar *string;
  guint *id;
  
  g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), 0);
  g_return_val_if_fail (context_description != NULL, 0);

  /* we need to preserve namespaces on object datas */
  string = g_strconcat ("gtk-status-bar-context:", context_description, NULL);

Manish Singh's avatar
Manish Singh committed
235
  id = g_object_get_data (G_OBJECT (statusbar), string);
236 237 238 239
  if (!id)
    {
      id = g_new (guint, 1);
      *id = statusbar->seq_context_id++;
Manish Singh's avatar
Manish Singh committed
240
      g_object_set_data_full (G_OBJECT (statusbar), string, id, g_free);
241 242 243 244 245 246 247 248
      statusbar->keys = g_slist_prepend (statusbar->keys, string);
    }
  else
    g_free (string);

  return *id;
}

249 250
guint
gtk_statusbar_push (GtkStatusbar *statusbar,
251
		    guint	  context_id,
252
		    const gchar  *text)
253 254
{
  GtkStatusbarMsg *msg;
255 256 257 258
  GtkStatusbarClass *class;

  g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), 0);
  g_return_val_if_fail (text != NULL, 0);
259

260
  class = GTK_STATUSBAR_GET_CLASS (statusbar);
261 262
  msg = g_chunk_new (GtkStatusbarMsg, class->messages_mem_chunk);
  msg->text = g_strdup (text);
263 264
  msg->context_id = context_id;
  msg->message_id = statusbar->seq_message_id++;
265

266
  statusbar->messages = g_slist_prepend (statusbar->messages, msg);
267

Manish Singh's avatar
Manish Singh committed
268 269 270 271 272
  g_signal_emit (statusbar,
		 statusbar_signals[SIGNAL_TEXT_PUSHED],
		 0,
		 msg->context_id,
		 msg->text);
273

274
  return msg->message_id;
275 276
}

277
void
278 279
gtk_statusbar_pop (GtkStatusbar *statusbar,
		   guint	 context_id)
280
{
281
  GtkStatusbarMsg *msg;
282

283
  g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
284

285 286
  if (statusbar->messages)
    {
287
      GSList *list;
288 289 290 291 292 293 294 295 296

      for (list = statusbar->messages; list; list = list->next)
	{
	  msg = list->data;

	  if (msg->context_id == context_id)
	    {
	      GtkStatusbarClass *class;

297
	      class = GTK_STATUSBAR_GET_CLASS (statusbar);
298 299 300 301 302 303 304 305 306

	      statusbar->messages = g_slist_remove_link (statusbar->messages,
							 list);
	      g_free (msg->text);
	      g_mem_chunk_free (class->messages_mem_chunk, msg);
	      g_slist_free_1 (list);
	      break;
	    }
	}
307 308 309
    }

  msg = statusbar->messages ? statusbar->messages->data : NULL;
310

Manish Singh's avatar
Manish Singh committed
311 312 313 314 315
  g_signal_emit (statusbar,
		 statusbar_signals[SIGNAL_TEXT_POPPED],
		 0,
		 (guint) (msg ? msg->context_id : 0),
		 msg ? msg->text : NULL);
316 317 318
}

void
319 320 321
gtk_statusbar_remove (GtkStatusbar *statusbar,
		      guint	   context_id,
		      guint        message_id)
322
{
323
  GtkStatusbarMsg *msg;
324

325
  g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
326
  g_return_if_fail (message_id > 0);
327

328 329 330
  msg = statusbar->messages ? statusbar->messages->data : NULL;
  if (msg)
    {
331 332 333 334 335
      GSList *list;

      /* care about signal emission if the topmost item is removed */
      if (msg->context_id == context_id &&
	  msg->message_id == message_id)
336
	{
337
	  gtk_statusbar_pop (statusbar, context_id);
338 339 340 341 342 343 344
	  return;
	}
      
      for (list = statusbar->messages; list; list = list->next)
	{
	  msg = list->data;
	  
345 346
	  if (msg->context_id == context_id &&
	      msg->message_id == message_id)
347 348 349
	    {
	      GtkStatusbarClass *class;
	      
350
	      class = GTK_STATUSBAR_GET_CLASS (statusbar);
351
	      statusbar->messages = g_slist_remove_link (statusbar->messages, list);
352 353
	      g_free (msg->text);
	      g_mem_chunk_free (class->messages_mem_chunk, msg);
354
	      g_slist_free_1 (list);
355 356 357 358
	      
	      break;
	    }
	}
359 360 361
    }
}

Owen Taylor's avatar
Owen Taylor committed
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
void
gtk_statusbar_set_has_resize_grip (GtkStatusbar *statusbar,
				   gboolean      setting)
{
  g_return_if_fail (GTK_IS_STATUSBAR (statusbar));

  setting = setting != FALSE;

  if (setting != statusbar->has_resize_grip)
    {
      statusbar->has_resize_grip = setting;
      gtk_widget_queue_draw (GTK_WIDGET (statusbar));

      if (GTK_WIDGET_REALIZED (statusbar))
        {
          if (statusbar->has_resize_grip && statusbar->grip_window == NULL)
            gtk_statusbar_create_window (statusbar);
          else if (!statusbar->has_resize_grip && statusbar->grip_window != NULL)
            gtk_statusbar_destroy_window (statusbar);
        }
    }
}

gboolean
gtk_statusbar_get_has_resize_grip (GtkStatusbar *statusbar)
{
  g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), FALSE);

  return statusbar->has_resize_grip;
}

393 394 395 396
static void
gtk_statusbar_destroy (GtkObject *object)
{
  GtkStatusbar *statusbar;
397
  GtkStatusbarClass *class;
398
  GSList *list;
399

400 401 402
  g_return_if_fail (GTK_IS_STATUSBAR (object));

  statusbar = GTK_STATUSBAR (object);
403
  class = GTK_STATUSBAR_GET_CLASS (statusbar);
404 405 406 407 408 409 410 411 412

  for (list = statusbar->messages; list; list = list->next)
    {
      GtkStatusbarMsg *msg;

      msg = list->data;
      g_free (msg->text);
      g_mem_chunk_free (class->messages_mem_chunk, msg);
    }
413
  g_slist_free (statusbar->messages);
414
  statusbar->messages = NULL;
415

416 417 418 419 420
  for (list = statusbar->keys; list; list = list->next)
    g_free (list->data);
  g_slist_free (statusbar->keys);
  statusbar->keys = NULL;

421 422
  GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
Owen Taylor's avatar
Owen Taylor committed
423

424 425 426 427 428 429 430 431 432 433 434
static GdkWindowEdge
get_grip_edge (GtkStatusbar *statusbar)
{
  GtkWidget *widget = GTK_WIDGET (statusbar);

  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) 
    return GDK_WINDOW_EDGE_SOUTH_EAST; 
  else
    return GDK_WINDOW_EDGE_SOUTH_WEST; 
}

Owen Taylor's avatar
Owen Taylor committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
static void
get_grip_rect (GtkStatusbar *statusbar,
               GdkRectangle *rect)
{
  GtkWidget *widget;
  gint w, h;
  
  widget = GTK_WIDGET (statusbar);

  /* These are in effect the max/default size of the grip. */
  w = 18;
  h = 18;

  if (w > (widget->allocation.width))
    w = widget->allocation.width;

  if (h > (widget->allocation.height - widget->style->ythickness))
    h = widget->allocation.height - widget->style->ythickness;
  
  rect->width = w;
  rect->height = h;
456 457 458 459 460 461
  rect->y = widget->allocation.y + widget->allocation.height - h;

  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) 
      rect->x = widget->allocation.x + widget->allocation.width - w;
  else 
      rect->x = widget->allocation.x + widget->style->xthickness;
Owen Taylor's avatar
Owen Taylor committed
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
}

static void
gtk_statusbar_create_window (GtkStatusbar *statusbar)
{
  GtkWidget *widget;
  GdkWindowAttr attributes;
  gint attributes_mask;
  GdkRectangle rect;
  
  g_return_if_fail (GTK_WIDGET_REALIZED (statusbar));
  g_return_if_fail (statusbar->has_resize_grip);
  
  widget = GTK_WIDGET (statusbar);

  get_grip_rect (statusbar, &rect);

  attributes.x = rect.x;
  attributes.y = rect.y;
  attributes.width = rect.width;
  attributes.height = rect.height;
  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.wclass = GDK_INPUT_ONLY;
  attributes.event_mask = gtk_widget_get_events (widget) |
    GDK_BUTTON_PRESS_MASK;

  attributes_mask = GDK_WA_X | GDK_WA_Y;

  statusbar->grip_window = gdk_window_new (widget->window,
                                           &attributes, attributes_mask);
  gdk_window_set_user_data (statusbar->grip_window, widget);
}

static void
gtk_statusbar_destroy_window (GtkStatusbar *statusbar)
{
  gdk_window_set_user_data (statusbar->grip_window, NULL);
  gdk_window_destroy (statusbar->grip_window);
  statusbar->grip_window = NULL;
}

static void
gtk_statusbar_realize (GtkWidget *widget)
{
  GtkStatusbar *statusbar;

  statusbar = GTK_STATUSBAR (widget);
  
  (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);

  if (statusbar->has_resize_grip)
    gtk_statusbar_create_window (statusbar);
}

static void
gtk_statusbar_unrealize (GtkWidget *widget)
{
  GtkStatusbar *statusbar;

  statusbar = GTK_STATUSBAR (widget);

  if (statusbar->grip_window)
    gtk_statusbar_destroy_window (statusbar);
  
  (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
}

static void
gtk_statusbar_map (GtkWidget *widget)
{
  GtkStatusbar *statusbar;

  statusbar = GTK_STATUSBAR (widget);
  
  (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
  
  if (statusbar->grip_window)
    gdk_window_show (statusbar->grip_window);
}

static void
gtk_statusbar_unmap (GtkWidget *widget)
{
  GtkStatusbar *statusbar;

  statusbar = GTK_STATUSBAR (widget);

  if (statusbar->grip_window)
    gdk_window_hide (statusbar->grip_window);
  
  (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
}

static gboolean
gtk_statusbar_button_press (GtkWidget      *widget,
                            GdkEventButton *event)
{
  GtkStatusbar *statusbar;
  GtkWidget *ancestor;
561
  GdkWindowEdge edge;
Owen Taylor's avatar
Owen Taylor committed
562 563 564
  
  statusbar = GTK_STATUSBAR (widget);
  
565 566
  if (!statusbar->has_resize_grip ||
    event->type != GDK_BUTTON_PRESS)
Owen Taylor's avatar
Owen Taylor committed
567 568 569 570 571 572 573
    return FALSE;
  
  ancestor = gtk_widget_get_toplevel (widget);

  if (!GTK_IS_WINDOW (ancestor))
    return FALSE;

574 575
  edge = get_grip_edge (statusbar);

Owen Taylor's avatar
Owen Taylor committed
576 577
  if (event->button == 1)
    gtk_window_begin_resize_drag (GTK_WINDOW (ancestor),
578
                                  edge,
Owen Taylor's avatar
Owen Taylor committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
                                  event->button,
                                  event->x_root, event->y_root,
                                  event->time);
  else if (event->button == 2)
    gtk_window_begin_move_drag (GTK_WINDOW (ancestor),
                                event->button,
                                event->x_root, event->y_root,
                                event->time);
  else
    return FALSE;
  
  return TRUE;
}

static gboolean
gtk_statusbar_expose_event (GtkWidget      *widget,
                            GdkEventExpose *event)
{
  GtkStatusbar *statusbar;
  GdkRectangle rect;
  
  statusbar = GTK_STATUSBAR (widget);

  GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);

  if (statusbar->has_resize_grip)
    {
606 607 608 609
      GdkWindowEdge edge;
      
      edge = get_grip_edge (statusbar);

Owen Taylor's avatar
Owen Taylor committed
610
      get_grip_rect (statusbar, &rect);
611

Owen Taylor's avatar
Owen Taylor committed
612 613 614 615 616 617
      gtk_paint_resize_grip (widget->style,
                             widget->window,
                             GTK_WIDGET_STATE (widget),
                             NULL,
                             widget,
                             "statusbar",
618
                             edge,
Owen Taylor's avatar
Owen Taylor committed
619 620 621 622 623 624 625 626 627 628
                             rect.x, rect.y,
                             /* don't draw grip over the frame, though you
                              * can click on the frame.
                              */
                             rect.width - widget->style->xthickness,
                             rect.height - widget->style->ythickness);
    }

  return FALSE;
}
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692

static void
gtk_statusbar_size_request   (GtkWidget      *widget,
                              GtkRequisition *requisition)
{
  GtkStatusbar *statusbar;
  GtkShadowType shadow_type;
  
  statusbar = GTK_STATUSBAR (widget);

  gtk_widget_style_get (GTK_WIDGET (statusbar), "shadow_type", &shadow_type, NULL);  
  gtk_frame_set_shadow_type (GTK_FRAME (statusbar->frame), shadow_type);
  
  GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);

  if (statusbar->has_resize_grip)
    {
      GdkRectangle rect;

      /* x, y in the grip rect depend on size allocation, but
       * w, h do not so this is OK
       */
      get_grip_rect (statusbar, &rect);
      
      requisition->width += rect.width;
      requisition->height = MAX (requisition->height, rect.height);
    }
}

static void
gtk_statusbar_size_allocate  (GtkWidget     *widget,
                              GtkAllocation *allocation)
{
  GtkStatusbar *statusbar;
  
  statusbar = GTK_STATUSBAR (widget);

  if (statusbar->has_resize_grip)
    {
      GdkRectangle rect;
      GtkRequisition saved_req;
      
      widget->allocation = *allocation; /* get_grip_rect needs this info */
      get_grip_rect (statusbar, &rect);
  
      if (statusbar->grip_window)
        gdk_window_move_resize (statusbar->grip_window,
                                rect.x, rect.y,
                                rect.width, rect.height);
      
      /* enter the bad hack zone */      
      saved_req = widget->requisition;
      widget->requisition.width -= rect.width; /* HBox::size_allocate needs this */
      if (widget->requisition.width < 0)
        widget->requisition.width = 0;
      GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
      widget->requisition = saved_req;
    }
  else
    {
      /* chain up normally */
      GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
    }
}