123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- // 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 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
- 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
- }
- }
- }
|