mirror of
https://github.com/Athemis/PyDSF.git
synced 2025-04-05 06:36:04 +00:00
110 lines
No EOL
4 KiB
Python
110 lines
No EOL
4 KiB
Python
from ..Qt import QtGui, QtCore
|
|
from ..Point import Point
|
|
|
|
|
|
class GraphicsWidgetAnchor(object):
|
|
"""
|
|
Class used to allow GraphicsWidgets to anchor to a specific position on their
|
|
parent. The item will be automatically repositioned if the parent is resized.
|
|
This is used, for example, to anchor a LegendItem to a corner of its parent
|
|
PlotItem.
|
|
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.__parent = None
|
|
self.__parentAnchor = None
|
|
self.__itemAnchor = None
|
|
self.__offset = (0,0)
|
|
if hasattr(self, 'geometryChanged'):
|
|
self.geometryChanged.connect(self.__geometryChanged)
|
|
|
|
def anchor(self, itemPos, parentPos, offset=(0,0)):
|
|
"""
|
|
Anchors the item at its local itemPos to the item's parent at parentPos.
|
|
Both positions are expressed in values relative to the size of the item or parent;
|
|
a value of 0 indicates left or top edge, while 1 indicates right or bottom edge.
|
|
|
|
Optionally, offset may be specified to introduce an absolute offset.
|
|
|
|
Example: anchor a box such that its upper-right corner is fixed 10px left
|
|
and 10px down from its parent's upper-right corner::
|
|
|
|
box.anchor(itemPos=(1,0), parentPos=(1,0), offset=(-10,10))
|
|
"""
|
|
parent = self.parentItem()
|
|
if parent is None:
|
|
raise Exception("Cannot anchor; parent is not set.")
|
|
|
|
if self.__parent is not parent:
|
|
if self.__parent is not None:
|
|
self.__parent.geometryChanged.disconnect(self.__geometryChanged)
|
|
|
|
self.__parent = parent
|
|
parent.geometryChanged.connect(self.__geometryChanged)
|
|
|
|
self.__itemAnchor = itemPos
|
|
self.__parentAnchor = parentPos
|
|
self.__offset = offset
|
|
self.__geometryChanged()
|
|
|
|
|
|
def autoAnchor(self, pos, relative=True):
|
|
"""
|
|
Set the position of this item relative to its parent by automatically
|
|
choosing appropriate anchor settings.
|
|
|
|
If relative is True, one corner of the item will be anchored to
|
|
the appropriate location on the parent with no offset. The anchored
|
|
corner will be whichever is closest to the parent's boundary.
|
|
|
|
If relative is False, one corner of the item will be anchored to the same
|
|
corner of the parent, with an absolute offset to achieve the correct
|
|
position.
|
|
"""
|
|
pos = Point(pos)
|
|
br = self.mapRectToParent(self.boundingRect()).translated(pos - self.pos())
|
|
pbr = self.parentItem().boundingRect()
|
|
anchorPos = [0,0]
|
|
parentPos = Point()
|
|
itemPos = Point()
|
|
if abs(br.left() - pbr.left()) < abs(br.right() - pbr.right()):
|
|
anchorPos[0] = 0
|
|
parentPos[0] = pbr.left()
|
|
itemPos[0] = br.left()
|
|
else:
|
|
anchorPos[0] = 1
|
|
parentPos[0] = pbr.right()
|
|
itemPos[0] = br.right()
|
|
|
|
if abs(br.top() - pbr.top()) < abs(br.bottom() - pbr.bottom()):
|
|
anchorPos[1] = 0
|
|
parentPos[1] = pbr.top()
|
|
itemPos[1] = br.top()
|
|
else:
|
|
anchorPos[1] = 1
|
|
parentPos[1] = pbr.bottom()
|
|
itemPos[1] = br.bottom()
|
|
|
|
if relative:
|
|
relPos = [(itemPos[0]-pbr.left()) / pbr.width(), (itemPos[1]-pbr.top()) / pbr.height()]
|
|
self.anchor(anchorPos, relPos)
|
|
else:
|
|
offset = itemPos - parentPos
|
|
self.anchor(anchorPos, anchorPos, offset)
|
|
|
|
def __geometryChanged(self):
|
|
if self.__parent is None:
|
|
return
|
|
if self.__itemAnchor is None:
|
|
return
|
|
|
|
o = self.mapToParent(Point(0,0))
|
|
a = self.boundingRect().bottomRight() * Point(self.__itemAnchor)
|
|
a = self.mapToParent(a)
|
|
p = self.__parent.boundingRect().bottomRight() * Point(self.__parentAnchor)
|
|
off = Point(self.__offset)
|
|
pos = p + (o-a) + off
|
|
self.setPos(pos)
|
|
|
|
|