ScrolledWindow shadow type



Currently, it is not possible to put a frame around a widget in a
GtkScrolledWindow, (such as a GnomeCanvas or GtkLayout), because the
scrollable widget must be the immediate child of the scrolled window.

The following patch adds gtk_scrolled_window_get_shadow_type().

The effect is similar to the Federico's gtkscrollframe in EOG,
but done from scratch.

I'll commit this later today assuming no objections.

Regards,
                                        Owen

Index: gtkscrolledwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkscrolledwindow.c,v
retrieving revision 1.42
diff -u -r1.42 gtkscrolledwindow.c
--- gtkscrolledwindow.c	2000/05/12 15:25:47	1.42
+++ gtkscrolledwindow.c	2000/07/21 15:17:20
@@ -73,7 +73,8 @@
   ARG_VADJUSTMENT,
   ARG_HSCROLLBAR_POLICY,
   ARG_VSCROLLBAR_POLICY,
-  ARG_WINDOW_PLACEMENT
+  ARG_WINDOW_PLACEMENT,
+  ARG_SHADOW
 };
 
 
@@ -91,6 +92,8 @@
 static void gtk_scrolled_window_unmap              (GtkWidget              *widget);
 static void gtk_scrolled_window_draw               (GtkWidget              *widget,
 						    GdkRectangle           *area);
+static gint gtk_scrolled_window_expose             (GtkWidget              *widget,
+						    GdkEventExpose         *event);
 static void gtk_scrolled_window_size_request       (GtkWidget              *widget,
 						    GtkRequisition         *requisition);
 static void gtk_scrolled_window_size_allocate      (GtkWidget              *widget,
@@ -160,6 +163,7 @@
   widget_class->map = gtk_scrolled_window_map;
   widget_class->unmap = gtk_scrolled_window_unmap;
   widget_class->draw = gtk_scrolled_window_draw;
+  widget_class->expose_event = gtk_scrolled_window_expose;
   widget_class->size_request = gtk_scrolled_window_size_request;
   widget_class->size_allocate = gtk_scrolled_window_size_allocate;
   widget_class->scroll_event = gtk_scrolled_window_scroll_event;
@@ -190,6 +194,10 @@
 			   GTK_TYPE_CORNER_TYPE,
 			   GTK_ARG_READWRITE,
 			   ARG_WINDOW_PLACEMENT);
+  gtk_object_add_arg_type ("GtkScrolledWindow::shadow",
+			   GTK_TYPE_SHADOW_TYPE,
+			   GTK_ARG_READWRITE,
+			   ARG_SHADOW);
 }
 
 static void
@@ -223,6 +231,10 @@
       gtk_scrolled_window_set_placement (scrolled_window,
 					 GTK_VALUE_ENUM (*arg));
       break;
+    case ARG_SHADOW:
+      gtk_scrolled_window_set_shadow_type (scrolled_window,
+					   GTK_VALUE_ENUM (*arg));
+      break;
     default:
       break;
     }
@@ -254,6 +266,9 @@
     case ARG_WINDOW_PLACEMENT:
       GTK_VALUE_ENUM (*arg) = scrolled_window->window_placement;
       break;
+    case ARG_SHADOW:
+      GTK_VALUE_ENUM (*arg) = scrolled_window->shadow_type;
+      break;
     default:
       arg->type = GTK_TYPE_INVALID;
       break;
@@ -458,6 +473,24 @@
     }
 }
 
+void
+gtk_scrolled_window_set_shadow_type (GtkScrolledWindow *scrolled_window,
+				     GtkShadowType      type)
+{
+  g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
+  g_return_if_fail (type >= GTK_SHADOW_NONE && type <= GTK_SHADOW_ETCHED_OUT);
+  
+  if (scrolled_window->shadow_type != type)
+    {
+      scrolled_window->shadow_type = type;
+
+      if (GTK_WIDGET_DRAWABLE (scrolled_window))
+	gtk_widget_queue_clear (GTK_WIDGET (scrolled_window));
+
+      gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
+    }
+}
+
 static void
 gtk_scrolled_window_destroy (GtkObject *object)
 {
@@ -530,6 +563,32 @@
 }
 
 static void
+gtk_scrolled_window_paint (GtkWidget    *widget,
+			   GdkRectangle *area)
+{
+  GtkAllocation relative_allocation;
+  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+  if (scrolled_window->shadow_type != GTK_SHADOW_NONE)
+    {
+      gtk_scrolled_window_relative_allocation (widget, &relative_allocation);
+      
+      relative_allocation.x -= widget->style->xthickness;
+      relative_allocation.y -= widget->style->ythickness;
+      relative_allocation.width += 2 * widget->style->xthickness;
+      relative_allocation.height += 2 * widget->style->ythickness;
+      
+      gtk_paint_shadow (widget->style, widget->window,
+			GTK_STATE_NORMAL, scrolled_window->shadow_type,
+			area, widget, "scrolled_window",
+			widget->allocation.x + relative_allocation.x,
+			widget->allocation.y + relative_allocation.y,
+			relative_allocation.width,
+			relative_allocation.height);
+    }
+}
+
+static void
 gtk_scrolled_window_draw (GtkWidget    *widget,
 			  GdkRectangle *area)
 {
@@ -544,17 +603,46 @@
   scrolled_window = GTK_SCROLLED_WINDOW (widget);
   bin = GTK_BIN (widget);
 
-  if (bin->child && GTK_WIDGET_VISIBLE (bin->child) &&
-      gtk_widget_intersect (bin->child, area, &child_area))
-    gtk_widget_draw (bin->child, &child_area);
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      gtk_scrolled_window_paint (widget, area);
   
-  if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) &&
-      gtk_widget_intersect (scrolled_window->hscrollbar, area, &child_area))
-    gtk_widget_draw (scrolled_window->hscrollbar, &child_area);
+      if (bin->child && GTK_WIDGET_VISIBLE (bin->child) &&
+	  gtk_widget_intersect (bin->child, area, &child_area))
+	gtk_widget_draw (bin->child, &child_area);
+      
+      if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) &&
+	  gtk_widget_intersect (scrolled_window->hscrollbar, area, &child_area))
+	gtk_widget_draw (scrolled_window->hscrollbar, &child_area);
+      
+      if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) &&
+	  gtk_widget_intersect (scrolled_window->vscrollbar, area, &child_area))
+	gtk_widget_draw (scrolled_window->vscrollbar, &child_area);
+    }
+}
   
-  if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) &&
-      gtk_widget_intersect (scrolled_window->vscrollbar, area, &child_area))
-    gtk_widget_draw (scrolled_window->vscrollbar, &child_area);
+static gint
+gtk_scrolled_window_expose (GtkWidget      *widget,
+			    GdkEventExpose *event)
+{
+  GtkBin *bin = GTK_BIN (widget);
+  GdkEventExpose child_event;
+
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      gtk_scrolled_window_paint (widget, &event->area);
+
+      if (bin->child && GTK_WIDGET_VISIBLE (bin->child) && GTK_WIDGET_NO_WINDOW (bin->child))
+	{
+	  child_event = *event;	  
+	  if (gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+	    gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+	}
+
+      /* We rely on our knowledge that scrollbars are !NO_WINDOW widgets */
+    }
+
+  return FALSE;
 }
 
 static void
@@ -673,6 +761,12 @@
 
   requisition->width += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_width);
   requisition->height += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_height);
+
+  if (scrolled_window->shadow_type != GTK_SHADOW_NONE)
+    {
+      requisition->width += 2 * widget->style->xthickness;
+      requisition->height += 2 * widget->style->ythickness;
+    }
 }
 
 static void
@@ -688,6 +782,13 @@
 
   allocation->x = GTK_CONTAINER (widget)->border_width;
   allocation->y = GTK_CONTAINER (widget)->border_width;
+
+  if (scrolled_window->shadow_type != GTK_SHADOW_NONE)
+    {
+      allocation->x += widget->style->xthickness;
+      allocation->y += widget->style->ythickness;
+    }
+  
   allocation->width = MAX (1, (gint)widget->allocation.width - allocation->x * 2);
   allocation->height = MAX (1, (gint)widget->allocation.height - allocation->y * 2);
 
@@ -808,7 +909,9 @@
 	  scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT)
 	child_allocation.y = (relative_allocation.y +
 			      relative_allocation.height +
-			      SCROLLBAR_SPACING (scrolled_window));
+			      SCROLLBAR_SPACING (scrolled_window) +
+			      (scrolled_window->shadow_type == GTK_SHADOW_NONE ?
+			       0 : widget->style->ythickness));
       else
 	child_allocation.y = GTK_CONTAINER (scrolled_window)->border_width;
 
@@ -817,6 +920,12 @@
       child_allocation.x += allocation->x;
       child_allocation.y += allocation->y;
 
+      if (scrolled_window->shadow_type != GTK_SHADOW_NONE)
+	{
+	  child_allocation.x -= widget->style->xthickness;
+	  child_allocation.width += 2 * widget->style->xthickness;
+	}
+
       gtk_widget_size_allocate (scrolled_window->hscrollbar, &child_allocation);
     }
   else if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar))
@@ -835,7 +944,9 @@
 	  scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT)
 	child_allocation.x = (relative_allocation.x +
 			      relative_allocation.width +
-			      SCROLLBAR_SPACING (scrolled_window));
+			      SCROLLBAR_SPACING (scrolled_window) +
+			      (scrolled_window->shadow_type == GTK_SHADOW_NONE ?
+			       0 : widget->style->xthickness));
       else
 	child_allocation.x = GTK_CONTAINER (scrolled_window)->border_width;
 
@@ -844,6 +955,12 @@
       child_allocation.height = relative_allocation.height;
       child_allocation.x += allocation->x;
       child_allocation.y += allocation->y;
+
+      if (scrolled_window->shadow_type != GTK_SHADOW_NONE)
+	{
+	  child_allocation.y -= widget->style->ythickness;
+	  child_allocation.height += 2 * widget->style->ythickness;
+	}
 
       gtk_widget_size_allocate (scrolled_window->vscrollbar, &child_allocation);
     }
Index: gtkscrolledwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkscrolledwindow.h,v
retrieving revision 1.13
diff -u -r1.13 gtkscrolledwindow.h
--- gtkscrolledwindow.h	2000/02/13 08:16:47	1.13
+++ gtkscrolledwindow.h	2000/07/21 15:17:20
@@ -63,6 +63,8 @@
   guint hscrollbar_visible     : 1;
   guint vscrollbar_visible     : 1;
   guint window_placement       : 2;
+
+  guint16 shadow_type;
 };
 
 struct _GtkScrolledWindowClass
@@ -87,6 +89,8 @@
 						      GtkPolicyType      vscrollbar_policy);
 void           gtk_scrolled_window_set_placement     (GtkScrolledWindow *scrolled_window,
 						      GtkCornerType      window_placement);
+void           gtk_scrolled_window_set_shadow_type   (GtkScrolledWindow *scrolled_window,
+						      GtkShadowType      type);
 void	       gtk_scrolled_window_add_with_viewport (GtkScrolledWindow *scrolled_window,
 						      GtkWidget		*child);
 




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]