Updated Button

This commit is contained in:
Alexei Anoshenko 2025-08-06 17:17:57 +03:00
parent c4dfba2796
commit 049a2b365f
7 changed files with 158 additions and 103 deletions

View File

@ -151,6 +151,14 @@ ul:focus {
overflow: auto; overflow: auto;
} }
.ruiButton {
display: flex;
overflow: auto;
justify-content: center;
align-items: center;
flex-flow: row;
}
.ruiColumnLayout { .ruiColumnLayout {
overflow: auto; overflow: auto;
} }

View File

@ -2,37 +2,74 @@ package rui
// Button represent a Button view // Button represent a Button view
type Button interface { type Button interface {
CustomView ListLayout
} }
type buttonData struct { type buttonData struct {
CustomViewData listLayoutData
} }
// NewButton create new Button object and return it // NewButton create new Button object and return it
func NewButton(session Session, params Params) Button { func NewButton(session Session, params Params) Button {
button := new(buttonData) button := new(buttonData)
InitCustomView(button, "Button", session, params) button.init(session)
setInitParams(button, params)
return button return button
} }
func newButton(session Session) View { func newButton(session Session) View {
return NewButton(session, nil) return new(buttonData)
//return new(buttonData)
} }
func (button *buttonData) CreateSuperView(session Session) View { func (button *buttonData) init(session Session) {
return NewListLayout(session, Params{ button.listLayoutData.init(session)
Semantics: ButtonSemantics, button.tag = "Button"
Style: "ruiButton", button.systemClass = "ruiButton"
StyleDisabled: "ruiDisabledButton", button.setRaw(Style, "ruiEnabledButton")
HorizontalAlign: CenterAlign, button.setRaw(StyleDisabled, "ruiDisabledButton")
VerticalAlign: CenterAlign, button.setRaw(Semantics, ButtonSemantics)
Orientation: StartToEndOrientation, button.setRaw(TabIndex, 0)
TabIndex: 0,
})
} }
func (button *buttonData) Focusable() bool { func (button *buttonData) Focusable() bool {
return true 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
}

View File

@ -82,8 +82,7 @@ theme {
background-color = @ruiBackgroundColor, background-color = @ruiBackgroundColor,
accent-color = @ruiHighlightColor, accent-color = @ruiHighlightColor,
}, },
ruiButton { ruiEnabledButton {
align = center,
padding = "@ruiButtonVerticalPadding, @ruiButtonHorizontalPadding, @ruiButtonVerticalPadding, @ruiButtonHorizontalPadding", padding = "@ruiButtonVerticalPadding, @ruiButtonHorizontalPadding, @ruiButtonVerticalPadding, @ruiButtonHorizontalPadding",
margin = @ruiButtonMargin, margin = @ruiButtonMargin,
radius = @ruiButtonRadius, radius = @ruiButtonRadius,
@ -92,7 +91,6 @@ theme {
border = _{width = 1px, style = solid, color = @ruiButtonTextColor} border = _{width = 1px, style = solid, color = @ruiButtonTextColor}
}, },
ruiDisabledButton { ruiDisabledButton {
align = center,
padding = "@ruiButtonVerticalPadding, @ruiButtonHorizontalPadding, @ruiButtonVerticalPadding, @ruiButtonHorizontalPadding", padding = "@ruiButtonVerticalPadding, @ruiButtonHorizontalPadding, @ruiButtonVerticalPadding, @ruiButtonHorizontalPadding",
margin = @ruiButtonMargin, margin = @ruiButtonMargin,
radius = @ruiButtonRadius, radius = @ruiButtonRadius,
@ -100,14 +98,14 @@ theme {
text-color = @ruiButtonDisabledTextColor, text-color = @ruiButtonDisabledTextColor,
border = _{width = 1px, style = solid, color = @ruiButtonDisabledTextColor} border = _{width = 1px, style = solid, color = @ruiButtonDisabledTextColor}
}, },
ruiButton:hover { ruiEnabledButton:hover {
text-color = @ruiTextColor, text-color = @ruiTextColor,
background-color = @ruiBackgroundColor, background-color = @ruiBackgroundColor,
}, },
ruiButton:focus { ruiEnabledButton:focus {
shadow = _{spread-radius = @ruiButtonHighlightDilation, blur = @ruiButtonHighlightBlur, color = @ruiHighlightColor }, shadow = _{spread-radius = @ruiButtonHighlightDilation, blur = @ruiButtonHighlightBlur, color = @ruiHighlightColor },
}, },
ruiButton:active { ruiEnabledButton:active {
background-color = @ruiButtonActiveColor background-color = @ruiButtonActiveColor
}, },
ruiDefaultButton { ruiDefaultButton {

View File

@ -457,7 +457,14 @@ func handleKeyEvents(view View, tag PropertyName, data DataObject) {
return 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 { if listeners := getOneArgEventListeners[View, MouseEvent](view, nil, ClickEvent); len(listeners) > 0 {
clickEvent := MouseEvent{ clickEvent := MouseEvent{
TimeStamp: event.TimeStamp, TimeStamp: event.TimeStamp,

View File

@ -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: // GetListWrap returns the wrap type of a ListLayout or ListView subview:

View File

@ -2235,7 +2235,7 @@ const (
// VerticalAlign is the constant for "vertical-align" property tag. // 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 // # Usage in Checkbox
// //
@ -2249,7 +2249,7 @@ const (
// - 2 (CenterAlign) or "center" - Content aligned in the center of the content area. // - 2 (CenterAlign) or "center" - Content aligned in the center of the content area.
// - 3 (StretchAlign) or "stretch" - Content relaxed to fill all 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. // 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. // 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 // # Usage in Checkbox
// //
@ -2305,7 +2305,7 @@ const (
// //
// Sets the horizontal alignment of the content inside a block element. // Sets the horizontal alignment of the content inside a block element.
// //
// Supported types: int, string. // Supported types: Button, int, string.
// //
// Values: // Values:
// - 0 (LeftAlign) or "left" - Left alignment. // - 0 (LeftAlign) or "left" - Left alignment.

View File

@ -109,6 +109,86 @@ func split4Values(text string) []string {
return []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) { func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
if visibility, ok := enumProperty(style, Visibility, session, Visible); ok { 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) style.cssListStyle(builder, session)
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`)
}
}
}
if r, ok := rangeProperty(style, Row, session); ok { if r, ok := rangeProperty(style, Row, session); ok {
builder.add("grid-row", fmt.Sprintf("%d / %d", r.First+1, r.Last+2)) builder.add("grid-row", fmt.Sprintf("%d / %d", r.First+1, r.Last+2))