Changeset View
Changeset View
Standalone View
Standalone View
toolboxes/desktoptoolbox/contents/ui/ToolBoxButton.qml
Show All 13 Lines | |||||
14 | * * | 14 | * * | ||
15 | * You should have received a copy of the GNU General Public License * | 15 | * You should have received a copy of the GNU General Public License * | ||
16 | * along with this program; if not, write to the * | 16 | * along with this program; if not, write to the * | ||
17 | * Free Software Foundation, Inc., * | 17 | * Free Software Foundation, Inc., * | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * | ||
19 | ***************************************************************************/ | 19 | ***************************************************************************/ | ||
20 | 20 | | |||
21 | import QtQuick 2.4 | 21 | import QtQuick 2.4 | ||
22 | import QtQuick.Layouts 1.4 | ||||
22 | import org.kde.plasma.core 2.0 as PlasmaCore | 23 | import org.kde.plasma.core 2.0 as PlasmaCore | ||
23 | import org.kde.plasma.components 2.0 as PlasmaComponents | 24 | import org.kde.plasma.components 2.0 as PlasmaComponents | ||
25 | import org.kde.plasma.components 3.0 as PlasmaComponents3 | ||||
24 | import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons | 26 | import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons | ||
25 | import org.kde.plasma.plasmoid 2.0 | 27 | import org.kde.plasma.plasmoid 2.0 | ||
26 | 28 | | |||
27 | Item { | 29 | Item { | ||
28 | id: toolBoxButton | 30 | id: toolBoxButton | ||
29 | 31 | | |||
30 | property string text: main.Plasmoid.activityName === i18n("Default") ? i18n("Desktop Toolbox") : i18n("Desktop Toolbox — %1 Activity", main.Plasmoid.activityName) | 32 | property bool isHorizontal: state != "left" && state != "right" && state != "leftcenter" && state != "rightcenter" | ||
31 | property bool isCorner: !buttonMouse.dragging && | | |||
32 | ((state == "topleft") || (state == "topright") || | | |||
33 | (state == "bottomright") || (state == "bottomleft")) | | |||
34 | property bool isHorizontal: (state != "left" && state != "right") | | |||
35 | 33 | | |||
36 | rotation: switch(state) { | 34 | rotation: switch(state) { | ||
37 | case "left": | 35 | case "left": | ||
36 | case "leftcenter": | ||||
38 | return -90; | 37 | return -90; | ||
39 | case "right": | 38 | case "right": | ||
39 | case "rightcenter": | ||||
40 | return 90; | 40 | return 90; | ||
41 | default: | 41 | default: | ||
42 | return 0; | 42 | return 0; | ||
43 | } | 43 | } | ||
44 | 44 | | |||
45 | transform: Translate { | 45 | transform: Translate { | ||
46 | x: state == "left" ? Math.round(-width/2 + height/2) : state == "right" ? + Math.round(width/2 - height/2) : 0 | 46 | x: state == "left" || state == "leftcenter" ? Math.round(-width/2 + height/2) - (plasmoid.editMode ? 0: height) | ||
47 | : state == "right" || state == "rightcenter" ? + Math.round(width/2 - height/2) + (plasmoid.editMode ? 0 : height) | ||||
48 | : 0 | ||||
49 | | ||||
50 | y: plasmoid.editMode ? 0 | ||||
51 | : state == "top" || state == "topcenter" ? -height | ||||
52 | : state == "bottom" || state == "bottomcenter" ? height | ||||
53 | : 0 | ||||
47 | Behavior on x { | 54 | Behavior on x { | ||
48 | NumberAnimation { | 55 | NumberAnimation { | ||
49 | duration: units.shortDuration * 3; | 56 | duration: units.longDuration | ||
50 | easing.type: Easing.InOutExpo; | 57 | easing.type: Easing.InOutQuad | ||
58 | } | ||||
59 | } | ||||
60 | Behavior on y { | ||||
61 | NumberAnimation { | ||||
62 | duration: units.longDuration | ||||
63 | easing.type: Easing.InOutQuad | ||||
51 | } | 64 | } | ||
52 | } | 65 | } | ||
53 | } | 66 | } | ||
54 | transformOrigin: Item.Center | 67 | transformOrigin: Item.Center | ||
68 | opacity: plasmoid.editMode | ||||
69 | Behavior on opacity { | ||||
70 | OpacityAnimator { | ||||
71 | duration: units.longDuration | ||||
72 | easing.type: Easing.InOutQuad | ||||
73 | } | ||||
74 | enabled: visible | ||||
75 | } | ||||
55 | Behavior on rotation { | 76 | Behavior on rotation { | ||
56 | NumberAnimation { | 77 | NumberAnimation { | ||
57 | duration: units.shortDuration * 3; | 78 | duration: units.shortDuration * 3; | ||
58 | easing.type: Easing.InOutExpo; | 79 | easing.type: Easing.InOutExpo; | ||
59 | } | 80 | } | ||
60 | enabled: visible | 81 | enabled: visible | ||
61 | } | 82 | } | ||
62 | Behavior on x { | 83 | Behavior on x { | ||
63 | NumberAnimation { | 84 | NumberAnimation { | ||
64 | duration: units.shortDuration * 3; | 85 | duration: units.shortDuration * 3; | ||
65 | easing.type: Easing.InOutExpo; | 86 | easing.type: Easing.InOutExpo; | ||
66 | } | 87 | } | ||
67 | enabled: visible | 88 | enabled: visible | ||
68 | 89 | | |||
69 | } | 90 | } | ||
70 | Behavior on y { | 91 | Behavior on y { | ||
71 | NumberAnimation { | 92 | NumberAnimation { | ||
72 | duration: units.shortDuration * 3; | 93 | duration: units.shortDuration * 3; | ||
73 | easing.type: Easing.InOutExpo; | 94 | easing.type: Easing.InOutExpo; | ||
74 | } | 95 | } | ||
75 | enabled: visible | 96 | enabled: visible | ||
76 | } | 97 | } | ||
77 | 98 | | |||
78 | clip: backgroundFrameWidthAnimation.running | 99 | width: buttonLayout.width | ||
79 | width: backgroundFrame.width + backgroundFrame.width % 2 | 100 | height: buttonLayout.height | ||
80 | height: backgroundFrame.height + backgroundFrame.height % 2 | 101 | | ||
81 | 102 | state: "topcenter" | |||
82 | //x and y default to 0, so top left would be correct | | |||
83 | //If the position is anything else it will updated via onXChanged during initialization | | |||
84 | state: "topleft" | | |||
85 | 103 | | |||
86 | onXChanged: stateTimer.restart() | 104 | onXChanged: stateTimer.restart() | ||
87 | onYChanged: stateTimer.restart() | 105 | onYChanged: stateTimer.restart() | ||
88 | 106 | | |||
89 | Timer { | 107 | Timer { | ||
90 | id: stateTimer | 108 | id: stateTimer | ||
91 | interval: 100 | 109 | interval: 0//toolBoxButton.state.indexOf("center") != -1 ? 0 : 100 | ||
davidedmundson: fix | |||||
92 | onTriggered: updateState() | 110 | onTriggered: updateState() | ||
93 | } | 111 | } | ||
94 | function updateState() { | 112 | function updateState() { | ||
95 | var container = main; | 113 | var container = main; | ||
96 | //print(" w: " + container.width +"x"+container.height+" : "+x+"/"+y+" tbw: " + toolBoxButton.width); | 114 | //print(" w: " + container.width +"x"+container.height+" : "+x+"/"+y+" tbw: " + toolBoxButton.width); | ||
97 | 115 | | |||
98 | var x = toolBoxButton.x - main.x; | 116 | var x = toolBoxButton.x - main.x; | ||
99 | var y = toolBoxButton.y - main.y; | 117 | var y = toolBoxButton.y - main.y; | ||
100 | 118 | | |||
101 | var cornerSnap = iconWidth | 119 | var cornerSnap = iconWidth | ||
102 | 120 | | |||
103 | if (x < cornerSnap && y < cornerSnap) { | | |||
104 | toolBoxButton.state = "topleft"; | | |||
105 | } else if (container.width - x - buttonLayout.width < cornerSnap && y < cornerSnap) { | | |||
106 | toolBoxButton.state = "topright"; | | |||
107 | } else if (container.width - x - buttonLayout.width < cornerSnap && container.height - y - buttonLayout.width < cornerSnap) { | | |||
108 | toolBoxButton.state = "bottomright"; | | |||
109 | } else if (x < cornerSnap && container.height - y - buttonLayout.width < cornerSnap) { | | |||
110 | toolBoxButton.state = "bottomleft"; | | |||
111 | //top diagonal half | 121 | //top diagonal half | ||
112 | } else if (x > (y * (container.width/container.height))) { | 122 | if (x > (y * (container.width/container.height))) { | ||
113 | //Top edge | 123 | //Top edge | ||
114 | if (container.width - x > y ) { | 124 | if (container.width - x - width/2 > y ) { | ||
125 | if (Math.abs(container.width/2 - (x + width/2)) < units.gridUnit) { | ||||
126 | toolBoxButton.state = "topcenter"; | ||||
127 | } else { | ||||
115 | toolBoxButton.state = "top"; | 128 | toolBoxButton.state = "top"; | ||
129 | } | ||||
116 | //right edge | 130 | //right edge | ||
117 | } else { | 131 | } else { | ||
118 | //toolBoxButton.transformOrigin = Item.BottomRight | 132 | if (Math.abs(container.height/2 - (y + height/2)) < units.gridUnit) { | ||
133 | toolBoxButton.state = "rightcenter"; | ||||
134 | } else { | ||||
119 | toolBoxButton.state = "right"; | 135 | toolBoxButton.state = "right"; | ||
120 | } | 136 | } | ||
137 | } | ||||
121 | //bottom diagonal half | 138 | //bottom diagonal half | ||
122 | } else { | 139 | } else { | ||
123 | //Left edge | 140 | //Left edge | ||
124 | if (container.height - y > x ) { | 141 | if (container.height - y - width/2 > x ) { | ||
125 | //toolBoxButton.transformOrigin = Item.TopLeft | 142 | if (Math.abs(container.height/2 - (y + width/2)) < units.gridUnit) { | ||
143 | toolBoxButton.state = "leftcenter"; | ||||
144 | } else { | ||||
126 | toolBoxButton.state = "left"; | 145 | toolBoxButton.state = "left"; | ||
146 | } | ||||
127 | //Bottom edge | 147 | //Bottom edge | ||
128 | } else { | 148 | } else { | ||
149 | if (Math.abs(container.width/2 - (x + height/2)) < units.gridUnit) { | ||||
150 | toolBoxButton.state = "bottomcenter"; | ||||
151 | } else { | ||||
129 | toolBoxButton.state = "bottom"; | 152 | toolBoxButton.state = "bottom"; | ||
130 | } | 153 | } | ||
131 | } | 154 | } | ||
155 | } | ||||
132 | 156 | | |||
133 | if (!buttonMouse.pressed) { | 157 | if (!buttonMouse.pressed) { | ||
134 | main.placeToolBox(toolBoxButton.state); | 158 | main.placeToolBox(toolBoxButton.state); | ||
135 | } | 159 | } | ||
136 | 160 | | |||
137 | stateTimer.running = false; | 161 | stateTimer.running = false; | ||
138 | } | 162 | } | ||
139 | 163 | | |||
140 | PlasmaCore.FrameSvgItem { | 164 | PlasmaCore.FrameSvgItem { | ||
141 | id: backgroundFrame | 165 | id: backgroundFrame | ||
142 | anchors { | 166 | anchors { | ||
143 | left: parent.left | 167 | //left: parent.left | ||
144 | top: parent.top | 168 | //top: parent.top | ||
169 | fill: parent | ||||
170 | leftMargin: -backgroundFrame.margins.left | ||||
171 | topMargin: -backgroundFrame.margins.top | ||||
172 | rightMargin: -backgroundFrame.margins.right | ||||
173 | bottomMargin: -backgroundFrame.margins.bottom | ||||
145 | } | 174 | } | ||
146 | imagePath: "widgets/translucentbackground" | 175 | imagePath: "widgets/background" | ||
147 | opacity: buttonMouse.containsMouse || (toolBoxLoader.item && toolBoxLoader.item.visible) ? 1.0 : 0.4 | 176 | width: Math.round(buttonLayout.width + margins.horizontal) | ||
148 | width: Math.round((isCorner ? buttonLayout.height : buttonLayout.width) + margins.horizontal) | | |||
149 | height: Math.round(buttonLayout.height + margins.vertical) | 177 | height: Math.round(buttonLayout.height + margins.vertical) | ||
150 | Behavior on width { | | |||
151 | NumberAnimation { | | |||
152 | id: backgroundFrameWidthAnimation | | |||
153 | duration: units.longDuration; | | |||
154 | easing.type: Easing.InOutQuad; | | |||
155 | } | | |||
156 | } | | |||
157 | Behavior on opacity { | | |||
158 | NumberAnimation { | | |||
159 | duration: units.longDuration; | | |||
160 | } | | |||
161 | } | | |||
162 | } | | |||
163 | | ||||
164 | Row { | | |||
165 | id: buttonLayout | | |||
166 | anchors.centerIn: parent | | |||
167 | height: Math.max(toolBoxIcon.height, fontMetrics.height) | | |||
168 | spacing: units.smallSpacing | | |||
169 | | ||||
170 | Behavior on x { | | |||
171 | NumberAnimation { | | |||
172 | duration: units.longDuration; | | |||
173 | easing.type: Easing.InOutQuad; | | |||
174 | } | | |||
175 | } | | |||
176 | | ||||
177 | PlasmaCore.SvgItem { | | |||
178 | id: toolBoxIcon | | |||
179 | svg: PlasmaCore.Svg { | | |||
180 | id: iconSvg | | |||
181 | imagePath: "widgets/configuration-icons" | | |||
182 | onRepaintNeeded: toolBoxIcon.elementId = iconSvg.hasElement("menu") ? "menu" : "configure" | | |||
183 | } | | |||
184 | elementId: iconSvg.hasElement("menu") ? "menu" : "configure" | | |||
185 | anchors.verticalCenter: parent.verticalCenter | | |||
186 | width: iconSize | | |||
187 | height: iconSize | | |||
188 | opacity: buttonMouse.containsMouse || (toolBoxLoader.item && toolBoxLoader.item.visible) ? 1 : 0.5 | | |||
189 | rotation: isHorizontal ? 0 : -90; | | |||
190 | transformOrigin: Item.Center | | |||
191 | Behavior on opacity { | | |||
192 | NumberAnimation { | | |||
193 | duration: units.longDuration; | | |||
194 | easing.type: Easing.InOutExpo; | | |||
195 | } | | |||
196 | } | | |||
197 | } | | |||
198 | | ||||
199 | PlasmaComponents.Label { | | |||
200 | id: activityName | | |||
201 | anchors.verticalCenter: parent.verticalCenter | | |||
202 | opacity: isCorner ? 0 : 1 | | |||
203 | text: toolBoxButton.text | | |||
204 | visible: opacity | | |||
205 | Behavior on opacity { | | |||
206 | //only have this animation when going from hidden -> shown | | |||
207 | enabled: activityName.opacity == 0 | | |||
208 | | ||||
209 | SequentialAnimation { | | |||
210 | //pause to allow the toolbox frame to resize | | |||
211 | //otherwise we see the text overflow the box | | |||
212 | //whilst that animates | | |||
213 | PauseAnimation { | | |||
214 | duration: units.longDuration | | |||
215 | } | | |||
216 | NumberAnimation { | | |||
217 | duration: units.shortDuration | | |||
218 | easing.type: Easing.InOutExpo | | |||
219 | } | | |||
220 | } | | |||
221 | } | | |||
222 | } | | |||
223 | | ||||
224 | FontMetrics { | | |||
225 | id: fontMetrics | | |||
226 | font: activityName.font | | |||
227 | } | | |||
228 | } | 178 | } | ||
229 | 179 | | |||
230 | MouseArea { | 180 | MouseArea { | ||
231 | id: buttonMouse | 181 | id: buttonMouse | ||
232 | 182 | | |||
233 | property QtObject container: main | 183 | property QtObject container: main | ||
234 | property int pressedX | 184 | property int pressedX | ||
235 | property int pressedY | 185 | property int pressedY | ||
186 | property int snapStartX | ||||
187 | property int snapStartY | ||||
188 | property bool snapX: false; | ||||
189 | property bool snapY: false; | ||||
236 | property bool dragging: false | 190 | property bool dragging: false | ||
237 | 191 | | |||
238 | anchors { | 192 | anchors.fill: parent | ||
239 | fill: parent | | |||
240 | margins: -10 | | |||
241 | } | | |||
242 | 193 | | |||
243 | drag { | 194 | drag { | ||
195 | filterChildren: true | ||||
244 | target: main.Plasmoid.immutable ? undefined : toolBoxButton | 196 | target: main.Plasmoid.immutable ? undefined : toolBoxButton | ||
245 | minimumX: 0 | 197 | minimumX: 0 | ||
246 | maximumX: container.width - toolBoxIcon.width | 198 | maximumX: container.width - toolBoxButton.width | ||
247 | minimumY: 0 | 199 | minimumY: toolBoxButton.isHorizontal ? 0 : toolBoxButton.width/2 - toolBoxButton.height/2 | ||
248 | maximumY: container.height - toolBoxIcon.height | 200 | maximumY: toolBoxButton.isHorizontal ? container.height : container.height - toolBoxButton.width/2 - toolBoxButton.height/2 | ||
249 | } | 201 | } | ||
250 | 202 | | |||
251 | hoverEnabled: true | 203 | hoverEnabled: true | ||
252 | 204 | | |||
253 | onPressed: { | 205 | onPressed: { | ||
254 | pressedX = toolBoxButton.x | 206 | pressedX = toolBoxButton.x | ||
255 | pressedY = toolBoxButton.y | 207 | pressedY = toolBoxButton.y | ||
256 | } | 208 | } | ||
257 | onPositionChanged: { | 209 | onPositionChanged: { | ||
258 | if (pressed && (Math.abs(toolBoxButton.x - pressedX) > iconSize || | 210 | if (pressed && (Math.abs(toolBoxButton.x - pressedX) > iconSize || | ||
259 | Math.abs(toolBoxButton.y - pressedY) > iconSize)) { | 211 | Math.abs(toolBoxButton.y - pressedY) > iconSize)) { | ||
260 | dragging = true; | 212 | dragging = true; | ||
261 | } | 213 | } | ||
214 | | ||||
215 | // Center snapping X | ||||
216 | if (snapX && Math.abs(snapStartX - mouse.x) > units.gridUnit) { | ||||
217 | toolBoxButton.anchors.horizontalCenter = undefined; | ||||
218 | snapX = false; | ||||
219 | } else if (!snapX && Math.abs(main.width/2 - (toolBoxButton.x + toolBoxButton.width/2)) < units.gridUnit) { | ||||
220 | toolBoxButton.anchors.horizontalCenter = main.horizontalCenter; | ||||
221 | snapStartX = mouse.x; | ||||
222 | snapX = true; | ||||
223 | } | ||||
224 | // Center snapping Y still use mouse.x because rotation | ||||
225 | if (snapY && Math.abs(snapStartY - mouse.x) > units.gridUnit) { | ||||
226 | toolBoxButton.anchors.verticalCenter = undefined; | ||||
227 | snapY = false; | ||||
228 | } else if (!snapY && Math.abs(main.height/2 - (toolBoxButton.y + toolBoxButton.height/2)) < units.gridUnit) { | ||||
229 | toolBoxButton.anchors.verticalCenter = main.verticalCenter; | ||||
230 | snapStartY = mouse.x; | ||||
231 | snapY = true; | ||||
262 | } | 232 | } | ||
263 | onClicked: { | | |||
264 | // the dialog auto-closes on losing focus | | |||
265 | main.open = !main.dialogWasVisible | | |||
266 | plasmoid.focus = true; | | |||
267 | } | 233 | } | ||
234 | | ||||
268 | onReleased: { | 235 | onReleased: { | ||
236 | toolBoxButton.anchors.horizontalCenter = undefined; | ||||
237 | toolBoxButton.anchors.verticalCenter = undefined; | ||||
238 | snapX = false; | ||||
239 | snapY = false; | ||||
269 | main.Plasmoid.configuration.ToolBoxButtonState = toolBoxButton.state; | 240 | main.Plasmoid.configuration.ToolBoxButtonState = toolBoxButton.state; | ||
270 | main.Plasmoid.configuration.ToolBoxButtonX = toolBoxButton.x; | 241 | main.Plasmoid.configuration.ToolBoxButtonX = toolBoxButton.x; | ||
271 | main.Plasmoid.configuration.ToolBoxButtonY = toolBoxButton.y; | 242 | main.Plasmoid.configuration.ToolBoxButtonY = toolBoxButton.y; | ||
272 | //print("Saved coordinates for ToolBox in config: " + toolBoxButton.x + ", " +toolBoxButton.x); | 243 | //print("Saved coordinates for ToolBox in config: " + toolBoxButton.x + ", " +toolBoxButton.x); | ||
273 | if (dragging) { | 244 | if (dragging) { | ||
274 | main.placeToolBox(); | 245 | main.placeToolBox(); | ||
275 | } | 246 | } | ||
276 | dragging = false; | 247 | dragging = false; | ||
277 | stateTimer.stop(); | 248 | stateTimer.stop(); | ||
278 | updateState(); | 249 | updateState(); | ||
279 | } | 250 | } | ||
280 | onCanceled: dragging = false; | 251 | onCanceled: dragging = false; | ||
281 | } | | |||
282 | 252 | | |||
283 | states: [ | 253 | RowLayout { | ||
284 | State { | 254 | id: buttonLayout | ||
285 | name: "topleft" | 255 | anchors.centerIn: parent | ||
286 | }, | 256 | spacing: units.smallSpacing | ||
287 | State { | 257 | | ||
288 | name: "top" | 258 | | ||
289 | }, | 259 | PlasmaComponents3.ToolButton { | ||
290 | State { | 260 | property QtObject qAction: plasmoid.action("add widgets") | ||
291 | name: "topright" | 261 | text: qAction.text | ||
292 | }, | 262 | icon.name: "list-add" | ||
293 | State { | 263 | icon.height: units.iconSizes.smallMedium | ||
294 | name: "right" | 264 | onClicked: qAction.trigger() | ||
295 | }, | 265 | } | ||
296 | State { | 266 | PlasmaComponents3.ToolButton { | ||
297 | name: "bottomright" | 267 | property QtObject qAction: plasmoid.globalAction("manage activities") | ||
298 | }, | 268 | text: qAction.text | ||
299 | State { | 269 | icon.name: "activities" | ||
300 | name: "bottom" | 270 | icon.height: units.iconSizes.smallMedium | ||
301 | }, | 271 | onClicked: qAction.trigger() | ||
302 | State { | 272 | } | ||
303 | name: "bottomleft" | 273 | PlasmaComponents3.ToolButton { | ||
304 | }, | 274 | property QtObject qAction: plasmoid.action("configure") | ||
305 | State { | 275 | text: qAction.text | ||
306 | name: "left" | 276 | icon.name: "preferences-desktop-wallpaper" | ||
277 | icon.height: units.iconSizes.smallMedium | ||||
278 | onClicked: qAction.trigger() | ||||
ngraham: Locking the widgets while in edit mode doesn't update the menu item, so it's possible to end up… | |||||
mart: latest revision should fix that | |||||
actually, revision of D24263 mart: actually, revision of D24263 | |||||
279 | } | ||||
280 | PlasmaComponents3.ToolButton { | ||||
281 | icon.name: "window-close" | ||||
282 | icon.height: units.iconSizes.smallMedium | ||||
283 | onClicked: plasmoid.editMode = false | ||||
284 | PlasmaComponents3.ToolTip { | ||||
285 | text: i18n("Close Edit Mode") | ||||
286 | } | ||||
GB_2: Please change to "Finish Customizing Layout" to match the menu entry. | |||||
287 | } | ||||
288 | } | ||||
307 | } | 289 | } | ||
308 | ] | | |||
309 | } | 290 | } | ||
This should probably be changed to "Finish Customizing Layout" to match the current menu entry. GB_2: This should probably be changed to "Finish Customizing Layout" to match the current menu entry. | |||||
GB_2: Not done. |
fix