libyui-gtk  2.44.5
ygtkfixed.c
1 /********************************************************************
2  * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
3  ********************************************************************/
4 
5 /* YGtkFixed container */
6 // check the header file for information about this container
7 
8 #include <yui/Libyui_config.h>
9 #include <math.h>
10 #include <gtk/gtk.h>
11 #include "ygtkfixed.h"
12 
13 G_DEFINE_TYPE (YGtkFixed, ygtk_fixed, GTK_TYPE_CONTAINER)
14 
15 static void ygtk_fixed_init (YGtkFixed *fixed)
16 {
17  gtk_widget_set_has_window(GTK_WIDGET(fixed), FALSE);
18  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (fixed), FALSE);
19 }
20 
21 void ygtk_fixed_setup (YGtkFixed *fixed, YGtkPreferredWidth cb1, YGtkPreferredHeight cb2, YGtkSetSize cb3, gpointer data)
22 {
23  fixed->preferred_width_cb = cb1;
24  fixed->preferred_height_cb = cb2;
25  fixed->set_size_cb = cb3;
26  fixed->data = data;
27 }
28 
29 static YGtkFixedChild *ygtk_fixed_get_child (YGtkFixed *fixed, GtkWidget *widget)
30 {
31  GSList *i;
32  for (i = fixed->children; i; i = i->next) {
33  YGtkFixedChild *child = i->data;
34  if (child->widget == widget)
35  return child;
36  }
37  g_warning ("YGtkFixed: could not find child.");
38  return NULL;
39 }
40 
41 void ygtk_fixed_set_child_pos (YGtkFixed *fixed, GtkWidget *widget, gint x, gint y)
42 {
43  YGtkFixedChild *child = ygtk_fixed_get_child (fixed, widget);
44  child->x = x;
45  child->y = y;
46 }
47 
48 void ygtk_fixed_set_child_size (YGtkFixed *fixed, GtkWidget *widget, gint width, gint height)
49 {
50  YGtkFixedChild *child = ygtk_fixed_get_child (fixed, widget);
51  child->width = width;
52  child->height = height;
53 }
54 
55 static void ygtk_fixed_add (GtkContainer *container, GtkWidget *widget)
56 {
57  YGtkFixed *fixed = YGTK_FIXED (container);
58  YGtkFixedChild *child = g_new0 (YGtkFixedChild, 1);
59  child->widget = widget;
60  child->width = child->height = 50;
61  fixed->children = g_slist_append (fixed->children, child);
62  gtk_widget_set_parent (widget, GTK_WIDGET (fixed));
63 }
64 
65 static void ygtk_fixed_remove (GtkContainer *container, GtkWidget *widget)
66 {
67  YGtkFixed *fixed = YGTK_FIXED (container);
68  GSList *i;
69  for (i = fixed->children; i; i = i->next) {
70  YGtkFixedChild *child = i->data;
71  if (child->widget == widget) {
72  gboolean was_visible = gtk_widget_get_visible (widget);
73  gtk_widget_unparent (widget);
74  fixed->children = g_slist_delete_link (fixed->children, i);
75  g_free (child);
76  if (was_visible)
77  gtk_widget_queue_resize (GTK_WIDGET (container));
78  break;
79  }
80  }
81 }
82 
83 static void ygtk_fixed_forall (GtkContainer *container, gboolean include_internals,
84  GtkCallback callback, gpointer callback_data)
85 {
86  g_return_if_fail (callback != NULL);
87  YGtkFixed *fixed = YGTK_FIXED (container);
88  GSList *i = fixed->children;
89  while (i) {
90  YGtkFixedChild *child = i->data;
91  i = i->next; // current node might get removed...
92  (* callback) (child->widget, callback_data);
93  }
94 }
95 
96 static void
97 ygtk_fixed_get_preferred_width (GtkWidget *widget,
98  gint *minimum_width,
99  gint *natural_width)
100 {
101  YGtkFixed *fixed = YGTK_FIXED (widget);
102  *natural_width = *minimum_width =
103  fixed->preferred_width_cb (fixed, fixed->data);
104 }
105 
106 static void
107 ygtk_fixed_get_preferred_height (GtkWidget *widget,
108  gint *minimum_height,
109  gint *natural_height)
110 {
111  YGtkFixed *fixed = YGTK_FIXED (widget);
112  *natural_height = *minimum_height =
113  fixed->preferred_height_cb (fixed, fixed->data);
114 }
115 
116 static void ygtk_fixed_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
117 {
118  YGtkFixed *fixed = YGTK_FIXED (widget);
119  fixed->set_size_cb (fixed, allocation->width, allocation->height, fixed->data);
120 
121  GSList *i;
122  for (i = fixed->children; i; i = i->next) {
123  YGtkFixedChild *child = i->data;
124  int x = child->x;
125  if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL)
126  x = allocation->width - (child->x + child->width);
127  x += allocation->x;
128  int y = child->y + allocation->y;
129  GtkAllocation child_alloc =
130  { x, y, MAX (child->width, 1), MAX (child->height, 1) };
131  gtk_widget_size_allocate (child->widget, &child_alloc);
132  }
133  GTK_WIDGET_CLASS (ygtk_fixed_parent_class)->size_allocate (widget, allocation);
134 }
135 
136 static GType ygtk_fixed_child_type (GtkContainer *container)
137 { return GTK_TYPE_WIDGET; }
138 
139 static void ygtk_fixed_class_init (YGtkFixedClass *klass)
140 {
141  ygtk_fixed_parent_class = g_type_class_peek_parent (klass);
142 
143  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
144  container_class->add = ygtk_fixed_add;
145  container_class->remove = ygtk_fixed_remove;
146  container_class->forall = ygtk_fixed_forall;
147  container_class->child_type = ygtk_fixed_child_type;
148 
149  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
150  widget_class->get_preferred_width = ygtk_fixed_get_preferred_width;
151  widget_class->get_preferred_height = ygtk_fixed_get_preferred_height;
152  widget_class->size_allocate = ygtk_fixed_size_allocate;
153 }
154