Added PopupButtonType

This commit is contained in:
anoshenko 2023-05-15 15:27:37 +03:00
parent 904859ff6e
commit ab421b4c32
5 changed files with 230 additions and 31 deletions

View File

@ -73,7 +73,7 @@ func getStartPage(buffer *strings.Builder, params AppParams, addScripts string)
buffer.WriteString(addScripts)
buffer.WriteString(`</script>
</head>
<body>
<body id="body" onkeydown="keyDownEvent(this, event)">
<div class="ruiRoot" id="ruiRootView"></div>
<div class="ruiPopupLayer" id="ruiPopupLayer" style="visibility: hidden; isolation: isolate;"></div>
<div class="ruiTooltipLayer" id="ruiTooltipLayer" style="visibility: hidden; opacity: 0;">

View File

@ -110,6 +110,26 @@ theme {
ruiButton:active {
background-color = @ruiButtonActiveColor
},
ruiDefaultButton {
align = center,
padding = "@ruiButtonVerticalPadding, @ruiButtonHorizontalPadding, @ruiButtonVerticalPadding, @ruiButtonHorizontalPadding",
margin = @ruiButtonMargin,
radius = @ruiButtonRadius,
background-color = @ruiButtonColor,
text-color = @ruiButtonTextColor,
text-weight = bold,
border = _{width = 1px, style = solid, color = @ruiButtonTextColor}
},
ruiDefaultButton:hover {
text-color = @ruiTextColor,
background-color = @ruiBackgroundColor,
},
ruiDefaultButton:focus {
shadow = _{spread-radius = @ruiButtonHighlightDilation, blur = @ruiButtonHighlightBlur, color = @ruiHighlightColor },
},
ruiDefaultButton:active {
background-color = @ruiButtonActiveColor
},
ruiCheckbox {
radius = 2px,
padding = 1px,

View File

@ -18,6 +18,117 @@ const (
// The additional listener formats:
// func(KeyEvent), func(View), and func().
KeyUpEvent = "key-up-event"
// AltKey is the mask of the "alt" key
AltKey = 1
// CtrlKey is the mask of the "ctrl" key
CtrlKey = 2
// ShiftKey is the mask of the "shift" key
ShiftKey = 4
// MetaKey is the mask of the "meta" key
MetaKey = 8
KeyA = "KeyA"
KeyB = "KeyB"
KeyC = "KeyC"
KeyD = "KeyD"
KeyE = "KeyE"
KeyF = "KeyF"
KeyG = "KeyG"
KeyH = "KeyH"
KeyI = "KeyI"
KeyJ = "KeyJ"
KeyK = "KeyK"
KeyL = "KeyL"
KeyM = "KeyM"
KeyN = "KeyN"
KeyO = "KeyO"
KeyP = "KeyP"
KeyQ = "KeyQ"
KeyR = "KeyR"
KeyS = "KeyS"
KeyT = "KeyT"
KeyU = "KeyU"
KeyV = "KeyV"
KeyW = "KeyW"
KeyX = "KeyX"
KeyY = "KeyY"
KeyZ = "KeyZ"
Digit0Key = "Digit0"
Digit1Key = "Digit1"
Digit2Key = "Digit2"
Digit3Key = "Digit3"
Digit4Key = "Digit4"
Digit5Key = "Digit5"
Digit6Key = "Digit6"
Digit7Key = "Digit7"
Digit8Key = "Digit8"
Digit9Key = "Digit9"
SpaceKey = "Space"
MinusKey = "Minus"
EqualKey = "Equal"
IntlBackslashKey = "IntlBackslash"
BracketLeftKey = "BracketLeft"
BracketRightKey = "BracketRight"
SemicolonKey = "Semicolon"
CommaKey = "Comma"
PeriodKey = "Period"
QuoteKey = "Quote"
BackquoteKey = "Backquote"
SlashKey = "Slash"
EscapeKey = "Escape"
EnterKey = "Enter"
TabKey = "Tab"
CapsLockKey = "CapsLock"
DeleteKey = "Delete"
HelpKey = "Help"
BackspaceKey = "Backspace"
ArrowLeftKey = "ArrowLeft"
ArrowRightKey = "ArrowRight"
ArrowUpKey = "ArrowUp"
ArrowDownKey = "ArrowDown"
HomeKey = "Home"
EndKey = "End"
PageUpKey = "PageUp"
PageDownKey = "PageDown"
F1Key = "F1"
F2Key = "F2"
F3Key = "F3"
F4Key = "F4"
F5Key = "F5"
F6Key = "F6"
F7Key = "F7"
F8Key = "F8"
F9Key = "F9"
F10Key = "F10"
F11Key = "F11"
F12Key = "F12"
F13Key = "F13"
NumLockKey = "NumLock"
NumpadKey0 = "Numpad0"
NumpadKey1 = "Numpad1"
NumpadKey2 = "Numpad2"
NumpadKey3 = "Numpad3"
NumpadKey4 = "Numpad4"
NumpadKey5 = "Numpad5"
NumpadKey6 = "Numpad6"
NumpadKey7 = "Numpad7"
NumpadKey8 = "Numpad8"
NumpadKey9 = "Numpad9"
NumpadDecimalKey = "NumpadDecimal"
NumpadEnterKey = "NumpadEnter"
NumpadAddKey = "NumpadAdd"
NumpadSubtractKey = "NumpadSubtract"
NumpadMultiplyKey = "NumpadMultiply"
NumpadDivideKey = "NumpadDivide"
ShiftLeftKey = "ShiftLeft"
ShiftRightKey = "ShiftRight"
ControlLeftKey = "ControlLeft"
ControlRightKey = "ControlRight"
AltLeftKey = "AltLeft"
AltRightKey = "AltRight"
MetaLeftKey = "MetaLeft"
MetaRightKey = "MetaRight"
)
type KeyEvent struct {
@ -372,12 +483,6 @@ func valueToEventWithOldListeners[V View, E any](value any) ([]func(V, E, E), bo
return nil, false
}
/*
var keyEvents = map[string]struct{ jsEvent, jsFunc string }{
KeyDownEvent: {jsEvent: "onkeydown", jsFunc: "keyDownEvent"},
KeyUpEvent: {jsEvent: "onkeyup", jsFunc: "keyUpEvent"},
}
*/
func (view *viewData) setKeyListener(tag string, value any) bool {
listeners, ok := valueToEventListeners[View, KeyEvent](value)
if !ok {
@ -390,11 +495,13 @@ func (view *viewData) setKeyListener(tag string, value any) bool {
} else {
switch tag {
case KeyDownEvent:
view.properties[tag] = listeners
if view.created {
view.session.updateProperty(view.htmlID(), "onkeydown", "keyDownEvent(this, event)")
}
case KeyUpEvent:
view.properties[tag] = listeners
if view.created {
view.session.updateProperty(view.htmlID(), "onkeyup", "keyUpEvent(this, event)")
}
@ -435,6 +542,7 @@ func getEventWithOldListeners[V View, E any](view View, subviewID []string, tag
}
return []func(V, E, E){}
}
func getEventListeners[V View, E any](view View, subviewID []string, tag string) []func(V, E) {
if len(subviewID) > 0 && subviewID[0] != "" {
view = ViewByID(view, subviewID[0])

View File

@ -78,11 +78,21 @@ const (
// LeftArrow is value of the popup "arrow" property:
// Arrow on the left side of the pop-up window
LeftArrow = 4
// NormalButton is the constant of the popup button type: the normal button
NormalButton PopupButtonType = 0
// DefaultButton is the constant of the popup button type: button that fires when the "Enter" key is pressed
DefaultButton PopupButtonType = 1
// CancelButton is the constant of the popup button type: button that fires when the "Escape" key is pressed
CancelButton PopupButtonType = 2
)
type PopupButtonType int
// PopupButton describes a button that will be placed at the bottom of the window.
type PopupButton struct {
Title string
Type PopupButtonType
OnClick func(Popup)
}
@ -95,11 +105,14 @@ type Popup interface {
onDismiss()
html(buffer *strings.Builder)
viewByHTMLID(id string) View
keyEvent(event KeyEvent) bool
}
type popupData struct {
layerView View
view View
buttons []PopupButton
cancelable bool
dismissListener []func(Popup)
}
@ -273,6 +286,7 @@ func (arrow *popupArrow) createView(popupView View) View {
func (popup *popupData) init(view View, popupParams Params) {
popup.view = view
popup.cancelable = false
session := view.Session()
columnCount := 3
@ -392,13 +406,15 @@ func (popup *popupData) init(view View, popupParams Params) {
TextSize: Px(20),
Content: "✕",
NotTranslate: true,
ClickEvent: func(View) {
popup.Dismiss()
},
ClickEvent: popup.cancel,
})
popup.cancelable = true
case OutsideClose:
outsideClose, _ = boolProperty(popupParams, OutsideClose, session)
if outsideClose {
popup.cancelable = true
}
case Buttons:
switch value := value.(type) {
@ -494,6 +510,7 @@ func (popup *popupData) init(view View, popupParams Params) {
view.Set(Row, viewRow)
popupView.Append(view)
popup.buttons = buttons
if buttonCount := len(buttons); buttonCount > 0 {
buttonsAlign, _ := enumProperty(params, ButtonsAlign, session, RightAlign)
popupCellHeight = append(popupCellHeight, AutoSize())
@ -511,21 +528,31 @@ func (popup *popupData) init(view View, popupParams Params) {
buttonsPanel.Set(Margin, gap)
}
createButton := func(n int, button PopupButton) Button {
return NewButton(session, Params{
Column: n,
Content: button.Title,
ClickEvent: func() {
if button.OnClick != nil {
button.OnClick(popup)
} else {
popup.Dismiss()
}
},
})
}
for i, button := range buttons {
buttonsPanel.Append(createButton(i, button))
title := button.Title
if title == "" && button.Type == CancelButton {
title = "Cancel"
}
buttonView := NewButton(session, Params{
Column: i,
Content: title,
})
if button.OnClick != nil {
fn := button.OnClick
buttonView.Set(ClickEvent, func() {
fn(popup)
})
} else if button.Type == CancelButton {
buttonView.Set(ClickEvent, popup.cancel)
}
if button.Type == DefaultButton {
buttonView.Set(Style, "ruiDefaultButton")
}
buttonsPanel.Append(buttonView)
}
popupView.Append(NewGridLayout(session, Params{
@ -544,11 +571,8 @@ func (popup *popupData) init(view View, popupParams Params) {
}
popup.layerView = NewGridLayout(session, layerParams)
if outsideClose {
popup.layerView.Set(ClickEvent, func(View) {
popup.Dismiss()
})
popup.layerView.Set(ClickEvent, popup.cancel)
}
}
@ -560,12 +584,21 @@ func (popup *popupData) Session() Session {
return popup.view.Session()
}
func (popup *popupData) cancel() {
for _, button := range popup.buttons {
if button.Type == CancelButton && button.OnClick != nil {
button.OnClick(popup)
return
}
}
popup.Dismiss()
}
func (popup *popupData) Dismiss() {
popup.Session().popupManager().dismissPopup(popup)
for _, listener := range popup.dismissListener {
listener(popup)
}
// TODO
}
func (popup *popupData) Show() {
@ -587,6 +620,27 @@ func (popup *popupData) onDismiss() {
}
}
func (popup *popupData) keyEvent(event KeyEvent) bool {
if !event.AltKey && !event.CtrlKey && !event.ShiftKey && !event.MetaKey {
switch strings.ToLower(event.Code) {
case "enter":
for _, button := range popup.buttons {
if button.Type == DefaultButton && button.OnClick != nil {
button.OnClick(popup)
return true
}
}
case "escape":
if popup.cancelable {
popup.Dismiss()
return true
}
}
}
return false
}
// NewPopup creates a new Popup
func NewPopup(view View, param Params) Popup {
if view == nil {

View File

@ -649,8 +649,15 @@ func (session *sessionData) handleEvent(command string, data DataObject) {
default:
if viewID, ok := data.PropertyValue("id"); ok {
if view := session.viewByHTMLID(viewID); view != nil {
view.handleCommand(view, command, data)
if viewID != "body" {
if view := session.viewByHTMLID(viewID); view != nil {
view.handleCommand(view, command, data)
}
}
if command == KeyDownEvent {
var event KeyEvent
event.init(data)
session.hotKey(event)
}
} else {
ErrorLog(`"id" property not found. Event: ` + command)
@ -658,6 +665,16 @@ func (session *sessionData) handleEvent(command string, data DataObject) {
}
}
func (session *sessionData) hotKey(event KeyEvent) {
popups := session.popupManager().popups
if count := len(popups); count > 0 {
if popups[count-1].keyEvent(event) {
return
}
}
// TODO
}
func (session *sessionData) SetTitle(title string) {
title, _ = session.GetString(title)
session.callFunc("setTitle", title)