Skip to content

Commit

Permalink
changed how slave windows work
Browse files Browse the repository at this point in the history
  • Loading branch information
aarzilli committed Dec 20, 2017
1 parent 5a87d76 commit 3e1ed2a
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 355 deletions.
60 changes: 2 additions & 58 deletions _demo/demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ func id(fn func (*nucular.Window)) func () func(*nucular.Window) {
}
}

func saveFnFor(i byte) func() []byte {
return func() []byte {
return []byte{ i }
}
}

type Demo struct {
Name string
Title string
Expand Down Expand Up @@ -76,16 +70,6 @@ var demos = []Demo{
} },
{ "nestedmenu", "Nested menu demo", 0, id(nestedMenu) },
{ "list", "List", nucular.WindowNoScrollbar, id(listDemo) },
{ "saverestore", "Save / Restore", nucular.WindowNoScrollbar, nil },
}

func init() {
for i := range demos {
if demos[i].Name == "saverestore" {
demos[i].UpdateFn = saveRestoreDemo
return
}
}
}

var Wnd nucular.MasterWindow
Expand Down Expand Up @@ -114,7 +98,7 @@ func main() {
switch whichdemo {
case "multi", "":
Wnd = nucular.NewMasterWindow(0, "Multiwindow Demo", func(w *nucular.Window) {})
Wnd.PopupOpenPersistent("Multiwindow Demo", nucular.WindowTitle|nucular.WindowBorder | nucular.WindowMovable | nucular.WindowScalable|nucular.WindowNonmodal, rect.Rect{ 0, 0, 400, 300 }, true, multiDemo, saveFnFor('m'))
Wnd.PopupOpen("Multiwindow Demo", nucular.WindowTitle|nucular.WindowBorder | nucular.WindowMovable | nucular.WindowScalable|nucular.WindowNonmodal, rect.Rect{ 0, 0, 400, 300 }, true, multiDemo)
default:
for i := range demos {
if demos[i].Name == whichdemo {
Expand Down Expand Up @@ -353,47 +337,7 @@ func multiDemo(w *nucular.Window) {
w.Row(30).Static(100, 100, 100)
for i := range demos {
if w.ButtonText(demos[i].Name) {
w.Master().PopupOpenPersistent(demos[i].Title, nucular.WindowDefaultFlags|nucular.WindowNonmodal | demos[i].Flags, rect.Rect{0, 0, 200, 200}, true, demos[i].UpdateFn(), saveFnFor(byte(i)))
}
}
}

func restoreFn(data []byte, openWndFn nucular.OpenWindowFn) error {
if data[0] == 'm' {
openWndFn("Multiwindow Demo", nucular.WindowTitle|nucular.WindowBorder | nucular.WindowMovable | nucular.WindowScalable|nucular.WindowNonmodal, multiDemo, saveFnFor('m'))
return nil
}
i := data[0]
openWndFn(demos[i].Title, nucular.WindowDefaultFlags|nucular.WindowNonmodal | demos[i].Flags, demos[i].UpdateFn(), saveFnFor(byte(i)))
return nil
}

func saveRestoreDemo() func(w *nucular.Window) {
var saveed nucular.TextEditor
saveed.Flags = nucular.EditSelectable | nucular.EditClipboard
wd, _ := os.Getwd()
saveed.Buffer = []rune(fmt.Sprintf("%s/save.sav", wd))
return func(w *nucular.Window) {
w.Row(30).Static(0)
saveed.Edit(w)
w.Row(30).Static(0, 100, 100)
w.Spacing(1)
if w.ButtonText("Save") {
s, err := w.Master().Save()
if err != nil {
fmt.Fprintf(os.Stderr, "Error saving layout: %v", err)
}
ioutil.WriteFile(string(saveed.Buffer), s, 0666)
w.Close()
}
if w.ButtonText("Restore") {
data, err := ioutil.ReadFile(string(saveed.Buffer))
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading save file: %v", err)
} else {
w.Master().Restore(data, restoreFn)
}
w.Close()
w.Master().PopupOpen(demos[i].Title, nucular.WindowDefaultFlags|nucular.WindowNonmodal | demos[i].Flags, rect.Rect{0, 0, 200, 200}, true, demos[i].UpdateFn())
}
}
}
91 changes: 66 additions & 25 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,29 @@ func (ctx *context) Restack() {
})
}

func (ctx *context) Walk(fn WindowWalkFn) {
fn(ctx.Windows[0].title, ctx.Windows[0].Data, false, 0, ctx.Windows[0].Bounds)
ctx.DockedWindows.walkExt(func(t *dockedTree) {
switch t.Type {
case dockedNodeHoriz:
fn("", nil, true, t.Split.Size, rect.Rect{})
case dockedNodeVert:
fn("", nil, true, -t.Split.Size, rect.Rect{})
case dockedNodeLeaf:
if t.W == nil {
fn("", nil, true, 0, rect.Rect{})
} else {
fn(t.W.title, t.W.Data, true, 0, t.W.Bounds)
}
}
})
for _, win := range ctx.Windows[1:] {
if win.flags&WindowNonmodal != 0 {
fn(win.title, win.Data, false, 0, win.Bounds)
}
}
}

func (ctx *context) restackClick(w *Window) bool {
if !ctx.Input.Mouse.valid {
return false
Expand All @@ -227,26 +250,6 @@ func (ctx *context) restackClick(w *Window) bool {
return false
}

func (w *masterWindow) ListWindowsData() []interface{} {
return w.ctx.ListWindowsData()
}

func (ctx *context) ListWindowsData() []interface{} {
r := []interface{}{}
ctx.DockedWindows.Walk(func(w *Window) *Window {
if w.Data != nil {
r = append(r, w.Data)
}
return w
})
for _, w := range ctx.Windows {
if w.Data != nil {
r = append(r, w.Data)
}
}
return r
}

var cnt = 0
var ln, frect, brrect, frrect, ftri, circ, fcirc, txt int

Expand Down Expand Up @@ -697,19 +700,26 @@ func (t *dockedTree) Update(bounds rect.Rect, scaling float64) *dockedTree {
return t
}

func (t *dockedTree) Walk(fn func(win *Window) *Window) {
func (t *dockedTree) walkExt(fn func(t *dockedTree)) {
if t == nil {
return
}
switch t.Type {
case dockedNodeVert, dockedNodeHoriz:
t.Child[0].Walk(fn)
t.Child[1].Walk(fn)
fn(t)
t.Child[0].walkExt(fn)
t.Child[1].walkExt(fn)
case dockedNodeLeaf:
if t.W != nil {
fn(t)
}
}

func (t *dockedTree) Walk(fn func(t *Window) *Window) {
t.walkExt(func(t *dockedTree) {
if t.Type == dockedNodeLeaf && t.W != nil {
t.W = fn(t.W)
}
}
})
}

func newDockedLeaf(win *Window) *dockedTree {
Expand Down Expand Up @@ -851,6 +861,37 @@ func (t *dockedTree) Scale(win *Window, delta image.Point, scaling float64) imag
return image.ZP
}

func (ctx *context) ResetWindows() *DockSplit {
ctx.DockedWindows = dockedTree{}
ctx.Windows = ctx.Windows[:1]
ctx.dockedCnt = 0
return &DockSplit{ctx, &ctx.DockedWindows}
}

type DockSplit struct {
ctx *context
node *dockedTree
}

func (ds *DockSplit) Split(horiz bool, size int) (left, right *DockSplit) {
if horiz {
ds.node.Type = dockedNodeHoriz
} else {
ds.node.Type = dockedNodeVert
}
ds.node.Split.Size = size
ds.node.Child[0] = &dockedTree{Type: dockedNodeLeaf, Split: ScalableSplit{MinSize: 40}}
ds.node.Child[1] = &dockedTree{Type: dockedNodeLeaf, Split: ScalableSplit{MinSize: 40}}
return &DockSplit{ds.ctx, ds.node.Child[0]}, &DockSplit{ds.ctx, ds.node.Child[1]}
}

func (ds *DockSplit) Open(title string, flags WindowFlags, rect rect.Rect, scale bool, updateFn UpdateFn) {
ds.ctx.popupOpen(title, flags, rect, scale, updateFn)
ds.node.Type = dockedNodeLeaf
ds.node.W = ds.ctx.Windows[len(ds.ctx.Windows)-1]
ds.ctx.dockWindow(ds.node.W)
}

func percentages(bounds rect.Rect, f float64) (r [4]rect.Rect) {
pw := int(float64(bounds.W) * f)
ph := int(float64(bounds.H) * f)
Expand Down
41 changes: 16 additions & 25 deletions nucular.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
///////////////////////////////////////////////////////////////////////////////////

type UpdateFn func(*Window)
type SaveFn func() []byte

type Window struct {
LastWidgetBounds rect.Rect
Expand Down Expand Up @@ -54,7 +53,6 @@ type Window struct {
editor *TextEditor
// update function
updateFn UpdateFn
saveFn SaveFn
usingSub bool
began bool
rowCtor rowConstructor
Expand Down Expand Up @@ -719,7 +717,9 @@ func (win *Window) move(delta image.Point, pos image.Point) {
win.cmds.FillRect(bounds, 0, color.RGBA{0x0, 0x0, 0x50, 0x50})
}
win.Bounds.X = win.Bounds.X + delta.X
win.Bounds.X = clampInt(0, win.Bounds.X, win.ctx.Windows[0].Bounds.X+win.ctx.Windows[0].Bounds.W-FontHeight(win.ctx.Style.Font))
win.Bounds.Y = win.Bounds.Y + delta.Y
win.Bounds.Y = clampInt(0, win.Bounds.Y, win.ctx.Windows[0].Bounds.Y+win.ctx.Windows[0].Bounds.H-FontHeight(win.ctx.Style.Font))
}

func (win *Window) scale(delta image.Point) {
Expand Down Expand Up @@ -823,7 +823,7 @@ func panelLayout(ctx *context, win *Window, height int, cols int, cnt int) {
item_spacing := style.Spacing

if height == 0 {
height = layout.Clip.H - (layout.AtY - layout.Bounds.Y)
height = layout.Bounds.H - layout.FooterH - (layout.AtY - layout.Bounds.Y)
subtractHeight := true
if layout.Row.Index == 0 {
subtractHeight = false
Expand Down Expand Up @@ -1865,7 +1865,7 @@ func scrollbarBehavior(state *nstyle.WidgetStates, in *Input, scroll, cursor, em

func scrollwheelBehavior(win *Window, scroll, scrollwheel_bounds rect.Rect, scroll_offset, target, scroll_step float64) float64 {
in := &win.ctx.Input

if ((in.Mouse.ScrollDelta < 0) || (in.Mouse.ScrollDelta > 0)) && in.Mouse.HoveringRect(scrollwheel_bounds) {
/* update cursor by mouse scrolling */
old_scroll_offset := scroll_offset
Expand Down Expand Up @@ -2624,28 +2624,15 @@ func (mw *masterWindow) PopupOpen(title string, flags WindowFlags, rect rect.Rec
go func() {
mw.uilock.Lock()
defer mw.uilock.Unlock()
mw.ctx.popupOpen(title, flags, rect, scale, updateFn, nil)
mw.ctx.popupOpen(title, flags, rect, scale, updateFn)
mw.Changed()
}()
}

func (mw *masterWindow) PopupOpenPersistent(title string, flags WindowFlags, rect rect.Rect, scale bool, updateFn UpdateFn, saveFn SaveFn) {
if flags&WindowNonmodal == 0 && saveFn != nil {
panic("save function set on modal window")
}
go func() {
mw.uilock.Lock()
defer mw.uilock.Unlock()
mw.ctx.popupOpen(title, flags, rect, scale, updateFn, saveFn)
mw.Changed()
}()
}

func (ctx *context) popupOpen(title string, flags WindowFlags, rect rect.Rect, scale bool, updateFn UpdateFn, saveFn SaveFn) {
func (ctx *context) popupOpen(title string, flags WindowFlags, rect rect.Rect, scale bool, updateFn UpdateFn) {
popup := createWindow(ctx, title)
popup.idx = len(ctx.Windows)
popup.updateFn = updateFn
popup.saveFn = saveFn
if updateFn == nil {
panic("nil update function")
}
Expand All @@ -2671,12 +2658,16 @@ func (ctx *context) popupOpen(title string, flags WindowFlags, rect rect.Rect, s
func (ctx *context) autoPosition() (int, int) {
x, y := ctx.autopos.X, ctx.autopos.Y

ctx.autopos.X += ctx.scale(20)
ctx.autopos.Y += ctx.scale(20)
z := FontHeight(ctx.Style.Font) + 2.0*ctx.Style.NormalWindow.Header.Padding.Y

if ctx.autopos.X >= ctx.Windows[0].Bounds.W || ctx.autopos.Y >= ctx.Windows[0].Bounds.H {
ctx.autopos.X = 0
ctx.autopos.Y = 0
ctx.autopos.X += ctx.scale(z)
ctx.autopos.Y += ctx.scale(z)

if ctx.Windows[0].Bounds.W != 0 && ctx.Windows[0].Bounds.H != 0 {
if ctx.autopos.X >= ctx.Windows[0].Bounds.W || ctx.autopos.Y >= ctx.Windows[0].Bounds.H {
ctx.autopos.X = 0
ctx.autopos.Y = 0
}
}

return x, y
Expand Down Expand Up @@ -2774,7 +2765,7 @@ func (win *Window) TooltipOpen(width int, scale bool, updateFn UpdateFn) {
bounds.X = (in.Mouse.Pos.X + 1)
bounds.Y = (in.Mouse.Pos.Y + 1)

win.ctx.popupOpen(tooltipWindowTitle, WindowDynamic|WindowNoScrollbar|windowTooltip, bounds, false, updateFn, nil)
win.ctx.popupOpen(tooltipWindowTitle, WindowDynamic|WindowNoScrollbar|windowTooltip, bounds, false, updateFn)
}

// Shows a tooltip window containing the specified text.
Expand Down
Loading

0 comments on commit 3e1ed2a

Please sign in to comment.