Add Gio app shells and platform stubs (T-003)

This commit is contained in:
ila
2026-07-16 15:43:03 +08:00
parent 0e20dd76b2
commit 6f920eb457
23 changed files with 668 additions and 15 deletions
+39 -2
View File
@@ -1,11 +1,48 @@
package main
import (
"fmt"
"log"
"os"
"gioui.org/app"
"gioui.org/op"
"gioui.org/unit"
"softbox.local/app-win7/platform/windows"
softboxgio "softbox.local/app-win7/ui/gio"
"softbox.local/core"
)
func main() {
fmt.Println(core.ProductName)
go func() {
if err := run(); err != nil {
log.Printf("%s Legacy stopped: %v", core.ProductName, err)
}
os.Exit(0)
}()
app.Main()
}
func run() error {
platform := windows.New()
window := new(app.Window)
window.Option(
app.Title(core.ProductName+" Legacy"),
app.Size(unit.Dp(1024), unit.Dp(680)),
)
theme := softboxgio.NewTheme()
shell := softboxgio.NewAppShell(string(platform.Edition()))
var operations op.Ops
for {
switch event := window.Event().(type) {
case app.DestroyEvent:
return event.Err
case app.FrameEvent:
context := app.NewContext(&operations, event)
shell.Layout(context, theme)
event.Frame(context.Ops)
}
}
}
+9
View File
@@ -1 +1,10 @@
gioui.org v0.6.0 h1:ZSXO/AbpFZJ2L9NU69uFQfDI3BKIH+YEJElrn0B+aZI=
gioui.org v0.6.0/go.mod h1:eUvGo6FAzA7jUqeSu5a+M1W03yc9r1nanIBS8A5+Nng=
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
gioui.org/shader v1.0.8 h1:6ks0o/A+b0ne7RzEqRZK5f4Gboz2CfG+mVliciy6+qA=
github.com/go-text/typesetting v0.1.1 h1:bGAesCuo85nXnEN5LmFMVGAGpGkCPtHrZLi//qD7EJo=
golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 h1:sBdrWpxhGDdTAYNqbgBLAR+ULAPPhfgncLr1X0lyWtg=
golang.org/x/exp/shiny v0.0.0-20220827204233-334a2380cb91 h1:ryT6Nf0R83ZgD8WnFFdfI8wCeyqgdXWN4+CkFVNPAT0=
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+2 -1
View File
@@ -1,2 +1,3 @@
// Package windows contains Win7-compatible Windows platform adapters.
// Package windows provides Win7-compatible platform adapters and non-Windows
// stubs for package-level tests.
package windows
+17
View File
@@ -0,0 +1,17 @@
package windows
// Edition identifies the application build channel shown by the UI.
type Edition string
const EditionLegacy Edition = "Legacy"
// Platform is the minimal boundary for target-specific capabilities.
type Platform interface {
OS() string
Edition() Edition
}
// New returns the platform implementation selected by build tags.
func New() Platform {
return newPlatform()
}
@@ -0,0 +1,19 @@
//go:build !windows
package windows
import "runtime"
type platformStub struct{}
func newPlatform() Platform {
return platformStub{}
}
func (platformStub) OS() string {
return runtime.GOOS
}
func (platformStub) Edition() Edition {
return EditionLegacy
}
@@ -0,0 +1,13 @@
package windows
import "testing"
func TestPlatformStubContract(t *testing.T) {
platform := New()
if platform.OS() == "" {
t.Fatal("OS() should not be empty")
}
if platform.Edition() != EditionLegacy {
t.Fatalf("Edition() = %q, want %q", platform.Edition(), EditionLegacy)
}
}
@@ -0,0 +1,17 @@
//go:build windows
package windows
type platform struct{}
func newPlatform() Platform {
return platform{}
}
func (platform) OS() string {
return "windows"
}
func (platform) Edition() Edition {
return EditionLegacy
}
+3
View File
@@ -1,2 +1,5 @@
// Package gio contains the Win7-compatible Gio UI adapter.
//
// Layout code is rendering-only: it must not read files, access the network,
// calculate hashes, or directly mutate background application state.
package gio
+90
View File
@@ -0,0 +1,90 @@
package gio
import (
"image/color"
"gioui.org/layout"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget/material"
)
var shellColors = struct {
background color.NRGBA
foreground color.NRGBA
primary color.NRGBA
onPrimary color.NRGBA
secondary color.NRGBA
}{
background: color.NRGBA{R: 248, G: 250, B: 252, A: 255},
foreground: color.NRGBA{R: 15, G: 23, B: 42, A: 255},
primary: color.NRGBA{R: 13, G: 148, B: 136, A: 255},
onPrimary: color.NRGBA{R: 255, G: 255, B: 255, A: 255},
secondary: color.NRGBA{R: 71, G: 85, B: 105, A: 255},
}
// AppShell is the Legacy window frame. Feature views are added in later tasks.
type AppShell struct {
edition string
}
// NewAppShell creates an empty shell for the supplied build edition.
func NewAppShell(edition string) *AppShell {
return &AppShell{edition: edition}
}
// NewTheme creates the semantic palette shared by the Legacy shell.
func NewTheme() *material.Theme {
theme := material.NewTheme()
theme.Palette = material.Palette{
Bg: shellColors.background,
Fg: shellColors.foreground,
ContrastBg: shellColors.primary,
ContrastFg: shellColors.onPrimary,
}
theme.FingerSize = unit.Dp(44)
return theme
}
// Layout renders the shell without performing IO or submitting use cases.
func (shell *AppShell) Layout(context layout.Context, theme *material.Theme) layout.Dimensions {
paint.Fill(context.Ops, theme.Bg)
return layout.UniformInset(unit.Dp(32)).Layout(context, func(context layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(
context,
layout.Rigid(func(context layout.Context) layout.Dimensions {
return layout.Flex{Alignment: layout.Middle}.Layout(
context,
layout.Rigid(material.H5(theme, "SoftBox").Layout),
layout.Rigid(layout.Spacer{Width: unit.Dp(16)}.Layout),
layout.Rigid(func(context layout.Context) layout.Dimensions {
label := material.Body2(theme, shell.edition)
label.Color = shellColors.primary
return label.Layout(context)
}),
)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(24)}.Layout),
layout.Flexed(1, func(context layout.Context) layout.Dimensions {
return layout.Center.Layout(context, func(context layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(
context,
layout.Rigid(material.H6(theme, "软件目录准备中").Layout),
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
layout.Rigid(func(context layout.Context) layout.Dimensions {
label := material.Body1(theme, "Legacy 窗口已就绪,业务功能将在后续任务接入。")
label.Color = shellColors.secondary
return label.Layout(context)
}),
)
})
}),
layout.Rigid(func(context layout.Context) layout.Dimensions {
label := material.Body2(theme, "Legacy · Windows 7 SP1 x64")
label.Color = shellColors.secondary
return label.Layout(context)
}),
)
})
}
+25
View File
@@ -0,0 +1,25 @@
package gio
import (
"image"
"testing"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/unit"
)
func TestAppShellFillsWindow(t *testing.T) {
var operations op.Ops
size := image.Pt(1024, 680)
context := layout.Context{
Ops: &operations,
Metric: unit.Metric{PxPerDp: 1, PxPerSp: 1},
Constraints: layout.Exact(size),
}
dimensions := NewAppShell("Legacy").Layout(context, NewTheme())
if dimensions.Size != size {
t.Fatalf("Layout() size = %v, want %v", dimensions.Size, size)
}
}