]> git.draconx.ca Git - aspectbin.git/commitdiff
Initial Commit
authorNick Bowler <nbowler@draconx.ca>
Sat, 14 Mar 2009 23:14:26 +0000 (19:14 -0400)
committerNick Bowler <nbowler@draconx.ca>
Sat, 14 Mar 2009 23:15:02 +0000 (19:15 -0400)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
aspectbin.c [new file with mode: 0644]
aspectbin.h [new file with mode: 0644]
main.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..87e54c2
--- /dev/null
@@ -0,0 +1,2 @@
+main
+*.o
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..339c8ae
--- /dev/null
@@ -0,0 +1,152 @@
+#include <stdio.h>
+#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 (file)
index 0000000..bca5ba7
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef ASPECTBIN_H_
+#define ASPECTBIN_H_
+
+#include <gtk/gtk.h>
+
+#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 (file)
index 0000000..72b4d97
--- /dev/null
+++ b/main.c
@@ -0,0 +1,28 @@
+#include <gtk/gtk.h>
+#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;
+}