summaryrefslogtreecommitdiff
path: root/modules/controlcenter/components/SplitPaneWithDetails.qml
blob: e139acad7721e61cf531ceb120d6b25febaf6105 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
pragma ComponentBehavior: Bound

import ".."
import qs.components
import qs.components.effects
import qs.components.containers
import qs.config
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts

/**
 * SplitPaneWithDetails
 * 
 * A reusable component that provides a split-pane layout with a list on the left
 * and a details/settings view on the right. The right pane automatically switches
 * between details and settings views based on whether an item is selected.
 * 
 * This component eliminates duplication across WirelessPane, EthernetPane, and BtPane
 * by providing a standardized pattern for split-pane layouts with transition animations.
 * 
 * Usage:
 * ```qml
 * SplitPaneWithDetails {
 *     activeItem: root.session.network.active
 *     leftContent: Component {
 *         WirelessList {
 *             session: root.session
 *         }
 *     }
 *     rightDetailsComponent: Component {
 *         WirelessDetails {
 *             session: root.session
 *         }
 *     }
 *     rightSettingsComponent: Component {
 *         StyledFlickable {
 *             WirelessSettings {
 *                 session: root.session
 *             }
 *         }
 *     }
 *     paneIdGenerator: (item) => item ? (item.ssid || item.bssid || "") : ""
 * }
 * ```
 */
Item {
    id: root

    required property Component leftContent
    required property Component rightDetailsComponent
    required property Component rightSettingsComponent
    
    property var activeItem: null
    property var paneIdGenerator: function(item) { return item ? String(item) : ""; }
    
    // Optional: Additional component to overlay on top (e.g., password dialogs)
    property Component overlayComponent: null

    SplitPaneLayout {
        id: splitLayout

        anchors.fill: parent

        leftContent: root.leftContent

        rightContent: Component {
        Item {
            id: rightPaneItem
            
            property var pane: root.activeItem
            property string paneId: root.paneIdGenerator(pane)
            property Component targetComponent: root.rightSettingsComponent
            property Component nextComponent: root.rightSettingsComponent

            function getComponentForPane() {
                return pane ? root.rightDetailsComponent : root.rightSettingsComponent;
            }

            Component.onCompleted: {
                targetComponent = getComponentForPane();
                nextComponent = targetComponent;
            }

            Loader {
                id: rightLoader

                anchors.fill: parent

                opacity: 1
                scale: 1
                transformOrigin: Item.Center

                clip: false
                asynchronous: true
                sourceComponent: rightPaneItem.targetComponent
            }

            Behavior on paneId {
                PaneTransition {
                    target: rightLoader
                    propertyActions: [
                        PropertyAction {
                            target: rightPaneItem
                            property: "targetComponent"
                            value: rightPaneItem.nextComponent
                        }
                    ]
                }
            }

            onPaneChanged: {
                nextComponent = getComponentForPane();
                paneId = root.paneIdGenerator(pane);
            }
        }
        }
    }

    // Overlay component (e.g., password dialogs)
    Loader {
        id: overlayLoader
        
        anchors.fill: parent
        z: 1000
        sourceComponent: root.overlayComponent
        active: root.overlayComponent !== null
    }
}