Merge lp:~zsombi/ubuntu-ui-toolkit/scrollbar-delegate-fix into lp:~ui-toolkit/ubuntu-ui-toolkit/trunk

Proposed by Zsombor Egri
Status: Superseded
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/scrollbar-delegate-fix
Merge into: lp:~ui-toolkit/ubuntu-ui-toolkit/trunk
Diff against target: 1434 lines (+462/-491)
14 files modified
CHANGES (+14/-0)
debian/changelog (+6/-0)
demos/ScrollBars.qml (+7/-15)
modules/Ubuntu/Components/ModelSectionCounter.qml (+63/-36)
modules/Ubuntu/Components/plugin/shapeitem.cpp (+70/-64)
modules/Ubuntu/Components/plugin/shapeitem.h (+3/-4)
modules/Ubuntu/Components/qmldir (+2/-1)
modules/Ubuntu/Components/scrollbarUtils.js (+127/-0)
tests/unit/tst_components/tst_modelsectioncounter.qml (+66/-29)
tests/unit/tst_components/tst_scrollbar.qml (+0/-98)
themes/Ambiance/qmltheme/ScrollSliderSizer.qml (+0/-55)
themes/Ambiance/qmltheme/ScrollbarDelegate.qml (+99/-133)
themes/Ambiance/qmltheme/ScrollbarStyle.qml (+0/-54)
themes/Ambiance/qmltheme/default.qmltheme (+5/-2)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/scrollbar-delegate-fix
Reviewer Review Type Date Requested Status
Gerry Boland (community) Needs Fixing
Review via email: mp+142303@code.launchpad.net

This proposal has been superseded by a proposal from 2013-01-09.

Commit message

Scrollbar slider size and positioning fix for ListViews with header, footer and sections.

Description of the change

Scrollbar slider size and positioning fix for ListViews.

To post a comment you must log in.
Revision history for this message
Gerry Boland (gerboland) wrote :

demos/ScrollBars.qml
+ highlightFollowsCurrentItem: true
+ highlightRangeMode: ListView.ApplyRange
Why needed?

Revision history for this message
Gerry Boland (gerboland) wrote :

modules/Ubuntu/Components/ModelSectionCounter.qml
- property int sectionCount: 0
+ property int count: 0
Changing API. Are we certain no projects are using this? This change necessary?

Revision history for this message
Gerry Boland (gerboland) wrote :

> modules/Ubuntu/Components/ModelSectionCounter.qml
> - property int sectionCount: 0
> + property int count: 0
> Changing API. Are we certain no projects are using this? This change
> necessary?
Sorry please ignore, I'm talking rubbish

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 04:35 PM, Gerry Boland wrote:
> modules/Ubuntu/Components/ModelSectionCounter.qml
> - property int sectionCount: 0
> + property int count: 0
> Changing API. Are we certain no projects are using this? This change necessary?
It's an internal component, there shouldn't be anybody using it.

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 04:20 PM, Gerry Boland wrote:
> demos/ScrollBars.qml
> + highlightFollowsCurrentItem: true
> + highlightRangeMode: ListView.ApplyRange
> Why needed?
I had problems when the CurrentLabelAtStart was set, and that was
solving it... Need to check it again, and will remove if it doesn't
cause problems anymore.

267. By Zsombor Egri

some comments applied. ModelSectionCounter made private. Unit test updated.

Revision history for this message
Gerry Boland (gerboland) wrote :

+++ modules/Ubuntu/Components/qmldir
+ScrollbarUtils 0.1 scrollbarUtils.js
internal?

Revision history for this message
Gerry Boland (gerboland) wrote :

+ if (flickable && flickable.hasOwnProperty("header") && !flickable.hasOwnProperty("cellWidth")) {
Feels a little shaky, no better way?

Revision history for this message
Gerry Boland (gerboland) wrote :

function sliderSize(vertical, flickable, min, max) {
It would be a little more efficient to read the values of (flickable.visibleArea[sizeRatio] and (flickable.visibleArea[posRatio] just once into variables.

Revision history for this message
Gerry Boland (gerboland) wrote :

+ The scroll and drag functions require a slider that is not having any minimum
"a slider that does not have any minimum"

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 05:19 PM, Gerry Boland wrote:
> +++ modules/Ubuntu/Components/qmldir
> +ScrollbarUtils 0.1 scrollbarUtils.js
> internal?
Nope

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 05:27 PM, Gerry Boland wrote:
> + if (flickable && flickable.hasOwnProperty("header") && !flickable.hasOwnProperty("cellWidth")) {
> Feels a little shaky, no better way?
Well, as there's no way to have type checking, that's the closest way to
differentiate ListView from Flickable and GridView...

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 05:37 PM, Gerry Boland wrote:
> function sliderSize(vertical, flickable, min, max) {
> It would be a little more efficient to read the values of (flickable.visibleArea[sizeRatio] and (flickable.visibleArea[posRatio] just once into variables.
I was thinking of creating a JSON object and store all these properties
there.. however reading these values are not that problematic, as far as
I know properties are hashed anyway... but this could be speeded up a
bit. Then I read somewhere that using too many variables may also cause
performance issues...

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 05:38 PM, Gerry Boland wrote:
> + The scroll and drag functions require a slider that is not having any minimum
> "a slider that does not have any minimum"
ack

Revision history for this message
Gerry Boland (gerboland) wrote :

+ var propContent = (vertical) ? "contentY" : "contentX";
You do this & similar in each function. It would be more elegant to have a object with a vertical property that is only changed when necessary, and private propOrigin, propContent and propPos vars based on that.

Revision history for this message
Gerry Boland (gerboland) wrote :

+++ tests/unit/tst_components/tst_modelsectioncounter.qml
+ wait(0);
I never like seeing lines like this in a test. Is it really needed?

Revision history for this message
Gerry Boland (gerboland) wrote :

Just a functional problem I've noticed when interactive=true and with a mouse. This a supported use-case?

Say for example you've a long list, so the slider is small. With my mouse, I can approach the bottom right of the list view's view and a thumb appears there. Then as a consequence if I grab the thumb, I can't scroll the list much at all.

review: Needs Information
Revision history for this message
Gerry Boland (gerboland) wrote :

+++ themes/Ambiance/qmltheme/ScrollbarDelegate.qml
+ onActiveChanged: {
+ print(drag.active)
Remove please

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote :

+ // update thump position
Typo: thumb

Revision history for this message
Juhapekka Piiroinen (juhapekka-piiroinen) wrote :

This MR needs to be resubmitted against the new trunk.

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 07:48 PM, Gerry Boland wrote:
> + var propContent = (vertical) ? "contentY" : "contentX";
> You do this & similar in each function. It would be more elegant to have a object with a vertical property that is only changed when necessary, and private propOrigin, propContent and propPos vars based on that.
Agreed... and as said in a previous post, I'll do it.

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 07:51 PM, Gerry Boland wrote:
> +++ tests/unit/tst_components/tst_modelsectioncounter.qml
> + wait(0);
> I never like seeing lines like this in a test. Is it really needed?
I had that line there because previously the test had only one type of
model, and was filled in a loop upon component completion. In those
cases you need to get the event loop executed somehow, and wait(0) does
that, so the model gets updated for the next line of execution. It is no
longer needed, so I'll remove it.

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 07:59 PM, Gerry Boland wrote:
> Review: Needs Fixing
>
> +++ themes/Ambiance/qmltheme/ScrollbarDelegate.qml
> + onActiveChanged: {
> + print(drag.active)
> Remove please
already removed.

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 08:00 PM, Gerry Boland wrote:
> + // update thump position
> Typo: thumb
ack

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/08/2013 07:55 PM, Gerry Boland wrote:
> Review: Needs Information
>
> Just a functional problem I've noticed when interactive=true and with a mouse. This a supported use-case?
>
> Say for example you've a long list, so the slider is small. With my mouse, I can approach the bottom right of the list view's view and a thumb appears there. Then as a consequence if I grab the thumb, I can't scroll the list much at all.
This is the way Scrollbars work in Ubuntu now. The way our Scrollbar
works was taken from Marumbi, and the functionality was kept as was
there. If we need to follow the current behavior, then I have to change
it again, as currently the thumb is just a decoration during dragging.

Revision history for this message
Gerry Boland (gerboland) wrote :

> On 01/08/2013 05:19 PM, Gerry Boland wrote:
> > +++ modules/Ubuntu/Components/qmldir
> > +ScrollbarUtils 0.1 scrollbarUtils.js
> > internal?
> Nope
Why?

268. By Zsombor Egri

second wave of comments applied

Revision history for this message
Gerry Boland (gerboland) wrote :

> On 01/08/2013 07:55 PM, Gerry Boland wrote:
> > Review: Needs Information
> >
> > Just a functional problem I've noticed when interactive=true and with a
> mouse. This a supported use-case?
> >
> > Say for example you've a long list, so the slider is small. With my mouse, I
> can approach the bottom right of the list view's view and a thumb appears
> there. Then as a consequence if I grab the thumb, I can't scroll the list much
> at all.
> This is the way Scrollbars work in Ubuntu now. The way our Scrollbar
> works was taken from Marumbi, and the functionality was kept as was
> there. If we need to follow the current behavior, then I have to change
> it again, as currently the thumb is just a decoration during dragging.

Ok let's leave it out of this MR, as I think it needs to be considered separately.

269. By Zsombor Egri

trunk merge

Revision history for this message
Zsombor Egri (zsombi) wrote :

On 01/09/2013 04:00 PM, Gerry Boland wrote:
>> On 01/08/2013 05:19 PM, Gerry Boland wrote:
>>> +++ modules/Ubuntu/Components/qmldir
>>> +ScrollbarUtils 0.1 scrollbarUtils.js
>>> internal?
>> Nope
> Why?
if you happen to create a new delegate, these utility funtions can be
used, so need to be public.

270. By Zsombor Egri

interactive turned off, animations fixed

Unmerged revisions

270. By Zsombor Egri

interactive turned off, animations fixed

269. By Zsombor Egri

trunk merge

268. By Zsombor Egri

second wave of comments applied

267. By Zsombor Egri

some comments applied. ModelSectionCounter made private. Unit test updated.

266. By Zsombor Egri

trunk merge

265. By Zsombor Egri

documentation fixes

264. By Zsombor Egri

test scrollbar delegate removed

263. By Zsombor Egri

section and model counting not needed anymore for proper scrollbar slider sizing and positioning

262. By Zsombor Egri

leftover code

261. By Zsombor Egri

trunk merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CHANGES'
2--- CHANGES 2013-01-07 18:28:42 +0000
3+++ CHANGES 2013-01-09 14:06:21 +0000
4@@ -15,6 +15,20 @@
5 API Changes
6 ***********
7
8+* None
9+
10+
11+SDK 0.1.25
12+##########
13+
14+Compatibility Breaks
15+********************
16+
17+* None
18+
19+API Changes
20+***********
21+
22 * Removed UbuntuShape::borderSource and UbuntuShape::maskSource. That API in
23 this form reveals to be too difficult to maintain while keeping an efficient
24 implementation. In the future, we plan to expose these features through
25
26=== modified file 'debian/changelog'
27--- debian/changelog 2012-12-21 09:37:46 +0000
28+++ debian/changelog 2013-01-09 14:06:21 +0000
29@@ -1,3 +1,9 @@
30+qt-components-ubuntu (0.1.25) quantal; urgency=low
31+
32+ * New release
33+
34+ -- Florian Boucault <florian.boucault@canonical.com> Tue, 08 Jan 2013 18:46:47 +0000
35+
36 qt-components-ubuntu (0.1.24) quantal; urgency=low
37
38 * New release
39
40=== modified file 'demos/ScrollBars.qml'
41--- demos/ScrollBars.qml 2012-12-13 08:24:38 +0000
42+++ demos/ScrollBars.qml 2013-01-09 14:06:21 +0000
43@@ -77,20 +77,12 @@
44
45 section.property: "title"
46 section.criteria: ViewSection.FirstCharacter
47- section.delegate: Header {
48- text: "Section - " + section
49- }
50-
51- delegate: Standard {
52- text: "Data - " + label
53- }
54-
55- header: Header {
56- text: "List header"
57- }
58- footer: Header {
59- text: "List footer"
60- }
61+ section.labelPositioning: ViewSection.CurrentLabelAtStart | ViewSection.InlineLabels
62+
63+ section.delegate: Header { text: "Section - " + section }
64+ delegate: Standard { text: "Data - " + label }
65+ header: Header { text: "List header" }
66+ footer: Header { text: "List footer" }
67 }
68 ListModel {
69 id: listModel
70@@ -99,7 +91,7 @@
71 listModel.append({"title": i, "label": i})
72 }
73 }
74- }
75+ }
76
77 Scrollbar {
78 flickableItem: listView
79
80=== modified file 'modules/Ubuntu/Components/ModelSectionCounter.qml'
81--- modules/Ubuntu/Components/ModelSectionCounter.qml 2012-11-30 17:39:06 +0000
82+++ modules/Ubuntu/Components/ModelSectionCounter.qml 2013-01-09 14:06:21 +0000
83@@ -25,6 +25,7 @@
84 */
85
86 Object {
87+ id: counter
88
89 /*!
90 \preliminary
91@@ -36,13 +37,13 @@
92 \preliminary
93 The property contains the section counts of the given view.
94 */
95- property int sectionCount: 0
96+ property int count: 0
97
98 /*!
99 \preliminary
100 The property contains the section Item height.
101 */
102- property real sectionHeight: 0
103+ readonly property alias sectionHeight: internals.sectionHeight
104
105 /*!
106 \preliminary
107@@ -57,10 +58,19 @@
108 This property holds the cached sections when the cacheSections property is set, and
109 is an empty list when no caching is requested.
110 */
111- property var sectionCache: []
112+ property var cache: []
113+
114+ /*!
115+ \internal
116+ */
117+ onCacheSectionsChanged: internals.checkSections()
118
119 QtObject {
120 id: internals
121+
122+ property real sectionHeight: (count > 0 && view.section.delegate) ?
123+ QuickUtils.modelDelegateHeight(view.section.delegate, view.model) : 0.0
124+
125 property var myView: null
126 function disconnectPreviousView()
127 {
128@@ -80,6 +90,9 @@
129
130 if (myView.model.itemsRemoved)
131 myView.model.itemsRemoved.disconnect(checkSections);
132+
133+ if (myView.section.delegateChanged)
134+ myView.section.delegateChanged.disconnect(checkSections);
135 }
136
137 function initSectionCounter()
138@@ -99,38 +112,50 @@
139
140 if (myView.model.itemsRemoved)
141 myView.model.itemsRemoved.connect(checkSections);
142+
143+ if (myView.section.delegateChanged)
144+ myView.section.delegateChanged.connect(checkSections);
145+
146+ // finally check sections
147+ checkSections();
148 }
149
150 function checkSections()
151 {
152- if (undefined === view.section.property || "" === view.section.property)
153- return;
154- function sectionString(str)
155- {
156- return (view.section.criteria === ViewSection.FirstCharacter) ? str.charAt(0) : str;
157- }
158-
159 var sections = 0, sectionStack = [];
160- var current = "",
161- prop = view.section.property,
162- item, section = "";
163- for (var i = 0, count = (typeof view.model.count === 'undefined' ? view.model.length : view.model.count); i < count; i++) {
164- item = view.model.get(i);
165- section = sectionString(JSON.stringify(item[prop])).toLowerCase();
166- if (section !== current) {
167- current = section;
168- sections++;
169- if (cacheSections)
170- sectionStack.push(current);
171+ if (view && view.section && undefined !== view.section.property && "" !== view.section.property) {
172+ function sectionString(str)
173+ {
174+ if (str === undefined)
175+ return "";
176+ return (view.section.criteria === ViewSection.FirstCharacter) ? str.charAt(1) : str;
177+ }
178+
179+ var current = "",
180+ prop = view.section.property,
181+ item = null, section = "",
182+ count = (typeof view.model.length === 'undefined' ? view.model.count : view.model.length);
183+ for (var i = 0; i < count; i++) {
184+ if (view.model.hasOwnProperty("get")) {
185+ item = view.model.get(i);
186+ section = sectionString(JSON.stringify(item[prop])).toLowerCase();
187+ } else {
188+ item = view.model[i];
189+ if (item.hasOwnProperty(prop))
190+ section = sectionString(JSON.stringify(item[prop])).toLowerCase();
191+ else
192+ section = sectionString(JSON.stringify(item)).toLowerCase();
193+ }
194+ if (section !== current) {
195+ current = section;
196+ sections++;
197+ if (cacheSections)
198+ sectionStack.push(current);
199+ }
200 }
201 }
202- if (sectionCount != sections && sectionCount <= 0 && sections > 0) {
203- sectionHeight = QuickUtils.modelDelegateHeight(view.section.delegate, view.model);
204- } else if (sections <= 0)
205- sectionHeight = 0;
206-
207- sectionCount = sections;
208- sectionCache = sectionStack;
209+ counter.count = sections;
210+ counter.cache = sectionStack;
211 }
212 }
213
214@@ -138,14 +163,16 @@
215
216 onViewChanged: {
217 internals.disconnectPreviousView()
218- if (view && view.model) {
219- internals.initSectionCounter();
220- } else if (view) {
221- view.modelChanged.connect(function()
222- {
223- if (view.model)
224- internals.initSectionCounter();
225- });
226+ if (view && view.hasOwnProperty("model")) {
227+ if (view && view.model) {
228+ internals.initSectionCounter();
229+ } else if (view) {
230+ view.modelChanged.connect(function()
231+ {
232+ if (view && view.model)
233+ internals.initSectionCounter();
234+ });
235+ }
236 }
237 }
238 }
239
240=== modified file 'modules/Ubuntu/Components/plugin/shapeitem.cpp'
241--- modules/Ubuntu/Components/plugin/shapeitem.cpp 2013-01-08 02:51:09 +0000
242+++ modules/Ubuntu/Components/plugin/shapeitem.cpp 2013-01-09 14:06:21 +0000
243@@ -266,7 +266,6 @@
244 QSGNode* ShapeItem::updatePaintNode(QSGNode* old_node, UpdatePaintNodeData* data)
245 {
246 Q_UNUSED(data);
247- bool setPosition = false;
248
249 // FIXME(loicm) Shape textures are stored in the read-only data section of the plugin as it
250 // avoids having to deal with paths for now. It should preferably be loaded from a file.
251@@ -286,55 +285,43 @@
252 node = new ShapeNode(this);
253 }
254
255- // Update dirty parameters.
256 ShapeTexturedMaterial* texturedMaterial = node->texturedMaterial();
257 ShapeColoredMaterial* coloredMaterial = node->coloredMaterial();
258- if (dirtyFlags_ & ShapeItem::DirtyBaseColor)
259- coloredMaterial->setBaseColor(baseColor_);
260- if (dirtyFlags_ & ShapeItem::DirtyGradientColor)
261- coloredMaterial->setGradientColor(gradientColor_);
262- if (dirtyFlags_ & (ShapeItem::DirtyBorder | ShapeItem::DirtyRadius
263- | ShapeItem::DirtyGridUnit)) {
264- TextureData* textureData = (gridUnit_ > lowHighTextureThreshold) ?
265- &shapeTextureHigh : &shapeTextureLow;
266- node->setShapeCoordinate(border_, radius_, textureData);
267- }
268- if (dirtyFlags_ & (ShapeItem::DirtyGeometry | ShapeItem::DirtyRadius
269- | ShapeItem::DirtyStretched | ShapeItem::DirtyHAlignment
270- | ShapeItem::DirtyVAlignment | ShapeItem::DirtyGridUnit)) {
271- setPosition = true;
272- }
273- if (dirtyFlags_ & ShapeItem::DirtyImage) {
274- texturedMaterial->setImage(image_);
275- node->setMaterialType(image_ ? ShapeNode::TexturedMaterial : ShapeNode::ColoredMaterial);
276- setPosition = true;
277- }
278- dirtyFlags_ = ShapeItem::NotDirty;
279-
280- if (setPosition) {
281- int scaledDown = 0;
282- TextureData* textureData = (gridUnit_ > lowHighTextureThreshold) ?
283- &shapeTextureHigh : &shapeTextureLow;
284- // Get the radius considering the current grid unit and the texture raster grid unit.
285- float radius = (radius_ == ShapeItem::SmallRadius) ?
286- textureData->smallRadius : textureData->mediumRadius;
287- const float scaleFactor = gridUnit_ / textureData->gridUnit;
288- radius *= scaleFactor;
289- if (scaleFactor != 1.0f) {
290- scaledDown |= 1;
291- }
292- // When the item size is less than 2 radii, the radius is scaled down anyhow.
293- const float halfMinWidthHeight = qMin(geometry_.width(), geometry_.height()) * 0.5f;
294- if (radius > halfMinWidthHeight) {
295- radius = halfMinWidthHeight;
296- scaledDown |= 1;
297- }
298- // Set the shape texture to be used depending on current grid unit.
299- coloredMaterial->setShapeTexture(textureData->texture, !!scaledDown);
300- texturedMaterial->setShapeTexture(textureData->texture, !!scaledDown);
301- // Update vertex position and shape coordinate attributes.
302- node->setPosition(geometry_, radius, image_, stretched_, hAlignment_, vAlignment_);
303- }
304+ TextureData* textureData = (gridUnit_ > lowHighTextureThreshold) ?
305+ &shapeTextureHigh : &shapeTextureLow;
306+
307+ // Set the shape texture to be used by the materials depending on current grid unit. The radius
308+ // is set considering the current grid unit and the texture raster grid unit. When the item size
309+ // is less than 2 radii, the radius is scaled down anyhow.
310+ float radius = (radius_ == ShapeItem::SmallRadius) ?
311+ textureData->smallRadius : textureData->mediumRadius;
312+ const float scaleFactor = gridUnit_ / textureData->gridUnit;
313+ radius *= scaleFactor;
314+ int scaledDown = 0;
315+ if (scaleFactor != 1.0f) {
316+ scaledDown |= 1;
317+ }
318+ const float halfMinWidthHeight = qMin(geometry_.width(), geometry_.height()) * 0.5f;
319+ if (radius > halfMinWidthHeight) {
320+ radius = halfMinWidthHeight;
321+ scaledDown |= 1;
322+ }
323+ coloredMaterial->setShapeTexture(textureData->texture, !!scaledDown);
324+ texturedMaterial->setShapeTexture(textureData->texture, !!scaledDown);
325+
326+ // Update the other material properties.
327+ coloredMaterial->setBaseColor(baseColor_);
328+ coloredMaterial->setGradientColor(gradientColor_);
329+ texturedMaterial->setImage(image_);
330+
331+ // Update node vertices and type.
332+ int index = (border_ == ShapeItem::RawBorder) ?
333+ 0 : (border_ == ShapeItem::IdleBorder) ? 1 : 2;
334+ if (radius_ == ShapeItem::SmallRadius)
335+ index += 3;
336+ node->setVertices(geometry_, radius, image_, stretched_, hAlignment_, vAlignment_,
337+ textureData->coordinate[index]);
338+ node->setMaterialType(image_ ? ShapeNode::TexturedMaterial : ShapeNode::ColoredMaterial);
339
340 return node;
341 }
342@@ -357,8 +344,9 @@
343 setFlag(UsePreprocess, false);
344 }
345
346-void ShapeNode::setPosition(const QRectF& geometry, float radius, QQuickItem* image, bool stretched,
347- ShapeItem::HAlignment hAlignment, ShapeItem::VAlignment vAlignment)
348+void ShapeNode::setVertices(const QRectF& geometry, float radius, QQuickItem* image, bool stretched,
349+ ShapeItem::HAlignment hAlignment, ShapeItem::VAlignment vAlignment,
350+ float shapeCoordinate[][2])
351 {
352 ShapeNode::Vertex* vertices = reinterpret_cast<ShapeNode::Vertex*>(geometry_.vertexData());
353 const QSGTextureProvider* provider = image ? image->textureProvider() : NULL;
354@@ -410,92 +398,110 @@
355 // Set top row of 4 vertices.
356 vertices[0].position[0] = 0.0f;
357 vertices[0].position[1] = 0.0f;
358+ vertices[0].shapeCoordinate[0] = shapeCoordinate[0][0];
359+ vertices[0].shapeCoordinate[1] = shapeCoordinate[0][1];
360 vertices[0].imageCoordinate[0] = leftCoordinate;
361 vertices[0].imageCoordinate[1] = topCoordinate;
362 vertices[1].position[0] = radius;
363 vertices[1].position[1] = 0.0f;
364+ vertices[1].shapeCoordinate[0] = shapeCoordinate[1][0];
365+ vertices[1].shapeCoordinate[1] = shapeCoordinate[1][1];
366 vertices[1].imageCoordinate[0] = radiusCoordinateWidth;
367 vertices[1].imageCoordinate[1] = topCoordinate;
368 vertices[2].position[0] = width - radius;
369 vertices[2].position[1] = 0.0f;
370+ vertices[2].shapeCoordinate[0] = shapeCoordinate[2][0];
371+ vertices[2].shapeCoordinate[1] = shapeCoordinate[2][1];
372 vertices[2].imageCoordinate[0] = rightCoordinate - radiusCoordinateWidth;
373 vertices[2].imageCoordinate[1] = topCoordinate;
374 vertices[3].position[0] = width;
375 vertices[3].position[1] = 0.0f;
376+ vertices[3].shapeCoordinate[0] = shapeCoordinate[3][0];
377+ vertices[3].shapeCoordinate[1] = shapeCoordinate[3][1];
378 vertices[3].imageCoordinate[0] = rightCoordinate;
379 vertices[3].imageCoordinate[1] = topCoordinate;
380
381 // Set middle-top row of 4 vertices.
382 vertices[4].position[0] = 0.0f;
383 vertices[4].position[1] = radius;
384+ vertices[4].shapeCoordinate[0] = shapeCoordinate[4][0];
385+ vertices[4].shapeCoordinate[1] = shapeCoordinate[4][1];
386 vertices[4].imageCoordinate[0] = leftCoordinate;
387 vertices[4].imageCoordinate[1] = topCoordinate + radiusCoordinateHeight;
388 vertices[5].position[0] = radius;
389 vertices[5].position[1] = radius;
390+ vertices[5].shapeCoordinate[0] = shapeCoordinate[5][0];
391+ vertices[5].shapeCoordinate[1] = shapeCoordinate[5][1];
392 vertices[5].imageCoordinate[0] = leftCoordinate + radiusCoordinateWidth;
393 vertices[5].imageCoordinate[1] = topCoordinate + radiusCoordinateHeight;
394 vertices[6].position[0] = width - radius;
395 vertices[6].position[1] = radius;
396+ vertices[6].shapeCoordinate[0] = shapeCoordinate[6][0];
397+ vertices[6].shapeCoordinate[1] = shapeCoordinate[6][1];
398 vertices[6].imageCoordinate[0] = rightCoordinate - radiusCoordinateWidth;
399 vertices[6].imageCoordinate[1] = topCoordinate + radiusCoordinateHeight;
400 vertices[7].position[0] = width;
401 vertices[7].position[1] = radius;
402+ vertices[7].shapeCoordinate[0] = shapeCoordinate[7][0];
403+ vertices[7].shapeCoordinate[1] = shapeCoordinate[7][1];
404 vertices[7].imageCoordinate[0] = rightCoordinate;
405 vertices[7].imageCoordinate[1] = topCoordinate + radiusCoordinateHeight;
406
407 // Set middle-bottom row of 4 vertices.
408 vertices[8].position[0] = 0.0f;
409 vertices[8].position[1] = height - radius;
410+ vertices[8].shapeCoordinate[0] = shapeCoordinate[8][0];
411+ vertices[8].shapeCoordinate[1] = shapeCoordinate[8][1];
412 vertices[8].imageCoordinate[0] = leftCoordinate;
413 vertices[8].imageCoordinate[1] = bottomCoordinate - radiusCoordinateHeight;
414 vertices[9].position[0] = radius;
415 vertices[9].position[1] = height - radius;
416+ vertices[9].shapeCoordinate[0] = shapeCoordinate[9][0];
417+ vertices[9].shapeCoordinate[1] = shapeCoordinate[9][1];
418 vertices[9].imageCoordinate[0] = leftCoordinate + radiusCoordinateWidth;
419 vertices[9].imageCoordinate[1] = bottomCoordinate - radiusCoordinateHeight;
420 vertices[10].position[0] = width - radius;
421 vertices[10].position[1] = height - radius;
422+ vertices[10].shapeCoordinate[0] = shapeCoordinate[10][0];
423+ vertices[10].shapeCoordinate[1] = shapeCoordinate[10][1];
424 vertices[10].imageCoordinate[0] = rightCoordinate - radiusCoordinateWidth;
425 vertices[10].imageCoordinate[1] = bottomCoordinate - radiusCoordinateHeight;
426 vertices[11].position[0] = width;
427 vertices[11].position[1] = height - radius;
428+ vertices[11].shapeCoordinate[0] = shapeCoordinate[11][0];
429+ vertices[11].shapeCoordinate[1] = shapeCoordinate[11][1];
430 vertices[11].imageCoordinate[0] = rightCoordinate;
431 vertices[11].imageCoordinate[1] = bottomCoordinate - radiusCoordinateHeight;
432
433 // Set bottom row of 4 vertices.
434 vertices[12].position[0] = 0.0f;
435 vertices[12].position[1] = height;
436+ vertices[12].shapeCoordinate[0] = shapeCoordinate[12][0];
437+ vertices[12].shapeCoordinate[1] = shapeCoordinate[12][1];
438 vertices[12].imageCoordinate[0] = leftCoordinate;
439 vertices[12].imageCoordinate[1] = bottomCoordinate;
440 vertices[13].position[0] = radius;
441 vertices[13].position[1] = height;
442+ vertices[13].shapeCoordinate[0] = shapeCoordinate[13][0];
443+ vertices[13].shapeCoordinate[1] = shapeCoordinate[13][1];
444 vertices[13].imageCoordinate[0] = leftCoordinate + radiusCoordinateWidth;
445 vertices[13].imageCoordinate[1] = bottomCoordinate;
446 vertices[14].position[0] = width - radius;
447 vertices[14].position[1] = height;
448+ vertices[14].shapeCoordinate[0] = shapeCoordinate[14][0];
449+ vertices[14].shapeCoordinate[1] = shapeCoordinate[14][1];
450 vertices[14].imageCoordinate[0] = rightCoordinate - radiusCoordinateWidth;
451 vertices[14].imageCoordinate[1] = bottomCoordinate;
452 vertices[15].position[0] = width;
453 vertices[15].position[1] = height;
454+ vertices[15].shapeCoordinate[0] = shapeCoordinate[15][0];
455+ vertices[15].shapeCoordinate[1] = shapeCoordinate[15][1];
456 vertices[15].imageCoordinate[0] = rightCoordinate;
457 vertices[15].imageCoordinate[1] = bottomCoordinate;
458
459 markDirty(DirtyGeometry);
460 }
461
462-void ShapeNode::setShapeCoordinate(ShapeItem::Border border, ShapeItem::Radius radius,
463- TextureData* textureData)
464-{
465- ShapeNode::Vertex* vertices = reinterpret_cast<ShapeNode::Vertex*>(geometry_.vertexData());
466- int index = (border == ShapeItem::RawBorder) ? 0 : (border == ShapeItem::IdleBorder) ? 1 : 2;
467- if (radius == ShapeItem::SmallRadius)
468- index += 3;
469- for (int i = 0; i < 16; i++) {
470- vertices[i].shapeCoordinate[0] = textureData->coordinate[index][i][0];
471- vertices[i].shapeCoordinate[1] = textureData->coordinate[index][i][1];
472- }
473- markDirty(DirtyGeometry);
474-}
475-
476 void ShapeNode::setMaterialType(ShapeNode::MaterialType material)
477 {
478 if (currentMaterial_ != material) {
479
480=== modified file 'modules/Ubuntu/Components/plugin/shapeitem.h'
481--- modules/Ubuntu/Components/plugin/shapeitem.h 2013-01-07 07:59:56 +0000
482+++ modules/Ubuntu/Components/plugin/shapeitem.h 2013-01-09 14:06:21 +0000
483@@ -220,10 +220,9 @@
484 ShapeNode(ShapeItem* item);
485 ShapeTexturedMaterial* texturedMaterial() { return &texturedMaterial_; }
486 ShapeColoredMaterial* coloredMaterial() { return &coloredMaterial_; }
487- void setPosition(const QRectF& geometry, float radius, QQuickItem* image, bool stretched,
488- ShapeItem::HAlignment hAlignment, ShapeItem::VAlignment vAlignment);
489- void setShapeCoordinate(ShapeItem::Border border, ShapeItem::Radius radius,
490- TextureData* textureData);
491+ void setVertices(const QRectF& geometry, float radius, QQuickItem* image, bool stretched,
492+ ShapeItem::HAlignment hAlignment, ShapeItem::VAlignment vAlignment,
493+ float shapeCoordinate[][2]);
494 void setMaterialType(MaterialType material);
495
496 private:
497
498=== modified file 'modules/Ubuntu/Components/qmldir'
499--- modules/Ubuntu/Components/qmldir 2012-12-12 06:29:58 +0000
500+++ modules/Ubuntu/Components/qmldir 2013-01-09 14:06:21 +0000
501@@ -14,7 +14,7 @@
502 CheckBox 0.1 CheckBox.qml
503 Slider 0.1 Slider.qml
504 Scrollbar 0.1 Scrollbar.qml
505-ModelSectionCounter 0.1 ModelSectionCounter.qml
506+internal ModelSectionCounter ModelSectionCounter.qml
507 Object 0.1 Object.qml
508 TabButton 0.1 TabButton.qml
509 Page 0.1 Page.qml
510@@ -27,3 +27,4 @@
511 MathUtils 0.1 mathUtils.js
512 ComponentUtils 0.1 componentUtils.js
513 SliderUtils 0.1 sliderUtils.js
514+ScrollbarUtils 0.1 scrollbarUtils.js
515
516=== added file 'modules/Ubuntu/Components/scrollbarUtils.js'
517--- modules/Ubuntu/Components/scrollbarUtils.js 1970-01-01 00:00:00 +0000
518+++ modules/Ubuntu/Components/scrollbarUtils.js 2013-01-09 14:06:21 +0000
519@@ -0,0 +1,127 @@
520+/*
521+ * Copyright 2012 Canonical Ltd.
522+ *
523+ * This program is free software; you can redistribute it and/or modify
524+ * it under the terms of the GNU Lesser General Public License as published by
525+ * the Free Software Foundation; version 3.
526+ *
527+ * This program is distributed in the hope that it will be useful,
528+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
529+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
530+ * GNU Lesser General Public License for more details.
531+ *
532+ * You should have received a copy of the GNU Lesser General Public License
533+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
534+ */
535+
536+Qt.include("mathUtils.js")
537+
538+/*!
539+ \internal
540+ Object storing property names used in calculations.
541+ */
542+var _obj = {
543+ scrollbar: null,
544+ vertical: false,
545+ propOrigin: "",
546+ propContent: "",
547+ propPosRatio: "",
548+ propSizeRatio: "",
549+ propCoordinate: "",
550+ propSize: "",
551+ refresh: function () {
552+ _obj.vertical = (_obj.scrollbar.align === Qt.AlignLeading) || (_obj.scrollbar.align === Qt.AlignTrailing)
553+ _obj.propOrigin = (_obj.vertical) ? "originY" : "originX";
554+ _obj.propContent = (_obj.vertical) ? "contentY" : "contentX";
555+ _obj.propPosRatio = (_obj.vertical) ? "yPosition" : "xPosition";
556+ _obj.propSizeRatio = (_obj.vertical) ? "heightRatio" : "widthRatio";
557+ _obj.propCoordinate = (_obj.vertical) ? "y" : "x";
558+ _obj.propSize = (_obj.vertical) ? "height" : "width";
559+ }
560+}
561+
562+/*!
563+ \internal
564+ Checks whether the _obj is valid or not. Must be called in every function
565+ as those can be invoked prior to the host (delegate) component completion.
566+ */
567+function __check(sb) {
568+ if (sb !== null && (_obj.scrollbar !== sb)) {
569+ _obj.scrollbar = sb;
570+ sb.flickableItemChanged.connect(_obj.refresh);
571+ sb.alignChanged.connect(_obj.refresh);
572+ _obj.refresh();
573+ }
574+
575+ return _obj.scrollbar;
576+}
577+
578+/*!
579+ Returns whether the scrollbar is vertical or horizontal.
580+ */
581+function isVertical(scrollbar) {
582+ if (!__check(scrollbar)) return 0;
583+ return _obj.vertical;
584+}
585+
586+/*!
587+ Calculates the slider position based on the visible area's ratios.
588+ */
589+function sliderPos(scrollbar, min, max) {
590+ if (!__check(scrollbar)) return 0;
591+ return clamp(scrollbar.flickableItem.visibleArea[_obj.propPosRatio] * scrollbar.flickableItem[_obj.propSize], min, max);
592+}
593+
594+/*!
595+ Calculates the slider size for ListViews based on the visible area's position
596+ and size ratios, clamping it between min and max.
597+
598+ The function can be used in Scrollbar delegates to calculate the size of the slider.
599+ */
600+function sliderSize(scrollbar, min, max) {
601+ if (!__check(scrollbar)) return 0;
602+ var sizeRatio = scrollbar.flickableItem.visibleArea[_obj.propSizeRatio];
603+ var posRatio = scrollbar.flickableItem.visibleArea[_obj.propPosRatio];
604+ var sizeUnderflow = (sizeRatio * max) < min ? min - (sizeRatio * max) : 0
605+ var startPos = posRatio * (max - sizeUnderflow)
606+ var endPos = (posRatio + sizeRatio) * (max - sizeUnderflow) + sizeUnderflow
607+ var overshootStart = startPos < 0 ? -startPos : 0
608+ var overshootEnd = endPos > max ? endPos - max : 0
609+
610+ // overshoot adjusted start and end
611+ var adjustedStartPos = startPos + overshootStart
612+ var adjustedEndPos = endPos - overshootStart - overshootEnd
613+
614+ // final position and size of thumb
615+ var position = adjustedStartPos + min > max ? max - min : adjustedStartPos
616+ var result = (adjustedEndPos - position) < min ? min : (adjustedEndPos - position)
617+
618+ return result;
619+}
620+
621+/*!
622+ The function calculates and clamps the position to be scrolled to the minimum
623+ and maximum values.
624+
625+ The scroll and drag functions require a slider that does not have any minimum
626+ size set (meaning the minimum is set to 0.0). Implementations should consider
627+ using an invisible cursor to drag the slider and the ListView position.
628+ */
629+function scrollAndClamp(scrollbar, amount, min, max) {
630+ if (!__check(scrollbar)) return 0;
631+ return scrollbar.flickableItem[_obj.propOrigin] +
632+ clamp(scrollbar.flickableItem[_obj.propContent] - scrollbar.flickableItem[_obj.propOrigin] + amount,
633+ min, max);
634+}
635+
636+/*!
637+ The function calculates the new position of the dragged slider. The amount is
638+ relative to the contentSize, which is either the flickable's contentHeight or
639+ contentWidth or other calculated value, depending on its orientation. The pageSize
640+ specifies the visibleArea, and it is usually the heigtht/width of the scrolling area.
641+ */
642+function dragAndClamp(scrollbar, cursor, contentSize, pageSize) {
643+ if (!__check(scrollbar)) return 0;
644+ scrollbar.flickableItem[_obj.propContent] =
645+ scrollbar.flickableItem[_obj.propOrigin] + cursor[_obj.propCoordinate] * contentSize / pageSize;
646+}
647
648=== modified file 'tests/unit/tst_components/tst_modelsectioncounter.qml'
649--- tests/unit/tst_components/tst_modelsectioncounter.qml 2012-11-21 14:55:54 +0000
650+++ tests/unit/tst_components/tst_modelsectioncounter.qml 2013-01-09 14:06:21 +0000
651@@ -5,52 +5,89 @@
652 TestCase {
653 name: "ModelSectionCounterAPI"
654
655- function test_defaults()
656- {
657+ function initTestCase() {
658+ var component = Qt.createComponent(Qt.resolvedUrl("../../../modules/Ubuntu/Components/ModelSectionCounter.qml"));
659+ counter = component.createObject(parent);
660+ }
661+
662+ function test_0_defaults() {
663 compare(counter.view, null, "ModelSectionCounter does not have valid view set");
664- compare(counter.sectionCount, 0, "ModelSectionCounter default sectionCount is 0");
665+ compare(counter.count, 0, "ModelSectionCounter default sectionCount is 0");
666 compare(counter.cacheSections, false, "ModelSectionCounter does not cache sections");
667- compare(counter.sectionCache, [], "ModelSectionCounter has empty section cache list");
668- }
669-
670- function test_sectionCount()
671- {
672+ compare(counter.cache, [], "ModelSectionCounter has empty section cache list");
673+ }
674+
675+ function test_1_count_data() {
676+ return [
677+ {tag: "Empty model", model: emptyModel, sectionProperty: "label", expect: 0, expectFail: false},
678+ {tag: "ListModel", model: objectModel, sectionProperty: "label", expect: 8, expectFail: false},
679+ {tag: "StringList model", model: stringModel, sectionProperty: "modelData", expect: 8, expectFail: false},
680+ {tag: "VariantList model", model: variantModel, sectionProperty: "label", expect: 8, expectFail: false},
681+ ];
682+ }
683+
684+ function test_1_count(data) {
685+ if (data.expectFail)
686+ expectFail("", data.tag);
687+ list.model = data.model;
688+ list.section.property = data.sectionProperty;
689+ list.section.criteria = ViewSection.FirstCharacter;
690 counter.view = list;
691- compare(counter.view, list, "List not set");
692- compare(counter.sectionCount, 10, "Section count is wrong");
693+ compare(counter.count, data.expect, "Section count is wrong");
694 }
695
696- function test_sectionCache()
697- {
698+ function test_2_cache() {
699+ list.model = objectModel;
700+ list.section.property = "label";
701+ list.section.criteria = ViewSection.FirstCharacter;
702 counter.view = list;
703 counter.cacheSections = true;
704- var cache = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
705- compare(counter.sectionCache, cache, "Section cache is wrong");
706+ var cache = ["1", "2", "3", "4", "5", "6", "7", "8"];
707+ compare(counter.cache, cache, "Section cache is wrong");
708
709 counter.cacheSections = false;
710 cache = [];
711- compare(counter.sectionCache, cache, "Section cache is wrong");
712+ compare(counter.cache, cache, "Section cache is wrong");
713 }
714
715 Item {
716- ListModel {
717- id: listModel
718- Component.onCompleted: {
719- for (var i = 0; i < 10; i++) {
720- listModel.append({"label": i})
721- }
722- }
723- }
724 ListView {
725 id: list
726- model: listModel
727
728- delegate: Item{ height: 40}
729- section.property: "label"
730- section.criteria: ViewSection.FirstCharacter
731+ delegate: Item{ height: 40 }
732+ section.delegate: Item{ height: 10 }
733 }
734 }
735- ModelSectionCounter {
736- id: counter
737+
738+ property var counter
739+
740+ property var emptyModel: ListModel {}
741+
742+ property var objectModel: ListModel {
743+ ListElement {label: "1"}
744+ ListElement {label: "10"}
745+ ListElement {label: "100"}
746+ ListElement {label: "2"}
747+ ListElement {label: "3"}
748+ ListElement {label: "4"}
749+ ListElement {label: "5"}
750+ ListElement {label: "6"}
751+ ListElement {label: "7"}
752+ ListElement {label: "8"}
753 }
754+
755+ property var variantModel: [
756+ {"label": "1"},
757+ {"label": "10"},
758+ {"label": "100"},
759+ {"label": "2"},
760+ {"label": "3"},
761+ {"label": "4"},
762+ {"label": "5"},
763+ {"label": "6"},
764+ {"label": "7"},
765+ {"label": "8"}
766+ ]
767+
768+ property var stringModel: ["1", "10", "100", "2", "3", "4", "5", "6", "7", "8"]
769 }
770
771=== modified file 'tests/unit/tst_components/tst_scrollbar.qml'
772--- tests/unit/tst_components/tst_scrollbar.qml 2012-12-13 12:06:13 +0000
773+++ tests/unit/tst_components/tst_scrollbar.qml 2013-01-09 14:06:21 +0000
774@@ -64,61 +64,6 @@
775 }
776 }
777
778- function test_scrollbar_height_with_ListView_data() {
779- return [
780- {tag: "Empty model", model: emptyModel, expect: 0, expectFail: false},
781- {tag: "Empty model + header", model: emptyModel, header: headerFooter, expect: 20, expectFail: false},
782- {tag: "Empty model + header + footer", model: emptyModel, header: headerFooter, footer: headerFooter, expect: 40, expectFail: false},
783- {tag: "Empty model + header + footer + section (inline)", model: emptyModel, header: headerFooter, footer: headerFooter, section: section, expect: 40, expectFail: false},
784- {tag: "Empty model + header + footer + section (top)", model: emptyModel, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.CurrentLabelAtStart, expect: 40, expectFail: false},
785- {tag: "Empty model + header + footer + section (bottom)", model: emptyModel, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.NextLabelAtEnd, expect: 40, expectFail: false},
786- {tag: "Empty model + header + footer + section (top+bottom)", model: emptyModel, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.CurrentLabelAtStart | ViewSection.NextLabelAtEnd, expect: 40, expectFail: false},
787-
788- {tag: "ObjectList model", model: objectList, expect: 150, expectFail: false},
789- {tag: "ObjectList model + header", model: objectList, header: headerFooter, expect: 170, expectFail: false},
790- {tag: "ObjectList model + header + footer", model: objectList, header: headerFooter, footer: headerFooter, expect: 190, expectFail: false},
791- {tag: "ObjectList model + header + footer + section (inline)", model: objectList, header: headerFooter, footer: headerFooter, section: section, expect: 290, expectFail: true},
792- {tag: "ObjectList model + header + footer + section (top)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.CurrentLabelAtStart, expect: 190, expectFail: false},
793- {tag: "ObjectList model + header + footer + section (bottom)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.NextLabelAtEnd, expect: 190, expectFail: false},
794- {tag: "ObjectList model + header + footer + section (top+bottom)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.CurrentLabelAtStart | ViewSection.NextLabelAtEnd, expect: 190, expectFail: false},
795-
796- {tag: "VariantList model", model: objectList, expect: 150, expectFail: false},
797- {tag: "VariantList model + header", model: objectList, header: headerFooter, expect: 170, expectFail: false},
798- {tag: "VariantList model + header + footer", model: objectList, header: headerFooter, footer: headerFooter, expect: 190, expectFail: false},
799- {tag: "VariantList model + header + footer + section (inline)", model: objectList, header: headerFooter, footer: headerFooter, section: section, expect: 290, expectFail: true},
800- {tag: "VariantList model + header + footer + section (top)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.CurrentLabelAtStart, expect: 190, expectFail: false},
801- {tag: "VariantList model + header + footer + section (bottom)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.NextLabelAtEnd, expect: 190, expectFail: false},
802- {tag: "VariantList model + header + footer + section (top+bottom)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.CurrentLabelAtStart | ViewSection.NextLabelAtEnd, expect: 190, expectFail: false},
803-
804- {tag: "StringList model", model: objectList, expect: 150, expectFail: false},
805- {tag: "StringList model + header", model: objectList, header: headerFooter, expect: 170, expectFail: false},
806- {tag: "StringList model + header + footer", model: objectList, header: headerFooter, footer: headerFooter, expect: 190, expectFail: false},
807- {tag: "StringList model + header + footer + section (inline)", model: objectList, header: headerFooter, footer: headerFooter, section: section, expect: 290, expectFail: true},
808- {tag: "StringList model + header + footer + section (top)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.CurrentLabelAtStart, expect: 190, expectFail: false},
809- {tag: "StringList model + header + footer + section (bottom)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.NextLabelAtEnd, expect: 190, expectFail: false},
810- {tag: "StringList model + header + footer + section (top+bottom)", model: objectList, header: headerFooter, footer: headerFooter, section: section, sectionPositioning: ViewSection.CurrentLabelAtStart | ViewSection.NextLabelAtEnd, expect: 190, expectFail: false},
811- ];
812- }
813-
814- function test_scrollbar_height_with_ListView(data) {
815- if (data.expectFail)
816- expectFail("", data.tag);
817-
818- // set data
819- listView.model = data["model"] ? data.model : null;
820- listView.header = data["header"] ? data.header : null;
821- listView.footer = data["footer"] ? data.footer : null;
822- listView.section.property = "label";
823- listView.section.criteria = ViewSection.FirstCharacter;
824- listView.section.labelPositioning = data["sectionPositioning"] ? data.sectionPositioning : ViewSection.InlineLabels;
825- listView.section.delegate = data["section"] ? data.section : null;
826- scrollbar.flickableItem = listView;
827-
828- wait(200);
829-
830- compare(scrollbar.ItemStyle.delegate.contentSize, data.expect, data.tag);
831- }
832-
833 Rectangle {
834 id: nonFlickable
835 }
836@@ -129,9 +74,6 @@
837
838 ListView {
839 id: listView
840- delegate: Item {
841- height: 15
842- }
843 }
844
845 Scrollbar {
846@@ -142,44 +84,4 @@
847 signalName: "styleChanged"
848 }
849 }
850-
851- Component {
852- id: headerFooter
853- Item { height: 20}
854- }
855-
856- Component {
857- id: section
858- Item { height: 10}
859- }
860-
861- property var emptyModel: ListModel {}
862-
863- property var objectList: ListModel {
864- ListElement {label: "1"}
865- ListElement {label: "10"}
866- ListElement {label: "100"}
867- ListElement {label: "2"}
868- ListElement {label: "3"}
869- ListElement {label: "4"}
870- ListElement {label: "5"}
871- ListElement {label: "6"}
872- ListElement {label: "7"}
873- ListElement {label: "8"}
874- }
875-
876- property var variantList: [
877- {"label": "1"},
878- {"label": "10"},
879- {"label": "100"},
880- {"label": "2"},
881- {"label": "3"},
882- {"label": "4"},
883- {"label": "5"},
884- {"label": "6"},
885- {"label": "7"},
886- {"label": "8"}
887- ]
888-
889- property var stringList: ["1", "10", "100", "2", "3", "4", "5", "6", "7", "8", "9"]
890 }
891
892=== removed file 'themes/Ambiance/qmltheme/ScrollSliderSizer.qml'
893--- themes/Ambiance/qmltheme/ScrollSliderSizer.qml 2012-11-22 16:08:44 +0000
894+++ themes/Ambiance/qmltheme/ScrollSliderSizer.qml 1970-01-01 00:00:00 +0000
895@@ -1,55 +0,0 @@
896-/*
897- * Copyright 2012 Canonical Ltd.
898- *
899- * This program is free software; you can redistribute it and/or modify
900- * it under the terms of the GNU Lesser General Public License as published by
901- * the Free Software Foundation; version 3.
902- *
903- * This program is distributed in the hope that it will be useful,
904- * but WITHOUT ANY WARRANTY; without even the implied warranty of
905- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
906- * GNU Lesser General Public License for more details.
907- *
908- * You should have received a copy of the GNU Lesser General Public License
909- * along with this program. If not, see <http://www.gnu.org/licenses/>.
910- */
911-
912-import QtQuick 2.0
913-
914-/*!
915- \internal
916- \qmltype ScrollSliderSizer
917- \inqmlmodule Ubuntu.Components 0.1
918- \ingroup ubuntu
919- \brief Scrollbar Decorator (Slider) sizer object, provides sizing and elasticity
920- support for the slider
921- */
922-QtObject {
923- // relative (0..1) position of top and bottom
924- property real positionRatio
925- property real sizeRatio
926-
927- // max position and min size
928- property real maximumPosition
929- property real minimumSize
930-
931- // size underflow
932- property real sizeUnderflow: (sizeRatio * maximumPosition) < minimumSize ? minimumSize - (sizeRatio * maximumPosition) : 0
933-
934- // raw start and end position considering minimum size
935- property real rawStartPosition: positionRatio * (maximumPosition - sizeUnderflow)
936- property real rawEndPosition: (positionRatio + sizeRatio) * (maximumPosition - sizeUnderflow) + sizeUnderflow
937-
938- // overshoot amount at start and end
939- property real overshootStart: rawStartPosition < 0 ? -rawStartPosition : 0
940- property real overshootEnd: rawEndPosition > maximumPosition ? rawEndPosition - maximumPosition : 0
941-
942- // overshoot adjusted start and end
943- property real adjustedStartPosition: rawStartPosition + overshootStart
944- property real adjustedEndPosition: rawEndPosition - overshootStart - overshootEnd
945-
946- // final position and size of thumb
947- property int position: 0.5 + (adjustedStartPosition + minimumSize > maximumPosition ? maximumPosition - minimumSize : adjustedStartPosition)
948- property int size: 0.5 + ((adjustedEndPosition - position) < minimumSize ? minimumSize : (adjustedEndPosition - position))
949-}
950-
951
952=== modified file 'themes/Ambiance/qmltheme/ScrollbarDelegate.qml'
953--- themes/Ambiance/qmltheme/ScrollbarDelegate.qml 2012-12-13 13:42:30 +0000
954+++ themes/Ambiance/qmltheme/ScrollbarDelegate.qml 2013-01-09 14:06:21 +0000
955@@ -24,99 +24,55 @@
956 On active scrollbars, positioning is handled so that the logic updates the flickable's
957 X/Y content positions, which is then synched with the contentPosition by the main
958 element.
959+
960+ Style properties used:
961+ - interactive: bool - drives the interactive behavior of the scrollbar
962+ - minimumSliderSize: real - specifies the minimum size of the slider
963+ * overlay
964+ - overlay: bool - true if the scrollbar is overlay type
965+ - overlayOpacityWhenHidden: opacity when hidden
966+ - overlayOpacityWhenShown: opacity when shown
967+ * animations - where duration and easing properties are used only
968+ - scrollbarFadeInAnimation: PropertyAnimation - animation used when fade in
969+ - scrollbarFadeOutAnimation: PropertyAnimation - animation used when fade out
970+ - scrollbarFadeOutPause: int - miliseconds to pause before fade out
971+ * behaviors - animations are used as declared
972+ - sliderAnimation: PropertyAnimation - animation for the slider size
973+ - thumbConnectorFading: PropertyAnimation - animation for the thumb connector
974+ - thumbFading: PropertyAnimation - animation for the thumb fading
975+ * other styling properties
976+ - color sliderColor: color for the slider
977+ - color thumbConnectorColor: thumb connector color
978+ - url forwardThumbReleased: forward thumb image when released
979+ - url forwardThumbPressed: forward thumb image when pressed
980+ - url backwardThumbReleased: backward thumb image when released
981+ - url backwardThumbPressed: backward thumb image when pressed
982+ - real scrollAreaThickness: scrollbar area thickness, the area where the
983+ slider, thumb and thumb-connector appear
984+ - real thumbConnectorMargin: margin of the thumb connector aligned to the
985+ thumb visuals
986 */
987
988 Item {
989 id: visuals
990 // helper properties to ease code readability
991 property Flickable flickableItem: item.flickableItem
992- property bool interactive: item.__interactive
993+ property bool interactive: StyleUtils.itemStyleProperty("interactive", false)
994 property bool isScrollable: item.__private.scrollable && pageSize > 0.0
995 && contentSize > 0.0 && contentSize > pageSize
996- property bool isVertical: (item.__private.vertical)
997+ property bool isVertical: ScrollbarUtils.isVertical(item)
998 property bool frontAligned: (item.align === Qt.AlignLeading)
999 property bool rearAligned: (item.align === Qt.AlignTrailing)
1000 property bool topAligned: (item.align === Qt.AlignTop)
1001 property bool bottomAligned: (item.align === Qt.AlignBottom)
1002
1003 property real pageSize: (isVertical) ? item.height : item.width
1004- property real contentSize: (listView) ?
1005- listView.size :
1006- ((isVertical) ? item.flickableItem.contentHeight : item.flickableItem.contentWidth)
1007+ property real contentSize: (isVertical) ? item.flickableItem.contentHeight : item.flickableItem.contentWidth
1008 property real overlayOpacityWhenShown: StyleUtils.itemStyleProperty("overlayOpacityWhenShown", 0.6)
1009 property real overlayOpacityWhenHidden: StyleUtils.itemStyleProperty("overlayOpacityWhenHidden", 0.0)
1010 property bool overlay: StyleUtils.itemStyleProperty("overlay", false) && !interactive
1011
1012- property real contentPosition
1013- property QtObject listView: logicLoader.item
1014-
1015- /* Removing the first row of the ListView's model will render
1016- ListView.contentY invalid and therefore break the scrollbar's position.
1017- This is fixable in QtQuick 2.0 thanks to the introduction of the
1018- Flickable.originY property, however the property is not reliable enough.
1019- Therefore we compute originY manually using the fact that
1020- ListView.visibleArea.yPosition is not rendered invalid by removing the
1021- first row of the ListView's model.
1022- Unfortunately the result is not flawless when the ListView uses section
1023- headers because ListView.visibleArea.yPosition is often slightly incorrect.
1024-
1025- Ref.: https://bugreports.qt-project.org/browse/QTBUG-20927
1026- https://bugreports.qt-project.org/browse/QTBUG-21358
1027- http://doc-snapshot.qt-project.org/5.0/qml-qtquick2-flickable.html#originX-prop
1028- */
1029- property real originX: (listView) ? -item.flickableItem.contentX + Math.round(item.flickableItem.visibleArea.xPosition * contentSize) : item.flickableItem.originX
1030- property real originY: (listView) ? -item.flickableItem.contentY + Math.round(item.flickableItem.visibleArea.yPosition * contentSize) : item.flickableItem.originY
1031-
1032- // common logic for Flickable and ListView to update contentPosition when Flicked
1033- Connections {
1034- target: item.flickableItem
1035- onContentYChanged: if (isVertical) contentPosition = MathUtils.clamp(item.flickableItem.contentY - visuals.originY, 0.0, contentSize)
1036- onContentXChanged: if (!isVertical) contentPosition = MathUtils.clamp(item.flickableItem.contentX - visuals.originX, 0.0, contentSize)
1037- }
1038- // logic for ListView
1039- Component {
1040- id: listViewLogic
1041- Object {
1042- /* ListView.contentHeight is not reliable when section headers are defined.
1043- In that case we compute 'size' manually.
1044-
1045- Ref.: https://bugreports.qt-project.org/browse/QTBUG-17057
1046- https://bugreports.qt-project.org/browse/QTBUG-19941
1047- */
1048- property real size: sectionCounter.sectionCount * sectionHeight + itemsSize + spacingSize + headerSize + footerSize
1049- property int sectionHeight: sectionCounter.sectionHeight
1050- property int spacingSize: flickableItem.spacing * (flickableItem.count - 1)
1051- property int itemsSize: flickableItem.count * QuickUtils.modelDelegateHeight(flickableItem.delegate, flickableItem.model)
1052- property int headerSize: flickableItem.header ? flickableItem.headerItem.height : 0
1053- property int footerSize: flickableItem.footer ? flickableItem.footerItem.height : 0
1054-
1055- // need to capture count change otherwise the count won't be
1056- // reported for the proxy models
1057- Connections {
1058- target: flickableItem
1059- onCountChanged: itemsSize = flickableItem.count * QuickUtils.modelDelegateHeight(flickableItem.delegate, flickableItem.model)
1060- }
1061-
1062- ModelSectionCounter {
1063- id: sectionCounter
1064- view: flickableItem
1065- }
1066- }
1067- }
1068- Loader { id:logicLoader }
1069- onFlickableItemChanged: {
1070- if (flickableItem) {
1071- if (flickableItem.hasOwnProperty("header")) {
1072- // we consider Grids same as Flickables
1073- if (flickableItem.hasOwnProperty("cellWidth")) {
1074- logicLoader.sourceComponent = undefined;
1075- } else {
1076- logicLoader.sourceComponent = listViewLogic;
1077- }
1078- } else
1079- logicLoader.sourceComponent = undefined;
1080- }
1081- }
1082+ property real minimumSliderSize: StyleUtils.itemStyleProperty("minimumSliderSize", units.gu(2))
1083
1084 /*****************************************
1085 Visuals
1086@@ -135,6 +91,7 @@
1087 } else
1088 return 'shown';
1089 }
1090+ onStateChanged: print(state)
1091
1092 states: [
1093 State {
1094@@ -168,6 +125,7 @@
1095 target: visuals
1096 property: "opacity"
1097 duration: StyleUtils.itemStyleProperty("scrollbarFadeInAnimation").duration
1098+ easing: StyleUtils.itemStyleProperty("scrollbarFadeInAnimation").easing
1099 }
1100 },
1101 Transition {
1102@@ -177,6 +135,7 @@
1103 target: visuals
1104 property: "opacity"
1105 duration: StyleUtils.itemStyleProperty("scrollbarFadeInAnimation").duration
1106+ easing: StyleUtils.itemStyleProperty("scrollbarFadeInAnimation").easing
1107 }
1108 },
1109 Transition {
1110@@ -187,35 +146,20 @@
1111 NumberAnimation {
1112 target: visuals
1113 property: "opacity"
1114- //to: overlayOpacityWhenHidden
1115 duration: StyleUtils.itemStyleProperty("scrollbarFadeOutAnimation").duration
1116- easing.type: StyleUtils.itemStyleProperty("scrollbarFadeOutAnimation").easing.type
1117+ easing: StyleUtils.itemStyleProperty("scrollbarFadeOutAnimation").easing
1118 }
1119 }
1120 }
1121 ]
1122
1123- /* Scroll by amount pixels never overshooting */
1124- function scrollBy(amount) {
1125- var destination = contentPosition + amount
1126- destination += (isVertical) ? visuals.originY : visuals.originX
1127- scrollAnimation.to = MathUtils.clamp(destination, 0, contentSize - pageSize)
1128- scrollAnimation.restart()
1129- }
1130-
1131- function scrollOnePageBackward() {
1132- scrollBy(-pageSize)
1133- }
1134-
1135- function scrollOnePageForward() {
1136- scrollBy(pageSize)
1137- }
1138-
1139 function mapToPoint(map)
1140 {
1141 return Qt.point(map.x, map.y)
1142 }
1143
1144+ SystemPalette { id: systemColors }
1145+
1146 SmoothedAnimation {
1147 id: scrollAnimation
1148
1149@@ -229,7 +173,7 @@
1150 Item {
1151 id: scrollbarArea
1152
1153- property real thickness: itemStyle.scrollAreaThickness
1154+ property real thickness: StyleUtils.itemStyleProperty("scrollAreaThickness", units.dp(2))
1155 property real proximityThickness: (isVertical) ? item.width - thickness : item.height - thickness
1156 anchors {
1157 fill: parent
1158@@ -255,6 +199,7 @@
1159 enabled: isScrollable && interactive
1160 hoverEnabled: true
1161 onEntered: thumb.show();
1162+
1163 onPressed: mouse.accepted = false
1164 onClicked: mouse.accepted = false
1165 onReleased: mouse.accepted = false
1166@@ -264,10 +209,22 @@
1167 // The slider's position represents which part of the flickable is visible.
1168 // The slider's size represents the size the visible part relative to the
1169 // total size of the flickable.
1170+ Item {
1171+ id: scrollCursor
1172+ x: (isVertical) ? 0 : ScrollbarUtils.sliderPos(item, 0.0, item.width - scrollCursor.width)
1173+ y: (!isVertical) ? 0 : ScrollbarUtils.sliderPos(item, 0.0, item.height - scrollCursor.height)
1174+ width: (isVertical) ? scrollbarArea.thickness : ScrollbarUtils.sliderSize(item, 0.0, flickableItem.width)
1175+ height: (!isVertical) ? scrollbarArea.thickness : ScrollbarUtils.sliderSize(item, 0.0, flickableItem.height)
1176+
1177+ function drag() {
1178+ ScrollbarUtils.dragAndClamp(item, scrollCursor, contentSize, pageSize);
1179+ }
1180+ }
1181+
1182 Rectangle {
1183 id: slider
1184
1185- color: itemStyle.sliderColor
1186+ color: StyleUtils.itemStyleProperty("sliderColor", systemColors.highlight)
1187
1188 anchors {
1189 left: (isVertical) ? scrollbarArea.left : undefined
1190@@ -276,18 +233,10 @@
1191 bottom: (!isVertical) ? scrollbarArea.bottom : undefined
1192 }
1193
1194- x: (isVertical) ? 0 : MathUtils.clampAndProject(contentPosition, 0.0, contentSize - pageSize, 0.0, item.width - slider.width)
1195- y: (!isVertical) ? 0 : MathUtils.clampAndProject(contentPosition, 0.0, contentSize - pageSize, 0.0, item.height - slider.height)
1196- width: (isVertical) ? scrollbarArea.thickness : sliderSizer.size
1197- height: (!isVertical) ? scrollbarArea.thickness : sliderSizer.size
1198-
1199- ScrollSliderSizer {
1200- id: sliderSizer
1201- positionRatio: (isVertical) ? item.flickableItem.visibleArea.yPosition : item.flickableItem.visibleArea.xPosition
1202- sizeRatio: (isVertical) ? item.flickableItem.visibleArea.heightRatio : item.flickableItem.visibleArea.widthRatio
1203- maximumPosition: (isVertical) ? item.flickableItem.height : item.flickableItem.width
1204- minimumSize: units.gu(2)
1205- }
1206+ x: (isVertical) ? 0 : ScrollbarUtils.sliderPos(item, 0.0, item.width - slider.width)
1207+ y: (!isVertical) ? 0 : ScrollbarUtils.sliderPos(item, 0.0, item.height - slider.height)
1208+ width: (isVertical) ? scrollbarArea.thickness : ScrollbarUtils.sliderSize(item, minimumSliderSize, flickableItem.width)
1209+ height: (!isVertical) ? scrollbarArea.thickness : ScrollbarUtils.sliderSize(item, minimumSliderSize, flickableItem.height)
1210
1211 Behavior on width {
1212 enabled: (!isVertical)
1213@@ -301,12 +250,18 @@
1214 script: StyleUtils.animate("sliderAnimation")
1215 }
1216 }
1217+
1218+ function scroll(amount) {
1219+ scrollAnimation.to = ScrollbarUtils.scrollAndClamp(item, amount, 0.0, contentSize - pageSize);
1220+ scrollAnimation.restart();
1221+ }
1222 }
1223
1224 // The sliderThumbConnector ensures a visual connection between the slider and the thumb
1225 Rectangle {
1226 id: sliderThumbConnector
1227
1228+ property real thumbConnectorMargin: StyleUtils.itemStyleProperty("thumbConnectorMargin", units.dp(3))
1229 property bool isThumbAboveSlider: (isVertical) ? thumb.y < slider.y : thumb.x < slider.x
1230 anchors {
1231 left: (isVertical) ? scrollbarArea.left : (isThumbAboveSlider ? thumb.left : slider.right)
1232@@ -314,12 +269,12 @@
1233 top: (!isVertical) ? scrollbarArea.top : (isThumbAboveSlider ? thumb.top : slider.bottom)
1234 bottom: (!isVertical) ? scrollbarArea.bottom : (isThumbAboveSlider ? slider.top : thumb.bottom)
1235
1236- leftMargin : (isVertical) ? 0 : (isThumbAboveSlider ? itemStyle.thumbConnectorMargin : 0)
1237- rightMargin : (isVertical) ? 0 : (isThumbAboveSlider ? 0 : itemStyle.thumbConnectorMargin)
1238- topMargin : (!isVertical) ? 0 : (isThumbAboveSlider ? itemStyle.thumbConnectorMargin : 0)
1239- bottomMargin : (!isVertical) ? 0 : (isThumbAboveSlider ? 0 : itemStyle.thumbConnectorMargin)
1240+ leftMargin : (isVertical) ? 0 : (isThumbAboveSlider ? thumbConnectorMargin : 0)
1241+ rightMargin : (isVertical) ? 0 : (isThumbAboveSlider ? 0 : thumbConnectorMargin)
1242+ topMargin : (!isVertical) ? 0 : (isThumbAboveSlider ? thumbConnectorMargin : 0)
1243+ bottomMargin : (!isVertical) ? 0 : (isThumbAboveSlider ? 0 : thumbConnectorMargin)
1244 }
1245- color: itemStyle.thumbConnectorColor
1246+ color: StyleUtils.itemStyleProperty("thumbConnectorColor", "white")
1247 opacity: thumb.shown ? 1.0 : 0.0
1248 Behavior on opacity {animation: ScriptAction {script: StyleUtils.animate("thumbConnectorFading")}}
1249 }
1250@@ -361,46 +316,53 @@
1251 }
1252 onClicked: {
1253 if (inThumbBottom)
1254- scrollOnePageForward()
1255+ slider.scroll(pageSize)
1256 else if (inThumbTop)
1257- scrollOnePageBackward()
1258+ slider.scroll(-pageSize)
1259 }
1260
1261 // Dragging behaviour
1262 function resetDrag() {
1263+ thumbYStart = thumb.y
1264+ thumbXStart = thumb.x
1265 dragYStart = drag.target.y
1266- thumbYStart = thumb.y
1267- sliderYStart = slider.y
1268 dragXStart = drag.target.x
1269- thumbXStart = thumb.x
1270- sliderXStart = slider.x
1271 }
1272
1273- property int sliderYStart
1274 property int thumbYStart
1275 property int dragYStart
1276 property int dragYAmount: thumbArea.drag.target.y - thumbArea.dragYStart
1277- property int sliderXStart
1278 property int thumbXStart
1279 property int dragXStart
1280 property int dragXAmount: thumbArea.drag.target.x - thumbArea.dragXStart
1281 drag {
1282- target: Item {}
1283+ target: scrollCursor
1284 axis: (isVertical) ? Drag.YAxis : Drag.XAxis
1285- filterChildren: true
1286- onActiveChanged: if (drag.active) resetDrag()
1287+ minimumY: 0
1288+ maximumY: flickableItem.height - scrollCursor.height
1289+ minimumX: 0
1290+ maximumX: flickableItem.width - scrollCursor.width
1291+ onActiveChanged: {
1292+ if (drag.active) resetDrag()
1293+ }
1294 }
1295- // update flickableItem's and thumb's position
1296- // cannot use Binding as there would be a binding loop
1297+ // update thumb position
1298 onDragYAmountChanged: {
1299- var pos = MathUtils.clampAndProject(thumbArea.sliderYStart + thumbArea.dragYAmount, 0.0, item.height - slider.height, 0.0, contentSize - pageSize);
1300- item.flickableItem.contentY = MathUtils.clamp(pos + visuals.originY, 0.0, contentSize - pageSize);
1301- thumb.y = MathUtils.clamp(thumbArea.thumbYStart + thumbArea.dragYAmount, 0, thumb.maximumPos);
1302+ if (drag.active) {
1303+ thumb.y = MathUtils.clamp(thumbArea.thumbYStart + thumbArea.dragYAmount, 0, thumb.maximumPos);
1304+ }
1305 }
1306 onDragXAmountChanged: {
1307- var pos = MathUtils.clampAndProject(thumbArea.sliderXStart + thumbArea.dragXAmount, 0.0, item.width - slider.width, 0.0, contentSize - pageSize);
1308- item.flickableItem.contentX = MathUtils.clamp(pos + visuals.originX, 0.0, contentSize - pageSize);
1309- thumb.x = MathUtils.clamp(thumbArea.thumbXStart + thumbArea.dragXAmount, 0, thumb.maximumPos);
1310+ if (drag.active) {
1311+ thumb.x = MathUtils.clamp(thumbArea.thumbXStart + thumbArea.dragXAmount, 0, thumb.maximumPos);
1312+ }
1313+ }
1314+
1315+ // drag slider and content to the proper position
1316+ onPositionChanged: {
1317+ if (pressedButtons == Qt.LeftButton) {
1318+ scrollCursor.drag()
1319+ }
1320 }
1321 }
1322
1323@@ -477,17 +439,21 @@
1324 opacity: shown ? (thumbArea.containsMouse || thumbArea.drag.active ? 1.0 : 0.5) : 0.0
1325 Behavior on opacity {animation: ScriptAction {script: StyleUtils.animate("thumbFading")}}
1326
1327+ property url backwardPressed: StyleUtils.itemStyleProperty("backwardThumbPressed", "")
1328+ property url backwardReleased: StyleUtils.itemStyleProperty("backwardThumbReleased", "")
1329+ property url forwardPressed: StyleUtils.itemStyleProperty("forwardThumbPressed", "")
1330+ property url forwardReleased: StyleUtils.itemStyleProperty("forwardThumbReleased", "")
1331 Flow {
1332 // disable mirroring as thumbs are placed in the same way no matter of RTL or LTR
1333 LayoutMirroring.enabled: false
1334 flow: (isVertical) ? Flow.TopToBottom : Flow.LeftToRight
1335 Image {
1336 id: thumbTop
1337- source: thumbArea.inThumbTop && thumbArea.pressed ? itemStyle.backwardThumbPressed : itemStyle.backwardThumbReleased
1338+ source: thumbArea.inThumbTop && thumbArea.pressed ? thumb.backwardPressed : thumb.backwardReleased
1339 }
1340 Image {
1341 id: thumbBottom
1342- source: thumbArea.inThumbBottom && thumbArea.pressed ? itemStyle.forwardThumbPressed : itemStyle.forwardThumbReleased
1343+ source: thumbArea.inThumbBottom && thumbArea.pressed ? thumb.forwardPressed : thumb.forwardReleased
1344 }
1345 }
1346 }
1347
1348=== removed file 'themes/Ambiance/qmltheme/ScrollbarStyle.qml'
1349--- themes/Ambiance/qmltheme/ScrollbarStyle.qml 2012-11-29 11:41:29 +0000
1350+++ themes/Ambiance/qmltheme/ScrollbarStyle.qml 1970-01-01 00:00:00 +0000
1351@@ -1,54 +0,0 @@
1352-/*
1353- * Copyright 2012 Canonical Ltd.
1354- *
1355- * This program is free software; you can redistribute it and/or modify
1356- * it under the terms of the GNU Lesser General Public License as published by
1357- * the Free Software Foundation; version 3.
1358- *
1359- * This program is distributed in the hope that it will be useful,
1360- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1361- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1362- * GNU Lesser General Public License for more details.
1363- *
1364- * You should have received a copy of the GNU Lesser General Public License
1365- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1366- */
1367-
1368-import QtQuick 2.0
1369-
1370-QtObject {
1371- /*!
1372- This property drives the interactive behavior of the scrollbar
1373- */
1374- property bool interactive
1375-
1376- /*!
1377- Overlay: when set, opacity specified in overlayOpacity will be used;
1378- when no overlay is specuified, the scrollbar is 100% visible
1379- */
1380- property bool overlay
1381- property var overlayOpacityWhenHidden
1382- property var overlayOpacityWhenShown
1383-
1384- /*!
1385- Scrollbar animations
1386- */
1387- property PropertyAnimation scrollbarFadeInAnimation
1388- property var scrollbarFadeOutPause
1389- property PropertyAnimation scrollbarFadeOutAnimation
1390- /*!
1391- Scrollbar element animations.
1392- */
1393- property PropertyAnimation sliderAnimation
1394- property PropertyAnimation thumbConnectorFading
1395- property PropertyAnimation thumbFading
1396- property color sliderColor
1397- property color thumbConnectorColor
1398- property url forwardThumbReleased
1399- property url forwardThumbPressed
1400- property url backwardThumbReleased
1401- property url backwardThumbPressed
1402- property real sensingAreaThickness
1403- property real scrollAreaThickness
1404- property real thumbConnectorMargin
1405-}
1406
1407=== modified file 'themes/Ambiance/qmltheme/default.qmltheme'
1408--- themes/Ambiance/qmltheme/default.qmltheme 2012-12-20 09:06:37 +0000
1409+++ themes/Ambiance/qmltheme/default.qmltheme 2013-01-09 14:06:21 +0000
1410@@ -19,7 +19,7 @@
1411 @qml-mapping(.new-tabs, NewTabsStyle, NewTabsDelegate);
1412 @qml-mapping(.tab-button, TabButtonStyle, TabButtonDelegate);
1413 @qml-mapping(.custom-button, ButtonStyle, ButtonDelegate);
1414-@qml-mapping(.scrollbar, ScrollbarStyle, ScrollbarDelegate);
1415+@qml-mapping(.scrollbar, , ScrollbarDelegate);
1416 @qml-mapping (.popover-foreground, , PopoverForegroundDelegate);
1417 @qml-mapping (.sheet-foreground, , SheetForegroundDelegate);
1418 @qml-mapping (.dialog-foreground, , DialogForegroundDelegate);
1419@@ -176,7 +176,6 @@
1420 backwardThumbPressed: (item.align === Qt.AlignLeading || item.align === Qt.AlignTrailing) ? url("artwork/ScrollbarTopPressed.png") : url("artwork/ScrollbarLeftPressed.png");
1421 forwardThumbReleased: (item.align === Qt.AlignLeading || item.align === Qt.AlignTrailing) ? url("artwork/ScrollbarBottomIdle.png") : url("artwork/ScrollbarRightIdle.png");
1422 forwardThumbPressed: (item.align === Qt.AlignLeading || item.align === Qt.AlignTrailing) ? url("artwork/ScrollbarBottomPressed.png") : url("artwork/ScrollbarRightPressed.png");
1423- sensingAreaThickness: units.gu(4);
1424 scrollAreaThickness: units.dp(2);
1425 thumbConnectorMargin: units.dp(3);
1426 sliderColor: "#fc7134";
1427@@ -278,3 +277,7 @@
1428 color: "white";
1429 weight: Font.Bold;
1430 }
1431+
1432+.scrollbar {
1433+ interactive: true
1434+}

Subscribers

People subscribed via source and target branches

to all changes: