mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
all: [API] replace unit.Value with separate unit.Dp, unit.Sp types
The unit.Value is a struct and thus more inconvenient to use than its
underlying float32 type. In addition, most uses don't need a general
value, but rather a specific unit given by the context. This change
replaces unit.Value with two float32 units, Dp and Sp. It also changes
variables and parameters of unit.Value to a specific unit type matching
the context. That is, unit.Dp everywhere except for text sizes which are
in Sp.
Switching to typed float32s has multiple advantages
- They can be constants:
const touchSlop = unit.Dp(16)
- Casting untyped constants is no longer necessary:
insets := layout.UniformInset(16)
- Calculation with values is natural:
func (s ScrollbarStyle) Width() unit.Dp {
return s.Indicator.MinorWidth + s.Track.MinorPadding + s.Track.MinorPadding
}
The main API change is that calls to gtx.Px must be replaced with either
gtx.Dp or gtx.Sp depending on the unit.
Idea by Christophe Meessen.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+18
-114
@@ -2,9 +2,7 @@
|
||||
|
||||
/*
|
||||
|
||||
Package unit implements device independent units and values.
|
||||
|
||||
A Value is a value with a Unit attached.
|
||||
Package unit implements device independent units.
|
||||
|
||||
Device independent pixel, or dp, is the unit for sizes independent of
|
||||
the underlying display device.
|
||||
@@ -23,19 +21,9 @@ values.
|
||||
package unit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Value is a value with a unit.
|
||||
type Value struct {
|
||||
V float32
|
||||
U Unit
|
||||
}
|
||||
|
||||
// Unit represents a unit for a Value.
|
||||
type Unit uint8
|
||||
|
||||
// Metric converts Values to device-dependent pixels, px. The zero
|
||||
// value represents a 1-to-1 scale from dp, sp to pixels.
|
||||
type Metric struct {
|
||||
@@ -45,113 +33,29 @@ type Metric struct {
|
||||
PxPerSp float32
|
||||
}
|
||||
|
||||
const (
|
||||
// UnitPx represent device pixels in the resolution of
|
||||
// the underlying display.
|
||||
UnitPx Unit = iota
|
||||
// UnitDp represents device independent pixels. 1 dp will
|
||||
type (
|
||||
// Dp represents device independent pixels. 1 dp will
|
||||
// have the same apparent size across platforms and
|
||||
// display resolutions.
|
||||
UnitDp
|
||||
// UnitSp is like UnitDp but for font sizes.
|
||||
UnitSp
|
||||
Dp float32
|
||||
// Sp is like UnitDp but for font sizes.
|
||||
Sp float32
|
||||
)
|
||||
|
||||
// Px returns the Value for v device pixels.
|
||||
func Px(v float32) Value {
|
||||
return Value{V: v, U: UnitPx}
|
||||
}
|
||||
|
||||
// Dp returns the Value for v device independent
|
||||
// pixels.
|
||||
func Dp(v float32) Value {
|
||||
return Value{V: v, U: UnitDp}
|
||||
}
|
||||
|
||||
// Sp returns the Value for v scaled dps.
|
||||
func Sp(v float32) Value {
|
||||
return Value{V: v, U: UnitSp}
|
||||
}
|
||||
|
||||
// Scale returns the value scaled by s.
|
||||
func (v Value) Scale(s float32) Value {
|
||||
v.V *= s
|
||||
return v
|
||||
}
|
||||
|
||||
func (v Value) String() string {
|
||||
return fmt.Sprintf("%g%s", v.V, v.U)
|
||||
}
|
||||
|
||||
func (u Unit) String() string {
|
||||
switch u {
|
||||
case UnitPx:
|
||||
return "px"
|
||||
case UnitDp:
|
||||
return "dp"
|
||||
case UnitSp:
|
||||
return "sp"
|
||||
default:
|
||||
panic("unknown unit")
|
||||
// Dp converts v to pixels, rounded to the nearest integer value.
|
||||
func (c Metric) Dp(v Dp) int {
|
||||
s := c.PxPerDp
|
||||
if s == 0. {
|
||||
s = 1.
|
||||
}
|
||||
return int(math.Round(float64(s) * float64(v)))
|
||||
}
|
||||
|
||||
// Add a list of Values.
|
||||
func Add(c Metric, values ...Value) Value {
|
||||
var sum Value
|
||||
for _, v := range values {
|
||||
sum, v = compatible(c, sum, v)
|
||||
sum.V += v.V
|
||||
// Sp converts v to pixels, rounded to the nearest integer value.
|
||||
func (c Metric) Sp(v Sp) int {
|
||||
s := c.PxPerSp
|
||||
if s == 0. {
|
||||
s = 1.
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
// Max returns the maximum of a list of Values.
|
||||
func Max(c Metric, values ...Value) Value {
|
||||
var max Value
|
||||
for _, v := range values {
|
||||
max, v = compatible(c, max, v)
|
||||
if v.V > max.V {
|
||||
max.V = v.V
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
func (c Metric) Px(v Value) int {
|
||||
var r float32
|
||||
switch v.U {
|
||||
case UnitPx:
|
||||
r = v.V
|
||||
case UnitDp:
|
||||
s := c.PxPerDp
|
||||
if s == 0 {
|
||||
s = 1
|
||||
}
|
||||
r = s * v.V
|
||||
case UnitSp:
|
||||
s := c.PxPerSp
|
||||
if s == 0 {
|
||||
s = 1
|
||||
}
|
||||
r = s * v.V
|
||||
default:
|
||||
panic("unknown unit")
|
||||
}
|
||||
return int(math.Round(float64(r)))
|
||||
}
|
||||
|
||||
func compatible(c Metric, v1, v2 Value) (Value, Value) {
|
||||
if v1.U == v2.U {
|
||||
return v1, v2
|
||||
}
|
||||
if v1.V == 0 {
|
||||
v1.U = v2.U
|
||||
return v1, v2
|
||||
}
|
||||
if v2.V == 0 {
|
||||
v2.U = v1.U
|
||||
return v1, v2
|
||||
}
|
||||
return Px(float32(c.Px(v1))), Px(float32(c.Px(v2)))
|
||||
return int(math.Round(float64(s) * float64(v)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user