diff --git a/CSS.go b/CSS.go new file mode 100644 index 00000000..32d8bed0 --- /dev/null +++ b/CSS.go @@ -0,0 +1,138 @@ +package giu + +import ( + "fmt" + "strconv" + "strings" + + "github.com/mazznoer/csscolorparser" + "github.com/napsy/go-css" +) + +// Code in this file allows to apply style using a CSS stylesheet +// The intention of the code looks as follows: +// - The CSS stylesheet is parsed and the resulting rules are stored in giu context +// NOTE: more than one CSS stylesheets can be parsed, however the app could panic if the same tag is present twice +// - CSSTagWidget allows to apply style to a specified layout +// - main tag allows to apply style to the whole application +// +// tools: +// css parser - for now github.com/napsy/go-css. it is a bit poor, but I don't think we need anything more +// css colors - github.com/mazznoer/csscolorparser +// +// docs: docs/css.md + +// ParseCSSStyleSheet parses CSS stylesheet and stores the rules in giu context +func ParseCSSStyleSheet(data []byte) error { + stylesheet, err := css.Unmarshal(data) + if err != nil { + return err + } + + for rule, style := range stylesheet { + setter := Style() + for styleVarName, styleVarValue := range style { + // convert style variable name to giu style variable name + var styleVarID StyleVarID + err := panicToErr(func() { + styleVarID = StyleVarIDFromString(styleVarName) + }) + + if err == nil { + // the style is StyleVarID - set it + f, err := strconv.ParseFloat(styleVarValue, 32) + if err == nil { + setter.SetStyleFloat(styleVarID, float32(f)) + } + + // so maybe it is a vec2 value: + // var-name: x, y; + vec2 := strings.Split(styleVarValue, ",") + if len(vec2) != 2 { + return fmt.Errorf("unable to parse value %v is not float nor vec2: %w", styleVarValue, err) + } + + for i, v := range vec2 { + vec2[i] = strings.ReplaceAll(v, " ", "") + } + + x, err := strconv.ParseFloat(vec2[0], 32) + if err != nil { + return fmt.Errorf("unable to parse value %v is not float: %w", vec2[0], err) + } + + y, err := strconv.ParseFloat(vec2[1], 32) + if err != nil { + return fmt.Errorf("unable to parse value %v is not float: %w", vec2[1], err) + } + + setter.SetStyle(styleVarID, float32(x), float32(y)) + + continue + } + + var styleColorID StyleColorID + err = panicToErr(func() { + styleColorID = StyleColorIDFromString(styleVarName) + }) + + if err != nil { + return fmt.Errorf("cannot parse style variable ID: %v", styleVarName) + } + + col, err := csscolorparser.Parse(styleVarValue) + if err != nil { + return fmt.Errorf("cannot parse color %v: %w", styleVarValue, err) + } + + setter.SetColor(styleColorID, col) + } + + Context.cssStylesheet[string(rule)] = setter + } + + return nil +} + +func panicToErr(f func()) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("%v", r) + } + }() + + f() + return err +} + +// cssStylesheet is a map tag:StyleSetter +type cssStylesheet map[string]*StyleSetter + +var _ Widget = &CSSTagWidget{} + +// CSSTagWidget is a widget that allows to apply CSS style to a specified layout +type CSSTagWidget struct { + tag string + layout Layout +} + +// CSSTag creates CSSTagWidget +func CSSTag(tag string) *CSSTagWidget { + return &CSSTagWidget{tag: tag} +} + +// To specifies a layout to which the style will be applied +func (c *CSSTagWidget) To(layout ...Widget) *CSSTagWidget { + c.layout = layout + return c +} + +// Build implements Widget interface +func (c *CSSTagWidget) Build() { + // get style from context. + // if it doesn't exist Assert. + style, exists := Context.cssStylesheet[c.tag] + Assert(exists, "CSSTagWidget", "Build", "CSS stylesheet doesn't contain tag: %s", c.tag) + + style.To(c.layout).Build() +} diff --git a/Context.go b/Context.go index 82a8bdee..7be50fec 100644 --- a/Context.go +++ b/Context.go @@ -47,12 +47,15 @@ type context struct { FontAtlas FontAtlas textureLoadingQueue *queue.Queue + + cssStylesheet cssStylesheet } func CreateContext(p imgui.Platform, r imgui.Renderer) context { result := context{ - platform: p, - renderer: r, + platform: p, + renderer: r, + cssStylesheet: make(cssStylesheet), } result.FontAtlas = newFontAtlas() diff --git a/MasterWindow.go b/MasterWindow.go index 2c621c1c..8bca6c1f 100644 --- a/MasterWindow.go +++ b/MasterWindow.go @@ -194,11 +194,18 @@ func (w *MasterWindow) render() { p := w.platform r := w.renderer + mainStylesheet := Style() + if s, found := Context.cssStylesheet["main"]; found { + mainStylesheet = s + } + p.NewFrame() r.PreRender(w.clearColor) imgui.NewFrame() + mainStylesheet.Push() w.updateFunc() + mainStylesheet.Pop() imgui.Render() r.Render(p.DisplaySize(), p.FramebufferSize(), imgui.RenderedDrawData()) diff --git a/StyleIDs.go b/StyleIDs.go index a62b409f..f195cfd4 100644 --- a/StyleIDs.go +++ b/StyleIDs.go @@ -5,125 +5,132 @@ import "github.com/AllenDang/imgui-go" // Here are the style IDs for styling imgui apps. // For details about each of attributes read comment above them. +// go-generate String() andStringToEnum methods +//go:generate stringer -type=StyleColorID,StyleVarID -output=StyleIDs_string.go -linecomment +// NOTE: string2enum is https://github.com/mewspring/tools +//go:generate string2enum -samepkg -type=StyleColorID,StyleVarID -output=StyleIDs_string2enum.go -linecomment + // StyleColorID identifies a color in the UI style. type StyleColorID imgui.StyleColorID // StyleColor identifier. +// NOTE: comments are used for CSS conversion and are generated by stringer and string2enum. const ( - StyleColorText StyleColorID = StyleColorID(imgui.StyleColorText) - StyleColorTextDisabled StyleColorID = StyleColorID(imgui.StyleColorTextDisabled) - StyleColorWindowBg StyleColorID = StyleColorID(imgui.StyleColorWindowBg) - StyleColorChildBg StyleColorID = StyleColorID(imgui.StyleColorChildBg) - StyleColorPopupBg StyleColorID = StyleColorID(imgui.StyleColorPopupBg) - StyleColorBorder StyleColorID = StyleColorID(imgui.StyleColorBorder) - StyleColorBorderShadow StyleColorID = StyleColorID(imgui.StyleColorBorderShadow) - StyleColorFrameBg StyleColorID = StyleColorID(imgui.StyleColorFrameBg) - StyleColorFrameBgHovered StyleColorID = StyleColorID(imgui.StyleColorFrameBgHovered) - StyleColorFrameBgActive StyleColorID = StyleColorID(imgui.StyleColorFrameBgActive) - StyleColorTitleBg StyleColorID = StyleColorID(imgui.StyleColorTitleBg) - StyleColorTitleBgActive StyleColorID = StyleColorID(imgui.StyleColorTitleBgActive) - StyleColorTitleBgCollapsed StyleColorID = StyleColorID(imgui.StyleColorTitleBgCollapsed) - StyleColorMenuBarBg StyleColorID = StyleColorID(imgui.StyleColorMenuBarBg) - StyleColorScrollbarBg StyleColorID = StyleColorID(imgui.StyleColorScrollbarBg) - StyleColorScrollbarGrab StyleColorID = StyleColorID(imgui.StyleColorScrollbarGrab) - StyleColorScrollbarGrabHovered StyleColorID = StyleColorID(imgui.StyleColorScrollbarGrabHovered) - StyleColorScrollbarGrabActive StyleColorID = StyleColorID(imgui.StyleColorScrollbarGrabActive) - StyleColorCheckMark StyleColorID = StyleColorID(imgui.StyleColorCheckMark) - StyleColorSliderGrab StyleColorID = StyleColorID(imgui.StyleColorSliderGrab) - StyleColorSliderGrabActive StyleColorID = StyleColorID(imgui.StyleColorSliderGrabActive) - StyleColorButton StyleColorID = StyleColorID(imgui.StyleColorButton) - StyleColorButtonHovered StyleColorID = StyleColorID(imgui.StyleColorButtonHovered) - StyleColorButtonActive StyleColorID = StyleColorID(imgui.StyleColorButtonActive) - StyleColorHeader StyleColorID = StyleColorID(imgui.StyleColorHeader) - StyleColorHeaderHovered StyleColorID = StyleColorID(imgui.StyleColorHeaderHovered) - StyleColorHeaderActive StyleColorID = StyleColorID(imgui.StyleColorHeaderActive) - StyleColorSeparator StyleColorID = StyleColorID(imgui.StyleColorSeparator) - StyleColorSeparatorHovered StyleColorID = StyleColorID(imgui.StyleColorSeparatorHovered) - StyleColorSeparatorActive StyleColorID = StyleColorID(imgui.StyleColorSeparatorActive) - StyleColorResizeGrip StyleColorID = StyleColorID(imgui.StyleColorResizeGrip) - StyleColorResizeGripHovered StyleColorID = StyleColorID(imgui.StyleColorResizeGripHovered) - StyleColorResizeGripActive StyleColorID = StyleColorID(imgui.StyleColorResizeGripActive) - StyleColorTab StyleColorID = StyleColorID(imgui.StyleColorTab) - StyleColorTabHovered StyleColorID = StyleColorID(imgui.StyleColorTabHovered) - StyleColorTabActive StyleColorID = StyleColorID(imgui.StyleColorTabActive) - StyleColorTabUnfocused StyleColorID = StyleColorID(imgui.StyleColorTabUnfocused) - StyleColorTabUnfocusedActive StyleColorID = StyleColorID(imgui.StyleColorTabUnfocusedActive) - StyleColorPlotLines StyleColorID = StyleColorID(imgui.StyleColorPlotLines) - StyleColorPlotLinesHovered StyleColorID = StyleColorID(imgui.StyleColorPlotLinesHovered) - StyleColorProgressBarActive StyleColorID = StyleColorPlotLinesHovered - StyleColorPlotHistogram StyleColorID = StyleColorID(imgui.StyleColorPlotHistogram) - StyleColorPlotHistogramHovered StyleColorID = StyleColorID(imgui.StyleColorPlotHistogramHovered) - StyleColorTableHeaderBg StyleColorID = StyleColorID(imgui.StyleColorTableHeaderBg) - StyleColorTableBorderStrong StyleColorID = StyleColorID(imgui.StyleColorTableBorderStrong) - StyleColorTableBorderLight StyleColorID = StyleColorID(imgui.StyleColorTableBorderLight) - StyleColorTableRowBg StyleColorID = StyleColorID(imgui.StyleColorTableRowBg) - StyleColorTableRowBgAlt StyleColorID = StyleColorID(imgui.StyleColorTableRowBgAlt) - StyleColorTextSelectedBg StyleColorID = StyleColorID(imgui.StyleColorTextSelectedBg) - StyleColorDragDropTarget StyleColorID = StyleColorID(imgui.StyleColorDragDropTarget) - StyleColorNavHighlight StyleColorID = StyleColorID(imgui.StyleColorNavHighlight) - StyleColorNavWindowingHighlight StyleColorID = StyleColorID(imgui.StyleColorNavWindowingHighlight) - StyleColorNavWindowingDimBg StyleColorID = StyleColorID(imgui.StyleColorNavWindowingDimBg) - StyleColorModalWindowDimBg StyleColorID = StyleColorID(imgui.StyleColorModalWindowDimBg) + StyleColorText = StyleColorID(imgui.StyleColorText) // color + StyleColorTextDisabled = StyleColorID(imgui.StyleColorTextDisabled) // disabled-color + StyleColorWindowBg = StyleColorID(imgui.StyleColorWindowBg) // background-color + StyleColorChildBg = StyleColorID(imgui.StyleColorChildBg) // child-background-color + StyleColorPopupBg = StyleColorID(imgui.StyleColorPopupBg) // popup-background-color + StyleColorBorder = StyleColorID(imgui.StyleColorBorder) // border-color + StyleColorBorderShadow = StyleColorID(imgui.StyleColorBorderShadow) // border-shadow-color + StyleColorFrameBg = StyleColorID(imgui.StyleColorFrameBg) // frame-background-color + StyleColorFrameBgHovered = StyleColorID(imgui.StyleColorFrameBgHovered) // frame-background-hovered-color + StyleColorFrameBgActive = StyleColorID(imgui.StyleColorFrameBgActive) // frame-background-active-color + StyleColorTitleBg = StyleColorID(imgui.StyleColorTitleBg) // title-background-color + StyleColorTitleBgActive = StyleColorID(imgui.StyleColorTitleBgActive) // title-background-active-color + StyleColorTitleBgCollapsed = StyleColorID(imgui.StyleColorTitleBgCollapsed) // title-background-collapsed-color + StyleColorMenuBarBg = StyleColorID(imgui.StyleColorMenuBarBg) // menu-bar-background-color + StyleColorScrollbarBg = StyleColorID(imgui.StyleColorScrollbarBg) // scrollbar-background-color + StyleColorScrollbarGrab = StyleColorID(imgui.StyleColorScrollbarGrab) // scrollbar-grab-color + StyleColorScrollbarGrabHovered = StyleColorID(imgui.StyleColorScrollbarGrabHovered) // scrollbar-grab-hovered-color + StyleColorScrollbarGrabActive = StyleColorID(imgui.StyleColorScrollbarGrabActive) // scrollbar-grab-active-color + StyleColorCheckMark = StyleColorID(imgui.StyleColorCheckMark) // checkmark-color + StyleColorSliderGrab = StyleColorID(imgui.StyleColorSliderGrab) // slider-grab-color + StyleColorSliderGrabActive = StyleColorID(imgui.StyleColorSliderGrabActive) // slider-grab-active-color + StyleColorButton = StyleColorID(imgui.StyleColorButton) // button-color + StyleColorButtonHovered = StyleColorID(imgui.StyleColorButtonHovered) // button-hovered-color + StyleColorButtonActive = StyleColorID(imgui.StyleColorButtonActive) // button-active-color + StyleColorHeader = StyleColorID(imgui.StyleColorHeader) // header-color + StyleColorHeaderHovered = StyleColorID(imgui.StyleColorHeaderHovered) // header-hovered-color + StyleColorHeaderActive = StyleColorID(imgui.StyleColorHeaderActive) // header-active-color + StyleColorSeparator = StyleColorID(imgui.StyleColorSeparator) // separator-color + StyleColorSeparatorHovered = StyleColorID(imgui.StyleColorSeparatorHovered) // separator-hovered-color + StyleColorSeparatorActive = StyleColorID(imgui.StyleColorSeparatorActive) // separator-active-color + StyleColorResizeGrip = StyleColorID(imgui.StyleColorResizeGrip) // resize-grip-color + StyleColorResizeGripHovered = StyleColorID(imgui.StyleColorResizeGripHovered) // resize-grip-hovered-color + StyleColorResizeGripActive = StyleColorID(imgui.StyleColorResizeGripActive) // resize-grip-active-color + StyleColorTab = StyleColorID(imgui.StyleColorTab) // tab-color + StyleColorTabHovered = StyleColorID(imgui.StyleColorTabHovered) // tab-hovered-color + StyleColorTabActive = StyleColorID(imgui.StyleColorTabActive) // tab-active-color + StyleColorTabUnfocused = StyleColorID(imgui.StyleColorTabUnfocused) // tab-unfocused-color + StyleColorTabUnfocusedActive = StyleColorID(imgui.StyleColorTabUnfocusedActive) // tab-unfocused-active-color + StyleColorPlotLines = StyleColorID(imgui.StyleColorPlotLines) // plot-lines-color + StyleColorPlotLinesHovered = StyleColorID(imgui.StyleColorPlotLinesHovered) // plot-lines-hovered-color + StyleColorProgressBarActive = StyleColorPlotLinesHovered // progress-bar-active-color + StyleColorPlotHistogram = StyleColorID(imgui.StyleColorPlotHistogram) // plot-histogram-color + StyleColorPlotHistogramHovered = StyleColorID(imgui.StyleColorPlotHistogramHovered) // plot-histogram-hovered-color + StyleColorTableHeaderBg = StyleColorID(imgui.StyleColorTableHeaderBg) // table-header-background-color + StyleColorTableBorderStrong = StyleColorID(imgui.StyleColorTableBorderStrong) // table-border-strong-color + StyleColorTableBorderLight = StyleColorID(imgui.StyleColorTableBorderLight) // table-border-light-color + StyleColorTableRowBg = StyleColorID(imgui.StyleColorTableRowBg) // table-row-background-color + StyleColorTableRowBgAlt = StyleColorID(imgui.StyleColorTableRowBgAlt) // table-row-alternate-background-color + StyleColorTextSelectedBg = StyleColorID(imgui.StyleColorTextSelectedBg) // text-selected-background-color + StyleColorDragDropTarget = StyleColorID(imgui.StyleColorDragDropTarget) // drag-drop-target-color + StyleColorNavHighlight = StyleColorID(imgui.StyleColorNavHighlight) // navigation-highlight-color + StyleColorNavWindowingHighlight = StyleColorID(imgui.StyleColorNavWindowingHighlight) // windowing-highlight-color + StyleColorNavWindowingDimBg = StyleColorID(imgui.StyleColorNavWindowingDimBg) // windowing-dim-background-color + StyleColorModalWindowDimBg = StyleColorID(imgui.StyleColorModalWindowDimBg) // modal-window-dim-background-color ) // StyleVarID identifies a style variable in the UI style. type StyleVarID imgui.StyleVarID // Style IDs. +// comments at same line is a CSS name. const ( // StyleVarAlpha is a float. - StyleVarAlpha StyleVarID = StyleVarID(imgui.StyleVarAlpha) - // float DisabledAlpha. - StyleVarDisabledAlpha StyleVarID = StyleVarID(imgui.StyleVarDisabledAlpha) + StyleVarAlpha = StyleVarID(imgui.StyleVarAlpha) // alpha + // StyleVarDisabledAlpha is a float. + StyleVarDisabledAlpha = StyleVarID(imgui.StyleVarDisabledAlpha) // disabled-alpha // StyleVarWindowPadding is a Vec2. - StyleVarWindowPadding StyleVarID = StyleVarID(imgui.StyleVarWindowPadding) + StyleVarWindowPadding = StyleVarID(imgui.StyleVarWindowPadding) // window-padding // StyleVarWindowRounding is a float. - StyleVarWindowRounding StyleVarID = StyleVarID(imgui.StyleVarWindowRounding) + StyleVarWindowRounding = StyleVarID(imgui.StyleVarWindowRounding) // window-rounding // StyleVarWindowBorderSize is a float. - StyleVarWindowBorderSize StyleVarID = StyleVarID(imgui.StyleVarWindowBorderSize) + StyleVarWindowBorderSize = StyleVarID(imgui.StyleVarWindowBorderSize) // window-border-size // StyleVarWindowMinSize is a Vec2. - StyleVarWindowMinSize StyleVarID = StyleVarID(imgui.StyleVarWindowMinSize) + StyleVarWindowMinSize = StyleVarID(imgui.StyleVarWindowMinSize) // window-min-size // StyleVarWindowTitleAlign is a Vec2. - StyleVarWindowTitleAlign StyleVarID = StyleVarID(imgui.StyleVarWindowTitleAlign) + StyleVarWindowTitleAlign = StyleVarID(imgui.StyleVarWindowTitleAlign) // window-title-align // StyleVarChildRounding is a float. - StyleVarChildRounding StyleVarID = StyleVarID(imgui.StyleVarChildRounding) + StyleVarChildRounding = StyleVarID(imgui.StyleVarChildRounding) // child-rounding // StyleVarChildBorderSize is a float. - StyleVarChildBorderSize StyleVarID = StyleVarID(imgui.StyleVarChildBorderSize) + StyleVarChildBorderSize = StyleVarID(imgui.StyleVarChildBorderSize) // child-border-size // StyleVarPopupRounding is a float. - StyleVarPopupRounding StyleVarID = StyleVarID(imgui.StyleVarPopupRounding) + StyleVarPopupRounding = StyleVarID(imgui.StyleVarPopupRounding) // popup-rounding // StyleVarPopupBorderSize is a float. - StyleVarPopupBorderSize StyleVarID = StyleVarID(imgui.StyleVarPopupBorderSize) + StyleVarPopupBorderSize = StyleVarID(imgui.StyleVarPopupBorderSize) // popup-border-size // StyleVarFramePadding is a Vec2. - StyleVarFramePadding StyleVarID = StyleVarID(imgui.StyleVarFramePadding) + StyleVarFramePadding = StyleVarID(imgui.StyleVarFramePadding) // frame-padding // StyleVarFrameRounding is a float. - StyleVarFrameRounding StyleVarID = StyleVarID(imgui.StyleVarFrameRounding) + StyleVarFrameRounding = StyleVarID(imgui.StyleVarFrameRounding) // frame-rounding // StyleVarFrameBorderSize is a float. - StyleVarFrameBorderSize StyleVarID = StyleVarID(imgui.StyleVarFrameBorderSize) + StyleVarFrameBorderSize = StyleVarID(imgui.StyleVarFrameBorderSize) // frame-border-size // StyleVarItemSpacing is a Vec2. - StyleVarItemSpacing StyleVarID = StyleVarID(imgui.StyleVarItemSpacing) + StyleVarItemSpacing = StyleVarID(imgui.StyleVarItemSpacing) // item-spacing // StyleVarItemInnerSpacing is a Vec2. - StyleVarItemInnerSpacing StyleVarID = StyleVarID(imgui.StyleVarItemInnerSpacing) + StyleVarItemInnerSpacing = StyleVarID(imgui.StyleVarItemInnerSpacing) // item-inner-spacing // StyleVarIndentSpacing is a float. - StyleVarIndentSpacing StyleVarID = StyleVarID(imgui.StyleVarIndentSpacing) + StyleVarIndentSpacing = StyleVarID(imgui.StyleVarIndentSpacing) // indent-spacing // StyleVarScrollbarSize is a float. - StyleVarScrollbarSize StyleVarID = StyleVarID(imgui.StyleVarScrollbarSize) + StyleVarScrollbarSize = StyleVarID(imgui.StyleVarScrollbarSize) // scrollbar-size // StyleVarScrollbarRounding is a float. - StyleVarScrollbarRounding StyleVarID = StyleVarID(imgui.StyleVarScrollbarRounding) + StyleVarScrollbarRounding = StyleVarID(imgui.StyleVarScrollbarRounding) // scrollbar-rounding // StyleVarGrabMinSize is a float. - StyleVarGrabMinSize StyleVarID = StyleVarID(imgui.StyleVarGrabMinSize) + StyleVarGrabMinSize = StyleVarID(imgui.StyleVarGrabMinSize) // grab-min-size // StyleVarGrabRounding is a float. - StyleVarGrabRounding StyleVarID = StyleVarID(imgui.StyleVarGrabRounding) + StyleVarGrabRounding = StyleVarID(imgui.StyleVarGrabRounding) // grab-rounding // StyleVarTabRounding is a float. - StyleVarTabRounding StyleVarID = StyleVarID(imgui.StyleVarTabRounding) + StyleVarTabRounding = StyleVarID(imgui.StyleVarTabRounding) // tab-rounding // StyleVarButtonTextAlign is a Vec2. - StyleVarButtonTextAlign StyleVarID = StyleVarID(imgui.StyleVarButtonTextAlign) + StyleVarButtonTextAlign = StyleVarID(imgui.StyleVarButtonTextAlign) // button-text-align // StyleVarSelectableTextAlign is a Vec2. - StyleVarSelectableTextAlign StyleVarID = StyleVarID(imgui.StyleVarSelectableTextAlign) + StyleVarSelectableTextAlign = StyleVarID(imgui.StyleVarSelectableTextAlign) // selectable-text-align ) // IsVec2 returns true if the style var id should be processed as imgui.Vec2 // if not, it is interpreted as float32. -func (s StyleVarID) IsVec2() bool { +func (i StyleVarID) IsVec2() bool { lookup := map[StyleVarID]bool{ // StyleVarWindowPadding is a Vec2. StyleVarWindowPadding: true, @@ -137,7 +144,7 @@ func (s StyleVarID) IsVec2() bool { StyleVarSelectableTextAlign: true, } - result, ok := lookup[s] + result, ok := lookup[i] return result && ok } diff --git a/StyleIDs_string.go b/StyleIDs_string.go new file mode 100644 index 00000000..e392a237 --- /dev/null +++ b/StyleIDs_string.go @@ -0,0 +1,127 @@ +// Code generated by "stringer -type=StyleColorID,StyleVarID -output=StyleIDs_string.go -linecomment"; DO NOT EDIT. + +package giu + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[StyleColorText-0] + _ = x[StyleColorTextDisabled-1] + _ = x[StyleColorWindowBg-2] + _ = x[StyleColorChildBg-3] + _ = x[StyleColorPopupBg-4] + _ = x[StyleColorBorder-5] + _ = x[StyleColorBorderShadow-6] + _ = x[StyleColorFrameBg-7] + _ = x[StyleColorFrameBgHovered-8] + _ = x[StyleColorFrameBgActive-9] + _ = x[StyleColorTitleBg-10] + _ = x[StyleColorTitleBgActive-11] + _ = x[StyleColorTitleBgCollapsed-12] + _ = x[StyleColorMenuBarBg-13] + _ = x[StyleColorScrollbarBg-14] + _ = x[StyleColorScrollbarGrab-15] + _ = x[StyleColorScrollbarGrabHovered-16] + _ = x[StyleColorScrollbarGrabActive-17] + _ = x[StyleColorCheckMark-18] + _ = x[StyleColorSliderGrab-19] + _ = x[StyleColorSliderGrabActive-20] + _ = x[StyleColorButton-21] + _ = x[StyleColorButtonHovered-22] + _ = x[StyleColorButtonActive-23] + _ = x[StyleColorHeader-24] + _ = x[StyleColorHeaderHovered-25] + _ = x[StyleColorHeaderActive-26] + _ = x[StyleColorSeparator-27] + _ = x[StyleColorSeparatorHovered-28] + _ = x[StyleColorSeparatorActive-29] + _ = x[StyleColorResizeGrip-30] + _ = x[StyleColorResizeGripHovered-31] + _ = x[StyleColorResizeGripActive-32] + _ = x[StyleColorTab-33] + _ = x[StyleColorTabHovered-34] + _ = x[StyleColorTabActive-35] + _ = x[StyleColorTabUnfocused-36] + _ = x[StyleColorTabUnfocusedActive-37] + _ = x[StyleColorPlotLines-38] + _ = x[StyleColorPlotLinesHovered-39] + _ = x[StyleColorProgressBarActive-39] + _ = x[StyleColorPlotHistogram-40] + _ = x[StyleColorPlotHistogramHovered-41] + _ = x[StyleColorTableHeaderBg-42] + _ = x[StyleColorTableBorderStrong-43] + _ = x[StyleColorTableBorderLight-44] + _ = x[StyleColorTableRowBg-45] + _ = x[StyleColorTableRowBgAlt-46] + _ = x[StyleColorTextSelectedBg-47] + _ = x[StyleColorDragDropTarget-48] + _ = x[StyleColorNavHighlight-49] + _ = x[StyleColorNavWindowingHighlight-50] + _ = x[StyleColorNavWindowingDimBg-51] + _ = x[StyleColorModalWindowDimBg-52] +} + +const _StyleColorID_name = "colordisabled-colorbackground-colorchild-background-colorpopup-background-colorborder-colorborder-shadow-colorframe-background-colorframe-background-hovered-colorframe-background-active-colortitle-background-colortitle-background-active-colortitle-background-collapsed-colormenu-bar-background-colorscrollbar-background-colorscrollbar-grab-colorscrollbar-grab-hovered-colorscrollbar-grab-active-colorcheckmark-colorslider-grab-colorslider-grab-active-colorbutton-colorbutton-hovered-colorbutton-active-colorheader-colorheader-hovered-colorheader-active-colorseparator-colorseparator-hovered-colorseparator-active-colorresize-grip-colorresize-grip-hovered-colorresize-grip-active-colortab-colortab-hovered-colortab-active-colortab-unfocused-colortab-unfocused-active-colorplot-lines-colorplot-lines-hovered-colorplot-histogram-colorplot-histogram-hovered-colortable-header-background-colortable-border-strong-colortable-border-light-colortable-row-background-colortable-row-alternate-background-colortext-selected-background-colordrag-drop-target-colornavigation-highlight-colorwindowing-highlight-colorwindowing-dim-background-colormodal-window-dim-background-color" + +var _StyleColorID_index = [...]uint16{0, 5, 19, 35, 57, 79, 91, 110, 132, 162, 191, 213, 242, 274, 299, 325, 345, 373, 400, 415, 432, 456, 468, 488, 507, 519, 539, 558, 573, 596, 618, 635, 660, 684, 693, 710, 726, 745, 771, 787, 811, 831, 859, 888, 913, 937, 963, 999, 1029, 1051, 1077, 1102, 1132, 1165} + +func (i StyleColorID) String() string { + if i < 0 || i >= StyleColorID(len(_StyleColorID_index)-1) { + return "StyleColorID(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _StyleColorID_name[_StyleColorID_index[i]:_StyleColorID_index[i+1]] +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[StyleVarAlpha-0] + _ = x[StyleVarDisabledAlpha-1] + _ = x[StyleVarWindowPadding-2] + _ = x[StyleVarWindowRounding-3] + _ = x[StyleVarWindowBorderSize-4] + _ = x[StyleVarWindowMinSize-5] + _ = x[StyleVarWindowTitleAlign-6] + _ = x[StyleVarChildRounding-7] + _ = x[StyleVarChildBorderSize-8] + _ = x[StyleVarPopupRounding-9] + _ = x[StyleVarPopupBorderSize-10] + _ = x[StyleVarFramePadding-11] + _ = x[StyleVarFrameRounding-12] + _ = x[StyleVarFrameBorderSize-13] + _ = x[StyleVarItemSpacing-14] + _ = x[StyleVarItemInnerSpacing-15] + _ = x[StyleVarIndentSpacing-16] + _ = x[StyleVarScrollbarSize-18] + _ = x[StyleVarScrollbarRounding-19] + _ = x[StyleVarGrabMinSize-20] + _ = x[StyleVarGrabRounding-21] + _ = x[StyleVarTabRounding-22] + _ = x[StyleVarButtonTextAlign-23] + _ = x[StyleVarSelectableTextAlign-24] +} + +const ( + _StyleVarID_name_0 = "alphadisabled-alphawindow-paddingwindow-roundingwindow-border-sizewindow-min-sizewindow-title-alignchild-roundingchild-border-sizepopup-roundingpopup-border-sizeframe-paddingframe-roundingframe-border-sizeitem-spacingitem-inner-spacingindent-spacing" + _StyleVarID_name_1 = "scrollbar-sizescrollbar-roundinggrab-min-sizegrab-roundingtab-roundingbutton-text-alignselectable-text-align" +) + +var ( + _StyleVarID_index_0 = [...]uint8{0, 5, 19, 33, 48, 66, 81, 99, 113, 130, 144, 161, 174, 188, 205, 217, 235, 249} + _StyleVarID_index_1 = [...]uint8{0, 14, 32, 45, 58, 70, 87, 108} +) + +func (i StyleVarID) String() string { + switch { + case 0 <= i && i <= 16: + return _StyleVarID_name_0[_StyleVarID_index_0[i]:_StyleVarID_index_0[i+1]] + case 18 <= i && i <= 24: + i -= 18 + return _StyleVarID_name_1[_StyleVarID_index_1[i]:_StyleVarID_index_1[i+1]] + default: + return "StyleVarID(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/StyleIDs_string2enum.go b/StyleIDs_string2enum.go new file mode 100644 index 00000000..f6921d7b --- /dev/null +++ b/StyleIDs_string2enum.go @@ -0,0 +1,202 @@ +// Code generated by "string2enum -samepkg -type=StyleColorID,StyleVarID -output=StyleIDs_string2enum.go -linecomment"; DO NOT EDIT. + +package giu + +import "fmt" + +// StyleColorIDFromString returns the StyleColorID enum corresponding to s. +func StyleColorIDFromString(s string) StyleColorID { + if len(s) == 0 { + return 0 + } + for i := range _StyleColorID_index[:len(_StyleColorID_index)-1] { + if s == _StyleColorID_name[_StyleColorID_index[i]:_StyleColorID_index[i+1]] { + return StyleColorID(i) + } + } + panic(fmt.Errorf("unable to locate StyleColorID enum corresponding to %q", s)) +} + +func _(s string) { + // Check for duplicate string values in type "StyleColorID". + switch s { + // 0 + case "color": + // 1 + case "disabled-color": + // 2 + case "background-color": + // 3 + case "child-background-color": + // 4 + case "popup-background-color": + // 5 + case "border-color": + // 6 + case "border-shadow-color": + // 7 + case "frame-background-color": + // 8 + case "frame-background-hovered-color": + // 9 + case "frame-background-active-color": + // 10 + case "title-background-color": + // 11 + case "title-background-active-color": + // 12 + case "title-background-collapsed-color": + // 13 + case "menu-bar-background-color": + // 14 + case "scrollbar-background-color": + // 15 + case "scrollbar-grab-color": + // 16 + case "scrollbar-grab-hovered-color": + // 17 + case "scrollbar-grab-active-color": + // 18 + case "checkmark-color": + // 19 + case "slider-grab-color": + // 20 + case "slider-grab-active-color": + // 21 + case "button-color": + // 22 + case "button-hovered-color": + // 23 + case "button-active-color": + // 24 + case "header-color": + // 25 + case "header-hovered-color": + // 26 + case "header-active-color": + // 27 + case "separator-color": + // 28 + case "separator-hovered-color": + // 29 + case "separator-active-color": + // 30 + case "resize-grip-color": + // 31 + case "resize-grip-hovered-color": + // 32 + case "resize-grip-active-color": + // 33 + case "tab-color": + // 34 + case "tab-hovered-color": + // 35 + case "tab-active-color": + // 36 + case "tab-unfocused-color": + // 37 + case "tab-unfocused-active-color": + // 38 + case "plot-lines-color": + // 39 + case "plot-lines-hovered-color": + // 40 + case "plot-histogram-color": + // 41 + case "plot-histogram-hovered-color": + // 42 + case "table-header-background-color": + // 43 + case "table-border-strong-color": + // 44 + case "table-border-light-color": + // 45 + case "table-row-background-color": + // 46 + case "table-row-alternate-background-color": + // 47 + case "text-selected-background-color": + // 48 + case "drag-drop-target-color": + // 49 + case "navigation-highlight-color": + // 50 + case "windowing-highlight-color": + // 51 + case "windowing-dim-background-color": + // 52 + case "modal-window-dim-background-color": + } +} + +// StyleVarIDFromString returns the StyleVarID enum corresponding to s. +func StyleVarIDFromString(s string) StyleVarID { + if len(s) == 0 { + return 0 + } + for i := range _StyleVarID_index_0[:len(_StyleVarID_index_0)-1] { + if s == _StyleVarID_name_0[_StyleVarID_index_0[i]:_StyleVarID_index_0[i+1]] { + return StyleVarID(i + 0) + } + } + for i := range _StyleVarID_index_1[:len(_StyleVarID_index_1)-1] { + if s == _StyleVarID_name_1[_StyleVarID_index_1[i]:_StyleVarID_index_1[i+1]] { + return StyleVarID(i + 18) + } + } + panic(fmt.Errorf("unable to locate StyleVarID enum corresponding to %q", s)) +} + +func _(s string) { + // Check for duplicate string values in type "StyleVarID". + switch s { + // 0 + case "alpha": + // 1 + case "disabled-alpha": + // 2 + case "window-padding": + // 3 + case "window-rounding": + // 4 + case "window-border-size": + // 5 + case "window-min-size": + // 6 + case "window-title-align": + // 7 + case "child-rounding": + // 8 + case "child-border-size": + // 9 + case "popup-rounding": + // 10 + case "popup-border-size": + // 11 + case "frame-padding": + // 12 + case "frame-rounding": + // 13 + case "frame-border-size": + // 14 + case "item-spacing": + // 15 + case "item-inner-spacing": + // 16 + case "indent-spacing": + // 18 + case "scrollbar-size": + // 19 + case "scrollbar-rounding": + // 20 + case "grab-min-size": + // 21 + case "grab-rounding": + // 22 + case "tab-rounding": + // 23 + case "button-text-align": + // 24 + case "selectable-text-align": + } +} diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..1c04c1e9 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,3 @@ +## Package documentation + +- [CSSWidget](./css.md) diff --git a/docs/css.md b/docs/css.md new file mode 100644 index 00000000..53ecc7a8 --- /dev/null +++ b/docs/css.md @@ -0,0 +1,147 @@ +# INTRO + +GIU provides a special widget called "CSSWidget". +This widget allows to set App's style for your app. + +# Usage + +1. open your stylesheet (e.g. with go-embed) +2. Tell giu about your stylesheet using `giu.ParseCSSStyleSheet(...)` +3. Put css tags in your code - `giu.CSS("tag name")` + +For simple use-case see [examples/CSS-styling](../examples/CSS-styling/) + +# Styles list + +## Colors + + + +- `color` - Text +- `disabled-color` - Text Disabled +- `background-color` - Window Bg +- `child-background-color` - Child Bg +- `popup-background-color` - Popup Bg +- `border-color` - Border +- `border-shadow-color` - Border Shadow +- `frame-background-color` - Frame Bg +- `frame-background-hovered-color` - Frame Bg Hovered +- `frame-background-active-color` - Frame Bg Active +- `title-background-color` - Title Bg +- `title-background-active-color` - Title Bg Active +- `title-background-collapsed-color` - Title Bg Collapsed +- `menu-bar-background-color` - Menu Bar Bg +- `scrollbar-background-color` - Scrollbar Bg +- `scrollbar-grab-color` - Scrollbar Grab +- `scrollbar-grab-hovered-color` - Scrollbar Grab Hovered +- `scrollbar-grab-active-color` - Scrollbar Grab Active +- `checkmark-color` - Check Mark +- `slider-grab-color` - Slider Grab +- `slider-grab-active-color` - Slider Grab Active +- `button-color` - Button +- `button-hovered-color` - Button Hovered +- `button-active-color` - Button Active +- `header-color` - Header +- `header-hovered-color` - Header Hovered +- `header-active-color` - Header Active +- `separator-color` - Separator +- `separator-hovered-color` - Separator Hovered +- `separator-active-color` - Separator Active +- `resize-grip-color` - Resize Grip +- `resize-grip-hovered-color` - Resize Grip Hovered +- `resize-grip-active-color` - Resize Grip Active +- `tab-color` - Tab +- `tab-hovered-color` - Tab Hovered +- `tab-active-color` - Tab Active +- `tab-unfocused-color` - Tab Unfocused +- `tab-unfocused-active-color` - Tab Unfocused Active +- `plot-lines-color` - Plot Lines +- `plot-lines-hovered-color` - Plot Lines Hovered +- `progress-bar-active-color` - Progress Bar Active +- `plot-histogram-color` - Plot Histogram +- `plot-histogram-hovered-color` - Plot Histogram Hovered +- `table-header-background-color` - Table Header Bg +- `table-border-strong-color` - Table Border Strong +- `table-border-light-color` - Table Border Light +- `table-row-background-color` - Table Row Bg +- `table-row-alternate-background-color` - Table Row Bg Alt +- `text-selected-background-color` - Text Selected Bg +- `drag-drop-target-color` - Drag Drop Target +- `navigation-highlight-color` - Nav Highlight +- `windowing-highlight-color` - Nav Windowing Highlight +- `windowing-dim-background-color` - Nav Windowing Dim Bg +- `modal-window-dim-background-color` - Modal Window Dim Bg + +## Style Variables + + + +- `alpha` - Alpha (float) +- `disabled-alpha` - Disabled Alpha (float) +- `window-padding` - Window Padding (Vec 2) +- `window-rounding` - Window Rounding (float) +- `window-border-size` - Window Border Size (float) +- `window-min-size` - Window Min Size (Vec 2) +- `window-title-align` - Window Title Align (Vec 2) +- `child-rounding` - Child Rounding (float) +- `child-border-size` - Child Border Size (float) +- `popup-rounding` - Popup Rounding (float) +- `popup-border-size` - Popup Border Size (float) +- `frame-padding` - Frame Padding (Vec 2) +- `frame-rounding` - Frame Rounding (float) +- `frame-border-size` - Frame Border Size (float) +- `item-spacing` - Item Spacing (Vec 2) +- `item-inner-spacing` - Item Inner Spacing (Vec 2) +- `indent-spacing` - Indent Spacing (float) +- `scrollbar-size` - Scrollbar Size (float) +- `scrollbar-rounding` - Scrollbar Rounding (float) +- `grab-min-size` - Grab Min Size (float) +- `grab-rounding` - Grab Rounding (float) +- `tab-rounding` - Tab Rounding (float) +- `button-text-align` - Button Text Align (Vec 2) +- `selectable-text-align` - Selectable Text Align (Vec 2) + +# Data types + +- color - supported types are: + * Named colors (e.g. red, yellow, e.t.c.) + * `rgb()` and `rgba()` + * `hsl()` and `hsla()` + * `hwb()` and `hwba()` + * `hsv()` and `hsva()` + * for more details about colors parsing visit [this repository](https://github.com/mazznoer/csscolorparser) +- float in form of plain number +- Vec2 - set of **exactly two** numbers, first for X and second for Y + +## example + +```css +main { + color: rgba(50, 100, 150, 255); + background-color: yellow; + alpha: 100; + item-spacing: 80, 20; +} +``` + +# special tags + +CSS widget supports a **special tag** called `main`. +This tag is automatically applied for the whole app and you don't need +to perform any additional actions to add it. +There is **no** need to call `giu.CSS("main")` + +# limitations + +- be careful with CSSS comments since they may not be parsed correctly :smile: + e.g. comments inside tags may not be supported, so if you need + comment out the whole tag, However feel free to play with that. +- more complex rules are not supported, just the simpliest one (like ruleName {...}) diff --git a/examples/CSS-styling/main.go b/examples/CSS-styling/main.go new file mode 100644 index 00000000..eea4a9fa --- /dev/null +++ b/examples/CSS-styling/main.go @@ -0,0 +1,29 @@ +package main + +import ( + _ "embed" + + "github.com/AllenDang/giu" +) + +//go:embed style.css +var cssStyle []byte + +func loop() { + giu.Window("Window").Layout( + giu.CSSTag("button").To( + giu.Button("HI! I'm a button styled with CSS"), + ), + giu.CSSTag("label").To( + giu.Label("I'ma normal label"), + ), + ) +} + +func main() { + wnd := giu.NewMasterWindow("CSS Style [example]", 640, 480, 0) + if err := giu.ParseCSSStyleSheet(cssStyle); err != nil { + panic(err) + } + wnd.Run(loop) +} diff --git a/examples/CSS-styling/style.css b/examples/CSS-styling/style.css new file mode 100644 index 00000000..4b9330be --- /dev/null +++ b/examples/CSS-styling/style.css @@ -0,0 +1,13 @@ +main { + background-color: blue; + frame-padding: 80, 20; +} + +label { + color: black; +} + +button { + color: red; + button-color: yellow; +} diff --git a/go.mod b/go.mod index 022da48b..e4b9b02c 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,8 @@ require ( github.com/AllenDang/imgui-go v1.12.1-0.20220322114136-499bbf6a42ad github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad + github.com/mazznoer/csscolorparser v0.1.3 + github.com/napsy/go-css v0.0.0-20221107082635-4ed403047a64 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/sahilm/fuzzy v0.1.0 github.com/stretchr/testify v1.8.1 diff --git a/go.sum b/go.sum index 6933b1b4..2f112912 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,14 @@ github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVin github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad h1:kX51IjbsJPCvzV9jUoVQG9GEUqIq5hjfYzXTqQ52Rh8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/gucio321/go-css v0.0.0-20220927183634-22e6096f036e h1:5FrujxF+Hl8A1vKMb91jyswjspgiDVnkkyZ0xY/cQvY= +github.com/gucio321/go-css v0.0.0-20220927183634-22e6096f036e/go.mod h1:HqZYcKcNnv50fgOTdGUn9YbJa2qC9oJ3kLnyrwwVzUI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mazznoer/csscolorparser v0.1.3 h1:vug4zh6loQxAUxfU1DZEu70gTPufDPspamZlHAkKcxE= +github.com/mazznoer/csscolorparser v0.1.3/go.mod h1:Aj22+L/rYN/Y6bj3bYqO3N6g1dtdHtGfQ32xZ5PJQic= +github.com/napsy/go-css v0.0.0-20221107082635-4ed403047a64 h1:7LWtWY3Ei9ghnamqn8xCu7LOXAKaQrcfbcf0sU33LG4= +github.com/napsy/go-css v0.0.0-20221107082635-4ed403047a64/go.mod h1:HqZYcKcNnv50fgOTdGUn9YbJa2qC9oJ3kLnyrwwVzUI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=