diff --git a/sandbox/pages/StatusPopupMenuPage.qml b/sandbox/pages/StatusPopupMenuPage.qml index 1434dd4e..e4b978f5 100644 --- a/sandbox/pages/StatusPopupMenuPage.qml +++ b/sandbox/pages/StatusPopupMenuPage.qml @@ -22,8 +22,8 @@ GridLayout { onClicked: complexMenu.popup() } - StatusButton { + id: customPopupButton text: "Menu with custom images and icons" onClicked: customMenu.popup() } @@ -51,7 +51,7 @@ GridLayout { StatusPopupMenu { id: complexMenu - subMenuItemIcons: [{ icon: 'info' }] +// subMenuItemIcons: [{ icon: 'info' }] StatusMenuItem { text: "One" @@ -65,13 +65,10 @@ GridLayout { assetSettings.name: "info" } - StatusMenuItem { - text: "Three" + StatusPopupMenu { + title: "Two" assetSettings.name: "info" - } - StatusPopupMenu { - title: "Four" StatusMenuItem { text: "One" assetSettings.name: "info" @@ -81,22 +78,22 @@ GridLayout { assetSettings.name: "info" } } + + StatusMenuItem { + text: "Disabled" + assetSettings.name: "info" + enabled: false + } + + StatusMenuItem { + text: "Danger" + type: StatusMenuItem.Type.Danger + } } StatusPopupMenu { id: customMenu - subMenuItemIcons: [ - { icon: "chat" }, - { - source: "qrc:/demoapp/data/profile-image-1.jpeg" - }, - { - isLetterIdenticon: true, - color: "red" - } - ] - StatusMenuItem { text: "Anywhere" } @@ -104,14 +101,15 @@ GridLayout { StatusMenuSeparator {} StatusPopupMenu { - title: "Chat" + title: "Chat" + assetSettings.name: "chat" StatusMenuItem { text: "vitalik.eth" assetSettings.isImage: true + assetSettings.imgIsIdenticon: true assetSettings.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC" - assetSettings.imgIsIdenticon: true } StatusMenuItem { @@ -123,6 +121,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I StatusPopupMenu { title: "Cryptokitties" + assetSettings.isImage: true + assetSettings.name: "qrc:/demoapp/data/profile-image-1.jpeg" StatusMenuItem { text: "welcome" @@ -146,6 +146,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I StatusPopupMenu { title: "Another community" + assetSettings.isLetterIdenticon: true + assetSettings.bgColor: "red" StatusMenuItem { text: "welcome" diff --git a/sandbox/pages/StatusSelectPage.qml b/sandbox/pages/StatusSelectPage.qml index 9304fa6c..8c7a9e6e 100644 --- a/sandbox/pages/StatusSelectPage.qml +++ b/sandbox/pages/StatusSelectPage.qml @@ -41,7 +41,6 @@ Column { model: commmonModel selectMenu.delegate: StatusMenuItemDelegate { - statusPopupMenu: select action: StatusMenuItem { assetSettings.name: "filled-account" text: name diff --git a/src/StatusQ/Popups/StatusMenuItem.qml b/src/StatusQ/Popups/StatusMenuItem.qml index 241af7af..025f8ae2 100644 --- a/src/StatusQ/Popups/StatusMenuItem.qml +++ b/src/StatusQ/Popups/StatusMenuItem.qml @@ -9,17 +9,20 @@ Action { Normal, Danger } - icon.color: "transparent" + property int type: StatusMenuItem.Type.Normal - property real iconRotation: 0 + property StatusAssetSettings assetSettings: StatusAssetSettings { - width: 16 - height: 16 - color: "transparent" + width: 18 + height: 18 + rotation: 0 isLetterIdenticon: false imgIsIdenticon: false + color: "transparent" name: statusMenuItem.icon.name } property StatusFontSettings fontSettings: StatusFontSettings {} + + icon.color: "transparent" } diff --git a/src/StatusQ/Popups/StatusMenuItemDelegate.qml b/src/StatusQ/Popups/StatusMenuItemDelegate.qml index 519cdffc..2e05e646 100644 --- a/src/StatusQ/Popups/StatusMenuItemDelegate.qml +++ b/src/StatusQ/Popups/StatusMenuItemDelegate.qml @@ -7,187 +7,164 @@ import StatusQ.Components 0.1 import StatusQ.Popups 0.1 MenuItem { - id: statusPopupMenuItem + id: root implicitWidth: parent ? parent.width : 0 - implicitHeight: action.enabled ? 34 : 0 - objectName: action.objectName - - property int subMenuIndex - property var statusPopupMenu: null - - Component.onCompleted: { - if (!!subMenu) { - subMenuIndex = statusPopupMenu.menuItemCount - statusPopupMenu.menuItemCount += 1 + implicitHeight: menu.hideDisabledItems && !enabled ? 0 : 38 + objectName: action ? action.objectName : "StatusMenuItemDelegate" + + spacing: 4 + horizontalPadding: 8 + + readonly property string logObjectName: "StatusMenuItemDelegate [%1, %2]".arg(this).arg(text) + + QtObject { + id: d + + readonly property bool isSubMenu: !!root.subMenu + readonly property bool isStatusSubMenu: isSubMenu && (root.subMenu instanceof StatusPopupMenu) + readonly property bool subMenuOpened: isSubMenu && root.subMenu.opened + readonly property bool hasAction: !!root.action + readonly property bool isStatusAction: d.hasAction && (root.action instanceof StatusMenuItem) + readonly property bool isDangerIcon: d.isStatusAction && root.action.type === StatusMenuItem.Type.Danger + + readonly property StatusAssetSettings assetSettings: d.isStatusSubMenu + ? root.subMenu.assetSettings + : d.isStatusAction + ? root.action.assetSettings + : d.defaultAsset + + readonly property StatusFontSettings fontSettings: d.isStatusSubMenu + ? root.subMenu.fontSettings + : d.isStatusAction ? root.action.fontSettings : d.defaultFontSettings + + readonly property StatusAssetSettings defaultAsset: StatusAssetSettings { + width: 18 + height: 18 + rotation: 0 } - } - action: StatusMenuItem { - onTriggered: { statusPopupMenu.menuItemClicked(statusPopupMenuItem.subMenuIndex); } + readonly property StatusFontSettings defaultFontSettings: StatusFontSettings { + pixelSize: 13 + bold: false + italic: false + } } Component { - id: indicatorComponent - Item { - implicitWidth: 24 - implicitHeight: 24 - StatusIcon { - anchors.centerIn: parent - width: { - let width = statusPopupMenuItem.action && statusPopupMenuItem.action.assetSettings.width - return !!width ? width : 18 - } - rotation: !!statusPopupMenuItem.action.iconRotation ? statusPopupMenuItem.action.iconRotation : 0 - icon: { - if (statusPopupMenuItem.subMenu && !!statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] && - statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].icon.toString() !== "") { - return statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].icon; - } else if (!!statusPopupMenuItem.action && statusPopupMenuItem.action.assetSettings.name !== "") { - return statusPopupMenuItem.action.assetSettings.name; - } else if (!!statusPopupMenuItem.action.assetSettings && statusPopupMenuItem.action.assetSettings.name !== "") { - return statusPopupMenuItem.action.assetSettings.name; - } else { - return ""; - } - } - color: { - let c = !!statusPopupMenuItem.action.assetSettings && statusPopupMenuItem.action.assetSettings.color - - if (!Qt.colorEqual(c, "transparent")) { - return c - } - switch (statusPopupMenuItem.action.type) { - case StatusMenuItem.Type.Danger: - return Theme.palette.dangerColor1 - default: - return Theme.palette.primaryColor1 - } - } + id: indicatorIcon + + StatusIcon { + width: d.assetSettings.width + height: d.assetSettings.height + rotation: d.assetSettings.rotation + icon: d.assetSettings.name + color: { + const c = d.assetSettings.color; + if (!Qt.colorEqual(c, "transparent")) + return c; + if (!root.enabled) + return Theme.palette.baseColor1; + if (d.isDangerIcon) + return Theme.palette.dangerColor1; + return Theme.palette.primaryColor1; } } } Component { - id: statusLetterIdenticonCmp - Item { - implicitWidth: 24 - implicitHeight: 24 - - StatusLetterIdenticon { - anchors.centerIn: parent - width: 16 - height: 16 - color: { - let subMenuItemIcon = statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] - return subMenuItemIcon && subMenuItemIcon.color ? subMenuItemIcon.color : statusPopupMenuItem.action.assetSettings.bgColor - } - name: statusPopupMenuItem.text - letterSize: 11 - } + id: indicatorLetterIdenticon + + StatusLetterIdenticon { + width: d.assetSettings.width + height: d.assetSettings.height + color: d.assetSettings.bgColor + name: root.text + letterSize: 11 } } Component { - id: statusRoundImageCmp - - Item { - implicitWidth: 24 - implicitHeight: 24 - StatusRoundedImage { - anchors.centerIn: parent - width: statusPopupMenuItem.action.assetSettings.width - height: statusPopupMenuItem.action.assetSettings.height - image.source: statusPopupMenuItem.subMenu ? - statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].source : - statusPopupMenuItem.action.assetSettings.name - border.width: (statusPopupMenuItem.subMenu && statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].isIdenticon) || - statusPopupMenuItem.action.assetSettings.imgIsIdenticon ? 1 : 0 - border.color: Theme.palette.directColor7 - } + id: indicatorImage + + StatusRoundedImage { + width: d.assetSettings.width + height: d.assetSettings.height + image.source: d.assetSettings.name + border.width: d.isSubMenu && d.assetSettings.imgIsIdenticon ? 1 : 0 + border.color: Theme.palette.directColor7 } } - indicator: Loader { - sourceComponent: { - let subMenuItemIcon = statusPopupMenu.subMenuItemIcons && statusPopupMenu.subMenuItemIcons[parent.subMenuIndex] - - if ((parent.subMenu && subMenuItemIcon && subMenuItemIcon.source) || - statusPopupMenuItem.action.assetSettings && !!statusPopupMenuItem.action.assetSettings.name.toString() - && statusPopupMenuItem.action.assetSettings.isImage) { - return statusRoundImageCmp + indicator: Item { + x: root.mirrored ? root.width - width - root.rightPadding : root.leftPadding + y: root.topPadding + (root.availableHeight - height) / 2 + + implicitWidth: 24 + implicitHeight: 24 + visible: d.assetSettings.isLetterIdenticon + || d.assetSettings.isImage + || !!d.assetSettings.name + + Loader { + anchors.centerIn: parent + active: parent.visible + sourceComponent: { + if (d.assetSettings.isImage) + return indicatorImage; + if (d.assetSettings.isLetterIdenticon) + return indicatorLetterIdenticon; + return indicatorIcon; } - return (parent.subMenu && subMenuItemIcon && subMenuItemIcon.isLetterIdenticon) || - (statusPopupMenuItem.action.assetSettings && statusPopupMenuItem.action.assetSettings.isLetterIdenticon) ? - statusLetterIdenticonCmp : indicatorComponent } - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: 8 - active: { - if (enabled) { - let hasIconSettings = !!statusPopupMenuItem.action.assetSettings.name || - (statusPopupMenuItem.action.assetSettings && - (!!statusPopupMenuItem.action.assetSettings.name || !!statusPopupMenuItem.action.assetSettings.isLetterIdenticon)) - - let hasImageSettings = statusPopupMenuItem.action.assetSettings && !!statusPopupMenuItem.action.assetSettings.name.toString() - - return enabled && (parent.subMenu && !!statusPopupMenu.subMenuItemIcons[parent.subMenuIndex]) || hasIconSettings || hasImageSettings - } - return false - } } contentItem: StatusBaseText { - anchors.left: statusPopupMenuItem.indicator.right - anchors.right: arrowIcon.visible ? arrowIcon.left : arrowIcon.right - anchors.rightMargin: 8 - anchors.leftMargin: 4 + readonly property real arrowPadding: root.subMenu && root.arrow ? root.arrow.width + root.spacing : 0 + readonly property real indicatorPadding: root.indicator.visible ? root.indicator.width + root.spacing : 0 + + leftPadding: !root.mirrored ? indicatorPadding : arrowPadding + rightPadding: root.mirrored ? indicatorPadding : arrowPadding horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter - text: statusPopupMenuItem.text - color: { - switch (statusPopupMenuItem.action.type) { - case StatusMenuItem.Type.Danger: - return Theme.palette.dangerColor1 - default: - return Theme.palette.directColor1 - } - } - font.pixelSize: !!statusPopupMenuItem.action.fontSettings ? statusPopupMenuItem.action.fontSettings.pixelSize : 13 - font.bold: !!statusPopupMenuItem.action.fontSettings ? statusPopupMenuItem.action.fontSettings.bold : false - font.italic: !!statusPopupMenuItem.action.fontSettings ? statusPopupMenuItem.action.fontSettings.italic : false + text: root.text + color: !root.enabled ? Theme.palette.baseColor1 + : d.isDangerIcon ? Theme.palette.dangerColor1 : Theme.palette.directColor1 + + font.pixelSize: d.fontSettings.pixelSize + font.bold: d.fontSettings.bold + font.italic: d.fontSettings.italic elide: Text.ElideRight - visible: statusPopupMenuItem.action.enabled + visible: true } arrow: StatusIcon { id: arrowIcon - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 8 + x: root.mirrored ? root.leftPadding : root.width - width - root.rightPadding + y: root.topPadding + (root.availableHeight - height) / 2 + height: 16 - visible: statusPopupMenuItem.subMenu + visible: d.isSubMenu icon: "next" color: Theme.palette.directColor1 } background: Rectangle { color: { - if (statusPopupMenuItem.hovered) { - return statusPopupMenuItem.action.type === StatusMenuItem.Type.Danger ? Theme.palette.dangerColor3 : Theme.palette.statusPopupMenu.hoverBackgroundColor - } - return "transparent" + if (!root.hovered && !d.subMenuOpened) + return "transparent" + if (root.action.type === StatusMenuItem.Type.Danger) + return Theme.palette.dangerColor3; + return Theme.palette.statusPopupMenu.hoverBackgroundColor; } } MouseArea { - id: sensor anchors.fill: parent cursorShape: Qt.PointingHandCursor - hoverEnabled: statusPopupMenuItem.action.enabled + hoverEnabled: root.enabled onPressed: mouse.accepted = false } } diff --git a/src/StatusQ/Popups/StatusPopupMenu.qml b/src/StatusQ/Popups/StatusPopupMenu.qml index 7c3682a7..4db571d0 100644 --- a/src/StatusQ/Popups/StatusPopupMenu.qml +++ b/src/StatusQ/Popups/StatusPopupMenu.qml @@ -10,21 +10,32 @@ import StatusQ.Popups 0.1 Menu { id: root + closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape topPadding: 8 bottomPadding: 8 bottomMargin: 16 - property int menuItemCount: 0 - property var subMenuItemIcons: [] + property StatusAssetSettings assetSettings: StatusAssetSettings { + width: 18 + height: 18 + rotation: 0 + isLetterIdenticon: false + isImage: false + color: "transparent" + } + + property StatusFontSettings fontSettings: StatusFontSettings {} + + property bool hideDisabledItems: false property var openHandler property var closeHandler - dim: false - signal menuItemClicked(int menuIndex) + dim: false + onOpened: { if (typeof openHandler === "function") { openHandler() @@ -37,9 +48,7 @@ Menu { } } - delegate: StatusMenuItemDelegate { - statusPopupMenu: root - } + delegate: StatusMenuItemDelegate { } contentItem: StatusListView { currentIndex: root.currentIndex diff --git a/src/StatusQ/Popups/StatusSearchLocationMenu.qml b/src/StatusQ/Popups/StatusSearchLocationMenu.qml index d7fa7941..4afb7c86 100644 --- a/src/StatusQ/Popups/StatusSearchLocationMenu.qml +++ b/src/StatusQ/Popups/StatusSearchLocationMenu.qml @@ -28,6 +28,8 @@ StatusPopupMenu { MenuItem { implicitHeight: 0.00001 } Instantiator { model: root.locationModel + + // NOTE: Use DelegateChooser here delegate: Loader { sourceComponent: (!!model.subItems && model.subItems.count > 0) ? subMenus : subMenuItemComponent onLoaded: { @@ -38,13 +40,13 @@ StatusPopupMenu { item.parentIconName = model.iconName; item.parentImageSource = model.imageSource; item.parentIdenticonColor = !!model.iconColor ? model.iconColor : Theme.palette.primaryColor1; - root.subMenuItemIcons.push({ - source: model.imageSource, - icon: model.iconName, - isIdenticon: model.isIdenticon, - color: model.iconColor, - isLetterIdenticon: !model.imageSource && !model.iconName - }); + + item.assetSettings.source = model.imageSource; + item.assetSettings.isIdenticon = model.isIdenticon; + item.assetSettings.name = model.iconName; + item.assetSettings.color = model.iconColor; + item.assetSettings.isLetterIdenticon = !model.imageSource && !model.iconName; + root.insertMenu(index + numDefaultItems, item); } else { item.value = model.value