diff --git a/ui/allg5ui/renderer.go b/ui/allg5ui/renderer.go index 1277c63..eb5c770 100644 --- a/ui/allg5ui/renderer.go +++ b/ui/allg5ui/renderer.go @@ -267,8 +267,12 @@ func key(key allg5.Key) ui.Key { return ui.KeyDelete case allg5.KeyDown: return ui.KeyDown + case allg5.KeyEnd: + return ui.KeyEnd case allg5.KeyEscape: return ui.KeyEscape + case allg5.KeyHome: + return ui.KeyHome case allg5.KeyLeft: return ui.KeyLeft case allg5.KeyRight: diff --git a/ui/button.go b/ui/button.go index 735f091..546c43a 100644 --- a/ui/button.go +++ b/ui/button.go @@ -43,10 +43,7 @@ func (b *Button) desiredSize(ctx Context) geom.PointF32 { w += pad + font.WidthOf(b.Text) } if b.Icon != nil && b.Icon.Height() > 0 { - iconW := b.Icon.Width() * h / b.Icon.Height() - if b.IconScale > 0 { - iconW *= b.IconScale - } + iconW := b.scale(b.Icon.Width() * h / b.Icon.Height()) w += pad + iconW } if w == 0 { @@ -88,6 +85,13 @@ func (b *Button) fillColor(p *Palette) color.Color { return nil } +func (b *Button) scale(f float32) float32 { + if b.IconScale == 0 { + return f + } + return b.IconScale * f +} + func (b *Button) textColor(p *Palette) color.Color { if b.Font.Color != nil { return b.Font.Color @@ -123,7 +127,7 @@ func (b *Button) Render(ctx Context) { bounds = bounds.Inset(pad) pos := bounds.Min if b.Icon != nil && b.Icon.Height() > 0 { - icon, _ := ctx.Images().ScaledHeight(b.Icon, b.IconScale*bounds.Dy()) + icon, _ := ctx.Images().ScaledHeight(b.Icon, b.scale(bounds.Dy())) if icon != nil { ctx.Renderer().DrawImageOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: textColor}) pos.X += icon.Width() + pad diff --git a/ui/event.go b/ui/event.go index dce60f6..1b95113 100644 --- a/ui/event.go +++ b/ui/event.go @@ -30,7 +30,9 @@ const ( KeyBackspace KeyDelete KeyDown + KeyEnd KeyEscape + KeyHome KeyLeft KeyRight KeyUp @@ -39,7 +41,7 @@ const ( type KeyModifier int const ( - KeyModifiersNone KeyModifier = 0 + KeyModifierNone KeyModifier = 0 KeyModifierShift = 1 << iota KeyModifierControl KeyModifierAlt diff --git a/ui/examples/01_basic/basic.go b/ui/examples/01_basic/basic.go index c8a1c8d..51af6a2 100644 --- a/ui/examples/01_basic/basic.go +++ b/ui/examples/01_basic/basic.go @@ -38,6 +38,7 @@ func run() error { }) } + var style = ui.DefaultStyle() var view = ui.BuildStackPanel(ui.OrientationVertical, func(p *ui.StackPanel) { p.Background = color.White p.Children = []ui.Control{ @@ -50,11 +51,6 @@ func run() error { stretch(ui.BuildIconButton(plus, "Text", func(b *ui.Button) { b.Type = ui.ButtonTypeText }), 8), } }), - ui.Margin(ui.BuildButton("Quit", func(b *ui.Button) { - b.OnClick(func(ctx ui.Context, _ ui.Control, _ geom.PointF32, _ ui.MouseButton) { - ctx.Quit() - }) - }), 8), ui.BuildStackPanel(ui.OrientationHorizontal, func(p *ui.StackPanel) { p.Children = []ui.Control{ &ui.Checkbox{}, @@ -62,14 +58,22 @@ func run() error { } }), ui.Stretch(&ui.Label{Text: "Content"}), - ui.StretchWidth(ui.BuildTextBox(func(b *ui.TextBox) { + ui.Margin(ui.StretchWidth(ui.BuildTextBox(func(b *ui.TextBox) { b.Text = "Type here..." - })), - &ui.Label{Text: "Status"}, + })), 8), + ui.Margin(ui.BuildButton("Quit", func(b *ui.Button) { + b.OnClick(func(ctx ui.Context, _ ui.Control, _ geom.PointF32, _ ui.MouseButton) { + ctx.Quit() + }) + }), 8), + ui.BuildLabel("Status...", func(l *ui.Label) { + l.Background = style.Palette.PrimaryDark + l.Font.Color = style.Palette.TextOnPrimary + }), } }) - return ui.RunWait(render, ui.DefaultStyle(), view, true) + return ui.RunWait(render, style, view, true) } func main() { diff --git a/ui/textbox.go b/ui/textbox.go index db23d23..935fa61 100644 --- a/ui/textbox.go +++ b/ui/textbox.go @@ -3,6 +3,7 @@ package ui import ( "fmt" "image/color" + "strings" "time" "unicode" @@ -149,7 +150,16 @@ func (b *TextBox) Handle(ctx Context, e Event) { b.Selection.End = b.Selection.Caret } case *KeyPressEvent: - if b.Focus { + if !b.Focus { + break + } + selectAfterMove := func() { + if e.Modifiers&KeyModifierShift == KeyModifierShift { + b.Selection.End = b.Selection.Caret + } else { + b.Selection.SetSelectionToCaret() + } + } switch { case e.Key == KeyDelete: if b.Selection.HasSelection() { @@ -168,28 +178,27 @@ func (b *TextBox) Handle(ctx Context, e Event) { if caret > 0 { b.Text = b.Text[:caret-1] + b.Text[caret:] b.Selection.Caret = caret - 1 + b.Selection.SetSelectionToCaret() } } + case e.Key == KeyEnd: + b.Selection.Caret = len(b.Text) + selectAfterMove() + case e.Key == KeyHome: + b.Selection.Caret = 0 + selectAfterMove() case e.Key == KeyLeft: if b.Selection.Caret > 0 { b.Selection.MoveCaret(-1) - if e.Modifiers&KeyModifierShift == KeyModifierShift { - b.Selection.End = b.Selection.Caret - } else { - b.Selection.SetSelectionToCaret() - } + selectAfterMove() } case e.Key == KeyRight: if b.Selection.Caret < len(b.Text) { b.Selection.MoveCaret(1) - if e.Modifiers&KeyModifierShift == KeyModifierShift { - b.Selection.End = b.Selection.Caret - } else { - b.Selection.SetSelectionToCaret() - } + selectAfterMove() } case !unicode.IsControl(e.Character): - if e.Modifiers == KeyModifiersNone { + if e.Modifiers == KeyModifierNone { b.cut() caret := b.Selection.Caret b.Text = fmt.Sprintf("%s%c%s", b.Text[:caret], e.Character, b.Text[caret:]) @@ -204,6 +213,12 @@ func (b *TextBox) Handle(ctx Context, e Event) { DefaultClipboard.WriteText(b.selection()) case 'v': text, err := DefaultClipboard.ReadText() + text = strings.Map(func(r rune) rune { + if unicode.IsControl(r) { + return -1 + } + return r + }, text) if err == nil { b.cut() caret := b.Selection.Caret @@ -216,6 +231,8 @@ func (b *TextBox) Handle(ctx Context, e Event) { } } } + if b.over { + ctx.Renderer().SetMouseCursor(MouseCursorText) } ctx.Animate() }