From 049a2b365f193a9824efe6253baa5346c8c0b179 Mon Sep 17 00:00:00 2001 From: Alexei Anoshenko <2277098+anoshenko@users.noreply.github.com> Date: Wed, 6 Aug 2025 17:17:57 +0300 Subject: [PATCH] Updated Button --- app_styles.css | 8 +++ button.go | 67 +++++++++++++++----- defaultTheme.rui | 10 ++- keyEvents.go | 9 ++- listLayout.go | 2 +- propertyNames.go | 8 +-- viewStyle.go | 157 ++++++++++++++++++++++++----------------------- 7 files changed, 158 insertions(+), 103 deletions(-) diff --git a/app_styles.css b/app_styles.css index 671ff7e..ce6aa60 100644 --- a/app_styles.css +++ b/app_styles.css @@ -151,6 +151,14 @@ ul:focus { overflow: auto; } +.ruiButton { + display: flex; + overflow: auto; + justify-content: center; + align-items: center; + flex-flow: row; +} + .ruiColumnLayout { overflow: auto; } diff --git a/button.go b/button.go index 0a14efd..5e1f840 100644 --- a/button.go +++ b/button.go @@ -2,37 +2,74 @@ package rui // Button represent a Button view type Button interface { - CustomView + ListLayout } type buttonData struct { - CustomViewData + listLayoutData } // NewButton create new Button object and return it func NewButton(session Session, params Params) Button { button := new(buttonData) - InitCustomView(button, "Button", session, params) + button.init(session) + setInitParams(button, params) return button } func newButton(session Session) View { - return NewButton(session, nil) - //return new(buttonData) + return new(buttonData) } -func (button *buttonData) CreateSuperView(session Session) View { - return NewListLayout(session, Params{ - Semantics: ButtonSemantics, - Style: "ruiButton", - StyleDisabled: "ruiDisabledButton", - HorizontalAlign: CenterAlign, - VerticalAlign: CenterAlign, - Orientation: StartToEndOrientation, - TabIndex: 0, - }) +func (button *buttonData) init(session Session) { + button.listLayoutData.init(session) + button.tag = "Button" + button.systemClass = "ruiButton" + button.setRaw(Style, "ruiEnabledButton") + button.setRaw(StyleDisabled, "ruiDisabledButton") + button.setRaw(Semantics, ButtonSemantics) + button.setRaw(TabIndex, 0) } func (button *buttonData) Focusable() bool { return true } + +// GetButtonVerticalAlign returns the vertical align of a Button subview: +// TopAlign (0), BottomAlign (1), CenterAlign (2), or StretchAlign (3) +// +// The second argument (subviewID) specifies the path to the child element whose value needs to be returned. +// If it is not specified then a value from the first argument (view) is returned. +func GetButtonVerticalAlign(view View, subviewID ...string) int { + return enumStyledProperty(view, subviewID, VerticalAlign, CenterAlign, false) +} + +// GetButtonHorizontalAlign returns the vertical align of a Button subview: +// LeftAlign (0), RightAlign (1), CenterAlign (2), or StretchAlign (3) +// +// The second argument (subviewID) specifies the path to the child element whose value needs to be returned. +// If it is not specified then a value from the first argument (view) is returned. +func GetButtonHorizontalAlign(view View, subviewID ...string) int { + return enumStyledProperty(view, subviewID, HorizontalAlign, CenterAlign, false) +} + +// GetButtonOrientation returns the orientation of a Button subview: +// TopDownOrientation (0), StartToEndOrientation (1), BottomUpOrientation (2), or EndToStartOrientation (3) +// +// The second argument (subviewID) specifies the path to the child element whose value needs to be returned. +// If it is not specified then a value from the first argument (view) is returned. +func GetButtonOrientation(view View, subviewID ...string) int { + if view = getSubview(view, subviewID); view != nil { + if orientation, ok := valueToOrientation(view.Get(Orientation), view.Session()); ok { + return orientation + } + + if value := valueFromStyle(view, Orientation); value != nil { + if orientation, ok := valueToOrientation(value, view.Session()); ok { + return orientation + } + } + } + + return StartToEndOrientation +} diff --git a/defaultTheme.rui b/defaultTheme.rui index f48d0a4..e9765d7 100644 --- a/defaultTheme.rui +++ b/defaultTheme.rui @@ -82,8 +82,7 @@ theme { background-color = @ruiBackgroundColor, accent-color = @ruiHighlightColor, }, - ruiButton { - align = center, + ruiEnabledButton { padding = "@ruiButtonVerticalPadding, @ruiButtonHorizontalPadding, @ruiButtonVerticalPadding, @ruiButtonHorizontalPadding", margin = @ruiButtonMargin, radius = @ruiButtonRadius, @@ -92,7 +91,6 @@ theme { border = _{width = 1px, style = solid, color = @ruiButtonTextColor} }, ruiDisabledButton { - align = center, padding = "@ruiButtonVerticalPadding, @ruiButtonHorizontalPadding, @ruiButtonVerticalPadding, @ruiButtonHorizontalPadding", margin = @ruiButtonMargin, radius = @ruiButtonRadius, @@ -100,14 +98,14 @@ theme { text-color = @ruiButtonDisabledTextColor, border = _{width = 1px, style = solid, color = @ruiButtonDisabledTextColor} }, - ruiButton:hover { + ruiEnabledButton:hover { text-color = @ruiTextColor, background-color = @ruiBackgroundColor, }, - ruiButton:focus { + ruiEnabledButton:focus { shadow = _{spread-radius = @ruiButtonHighlightDilation, blur = @ruiButtonHighlightBlur, color = @ruiHighlightColor }, }, - ruiButton:active { + ruiEnabledButton:active { background-color = @ruiButtonActiveColor }, ruiDefaultButton { diff --git a/keyEvents.go b/keyEvents.go index 22f7621..247bca7 100644 --- a/keyEvents.go +++ b/keyEvents.go @@ -457,7 +457,14 @@ func handleKeyEvents(view View, tag PropertyName, data DataObject) { return } - if tag == KeyDownEvent && view.Focusable() && (event.Key == " " || event.Key == "Enter") && !IsDisabled(view) { + if tag == KeyDownEvent && view.Focusable() && (event.Key == " " || event.Key == "Enter") && + !IsDisabled(view) && GetSemantics(view) != ButtonSemantics { + + switch view.Tag() { + case "EditView", "ListView", "TableView", "TabsLayout", "TimePicker", "DatePicker", "AudioPlayer", "VideoPlayer": + return + } + if listeners := getOneArgEventListeners[View, MouseEvent](view, nil, ClickEvent); len(listeners) > 0 { clickEvent := MouseEvent{ TimeStamp: event.TimeStamp, diff --git a/listLayout.go b/listLayout.go index 2481a30..1eae12a 100644 --- a/listLayout.go +++ b/listLayout.go @@ -238,7 +238,7 @@ func GetListOrientation(view View, subviewID ...string) int { } } - return 0 + return TopDownOrientation } // GetListWrap returns the wrap type of a ListLayout or ListView subview: diff --git a/propertyNames.go b/propertyNames.go index b327ca2..6a58889 100644 --- a/propertyNames.go +++ b/propertyNames.go @@ -2235,7 +2235,7 @@ const ( // VerticalAlign is the constant for "vertical-align" property tag. // - // Used by Checkbox, ListLayout, ListView, Popup, SvgImageView. + // Used by Button, Checkbox, ListLayout, ListView, Popup, SvgImageView. // // # Usage in Checkbox // @@ -2249,7 +2249,7 @@ const ( // - 2 (CenterAlign) or "center" - Content aligned in the center of the content area. // - 3 (StretchAlign) or "stretch" - Content relaxed to fill all content area. // - // # Usage in ListLayout and ListView + // # Usage in Button, ListLayout and ListView // // Sets the vertical alignment of the content inside a block element. // @@ -2287,7 +2287,7 @@ const ( // HorizontalAlign is the constant for "horizontal-align" property tag. // - // Used by Checkbox, ListLayout, ListView, Popup, SvgImageView. + // Used by Button, Checkbox, ListLayout, ListView, Popup, SvgImageView. // // # Usage in Checkbox // @@ -2305,7 +2305,7 @@ const ( // // Sets the horizontal alignment of the content inside a block element. // - // Supported types: int, string. + // Supported types: Button, int, string. // // Values: // - 0 (LeftAlign) or "left" - Left alignment. diff --git a/viewStyle.go b/viewStyle.go index 15f36fb..316d932 100644 --- a/viewStyle.go +++ b/viewStyle.go @@ -109,6 +109,86 @@ func split4Values(text string) []string { return []string{} } +func (style *viewStyle) cssListStyle(builder cssBuilder, session Session) { + wrap, _ := enumProperty(style, ListWrap, session, 0) + orientation, ok := valueToOrientation(style.Get(Orientation), session) + if ok || wrap > 0 { + cssText := enumProperties[Orientation].cssValues[orientation] + switch wrap { + case ListWrapOn: + cssText += " wrap" + + case ListWrapReverse: + cssText += " wrap-reverse" + } + builder.add(`flex-flow`, cssText) + } + + rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation) + + var hAlignTag, vAlignTag string + if rows { + hAlignTag = `justify-content` + vAlignTag = `align-items` + } else { + hAlignTag = `align-items` + vAlignTag = `justify-content` + } + + if align, ok := enumProperty(style, HorizontalAlign, session, LeftAlign); ok { + switch align { + case LeftAlign: + if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation { + builder.add(hAlignTag, `flex-end`) + } else { + builder.add(hAlignTag, `flex-start`) + } + case RightAlign: + if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation { + builder.add(hAlignTag, `flex-start`) + } else { + builder.add(hAlignTag, `flex-end`) + } + case CenterAlign: + builder.add(hAlignTag, `center`) + + case StretchAlign: + if rows { + builder.add(hAlignTag, `space-between`) + } else { + builder.add(hAlignTag, `stretch`) + } + } + } + + if align, ok := enumProperty(style, VerticalAlign, session, LeftAlign); ok { + switch align { + case TopAlign: + if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation { + builder.add(vAlignTag, `flex-end`) + } else { + builder.add(vAlignTag, `flex-start`) + } + case BottomAlign: + if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation { + builder.add(vAlignTag, `flex-start`) + } else { + builder.add(vAlignTag, `flex-end`) + } + case CenterAlign: + builder.add(vAlignTag, `center`) + + case StretchAlign: + if rows { + builder.add(vAlignTag, `stretch`) + } else { + builder.add(vAlignTag, `space-between`) + } + } + } + +} + func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) { if visibility, ok := enumProperty(style, Visibility, session, Visible); ok { @@ -291,82 +371,7 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) { } } - wrap, _ := enumProperty(style, ListWrap, session, 0) - orientation, ok := valueToOrientation(style.Get(Orientation), session) - if ok || wrap > 0 { - cssText := enumProperties[Orientation].cssValues[orientation] - switch wrap { - case ListWrapOn: - cssText += " wrap" - - case ListWrapReverse: - cssText += " wrap-reverse" - } - builder.add(`flex-flow`, cssText) - } - - rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation) - - var hAlignTag, vAlignTag string - if rows { - hAlignTag = `justify-content` - vAlignTag = `align-items` - } else { - hAlignTag = `align-items` - vAlignTag = `justify-content` - } - - if align, ok := enumProperty(style, HorizontalAlign, session, LeftAlign); ok { - switch align { - case LeftAlign: - if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation { - builder.add(hAlignTag, `flex-end`) - } else { - builder.add(hAlignTag, `flex-start`) - } - case RightAlign: - if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation { - builder.add(hAlignTag, `flex-start`) - } else { - builder.add(hAlignTag, `flex-end`) - } - case CenterAlign: - builder.add(hAlignTag, `center`) - - case StretchAlign: - if rows { - builder.add(hAlignTag, `space-between`) - } else { - builder.add(hAlignTag, `stretch`) - } - } - } - - if align, ok := enumProperty(style, VerticalAlign, session, LeftAlign); ok { - switch align { - case TopAlign: - if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation { - builder.add(vAlignTag, `flex-end`) - } else { - builder.add(vAlignTag, `flex-start`) - } - case BottomAlign: - if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation { - builder.add(vAlignTag, `flex-start`) - } else { - builder.add(vAlignTag, `flex-end`) - } - case CenterAlign: - builder.add(vAlignTag, `center`) - - case StretchAlign: - if rows { - builder.add(vAlignTag, `stretch`) - } else { - builder.add(vAlignTag, `space-between`) - } - } - } + style.cssListStyle(builder, session) if r, ok := rangeProperty(style, Row, session); ok { builder.add("grid-row", fmt.Sprintf("%d / %d", r.First+1, r.Last+2))