Reset pop-up orientation if it moved

Contributes to CL-1165
This commit is contained in:
Ian Paschal 2019-01-10 15:54:58 +01:00
parent 292d04f3ea
commit 612b0d0165
2 changed files with 75 additions and 49 deletions

View File

@ -9,9 +9,9 @@ import QtGraphicalEffects 1.0
import UM 1.3 as UM import UM 1.3 as UM
/** /**
* This is a generic pop-up element which can be supplied with a target and a content * This is a generic pop-up element which can be supplied with a target and a content item. The
* item. The content item will appear to the left, right, above, or below the target * content item will appear to the left, right, above, or below the target depending on the value of
* depending on the value of the direction property * the direction property
*/ */
Popup Popup
{ {
@ -23,14 +23,20 @@ Popup
property var target property var target
/** /**
* Which side of the target should the contentItem appear on? * Which direction should the pop-up "point"?
* Possible values include: * Possible values include:
* - "top" * - "up"
* - "bottom" * - "down"
* - "left" * - "left"
* - "right" * - "right"
*/ */
property string direction: "bottom" 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 * Should the popup close when you click outside it? For example, this is
@ -44,7 +50,13 @@ Popup
*/ */
property var color: "#ffffff" // TODO: Theme! property var color: "#ffffff" // TODO: Theme!
Component.onCompleted: recalculatePosition() Component.onCompleted:
{
recalculatePosition()
// Set the direction here so it's only set once and never mutated
originalDirection = (' ' + direction).slice(1)
}
background: Item background: Item
{ {
@ -92,9 +104,9 @@ Popup
{ {
switch(direction) switch(direction)
{ {
case "top": case "up":
return bloop.top return bloop.top
case "bottom": case "down":
return bloop.bottom return bloop.bottom
default: default:
return bloop.verticalCenter return bloop.verticalCenter
@ -118,10 +130,10 @@ Popup
anchors anchors
{ {
fill: parent fill: parent
leftMargin: direction == "left" ? 8 * screenScaleFactor : 0 leftMargin: direction == "left" ? 8 * screenScaleFactor : 0
rightMargin: direction == "right" ? 8 * screenScaleFactor : 0 rightMargin: direction == "right" ? 8 * screenScaleFactor : 0
topMargin: direction == "top" ? 8 * screenScaleFactor : 0 topMargin: direction == "up" ? 8 * screenScaleFactor : 0
bottomMargin: direction == "bottom" ? 8 * screenScaleFactor : 0 bottomMargin: direction == "down" ? 8 * screenScaleFactor : 0
} }
color: base.color color: base.color
width: parent.width width: parent.width
@ -133,35 +145,10 @@ Popup
onClosed: visible = false onClosed: visible = false
onOpened: onOpened:
{ {
// Flip direction if there is not enough screen space // Flip orientation if necessary
var availableSpace recalculateOrientation()
var targetPosition = target.mapToItem(monitorFrame, 0, 0)
var requiredSpace = contentItem.implicitHeight + 2 * padding + 8 * screenScaleFactor
switch(direction)
{
case "top":
availableSpace = monitorFrame.height - (targetPosition.y + target.height)
// console.log("Needs", requiredSpace, "has got", availableSpace)
if (availableSpace < requiredSpace)
{
// console.log("putting point on bottom")
direction = "bottom"
}
break
case "bottom":
availableSpace = targetPosition.y
// console.log("Needs", requiredSpace, "has got", availableSpace)
if (availableSpace < requiredSpace)
{
// console.log("putting point on top")
direction = "top"
}
break
}
// Fix position if necessary
recalculatePosition() recalculatePosition()
// Show the pop up // Show the pop up
@ -172,10 +159,10 @@ Popup
clip: true clip: true
padding: UM.Theme.getSize("monitor_shadow_radius").width padding: UM.Theme.getSize("monitor_shadow_radius").width
topPadding: direction == "top" ? padding + 8 * screenScaleFactor : padding topPadding: direction == "up" ? padding + 8 * screenScaleFactor : padding
bottomPadding: direction == "bottom" ? padding + 8 * screenScaleFactor : padding bottomPadding: direction == "down" ? padding + 8 * screenScaleFactor : padding
leftPadding: direction == "left" ? padding + 8 * screenScaleFactor : padding leftPadding: direction == "left" ? padding + 8 * screenScaleFactor : padding
rightPadding: direction == "right" ? padding + 8 * screenScaleFactor : padding rightPadding: direction == "right" ? padding + 8 * screenScaleFactor : padding
function recalculatePosition() { function recalculatePosition() {
@ -198,14 +185,52 @@ Popup
x = target.x - realWidth x = target.x - realWidth
y = centered.y y = centered.y
break break
case "top": case "up":
x = centered.x x = centered.x
y = target.y + target.height y = target.y + target.height
break break
case "bottom": case "down":
x = centered.x x = centered.x
y = target.y - realHeight y = target.y - realHeight
break break
} }
} }
function recalculateOrientation() {
// Flip direction if there is not enough screen space
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
// if (availableSpace < realHeight)
// {
// if (direction != originalDirection)
// {
// }
// }
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
}
}
} }

View File

@ -20,7 +20,8 @@ Item
{ {
id: popUp id: popUp
direction: "top" // Which way should the pop-up point? Default is up, but will flip when required
direction: "up"
// Use dark grey for info blurbs and white for context menus // Use dark grey for info blurbs and white for context menus
color: "#191919" // TODO: Theme! color: "#191919" // TODO: Theme!