summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redo/basicctrls_unix.go58
-rw-r--r--redo/containerctrls_unix.go9
-rw-r--r--redo/control_unix.go112
-rw-r--r--redo/sizing_unix.go55
-rw-r--r--redo/table_unix.go23
5 files changed, 133 insertions, 124 deletions
diff --git a/redo/basicctrls_unix.go b/redo/basicctrls_unix.go
index 67d844b..1271b88 100644
--- a/redo/basicctrls_unix.go
+++ b/redo/basicctrls_unix.go
@@ -16,38 +16,8 @@ import "C"
// TODOs:
// - standalone label on its own: should it be centered or not?
-type widgetbase struct {
- widget *C.GtkWidget
-}
-
-func newWidget(w *C.GtkWidget) *widgetbase {
- return &widgetbase{
- widget: w,
- }
-}
-
-// these few methods are embedded by all the various Controls since they all will do the same thing
-
-type controlParent struct {
- c *C.GtkContainer
-}
-
-func (w *widgetbase) setParent(c *controlParent) {
- C.gtk_container_add(c.c, w.widget)
- // make sure the new widget is shown
- C.gtk_widget_show_all(w.widget)
-}
-
-func (w *widgetbase) containerShow() {
- C.gtk_widget_show_all(w.widget)
-}
-
-func (w *widgetbase) containerHide() {
- C.gtk_widget_hide(w.widget)
-}
-
type button struct {
- *widgetbase
+ *controlbase
button *C.GtkButton
clicked *event
}
@@ -55,7 +25,7 @@ type button struct {
// shared code for setting up buttons, check boxes, etc.
func finishNewButton(widget *C.GtkWidget, event string, handler unsafe.Pointer) *button {
b := &button{
- widgetbase: newWidget(widget),
+ controlbase: newControl(widget),
button: (*C.GtkButton)(unsafe.Pointer(widget)),
clicked: newEvent(),
}
@@ -129,14 +99,14 @@ func (c *checkbox) SetChecked(checked bool) {
}
type textField struct {
- *widgetbase
+ *controlbase
entry *C.GtkEntry
}
func startNewTextField() *textField {
w := C.gtk_entry_new()
return &textField{
- widgetbase: newWidget(w),
+ controlbase: newControl(w),
entry: (*C.GtkEntry)(unsafe.Pointer(w)),
}
}
@@ -162,22 +132,26 @@ func (t *textField) SetText(text string) {
}
type label struct {
- *widgetbase
- misc *C.GtkMisc
- label *C.GtkLabel
- standalone bool
+ *controlbase
+ misc *C.GtkMisc
+ label *C.GtkLabel
+ standalone bool
+ supercommitResize func(c *allocation, d *sizing)
}
func finishNewLabel(text string, standalone bool) *label {
ctext := togstr(text)
defer freegstr(ctext)
widget := C.gtk_label_new(ctext)
- return &label{
- widgetbase: newWidget(widget),
+ l := &label{
+ controlbase: newControl(widget),
misc: (*C.GtkMisc)(unsafe.Pointer(widget)),
label: (*C.GtkLabel)(unsafe.Pointer(widget)),
standalone: standalone,
}
+ l.supercommitResize = l.fcommitResize
+ l.fcommitResize = l.labelcommitResize
+ return l
}
func newLabel(text string) Label {
@@ -198,7 +172,7 @@ func (l *label) SetText(text string) {
C.gtk_label_set_text(l.label, ctext)
}
-func (l *label) commitResize(c *allocation, d *sizing) {
+func (l *label) labelcommitResize(c *allocation, d *sizing) {
if !l.standalone && c.neighbor != nil {
c.neighbor.getAuxResizeInfo(d)
if d.shouldVAlignTop {
@@ -208,5 +182,5 @@ func (l *label) commitResize(c *allocation, d *sizing) {
C.gtk_misc_set_alignment(l.misc, 0, 0.5)
}
}
- l.widgetbase.commitResize(c, d)
+ l.supercommitResize(c, d)
}
diff --git a/redo/containerctrls_unix.go b/redo/containerctrls_unix.go
index 36118fe..2f2c1f2 100644
--- a/redo/containerctrls_unix.go
+++ b/redo/containerctrls_unix.go
@@ -13,7 +13,7 @@ import (
import "C"
type tab struct {
- *widgetbase
+ *controlbase
notebook *C.GtkNotebook
containers []*container
@@ -25,7 +25,7 @@ type tab struct {
func newTab() Tab {
widget := C.gtk_notebook_new()
t := &tab{
- widgetbase: newWidget(widget),
+ controlbase: newControl(widget),
notebook: (*C.GtkNotebook)(unsafe.Pointer(widget)),
}
// there are no scrolling arrows by default; add them in case there are too many tabs
@@ -58,10 +58,7 @@ func (t *tab) Append(name string, control Control) {
}
}
-func (t *tab) allocate(x int, y int, width int, height int, d *sizing) []*allocation {
- // only prepared the tabbed control; its children will be reallocated when that one is resized
- return t.widgetbase.allocate(x, y, width, height, d)
-}
+// no need to override Control.allocate() as only prepared the tabbed control; its children will be reallocated when that one is resized
//export layoutResizing
func layoutResizing(wid *C.GtkWidget, r *C.GdkRectangle, data C.gpointer) {
diff --git a/redo/control_unix.go b/redo/control_unix.go
new file mode 100644
index 0000000..a5746e7
--- /dev/null
+++ b/redo/control_unix.go
@@ -0,0 +1,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
+}
diff --git a/redo/sizing_unix.go b/redo/sizing_unix.go
index abca80d..5fa7fac 100644
--- a/redo/sizing_unix.go
+++ b/redo/sizing_unix.go
@@ -38,58 +38,3 @@ func (c *container) beginResize() (d *sizing) {
func (c *container) translateAllocationCoords(allocations []*allocation, winwidth, winheight int) {
// no need for coordinate conversion with gtk+
}
-
-func (w *widgetbase) allocate(x int, y int, width int, height int, d *sizing) []*allocation {
- return []*allocation{&allocation{
- x: x,
- y: y,
- width: width,
- height: height,
- this: w,
- }}
-}
-
-func (w *widgetbase) commitResize(c *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(c.x)
- r.y = C.int(c.y)
- r.width = C.int(c.width)
- r.height = C.int(c.height)
- C.gtk_widget_size_allocate(w.widget, &r)
-}
-
-func (w *widgetbase) getAuxResizeInfo(d *sizing) {
-//TODO
-// d.shouldVAlignTop = (s.ctype == c_listbox) || (s.ctype == c_area)
- d.shouldVAlignTop = false
-}
-
-// 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.
-
-// We don't need to worry about y-offset because label alignment is "vertically center", which GtkLabel does for us.
-
-func (w *widgetbase) preferredSize(d *sizing) (width int, height int) {
-//TODO
-/*
- if s.ctype == c_area {
- return s.areawidth, s.areaheight
- }
-*/
-
- var r C.GtkRequisition
-
- C.gtk_widget_get_preferred_size(w.widget, nil, &r)
- return int(r.width), int(r.height)
-}
diff --git a/redo/table_unix.go b/redo/table_unix.go
index 4d47405..23366f4 100644
--- a/redo/table_unix.go
+++ b/redo/table_unix.go
@@ -14,15 +14,11 @@ import (
import "C"
type table struct {
- *widgetbase
+ *scrolledcontrol
*tablebase
- treewidget *C.GtkWidget
treeview *C.GtkTreeView
- scrollc *C.GtkContainer
- scrollwindow *C.GtkScrolledWindow
-
model *C.goTableModel
modelgtk *C.GtkTreeModel
@@ -33,19 +29,11 @@ type table struct {
func finishNewTable(b *tablebase, ty reflect.Type) Table {
widget := C.gtk_tree_view_new()
- scroller := C.gtk_scrolled_window_new(nil, nil)
t := &table{
- // TODO kludge
- widgetbase: newWidget(scroller),
+ scrolledcontrol: newScrolledControl(widget, true),
tablebase: b,
- treewidget: widget,
treeview: (*C.GtkTreeView)(unsafe.Pointer(widget)),
- scrollc: (*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(t.scrollwindow, C.GTK_SHADOW_IN)
- C.gtk_container_add(t.scrollc, t.treewidget)
model := C.newTableModel(unsafe.Pointer(t))
t.model = model
t.modelgtk = (*C.GtkTreeModel)(unsafe.Pointer(model))
@@ -60,13 +48,6 @@ func finishNewTable(b *tablebase, ty reflect.Type) Table {
return t
}
-func (t *table) preferredSize(d *sizing) (width int, height int) {
- var r C.GtkRequisition
-
- C.gtk_widget_get_preferred_size(t.treewidget, nil, &r)
- return int(r.width), int(r.height)
-}
-
func (t *table) Lock() {
t.tablebase.Lock()
d := reflect.Indirect(reflect.ValueOf(t.data))