FormItem takes *ui.Context first (PRD 6.1); drop dead internal.Rule
This commit is contained in:
8 files changed
+22
-29
No files matched your search
@@ -169,7 +169,7 @@ func TestFormFocusesDatePickerInput(t *testing.T) {
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
Use(c, Settings{})
|
||||
Form(c, &st, FormOptions{}, func(f *FormScope) {
|
||||
FormItem(f, "debut", &day, FormItemOptions[Date]{Label: "Debut date", Required: true}, func() *ui.Element {
|
||||
FormItem(c, f, "debut", &day, FormItemOptions[Date]{Label: "Debut date", Required: true}, func() *ui.Element {
|
||||
r := DatePicker(c, &day, DatePickerOptions{Today: calendarToday})
|
||||
input = r.Input
|
||||
return r.Input
|
||||
|
||||
@@ -14,7 +14,7 @@ name := ""
|
||||
view := func(c *ui.Context) {
|
||||
mujica.Use(c, mujica.Settings{})
|
||||
res := mujica.Form(c, &state, mujica.FormOptions{}, func(f *mujica.FormScope) {
|
||||
mujica.FormItem(f, "name", &name, mujica.FormItemOptions[string]{Label: "Name", Required: true}, func() *ui.Element {
|
||||
mujica.FormItem(c, f, "name", &name, mujica.FormItemOptions[string]{Label: "Name", Required: true}, func() *ui.Element {
|
||||
return mujica.InputGroup(c, &name, mujica.InputGroupOptions{Invalid: state.Error("name") != ""}).Input
|
||||
})
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ func ExampleForm() {
|
||||
view := func(c *ui.Context) {
|
||||
mujica.Use(c, mujica.Settings{})
|
||||
res := mujica.Form(c, &state, mujica.FormOptions{}, func(f *mujica.FormScope) {
|
||||
mujica.FormItem(f, "name", &name, mujica.FormItemOptions[string]{Label: "Name", Required: true}, func() *ui.Element {
|
||||
mujica.FormItem(c, f, "name", &name, mujica.FormItemOptions[string]{Label: "Name", Required: true}, func() *ui.Element {
|
||||
return mujica.InputGroup(c, &name, mujica.InputGroupOptions{Invalid: state.Error("name") != ""}).Input
|
||||
})
|
||||
})
|
||||
|
||||
@@ -110,7 +110,7 @@ func (g *gallery) formEdit(c *ui.Context, log func(string)) {
|
||||
|
||||
func (g *gallery) formFields(c *ui.Context, f *mujica.FormScope, log func(string)) {
|
||||
s := &g.cForm
|
||||
mujica.FormItem(f, "name", &s.name, mujica.FormItemOptions[string]{Label: g.t("Stage name", "艺名"), Required: true,
|
||||
mujica.FormItem(c, f, "name", &s.name, mujica.FormItemOptions[string]{Label: g.t("Stage name", "艺名"), Required: true,
|
||||
Description: g.t("Checked against the archive; “Oblivionis” is taken.", "将与档案核对;“Oblivionis”已被占用。"),
|
||||
Validate: func(v string) string {
|
||||
if len([]rune(strings.TrimSpace(v))) < 2 {
|
||||
@@ -134,7 +134,7 @@ func (g *gallery) formFields(c *ui.Context, f *mujica.FormScope, log func(string
|
||||
}}, func() *ui.Element {
|
||||
return mujica.TextInput(c, &s.name, mujica.TextInputOptions{}).Input
|
||||
})
|
||||
mujica.FormItem(f, "password", &s.password, mujica.FormItemOptions[string]{Label: g.t("Password", "密码"), Required: true,
|
||||
mujica.FormItem(c, f, "password", &s.password, mujica.FormItemOptions[string]{Label: g.t("Password", "密码"), Required: true,
|
||||
Validate: func(v string) string {
|
||||
if len([]rune(v)) < 8 {
|
||||
return g.t("Use at least 8 characters.", "至少 8 个字符。")
|
||||
@@ -147,14 +147,14 @@ func (g *gallery) formFields(c *ui.Context, f *mujica.FormScope, log func(string
|
||||
}
|
||||
return r.Input
|
||||
})
|
||||
mujica.FormItem(f, "debut", &s.debut, mujica.FormItemOptions[mujica.Date]{Label: g.t("Debut date", "首演日期"), Required: true}, func() *ui.Element {
|
||||
mujica.FormItem(c, f, "debut", &s.debut, mujica.FormItemOptions[mujica.Date]{Label: g.t("Debut date", "首演日期"), Required: true}, func() *ui.Element {
|
||||
r := mujica.DatePicker(c, &s.debut, mujica.DatePickerOptions{Clearable: true})
|
||||
if r.Changed() {
|
||||
log("debut " + s.debut.Format("2006-01-02"))
|
||||
}
|
||||
return r.Input
|
||||
})
|
||||
mujica.FormItem(f, "roles", &s.tags, mujica.FormItemOptions[[]string]{Label: g.t("Roles", "担当"), Required: true,
|
||||
mujica.FormItem(c, f, "roles", &s.tags, mujica.FormItemOptions[[]string]{Label: g.t("Roles", "担当"), Required: true,
|
||||
Description: g.t("Up to 4; press Enter after each.", "最多 4 个;每个后按 Enter。")}, func() *ui.Element {
|
||||
r := mujica.TagsInput(c, &s.tags, mujica.TagsInputOptions{Max: 4, Invalid: s.st.Error("roles") != "", Placeholder: g.t("keyboard, bass…", "键盘、贝斯…")})
|
||||
if r.Changed() {
|
||||
@@ -162,7 +162,7 @@ func (g *gallery) formFields(c *ui.Context, f *mujica.FormScope, log func(string
|
||||
}
|
||||
return r.Input
|
||||
})
|
||||
mujica.FormItem(f, "terms", &s.terms, mujica.FormItemOptions[bool]{Label: g.t("Terms", "条款"),
|
||||
mujica.FormItem(c, f, "terms", &s.terms, mujica.FormItemOptions[bool]{Label: g.t("Terms", "条款"),
|
||||
Validate: func(v bool) string {
|
||||
if !v {
|
||||
return g.t("Accept the terms to continue.", "请先同意条款。")
|
||||
|
||||
@@ -118,7 +118,7 @@ var formPages = []page{
|
||||
}
|
||||
formToggles(c, []string{"Labels beside fields", "Server rejects the submit"}, &d.horizontal, &d.slowServer)
|
||||
res := mujica.Form(c, &d.st, mujica.FormOptions{Horizontal: d.horizontal}, func(f *mujica.FormScope) {
|
||||
mujica.FormItem(f, "name", &d.name, mujica.FormItemOptions[string]{Label: "Stage name", Required: true, Initial: "Sakiko",
|
||||
mujica.FormItem(c, f, "name", &d.name, mujica.FormItemOptions[string]{Label: "Stage name", Required: true, Initial: "Sakiko",
|
||||
Description: "Checked against the archive; \"Oblivionis\" is taken.",
|
||||
Async: func(v string, version uint64) {
|
||||
log(fmt.Sprintf("async check started v%d", version))
|
||||
@@ -134,7 +134,7 @@ var formPages = []page{
|
||||
}}, func() *ui.Element {
|
||||
return mujica.InputGroup(c, &d.name, mujica.InputGroupOptions{Invalid: d.st.Error("name") != ""}).Input
|
||||
})
|
||||
mujica.FormItem(f, "email", &d.email, mujica.FormItemOptions[string]{Label: "Email", Required: true,
|
||||
mujica.FormItem(c, f, "email", &d.email, mujica.FormItemOptions[string]{Label: "Email", Required: true,
|
||||
Validate: func(v string) string {
|
||||
if !strings.Contains(v, "@") {
|
||||
return "Enter an email address."
|
||||
@@ -147,7 +147,7 @@ var formPages = []page{
|
||||
}
|
||||
return g.Input
|
||||
})
|
||||
mujica.FormItem(f, "tags", &d.tags, mujica.FormItemOptions[[]string]{Label: "Roles", Required: true, Initial: []string{"keyboard"}}, func() *ui.Element {
|
||||
mujica.FormItem(c, f, "tags", &d.tags, mujica.FormItemOptions[[]string]{Label: "Roles", Required: true, Initial: []string{"keyboard"}}, func() *ui.Element {
|
||||
return mujica.TagsInput(c, &d.tags, mujica.TagsInputOptions{Max: 4, Invalid: d.st.Error("tags") != ""}).Input
|
||||
})
|
||||
})
|
||||
@@ -336,7 +336,7 @@ name := ""
|
||||
view := func(c *ui.Context) {
|
||||
mujica.Use(c, mujica.Settings{})
|
||||
res := mujica.Form(c, &state, mujica.FormOptions{}, func(f *mujica.FormScope) {
|
||||
mujica.FormItem(f, "name", &name, mujica.FormItemOptions[string]{Label: "Name", Required: true}, func() *ui.Element {
|
||||
mujica.FormItem(c, f, "name", &name, mujica.FormItemOptions[string]{Label: "Name", Required: true}, func() *ui.Element {
|
||||
return mujica.InputGroup(c, &name, mujica.InputGroupOptions{Invalid: state.Error("name") != ""}).Input
|
||||
})
|
||||
})
|
||||
|
||||
@@ -99,7 +99,6 @@ type FormOptions struct {
|
||||
|
||||
// FormScope registers a Form's fields with FormItem.
|
||||
type FormScope struct {
|
||||
c *ui.Context
|
||||
st *FormState
|
||||
horizontal bool
|
||||
}
|
||||
@@ -140,7 +139,7 @@ func Form(c *ui.Context, st *FormState, opts FormOptions, fields func(f *FormSco
|
||||
parts := FormParts{}
|
||||
col := ui.Column(c).Gap(d.Unit() * 5)
|
||||
parts.Element = col
|
||||
scope := &FormScope{c: c, st: st, horizontal: opts.Horizontal}
|
||||
scope := &FormScope{st: st, horizontal: opts.Horizontal}
|
||||
col.Children(func() {
|
||||
// A new key after Reset drops the controls' drafts and errors.
|
||||
ui.Box(c).Key(st.generation).Children(func() {
|
||||
@@ -242,8 +241,8 @@ func formReset(st *FormState) {
|
||||
}
|
||||
|
||||
// FormItem registers field name around the focusable element control returns.
|
||||
func FormItem[T any](f *FormScope, name string, value *T, opts FormItemOptions[T], control func() *ui.Element) *ui.Element {
|
||||
c, st := f.c, f.st
|
||||
func FormItem[T any](c *ui.Context, f *FormScope, name string, value *T, opts FormItemOptions[T], control func() *ui.Element) *ui.Element {
|
||||
st := f.st
|
||||
if name == "" || opts.Label == "" {
|
||||
panic("mujica: FormItem needs a name and a Label")
|
||||
}
|
||||
|
||||
+7
-7
@@ -25,7 +25,7 @@ func (p *formProbe) run(c *ui.Context) {
|
||||
|
||||
func (p *formProbe) view(c *ui.Context) {
|
||||
res := Form(c, &p.st, FormOptions{Horizontal: p.horizontal}, func(f *FormScope) {
|
||||
FormItem(f, "name", &p.name, FormItemOptions[string]{Label: "Name", Required: true, Initial: "Sakiko"}, func() *ui.Element {
|
||||
FormItem(c, f, "name", &p.name, FormItemOptions[string]{Label: "Name", Required: true, Initial: "Sakiko"}, func() *ui.Element {
|
||||
return InputGroup(c, &p.name, InputGroupOptions{Invalid: p.st.Error("name") != ""}).Input
|
||||
})
|
||||
opts := FormItemOptions[string]{Label: "Email", Validate: func(v string) string {
|
||||
@@ -40,10 +40,10 @@ func (p *formProbe) view(c *ui.Context) {
|
||||
p.asyncValues = append(p.asyncValues, v)
|
||||
}
|
||||
}
|
||||
FormItem(f, "email", &p.email, opts, func() *ui.Element {
|
||||
FormItem(c, f, "email", &p.email, opts, func() *ui.Element {
|
||||
return InputGroup(c, &p.email, InputGroupOptions{Invalid: p.st.Error("email") != ""}).Input
|
||||
})
|
||||
FormItem(f, "tags", &p.tags, FormItemOptions[[]string]{Label: "Tags", Required: true, Initial: []string{"rose"}}, func() *ui.Element {
|
||||
FormItem(c, f, "tags", &p.tags, FormItemOptions[[]string]{Label: "Tags", Required: true, Initial: []string{"rose"}}, func() *ui.Element {
|
||||
return TagsInput(c, &p.tags, TagsInputOptions{}).Input
|
||||
})
|
||||
})
|
||||
@@ -222,7 +222,7 @@ func TestFormResetClearsControlState(t *testing.T) {
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
Use(c, Settings{})
|
||||
Form(c, &st, FormOptions{}, func(f *FormScope) {
|
||||
FormItem(f, "tags", &tags, FormItemOptions[[]string]{Label: "Tags"}, func() *ui.Element {
|
||||
FormItem(c, f, "tags", &tags, FormItemOptions[[]string]{Label: "Tags"}, func() *ui.Element {
|
||||
return TagsInput(c, &tags, TagsInputOptions{Validate: func(s string) string {
|
||||
seen = s
|
||||
return "Invalid tag"
|
||||
@@ -289,13 +289,13 @@ func TestFormCrossFieldRuleAtSettle(t *testing.T) {
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
Use(c, Settings{})
|
||||
res := Form(c, &st, FormOptions{}, func(f *FormScope) {
|
||||
FormItem(f, "user", &user, FormItemOptions[string]{Label: "User", Async: func(_ string, v uint64) { version = v }}, func() *ui.Element {
|
||||
FormItem(c, f, "user", &user, FormItemOptions[string]{Label: "User", Async: func(_ string, v uint64) { version = v }}, func() *ui.Element {
|
||||
return InputGroup(c, &user, InputGroupOptions{}).Input
|
||||
})
|
||||
FormItem(f, "pw", &pw, FormItemOptions[string]{Label: "Password"}, func() *ui.Element {
|
||||
FormItem(c, f, "pw", &pw, FormItemOptions[string]{Label: "Password"}, func() *ui.Element {
|
||||
return InputGroup(c, &pw, InputGroupOptions{}).Input
|
||||
})
|
||||
FormItem(f, "confirm", &confirm, FormItemOptions[string]{Label: "Confirm", Validate: func(v string) string {
|
||||
FormItem(c, f, "confirm", &confirm, FormItemOptions[string]{Label: "Confirm", Validate: func(v string) string {
|
||||
if v != pw {
|
||||
return "Passwords differ."
|
||||
}
|
||||
|
||||
@@ -6,12 +6,6 @@ import (
|
||||
"github.com/egoist/mygo/ui"
|
||||
)
|
||||
|
||||
// Rule draws a pixel-aligned 1 DIP horizontal line at y.
|
||||
func Rule(p *ui.Painter, x0, x1, y float32, c ui.Color) {
|
||||
yy := ruleY(p, y)
|
||||
p.Line(x0, yy, x1, yy, 1, c)
|
||||
}
|
||||
|
||||
// ruleY moves y to where a 1 DIP line fills whole device pixels.
|
||||
func ruleY(p *ui.Painter, y float32) float32 {
|
||||
s := float64(p.Scale())
|
||||
|
||||
Reference in new issue
Block a user