From 584f52bcf8fca3913084102405fdf78241b5f2b0 Mon Sep 17 00:00:00 2001 From: Matt Birkholz Date: Tue, 29 Jan 2013 12:29:27 -0700 Subject: [PATCH] gtk: Added GtkPanedView, a specialized GtkPaned. --- doc/gtk/gtk.texinfo | 43 ++- src/gtk/Makefile-fragment | 13 +- src/gtk/fix-demo.scm | 8 +- src/gtk/gtk-shim.h | 1 + src/gtk/gtk-widget.scm | 34 +- src/gtk/gtk.cdecl | 4 + src/gtk/gtk.pkg | 3 +- src/gtk/gtkpanedview.c.stay | 612 +++++++++++++++++++++++++++++++++ src/gtk/gtkpanedview.h | 51 +++ src/gtk/gtkscrolledview.c.stay | 54 ++- src/gtk/gtkscrolledview.h | 26 ++ 11 files changed, 796 insertions(+), 53 deletions(-) create mode 100644 src/gtk/gtkpanedview.c.stay create mode 100644 src/gtk/gtkpanedview.h diff --git a/doc/gtk/gtk.texinfo b/doc/gtk/gtk.texinfo index 7bde112e5..9d122721b 100644 --- a/doc/gtk/gtk.texinfo +++ b/doc/gtk/gtk.texinfo @@ -1576,6 +1576,33 @@ Returns @var{paned}'s first child, or @code{#f} if there is none. Returns @var{paned}'s second child, or @code{#f} if there is none. @end deffn +@deffn Class +A direct subclass of gtk-scrolled-view representing a reference to a +GtkPanedView. This is an extension to the Gtks, a specialization of +GtkPaned that overrides its widget geometry protocol. + +A GtkPaned allows the user to shrink a child (or not!), displaying it +in a smaller area than its minimum size normally allows. If neither +child is indicated as the shrinkable one, it is assumed both childen +can be shrunk. The geometry implementation completely ignores the +natural size of the children, sizing and expanding them in proportion +to their minimum sizes (until the divider's position is set). It will +truncate the ``beginning'' of a child that does not fit, displaying +its ``end'' (per the writing direction). + +A GtkPanedView sizes/expands its children according to their natural +sizes and respects their minimum sizes (while the position of its +divider is unset, unless indicated as shrinkable). If neither child +is allowed to shrink, it is assumed neither child should be shrunk. +The minimum size of the paned view allows for the minimum sizes of +both children. + +The difference between paned windows and paned viewports can be +observed by substituting @code{gtk-paned-new} and +@code{gtk-paned-view-new} in the fix layout demo. See @bref{Fix +Demo}. +@end deffn + @node Gtk Scrolled Window, Scheme Widget, Gtk Paned, API Reference @section Gtk Scrolled Window @@ -1610,10 +1637,8 @@ above and to the right. @deffn Class A direct subclass of gtk-scrolled-window representing a reference to a -GtkScrolledView. - -This specialization of GtkScrolledWindow overrides the widget geometry -protocol to work somewhat differently. +GtkScrolledView. This is an extension to the Gtks, a specialization +of GtkScrolledWindow that overrides its widget geometry protocol. A GtkScrolledWindow is used to squeeze an overly large widget into a smaller space and allow the user to scroll it. The geometry @@ -1624,10 +1649,12 @@ size. A GtkScrolledView is used to stick scrollbars on a viewport. Its natural size is the natural size of the viewport, plus scrollbars, frame, etc. Using @code{gtk_widget_set_size_request} is unnecessary -and interferes with resizing. The difference can be observed by -replacing @code{gtk-scrolled-view-new} with -@code{gtk-scrolled-window-new} in the fix layout demo. -See @bref{Fix Demo}. +and interferes with resizing. + +The difference between a scrolled window and a scrolled viewport can +be observed by substituting @code{gtk-scrolled-view-new} and +@code{gtk-scrolled-window-new} in the fix layout demo. See @bref{Fix +Demo}. @end deffn @node Scheme Widget, Fix Layout, Gtk Scrolled Window, API Reference diff --git a/src/gtk/Makefile-fragment b/src/gtk/Makefile-fragment index 1bab067ee..18c0092d9 100644 --- a/src/gtk/Makefile-fragment +++ b/src/gtk/Makefile-fragment @@ -59,9 +59,10 @@ install: | ../microcode/scheme --library ../lib --batch-mode` = "c"; \ then $(MAKE) install-liarc-bundle; fi -gtk-shim.so: gtk-shim.o gtkscrolledview.o scmwidget.o gtkio.o $(SHIM_LOADER) - $(LINK_SHIM) gtk-shim.o gtkscrolledview.o scmwidget.o gtkio.o \ - `pkg-config --libs gtk+-3.0 gthread-2.0` $(SHIM_LIBS) +gtk-shim.so: gtk-shim.o gtkpanedview.o gtkscrolledview.o scmwidget.o \ + gtkio.o $(SHIM_LOADER) + $(LINK_SHIM) gtk-shim.o gtkpanedview.o gtkscrolledview.o scmwidget.o \ + gtkio.o `pkg-config --libs gtk+-3.0 gthread-2.0` $(SHIM_LIBS) gtkscrolledview.o: gtkscrolledview.c gtkscrolledview.h $(COMPILE_SHIM) `pkg-config --cflags gtk+-3.0` -c gtkscrolledview.c @@ -69,6 +70,12 @@ gtkscrolledview.o: gtkscrolledview.c gtkscrolledview.h gtkscrolledview.c: gtkscrolledview.c.stay cp -p gtkscrolledview.c.stay gtkscrolledview.c +gtkpanedview.o: gtkpanedview.c gtkpanedview.h + $(COMPILE_SHIM) `pkg-config --cflags gtk+-3.0` -c gtkpanedview.c + +gtkpanedview.c: gtkpanedview.c.stay + cp -p gtkpanedview.c.stay gtkpanedview.c + scmwidget.o: scmwidget.c scmwidget.h $(COMPILE_SHIM) `pkg-config --cflags gtk+-3.0` -c scmwidget.c diff --git a/src/gtk/fix-demo.scm b/src/gtk/fix-demo.scm index 22b7782cc..2eb28eed6 100644 --- a/src/gtk/fix-demo.scm +++ b/src/gtk/fix-demo.scm @@ -40,17 +40,19 @@ USA. (layout1 (let ((l (make-demo-layout 200 200))) (gtk-widget-set-hexpand l #t) (gtk-widget-set-vexpand l #t) + (set-scm-widget-minimum-size! l 40 40) l)) (layout2 (let ((l (make-demo-layout 200 300))) (gtk-widget-set-hexpand l #t) (gtk-widget-set-vexpand l #t) + (set-scm-widget-minimum-size! l 40 60) l)) - (paned (gtk-paned-new 'vertical))) + (paned (gtk-paned-view-new 'vertical))) (gtk-container-add scroller1 layout1) - (gtk-paned-pack1 paned scroller1 'resize 'shrink) + (gtk-paned-pack1 paned scroller1 'resize #f) (gtk-container-add scroller2 layout2) - (gtk-paned-pack2 paned scroller2 'resize 'shrink) + (gtk-paned-pack2 paned scroller2 'resize #f) (gtk-container-add window paned) (gtk-widget-show-all window) diff --git a/src/gtk/gtk-shim.h b/src/gtk/gtk-shim.h index 3c337542f..c80eb840d 100644 --- a/src/gtk/gtk-shim.h +++ b/src/gtk/gtk-shim.h @@ -30,6 +30,7 @@ USA. #include #include "scmwidget.h" +#include "gtkpanedview.h" #include "gtkscrolledview.h" typedef unsigned int uint; diff --git a/src/gtk/gtk-widget.scm b/src/gtk/gtk-widget.scm index c6bd4f5b7..90647d5da 100644 --- a/src/gtk/gtk-widget.scm +++ b/src/gtk/gtk-widget.scm @@ -718,7 +718,7 @@ USA. operator)))) (define-class ( (constructor ())) - ()) + ()) (define-guarantee gtk-scrolled-view "a ") @@ -733,19 +733,20 @@ USA. ;;; GtkPaneds -(define-class ( (constructor gtk-paned-new () (orientation))) +(define-class ( (constructor ())) () (child1 define standard accessor gtk-paned-get-child1 initial-value #f) (child2 define standard accessor gtk-paned-get-child2 initial-value #f)) -(define-method initialize-instance ((paned ) orientation) - (call-next-method paned) - (let ((alien (gobject-alien paned)) - (orient (->gtk-orientation orientation 'gtk-paned-new))) - (C-call "gtk_paned_new" alien orient) - (error-if-null alien "Could not create:" paned orient) - (C-call "g_object_ref_sink" alien alien)) - (set-gtk-widget-destroy-callback! paned)) +(define (gtk-paned-new orientation) + (let ((orient (->gtk-orientation orientation 'gtk-paned-new)) + (paned (make-gtk-paned))) + (let ((alien (gobject-alien paned))) + (C-call "gtk_paned_new" alien orient) + (error-if-null alien "Could not create:" paned orient) + (C-call "g_object_ref_sink" alien alien)) + (set-gtk-widget-destroy-callback! paned) + paned)) (define (gtk-paned-pack1 paned child1 resize? shrink?) (guarantee-gtk-widget child1 'gtk-paned-pack1) @@ -766,6 +767,19 @@ USA. (container-add! paned child2) (C-call "gtk_paned_pack2" (gobject-alien paned) (gobject-alien child2) (if resize? 1 0) (if shrink? 1 0))) + +(define-class ( (constructor ())) + ()) + +(define (gtk-paned-view-new orientation) + (let ((orient (->gtk-orientation orientation 'gtk-paned-view-new)) + (paned (make-gtk-paned-view))) + (let ((alien (gobject-alien paned))) + (C-call "gtk_paned_view_new" alien orient) + (error-if-null alien "Could not create:" paned) + (C-call "g_object_ref_sink" alien alien)) + (set-gtk-widget-destroy-callback! paned) + paned)) ;;; GtkWindows diff --git a/src/gtk/gtk.cdecl b/src/gtk/gtk.cdecl index 1d2ab6c6d..9203adcb7 100644 --- a/src/gtk/gtk.cdecl +++ b/src/gtk/gtk.cdecl @@ -99,6 +99,10 @@ USA. ;;; miscellaneous +(extern (* GtkWidget) ;gtkpanedview.h + gtk_paned_view_new + (orientation GtkOrientation)) + (extern (* GtkWidget) ;gtkscrolledview.h gtk_scrolled_view_new (hadjustment (* GtkAdjustment)) diff --git a/src/gtk/gtk.pkg b/src/gtk/gtk.pkg index 609815cd3..c3aa43dcd 100644 --- a/src/gtk/gtk.pkg +++ b/src/gtk/gtk.pkg @@ -213,7 +213,8 @@ USA. guarantee-gtk-scrolled-view gtk-scrolled-view-new gtk-paned? gtk-paned-new gtk-paned-pack1 gtk-paned-pack2 - gtk-paned-get-child1 gtk-paned-get-child2) + gtk-paned-get-child1 gtk-paned-get-child2 + gtk-paned-view? gtk-paned-view-new) (import (gtk pango) make-pango-layout guarantee-pango-font-description)) (define-package (gtk widget) diff --git a/src/gtk/gtkpanedview.c.stay b/src/gtk/gtkpanedview.c.stay new file mode 100644 index 000000000..9b6f04bda --- /dev/null +++ b/src/gtk/gtkpanedview.c.stay @@ -0,0 +1,612 @@ +/* -*-C-*- + +Copyright (C) 2013 Matthew Birkholz + +This file is part of MIT/GNU Scheme. + +MIT/GNU Scheme 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. + +MIT/GNU Scheme 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 MIT/GNU Scheme; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, +USA. + +*/ + +/* A specialized GtkPaned. See documentation of . */ + +#include "gtkpanedview.h" + +static void gtk_paned_view_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_paned_view_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_paned_view_get_preferred_height_for_width + (GtkWidget *layout, + gint width, + gint *minimum_height, + gint *natural_height); +static void gtk_paned_view_get_preferred_width_for_height + (GtkWidget *layout, + gint width, + gint *minimum_height, + gint *natural_height); + +static void gtk_paned_view_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); + +G_DEFINE_TYPE (GtkPanedView, gtk_paned_view, + GTK_TYPE_PANED) + +static void +gtk_paned_view_class_init (GtkPanedViewClass *class) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass*) class; + + widget_class->get_preferred_width = gtk_paned_view_get_preferred_width; + widget_class->get_preferred_height = gtk_paned_view_get_preferred_height; + widget_class->get_preferred_height_for_width = gtk_paned_view_get_preferred_height_for_width; + widget_class->get_preferred_width_for_height = gtk_paned_view_get_preferred_width_for_height; + widget_class->size_allocate = gtk_paned_view_size_allocate; +} + +static void +gtk_paned_view_init (GtkPanedView *paned_view) +{ + g_assert (GTK_PANED (paned_view) ->priv != NULL); +} + +/** + * gtk_paned_view_new: + * @orientation: GTK_ORIENTATION_VERTICAL or GTK_ORIENTATION_HORIZONTAL. + * + * Creates a new paned view. + * + * Returns: a new paned view. + */ +GtkWidget* +gtk_paned_view_new (GtkOrientation orientation) +{ + return (g_object_new (GTK_TYPE_PANED_VIEW, + "orientation", orientation, + NULL)); +} + +/* The rest of this file was copied from gtkpaned.c v3.6.0 with + minimal modification. */ + +enum { + CHILD1, + CHILD2 +}; + +struct _GtkPanedPrivate +{ + GtkPaned *first_paned; + GtkWidget *child1; + GtkWidget *child2; + GdkWindow *child1_window; + GdkWindow *child2_window; + GtkWidget *last_child1_focus; + GtkWidget *last_child2_focus; + GtkWidget *saved_focus; + GtkOrientation orientation; + + GdkCursorType cursor_type; + GdkDevice *grab_device; + GdkRectangle handle_pos; + GdkWindow *handle; + + gint child1_size; + gint drag_pos; + gint last_allocation; + gint max_position; + gint min_position; + gint original_position; + + guint32 grab_time; + + guint handle_prelit : 1; + guint in_drag : 1; + guint in_recursion : 1; + guint child1_resize : 1; + guint child1_shrink : 1; + guint child2_resize : 1; + guint child2_shrink : 1; + guint position_set : 1; +}; + +static void +flip_child (GtkWidget *widget, + GtkAllocation *child_pos) +{ + GtkAllocation allocation; + gint x, width; + + gtk_widget_get_allocation (widget, &allocation); + x = allocation.x; + width = allocation.width; + + child_pos->x = 2 * x + width - child_pos->x - child_pos->width; +} + +static void +gtk_paned_set_child_visible (GtkPaned *paned, + guint id, + gboolean visible) +{ + GtkPanedPrivate *priv = paned->priv; + GtkWidget *child; + + child = id == CHILD1 ? priv->child1 : priv->child2; + + if (child == NULL) + return; + + gtk_widget_set_child_visible (child, visible); + + if (gtk_widget_get_mapped (GTK_WIDGET (paned))) + { + GdkWindow *window = id == CHILD1 ? priv->child1_window : priv->child2_window; + + if (visible != gdk_window_is_visible (window)) + { + if (visible) + gdk_window_show (window); + else + gdk_window_hide (window); + } + } +} + +static void +gtk_paned_child_allocate (GtkWidget *child, + GdkWindow *child_window, /* can be NULL */ + const GtkAllocation *window_allocation, + GtkAllocation *child_allocation) +{ + if (child_window) + gdk_window_move_resize (child_window, + window_allocation->x, window_allocation->y, + window_allocation->width, window_allocation->height); + + gtk_widget_size_allocate (child, child_allocation); +} + +static void +gtk_paned_calc_position (GtkPaned *paned, + gint allocation, + gint child1_min, + gint child1_nat, + gint child2_min, + gint child2_nat) +{ + GtkPanedPrivate *priv = paned->priv; + gint old_position; + gint old_min_position; + gint old_max_position; + + old_position = priv->child1_size; + old_min_position = priv->min_position; + old_max_position = priv->max_position; + + priv->min_position = priv->child1_shrink ? 0 : child1_min; + + priv->max_position = allocation; + if (!priv->child2_shrink) + priv->max_position = MAX (1, priv->max_position - child2_min); + priv->max_position = MAX (priv->min_position, priv->max_position); + + if (!priv->position_set) + { + if (priv->child1_resize && !priv->child2_resize) + priv->child1_size = MAX (0, allocation - child2_nat); + else if (!priv->child1_resize && priv->child2_resize) + priv->child1_size = child1_nat; + else if (child1_nat + child2_nat != 0) + priv->child1_size = allocation * ((gdouble)child1_nat / (child1_nat + child2_nat)) + 0.5; + else + priv->child1_size = allocation * 0.5 + 0.5; + } + else + { + /* If the position was set before the initial allocation. + * (priv->last_allocation <= 0) just clamp it and leave it. + */ + if (priv->last_allocation > 0) + { + if (priv->child1_resize && !priv->child2_resize) + priv->child1_size += allocation - priv->last_allocation; + else if (!(!priv->child1_resize && priv->child2_resize)) + priv->child1_size = allocation * ((gdouble) priv->child1_size / (priv->last_allocation)) + 0.5; + } + } + + priv->child1_size = CLAMP (priv->child1_size, + priv->min_position, + priv->max_position); + + if (priv->child1) + gtk_paned_set_child_visible (paned, 0, priv->child1_size != 0); + + if (priv->child2) + gtk_paned_set_child_visible (paned, 1, priv->child1_size != allocation); + + g_object_freeze_notify (G_OBJECT (paned)); + if (priv->child1_size != old_position) + g_object_notify (G_OBJECT (paned), "position"); + if (priv->min_position != old_min_position) + g_object_notify (G_OBJECT (paned), "min-position"); + if (priv->max_position != old_max_position) + g_object_notify (G_OBJECT (paned), "max-position"); + g_object_thaw_notify (G_OBJECT (paned)); + + priv->last_allocation = allocation; +} + +static void +gtk_paned_view_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkPaned *paned = GTK_PANED (widget); + GtkPanedPrivate *priv = paned->priv; + + gtk_widget_set_allocation (widget, allocation); + + if (priv->child1 && gtk_widget_get_visible (priv->child1) && + priv->child2 && gtk_widget_get_visible (priv->child2)) + { + GtkAllocation child1_allocation, window1_allocation; + GtkAllocation child2_allocation, window2_allocation; + GtkAllocation priv_child1_allocation; + GdkRectangle old_handle_pos; + gint handle_size; + + gtk_widget_style_get (widget, "handle-size", &handle_size, NULL); + + old_handle_pos = priv->handle_pos; + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + { + gint child1_min_width, child1_nat_width; + gint child2_min_width, child2_nat_width; + + gtk_widget_get_preferred_width_for_height (priv->child1, + allocation->height, + &child1_min_width, &child1_nat_width); + gtk_widget_get_preferred_width_for_height (priv->child2, + allocation->height, + &child2_min_width, &child2_nat_width); + + gtk_paned_calc_position (paned, + MAX (1, allocation->width - handle_size), + child1_min_width, child1_nat_width, + child2_min_width, child2_nat_width); + + priv->handle_pos.x = allocation->x + priv->child1_size; + priv->handle_pos.y = allocation->y; + priv->handle_pos.width = handle_size; + priv->handle_pos.height = allocation->height; + + window1_allocation.height = window2_allocation.height = allocation->height; + window1_allocation.width = MAX (1, priv->child1_size); + window1_allocation.x = allocation->x; + window1_allocation.y = window2_allocation.y = allocation->y; + + window2_allocation.x = window1_allocation.x + priv->child1_size + priv->handle_pos.width; + window2_allocation.width = MAX (1, allocation->x + allocation->width - window2_allocation.x); + + if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL) + { + flip_child (widget, &(window2_allocation)); + flip_child (widget, &(window1_allocation)); + flip_child (widget, &(priv->handle_pos)); + } + + child1_allocation.x = child1_allocation.y = 0; + child1_allocation.width = window1_allocation.width; + child1_allocation.height = window1_allocation.height; + if (child1_min_width > child1_allocation.width) + { + if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_LTR) + child1_allocation.x -= child1_min_width - child1_allocation.width; + child1_allocation.width = child1_min_width; + } + + child2_allocation.x = child2_allocation.y = 0; + child2_allocation.width = window2_allocation.width; + child2_allocation.height = window2_allocation.height; + if (child2_min_width > child2_allocation.width) + { + if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL) + child2_allocation.x -= child2_min_width - child2_allocation.width; + child2_allocation.width = child2_min_width; + } + } + else + { + gint child1_min_height, child1_nat_height; + gint child2_min_height, child2_nat_height; + + gtk_widget_get_preferred_height_for_width (priv->child1, + allocation->width, + &child1_min_height, + &child1_nat_height); + gtk_widget_get_preferred_height_for_width (priv->child2, + allocation->width, + &child2_min_height, + &child2_nat_height); + + gtk_paned_calc_position (paned, + MAX (1, allocation->height - handle_size), + child1_min_height, child1_nat_height, + child2_min_height, child2_nat_height); + + priv->handle_pos.x = allocation->x; + priv->handle_pos.y = allocation->y + priv->child1_size; + priv->handle_pos.width = allocation->width; + priv->handle_pos.height = handle_size; + + window1_allocation.width = window2_allocation.width = allocation->width; + window1_allocation.height = MAX (1, priv->child1_size); + window1_allocation.x = window2_allocation.x = allocation->x; + window1_allocation.y = allocation->y; + + window2_allocation.y = window1_allocation.y + priv->child1_size + priv->handle_pos.height; + window2_allocation.height = MAX (1, allocation->y + allocation->height - window2_allocation.y); + + child1_allocation.x = child1_allocation.y = 0; + child1_allocation.width = window1_allocation.width; + child1_allocation.height = window1_allocation.height; + if (child1_min_height > child1_allocation.height) + { + child1_allocation.y -= child1_min_height - child1_allocation.height; + child1_allocation.height = child1_min_height; + } + + child2_allocation.x = child2_allocation.y = 0; + child2_allocation.width = window2_allocation.width; + child2_allocation.height = window2_allocation.height; + if (child2_min_height > child2_allocation.height) + child2_allocation.height = child2_min_height; + } + + if (gtk_widget_get_mapped (widget) && + (old_handle_pos.x != priv->handle_pos.x || + old_handle_pos.y != priv->handle_pos.y || + old_handle_pos.width != priv->handle_pos.width || + old_handle_pos.height != priv->handle_pos.height)) + { + GdkWindow *window; + + window = gtk_widget_get_window (widget); + gdk_window_invalidate_rect (window, &old_handle_pos, FALSE); + gdk_window_invalidate_rect (window, &priv->handle_pos, FALSE); + } + + if (gtk_widget_get_realized (widget)) + { + if (gtk_widget_get_mapped (widget)) + gdk_window_show (priv->handle); + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + { + gdk_window_move_resize (priv->handle, + priv->handle_pos.x, + priv->handle_pos.y, + handle_size, + priv->handle_pos.height); + } + else + { + gdk_window_move_resize (priv->handle, + priv->handle_pos.x, + priv->handle_pos.y, + priv->handle_pos.width, + handle_size); + } + } + + /* Now allocate the childen, making sure, when resizing not to + * overlap the windows + */ + gtk_widget_get_allocation (priv->child1, &priv_child1_allocation); + if (gtk_widget_get_mapped (widget) && + ((priv->orientation == GTK_ORIENTATION_HORIZONTAL && + priv_child1_allocation.width < child1_allocation.width) || + + (priv->orientation == GTK_ORIENTATION_VERTICAL && + priv_child1_allocation.height < child1_allocation.height))) + { + gtk_paned_child_allocate (priv->child2, + priv->child2_window, + &window2_allocation, + &child2_allocation); + gtk_paned_child_allocate (priv->child1, + priv->child1_window, + &window1_allocation, + &child1_allocation); + } + else + { + gtk_paned_child_allocate (priv->child1, + priv->child1_window, + &window1_allocation, + &child1_allocation); + gtk_paned_child_allocate (priv->child2, + priv->child2_window, + &window2_allocation, + &child2_allocation); + } + } + else + { + GtkAllocation window_allocation, child_allocation; + + if (gtk_widget_get_realized (widget)) + gdk_window_hide (priv->handle); + + window_allocation.x = allocation->x; + window_allocation.y = allocation->y; + window_allocation.width = allocation->width; + window_allocation.height = allocation->height; + child_allocation.x = child_allocation.y = 0; + child_allocation.width = allocation->width; + child_allocation.height = allocation->height; + + if (priv->child1 && gtk_widget_get_visible (priv->child1)) + { + gtk_paned_set_child_visible (paned, 0, TRUE); + if (priv->child2) + gtk_paned_set_child_visible (paned, 1, FALSE); + + gtk_paned_child_allocate (priv->child1, + priv->child1_window, + &window_allocation, + &child_allocation); + } + else if (priv->child2 && gtk_widget_get_visible (priv->child2)) + { + gtk_paned_set_child_visible (paned, 1, TRUE); + if (priv->child1) + gtk_paned_set_child_visible (paned, 0, FALSE); + + gtk_paned_child_allocate (priv->child2, + priv->child2_window, + &window_allocation, + &child_allocation); + } + else + { + if (priv->child1) + gtk_paned_set_child_visible (paned, 0, FALSE); + if (priv->child2) + gtk_paned_set_child_visible (paned, 1, FALSE); + } + } +} + +static void +get_preferred_size_for_size (GtkWidget *widget, + GtkOrientation orientation, + gint size, + gint *minimum, + gint *natural) +{ + if (orientation == GTK_ORIENTATION_HORIZONTAL) + if (size < 0) + gtk_widget_get_preferred_width (widget, minimum, natural); + else + gtk_widget_get_preferred_width_for_height (widget, size, minimum, natural); + else + if (size < 0) + gtk_widget_get_preferred_height (widget, minimum, natural); + else + gtk_widget_get_preferred_height_for_width (widget, size, minimum, natural); +} + +static void +gtk_paned_view_get_preferred_size (GtkWidget *widget, + GtkOrientation orientation, + gint size, + gint *minimum_size, + gint *natural_size) +{ + GtkPaned *paned = GTK_PANED (widget); + GtkPanedPrivate *priv = paned->priv; + gint child_min, child_nat; + gint minimum, natural; + + minimum = 0; + natural = 0; + + if (priv->child1 && gtk_widget_get_visible (priv->child1)) + { + get_preferred_size_for_size (priv->child1, orientation, size, &child_min, &child_nat); + if (priv->child1_shrink && priv->orientation == orientation) + minimum += 0; + else + minimum += child_min; + natural += child_nat; + } + + if (priv->child2 && gtk_widget_get_visible (priv->child2)) + { + get_preferred_size_for_size (priv->child2, orientation, size, &child_min, &child_nat); + + if (priv->orientation == orientation) + { + if (!priv->child2_shrink) + minimum += child_min; + natural += child_nat; + } + else + { + minimum = MAX (minimum, child_min); + natural = MAX (natural, child_nat); + } + } + + if (priv->child1 && gtk_widget_get_visible (priv->child1) && + priv->child2 && gtk_widget_get_visible (priv->child2)) + { + gint handle_size; + + gtk_widget_style_get (widget, "handle-size", &handle_size, NULL); + + if (priv->orientation == orientation) + { + minimum += handle_size; + natural += handle_size; + } + } + + if (minimum_size) + *minimum_size = minimum; + if (natural_size) + *natural_size = natural; +} + +static void +gtk_paned_view_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + gtk_paned_view_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, -1, minimum, natural); +} + +static void +gtk_paned_view_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + gtk_paned_view_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, -1, minimum, natural); +} + +static void +gtk_paned_view_get_preferred_width_for_height (GtkWidget *widget, + gint height, + gint *minimum, + gint *natural) +{ + gtk_paned_view_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, height, minimum, natural); +} + +static void +gtk_paned_view_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum, + gint *natural) +{ + gtk_paned_view_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, width, minimum, natural); +} diff --git a/src/gtk/gtkpanedview.h b/src/gtk/gtkpanedview.h new file mode 100644 index 000000000..9370b4420 --- /dev/null +++ b/src/gtk/gtkpanedview.h @@ -0,0 +1,51 @@ +/* -*-C-*- + +Copyright (C) 2013 Matthew Birkholz + +This file is part of MIT/GNU Scheme. + +MIT/GNU Scheme 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. + +MIT/GNU Scheme 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 MIT/GNU Scheme; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, +USA. + +*/ + +/* A specialized GtkPaned. See documentation of . */ + +#include + +#define GTK_TYPE_PANED_VIEW (gtk_paned_view_get_type ()) +#define GTK_PANED_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PANED_VIEW, GtkPanedView)) +#define GTK_PANED_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PANED_VIEW, GtkPanedViewClass)) +#define GTK_IS_PANED_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PANED_VIEW)) +#define GTK_IS_PANED_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PANED_VIEW)) +#define GTK_PANED_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PANED_VIEW, GtkPanedViewClass)) + + +typedef struct _GtkPanedView GtkPanedView; +typedef struct _GtkPanedViewClass GtkPanedViewClass; + +struct _GtkPanedView +{ + GtkPaned paned; +}; + +struct _GtkPanedViewClass +{ + GtkPanedClass parent_class; +}; + + +GType gtk_paned_view_get_type (void) G_GNUC_CONST; +GtkWidget* gtk_paned_view_new (GtkOrientation orientation); diff --git a/src/gtk/gtkscrolledview.c.stay b/src/gtk/gtkscrolledview.c.stay index 0967c1f36..54d718706 100644 --- a/src/gtk/gtkscrolledview.c.stay +++ b/src/gtk/gtkscrolledview.c.stay @@ -1,32 +1,30 @@ -#include "gtkscrolledview.h" +/* -*-C-*- -/** - * SECTION:gtkscrolledview - * @Short_description: Adds scrollbars to its child widget - * @Title: GtkScrolledView - * @See_also: #GtkScrollable, #GtkViewport, #GtkAdjustment - * - * #GtkScrolledView is a #GtkBin subclass: it's a container that - * accepts a single child widget (a GtkScrollable) and adds an - * optional beveled frame and scrollbars. - * - * The position of the scrollbars is controlled by the scroll - * adjustments. See #GtkAdjustment for the fields in an adjustment. - * - * #GtkScrolledView is a #GtkScrolledWindow subclass that overrides - * the geometry protocol to work as follows: - * - * A scrolled window (GtkScrolledWindow) is about squeezing an overly - * large widget into a small space and allowing the user to scroll it. - * It ignores the natural size of the problem widget, expecting a - * gtk_widget_set_size_request to override (squeeze) it. - * - * A scrolled view (GtkScrolledView) is about sticking scrollbars on a - * viewport -- a GtkScrollable. Its natural size is the natural size - * of the viewport, scrollbars and frame (with spacing). Using - * gtk_widget_set_size_request interferes with the natural sizing - * (esp. shrinking of expandable viewports). - */ +Copyright (C) 2012, 2013 Matthew Birkholz + +This file is part of MIT/GNU Scheme. + +MIT/GNU Scheme 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. + +MIT/GNU Scheme 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 MIT/GNU Scheme; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, +USA. + +*/ + +/* A specialized GtkScrolledWindow. See documentation of + . */ + +#include "gtkscrolledview.h" struct _GtkScrolledWindowPrivate { diff --git a/src/gtk/gtkscrolledview.h b/src/gtk/gtkscrolledview.h index 5508728f3..028adbc6a 100644 --- a/src/gtk/gtkscrolledview.h +++ b/src/gtk/gtkscrolledview.h @@ -1,3 +1,29 @@ +/* -*-C-*- + +Copyright (C) 2012, 2013 Matthew Birkholz + +This file is part of MIT/GNU Scheme. + +MIT/GNU Scheme 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. + +MIT/GNU Scheme 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 MIT/GNU Scheme; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, +USA. + +*/ + +/* A specialized GtkScrolledWindow. See documentation of + . */ + #include #define GTK_TYPE_SCROLLED_VIEW (gtk_scrolled_view_get_type ()) -- 2.25.1