diff --git a/_demo/demo.go b/_demo/demo.go index 3faf6ee..820f35d 100644 --- a/_demo/demo.go +++ b/_demo/demo.go @@ -18,16 +18,63 @@ import ( "golang.org/x/mobile/event/key" ) -var whichdemo int = 4 - const dotrace = false const scaling = 1.8 //var theme nucular.Theme = nucular.WhiteTheme var theme nstyle.Theme = nstyle.DarkTheme +func id(fn func (*nucular.Window)) func () func(*nucular.Window) { + return func() func(*nucular.Window) { + return fn + } +} + +type Demo struct { + Name string + Title string + Flags nucular.WindowFlags + UpdateFn func() func(*nucular.Window) +} + +var demos = []Demo{ + { "button", "Button Demo", 0, id(buttonDemo) }, + { "basic", "Basic Demo", 0, func() func(*nucular.Window) { + go func() { + for { + time.Sleep(1 * time.Second) + if Wnd.Closed() { + break + } + Wnd.Changed() + } + }() + return basicDemo + } }, + { "basic2", "Text Editor Demo", 0, textEditorDemo }, + { "calc", "Calculator Demo", 0, func() func(*nucular.Window) { + var cd calcDemo + cd.current = &cd.a + return cd.calculatorDemo + } }, + { "overview", "Overview", 0, func() func(*nucular.Window) { + od := newOverviewDemo() + od.Theme = theme + return od.overviewDemo + } }, + { "editor", "Multiline Text Editor", nucular.WindowNoScrollbar, multilineTextEditorDemo }, + { "split", "Split panel demo", nucular.WindowNoScrollbar, func() func(*nucular.Window) { + pd := &panelDebug{} + pd.Init() + return pd.Update + } }, + { "nestedmenu", "Nested menu demo", 0, id(nestedMenu) }, + { "list", "List", nucular.WindowNoScrollbar, id(listDemo) }, +} + +var Wnd nucular.MasterWindow + func main() { - var wnd nucular.MasterWindow if dotrace { fh, _ := os.Create("demo.trace.out") @@ -42,48 +89,35 @@ func main() { defer pprof.StopCPUProfile() } } - + + whichdemo := "" + if len(os.Args) > 1 { + whichdemo = os.Args[1] + } + switch whichdemo { - case 0: - wnd = nucular.NewMasterWindow(0, "Button Demo", buttonDemo) - case 1: - wnd = nucular.NewMasterWindow(0, "Basic Demo", basicDemo) - go func() { - for { - time.Sleep(1 * time.Second) - if wnd.Closed() { - break - } - wnd.Changed() + case "multi", "": + Wnd = nucular.NewMasterWindow(0, "Multiwindow Demo", func(w *nucular.Window) {}) + 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 { + Wnd = nucular.NewMasterWindow(demos[i].Flags, demos[i].Title, demos[i].UpdateFn()) + break } - }() - case 2: - textEditorEditor.Flags = nucular.EditSelectable - textEditorEditor.Buffer = []rune("prova") - wnd = nucular.NewMasterWindow(0, "Text Editor Demo", textEditorDemo) - case 3: - var cd calcDemo - cd.current = &cd.a - wnd = nucular.NewMasterWindow(0, "Calculator Demo", cd.calculatorDemo) - case 4: - od := newOverviewDemo() - od.Theme = theme - wnd = nucular.NewMasterWindow(0, "Overview", od.overviewDemo) - case 7: - bs, _ := ioutil.ReadFile("overview.go") - multilineTextEditor.Buffer = []rune(string(bs)) - wnd = nucular.NewMasterWindow(nucular.WindowNoScrollbar, "Multiline Text Editor", multilineTextEditorDemo) - case 8: - pd := &panelDebug{} - pd.Init() - wnd = nucular.NewMasterWindow(nucular.WindowNoScrollbar, "Split panel demo", pd.Update) - case 9: - wnd = nucular.NewMasterWindow(nucular.WindowNoScrollbar, "Nested menu demo", nestedMenu) - case 10: - wnd = nucular.NewMasterWindow(nucular.WindowNoScrollbar, "List", listDemo) + } + } + if Wnd == nil { + fmt.Fprintf(os.Stderr, "unknown demo %q\n", whichdemo) + fmt.Fprintf(os.Stderr, "known demos:\n") + for i := range demos { + fmt.Fprintf(os.Stderr, "\t%s\n", demos[i].Name) + } + os.Exit(1) } - wnd.SetStyle(nstyle.FromTheme(theme, scaling)) - wnd.Main() + + Wnd.SetStyle(nstyle.FromTheme(theme, scaling)) + Wnd.Main() if dotrace { fh, _ := os.Create("demo.heap.pprof") if fh != nil { @@ -132,20 +166,27 @@ func basicDemo(w *nucular.Window) { w.PropertyInt("Compression:", 0, &compression, 100, 10, 1) } -var textEditorEditor nucular.TextEditor -func textEditorDemo(w *nucular.Window) { - w.Row(30).Dynamic(1) - textEditorEditor.Maxlen = 30 - textEditorEditor.Edit(w) +func textEditorDemo() func(w *nucular.Window) { + var textEditorEditor nucular.TextEditor + textEditorEditor.Flags = nucular.EditSelectable + textEditorEditor.Buffer = []rune("prova") + return func (w *nucular.Window) { + w.Row(30).Dynamic(1) + textEditorEditor.Maxlen = 30 + textEditorEditor.Edit(w) + } } -var multilineTextEditor nucular.TextEditor - -func multilineTextEditorDemo(w *nucular.Window) { - w.Row(0).Dynamic(1) - multilineTextEditor.Flags = nucular.EditMultiline | nucular.EditSelectable | nucular.EditClipboard - multilineTextEditor.Edit(w) +func multilineTextEditorDemo() func(w *nucular.Window) { + var multilineTextEditor nucular.TextEditor + bs, _ := ioutil.ReadFile("overview.go") + multilineTextEditor.Buffer = []rune(string(bs)) + return func(w *nucular.Window) { + w.Row(0).Dynamic(1) + multilineTextEditor.Flags = nucular.EditMultiline | nucular.EditSelectable | nucular.EditClipboard + multilineTextEditor.Edit(w) + } } type panelDebug struct { @@ -286,3 +327,17 @@ func listDemo(w *nucular.Window) { } } } + +func multiDemo(w *nucular.Window) { + w.Row(20).Dynamic(1) + w.Label("Welcome to the multi-window demo.", "LC") + w.Label("Open any demo window by clicking on the buttons.", "LC") + w.Label("To run a demo as a stand-alone window use:", "LC") + w.Label(" \"./demo \"", "LC") + w.Row(30).Static(100, 100, 100) + for i := range demos { + if w.ButtonText(demos[i].Name) { + w.Master().PopupOpen(demos[i].Title, nucular.WindowDefaultFlags|nucular.WindowNonmodal | demos[i].Flags, rect.Rect{0, 0, 200, 200}, true, demos[i].UpdateFn()) + } + } +} diff --git a/_demo/overview.go b/_demo/overview.go index 69132a5..820731e 100644 --- a/_demo/overview.go +++ b/_demo/overview.go @@ -113,7 +113,6 @@ func newOverviewDemo() (od *overviewDemo) { od.Resize = true od.Movable = true od.NoScrollbar = false - od.Minimizable = true od.Close = true od.HeaderAlign = nstyle.HeaderRight od.Mprog = 60 @@ -232,7 +231,6 @@ func (od *overviewDemo) overviewDemo(w *nucular.Window) { w.CheckboxText("Resizable", &od.Resize) w.CheckboxText("Movable", &od.Movable) w.CheckboxText("No Scrollbars", &od.NoScrollbar) - w.CheckboxText("Minimizable", &od.Minimizable) w.CheckboxText("Closable", &od.Close) w.TreePop() } @@ -1055,9 +1053,6 @@ func (od *overviewDemo) showAppAbout(mw nucular.MasterWindow) { if od.NoScrollbar { wf |= nucular.WindowNoScrollbar } - if od.Minimizable { - wf |= nucular.WindowMinimizable - } if od.Close { wf |= nucular.WindowClosable } diff --git a/context.go b/context.go index 7b3b4be..d654a83 100644 --- a/context.go +++ b/context.go @@ -27,6 +27,7 @@ type context struct { activateEditor *TextEditor cmds []command.Command trashFrame bool + autopos image.Point } func contextAllCommands(ctx *context) { @@ -52,6 +53,7 @@ func (ctx *context) Update() { for i := 0; i < len(ctx.Windows); i++ { ctx.Windows[i].began = false } + ctx.Restack() for i := 0; i < len(ctx.Windows); i++ { // this must not use range or tooltips won't work win := ctx.Windows[i] if win.updateFn != nil { @@ -125,6 +127,56 @@ func (ctx *context) Reset() { in.Keyboard.Keys = in.Keyboard.Keys[0:0] } +func (ctx *context) Restack() { + nonmodalToplevel := false + var toplevelIdx int + for i := len(ctx.Windows) - 1; i >= 0; i-- { + if ctx.Windows[i].flags&windowTooltip == 0 { + toplevelIdx = i + nonmodalToplevel = ctx.Windows[i].flags&WindowNonmodal != 0 + break + } + } + if !nonmodalToplevel { + return + } + // toplevel window is non-modal, proceed to change the stacking order if + // the user clicked outside of it + restacked := false + for i := len(ctx.Windows) - 1; i > 0; i-- { + if ctx.Windows[i].flags&windowTooltip != 0 { + continue + } + if ctx.restackClick(i) { + if toplevelIdx != i { + newToplevel := ctx.Windows[i] + copy(ctx.Windows[i:toplevelIdx], ctx.Windows[i+1:toplevelIdx+1]) + ctx.Windows[toplevelIdx] = newToplevel + restacked = true + } + break + } + } + if restacked { + for i := range ctx.Windows { + ctx.Windows[i].idx = i + } + } +} + +func (ctx *context) restackClick(i int) bool { + if !ctx.Input.Mouse.valid { + return false + } + for _, b := range []mouse.Button{mouse.ButtonLeft, mouse.ButtonRight, mouse.ButtonMiddle} { + btn := ctx.Input.Mouse.Buttons[b] + if btn.Clicked && btn.Down && ctx.Windows[i].Bounds.Contains(btn.ClickedPos) { + return true + } + } + return false +} + var cnt = 0 var ln, frect, brrect, frrect, ftri, circ, fcirc, txt int diff --git a/drawing.go b/drawing.go index 41e9b9a..2883c72 100644 --- a/drawing.go +++ b/drawing.go @@ -74,7 +74,6 @@ type drawableWindowHeader struct { Hovered bool Title string - Minimized bool Dynamic bool HeaderActive bool Bounds rect.Rect @@ -86,10 +85,7 @@ type drawableWindowHeader struct { func (dwh *drawableWindowHeader) Draw(z *nstyle.Style, out *command.Buffer) { style := dwh.Style - if dwh.Minimized { - /* draw window background if minimized */ - out.FillRect(rect.Rect{dwh.Bounds.X, dwh.Bounds.Y, dwh.Bounds.W, dwh.RowHeight}, 0, style.Background) - } else if !dwh.Dynamic { + if !dwh.Dynamic { /* draw fixed window body */ body := dwh.Bounds if dwh.HeaderActive { diff --git a/nucular.go b/nucular.go index a95bc56..9ff3441 100644 --- a/nucular.go +++ b/nucular.go @@ -128,16 +128,14 @@ const ( WindowMovable WindowScalable WindowClosable - WindowMinimizable WindowDynamic WindowNoScrollbar WindowNoHScrollbar WindowTitle WindowContextualReplace + WindowNonmodal windowPrivate - windowHidden - windowMinimized windowSub windowGroup windowPopup @@ -148,8 +146,9 @@ const ( windowTooltip windowEnabled windowHDynamic + windowDocked - WindowDefaultFlags = WindowBorder | WindowMovable | WindowScalable | WindowClosable | WindowMinimizable | WindowTitle + WindowDefaultFlags = WindowBorder | WindowMovable | WindowScalable | WindowClosable | WindowTitle ) func createTreeNode(initialState bool, parent *treeNode) *treeNode { @@ -212,7 +211,7 @@ func (win *Window) style() *nstyle.Window { } } -func panelBegin(ctx *context, win *Window, title string) bool { +func panelBegin(ctx *context, win *Window, title string) { win.usingSub = false style := &ctx.Style font := style.Font @@ -229,10 +228,6 @@ func panelBegin(ctx *context, win *Window, title string) bool { /* check arguments */ *layout = panel{} - if win.flags&windowHidden != 0 { - return false - } - /* window dragging */ if (win.flags&WindowMovable != 0) && win.toplevel() { var move rect.Rect @@ -291,10 +286,7 @@ func panelBegin(ctx *context, win *Window, title string) bool { } /* calculate window header */ - if win.flags&windowMinimized != 0 { - layout.HeaderH = 0 - layout.Row.Height = 0 - } else if win.flags&windowMenu != 0 || win.flags&windowContextual != 0 { + if win.flags&windowMenu != 0 || win.flags&windowContextual != 0 { layout.HeaderH = window_padding.Y layout.Row.Height = window_padding.Y } else { @@ -320,7 +312,6 @@ func panelBegin(ctx *context, win *Window, title string) bool { header_active := (win.idx != 0) && (win.flags&WindowTitle != 0) var dwh drawableWindowHeader - dwh.Minimized = layout.Flags&windowMinimized != 0 dwh.Dynamic = layout.Flags&WindowDynamic != 0 dwh.Bounds = layout.Bounds dwh.HeaderActive = header_active @@ -379,37 +370,7 @@ func panelBegin(ctx *context, win *Window, title string) bool { } if doButton(win, label.S(wstyle.Header.CloseSymbol), button, &wstyle.Header.CloseButton, in, false) { - layout.Flags |= windowHidden - } - } - - /* window minimize button */ - if win.flags&WindowMinimizable != 0 { - if wstyle.Header.Align == nstyle.HeaderRight { - button.X = (header.W + header.X) - button.W - if win.flags&WindowClosable == 0 { - button.X -= wstyle.Header.Padding.X - header.W -= wstyle.Header.Padding.X - } - - header.W -= button.W + wstyle.Header.Spacing.X - } else { - button.X = header.X - header.X += button.W + wstyle.Header.Spacing.X + wstyle.Header.Padding.X - } - - var symbolType label.SymbolType - if layout.Flags&windowMinimized != 0 { - symbolType = wstyle.Header.MaximizeSymbol - } else { - symbolType = wstyle.Header.MinimizeSymbol - } - if doButton(win, label.S(symbolType), button, &wstyle.Header.MinimizeButton, in, false) { - if layout.Flags&windowMinimized != 0 { - layout.Flags = layout.Flags & ^windowMinimized - } else { - layout.Flags = layout.Flags | windowMinimized - } + win.close = true } } } else { @@ -419,21 +380,11 @@ func panelBegin(ctx *context, win *Window, title string) bool { dwh.Draw(&win.ctx.Style, &win.cmds) } - /* fix header height for transition between minimized and maximized window state */ - if win.flags&windowMinimized != 0 && layout.Flags&windowMinimized == 0 { - layout.Row.Height += 2*item_spacing.Y + wstyle.Border - } - var dwb drawableWindowBody dwb.NoScrollbar = win.flags&WindowNoScrollbar != 0 dwb.Style = win.style() - if dwh.Minimized { - /* draw window background if minimized */ - layout.Row.Height = 0 - } - /* calculate and set the window clipping rectangle*/ if win.flags&WindowDynamic == 0 { layout.Clip.X = layout.Bounds.X + window_padding.X @@ -464,8 +415,6 @@ func panelBegin(ctx *context, win *Window, title string) bool { dwb.Draw(&win.ctx.Style, &win.cmds) layout.Row.Type = layoutInvalid - - return layout.Flags&windowHidden == 0 && layout.Flags&windowMinimized == 0 } func (win *Window) specialPanelBegin() { @@ -526,9 +475,7 @@ func (win *Window) specialPanelBegin() { if win.flags&windowPopup != 0 { win.cmds.PushScissor(nk_null_rect) - if !panelBegin(ctx, win, win.title) { - win.close = true - } + panelBegin(ctx, win, win.title) win.layout.Offset = &win.Scrollbar } @@ -569,7 +516,7 @@ func panelEnd(ctx *context, window *Window) { layout.AtY += layout.Row.Height /* draw footer and fill empty spaces inside a dynamically growing panel */ - if layout.Flags&WindowDynamic != 0 && layout.Flags&windowMinimized == 0 { + if layout.Flags&WindowDynamic != 0 { layout.Height = layout.AtY - layout.Bounds.Y layout.Height = min(layout.Height, layout.Bounds.H) @@ -629,7 +576,7 @@ func panelEnd(ctx *context, window *Window) { } /* scrollbars */ - if layout.Flags&WindowNoScrollbar == 0 && layout.Flags&windowMinimized == 0 { + if layout.Flags&WindowNoScrollbar == 0 { var bounds rect.Rect var scroll_target float64 var scroll_offset float64 @@ -690,17 +637,23 @@ func panelEnd(ctx *context, window *Window) { dsab.HeaderH = layout.HeaderH /* scaler */ - if (layout.Flags&WindowScalable != 0) && layout.Flags&windowMinimized == 0 { + if layout.Flags&WindowScalable != 0 { dsab.DrawScaler = true - dsab.ScalerRect.W = max(0, scaler_size.X-window_padding.X) - dsab.ScalerRect.H = max(0, scaler_size.Y-window_padding.Y) + dsab.ScalerRect.W = max(0, scaler_size.X) + dsab.ScalerRect.H = max(0, scaler_size.Y) dsab.ScalerRect.X = (layout.Bounds.X + layout.Bounds.W) - (window_padding.X + dsab.ScalerRect.W) /* calculate scaler bounds */ if layout.Flags&WindowDynamic != 0 { dsab.ScalerRect.Y = footer.Y + layout.FooterH - scaler_size.Y } else { - dsab.ScalerRect.Y = layout.Bounds.Y + layout.Bounds.H - scaler_size.Y + dsab.ScalerRect.Y = layout.Bounds.Y + layout.Bounds.H - (scaler_size.Y + window_padding.Y) + } + + scalingRect := dsab.ScalerRect + if layout.Flags&windowDocked != 0 { + scalingRect = layout.Bounds + scalingRect.Y = dsab.ScalerRect.Y } /* do window scaling logic */ @@ -708,7 +661,7 @@ func panelEnd(ctx *context, window *Window) { prev := in.Mouse.Prev window_size := wstyle.MinSize - incursor := dsab.ScalerRect.Contains(prev) + incursor := scalingRect.Contains(prev) if in != nil && in.Mouse.Down(mouse.ButtonLeft) && incursor { window.Bounds.W = max(window_size.X, window.Bounds.W+in.Mouse.Delta.X) @@ -725,9 +678,7 @@ func panelEnd(ctx *context, window *Window) { if layout.Flags&WindowBorder != 0 { dsab.DrawBorders = true - if layout.Flags&windowMinimized != 0 { - dsab.PaddingY = 2.0*wstyle.Border + window.Bounds.Y + layout.HeaderH - } else if layout.Flags&WindowDynamic != 0 { + if layout.Flags&WindowDynamic != 0 { dsab.PaddingY = layout.FooterH + footer.Y } else { dsab.PaddingY = layout.Bounds.Y + layout.Bounds.H @@ -744,13 +695,6 @@ func panelEnd(ctx *context, window *Window) { window.widgets.Add(nstyle.WidgetStateInactive, dsab.Bounds) dsab.Draw(&window.ctx.Style, &window.cmds) - if window.flags&windowSub == 0 { - if layout.Flags&windowHidden != 0 { - /* window is hidden so clear command buffer */ - window.widgets.reset() - } - } - layout.Flags |= windowEnabled window.flags = layout.Flags @@ -764,9 +708,6 @@ func panelEnd(ctx *context, window *Window) { // Remember to call MenubarEnd when you are done adding elements to the menubar. func (win *Window) MenubarBegin() { layout := win.layout - if layout.Flags&windowHidden != 0 || layout.Flags&windowMinimized != 0 { - return - } layout.Menu.X = layout.AtX layout.Menu.Y = layout.Bounds.Y + layout.HeaderH @@ -778,9 +719,6 @@ func (win *Window) MenubarBegin() { // MenubarEnd signals that all widgets have been added to the menubar. func (win *Window) MenubarEnd() { layout := win.layout - if layout.Flags&windowHidden != 0 || layout.Flags&windowMinimized != 0 { - return - } layout.Menu.H = layout.AtY - layout.Menu.Y layout.Clip.Y = layout.Bounds.Y + layout.HeaderH + layout.Menu.H + layout.Row.Height @@ -866,7 +804,16 @@ func panelLayout(ctx *context, win *Window, height int, cols int, cnt int) { if height == 0 { height = layout.Clip.H - (layout.AtY - layout.Bounds.Y) - height -= layout.Row.Height + subtractHeight := true + if layout.Row.Columns > 0 && layout.Row.Index >= layout.Row.Columns { + subtractHeight = false + } + if layout.Row.Index == 0 { + subtractHeight = false + } + if subtractHeight { + height -= layout.Row.Height + } if layout.ReservedHeight > 0 { height -= layout.ReservedHeight + item_spacing.Y } @@ -2681,11 +2628,29 @@ func (ctx *context) popupOpen(title string, flags WindowFlags, rect rect.Rect, s rect.H = ctx.scale(rect.H) } + if rect.X == 0 && rect.Y == 0 && flags&WindowNonmodal != 0 { + rect.X, rect.Y = ctx.autoPosition() + } + popup.Bounds = rect popup.layout = &panel{} popup.flags = flags | WindowBorder | windowSub | windowPopup } +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) + + 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 +} + // Programmatically closes this window func (win *Window) Close() { if win.idx != 0 { diff --git a/style/style.go b/style/style.go index 2973aab..f1e9a9b 100644 --- a/style/style.go +++ b/style/style.go @@ -52,34 +52,34 @@ type Style struct { } type ColorTable struct { - ColorText color.RGBA - ColorWindow color.RGBA - ColorHeader color.RGBA - ColorBorder color.RGBA - ColorButton color.RGBA - ColorButtonHover color.RGBA - ColorButtonActive color.RGBA - ColorToggle color.RGBA - ColorToggleHover color.RGBA - ColorToggleCursor color.RGBA - ColorSelect color.RGBA - ColorSelectActive color.RGBA - ColorSlider color.RGBA - ColorSliderCursor color.RGBA - ColorSliderCursorHover color.RGBA - ColorSliderCursorActive color.RGBA - ColorProperty color.RGBA - ColorEdit color.RGBA - ColorEditCursor color.RGBA - ColorCombo color.RGBA - ColorChart color.RGBA - ColorChartColor color.RGBA - ColorChartColorHighlight color.RGBA - ColorScrollbar color.RGBA - ColorScrollbarCursor color.RGBA - ColorScrollbarCursorHover color.RGBA + ColorText color.RGBA + ColorWindow color.RGBA + ColorHeader color.RGBA + ColorBorder color.RGBA + ColorButton color.RGBA + ColorButtonHover color.RGBA + ColorButtonActive color.RGBA + ColorToggle color.RGBA + ColorToggleHover color.RGBA + ColorToggleCursor color.RGBA + ColorSelect color.RGBA + ColorSelectActive color.RGBA + ColorSlider color.RGBA + ColorSliderCursor color.RGBA + ColorSliderCursorHover color.RGBA + ColorSliderCursorActive color.RGBA + ColorProperty color.RGBA + ColorEdit color.RGBA + ColorEditCursor color.RGBA + ColorCombo color.RGBA + ColorChart color.RGBA + ColorChartColor color.RGBA + ColorChartColorHighlight color.RGBA + ColorScrollbar color.RGBA + ColorScrollbarCursor color.RGBA + ColorScrollbarCursorHover color.RGBA ColorScrollbarCursorActive color.RGBA - ColorTabHeader color.RGBA + ColorTabHeader color.RGBA } type ItemType int @@ -105,22 +105,22 @@ type Text struct { } type Button struct { - Normal Item - Hover Item - Active Item - BorderColor color.RGBA - TextBackground color.RGBA - TextNormal color.RGBA - TextHover color.RGBA - TextActive color.RGBA - Border int - Rounding uint16 - Padding image.Point - ImagePadding image.Point - TouchPadding image.Point - DrawBegin func(*command.Buffer) - Draw CustomButtonDrawing - DrawEnd func(*command.Buffer) + Normal Item + Hover Item + Active Item + BorderColor color.RGBA + TextBackground color.RGBA + TextNormal color.RGBA + TextHover color.RGBA + TextActive color.RGBA + Border int + Rounding uint16 + Padding image.Point + ImagePadding image.Point + TouchPadding image.Point + DrawBegin func(*command.Buffer) + Draw CustomButtonDrawing + DrawEnd func(*command.Buffer) SymbolBorderWidth int } @@ -812,8 +812,8 @@ func FromTable(table ColorTable, scaling float64) *Style { win.Header.LabelNormal = table.ColorText win.Header.LabelHover = table.ColorText win.Header.LabelActive = table.ColorText - win.Header.LabelPadding = image.Point{4, 4} - win.Header.Padding = image.Point{4, 4} + win.Header.LabelPadding = image.Point{2, 2} + win.Header.Padding = image.Point{2, 2} win.Header.Spacing = image.Point{0, 0} /* window header close button */ @@ -863,7 +863,7 @@ func FromTable(table ColorTable, scaling float64) *Style { win.Scaler = MakeItemColor(table.ColorText) win.FooterPadding = image.Point{0, 0} win.Rounding = 0.0 - win.ScalerSize = image.Point{16, 16} + win.ScalerSize = image.Point{9, 9} win.Padding = image.Point{4, 4} win.Spacing = image.Point{4, 4} win.ScrollbarSize = image.Point{10, 10} @@ -931,96 +931,96 @@ const ( ) var whiteThemeTable = ColorTable{ - ColorText: color.RGBA{70, 70, 70, 255}, - ColorWindow: color.RGBA{175, 175, 175, 255}, - ColorHeader: color.RGBA{175, 175, 175, 255}, - ColorBorder: color.RGBA{0, 0, 0, 255}, - ColorButton: color.RGBA{185, 185, 185, 255}, - ColorButtonHover: color.RGBA{170, 170, 170, 255}, - ColorButtonActive: color.RGBA{160, 160, 160, 255}, - ColorToggle: color.RGBA{150, 150, 150, 255}, - ColorToggleHover: color.RGBA{120, 120, 120, 255}, - ColorToggleCursor: color.RGBA{175, 175, 175, 255}, - ColorSelect: color.RGBA{175, 175, 175, 255}, - ColorSelectActive: color.RGBA{190, 190, 190, 255}, - ColorSlider: color.RGBA{190, 190, 190, 255}, - ColorSliderCursor: color.RGBA{80, 80, 80, 255}, - ColorSliderCursorHover: color.RGBA{70, 70, 70, 255}, - ColorSliderCursorActive: color.RGBA{60, 60, 60, 255}, - ColorProperty: color.RGBA{175, 175, 175, 255}, - ColorEdit: color.RGBA{150, 150, 150, 255}, - ColorEditCursor: color.RGBA{0, 0, 0, 255}, - ColorCombo: color.RGBA{175, 175, 175, 255}, - ColorChart: color.RGBA{160, 160, 160, 255}, - ColorChartColor: color.RGBA{45, 45, 45, 255}, - ColorChartColorHighlight: color.RGBA{255, 0, 0, 255}, - ColorScrollbar: color.RGBA{180, 180, 180, 255}, - ColorScrollbarCursor: color.RGBA{140, 140, 140, 255}, - ColorScrollbarCursorHover: color.RGBA{150, 150, 150, 255}, + ColorText: color.RGBA{70, 70, 70, 255}, + ColorWindow: color.RGBA{175, 175, 175, 255}, + ColorHeader: color.RGBA{175, 175, 175, 255}, + ColorBorder: color.RGBA{0, 0, 0, 255}, + ColorButton: color.RGBA{185, 185, 185, 255}, + ColorButtonHover: color.RGBA{170, 170, 170, 255}, + ColorButtonActive: color.RGBA{160, 160, 160, 255}, + ColorToggle: color.RGBA{150, 150, 150, 255}, + ColorToggleHover: color.RGBA{120, 120, 120, 255}, + ColorToggleCursor: color.RGBA{175, 175, 175, 255}, + ColorSelect: color.RGBA{175, 175, 175, 255}, + ColorSelectActive: color.RGBA{190, 190, 190, 255}, + ColorSlider: color.RGBA{190, 190, 190, 255}, + ColorSliderCursor: color.RGBA{80, 80, 80, 255}, + ColorSliderCursorHover: color.RGBA{70, 70, 70, 255}, + ColorSliderCursorActive: color.RGBA{60, 60, 60, 255}, + ColorProperty: color.RGBA{175, 175, 175, 255}, + ColorEdit: color.RGBA{150, 150, 150, 255}, + ColorEditCursor: color.RGBA{0, 0, 0, 255}, + ColorCombo: color.RGBA{175, 175, 175, 255}, + ColorChart: color.RGBA{160, 160, 160, 255}, + ColorChartColor: color.RGBA{45, 45, 45, 255}, + ColorChartColorHighlight: color.RGBA{255, 0, 0, 255}, + ColorScrollbar: color.RGBA{180, 180, 180, 255}, + ColorScrollbarCursor: color.RGBA{140, 140, 140, 255}, + ColorScrollbarCursorHover: color.RGBA{150, 150, 150, 255}, ColorScrollbarCursorActive: color.RGBA{160, 160, 160, 255}, - ColorTabHeader: color.RGBA{180, 180, 180, 255}, + ColorTabHeader: color.RGBA{180, 180, 180, 255}, } var redThemeTable = ColorTable{ - ColorText: color.RGBA{190, 190, 190, 255}, - ColorWindow: color.RGBA{30, 33, 40, 215}, - ColorHeader: color.RGBA{181, 45, 69, 220}, - ColorBorder: color.RGBA{51, 55, 67, 255}, - ColorButton: color.RGBA{181, 45, 69, 255}, - ColorButtonHover: color.RGBA{190, 50, 70, 255}, - ColorButtonActive: color.RGBA{195, 55, 75, 255}, - ColorToggle: color.RGBA{51, 55, 67, 255}, - ColorToggleHover: color.RGBA{45, 60, 60, 255}, - ColorToggleCursor: color.RGBA{181, 45, 69, 255}, - ColorSelect: color.RGBA{51, 55, 67, 255}, - ColorSelectActive: color.RGBA{181, 45, 69, 255}, - ColorSlider: color.RGBA{51, 55, 67, 255}, - ColorSliderCursor: color.RGBA{181, 45, 69, 255}, - ColorSliderCursorHover: color.RGBA{186, 50, 74, 255}, - ColorSliderCursorActive: color.RGBA{191, 55, 79, 255}, - ColorProperty: color.RGBA{51, 55, 67, 255}, - ColorEdit: color.RGBA{51, 55, 67, 225}, - ColorEditCursor: color.RGBA{190, 190, 190, 255}, - ColorCombo: color.RGBA{51, 55, 67, 255}, - ColorChart: color.RGBA{51, 55, 67, 255}, - ColorChartColor: color.RGBA{170, 40, 60, 255}, - ColorChartColorHighlight: color.RGBA{255, 0, 0, 255}, - ColorScrollbar: color.RGBA{30, 33, 40, 255}, - ColorScrollbarCursor: color.RGBA{64, 84, 95, 255}, - ColorScrollbarCursorHover: color.RGBA{70, 90, 100, 255}, + ColorText: color.RGBA{190, 190, 190, 255}, + ColorWindow: color.RGBA{30, 33, 40, 215}, + ColorHeader: color.RGBA{181, 45, 69, 220}, + ColorBorder: color.RGBA{51, 55, 67, 255}, + ColorButton: color.RGBA{181, 45, 69, 255}, + ColorButtonHover: color.RGBA{190, 50, 70, 255}, + ColorButtonActive: color.RGBA{195, 55, 75, 255}, + ColorToggle: color.RGBA{51, 55, 67, 255}, + ColorToggleHover: color.RGBA{45, 60, 60, 255}, + ColorToggleCursor: color.RGBA{181, 45, 69, 255}, + ColorSelect: color.RGBA{51, 55, 67, 255}, + ColorSelectActive: color.RGBA{181, 45, 69, 255}, + ColorSlider: color.RGBA{51, 55, 67, 255}, + ColorSliderCursor: color.RGBA{181, 45, 69, 255}, + ColorSliderCursorHover: color.RGBA{186, 50, 74, 255}, + ColorSliderCursorActive: color.RGBA{191, 55, 79, 255}, + ColorProperty: color.RGBA{51, 55, 67, 255}, + ColorEdit: color.RGBA{51, 55, 67, 225}, + ColorEditCursor: color.RGBA{190, 190, 190, 255}, + ColorCombo: color.RGBA{51, 55, 67, 255}, + ColorChart: color.RGBA{51, 55, 67, 255}, + ColorChartColor: color.RGBA{170, 40, 60, 255}, + ColorChartColorHighlight: color.RGBA{255, 0, 0, 255}, + ColorScrollbar: color.RGBA{30, 33, 40, 255}, + ColorScrollbarCursor: color.RGBA{64, 84, 95, 255}, + ColorScrollbarCursorHover: color.RGBA{70, 90, 100, 255}, ColorScrollbarCursorActive: color.RGBA{75, 95, 105, 255}, - ColorTabHeader: color.RGBA{181, 45, 69, 220}, + ColorTabHeader: color.RGBA{181, 45, 69, 220}, } var darkThemeTable = ColorTable{ - ColorText: color.RGBA{210, 210, 210, 255}, - ColorWindow: color.RGBA{57, 67, 71, 255}, - ColorHeader: color.RGBA{51, 51, 56, 220}, - ColorBorder: color.RGBA{46, 46, 46, 255}, - ColorButton: color.RGBA{48, 83, 111, 255}, - ColorButtonHover: color.RGBA{58, 93, 121, 255}, - ColorButtonActive: color.RGBA{63, 98, 126, 255}, - ColorToggle: color.RGBA{50, 58, 61, 255}, - ColorToggleHover: color.RGBA{45, 53, 56, 255}, - ColorToggleCursor: color.RGBA{48, 83, 111, 255}, - ColorSelect: color.RGBA{57, 67, 61, 255}, - ColorSelectActive: color.RGBA{48, 83, 111, 255}, - ColorSlider: color.RGBA{50, 58, 61, 255}, - ColorSliderCursor: color.RGBA{48, 83, 111, 245}, - ColorSliderCursorHover: color.RGBA{53, 88, 116, 255}, - ColorSliderCursorActive: color.RGBA{58, 93, 121, 255}, - ColorProperty: color.RGBA{50, 58, 61, 255}, - ColorEdit: color.RGBA{50, 58, 61, 225}, - ColorEditCursor: color.RGBA{210, 210, 210, 255}, - ColorCombo: color.RGBA{50, 58, 61, 255}, - ColorChart: color.RGBA{50, 58, 61, 255}, - ColorChartColor: color.RGBA{48, 83, 111, 255}, - ColorChartColorHighlight: color.RGBA{255, 0, 0, 255}, - ColorScrollbar: color.RGBA{50, 58, 61, 255}, - ColorScrollbarCursor: color.RGBA{48, 83, 111, 255}, - ColorScrollbarCursorHover: color.RGBA{53, 88, 116, 255}, + ColorText: color.RGBA{210, 210, 210, 255}, + ColorWindow: color.RGBA{57, 67, 71, 255}, + ColorHeader: color.RGBA{51, 51, 56, 220}, + ColorBorder: color.RGBA{46, 46, 46, 255}, + ColorButton: color.RGBA{48, 83, 111, 255}, + ColorButtonHover: color.RGBA{58, 93, 121, 255}, + ColorButtonActive: color.RGBA{63, 98, 126, 255}, + ColorToggle: color.RGBA{50, 58, 61, 255}, + ColorToggleHover: color.RGBA{45, 53, 56, 255}, + ColorToggleCursor: color.RGBA{48, 83, 111, 255}, + ColorSelect: color.RGBA{57, 67, 61, 255}, + ColorSelectActive: color.RGBA{48, 83, 111, 255}, + ColorSlider: color.RGBA{50, 58, 61, 255}, + ColorSliderCursor: color.RGBA{48, 83, 111, 245}, + ColorSliderCursorHover: color.RGBA{53, 88, 116, 255}, + ColorSliderCursorActive: color.RGBA{58, 93, 121, 255}, + ColorProperty: color.RGBA{50, 58, 61, 255}, + ColorEdit: color.RGBA{50, 58, 61, 225}, + ColorEditCursor: color.RGBA{210, 210, 210, 255}, + ColorCombo: color.RGBA{50, 58, 61, 255}, + ColorChart: color.RGBA{50, 58, 61, 255}, + ColorChartColor: color.RGBA{48, 83, 111, 255}, + ColorChartColorHighlight: color.RGBA{255, 0, 0, 255}, + ColorScrollbar: color.RGBA{50, 58, 61, 255}, + ColorScrollbarCursor: color.RGBA{48, 83, 111, 255}, + ColorScrollbarCursorHover: color.RGBA{53, 88, 116, 255}, ColorScrollbarCursorActive: color.RGBA{58, 93, 121, 255}, - ColorTabHeader: color.RGBA{48, 83, 111, 255}, + ColorTabHeader: color.RGBA{48, 83, 111, 255}, } func FromTheme(theme Theme, scaling float64) *Style { diff --git a/text.go b/text.go index d5ccca4..413bfaf 100644 --- a/text.go +++ b/text.go @@ -1416,6 +1416,7 @@ func (ed *TextEditor) doEdit(bounds rect.Rect, style *nstyle.Edit, inp *Input, c d.Bounds = bounds d.Area = area d.RowHeight = row_height + d.hasInput = inp.Mouse.valid ed.win.widgets.Add(state, bounds) d.Draw(&ed.win.ctx.Style, &ed.win.cmds) @@ -1471,6 +1472,7 @@ type drawableTextEditor struct { Bounds rect.Rect Area rect.Rect RowHeight int + hasInput bool SelectionBegin, SelectionEnd int @@ -1575,7 +1577,7 @@ func (d *drawableTextEditor) Draw(z *nstyle.Style, out *command.Buffer) { /* no selection so just draw the complete text */ pos = edit.editDrawText(out, style, pos, x_margin, edit.Buffer[:edit.Cursor], 0, row_height, font, background_color, text_color, false) d.CursorPos = pos.Sub(startPos) - if edit.Active { + if edit.Active && d.hasInput { if edit.Cursor < len(edit.Buffer) { switch edit.Buffer[edit.Cursor] { case '\n', '\t':