From ae774d97cc05fdcc8baf5b916be66f99f4f33a77 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Sat, 14 Mar 2009 19:14:26 -0400 Subject: [PATCH] Initial Commit --- .gitignore | 2 + Makefile | 14 +++++ aspectbin.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++ aspectbin.h | 32 +++++++++++ main.c | 28 ++++++++++ 5 files changed, 228 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 aspectbin.c create mode 100644 aspectbin.h create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..87e54c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +main +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bbfce76 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +CC = gcc -std=c99 -pedantic +WARNINGS = -Wall + +GTK_CFLAGS = $(shell pkg-config --cflags gtk+-2.0) +GTK_LIBS = $(shell pkg-config --libs gtk+-2.0) + +main: main.o aspectbin.o + $(CC) -o $@ $(GTK_LIBS) $^ + +.c.o: + $(CC) -c -o $@ $(WARNINGS) $(GTK_CFLAGS) $(CFLAGS) $< + +aspectbin.o: aspectbin.h +main.o: aspectbin.h diff --git a/aspectbin.c b/aspectbin.c new file mode 100644 index 0000000..339c8ae --- /dev/null +++ b/aspectbin.c @@ -0,0 +1,152 @@ +#include +#include "aspectbin.h" + +static void aspect_bin_size_request(GtkWidget *, GtkRequisition *); +static void aspect_bin_size_allocate(GtkWidget *, GtkAllocation *); +static void aspect_bin_remove(GtkContainer *, GtkWidget *); +static void aspect_bin_forall(GtkContainer *, gboolean, GtkCallback, gpointer); + +G_DEFINE_TYPE(AspectBin, aspect_bin, GTK_TYPE_BIN) + +static void aspect_bin_init(AspectBin *ab) +{ + ab->child = NULL; + ab->ratio = 1; +} + +static void aspect_bin_class_init(AspectBinClass *abc) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(abc); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(abc); + + widget_class->size_request = aspect_bin_size_request; + widget_class->size_allocate = aspect_bin_size_allocate; + + container_class->remove = aspect_bin_remove; + container_class->forall = aspect_bin_forall; +} + +GtkWidget *aspect_bin_new(void) +{ + return GTK_WIDGET(g_object_new(ASPECT_BIN_TYPE, NULL)); +} + +static void aspect_bin_remove(GtkContainer *container, GtkWidget *child) +{ + AspectBin *abin = ASPECT_BIN(container); + + if (abin->child == child) { + aspect_bin_set_body_widget(abin, NULL, 1); + } else { + GTK_CONTAINER_CLASS(aspect_bin_parent_class)->remove + (container, child); + } +} + +static void aspect_bin_forall(GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + AspectBin *abin = ASPECT_BIN(container); + GtkBin *bin = GTK_BIN(container); + + if (bin->child) + callback(bin->child, callback_data); + + if (abin->child) + callback(abin->child, callback_data); +} + +static void +aspect_bin_size_request(GtkWidget *widget, GtkRequisition *requisition) +{ + AspectBin *abin = ASPECT_BIN(widget); + GtkBin *bin = GTK_BIN(widget); + GtkRequisition creq = {0}, areq = {0}; + + if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) { + gtk_widget_size_request(bin->child, &creq); + } + + if (abin->child && GTK_WIDGET_VISIBLE(abin->child)) { + int wtmp, htmp; + gtk_widget_size_request(abin->child, &areq); + wtmp = areq.height * abin->ratio + 0.5; + htmp = areq.width / abin->ratio + 0.5; + + if (wtmp > areq.width) { + areq.width = wtmp; + } else { + areq.height = htmp; + } + } + + requisition->width = areq.width + creq.width; + requisition->height = MAX(areq.height, creq.height); +} + +static void +aspect_bin_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + AspectBin *abin = ASPECT_BIN(widget); + GtkBin *bin = GTK_BIN(widget); + GtkRequisition creq = {0}; + GtkAllocation csize = {0}, asize = {0}; + + if (abin->child && GTK_WIDGET_VISIBLE(abin->child)) { + asize.height = allocation->height; + asize.width = asize.height * abin->ratio + 0.5; + + if (asize.width > allocation->width) { + asize.width = allocation->width; + asize.height = asize.width / abin->ratio + 0.5; + } + } + + if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) { + gtk_widget_get_child_requisition(bin->child, &creq); + + if (allocation->width - asize.width < creq.width) { + asize.width = allocation->width - creq.width; + asize.height = asize.width / abin->ratio + 0.5; + } + + csize.width = allocation->width - asize.width; + csize.height = allocation->height; + csize.x = asize.width; + csize.y = 0; + } + + if (bin->child) + gtk_widget_size_allocate(bin->child, &csize); + if (abin->child) + gtk_widget_size_allocate(abin->child, &asize); +} + +void +aspect_bin_set_body_widget(AspectBin *ab, GtkWidget *widget, gfloat ratio) +{ + gboolean need_resize = FALSE; + + g_return_if_fail(IS_ASPECT_BIN(ab)); + g_return_if_fail(widget == NULL || GTK_IS_WIDGET(widget)); + g_return_if_fail(widget == NULL || widget->parent == NULL); + + if (ab->child == widget) + return; + + if (ab->child) { + need_resize |= GTK_WIDGET_VISIBLE(ab->child); + gtk_widget_unparent(ab->child); + } + + ab->child = widget; + if (widget) { + gtk_widget_set_parent(widget, GTK_WIDGET(ab)); + need_resize |= GTK_WIDGET_VISIBLE(widget); + } + + if (GTK_WIDGET_VISIBLE(ab) && need_resize) + gtk_widget_queue_resize(GTK_WIDGET(ab)); +} diff --git a/aspectbin.h b/aspectbin.h new file mode 100644 index 0000000..bca5ba7 --- /dev/null +++ b/aspectbin.h @@ -0,0 +1,32 @@ +#ifndef ASPECTBIN_H_ +#define ASPECTBIN_H_ + +#include + +#define ASPECT_BIN_TYPE (aspect_bin_get_type()) +#define ASPECT_BIN(obj) GTK_CHECK_CAST((obj), ASPECT_BIN_TYPE, AspectBin) +#define ASPECT_BIN_CLASS(class) \ + GTK_CHECK_CLASS_CAST((class), ASPECT_BIN_TYPE, AspectBinClass) +#define IS_ASPECT_BIN(obj) GTK_CHECK_TYPE((obj), ASPECT_BIN_TYPE) +#define IS_ASPECT_BIN_CLASS(class) \ + GTK_CHECK_CLASS_TYPE((class), ASPECT_BIN_TYPE, AspectBinClass) + +typedef struct AspectBin AspectBin; +typedef struct AspectBinClass AspectBinClass; + +struct AspectBin { + GtkBin bin; + + GtkWidget *child; + gfloat ratio; +}; + +struct AspectBinClass { + GtkBinClass parent_class; +}; + +GType aspect_bin_get_type(void); +GtkWidget *aspect_bin_new(void); +void aspect_bin_set_body_widget(AspectBin *, GtkWidget *, gfloat); + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..72b4d97 --- /dev/null +++ b/main.c @@ -0,0 +1,28 @@ +#include +#include "aspectbin.h" + +int main(int argc, char **argv) +{ + GtkWidget *window; + GtkWidget *aspectbin; + GtkWidget *button1, *button2; + + gtk_init(&argc, &argv); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "Blargh"); + gtk_window_set_default_size(GTK_WINDOW(window), 400, 300); + + aspectbin = aspect_bin_new(); + button1 = gtk_button_new_with_label("Square"); + button2 = gtk_button_new_with_label("Rectangle"); + aspect_bin_set_body_widget(ASPECT_BIN(aspectbin), button1, 1); + gtk_container_add(GTK_CONTAINER(aspectbin), button2); + + gtk_container_add(GTK_CONTAINER(window), aspectbin); + + gtk_widget_show_all(window); + gtk_main(); + + return 0; +} -- 2.43.0