From a41f58286646057d1c022e260662944efd7b85ce Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 23 Mar 2014 20:54:11 -0400 Subject: [PATCH] Added Area resizing. Everything mostly works, but not making things smaller... --- area.go | 37 ++++++++++++++++++++++++++++--------- area_unix.go | 2 +- gtkcalls_unix.go | 4 ++++ sysdata.go | 3 +++ sysdata_unix.go | 12 ++++++++++++ test/main.go | 24 ++++++++++++++++++++++-- 6 files changed, 70 insertions(+), 12 deletions(-) diff --git a/area.go b/area.go index 8ebfa0e..73453c8 100644 --- a/area.go +++ b/area.go @@ -21,12 +21,14 @@ import ( // in platform-native ways is painful. // [Use TextArea instead, providing a TextAreaHandler.] // -// To facilitate development and debugging, for the time being, Areas have a fixed size of 320x240 and only work on GTK+. +// To facilitate development and debugging, for the time being, Areas only work on GTK+. type Area struct { - lock sync.Mutex - created bool - sysData *sysData - handler AreaHandler + lock sync.Mutex + created bool + sysData *sysData + handler AreaHandler + initwidth int + initheight int } // AreaHandler represents the events that an Area should respond to. @@ -210,18 +212,34 @@ const ( // TODO add Super ) -// NewArea creates a new Area. +// NewArea creates a new Area with the given size and handler. // It panics if handler is nil. -func NewArea(handler AreaHandler) *Area { +func NewArea(width int, height int, handler AreaHandler) *Area { if handler == nil { panic("handler passed to NewArea() must not be nil") } return &Area{ - sysData: mksysdata(c_area), - handler: handler, + sysData: mksysdata(c_area), + handler: handler, + initwidth: width, + initheight: height, } } +// SetSize sets the Area's internal drawing size. +// It has no effect on the actual control size. +func (a *Area) SetSize(width int, height int) { + a.lock.Lock() + defer a.lock.Unlock() + + if a.created { + a.sysData.setAreaSize(width, height) + return + } + a.initwidth = width + a.initheight = height +} + func (a *Area) make(window *sysData) error { a.lock.Lock() defer a.lock.Unlock() @@ -231,6 +249,7 @@ func (a *Area) make(window *sysData) error { if err != nil { return err } + a.sysData.setAreaSize(a.initwidth, a.initheight) a.created = true return nil } diff --git a/area_unix.go b/area_unix.go index 4e4788b..83aafc5 100644 --- a/area_unix.go +++ b/area_unix.go @@ -24,7 +24,7 @@ import "C" func gtkAreaNew() *gtkWidget { drawingarea := C.gtk_drawing_area_new() - C.gtk_widget_set_size_request(drawingarea, 320, 240) + C.gtk_widget_set_size_request(drawingarea, 100, 100) // default initial size (TODO do we need it?); use C. to avoid casting drawingarea // we need to explicitly subscribe to mouse events with GtkDrawingArea C.gtk_widget_add_events(drawingarea, C.GDK_BUTTON_PRESS_MASK | C.GDK_BUTTON_RELEASE_MASK | C.GDK_POINTER_MOTION_MASK | C.GDK_BUTTON_MOTION_MASK) diff --git a/gtkcalls_unix.go b/gtkcalls_unix.go index c7b409a..3591e65 100644 --- a/gtkcalls_unix.go +++ b/gtkcalls_unix.go @@ -217,3 +217,7 @@ func gtk_progress_bar_set_fraction(w *gtkWidget, percent int) { func gtk_progress_bar_pulse(w *gtkWidget) { C.gtk_progress_bar_pulse(togtkprogressbar(w)) } + +func gtk_widget_queue_draw(widget *gtkWidget) { + C.gtk_widget_queue_draw(togtkwidget(widget)) +} diff --git a/sysdata.go b/sysdata.go index c010ab6..5076093 100644 --- a/sysdata.go +++ b/sysdata.go @@ -76,6 +76,9 @@ func (c *cSysData) setProgress(int) { func (c *cSysData) len() int { panic(runtime.GOOS + " sysData does not define len()") } +func (c *cSysData) setAreaSize(int, int) { + panic(runtime.GOOS + " sysData does not define setAreaSize()") +} // signal sends the event signal. This raise is done asynchronously to avoid deadlocking the UI task. // Thanks skelterjohn for this techinque: if we can't queue any more events, drop them diff --git a/sysdata_unix.go b/sysdata_unix.go index 306d962..6100606 100644 --- a/sysdata_unix.go +++ b/sysdata_unix.go @@ -350,3 +350,15 @@ func (s *sysData) len() int { } return <-ret } + +func (s *sysData) setAreaSize(width int, height int) { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { + c := gtkAreaGetControl(s.widget) + gtk_widget_set_size_request(c, width, height) + gtk_widget_queue_draw(c) // force repaint (TODO doesn't have an effect when shrinking?) + ret <- struct{}{} + } + <-ret +} diff --git a/test/main.go b/test/main.go index b2d6a6d..a2d683e 100644 --- a/test/main.go +++ b/test/main.go @@ -10,6 +10,7 @@ import ( _ "image/png" "bytes" "time" + "strconv" . "github.com/andlabs/ui" ) @@ -158,13 +159,25 @@ func areaTest() { img := image.NewNRGBA(ximg.Bounds()) draw.Draw(img, img.Rect, ximg, image.ZP, draw.Over) w := NewWindow("Area Test", 100, 100) - a := NewArea(&areaHandler{ + a := NewArea(320, 240, &areaHandler{ img: img, }) timedisp := NewLabel("") timechan := time.Tick(time.Second) + widthbox := NewLineEdit("320") + heightbox := NewLineEdit("240") + resize := NewButton("Resize") + sizeStack := NewHorizontalStack(widthbox, heightbox, resize) + sizeStack.SetStretchy(0) + sizeStack.SetStretchy(1) + sizeStack.SetStretchy(2) + sizeStack = NewHorizontalStack(sizeStack, Space(), Space()) + sizeStack.SetStretchy(0) + sizeStack.SetStretchy(1) + sizeStack.SetStretchy(2) layout := NewVerticalStack(a, - NewHorizontalStack(timedisp)) + NewHorizontalStack(timedisp), + sizeStack) layout.SetStretchy(0) err = w.Open(layout) if err != nil { @@ -176,6 +189,13 @@ func areaTest() { return case t := <-timechan: timedisp.SetText(t.String()) + case <-resize.Clicked: + width, err := strconv.Atoi(widthbox.Text()) + if err != nil { println(err); continue } + height, err := strconv.Atoi(heightbox.Text()) + if err != nil { println(err); continue } +println(width, height) + a.SetSize(width, height) } } }