summaryrefslogtreecommitdiff
path: root/redo/control_unix.go
blob: a5746e76425101316afe8246831714a9aed24026 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// +build !windows,!darwin

// 30 july 2014

package ui

import (
	"unsafe"
)

// #include "gtk_unix.h"
import "C"

type controlbase struct {
	*controldefs
	widget		*C.GtkWidget
}

type controlParent struct {
	c	*C.GtkContainer
}

func newControl(widget *C.GtkWidget) *controlbase {
	c := new(controlbase)
	c.widget = widget
	c.controldefs = new(controldefs)
	c.fsetParent = func(p *controlParent) {
		C.gtk_container_add(p.c, c.widget)
		// make sure the new widget is shown if not explicitly hidden
		c.containerShow()
	}
	c.fcontainerShow = func() {
		C.gtk_widget_show_all(c.widget)
	}
	c.fcontainerHide = func() {
		C.gtk_widget_hide(c.widget)
	}
	c.fallocate = func(x int, y int, width int, height int, d *sizing) []*allocation {
		// TODO split into its own function
		return []*allocation{&allocation{
			x:		x,
			y:		y,
			width:	width,
			height:	height,
			this:		c,
		}}
	}
	c.fpreferredSize = func(d *sizing) (int, int) {
		// GTK+ 3 makes this easy: controls can tell us what their preferred size is!
		// ...actually, it tells us two things: the "minimum size" and the "natural size".
		// The "minimum size" is the smallest size we /can/ display /anything/. The "natural size" is the smallest size we would /prefer/ to display.
		// The difference? Minimum size takes into account things like truncation with ellipses: the minimum size of a label can allot just the ellipses!
		// So we use the natural size instead.
		// There is a warning about height-for-width controls, but in my tests this isn't an issue.
		// For Areas, we manually save the Area size and use that, just to be safe.

//TODO
/*
		if s.ctype == c_area {
			return s.areawidth, s.areaheight
		}
*/

		var r C.GtkRequisition

		C.gtk_widget_get_preferred_size(c.widget, nil, &r)
		return int(r.width), int(r.height)
	}
	c.fcommitResize = func(a *allocation, d *sizing) {
		// as we resize on size-allocate, we have to also use size-allocate on our children
		// this is fine anyway; in fact, this allows us to move without knowing what the container is!
		// this is what GtkBox does anyway
		// thanks to tristan in irc.gimp.net/#gtk+

		var r C.GtkAllocation

		r.x = C.int(a.x)
		r.y = C.int(a.y)
		r.width = C.int(a.width)
		r.height = C.int(a.height)
		C.gtk_widget_size_allocate(c.widget, &r)
	}
	c.fgetAuxResizeInfo = func(d *sizing) {
//TODO
//		d.shouldVAlignTop = (s.ctype == c_listbox) || (s.ctype == c_area)
		d.shouldVAlignTop = false
	}
	return c
}

type scrolledcontrol struct {
	*controlbase
	scroller			*controlbase
	scrollcontainer		*C.GtkContainer
	scrollwindow		*C.GtkScrolledWindow
}

func newScrolledControl(widget *C.GtkWidget, native bool) *scrolledcontrol {
	scroller := C.gtk_scrolled_window_new(nil, nil)
	s := &scrolledcontrol{
		controlbase:		newControl(widget),
		scroller:			newControl(scroller),
		scrollcontainer:	(*C.GtkContainer)(unsafe.Pointer(scroller)),
		scrollwindow:		(*C.GtkScrolledWindow)(unsafe.Pointer(scroller)),
	}
	// give the scrolled window a border (thanks to jlindgren in irc.gimp.net/#gtk+)
	C.gtk_scrolled_window_set_shadow_type(s.scrollwindow, C.GTK_SHADOW_IN)
	C.gtk_container_add(s.scrollcontainer, s.widget)
	s.fsetParent = s.scroller.fsetParent
	s.fcommitResize = s.scroller.fcommitResize
	return s
}