mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-19 04:18:08 +00:00
318 lines
8.2 KiB
QML
318 lines
8.2 KiB
QML
import QtQuick 2.7
|
|
|
|
import Common.Styles 1.0
|
|
import Utils 1.0
|
|
|
|
// =============================================================================
|
|
//
|
|
// Paned is one container divided in two areas.
|
|
// The division between the areas can be modified with a handle.
|
|
//
|
|
// Each area can have a fixed or dynamic minimum width.
|
|
// See `minimumLeftLimit` and `minimumRightLimit` attributes.
|
|
//
|
|
// Note: Paned supports too `maximumLeftLimit` and
|
|
// `maximumRightLimit`.
|
|
//
|
|
// To create a dynamic minimum width, it's necessary to give
|
|
// a percentage to `minmimumLeftLimit` or `minimumRightLimit` like:
|
|
// `minimumLeftLimit: '66%'`.
|
|
// The percentage is relative to the container width.
|
|
//
|
|
// =============================================================================
|
|
|
|
Item {
|
|
id: container
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
property alias childA: contentA.data
|
|
property alias childB: contentB.data
|
|
property bool defaultClosed: false
|
|
property bool resizeAInPriority: false
|
|
property int closingEdge: Qt.LeftEdge // `LeftEdge` or `RightEdge`.
|
|
property int defaultChildAWidth
|
|
|
|
// User limits: string or int values.
|
|
// By default: no limits.
|
|
property var maximumLeftLimit
|
|
property var maximumRightLimit
|
|
property var minimumLeftLimit: 0
|
|
property var minimumRightLimit: 0
|
|
|
|
property bool _isClosed
|
|
|
|
// Internal limits.
|
|
property var _maximumLeftLimit
|
|
property var _maximumRightLimit
|
|
property var _minimumLeftLimit
|
|
property var _minimumRightLimit
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Public functions.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function isClosed () {
|
|
return _isClosed
|
|
}
|
|
|
|
function open () {
|
|
if (_isClosed) {
|
|
openingTransition.running = true
|
|
}
|
|
}
|
|
|
|
function close () {
|
|
if (!_isClosed) {
|
|
_close()
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Private functions.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function _getLimitValue (limit) {
|
|
if (limit == null) {
|
|
return
|
|
}
|
|
|
|
return limit.isDynamic
|
|
? width * limit.value
|
|
: limit.value
|
|
}
|
|
|
|
function _parseLimit (limit) {
|
|
if (limit == null) {
|
|
return
|
|
}
|
|
|
|
if (Utils.isString(limit)) {
|
|
var arr = limit.split('%')
|
|
|
|
if (arr[1] === '') {
|
|
return {
|
|
isDynamic: true,
|
|
value: +arr[0] / 100
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
value: limit
|
|
}
|
|
}
|
|
|
|
function _applyLimits () {
|
|
var maximumLeftLimit = _getLimitValue(_maximumLeftLimit)
|
|
var maximumRightLimit = _getLimitValue(_maximumRightLimit)
|
|
var minimumLeftLimit = _getLimitValue(_minimumLeftLimit)
|
|
var minimumRightLimit = _getLimitValue(_minimumRightLimit)
|
|
|
|
var theoreticalBWidth = container.width - contentA.width - handle.width
|
|
|
|
// If closed, set correctly the handle position to left or right.
|
|
if (_isClosed) {
|
|
contentA.width = (closingEdge !== Qt.LeftEdge)
|
|
? container.width - handle.width
|
|
: 0
|
|
}
|
|
// width(A) < minimum width(A).
|
|
else if (contentA.width < minimumLeftLimit) {
|
|
contentA.width = minimumLeftLimit
|
|
}
|
|
// width(A) > maximum width(A).
|
|
else if (maximumLeftLimit != null && contentA.width > maximumLeftLimit) {
|
|
contentA.width = maximumLeftLimit
|
|
}
|
|
// width(B) < minimum width(B).
|
|
else if (theoreticalBWidth < minimumRightLimit) {
|
|
contentA.width = container.width - handle.width - minimumRightLimit
|
|
}
|
|
// width(B) > maximum width(B).
|
|
else if (maximumRightLimit != null && theoreticalBWidth > maximumRightLimit) {
|
|
contentA.width = container.width - handle.width - maximumRightLimit
|
|
} else if (resizeAInPriority) {
|
|
contentA.width = container.width - handle.width - contentB.width
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function _applyLimitsOnUserMove (offset) {
|
|
var minimumRightLimit = _getLimitValue(_minimumRightLimit)
|
|
var minimumLeftLimit = _getLimitValue(_minimumLeftLimit)
|
|
|
|
// One area is closed.
|
|
if (_isClosed) {
|
|
if (closingEdge === Qt.LeftEdge) {
|
|
if (offset > minimumLeftLimit / 2) {
|
|
_open()
|
|
}
|
|
} else {
|
|
if (-offset > minimumRightLimit / 2) {
|
|
_open()
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// Check limits.
|
|
var maximumLeftLimit = _getLimitValue(_maximumLeftLimit)
|
|
var maximumRightLimit = _getLimitValue(_maximumRightLimit)
|
|
|
|
var theoreticalBWidth = container.width - offset - contentA.width - handle.width
|
|
|
|
// width(A) < minimum width(A).
|
|
if (contentA.width + offset < minimumLeftLimit) {
|
|
contentA.width = minimumLeftLimit
|
|
|
|
if (closingEdge === Qt.LeftEdge && -offset > minimumLeftLimit / 2) {
|
|
if (_isClosed) {
|
|
_open()
|
|
} else {
|
|
_close()
|
|
}
|
|
}
|
|
}
|
|
// width(A) > maximum width(A).
|
|
else if (maximumLeftLimit != null && contentA.width + offset > maximumLeftLimit) {
|
|
contentA.width = maximumLeftLimit
|
|
}
|
|
// width(B) < minimum width(B).
|
|
else if (theoreticalBWidth < minimumRightLimit) {
|
|
contentA.width = container.width - handle.width - minimumRightLimit
|
|
|
|
if (closingEdge !== Qt.LeftEdge && offset > minimumRightLimit / 2) {
|
|
if (_isClosed) {
|
|
_open()
|
|
} else {
|
|
_close()
|
|
}
|
|
}
|
|
}
|
|
// width(B) > maximum width(B).
|
|
else if (maximumRightLimit != null && theoreticalBWidth > maximumRightLimit) {
|
|
contentA.width = container.width - handle.width - maximumRightLimit
|
|
}
|
|
// Resize A/B.
|
|
else {
|
|
contentA.width = contentA.width + offset
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function _open () {
|
|
_isClosed = false
|
|
_applyLimits()
|
|
}
|
|
|
|
function _close () {
|
|
_isClosed = true
|
|
closingTransition.running = true
|
|
}
|
|
|
|
function _inverseClosingState () {
|
|
if (!_isClosed) {
|
|
// Save state and close.
|
|
_close()
|
|
} else {
|
|
// Restore old state.
|
|
openingTransition.running = true
|
|
}
|
|
}
|
|
|
|
function _isVisible (edge) {
|
|
return (
|
|
!_isClosed ||
|
|
openingTransition.running ||
|
|
closingTransition.running
|
|
) || closingEdge !== edge
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
onWidthChanged: _applyLimits()
|
|
|
|
Component.onCompleted: {
|
|
// Unable to modify these properties after creation.
|
|
// It's a desired choice.
|
|
_maximumLeftLimit = _parseLimit(maximumLeftLimit)
|
|
_maximumRightLimit = _parseLimit(maximumRightLimit)
|
|
_minimumLeftLimit = _parseLimit(minimumLeftLimit)
|
|
_minimumRightLimit = _parseLimit(minimumRightLimit)
|
|
|
|
contentA.width = (defaultChildAWidth == null)
|
|
? _getLimitValue(_minimumLeftLimit)
|
|
: defaultChildAWidth
|
|
|
|
_isClosed = defaultClosed
|
|
}
|
|
|
|
Item {
|
|
id: contentA
|
|
|
|
height: parent.height
|
|
visible: _isVisible(Qt.LeftEdge)
|
|
}
|
|
|
|
MouseArea {
|
|
id: handle
|
|
|
|
property int _mouseStart
|
|
|
|
anchors.left: contentA.right
|
|
cursorShape: Qt.SplitHCursor
|
|
height: parent.height
|
|
hoverEnabled: true
|
|
width: PanedStyle.handle.width
|
|
|
|
onDoubleClicked: _inverseClosingState()
|
|
onMouseXChanged: pressed &&
|
|
_applyLimitsOnUserMove(mouseX - _mouseStart)
|
|
onPressed: _mouseStart = mouseX
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
color: parent.pressed
|
|
? PanedStyle.handle.color.pressed
|
|
: (parent.containsMouse
|
|
? PanedStyle.handle.color.hovered
|
|
: PanedStyle.handle.color.normal
|
|
)
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: contentB
|
|
|
|
anchors.left: handle.right
|
|
height: parent.height
|
|
visible: _isVisible(Qt.RightEdge)
|
|
width: container.width - contentA.width - handle.width
|
|
}
|
|
|
|
PropertyAnimation {
|
|
id: openingTransition
|
|
|
|
duration: PanedStyle.transitionDuration
|
|
property: 'width'
|
|
target: contentA
|
|
to: closingEdge === Qt.LeftEdge
|
|
? minimumLeftLimit
|
|
: container.width - minimumRightLimit - handle.width
|
|
|
|
onRunningChanged: !running && _open()
|
|
}
|
|
|
|
PropertyAnimation {
|
|
id: closingTransition
|
|
|
|
duration: PanedStyle.transitionDuration
|
|
property: 'width'
|
|
target: contentA
|
|
to: closingEdge === Qt.LeftEdge ? 0 : container.width - handle.width
|
|
}
|
|
}
|