3
/* Item displaying a launcher item.
6
- a generic bordered background image
7
- an icon representing the item
8
- a text describing the item
10
When an application is launched, the border changes appearance.
11
It supports mouse hover by changing the appearance of the background image.
13
The 'icon' property holds the source of the image to load as an icon.
14
The 'label' property holds the text to display.
15
The 'running' property is a boolean indicating whether or not the
16
application is launched.
18
The 'clicked' signal is emitted upon clicking on the item.
4
/* This component represents a single "tile" in the launcher and the surrounding
7
The tile is square in size, with a side determined by the 'tileSize' property,
9
It is composed by a colored background layer, an icon (with 'icon' as source),
10
and a layer on top that provides a "shine" effect.
11
The main color of the background layer may be calculated based on the icon color
12
or may be fixed (depending on the 'backgroundFromIcon' property).
14
There's also an additional layer which contains only the outline of the tile
15
that is only appearing during the launching animation (when the 'launching' property is
16
true). During this animation the background fades out and the outline fades in,
17
giving a "pulsing" appearance to the tile.
19
Around the tile we may have on the left a number of "pips" between zero and three.
20
Pips are small icons used to indicate how many windows we have open for the current tile
21
(based on the 'windowCount' property).
22
The rule is: if there's only one window, we just display an arrow. If there are
23
two we display 2 pips, if there are 3 or more display 3 pips.
25
On the right of the tile there's an arrow that appears if the tile is currently 'active'.
27
Additionally, when the tile is marked as 'urgent' it will start an animation where the
28
rotation is changed so that it appears to be "shaking".
32
/* The object name is used by the launcher view to find the current
33
launcher item under the mouse cursor during a drag’n’drop event. */
34
objectName: "launcherItem"
36
anchors.horizontalCenter: parent.horizontalCenter
37
/* Manually add some padding to compensate for the spacing
38
of the ListView being set to 0 to work around
39
http://bugreports.qt.nokia.com/browse/QTBUG-17622. */
40
property int padding: 5
41
height: tileSize + padding
44
property string desktopFile: ""
23
45
property alias icon: icon.source
24
property alias label: label.text
25
46
property bool running: false
26
47
property bool active: false
27
48
property bool urgent: false
28
49
property bool launching: false
51
property int counter: 0
52
property bool counterVisible: false
53
property real progress: 0.0
54
property bool progressBarVisible: false
55
property alias emblem: emblemIcon.source
56
property bool emblemVisible: false
58
property bool backgroundFromIcon
59
property color defaultBackgroundColor: "#333333"
61
property alias shortcutVisible: shortcut.visible
62
property alias shortcutText: shortcutText.text
65
property string pipSource: engineBaseUrl + "artwork/launcher_" +
66
((pips <= 1) ? "arrow" : "pip") + "_ltr.png"
67
function getPipOffset(index) {
68
/* Pips need to always be centered, regardless if they are an even or odd
69
number. The following simple conditional code works and is less
70
convoluted than a generic formula. It's ok since we always work with at
71
most three pips anyway. */
72
if (pips == 1) return 0;
73
if (pips == 2) return (index == 0) ? -2 : +2
74
else return (index == 0) ? 0 : (index == 1) ? -4 : +4
30
77
signal clicked(variant mouse)
35
if (event.key == Qt.Key_Return) {
37
event.accepted = true;
44
source: "artwork/shadow.png"
51
anchors.horizontalCenter: parent.horizontalCenter
52
anchors.verticalCenter: parent.verticalCenter
54
source: "artwork/glow.png"
58
SequentialAnimation on opacity {
59
loops: Animation.Infinite
62
NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad }
63
NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad }
72
anchors.horizontalCenter: parent.horizontalCenter
73
anchors.verticalCenter: parent.verticalCenter
78
acceptedButtons: Qt.LeftButton | Qt.RightButton
81
onClicked: launcherItem.clicked(mouse)
82
onEntered: launcherItem.entered()
83
onExited: launcherItem.exited()
89
opacity: mouse.containsMouse ? 1.0 : 0.9
92
anchors.horizontalCenter: parent.horizontalCenter
93
anchors.verticalCenter: parent.verticalCenter
95
color: if(icon.source != "")
96
return launcherView.iconAverageColor(icon.source,
97
Qt.size(icon.width, icon.height))
106
anchors.horizontalCenter: parent.horizontalCenter
107
anchors.verticalCenter: parent.verticalCenter
108
fillMode: Image.PreserveAspectFit
109
sourceSize.width: width
110
sourceSize.height: height
114
opacity: status == Image.Ready ? 1 : 0
115
Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}}
122
anchors.horizontalCenter: parent.horizontalCenter
123
anchors.verticalCenter: parent.verticalCenter
124
fillMode: Image.PreserveAspectFit
125
sourceSize.width: width
126
sourceSize.height: height
129
source: "/usr/share/unity/themes/prism_icon_foreground.png"
132
opacity: status == Image.Ready ? 1 : 0
133
Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}}
136
SequentialAnimation {
82
/* The actual item, reparented so its y coordinate can be animated. */
88
/* item.parent is the delegate, and its parent is the LauncherList */
89
y: item.parent.parent.y - item.parent.parent.contentY + item.y
90
z: item.parent.parent.itemZ
92
/* This is the arrow shown at the right of the tile when the application is
95
anchors.right: parent.right
96
anchors.verticalCenter: parent.verticalCenter
97
source: "image://blended/%1color=%2alpha=%3"
98
.arg(engineBaseUrl + "artwork/launcher_arrow_rtl.png")
102
/* This extra shift is necessary (as is for the pips below)
103
since we are vertically centering in a parent with even height, so
104
there's one pixel offset that need to be assigned arbitrarily.
105
Unity chose to add it, QML to subtract it. So we adjust for that. */
106
transform: Translate { y: 1 }
108
visible: active && (looseItem.state != "beingDragged")
111
/* This is the area on the left of the tile where the pips/arrow end up.
113
I'd rather use a Column here, but the pip images have an halo
114
around them, so they are pretty tall and would mess up the column.
115
As a workaround I center all of them, then shift up or down
116
depending on the index. */
120
/* FIXME: It seems that when the image is created (or re-used) by the Repeater
121
for a moment it doesn't have any parent, and therefore warnings are
122
printed for the following two anchor assignements. This fixes the
123
problem, but I'm not sure if it should happen in the first place. */
124
anchors.left: (parent) ? parent.left : undefined
125
anchors.verticalCenter: (parent) ? parent.verticalCenter : undefined
127
source: "image://blended/%1color=%2alpha=%3"
128
.arg(pipSource).arg("lightgrey").arg(1.0)
130
transform: Translate { y: getPipOffset(index) + 1 }
132
visible: looseItem.state != "beingDragged"
136
/* This is the for centering the actual tile in the launcher */
140
height: item.tileSize
141
anchors.centerIn: parent
143
/* This is the image providing the background image. The
144
color blended with this image is obtained from the color of the icon when it's
146
While the application is launching, this will fade out and in. */
149
property color color: defaultBackgroundColor
152
SequentialAnimation on opacity {
153
NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad }
154
NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad }
156
loops: Animation.Infinite
161
sourceSize.width: item.tileSize
162
sourceSize.height: item.tileSize
163
source: "image://blended/%1color=%2alpha=%3"
164
.arg(engineBaseUrl + "artwork/round_corner_54x54.png")
165
.arg(color.toString().replace("#", ""))
169
/* This image appears only while launching, and pulses in and out in counterpoint
170
to the background, so that the outline of the tile is always visible. */
175
sourceSize.width: item.tileSize
176
sourceSize.height: item.tileSize
177
source: "artwork/round_outline_54x54.png"
181
SequentialAnimation on opacity {
182
NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad }
183
NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad }
185
loops: Animation.Infinite
191
/* This is just the main icon of the tile */
194
anchors.centerIn: parent
197
sourceSize.height: 48
199
/* Whenever one of the parameters used in calculating the background color of
200
the icon changes, recalculate its value */
201
onWidthChanged: updateColors()
202
onHeightChanged: updateColors()
203
onSourceChanged: updateColors()
205
function updateColors() {
206
if (!item.backgroundFromIcon) return;
208
var colors = launcherView.getColorsFromIcon(icon.source, icon.sourceSize)
209
if (colors && colors.length > 0) tileBackground.color = colors[0]
213
/* This just adds some shiny effect to the tile */
218
source: "artwork/round_shine_54x54.png"
219
sourceSize.width: item.tileSize
220
sourceSize.height: item.tileSize
225
height: 16 - border.width
227
// Using anchors the item will be 1 pixel off with respect to Unity
230
radius: height / 2 - 1
232
border.color: "white"
234
visible: launcherItem.counterVisible
237
anchors.centerIn: parent
238
font.pixelSize: parent.height - 3
239
width: parent.width - 5
240
elide: Text.ElideRight
241
horizontalAlignment: Text.AlignHCenter
243
text: launcherItem.counter
249
source: "artwork/progress_bar_trough.png"
250
anchors.verticalCenter: parent.verticalCenter
251
anchors.left: parent.left
253
state: launcherItem.progressBarVisible ? "" : "hidden"
257
source: "artwork/progress_bar_fill.png"
258
anchors.verticalCenter: parent.verticalCenter
260
width: sourceSize.width * launcherItem.progress
263
NumberAnimation { duration: 200; easing.type: Easing.InOutSine }
268
NumberAnimation { duration: 200; easing.type: Easing.InOutSine }
277
// This, combined with anchors.left: parent.left in the default state
278
// makes the bar seem to come in from the left and go away at the right
281
anchors.left: undefined
282
anchors.right: tile.right
289
anchors.centerIn: parent
290
color: "#B3000000" // 0.7 opacity on black
297
anchors.centerIn: parent
304
anchors.left: parent.left
305
anchors.top: parent.top
306
visible: launcherItem.emblemVisible && !counter.visible
310
/* The entire tile will "shake" when the window is marked as "urgent", to attract
311
the user's attention */
139
312
SequentialAnimation {
141
NumberAnimation { target: container; property: "rotation"; to: 15; duration: 150 }
142
NumberAnimation { target: container; property: "rotation"; to: -15; duration: 150 }
144
NumberAnimation { target: container; property: "rotation"; to: 0; duration: 75 }
162
width: sourceSize.width
163
height: sourceSize.height
164
anchors.rightMargin: -2
165
anchors.right: container.left
166
anchors.verticalCenter: container.verticalCenter
167
opacity: running ? 1.0 : 0.0
168
source: urgent ? "/usr/share/unity/themes/application-running-notify.png" : "/usr/share/unity/themes/application-running.png"
170
Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}}
177
width: sourceSize.width
178
height: sourceSize.height
179
anchors.leftMargin: -2
180
anchors.left: container.right
181
anchors.verticalCenter: container.verticalCenter
182
opacity: active ? 1.0 : 0.0
183
source: "/usr/share/unity/themes/application-selected.png"
185
Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}}
192
wrapMode: Text.WordWrap
193
horizontalAlignment: Text.AlignHCenter
194
anchors.top: parent.bottom
196
anchors.right: parent.right
197
anchors.bottom: parent.bottom
198
anchors.left: parent.left
199
font.underline: parent.focus
316
SequentialAnimation {
318
NumberAnimation { target: tile; property: "rotation"; to: 15; duration: 150 }
319
NumberAnimation { target: tile; property: "rotation"; to: -15; duration: 150 }
321
NumberAnimation { target: tile; property: "rotation"; to: 0; duration: 75 }
329
acceptedButtons: Qt.LeftButton | Qt.RightButton
330
onClicked: item.clicked(mouse)
331
onEntered: item.entered()
332
onExited: item.exited()
338
when: (dnd.currentId != "") && (dnd.currentId == item.desktopFile)
341
/* item.parent is the delegate, and its parent is the LauncherList */
342
y: dnd.listCoordinates.y - item.parent.parent.contentY - tile.height / 2
343
/* When dragging an item, stack it on top of all its siblings */
348
enabled: (looseItem.state != "beingDragged") && !item.parent.parent.moving && !item.parent.parent.autoScrolling
351
easing.type: Easing.OutBack