mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-01 08:14:22 +08:00
228 lines
7.2 KiB
QML
228 lines
7.2 KiB
QML
// Copyright (c) 2019 Ultimaker B.V.
|
|
// Cura is released under the terms of the LGPLv3 or higher.
|
|
|
|
import QtQuick 2.2
|
|
import QtQuick.Controls 2.0
|
|
import QtQuick.Controls.Styles 1.4
|
|
import QtQuick.Dialogs 1.1
|
|
import QtGraphicalEffects 1.0
|
|
import UM 1.3 as UM
|
|
|
|
/**
|
|
* This is a generic pop-up element which can be supplied with a target and a content item. The
|
|
* content item will appear to the left, right, above, or below the target depending on the value of
|
|
* the direction property
|
|
*/
|
|
Popup
|
|
{
|
|
id: base
|
|
|
|
/**
|
|
* The target item is what the pop-up is "tied" to, usually a button
|
|
*/
|
|
property var target
|
|
|
|
/**
|
|
* Which direction should the pop-up "point"?
|
|
* Possible values include:
|
|
* - "up"
|
|
* - "down"
|
|
* - "left"
|
|
* - "right"
|
|
*/
|
|
property string direction: "down"
|
|
|
|
/**
|
|
* We save the default direction so that if a pop-up was flipped but later has space (i.e. it
|
|
* moved), we can unflip it back to the default direction.
|
|
*/
|
|
property string originalDirection: ""
|
|
|
|
/**
|
|
* Should the popup close when you click outside it? For example, this is
|
|
* disabled by the InfoBlurb component since it's opened and closed using mouse
|
|
* hovers, not clicks.
|
|
*/
|
|
property bool closeOnClick: true
|
|
|
|
/**
|
|
* Use white for context menus, dark grey for info blurbs!
|
|
*/
|
|
property var color: "#ffffff" // TODO: Theme!
|
|
|
|
Component.onCompleted:
|
|
{
|
|
recalculatePosition()
|
|
|
|
// Set the direction here so it's only set once and never mutated
|
|
originalDirection = (' ' + direction).slice(1)
|
|
}
|
|
|
|
background: Item
|
|
{
|
|
anchors.fill: parent
|
|
|
|
DropShadow
|
|
{
|
|
anchors.fill: pointedRectangle
|
|
color: UM.Theme.getColor("monitor_shadow")
|
|
radius: UM.Theme.getSize("monitor_shadow_radius").width
|
|
source: pointedRectangle
|
|
transparentBorder: true
|
|
verticalOffset: 2 * screenScaleFactor
|
|
}
|
|
|
|
Item
|
|
{
|
|
id: pointedRectangle
|
|
anchors
|
|
{
|
|
horizontalCenter: parent.horizontalCenter
|
|
verticalCenter: parent.verticalCenter
|
|
}
|
|
height: parent.height - 10 * screenScaleFactor // Because of the shadow
|
|
width: parent.width - 10 * screenScaleFactor // Because of the shadow
|
|
|
|
Rectangle
|
|
{
|
|
id: point
|
|
anchors
|
|
{
|
|
horizontalCenter:
|
|
{
|
|
switch(direction)
|
|
{
|
|
case "left":
|
|
return bloop.left
|
|
case "right":
|
|
return bloop.right
|
|
default:
|
|
return bloop.horizontalCenter
|
|
}
|
|
}
|
|
verticalCenter:
|
|
{
|
|
switch(direction)
|
|
{
|
|
case "up":
|
|
return bloop.top
|
|
case "down":
|
|
return bloop.bottom
|
|
default:
|
|
return bloop.verticalCenter
|
|
}
|
|
}
|
|
}
|
|
color: base.color
|
|
height: 12 * screenScaleFactor
|
|
transform: Rotation
|
|
{
|
|
angle: 45
|
|
origin.x: point.width / 2
|
|
origin.y: point.height / 2
|
|
}
|
|
width: height
|
|
}
|
|
|
|
Rectangle
|
|
{
|
|
id: bloop
|
|
anchors
|
|
{
|
|
fill: parent
|
|
leftMargin: direction == "left" ? 8 * screenScaleFactor : 0
|
|
rightMargin: direction == "right" ? 8 * screenScaleFactor : 0
|
|
topMargin: direction == "up" ? 8 * screenScaleFactor : 0
|
|
bottomMargin: direction == "down" ? 8 * screenScaleFactor : 0
|
|
}
|
|
color: base.color
|
|
width: parent.width
|
|
}
|
|
}
|
|
}
|
|
|
|
visible: false
|
|
onClosed: visible = false
|
|
onOpened:
|
|
{
|
|
// Flip orientation if necessary
|
|
recalculateOrientation()
|
|
|
|
// Fix position if necessary
|
|
recalculatePosition()
|
|
|
|
// Show the pop up
|
|
visible = true
|
|
}
|
|
closePolicy: closeOnClick ? Popup.CloseOnPressOutside : Popup.NoAutoClose
|
|
|
|
clip: true
|
|
|
|
padding: UM.Theme.getSize("monitor_shadow_radius").width
|
|
topPadding: direction == "up" ? padding + 8 * screenScaleFactor : padding
|
|
bottomPadding: direction == "down" ? padding + 8 * screenScaleFactor : padding
|
|
leftPadding: direction == "left" ? padding + 8 * screenScaleFactor : padding
|
|
rightPadding: direction == "right" ? padding + 8 * screenScaleFactor : padding
|
|
|
|
function recalculatePosition() {
|
|
|
|
// Stupid pop-up logic causes the pop-up to resize, so let's compute what it SHOULD be
|
|
const realWidth = contentItem.implicitWidth + leftPadding + rightPadding
|
|
const realHeight = contentItem.implicitHeight + topPadding + bottomPadding
|
|
|
|
var centered = {
|
|
x: target.x + target.width / 2 - realWidth / 2,
|
|
y: target.y + target.height / 2 - realHeight / 2
|
|
}
|
|
|
|
switch(direction)
|
|
{
|
|
case "left":
|
|
x = target.x + target.width
|
|
y = centered.y
|
|
break
|
|
case "right":
|
|
x = target.x - realWidth
|
|
y = centered.y
|
|
break
|
|
case "up":
|
|
x = centered.x
|
|
y = target.y + target.height
|
|
break
|
|
case "down":
|
|
x = centered.x
|
|
y = target.y - realHeight
|
|
break
|
|
}
|
|
}
|
|
|
|
function recalculateOrientation() {
|
|
var availableSpace
|
|
var targetPosition = target.mapToItem(monitorFrame, 0, 0)
|
|
|
|
// Stupid pop-up logic causes the pop-up to resize, so let's compute what it SHOULD be
|
|
const realWidth = contentItem.implicitWidth + leftPadding + rightPadding
|
|
const realHeight = contentItem.implicitHeight + topPadding + bottomPadding
|
|
|
|
switch(originalDirection)
|
|
{
|
|
case "up":
|
|
availableSpace = monitorFrame.height - (targetPosition.y + target.height)
|
|
direction = availableSpace < realHeight ? "down" : originalDirection
|
|
break
|
|
case "down":
|
|
availableSpace = targetPosition.y
|
|
direction = availableSpace < realHeight ? "up" : originalDirection
|
|
break
|
|
case "right":
|
|
availableSpace = targetPosition.x
|
|
direction = availableSpace < realWidth ? "left" : originalDirection
|
|
break
|
|
case "left":
|
|
availableSpace = monitorFrame.width - (targetPosition.x + target.width)
|
|
direction = availableSpace < realWidth ? "right" : originalDirection
|
|
break
|
|
}
|
|
}
|
|
}
|