561eba2a |
1 | #include <gtk/gtk.h> |
2 | |
3 | #include "gtkcustom.h" |
4 | //#include "gtkintl.h" |
5 | |
6 | static void gtk_custom_class_init (GtkCustomClass *klass); |
7 | static void gtk_custom_init (GtkCustom *custom); |
8 | |
9 | |
10 | static void gtk_custom_size_request (GtkWidget *widget, |
11 | GtkRequisition *requisition); |
12 | static void gtk_custom_size_allocate (GtkWidget *widget, |
13 | GtkAllocation *allocation); |
14 | |
15 | GType |
16 | gtk_custom_get_type (void) |
17 | { |
18 | static GType custom_type = 0; |
19 | |
20 | if (!custom_type) |
21 | { |
22 | static const GTypeInfo custom_info = |
23 | { |
24 | sizeof (GtkCustomClass), |
25 | NULL, /* base_init */ |
26 | NULL, /* base_finalize */ |
27 | (GClassInitFunc) gtk_custom_class_init, |
28 | NULL, /* class_finalize */ |
29 | NULL, /* class_data */ |
30 | sizeof (GtkCustom), |
31 | 0, /* n_preallocs */ |
32 | (GInstanceInitFunc) gtk_custom_init, |
33 | NULL, /* value_table */ |
34 | }; |
35 | |
36 | custom_type = g_type_register_static (GTK_TYPE_PANED, "GtkCustom", |
37 | &custom_info, 0); |
38 | } |
39 | |
40 | return custom_type; |
41 | } |
42 | |
43 | static void |
44 | gtk_custom_class_init (GtkCustomClass *class) |
45 | { |
46 | GtkWidgetClass *widget_class; |
47 | |
48 | widget_class = (GtkWidgetClass *) class; |
49 | |
50 | widget_class->size_request = gtk_custom_size_request; |
51 | widget_class->size_allocate = gtk_custom_size_allocate; |
52 | } |
53 | |
54 | static void |
55 | gtk_custom_init (GtkCustom *custom) |
56 | { |
57 | GtkWidget * button; |
58 | |
59 | GTK_WIDGET_SET_FLAGS (custom, GTK_NO_WINDOW); |
60 | gtk_widget_set_redraw_on_allocate (GTK_WIDGET (custom), FALSE); |
61 | |
62 | custom->firstPane = NULL; |
63 | custom->lastPane = NULL; |
64 | custom->focusedPane = NULL; |
65 | custom->numChildren = 0; |
66 | |
67 | custom->vbox = NULL; |
68 | // custom->scrollWindow = NULL; |
69 | // custom->viewport = NULL; |
70 | custom->hScrollbar = NULL; |
71 | } |
72 | |
73 | |
74 | GtkWidget* gtk_custom_new () |
75 | { |
76 | return GTK_WIDGET (g_object_new (gtk_custom_get_type (), NULL)); |
77 | } |
78 | |
79 | |
80 | void gtk_custom_set_focus (GtkWidget * widget, gpointer user_data) |
81 | { |
82 | GtkCustom * custom = (GtkCustom*) widget; |
83 | GtkPaned * pane; |
84 | if(!custom->firstPane) return; |
85 | |
86 | |
87 | pane = custom->firstPane; |
88 | while(1){ |
89 | if((GtkWidget*)pane == (GtkWidget*)user_data){ |
90 | custom->focusedPane = pane; |
91 | break; |
92 | } |
93 | if(pane == custom->lastPane){ |
94 | custom->focusedPane = NULL; |
95 | break; |
96 | } |
97 | pane = (GtkPaned*)pane->child1; |
98 | } |
99 | } |
100 | |
101 | void gtk_custom_widget_add(GtkCustom * custom, GtkWidget * widget1) |
102 | { |
103 | GtkPaned * tmpPane; |
104 | GtkWidget * w; |
105 | |
106 | g_return_if_fail(GTK_IS_CUSTOM(custom)); |
107 | g_object_ref(G_OBJECT(widget1)); |
108 | |
109 | |
110 | if(!custom->firstPane){ |
111 | custom->firstPane = (GtkPaned *)gtk_vpaned_new(); |
112 | custom->lastPane = custom->firstPane; |
113 | |
114 | custom->hScrollbar = gtk_hscrollbar_new (NULL); |
115 | gtk_widget_show(custom->hScrollbar); |
116 | |
117 | custom->vbox = gtk_vbox_new(FALSE,0); |
118 | gtk_widget_show(custom->vbox); |
119 | |
120 | // custom->viewport = gtk_viewport_new (NULL,NULL); |
121 | // gtk_widget_show(custom->viewport); |
122 | |
123 | // gtk_container_add(GTK_CONTAINER(custom->viewport), (GtkWidget*)custom->vbox); |
124 | gtk_box_pack_end(GTK_BOX(custom->vbox),(GtkWidget*)custom->hScrollbar,FALSE,FALSE,0); |
125 | gtk_box_pack_end(GTK_BOX(custom->vbox),(GtkWidget*)custom->firstPane,TRUE,TRUE,0); |
126 | |
127 | // custom->scrollWindow = gtk_scrolled_window_new (NULL, NULL); |
128 | // gtk_widget_show(custom->scrollWindow); |
129 | // gtk_container_add (GTK_CONTAINER (custom->scrollWindow), (GtkWidget*)custom->viewport); |
130 | // gtk_paned_pack1(GTK_PANED(custom), (GtkWidget*)custom->scrollWindow,FALSE, TRUE); |
131 | |
132 | gtk_paned_pack1(GTK_PANED(custom), (GtkWidget*)custom->vbox,FALSE, TRUE); |
133 | }else{ |
134 | tmpPane = custom->lastPane; |
135 | custom->lastPane = (GtkPaned *)gtk_vpaned_new(); |
136 | gtk_paned_pack1 (tmpPane,(GtkWidget*)custom->lastPane, FALSE,TRUE); |
137 | } |
138 | gtk_widget_show((GtkWidget *)custom->lastPane); |
139 | |
140 | gtk_paned_pack2 (custom->lastPane,widget1, TRUE, TRUE); |
141 | custom->focusedPane = custom->lastPane; |
142 | custom->numChildren++; |
143 | |
144 | } |
145 | |
146 | void gtk_custom_widget_delete(GtkCustom * custom) |
147 | { |
148 | GtkPaned * tmp, *prev, *next; |
149 | |
150 | if(!custom->focusedPane) return; |
151 | |
152 | tmp = (GtkPaned*)custom->focusedPane->child2; //widget in vpaned |
153 | g_object_unref(G_OBJECT(tmp)); |
154 | |
155 | if(custom->focusedPane == custom->firstPane && |
156 | custom->focusedPane == custom->lastPane){ |
157 | // gtk_container_remove(GTK_CONTAINER(custom),(GtkWidget*)custom->scrollWindow); |
158 | gtk_container_remove(GTK_CONTAINER(custom),(GtkWidget*)custom->vbox); |
159 | custom->firstPane = NULL; |
160 | custom->lastPane = NULL; |
161 | custom->focusedPane = NULL; |
162 | }else if(custom->focusedPane == custom->firstPane && |
163 | custom->focusedPane != custom->lastPane){ |
164 | next = (GtkPaned*)custom->firstPane->child1; |
165 | g_object_ref(G_OBJECT(next)); |
166 | gtk_container_remove(GTK_CONTAINER(custom->firstPane),(GtkWidget*)next); |
167 | gtk_container_remove(GTK_CONTAINER(custom->vbox),(GtkWidget*)custom->firstPane); |
168 | custom->firstPane = next; |
169 | gtk_box_pack_end(GTK_BOX(custom->vbox),(GtkWidget*)custom->firstPane,TRUE,TRUE,0); |
170 | custom->focusedPane = custom->firstPane; |
171 | g_object_unref(G_OBJECT(next)); |
172 | }else if(custom->focusedPane != custom->firstPane && |
173 | custom->focusedPane == custom->lastPane){ |
174 | tmp = custom->lastPane; |
175 | custom->lastPane = (GtkPaned*)gtk_widget_get_parent((GtkWidget*)custom->lastPane); |
176 | custom->focusedPane = custom->lastPane; |
177 | gtk_container_remove(GTK_CONTAINER(custom->lastPane),(GtkWidget*)tmp); |
178 | }else{ |
179 | tmp = custom->focusedPane; |
180 | prev = (GtkPaned*)gtk_widget_get_parent((GtkWidget*)tmp); |
181 | next = (GtkPaned*)tmp->child1; |
182 | g_object_ref(G_OBJECT(next)); |
183 | gtk_container_remove(GTK_CONTAINER(custom->focusedPane),(GtkWidget*)next); |
184 | gtk_container_remove(GTK_CONTAINER(prev),(GtkWidget*)custom->focusedPane); |
185 | gtk_paned_pack1(prev, (GtkWidget*)next, FALSE, TRUE); |
186 | custom->focusedPane = next; |
187 | g_object_unref(G_OBJECT(next)); |
188 | } |
189 | |
190 | custom->numChildren--; |
191 | } |
192 | |
193 | |
194 | void gtk_custom_widget_move_up(GtkCustom * custom) |
195 | { |
196 | GtkWidget* upWidget, *downWidget; |
197 | GtkPaned * prev,*next, *prevPrev; |
198 | |
199 | if(custom->lastPane == custom->focusedPane) return; |
200 | |
201 | // move VPane |
202 | prev = (GtkPaned*)custom->focusedPane->child1; |
203 | g_object_ref(G_OBJECT(prev)); |
204 | gtk_container_remove(GTK_CONTAINER(custom->focusedPane),(GtkWidget*)prev); |
205 | |
206 | if(prev == custom->lastPane){ |
207 | prevPrev = NULL; |
208 | custom->lastPane = custom->focusedPane; |
209 | }else{ |
210 | prevPrev = (GtkPaned*)prev->child1; |
211 | g_object_ref(G_OBJECT(prevPrev)); |
212 | gtk_container_remove(GTK_CONTAINER(prev),(GtkWidget*)prevPrev); |
213 | } |
214 | |
215 | g_object_ref(G_OBJECT(custom->focusedPane)); |
216 | if(custom->firstPane == custom->focusedPane){ |
217 | gtk_container_remove(GTK_CONTAINER(custom->vbox),(GtkWidget*)custom->focusedPane); |
218 | gtk_box_pack_end(GTK_BOX(custom->vbox),(GtkWidget*)prev,TRUE,TRUE,0); |
219 | custom->firstPane = prev; |
220 | }else{ |
221 | next = (GtkPaned*)gtk_widget_get_parent((GtkWidget*)custom->focusedPane); |
222 | gtk_container_remove(GTK_CONTAINER(next),(GtkWidget*)custom->focusedPane); |
223 | gtk_paned_pack1(GTK_PANED(next), (GtkWidget*)prev, FALSE,TRUE); |
224 | } |
225 | gtk_paned_pack1(GTK_PANED(prev),(GtkWidget*)custom->focusedPane, FALSE,TRUE); |
226 | if(prevPrev) |
227 | gtk_paned_pack1(GTK_PANED(custom->focusedPane),(GtkWidget*)prevPrev, FALSE,TRUE); |
228 | |
229 | g_object_unref(G_OBJECT(prev)); |
230 | if(prevPrev) g_object_unref(G_OBJECT(prevPrev)); |
231 | g_object_unref(G_OBJECT(custom->focusedPane)); |
232 | } |
233 | |
234 | |
235 | void gtk_custom_widget_move_down(GtkCustom * custom) |
236 | { |
237 | GtkWidget* upWidget, *downWidget; |
238 | GtkPaned * prev,*next, *nextNext; |
239 | |
240 | if(custom->firstPane == custom->focusedPane) return; |
241 | |
242 | //move VPane |
243 | next = (GtkPaned*)gtk_widget_get_parent((GtkWidget*)custom->focusedPane); |
244 | g_object_ref(G_OBJECT(next)); |
245 | |
246 | if(custom->lastPane == custom->focusedPane){ |
247 | prev = NULL; |
248 | custom->lastPane = next; |
249 | }else{ |
250 | prev = (GtkPaned*)custom->focusedPane->child1; |
251 | g_object_ref(G_OBJECT(prev)); |
252 | gtk_container_remove(GTK_CONTAINER(custom->focusedPane),(GtkWidget*)prev); |
253 | } |
254 | |
255 | g_object_ref(G_OBJECT(custom->focusedPane)); |
256 | gtk_container_remove(GTK_CONTAINER(next),(GtkWidget*)custom->focusedPane); |
257 | |
258 | if(next == custom->firstPane){ |
259 | custom->firstPane = custom->focusedPane; |
260 | gtk_container_remove(GTK_CONTAINER(custom->vbox),(GtkWidget*)next); |
261 | gtk_box_pack_end(GTK_BOX(custom->vbox),(GtkWidget*)custom->focusedPane,TRUE,TRUE,0); |
262 | }else{ |
263 | nextNext = (GtkPaned*)gtk_widget_get_parent((GtkWidget*)next); |
264 | gtk_container_remove(GTK_CONTAINER(nextNext),(GtkWidget*)next); |
265 | gtk_paned_pack1(nextNext, (GtkWidget*)custom->focusedPane, FALSE, TRUE); |
266 | } |
267 | gtk_paned_pack1(custom->focusedPane,(GtkWidget*)next, FALSE,TRUE); |
268 | if(prev) |
269 | gtk_paned_pack1(next,(GtkWidget*)prev, FALSE,TRUE); |
270 | |
271 | if(prev)g_object_unref(G_OBJECT(prev)); |
272 | g_object_unref(G_OBJECT(next)); |
273 | g_object_unref(G_OBJECT(custom->focusedPane)); |
274 | } |
275 | |
276 | |
277 | static void |
278 | gtk_custom_size_request (GtkWidget *widget, |
279 | GtkRequisition *requisition) |
280 | { |
281 | GtkPaned *paned = GTK_PANED (widget); |
282 | GtkRequisition child_requisition; |
283 | |
284 | requisition->width = 0; |
285 | requisition->height = 0; |
286 | |
287 | if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1)) |
288 | { |
289 | gtk_widget_size_request (paned->child1, &child_requisition); |
290 | |
291 | requisition->height = child_requisition.height; |
292 | requisition->width = child_requisition.width; |
293 | } |
294 | |
295 | if (paned->child2 && GTK_WIDGET_VISIBLE (paned->child2)) |
296 | { |
297 | gtk_widget_size_request (paned->child2, &child_requisition); |
298 | |
299 | requisition->width = MAX (requisition->width, child_requisition.width); |
300 | requisition->height += child_requisition.height; |
301 | } |
302 | |
303 | requisition->height += GTK_CONTAINER (paned)->border_width * 2; |
304 | requisition->width += GTK_CONTAINER (paned)->border_width * 2; |
305 | |
306 | if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1) && |
307 | paned->child2 && GTK_WIDGET_VISIBLE (paned->child2)) |
308 | { |
309 | gint handle_size; |
310 | |
311 | gtk_widget_style_get (widget, "handle_size", &handle_size, NULL); |
312 | requisition->height += handle_size; |
313 | } |
314 | |
315 | } |
316 | |
317 | static void |
318 | gtk_custom_size_allocate (GtkWidget *widget, |
319 | GtkAllocation *allocation) |
320 | { |
321 | GtkPaned *paned = GTK_PANED (widget); |
322 | gint border_width = GTK_CONTAINER (paned)->border_width; |
323 | |
324 | widget->allocation = *allocation; |
325 | |
326 | if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1) && |
327 | paned->child2 && GTK_WIDGET_VISIBLE (paned->child2)) |
328 | { |
329 | GtkRequisition child1_requisition; |
330 | GtkRequisition child2_requisition; |
331 | GtkAllocation child1_allocation; |
332 | GtkAllocation child2_allocation; |
333 | gint handle_size; |
334 | |
335 | gtk_widget_style_get (widget, "handle_size", &handle_size, NULL); |
336 | |
337 | gtk_widget_get_child_requisition (paned->child1, &child1_requisition); |
338 | gtk_widget_get_child_requisition (paned->child2, &child2_requisition); |
339 | |
340 | gtk_paned_compute_position (paned, |
341 | MAX (1, widget->allocation.height |
342 | - handle_size |
343 | - 2 * border_width), |
344 | child1_requisition.height, |
345 | child2_requisition.height); |
346 | |
347 | paned->handle_pos.x = widget->allocation.x + border_width; |
348 | paned->handle_pos.y = widget->allocation.y + paned->child1_size + border_width; |
349 | paned->handle_pos.width = MAX (1, (gint) widget->allocation.width - 2 * border_width); |
350 | paned->handle_pos.height = handle_size; |
351 | |
352 | if (GTK_WIDGET_REALIZED (widget)) |
353 | { |
354 | if (GTK_WIDGET_MAPPED (widget)) |
355 | gdk_window_show (paned->handle); |
356 | gdk_window_move_resize (paned->handle, |
357 | paned->handle_pos.x, |
358 | paned->handle_pos.y, |
359 | paned->handle_pos.width, |
360 | handle_size); |
361 | } |
362 | |
363 | child1_allocation.width = child2_allocation.width = MAX (1, (gint) allocation->width - border_width * 2); |
364 | child1_allocation.height = MAX (1, paned->child1_size); |
365 | child1_allocation.x = child2_allocation.x = widget->allocation.x + border_width; |
366 | child1_allocation.y = widget->allocation.y + border_width; |
367 | |
368 | child2_allocation.y = child1_allocation.y + paned->child1_size + paned->handle_pos.height; |
369 | child2_allocation.height = MAX (1, widget->allocation.y + widget->allocation.height - child2_allocation.y - border_width); |
370 | |
371 | if (GTK_WIDGET_MAPPED (widget) && |
372 | paned->child1->allocation.height < child1_allocation.height) |
373 | { |
374 | gtk_widget_size_allocate (paned->child2, &child2_allocation); |
375 | gtk_widget_size_allocate (paned->child1, &child1_allocation); |
376 | } |
377 | else |
378 | { |
379 | gtk_widget_size_allocate (paned->child1, &child1_allocation); |
380 | gtk_widget_size_allocate (paned->child2, &child2_allocation); |
381 | } |
382 | } |
383 | else |
384 | { |
385 | GtkAllocation child_allocation; |
386 | |
387 | if (GTK_WIDGET_REALIZED (widget)) |
388 | gdk_window_hide (paned->handle); |
389 | |
390 | if (paned->child1) |
391 | gtk_widget_set_child_visible (paned->child1, TRUE); |
392 | if (paned->child2) |
393 | gtk_widget_set_child_visible (paned->child2, TRUE); |
394 | |
395 | child_allocation.x = widget->allocation.x + border_width; |
396 | child_allocation.y = widget->allocation.y + border_width; |
397 | child_allocation.width = MAX (1, allocation->width - 2 * border_width); |
398 | child_allocation.height = MAX (1, allocation->height - 2 * border_width); |
399 | |
400 | if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1)) |
401 | gtk_widget_size_allocate (paned->child1, &child_allocation); |
402 | else if (paned->child2 && GTK_WIDGET_VISIBLE (paned->child2)) |
403 | gtk_widget_size_allocate (paned->child2, &child_allocation); |
404 | } |
405 | } |
406 | |