RibbonUI/lib_source/qml/Qt6/RibbonMessageBar.qml

334 lines
12 KiB
QML

import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import RibbonUI
Rectangle {
id: control
implicitWidth: parent ? parent.width : 100
implicitHeight: contentHeight
enum Type {
Info,
Success,
SevereWarning,
Blocked,
Error,
Warning
}
property real contentHeight: layout.height + layout.anchors.topMargin * 2
property alias text: barText.text
property int type: RibbonMessageBar.Info
property bool rounded: false
property string warningColor: RibbonTheme.isDarkMode ? "#41361D" : "#FDF4D2"
property string successColor: RibbonTheme.isDarkMode ? "#3A3D1F" : "#E3F5DF"
property string severeWarningColor: RibbonTheme.isDarkMode ? "#4A2C15" : "#F8DACE"
property string blockedColor: RibbonTheme.isDarkMode ? "#402827" : "#F9E8E9"
property string errorColor: RibbonTheme.isDarkMode ? "#402827" : "#F9E8E9"
property string infoColor: RibbonTheme.isDarkMode ? "#323130" : "#F3F2F1"
property string externalURL: ""
property string externalURLLabel: qsTr("Link")
property string dismissLabel: qsTr("Close")
property string overflowLabel: qsTr("See More")
property string actionALabel: qsTr("ActionA")
property string actionBLabel: qsTr("ActionB")
property bool isMultiline: type === RibbonMessageBar.SevereWarning || type === RibbonMessageBar.Warning
property bool showActionA: false
property bool showActionB: false
property bool truncated: !(isMultiline || showActionA || showActionB) && type === RibbonMessageBar.Blocked
property var actionA: ()=>console.log(qsTr("ActionA Clicked"))
property var actionB: ()=>console.log(qsTr("ActionB Clicked"))
property var dismissAction
radius: rounded ? 3 : 0
clip: true
signal dismissClicked()
signal actionAClicked()
signal actionBClicked()
Behavior on implicitHeight {
NumberAnimation {
duration: 200
easing.type: Easing.OutSine
}
}
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.OutSine
}
}
Behavior on opacity{
NumberAnimation {
duration: 200
easing.type: Easing.OutSine
}
}
onOpacityChanged: {
if(opacity > 0)
visible = true
else
visible = false
}
onVisibleChanged: {
if(visible && opacity === 0)
opacity = 1
}
Rectangle{
anchors{
top: parent.top
horizontalCenter: parent.horizontalCenter
}
width: parent.width
height: 1
color: Qt.rgba(0,0,0,0.1)
visible: RibbonTheme.modernStyle
}
Rectangle{
anchors{
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
}
width: parent.width
height: 1
color: Qt.rgba(0,0,0,0.1)
}
gradient: Gradient {
GradientStop { position: 0.0; color: calculateClassicColor(control.color)[0]}
GradientStop { position: 1.0; color: calculateClassicColor(control.color)[1]}
}
Column{
id: layout
anchors{
top: parent.top
left: parent.left
leftMargin: 12
right: parent.right
rightMargin: anchors.leftMargin
topMargin: 8
bottomMargin: anchors.topMargin
}
spacing: 5
RowLayout{
id: row_1
RibbonIcon{
id: icon
iconSize: height
Layout.alignment: Qt.AlignTop
Layout.preferredHeight: Math.min(barText.contentHeight, 16)
}
Text{
id: barText
elide: truncated.checked ? Text.ElideNone : Text.ElideRight
renderType: RibbonTheme.nativeText ? Text.NativeRendering : Text.QtRendering
wrapMode: truncated.checked ? Text.Wrap : Text.NoWrap
color: RibbonTheme.isDarkMode ? "white" : "black"
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: {
var w = 0
if(actiona.visible && !control.isMultiline)
w += actiona.width + row_1.spacing
if(actionb.visible && !control.isMultiline)
w += actionb.width + row_1.spacing
if(link.visible)
w += link.width + row_1.spacing
if(truncated.visible)
w += truncated.width + row_1.spacing
if(dismiss.visible)
w += dismiss.width + row_1.spacing
return control.implicitWidth - (w + icon.width + layout.anchors.leftMargin * 2)
}
}
Text{
id: link
text: control.externalURLLabel
font.underline: true
elide: Text.ElideRight
renderType: RibbonTheme.nativeText ? Text.NativeRendering : Text.QtRendering
color: tm.containsMouse ? RibbonTheme.isDarkMode ? "#91C5FA" : "#1A4474" :
RibbonTheme.isDarkMode ? "#7EB6F1" : "#255999"
Layout.alignment: Qt.AlignVCenter
Layout.maximumWidth: 150
Layout.preferredHeight: Math.min(barText.contentHeight, 16)
visible: control.externalURL
MouseArea{
id: tm
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: Qt.openUrlExternally(control.externalURL)
}
}
Item{
parent: control.isMultiline ? row_2 : row_1
visible: control.isMultiline && (showActionA || showActionB)
implicitHeight: 1
implicitWidth: {
var w = 0
if(actiona.visible && control.isMultiline)
w += actiona.width + row_2.spacing
if(actionb.visible && control.isMultiline)
w += actionb.width + row_2.spacing
return layout.width - w
}
}
RibbonButton{
id: actiona
parent: control.isMultiline ? row_2 : row_1
text: control.actionALabel
Layout.alignment: control.isMultiline ? Qt.AlignVCenter : Qt.AlignTop
Layout.topMargin: control.isMultiline ? 0 : - layout.anchors.topMargin * 3 / 4
Layout.bottomMargin: Layout.topMargin
onClicked: {
actionA()
actionAClicked()
}
visible: control.showActionA
}
RibbonButton{
id: actionb
parent: control.isMultiline ? row_2 : row_1
text: control.actionBLabel
Layout.alignment: control.isMultiline ? Qt.AlignVCenter : Qt.AlignTop
Layout.topMargin: control.isMultiline ? 0 : - layout.anchors.topMargin * 3 / 4
Layout.bottomMargin: Layout.topMargin
onClicked: {
actionB()
actionBClicked()
}
visible: control.showActionB
}
RibbonButton{
id: truncated
textColor: RibbonTheme.isDarkMode ? "#F1F0EF" : "#3E3D3C"
showBg: false
checkable: true
showHoveredBg: false
iconSource: RibbonIcons.ChevronDoubleDown
rotation: checked ? 180 : 0
tipText: control.overflowLabel
Layout.alignment: Qt.AlignTop
Layout.preferredHeight: Math.min(barText.contentHeight, 16)
visible: control.truncated && ((barText.height > link.height) || barText.truncated)
checked: control.isMultiline
Behavior on rotation {
NumberAnimation {
duration: 200
easing.type: Easing.OutSine
}
}
}
RibbonButton{
id: dismiss
textColor: RibbonTheme.isDarkMode ? "#F1F0EF" : "#3E3D3C"
showBg: false
showHoveredBg: false
iconSource: RibbonIcons.Dismiss
Layout.alignment: Qt.AlignTop
Layout.preferredHeight: Math.min(barText.contentHeight, 16)
tipText: control.dismissLabel
onClicked: {
dismissAction()
dismissClicked()
control.opacity = 0
}
}
}
RowLayout{
id: row_2
visible: control.isMultiline
layoutDirection: Qt.RightToLeft
}
}
onInfoColorChanged: refresh()
onTypeChanged: refresh()
Component.onCompleted: refresh()
function refresh(){
switch(type){
case RibbonMessageBar.Info:{
icon.color = !RibbonTheme.isDarkMode ? "#605E5C" : "#C8C6C4"
icon.iconSource = RibbonIcons.Info
control.color = infoColor
break
}
case RibbonMessageBar.Warning:{
icon.color = !RibbonTheme.isDarkMode ? "#605E5C" : "#C8C6C4"
icon.iconSource = RibbonIcons.Info
control.color = warningColor
break
}
case RibbonMessageBar.Success:{
icon.color = !RibbonTheme.isDarkMode ? "#387A26" : "#9CC262"
icon.iconSource = RibbonIcons.CheckmarkCircle
control.color = successColor
break
}
case RibbonMessageBar.SevereWarning:{
icon.color = !RibbonTheme.isDarkMode ? "#C74821" : "#F8E24B"
icon.iconSource = RibbonIcons.Warning
control.color = severeWarningColor
break
}
case RibbonMessageBar.Blocked:{
icon.color = !RibbonTheme.isDarkMode ? "#9A1E13" : "#E1777E"
icon.iconSource = RibbonIcons.SubtractCircle
control.color = blockedColor
break
}
case RibbonMessageBar.Error:{
icon.color = !RibbonTheme.isDarkMode ? "#9A1E13" : "#E1777E"
icon.iconSource = RibbonIcons.DismissCircle
control.color = errorColor
break
}
}
}
function calculateClassicColor(modernColor){
function limit(num){
if(num < 0)
return 0
else if(num > 255)
return 255
else
return num
}
if(!RibbonTheme.modernStyle){
modernColor = String(modernColor)
const num = parseInt(modernColor.slice(1), 16)
if(modernColor.length === 7)
return [Qt.rgba(limit((num >> 16) & 255) / 255,
limit(((num >> 8) & 255) + 0x03) / 255,
limit((num & 255) + 0x12) / 255,
1),
Qt.rgba(limit(((num >> 16) & 255) - 0x05) / 255,
limit(((num >> 8) & 255) - 0x01) / 255,
limit((num & 255) + 0x0C) / 255,
1)]
else
return [Qt.rgba(limit((num >> 24) & 255) / 255,
limit(((num >> 16) & 255) + 0x03) / 255,
limit(((num >> 8) & 255) + 0x12) / 255,
limit(num & 255) / 255),
Qt.rgba(limit(((num >> 24) & 255) - 0x05) / 255,
limit(((num >> 16) & 255) - 0x01) / 255,
limit(((num >> 8) & 255) + 0x0C) / 255,
limit(num & 255) / 255)]
}
else
return [modernColor,modernColor]
}
}