parent
4206330398
commit
e675ead0ed
11 changed files with 534 additions and 22 deletions
@ -0,0 +1,11 @@ |
||||
.PHONY: run |
||||
run: |
||||
go run main.go
|
||||
|
||||
.PHONY: wasm |
||||
wasm: |
||||
GOOS=js GOARCH=wasm go build -v -o windows.wasm main_wasm.go
|
||||
|
||||
.PHONY: wasm-serve |
||||
wasm-serve: wasm |
||||
../wasm-common/serve.sh
|
@ -0,0 +1,107 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"os" |
||||
|
||||
"git.kirsle.net/go/render" |
||||
"git.kirsle.net/go/render/event" |
||||
"git.kirsle.net/go/render/sdl" |
||||
"git.kirsle.net/go/ui" |
||||
"git.kirsle.net/go/ui/theme" |
||||
) |
||||
|
||||
// Program globals.
|
||||
var ( |
||||
// Size of the MainWindow.
|
||||
Width = 1024 |
||||
Height = 768 |
||||
) |
||||
|
||||
func init() { |
||||
sdl.DefaultFontFilename = "../DejaVuSans.ttf" |
||||
} |
||||
|
||||
func main() { |
||||
mw, err := ui.NewMainWindow("Theme Demo", Width, Height) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
// Menu bar.
|
||||
menu := ui.NewMenuBar("Main Menu") |
||||
file := menu.AddMenu("Select Theme") |
||||
file.AddItem("Default", func() { |
||||
addWindow(mw, theme.Default) |
||||
}) |
||||
file.AddItem("DefaultFlat", func() { |
||||
addWindow(mw, theme.DefaultFlat) |
||||
}) |
||||
file.AddItem("DefaultDark", func() { |
||||
addWindow(mw, theme.DefaultDark) |
||||
}) |
||||
|
||||
menu.Supervise(mw.Supervisor()) |
||||
menu.Compute(mw.Engine) |
||||
mw.Pack(menu, menu.PackTop()) |
||||
|
||||
mw.SetBackground(render.White) |
||||
|
||||
mw.OnLoop(func(e *event.State) { |
||||
if e.Escape { |
||||
os.Exit(0) |
||||
} |
||||
}) |
||||
|
||||
mw.MainLoop() |
||||
} |
||||
|
||||
// Add a new child window.
|
||||
func addWindow(mw *ui.MainWindow, theme theme.Theme) { |
||||
ui.Theme = theme |
||||
|
||||
win1 := ui.NewWindow(theme.Name) |
||||
win1.SetButtons(ui.CloseButton) |
||||
win1.Configure(ui.Config{ |
||||
Width: 320, |
||||
Height: 240, |
||||
}) |
||||
win1.Compute(mw.Engine) |
||||
win1.Supervise(mw.Supervisor()) |
||||
|
||||
// Draw a label.
|
||||
label := ui.NewLabel(ui.Label{ |
||||
Text: theme.Name, |
||||
}) |
||||
win1.Place(label, ui.Place{ |
||||
Top: 10, |
||||
Left: 10, |
||||
}) |
||||
|
||||
// Add a button with tooltip.
|
||||
btn2 := ui.NewButton(theme.Name+":Button2", ui.NewLabel(ui.Label{ |
||||
Text: "Button", |
||||
})) |
||||
btn2.Handle(ui.Click, func(ed ui.EventData) error { |
||||
return nil |
||||
}) |
||||
mw.Add(btn2) |
||||
win1.Place(btn2, ui.Place{ |
||||
Top: 10, |
||||
Right: 10, |
||||
}) |
||||
ui.NewTooltip(btn2, ui.Tooltip{ |
||||
Text: "Hello world!", |
||||
Edge: ui.Bottom, |
||||
}) |
||||
|
||||
// Add a checkbox.
|
||||
var b bool |
||||
cb := ui.NewCheckbox("Checkbox", &b, ui.NewLabel(ui.Label{ |
||||
Text: "Check me!", |
||||
})) |
||||
mw.Add(cb) |
||||
win1.Place(cb, ui.Place{ |
||||
Top: 30, |
||||
Left: 10, |
||||
}) |
||||
} |
@ -0,0 +1,169 @@ |
||||
// +build js,wasm
|
||||
|
||||
// WebAssembly version of the window manager demo.
|
||||
// To build: make wasm
|
||||
// To test: make wasm-serve
|
||||
|
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"time" |
||||
|
||||
"git.kirsle.net/go/render" |
||||
"git.kirsle.net/go/render/canvas" |
||||
"git.kirsle.net/go/ui" |
||||
) |
||||
|
||||
// Program globals.
|
||||
var ( |
||||
ThrottleFPS = 1000 / 60 |
||||
|
||||
// Size of the MainWindow.
|
||||
Width = 1024 |
||||
Height = 768 |
||||
|
||||
// Cascade offset for creating multiple windows.
|
||||
Cascade = render.NewPoint(10, 32) |
||||
CascadeStep = render.NewPoint(24, 24) |
||||
CascadeLoops = 1 |
||||
|
||||
// Colors for each window created.
|
||||
WindowColors = []render.Color{ |
||||
render.Blue, |
||||
render.Red, |
||||
render.DarkYellow, |
||||
render.DarkGreen, |
||||
render.DarkCyan, |
||||
render.DarkBlue, |
||||
render.DarkRed, |
||||
} |
||||
WindowID int |
||||
OpenWindows int |
||||
) |
||||
|
||||
func main() { |
||||
mw, err := canvas.New("canvas") |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
// Bind DOM event handlers.
|
||||
mw.AddEventListeners() |
||||
|
||||
supervisor := ui.NewSupervisor() |
||||
|
||||
frame := ui.NewFrame("Main Frame") |
||||
frame.Resize(render.NewRect(mw.WindowSize())) |
||||
frame.Compute(mw) |
||||
|
||||
_, height := mw.WindowSize() |
||||
lbl := ui.NewLabel(ui.Label{ |
||||
Text: "Window Manager Demo", |
||||
Font: render.Text{ |
||||
FontFilename: "DejaVuSans.ttf", |
||||
Size: 32, |
||||
Color: render.SkyBlue, |
||||
Shadow: render.SkyBlue.Darken(60), |
||||
}, |
||||
}) |
||||
lbl.Compute(mw) |
||||
lbl.MoveTo(render.NewPoint( |
||||
20, |
||||
height-lbl.Size().H-20, |
||||
)) |
||||
|
||||
// Menu bar.
|
||||
menu := ui.NewMenuBar("Main Menu") |
||||
file := menu.AddMenu("Options") |
||||
file.AddItem("New window", func() { |
||||
addWindow(mw, frame, supervisor) |
||||
}) |
||||
file.AddItem("Close all windows", func() { |
||||
OpenWindows -= supervisor.CloseAllWindows() |
||||
}) |
||||
|
||||
menu.Supervise(supervisor) |
||||
menu.Compute(mw) |
||||
frame.Pack(menu, menu.PackTop()) |
||||
|
||||
// Add some windows to play with.
|
||||
addWindow(mw, frame, supervisor) |
||||
addWindow(mw, frame, supervisor) |
||||
|
||||
for { |
||||
mw.Clear(render.RGBA(255, 255, 200, 255)) |
||||
start := time.Now() |
||||
ev, err := mw.Poll() |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
frame.Present(mw, frame.Point()) |
||||
lbl.Present(mw, lbl.Point()) |
||||
supervisor.Loop(ev) |
||||
supervisor.Present(mw) |
||||
|
||||
var delay uint32 |
||||
elapsed := time.Now().Sub(start) |
||||
tmp := elapsed / time.Millisecond |
||||
if ThrottleFPS-int(tmp) > 0 { |
||||
delay = uint32(ThrottleFPS - int(tmp)) |
||||
} |
||||
mw.Delay(delay) |
||||
} |
||||
} |
||||
|
||||
// Add a new child window.
|
||||
func addWindow(engine render.Engine, parent *ui.Frame, sup *ui.Supervisor) { |
||||
var ( |
||||
color = WindowColors[WindowID%len(WindowColors)] |
||||
title = fmt.Sprintf("Window %d", WindowID+1) |
||||
) |
||||
WindowID++ |
||||
|
||||
win1 := ui.NewWindow(title) |
||||
win1.SetButtons(ui.CloseButton) |
||||
win1.ActiveTitleBackground = color |
||||
win1.InactiveTitleBackground = color.Darken(60) |
||||
win1.InactiveTitleForeground = render.Grey |
||||
win1.Configure(ui.Config{ |
||||
Width: 320, |
||||
Height: 240, |
||||
}) |
||||
win1.Compute(engine) |
||||
win1.Supervise(sup) |
||||
|
||||
// Re-open a window when the last one is closed.
|
||||
OpenWindows++ |
||||
win1.Handle(ui.CloseWindow, func(ed ui.EventData) error { |
||||
OpenWindows-- |
||||
if OpenWindows <= 0 { |
||||
addWindow(engine, parent, sup) |
||||
} |
||||
return nil |
||||
}) |
||||
|
||||
// Default placement via cascade.
|
||||
win1.MoveTo(Cascade) |
||||
Cascade.Add(CascadeStep) |
||||
if Cascade.Y > Height-240-64 { |
||||
CascadeLoops++ |
||||
Cascade.Y = 24 |
||||
Cascade.X = 24 * CascadeLoops |
||||
} |
||||
|
||||
// Add a window duplicator button.
|
||||
btn2 := ui.NewButton(title+":Button2", ui.NewLabel(ui.Label{ |
||||
Text: "New Window", |
||||
})) |
||||
btn2.Handle(ui.Click, func(ed ui.EventData) error { |
||||
addWindow(engine, parent, sup) |
||||
return nil |
||||
}) |
||||
sup.Add(btn2) |
||||
win1.Place(btn2, ui.Place{ |
||||
Top: 10, |
||||
Right: 10, |
||||
}) |
||||
} |
@ -0,0 +1,71 @@ |
||||
// Package style provides style definitions for UI components.
|
||||
package style |
||||
|
||||
import "git.kirsle.net/go/render" |
||||
|
||||
// Default styles for widgets without a theme.
|
||||
var ( |
||||
DefaultWindow = Window{ |
||||
ActiveTitleBackground: render.Blue, |
||||
ActiveTitleForeground: render.White, |
||||
InactiveTitleBackground: render.DarkGrey, |
||||
InactiveTitleForeground: render.Grey, |
||||
ActiveBackground: render.Grey, |
||||
InactiveBackground: render.Grey, |
||||
} |
||||
|
||||
DefaultLabel = Label{ |
||||
Background: render.Invisible, |
||||
Foreground: render.Black, |
||||
} |
||||
|
||||
DefaultButton = Button{ |
||||
Background: render.RGBA(200, 200, 200, 255), |
||||
Foreground: render.Black, |
||||
OutlineColor: render.Black, |
||||
OutlineSize: 1, |
||||
HoverBackground: render.RGBA(200, 255, 255, 255), |
||||
HoverForeground: render.Black, |
||||
BorderStyle: BorderRaised, |
||||
BorderSize: 2, |
||||
} |
||||
|
||||
DefaultTooltip = Tooltip{ |
||||
Background: render.RGBA(0, 0, 0, 230), |
||||
Foreground: render.White, |
||||
} |
||||
) |
||||
|
||||
// Window style configuration.
|
||||
type Window struct { |
||||
ActiveTitleBackground render.Color |
||||
ActiveTitleForeground render.Color |
||||
ActiveBackground render.Color |
||||
InactiveTitleBackground render.Color |
||||
InactiveTitleForeground render.Color |
||||
InactiveBackground render.Color |
||||
} |
||||
|
||||
// Label style configuration.
|
||||
type Label struct { |
||||
Background render.Color |
||||
Foreground render.Color |
||||
} |
||||
|
||||
// Button style configuration.
|
||||
type Button struct { |
||||
Background render.Color |
||||
Foreground render.Color // Labels only
|
||||
OutlineColor render.Color |
||||
OutlineSize int |
||||
HoverBackground render.Color |
||||
HoverForeground render.Color |
||||
BorderStyle BorderStyle |
||||
BorderSize int |
||||
} |
||||
|
||||
// Tooltip style configuration.
|
||||
type Tooltip struct { |
||||
Background render.Color |
||||
Foreground render.Color |
||||
} |
@ -0,0 +1,13 @@ |
||||
// Package style provides style definitions for UI components.
|
||||
package style |
||||
|
||||
// BorderStyle options for widget.SetBorderStyle()
|
||||
type BorderStyle string |
||||
|
||||
// Styles for a widget border.
|
||||
const ( |
||||
BorderNone BorderStyle = "" |
||||
BorderSolid BorderStyle = "solid" |
||||
BorderRaised = "raised" |
||||
BorderSunken = "sunken" |
||||
) |
@ -0,0 +1,6 @@ |
||||
package ui |
||||
|
||||
import "git.kirsle.net/go/ui/theme" |
||||
|
||||
// Theme sets the default theme used when creating new widgets.
|
||||
var Theme = theme.Default |
Loading…
Reference in new issue