From 28ab816bae1d8667da887b3632ae984d647c6687 Mon Sep 17 00:00:00 2001 From: Sander Schobers Date: Sun, 17 May 2020 16:13:26 +0200 Subject: [PATCH] Fixed intro dialog (and generic part of showing dialogs). --- cmd/tins2020/tins2020.go | 44 ++++++++---- dialogs.go | 68 +++++++++--------- iconbutton.go | 1 - intro.go | 9 ++- largedialog.go | 147 +++++++++++++++------------------------ research.go | 2 +- 6 files changed, 131 insertions(+), 140 deletions(-) diff --git a/cmd/tins2020/tins2020.go b/cmd/tins2020/tins2020.go index e6538e8..1973fdb 100644 --- a/cmd/tins2020/tins2020.go +++ b/cmd/tins2020/tins2020.go @@ -7,10 +7,13 @@ import ( "opslag.de/schobers/fs/ricefs" "opslag.de/schobers/geom" + "opslag.de/schobers/zntg" "opslag.de/schobers/zntg/addons/res" - _ "opslag.de/schobers/zntg/sdlui" // rendering backend "opslag.de/schobers/zntg/ui" + _ "opslag.de/schobers/zntg/sdlui" // rendering backend + // _ "opslag.de/schobers/zntg/allg5ui" // rendering backend + rice "github.com/GeertJohan/go.rice" "github.com/veandco/go-sdl2/sdl" "opslag.de/schobers/tins2020" @@ -91,17 +94,17 @@ func (a *app) Init(ctx ui.Context) error { return nil } -func (a *app) Handle(ctx ui.Context, event ui.Event) bool { - // switch e := event.(type) { - // case *ui.WindowMoved: - // // x, y := window.GetPosition() - // // settings.Window.Location = ptPtr(x, y) - // case *ui.WindowSizeChanged: - // w, h := window.GetSize() - // app.Arrange(ctx, geom.RectRelF32(0, 0, w, h)) - // settings.Window.Size = ptPtr(w, h) - // } - return a.Proxy.Handle(ctx, event) +func (a *app) Handle(ctx ui.Context, e ui.Event) bool { + switch e := e.(type) { + case *ui.DisplayMoveEvent: + location := e.Bounds.Min.ToInt() + a.settings.Window.Location = &location + case *ui.DisplayResizeEvent: + a.Arrange(ctx, e.Bounds, geom.ZeroPtF32, nil) + size := e.Bounds.Size().ToInt() + a.settings.Window.Size = &size + } + return a.Proxy.Handle(ctx, e) } func (a *app) Render(ctx ui.Context) { @@ -159,5 +162,20 @@ func run() error { dialogs: tins2020.NewDialogs(game), settings: settings, } - return ui.Run(renderer, nil, app) + style := ui.DefaultStyle() + style.Palette = &ui.Palette{ + Background: zntg.MustHexColor(`#5388C3`), + Primary: zntg.MustHexColor(`#5388C3`), + PrimaryDark: zntg.MustHexColor(`#15569F`), + PrimaryLight: zntg.MustHexColor(`#ABCAED`), + Secondary: zntg.MustHexColor(`#4AC69A`), + SecondaryDark: zntg.MustHexColor(`#0AA36D`), + SecondaryLight: zntg.MustHexColor(`#A6EED4`), + Text: color.White, + TextOnPrimary: color.White, + TextOnSecondary: color.White, + TextNegative: zntg.MustHexColor(`F3590E`), + TextPositive: zntg.MustHexColor(`65D80D`), + } + return ui.Run(renderer, style, app) } diff --git a/dialogs.go b/dialogs.go index 339dcfe..bcd8e0c 100644 --- a/dialogs.go +++ b/dialogs.go @@ -5,66 +5,72 @@ import ( ) type Dialogs struct { - intro ui.Overlay - settings ui.Overlay - research ui.Overlay + ui.OverlayProxy - open string + intro ui.Overlay + research ui.Overlay + settings ui.Overlay + nothing ui.Control closed ui.Events opened ui.Events } -const introDialogName = "dialog-intro" -const settingsDialogName = "dialog-settings" -const researchDialogName = "dialog-research" +const dialogsOverlayName = "dialogs" func NewDialogs(game *Game) *Dialogs { - return &Dialogs{ - intro: NewIntro(), - settings: &LargeDialog{}, - research: NewResearch(game), + intro := NewIntro() + research := NewResearch(game) + settings := NewLargeDialog("settings", &ui.Label{}) + + dialogs := &Dialogs{ + intro: intro, + settings: settings, + research: research, + nothing: &ui.ControlBase{}, } + + intro.CloseRequested().AddHandlerEmpty(dialogs.Close) + research.CloseRequested().AddHandlerEmpty(dialogs.Close) + settings.CloseRequested().AddHandlerEmpty(dialogs.Close) + + return dialogs } func (d *Dialogs) Init(ctx ui.Context) { overlays := ctx.Overlays() + overlays.AddOnTop(dialogsOverlayName, d, false) - overlays.AddOnTop(introDialogName, d.intro, false) - overlays.AddOnTop(settingsDialogName, d.settings, false) - overlays.AddOnTop(researchDialogName, d.research, false) + d.Content = d.nothing } -func (d *Dialogs) showDialog(ctx ui.Context, name string) { - d.Close(ctx) - - ctx.Overlays().Show(name) - d.open = name - - d.opened.Notify(ctx, name) +func (d *Dialogs) showDialog(ctx ui.Context, control ui.Control) { + if control == nil { + d.Content = d.nothing + ctx.Overlays().Hide(dialogsOverlayName) + d.closed.Notify(ctx, control) + } else { + d.Content = control + ctx.Overlays().Show(dialogsOverlayName) + d.opened.Notify(ctx, control) + } } func (d *Dialogs) Close(ctx ui.Context) { - name := d.open - if name == "" { - return - } - ctx.Overlays().Hide(name) - d.open = "" - d.closed.Notify(ctx, name) + d.showDialog(ctx, nil) } func (d *Dialogs) DialogClosed() ui.EventHandler { return &d.closed } func (d *Dialogs) DialogOpened() ui.EventHandler { return &d.opened } func (d *Dialogs) ShowIntro(ctx ui.Context) { - d.showDialog(ctx, introDialogName) + d.showDialog(ctx, d.intro) } func (d *Dialogs) ShowResearch(ctx ui.Context) { - d.showDialog(ctx, researchDialogName) + d.showDialog(ctx, d.research) } func (d *Dialogs) ShowSettings(ctx ui.Context) { - d.showDialog(ctx, settingsDialogName) + d.showDialog(ctx, d.settings) } diff --git a/iconbutton.go b/iconbutton.go index dbfb691..bab76a5 100644 --- a/iconbutton.go +++ b/iconbutton.go @@ -19,7 +19,6 @@ type IconButton struct { ui.Button IconDisabled string - IconHeight int32 // IconScale Scale // IconWidth int32 diff --git a/intro.go b/intro.go index 3e71d29..818a099 100644 --- a/intro.go +++ b/intro.go @@ -1,13 +1,18 @@ package tins2020 -import "opslag.de/schobers/zntg/ui" +import ( + "image/color" + + "opslag.de/schobers/zntg/ui" +) type Intro struct { ui.Paragraph } -func NewIntro() ui.Overlay { +func NewIntro() *LargeDialog { i := &Intro{} + i.Font.Color = color.White i.Text = "Welcome to Botanim!\n\n" + "In Botanim you play the role of botanist and your goal is to cultivate flowers in an open landscape.\n\n" + diff --git a/largedialog.go b/largedialog.go index 57788ac..27dba21 100644 --- a/largedialog.go +++ b/largedialog.go @@ -1,49 +1,13 @@ package tins2020 import ( + "image/color" + + "opslag.de/schobers/geom" "opslag.de/schobers/zntg" "opslag.de/schobers/zntg/ui" ) -// type DialogBase struct { -// } - -// type Dialog interface { -// CloseDialog() -// OnShow() zntg.EventHandler -// ShowDialog(ui.Context, zntg.EventFn) -// } - -// func (d *DialogBase) CloseDialog() { -// close := d.close -// if close != nil { -// close() -// } -// } - -// func (d *DialogBase) Init(ctx ui.Context) error { -// d.AddChild(&d.content) -// return d.Container.Init(ctx) -// } - -// func (d *DialogBase) OnShow() zntg.EventHandler { -// if d.onShow == nil { -// d.onShow = NewEvents() -// } -// return d.onShow -// } - -// func (d *DialogBase) SetContent(control ui.Control) { -// d.content.Proxied = control -// } - -// func (d *DialogBase) ShowDialog(ctx ui.Context, close zntg.EventFn) { -// d.close = close -// if d.onShow != nil { -// d.onShow.Notify(ctx) -// } -// } - type LargeDialog struct { ui.StackPanel @@ -51,14 +15,12 @@ type LargeDialog struct { content ui.OverlayProxy closeRequested ui.Events - - onShow zntg.Events - close zntg.EventFn } func NewLargeDialog(title string, content ui.Control) *LargeDialog { dialog := &LargeDialog{} + dialog.Orientation = ui.OrientationVertical dialog.titleBar = NewLargeDialogTitleBar(title, func(ctx ui.Context, state interface{}) { dialog.closeRequested.Notify(ctx, state) }) @@ -68,8 +30,39 @@ func NewLargeDialog(title string, content ui.Control) *LargeDialog { return dialog } +func (d *LargeDialog) CloseRequested() ui.EventHandler { return &d.closeRequested } + +// func (d *LargeDialog) Arrange(ctx ui.Context, bounds geom.RectangleF32, offset geom.PointF32, parent ui.Control) { +// d.titleBar.Arrange(ctx, bounds.Min.RectRel2D(bounds.Dx(), titleHeight), offset, d) +// d.content.Arrange(ctx, geom.RectRelF32(bounds.Min.X+titleHeight, bounds.Min.Y, bounds.Dx(), bounds.Dy()-titleHeight), offset, d) +// } + +func (d *LargeDialog) Handle(ctx ui.Context, e ui.Event) bool { + if d.StackPanel.Handle(ctx, e) { + return true + } + + switch e := e.(type) { + case *ui.KeyDownEvent: + switch e.Key { + case ui.KeyEscape: + d.closeRequested.Notify(ctx, nil) + return true + case ui.KeyEnter: + d.closeRequested.Notify(ctx, nil) + return true + } + } + return false +} + func (d *LargeDialog) Hidden() { d.content.Hidden() } +func (d *LargeDialog) Render(ctx ui.Context) { + ctx.Renderer().Clear(zntg.MustHexColor("#356DAD")) + d.StackPanel.Render(ctx) +} + func (d *LargeDialog) Shown() { d.content.Shown() } type LargeDialogTitleBar struct { @@ -85,57 +78,27 @@ func NewLargeDialogTitleBar(title string, closeRequested ui.EventFn) *LargeDialo titleBar.close.ButtonClicked().AddHandler(func(ctx ui.Context, args ui.ControlClickedArgs) { closeRequested(ctx, args) }) + titleBar.title.Font.Color = color.White + titleBar.title.Font.Name = "title" + titleBar.title.Text = title + titleBar.title.TextAlignment = ui.AlignCenter + + titleBar.close.Icon = "control-cancel" + titleBar.close.IconHeight = 32 + titleBar.close.Type = ui.ButtonTypeIcon + return titleBar } -// func (d *LargeDialog) Arrange(ctx ui.Context, bounds Rectangle) { -// const titleHeight = 64 -// d.ControlBase.Arrange(ctx, bounds) -// d.title.Arrange(ctx, Rect(bounds.X, bounds.Y, bounds.W, titleHeight)) -// d.close.Arrange(ctx, Rect(bounds.W-64, 0, 64, 64)) -// d.content.Arrange(ctx, Rect(bounds.X+titleHeight, 96, bounds.W-2*titleHeight, bounds.H-titleHeight)) -// } +func (b *LargeDialogTitleBar) Arrange(ctx ui.Context, bounds geom.RectangleF32, offset geom.PointF32, parent ui.Control) { + b.ControlBase.Arrange(ctx, bounds, offset, parent) + b.title.Arrange(ctx, bounds, offset, parent) + height := bounds.Dy() + b.close.Arrange(ctx, geom.RectRelF32(bounds.Max.X-height, bounds.Min.Y, height, height), offset, parent) + b.close.HoverColor = ctx.Style().Palette.PrimaryDark +} -// func (d *LargeDialog) Init(ctx ui.Context) error { -// d.title.Text = "Botanim" -// d.title.FontName = "title" -// d.title.Alignment = TextAlignmentCenter - -// d.close = IconButton{ -// Icon: "control-cancel", -// IconHover: HoverEffectColor, -// IconWidth: 32, -// } -// d.close.OnLeftMouseButtonClick = EmptyEvent(d.CloseDialog) -// d.AddChild(&d.title) -// d.AddChild(&d.close) -// return d.DialogBase.Init(ctx) -// } - -// func (d *LargeDialog) Handle(ctx ui.Context, event sdl.Event) bool { -// if d.DialogBase.Handle(ctx, event) { -// return true -// } - -// switch e := event.(type) { -// case *sdl.KeyboardEvent: -// if e.Type == sdl.KEYDOWN { -// switch e.Keysym.Sym { -// case sdl.K_ESCAPE: -// d.CloseDialog() -// return true -// case sdl.K_RETURN: -// d.CloseDialog() -// return true -// } -// } -// } -// return false -// } - -// func (d *LargeDialog) Render(ctx ui.Context) { -// SetDrawColor(ctx.Renderer, MustHexColor("#356DAD")) -// ctx.Renderer.FillRect(d.Bounds.SDLPtr()) - -// d.DialogBase.Render(ctx) -// } +func (b *LargeDialogTitleBar) DesiredSize(ctx ui.Context, size geom.PointF32) geom.PointF32 { + const titleHeight = 64 + return geom.PtF32(size.X, titleHeight) +} diff --git a/research.go b/research.go index 44df0d0..488a3d0 100644 --- a/research.go +++ b/research.go @@ -32,7 +32,7 @@ type Research struct { animate zntg.Animation } -func NewResearch(game *Game) ui.Overlay { +func NewResearch(game *Game) *LargeDialog { research := &Research{game: game} research.animate.Interval = 20 * time.Millisecond