shithub: mycel

Download patch

ref: cee10df58933854e4f59ac2a1c87a3cba20dc6af
parent: e384a34196d16392ecd428b63d21a3868e8957b6
author: Philip Silva <philip.silva@protonmail.com>
date: Fri Aug 20 14:15:37 EDT 2021

place: much less redraws

--- a/browser/browser.go
+++ b/browser/browser.go
@@ -786,7 +786,7 @@
 	n.Attr = append(n.Attr, newAttr)
 }
 
-func placeFunc(name string, place *duit.Place) func(self *duit.Kid, sizeAvail image.Point) {
+func placeFunc(name string, place *duitx.Place) func(self *duit.Kid, sizeAvail image.Point) {
 	return func(self *duit.Kid, sizeAvail image.Point) {
 		for i, kid := range place.Kids {
 			el := kid.UI.(*Element)
@@ -842,7 +842,7 @@
 	for _, a := range absolutes {
 		uis = append(uis, a)
 	}
-	pl := &duit.Place{
+	pl := &duitx.Place{
 		Kids: duit.NewKids(uis...),
 		Background: bg,
 	}
@@ -1301,7 +1301,7 @@
 	case *duit.Edit:
 	case *duit.Button:
 	case *duit.List:
-	case *duit.Place:
+	case *duitx.Place:
 		for _, kid := range v.Kids {
 			traverseTree(r+1, kid.UI, f)
 		}
--- /dev/null
+++ b/browser/duitx/place.go
@@ -1,0 +1,140 @@
+package duitx
+
+// Original code from github.com/mjl-/duit
+//
+// Copyright 2018 Mechiel Lukkien mechiel@ueber.net
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import (
+	"image"
+
+	"9fans.net/go/draw"
+	"github.com/mjl-/duit"
+	"github.com/psilva261/opossum/logger"
+)
+
+// Place contains other UIs it can position absolute, possibly on top of each other.
+type Place struct {
+	// Place is called during layout. It must configure Kids, and set self.R, based on sizeAvail.
+	Place      func(self *duit.Kid, sizeAvail image.Point) `json:"-"`
+	Kids       []*duit.Kid                                 // Kids to draw, set by the Place function.
+	Background *draw.Image                            `json:"-"` // For background color.
+
+	kidsReversed []*duit.Kid
+	size         image.Point
+	img          *draw.Image
+	force        bool
+}
+
+var _ duit.UI = &Place{}
+
+func (ui *Place) ensure() {
+	if len(ui.kidsReversed) == len(ui.Kids) {
+		return
+	}
+	ui.kidsReversed = make([]*duit.Kid, len(ui.Kids))
+	for i, k := range ui.Kids {
+		ui.kidsReversed[len(ui.Kids)-1-i] = k
+	}
+}
+
+func (ui *Place) Layout(dui *duit.DUI, self *duit.Kid, sizeAvail image.Point, force bool) {
+	ui.ensure()
+	debugLayout(dui, self)
+
+	ui.Place(self, sizeAvail)
+}
+
+func (ui *Place) Draw(dui *duit.DUI, self *duit.Kid, img *draw.Image, orig image.Point, m draw.Mouse, force bool) {
+	if self.Draw == duit.Clean {
+		return
+	}
+	self.Draw = duit.Clean
+	if ui.img == nil || ui.Kids[0].R.Size() != ui.img.R.Size() {
+		var err error
+		if ui.img != nil {
+			ui.img.Free()
+			ui.img = nil
+		}
+		if ui.Kids[0].R.Dx() == 0 || ui.Kids[0].R.Dy() == 0 {
+			return
+		}
+		ui.img, err = dui.Display.AllocImage(ui.Kids[0].R, draw.ARGB32, false, 0x00000000)
+		if err != nil {
+			log.Errorf("allocimage: %v", err)
+			return
+		}
+		self.Draw = duit.DirtyKid
+	}
+	if self.Draw == duit.DirtyKid || ui.force {
+		duit.KidsDraw(dui, self, ui.Kids, ui.size, ui.Background, ui.img, image.ZP, m, true)
+		self.Draw = duit.Clean
+		ui.force = false
+	}
+	img.Draw(ui.img.R.Add(orig), ui.img, nil, image.ZP)
+}
+
+func (ui *Place) result(dui *duit.DUI, self *duit.Kid, r *duit.Result) {
+	relayout := false
+	redraw := false
+
+	for _, k := range ui.Kids {
+		if k.Layout != duit.Clean {
+			relayout = true
+		} else if k.Draw != duit.Clean {
+			redraw = true
+		}
+	}
+	if relayout {
+		self.Layout = duit.DirtyKid
+		self.Draw = duit.DirtyKid
+		ui.force = ui.force || r.Consumed
+	} else if redraw {
+		self.Draw = duit.DirtyKid
+		ui.force = ui.force || r.Consumed
+	}
+}
+
+func (ui *Place) Mouse(dui *duit.DUI, self *duit.Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r duit.Result) {
+	r = duit.KidsMouse(dui, self, ui.kidsReversed, m, origM, orig)
+	ui.result(dui, self, &r)
+	return
+}
+
+func (ui *Place) Key(dui *duit.DUI, self *duit.Kid, k rune, m draw.Mouse, orig image.Point) (r duit.Result) {
+	r = duit.KidsKey(dui, self, ui.kidsReversed, k, m, orig)
+	ui.result(dui, self, &r)
+	return
+}
+
+func (ui *Place) FirstFocus(dui *duit.DUI, self *duit.Kid) (warp *image.Point) {
+	return duit.KidsFirstFocus(dui, self, ui.Kids)
+}
+
+func (ui *Place) Focus(dui *duit.DUI, self *duit.Kid, o duit.UI) (warp *image.Point) {
+	return duit.KidsFocus(dui, self, ui.Kids, o)
+}
+
+func (ui *Place) Mark(self *duit.Kid, o duit.UI, forLayout bool) (marked bool) {
+	return duit.KidsMark(self, ui.Kids, o, forLayout)
+}
+
+func (ui *Place) Print(self *duit.Kid, indent int) {
+	duit.PrintUI("Place", self, indent)
+	duit.KidsPrint(ui.Kids, indent+1)
+}