rui_orig/popup.go

852 lines
20 KiB
Go
Raw Normal View History

2021-09-07 17:36:50 +03:00
package rui
2022-07-31 15:37:26 +03:00
import (
"strings"
)
2021-09-07 17:36:50 +03:00
// Constants for [Popup] specific properties and events
2021-09-07 17:36:50 +03:00
const (
// Title is the constant for "title" property tag.
//
// Used by `Popup`, `TabsLayout`.
//
// Usage in `Popup`:
// Define the title.
//
// Supported types: `string`.
//
// Usage in `TabsLayout`:
// Set the title of the tab. The property is set for the child view of `TabsLayout`.
//
// Supported types: `string`.
2021-09-07 17:36:50 +03:00
Title = "title"
// TitleStyle is the constant for "title-style" property tag.
//
// Used by `Popup`.
// Set popup title style. Default title style is "ruiPopupTitle".
//
// Supported types: `string`.
2024-11-13 12:56:39 +03:00
TitleStyle PropertyName = "title-style"
// CloseButton is the constant for "close-button" property tag.
//
// Used by `Popup`.
// Controls whether a close button can be added to the popup. Default value is `false`.
//
// Supported types: `bool`, `int`, `string`.
//
// Values:
// `true` or `1` or "true", "yes", "on", "1" - Close button will be added to a title bar of a window.
// `false` or `0` or "false", "no", "off", "0" - Popup without a close button.
2024-11-13 12:56:39 +03:00
CloseButton PropertyName = "close-button"
// OutsideClose is the constant for "outside-close" property tag.
//
// Used by `Popup`.
// Controls whether popup can be closed by clicking outside of the window. Default value is `false`.
//
// Supported types: `bool`, `int`, `string`.
//
// Values:
// `true` or `1` or "true", "yes", "on", "1" - Clicking outside the popup window will automatically call the `Dismiss()` method.
// `false` or `0` or "false", "no", "off", "0" - Clicking outside the popup window has no effect.
2024-11-13 12:56:39 +03:00
OutsideClose PropertyName = "outside-close"
// Buttons is the constant for "buttons" property tag.
//
// Used by `Popup`.
// Buttons that will be placed at the bottom of the popup.
//
// Supported types: `PopupButton`, `[]PopupButton`.
//
// Internal type is `[]PopupButton`, other types converted to it during assignment.
// See `PopupButton` description for more details.
2024-11-13 12:56:39 +03:00
Buttons PropertyName = "buttons"
// ButtonsAlign is the constant for "buttons-align" property tag.
//
// Used by `Popup`.
// Set the horizontal alignment of popup buttons.
//
// Supported types: `int`, `string`.
//
// Values:
// `0`(`LeftAlign`) or "left" - Left alignment.
// `1`(`RightAlign`) or "right" - Right alignment.
// `2`(`CenterAlign`) or "center" - Center alignment.
// `3`(`StretchAlign`) or "stretch" - Width alignment.
2024-11-13 12:56:39 +03:00
ButtonsAlign PropertyName = "buttons-align"
// DismissEvent is the constant for "dismiss-event" property tag.
//
// Used by `Popup`.
// Used to track the closing state of the `Popup`. It occurs after the `Popup` disappears from the screen.
//
// General listener format:
// `func(popup rui.Popup)`.
//
// where:
// popup - Interface of a popup which generated this event.
//
// Allowed listener formats:
// `func()`.
2024-11-13 12:56:39 +03:00
DismissEvent PropertyName = "dismiss-event"
2022-07-27 20:31:57 +03:00
// Arrow is the constant for "arrow" property tag.
//
// Used by `Popup`.
// Add an arrow to popup. Default value is "none".
//
// Supported types: `int`, `string`.
//
// Values:
// `0`(`NoneArrow`) or "none" - No arrow.
// `1`(`TopArrow`) or "top" - Arrow at the top side of the pop-up window.
// `2`(`RightArrow`) or "right" - Arrow on the right side of the pop-up window.
// `3`(`BottomArrow`) or "bottom" - Arrow at the bottom of the pop-up window.
// `4`(`LeftArrow`) or "left" - Arrow on the left side of the pop-up window.
2024-11-13 12:56:39 +03:00
Arrow PropertyName = "arrow"
2022-07-31 15:37:26 +03:00
// ArrowAlign is the constant for "arrow-align" property tag.
//
// Used by `Popup`.
// Set the horizontal alignment of the popup arrow. Default value is "center".
//
// Supported types: `int`, `string`.
//
// Values:
// `0`(`TopAlign`/`LeftAlign`) or "top" - Top/left alignment.
// `1`(`BottomAlign`/`RightAlign`) or "bottom" - Bottom/right alignment.
// `2`(`CenterAlign`) or "center" - Center alignment.
2024-11-13 12:56:39 +03:00
ArrowAlign PropertyName = "arrow-align"
2022-07-31 15:37:26 +03:00
// ArrowSize is the constant for "arrow-size" property tag.
//
// Used by `Popup`.
// Set the size(length) of the popup arrow. Default value is 16px defined by @ruiArrowSize constant.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
ArrowSize PropertyName = "arrow-size"
2022-07-31 15:37:26 +03:00
// ArrowWidth is the constant for "arrow-width" property tag.
//
// Used by `Popup`.
// Set the width of the popup arrow. Default value is 16px defined by @ruiArrowWidth constant.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
ArrowWidth PropertyName = "arrow-width"
2022-08-07 18:59:56 +03:00
// ArrowOffset is the constant for "arrow-offset" property tag.
//
// Used by `Popup`.
// Set the offset of the popup arrow.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
ArrowOffset PropertyName = "arrow-offset"
2022-07-31 15:37:26 +03:00
2022-08-07 18:59:56 +03:00
// NoneArrow is value of the popup "arrow" property: no arrow
NoneArrow = 0
// TopArrow is value of the popup "arrow" property:
// Arrow at the top side of the pop-up window
TopArrow = 1
// RightArrow is value of the popup "arrow" property:
// Arrow on the right side of the pop-up window
RightArrow = 2
// BottomArrow is value of the popup "arrow" property:
// Arrow at the bottom of the pop-up window
2022-07-31 15:37:26 +03:00
BottomArrow = 3
2022-08-07 18:59:56 +03:00
// LeftArrow is value of the popup "arrow" property:
// Arrow on the left side of the pop-up window
LeftArrow = 4
)
2023-05-15 15:27:37 +03:00
// Constants which are used as a values of [PopupButtonType] variables
const (
2023-05-15 15:27:37 +03:00
// NormalButton is the constant of the popup button type: the normal button
NormalButton PopupButtonType = 0
2023-05-15 15:27:37 +03:00
// DefaultButton is the constant of the popup button type: button that fires when the "Enter" key is pressed
DefaultButton PopupButtonType = 1
2023-05-15 15:27:37 +03:00
// CancelButton is the constant of the popup button type: button that fires when the "Escape" key is pressed
CancelButton PopupButtonType = 2
2021-09-07 17:36:50 +03:00
)
// PopupButtonType represent popup button type
2023-05-15 15:27:37 +03:00
type PopupButtonType int
// PopupButton describes a button that will be placed at the bottom of the window.
2021-09-07 17:36:50 +03:00
type PopupButton struct {
// Title of the button
Title string
// Type of the button
Type PopupButtonType
// OnClick is the handler function that gets called when the button is pressed
2021-09-07 17:36:50 +03:00
OnClick func(Popup)
}
// Popup represents a Popup view
2021-09-07 17:36:50 +03:00
type Popup interface {
// View returns a content view of the popup
2021-09-07 17:36:50 +03:00
View() View
// Session returns current client session
2021-09-07 17:36:50 +03:00
Session() Session
// Show displays a popup
2021-09-07 17:36:50 +03:00
Show()
// Dismiss closes a popup
2021-09-07 17:36:50 +03:00
Dismiss()
onDismiss()
2021-09-07 17:36:50 +03:00
html(buffer *strings.Builder)
viewByHTMLID(id string) View
2023-05-15 15:27:37 +03:00
keyEvent(event KeyEvent) bool
2021-09-07 17:36:50 +03:00
}
type popupData struct {
2021-11-17 12:32:37 +03:00
layerView View
view View
2023-05-15 15:27:37 +03:00
buttons []PopupButton
cancelable bool
2021-11-17 12:32:37 +03:00
dismissListener []func(Popup)
2021-09-07 17:36:50 +03:00
}
type popupManager struct {
popups []Popup
}
2022-08-07 18:59:56 +03:00
type popupArrow struct {
column, row int
location, align int
size, width, off SizeUnit
}
func (arrow *popupArrow) fixOff(popupView View) {
if arrow.align == CenterAlign && arrow.off.Type == Auto {
r := GetRadius(popupView)
2022-08-07 18:59:56 +03:00
switch arrow.location {
case TopArrow:
switch arrow.align {
case LeftAlign:
arrow.off = r.TopLeftX
case RightAlign:
arrow.off = r.TopRightX
}
case BottomArrow:
switch arrow.align {
case LeftAlign:
arrow.off = r.BottomLeftX
case RightAlign:
arrow.off = r.BottomRightX
}
case RightArrow:
switch arrow.align {
case TopAlign:
arrow.off = r.TopRightY
case BottomAlign:
arrow.off = r.BottomRightY
}
case LeftArrow:
switch arrow.align {
case TopAlign:
arrow.off = r.TopLeftY
case BottomAlign:
arrow.off = r.BottomLeftY
}
}
}
}
func (arrow *popupArrow) createView(popupView View) View {
session := popupView.Session()
defaultSize := func(constTag string, defValue SizeUnit) SizeUnit {
if value, ok := session.Constant(constTag); ok {
if size, ok := StringToSizeUnit(value); ok && size.Type != Auto && size.Value != 0 {
return size
}
}
return defValue
}
if arrow.size.Type == Auto || arrow.size.Value == 0 {
arrow.size = defaultSize("ruiArrowSize", Px(16))
}
if arrow.width.Type == Auto || arrow.width.Value == 0 {
arrow.width = defaultSize("ruiArrowWidth", Px(16))
}
params := Params{BackgroundColor: GetBackgroundColor(popupView)}
2022-08-08 17:00:49 +03:00
if shadow := GetViewShadows(popupView); shadow != nil {
2022-08-08 17:00:49 +03:00
params[Shadow] = shadow
}
if filter := GetBackdropFilter(popupView); filter != nil {
2022-08-08 17:00:49 +03:00
params[BackdropFilter] = filter
}
2022-08-07 18:59:56 +03:00
switch arrow.location {
case TopArrow:
params[Row] = 0
params[Column] = 1
2022-08-08 17:00:49 +03:00
params[Clip] = PolygonClip([]any{"0%", "100%", "50%", "0%", "100%", "100%"})
params[Width] = arrow.width
params[Height] = arrow.size
2022-08-07 18:59:56 +03:00
case RightArrow:
params[Row] = 1
params[Column] = 0
2022-08-08 17:00:49 +03:00
params[Clip] = PolygonClip([]any{"0%", "0%", "100%", "50%", "0%", "100%"})
params[Width] = arrow.size
params[Height] = arrow.width
2022-08-07 18:59:56 +03:00
case BottomArrow:
params[Row] = 0
params[Column] = 1
2022-08-08 17:00:49 +03:00
params[Clip] = PolygonClip([]any{"0%", "0%", "50%", "100%", "100%", "0%"})
params[Width] = arrow.width
params[Height] = arrow.size
2022-08-07 18:59:56 +03:00
case LeftArrow:
params[Row] = 1
params[Column] = 0
2022-08-08 17:00:49 +03:00
params[Clip] = PolygonClip([]any{"100%", "0%", "0%", "50%", "100%", "100%"})
params[Width] = arrow.size
params[Height] = arrow.width
2022-08-07 18:59:56 +03:00
}
arrowView := NewView(session, params)
params = Params{
Row: arrow.row,
Column: arrow.column,
Content: arrowView,
}
arrow.fixOff(popupView)
switch arrow.location {
case TopArrow, BottomArrow:
cellWidth := make([]SizeUnit, 3)
switch arrow.align {
case LeftAlign:
cellWidth[0] = arrow.off
cellWidth[2] = Fr(1)
case RightAlign:
cellWidth[0] = Fr(1)
cellWidth[2] = arrow.off
default:
cellWidth[0] = Fr(1)
cellWidth[2] = Fr(1)
if arrow.off.Type != Auto && arrow.off.Value != 0 {
arrowView.Set(MarginLeft, arrow.off)
}
}
params[CellWidth] = cellWidth
case RightArrow, LeftArrow:
cellHeight := make([]SizeUnit, 3)
switch arrow.align {
case TopAlign:
cellHeight[0] = arrow.off
cellHeight[2] = Fr(1)
case BottomAlign:
cellHeight[0] = Fr(1)
cellHeight[2] = arrow.off
default:
cellHeight[0] = Fr(1)
cellHeight[2] = Fr(1)
if arrow.off.Type != Auto && arrow.off.Value != 0 {
arrowView.Set(MarginTop, arrow.off)
}
}
params[CellHeight] = cellHeight
}
return NewGridLayout(session, params)
}
2022-07-31 15:37:26 +03:00
func (popup *popupData) init(view View, popupParams Params) {
2021-09-07 17:36:50 +03:00
popup.view = view
2023-05-15 15:27:37 +03:00
popup.cancelable = false
2021-09-07 17:36:50 +03:00
session := view.Session()
2022-08-07 18:59:56 +03:00
columnCount := 3
rowCount := 3
popupRow := 1
popupColumn := 1
arrow := popupArrow{
row: 1,
column: 1,
align: CenterAlign,
}
switch arrow.location, _ = enumProperty(popupParams, Arrow, session, NoneArrow); arrow.location {
case TopArrow:
rowCount = 4
popupRow = 2
case BottomArrow:
rowCount = 4
arrow.row = 2
case LeftArrow:
columnCount = 4
popupColumn = 2
case RightArrow:
columnCount = 4
arrow.column = 2
default:
}
cellWidth := make([]SizeUnit, columnCount)
switch hAlign, _ := enumProperty(popupParams, HorizontalAlign, session, CenterAlign); hAlign {
case LeftAlign:
cellWidth[columnCount-1] = Fr(1)
case RightAlign:
cellWidth[0] = Fr(1)
default:
cellWidth[0] = Fr(1)
cellWidth[columnCount-1] = Fr(1)
}
cellHeight := make([]SizeUnit, rowCount)
switch vAlign, _ := enumProperty(popupParams, VerticalAlign, session, CenterAlign); vAlign {
case LeftAlign:
cellHeight[rowCount-1] = Fr(1)
case RightAlign:
cellHeight[0] = Fr(1)
default:
cellHeight[0] = Fr(1)
cellHeight[rowCount-1] = Fr(1)
}
layerParams := Params{
Style: "ruiPopupLayer",
MaxWidth: Percent(100),
MaxHeight: Percent(100),
CellWidth: cellWidth,
CellHeight: cellHeight,
}
2022-07-31 15:37:26 +03:00
params := Params{
Style: "ruiPopup",
2022-08-07 18:59:56 +03:00
Row: popupRow,
Column: popupColumn,
2022-07-31 15:37:26 +03:00
MaxWidth: Percent(100),
MaxHeight: Percent(100),
CellVerticalAlign: StretchAlign,
CellHorizontalAlign: StretchAlign,
ClickEvent: func(View) {},
2022-08-07 18:59:56 +03:00
Shadow: NewShadowWithParams(Params{
SpreadRadius: Px(4),
Blur: Px(16),
ColorTag: "@ruiPopupShadow",
}),
}
2022-08-07 18:59:56 +03:00
var closeButton View = nil
2022-07-31 15:37:26 +03:00
outsideClose := false
buttons := []PopupButton{}
titleStyle := "ruiPopupTitle"
var title View = nil
2021-11-17 12:32:37 +03:00
2022-07-31 15:37:26 +03:00
for tag, value := range popupParams {
if value != nil {
switch tag {
2022-08-07 18:59:56 +03:00
case VerticalAlign, HorizontalAlign, Arrow, Row, Column:
// Do nothing
case Margin:
layerParams[Padding] = value
case MarginLeft:
layerParams[PaddingLeft] = value
case MarginRight:
layerParams[PaddingRight] = value
case MarginTop:
layerParams[PaddingTop] = value
case MarginBottom:
layerParams[PaddingBottom] = value
2022-07-31 15:37:26 +03:00
case CloseButton:
2022-08-07 18:59:56 +03:00
closeButton = NewGridLayout(session, Params{
Column: 1,
Height: "@ruiPopupTitleHeight",
Width: "@ruiPopupTitleHeight",
CellHorizontalAlign: CenterAlign,
CellVerticalAlign: CenterAlign,
TextSize: Px(20),
Content: "✕",
NotTranslate: true,
2023-05-15 15:27:37 +03:00
ClickEvent: popup.cancel,
2022-08-07 18:59:56 +03:00
})
2023-05-15 15:27:37 +03:00
popup.cancelable = true
2021-11-17 12:32:37 +03:00
2022-07-31 15:37:26 +03:00
case OutsideClose:
outsideClose, _ = boolProperty(popupParams, OutsideClose, session)
2023-05-15 15:27:37 +03:00
if outsideClose {
popup.cancelable = true
}
2022-07-31 15:37:26 +03:00
case Buttons:
switch value := value.(type) {
case PopupButton:
buttons = []PopupButton{value}
2021-11-17 12:32:37 +03:00
2022-07-31 15:37:26 +03:00
case []PopupButton:
buttons = value
2021-11-17 12:32:37 +03:00
}
2022-07-31 15:37:26 +03:00
case Title:
switch value := value.(type) {
case string:
title = NewTextView(view.Session(), Params{Text: value})
case View:
title = value
default:
notCompatibleType(Title, value)
2021-11-17 12:32:37 +03:00
}
2022-07-31 15:37:26 +03:00
case TitleStyle:
switch value := value.(type) {
case string:
titleStyle = value
2021-09-07 17:36:50 +03:00
2022-07-31 15:37:26 +03:00
default:
notCompatibleType(TitleStyle, value)
}
2021-09-07 17:36:50 +03:00
2022-07-31 15:37:26 +03:00
case DismissEvent:
if listeners, ok := valueToNoArgEventListeners[Popup](value); ok {
2022-07-31 15:37:26 +03:00
if listeners != nil {
popup.dismissListener = listeners
}
} else {
notCompatibleType(tag, value)
}
2021-09-07 17:36:50 +03:00
2022-07-31 15:37:26 +03:00
case ArrowAlign:
switch text := value.(type) {
case string:
switch text {
case "top":
value = "left"
2021-09-07 17:36:50 +03:00
2022-07-31 15:37:26 +03:00
case "bottom":
value = "right"
}
}
2022-08-07 18:59:56 +03:00
arrow.align, _ = enumProperty(popupParams, ArrowAlign, session, CenterAlign)
2021-09-07 17:36:50 +03:00
2022-07-31 15:37:26 +03:00
case ArrowSize:
2022-08-07 18:59:56 +03:00
arrow.size, _ = sizeProperty(popupParams, ArrowSize, session)
2021-09-07 17:36:50 +03:00
2022-07-31 15:37:26 +03:00
case ArrowOffset:
2022-08-07 18:59:56 +03:00
arrow.off, _ = sizeProperty(popupParams, ArrowOffset, session)
2021-09-07 17:36:50 +03:00
default:
2022-07-31 15:37:26 +03:00
params[tag] = value
2021-09-07 17:36:50 +03:00
}
}
}
2022-07-31 15:37:26 +03:00
popupView := NewGridLayout(view.Session(), params)
2022-08-07 18:59:56 +03:00
var popupCellHeight []SizeUnit
2021-09-07 17:36:50 +03:00
viewRow := 0
2022-08-07 18:59:56 +03:00
if title != nil || closeButton != nil {
titleContent := []View{}
if title != nil {
titleContent = append(titleContent, title)
}
if closeButton != nil {
titleContent = append(titleContent, closeButton)
}
popupView.Append(NewGridLayout(session, Params{
2021-09-07 17:36:50 +03:00
Row: 0,
Style: titleStyle,
2022-08-07 18:59:56 +03:00
CellWidth: []any{Fr(1), AutoSize()},
2021-09-07 17:36:50 +03:00
CellVerticalAlign: CenterAlign,
PaddingLeft: Px(12),
2022-08-07 18:59:56 +03:00
Content: titleContent,
}))
2021-09-07 17:36:50 +03:00
2022-08-07 18:59:56 +03:00
viewRow = 1
popupCellHeight = []SizeUnit{AutoSize(), Fr(1)}
2021-09-07 17:36:50 +03:00
} else {
2022-08-07 18:59:56 +03:00
popupCellHeight = []SizeUnit{Fr(1)}
2021-09-07 17:36:50 +03:00
}
view.Set(Row, viewRow)
popupView.Append(view)
2023-05-15 15:27:37 +03:00
popup.buttons = buttons
2021-09-07 17:36:50 +03:00
if buttonCount := len(buttons); buttonCount > 0 {
buttonsAlign, _ := enumProperty(params, ButtonsAlign, session, RightAlign)
2022-08-07 18:59:56 +03:00
popupCellHeight = append(popupCellHeight, AutoSize())
2021-11-17 12:32:37 +03:00
gap, _ := sizeConstant(session, "ruiPopupButtonGap")
2021-09-07 17:36:50 +03:00
cellWidth := []SizeUnit{}
for i := 0; i < buttonCount; i++ {
cellWidth = append(cellWidth, Fr(1))
}
buttonsPanel := NewGridLayout(session, Params{
CellWidth: cellWidth,
})
if gap.Type != Auto && gap.Value > 0 {
buttonsPanel.Set(Gap, gap)
buttonsPanel.Set(Margin, gap)
}
for i, button := range buttons {
2023-05-15 15:27:37 +03:00
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)
2021-09-07 17:36:50 +03:00
}
popupView.Append(NewGridLayout(session, Params{
Row: viewRow + 1,
CellHorizontalAlign: buttonsAlign,
Content: buttonsPanel,
}))
}
2022-08-07 18:59:56 +03:00
popupView.Set(CellHeight, popupCellHeight)
if arrow.location != NoneArrow {
layerParams[Content] = []View{popupView, arrow.createView(popupView)}
} else {
layerParams[Content] = []View{popupView}
}
popup.layerView = NewGridLayout(session, layerParams)
2021-09-07 17:36:50 +03:00
if outsideClose {
2023-05-15 15:27:37 +03:00
popup.layerView.Set(ClickEvent, popup.cancel)
2021-09-07 17:36:50 +03:00
}
}
func (popup popupData) View() View {
return popup.view
}
func (popup *popupData) Session() Session {
return popup.view.Session()
}
2023-05-15 15:27:37 +03:00
func (popup *popupData) cancel() {
for _, button := range popup.buttons {
if button.Type == CancelButton && button.OnClick != nil {
button.OnClick(popup)
return
}
}
popup.Dismiss()
}
2021-09-07 17:36:50 +03:00
func (popup *popupData) Dismiss() {
popup.Session().popupManager().dismissPopup(popup)
2021-11-17 12:32:37 +03:00
for _, listener := range popup.dismissListener {
listener(popup)
}
2021-09-07 17:36:50 +03:00
}
func (popup *popupData) Show() {
popup.Session().popupManager().showPopup(popup)
}
func (popup *popupData) html(buffer *strings.Builder) {
2024-11-21 09:25:46 +03:00
viewHTML(popup.layerView, buffer, "")
2021-09-07 17:36:50 +03:00
}
func (popup *popupData) viewByHTMLID(id string) View {
return viewByHTMLID(id, popup.layerView)
}
func (popup *popupData) onDismiss() {
for _, listener := range popup.dismissListener {
listener(popup)
}
}
2023-05-15 15:27:37 +03:00
func (popup *popupData) keyEvent(event KeyEvent) bool {
if !event.AltKey && !event.CtrlKey && !event.ShiftKey && !event.MetaKey {
switch event.Code {
case EnterKey:
2023-05-15 15:27:37 +03:00
for _, button := range popup.buttons {
if button.Type == DefaultButton && button.OnClick != nil {
button.OnClick(popup)
return true
}
}
case EscapeKey:
2023-05-15 15:27:37 +03:00
if popup.cancelable {
popup.Dismiss()
return true
}
}
}
return false
}
2021-09-07 17:36:50 +03:00
// NewPopup creates a new Popup
func NewPopup(view View, param Params) Popup {
if view == nil {
return nil
}
popup := new(popupData)
popup.init(view, param)
return popup
}
// ShowPopup creates a new Popup and shows it
func ShowPopup(view View, param Params) Popup {
popup := NewPopup(view, param)
if popup != nil {
popup.Show()
}
return popup
}
2021-09-07 17:36:50 +03:00
func (manager *popupManager) updatePopupLayerInnerHTML(session Session) {
if manager.popups == nil {
manager.popups = []Popup{}
2022-10-30 17:22:33 +03:00
session.updateInnerHTML("ruiPopupLayer", "")
2021-09-07 17:36:50 +03:00
return
}
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
2022-10-29 20:16:40 +03:00
for _, popup := range manager.popups {
popup.html(buffer)
2021-09-07 17:36:50 +03:00
}
2022-10-30 17:22:33 +03:00
session.updateInnerHTML("ruiPopupLayer", buffer.String())
2021-09-07 17:36:50 +03:00
}
func (manager *popupManager) showPopup(popup Popup) {
if popup == nil {
return
}
session := popup.Session()
if len(manager.popups) == 0 {
2021-09-07 17:36:50 +03:00
manager.popups = []Popup{popup}
} else {
manager.popups = append(manager.popups, popup)
}
2022-11-02 20:10:19 +03:00
session.callFunc("blurCurrent")
2021-09-07 17:36:50 +03:00
manager.updatePopupLayerInnerHTML(session)
2023-04-25 17:20:47 +03:00
session.updateCSSProperty("ruiTooltipLayer", "visibility", "hidden")
2023-04-25 17:33:08 +03:00
session.updateCSSProperty("ruiTooltipLayer", "opacity", "0")
2022-10-30 17:22:33 +03:00
session.updateCSSProperty("ruiPopupLayer", "visibility", "visible")
session.updateCSSProperty("ruiRoot", "pointer-events", "none")
2021-09-07 17:36:50 +03:00
}
func (manager *popupManager) dismissPopup(popup Popup) {
if manager.popups == nil {
manager.popups = []Popup{}
return
}
count := len(manager.popups)
if count <= 0 || popup == nil {
return
}
session := popup.Session()
if manager.popups[count-1] == popup {
if count == 1 {
manager.popups = []Popup{}
2022-10-30 17:22:33 +03:00
session.updateCSSProperty("ruiRoot", "pointer-events", "auto")
session.updateCSSProperty("ruiPopupLayer", "visibility", "hidden")
session.updateInnerHTML("ruiPopupLayer", "")
2021-09-07 17:36:50 +03:00
} else {
manager.popups = manager.popups[:count-1]
manager.updatePopupLayerInnerHTML(session)
}
popup.onDismiss()
2021-09-07 17:36:50 +03:00
return
}
for n, p := range manager.popups {
if p == popup {
if n == 0 {
manager.popups = manager.popups[1:]
} else {
manager.popups = append(manager.popups[:n], manager.popups[n+1:]...)
}
manager.updatePopupLayerInnerHTML(session)
popup.onDismiss()
2021-09-07 17:36:50 +03:00
return
}
}
}