func (self window) run() { var frame geom.Size var density float64 defer self.window.Release() defer close(self.events) for { v := self.window.NextEvent() switch e := v.(type) { default: // This is none of the events that we know the mobile package should send, // probably a custom event from the application so we simply forward it. self.events <- v case paint.Event: gc := newGraphicContext(self.window) self.events <- event.Redraw{ GC: gc, Clip: geom.Rect{W: frame.W, H: frame.H}, External: e.External, } gc.join.Wait() case size.Event: w := float64(e.WidthPt) h := float64(e.HeightPt) d := float64(e.PixelsPerPt) if w != frame.W || h != frame.H || d != density { frame.W = w frame.H = h density = d self.events <- event.ChangeScreen{Density: density} self.events <- event.Resize{Size: frame} } case lifecycle.Event: if e.To == lifecycle.StageDead { self.events <- event.Close{} return } switch e.Crosses(lifecycle.StageVisible) { case lifecycle.CrossOn: self.events <- event.Focus{Focused: true} case lifecycle.CrossOff: self.events <- event.Focus{Focused: false} } } } }
func (self UniformFillImageLayout) Layout(widget geom.Size, image geom.Size) (bounds geom.Rect) { if r1, r2 := image.Ratio(), widget.Ratio(); r1 < r2 { bounds.W = widget.W bounds.H = widget.W / r1 bounds.Y = (widget.H / 2) - (bounds.H / 2) } else if r1 > r2 { bounds.W = widget.H * r1 bounds.H = widget.H bounds.X = (widget.W / 2) - (bounds.W / 2) } else { bounds.W = widget.W bounds.H = widget.H } return }
func (self *MarginBox) PreferredSize(constraints geom.Size) geom.Size { margin := self.Margin() if self.content == nil { return margin.Size() } if constraints.W >= 0 { constraints.W = math.Max(0, constraints.W-margin.Width()) } if constraints.H >= 0 { constraints.H = math.Max(0, constraints.H-margin.Height()) } return margin.GrowSize(self.content.PreferredSize(constraints)) }
func (self HorizontalLayout) PreferredSize(constraints geom.Size, widgets ...Widget) (size geom.Size) { n := len(widgets) if n == 0 { return } constraints.W /= float64(n) for _, w := range widgets { s := w.PreferredSize(constraints) size.W = math.Max(s.W, size.W) size.H = math.Max(s.H, size.H) } size.W = (size.W * float64(n)) + (self.Spacing * float64(n-1)) return }
func (self *window) run() { var glctx gl.Context var frame geom.Size var scale float64 defer close(self.events) for v := range self.app.Events() { switch e := v.(type) { default: // This is none of the events that we know the mobile package should send, // probably a custom event from the application so we simply forward it. self.events <- v case paint.Event: if glctx != nil { // Always clear the content before redrawing so we don't leak left overs // of the video buffer. glctx.ClearColor(0, 0, 0, 1) glctx.Clear(gl.COLOR_BUFFER_BIT) gc := newGraphicContext(self.app, glctx) self.events <- event.Redraw{ GC: gc, Clip: geom.Rect{W: frame.W, H: frame.H}, External: e.External, } gc.join.Wait() } case size.Event: w := float64(e.WidthPt) h := float64(e.HeightPt) d := float64(e.PixelsPerPt) if w != frame.W || h != frame.H || d != scale { frame.W = w frame.H = h scale = d self.events <- event.ChangeScreen{ Bounds: geom.Rect{W: frame.W, H: frame.H}, Scale: scale, } self.events <- event.Move{} self.events <- event.Resize{ Size: frame, } } case lifecycle.Event: if e.To == lifecycle.StageDead { self.events <- event.Close{} return } switch e.Crosses(lifecycle.StageVisible) { case lifecycle.CrossOn: // The app doesn't send a paint event when it starts so we force // it here to trigger the first drawing of the newly created // window. glctx = e.DrawContext.(gl.Context) self.app.Send(paint.Event{External: true}) self.events <- event.Focus{Focused: true} case lifecycle.CrossOff: glctx = nil self.events <- event.Focus{Focused: false} } } } // Unsure under which condition the events channel could get closed before a // lifecycle event indicating the app is going away but just in case we send // a close event before returning. self.events <- event.Close{} }