Merge lp:~brandontschaefer/unity/lp.1131646-fix into lp:unity

Proposed by Brandon Schaefer
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: no longer in the source branch.
Merged at revision: 3378
Proposed branch: lp:~brandontschaefer/unity/lp.1131646-fix
Merge into: lp:unity
Diff against target: 734 lines (+484/-24)
13 files modified
launcher/SwitcherController.cpp (+72/-0)
launcher/SwitcherController.h (+3/-0)
launcher/SwitcherControllerImpl.h (+5/-0)
launcher/SwitcherModel.cpp (+97/-0)
launcher/SwitcherModel.h (+13/-0)
launcher/SwitcherView.cpp (+1/-0)
plugins/unityshell/src/unityshell.cpp (+6/-18)
plugins/unityshell/src/unityshell.h (+2/-2)
tests/test_layout_system.cpp (+48/-0)
tests/test_switcher_controller.cpp (+71/-0)
tests/test_switcher_model.cpp (+150/-0)
unity-shared/LayoutSystem.cpp (+13/-2)
unity-shared/LayoutSystem.h (+3/-2)
To merge this branch: bzr merge lp:~brandontschaefer/unity/lp.1131646-fix
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Marco Trevisan (Treviño) Approve
Review via email: mp+169475@code.launchpad.net

Commit message

When in detail mode, you are now allowed to use UP/DOWN keys to move around.

Description of the change

When in detail mode, you are now allowed to use UP/DOWN keys to move around.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Nice work, overall it looks fine, just few things:

143 - if (detail_selection_index >= (unsigned int) 1)
232 + return (detail_selection_index > 0);

doesn't compile on raring g++... Probably we should wait a little.

478 + std::vector<LayoutWindow::Vector> rows = GetRows(windows, max_bounds);
235 +void SwitcherModel::SetRowSizes(std::vector<int> row_sizes)

Use const& please.

174 + for (unsigned int i = 0; i <= n; i++)

++i is nicer. Also you should make sure that n is < row_sizes_.size().

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

+bool Controller::HandleStartInitiateEvent()
+bool Controller::HandleStopInitiateEvent()

What about using different naming? Such {Start,Stop}DetailMode or better?

Probably it would be better to change the compiz option names also, since they generates functions that doesn't represent anymore what they say. Don't you agree?

Would be now possible to test the controller also?

133 + void NextDetailRow();
134 + void PrevDetailRow();
135 + bool HasNextDetailRow() const;
136 + bool HasPrevDetailRow() const;

Are probably not needed anymore, right (also in the impl)?

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Yeeah, but it still starts/stops detail mode. Ill try to think of a different name :). Yes, I don't have to expose those function publicily anymore, and yes it will be possible to get tests on that 2 new function. What I was going to do this morning :)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Great, I think we're fine for trunk now! :)

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'launcher/SwitcherController.cpp'
2--- launcher/SwitcherController.cpp 2013-06-14 16:10:26 +0000
3+++ launcher/SwitcherController.cpp 2013-06-18 19:07:26 +0000
4@@ -124,6 +124,46 @@
5 return visible_;
6 }
7
8+bool Controller::StartDetailMode()
9+{
10+ if (visible_)
11+ {
12+ if (IsDetailViewShown() &&
13+ impl_->HasNextDetailRow())
14+ {
15+ impl_->NextDetailRow();
16+ }
17+ else
18+ {
19+ SetDetail(true);
20+ }
21+
22+ return true;
23+ }
24+
25+ return false;
26+}
27+
28+bool Controller::StopDetailMode()
29+{
30+ if (visible_)
31+ {
32+ if (IsDetailViewShown() &&
33+ impl_->HasPrevDetailRow())
34+ {
35+ impl_->PrevDetailRow();
36+ }
37+ else
38+ {
39+ SetDetail(false);
40+ }
41+
42+ return true;
43+ }
44+
45+ return false;
46+}
47+
48 void Controller::Next()
49 {
50 impl_->Next();
51@@ -586,6 +626,38 @@
52 model_->PrevDetail();
53 }
54
55+void Controller::Impl::NextDetailRow()
56+{
57+ if (!model_)
58+ return;
59+
60+ model_->NextDetailRow();
61+}
62+
63+void Controller::Impl::PrevDetailRow()
64+{
65+ if (!model_)
66+ return;
67+
68+ model_->PrevDetailRow();
69+}
70+
71+bool Controller::Impl::HasNextDetailRow() const
72+{
73+ if (!model_)
74+ return false;
75+
76+ return model_->HasNextDetailRow();
77+}
78+
79+bool Controller::Impl::HasPrevDetailRow() const
80+{
81+ if (!model_)
82+ return false;
83+
84+ return model_->HasPrevDetailRow();
85+}
86+
87 LayoutWindow::Vector Controller::Impl::ExternalRenderTargets()
88 {
89 if (!view_)
90
91=== modified file 'launcher/SwitcherController.h'
92--- launcher/SwitcherController.h 2013-02-26 16:27:23 +0000
93+++ launcher/SwitcherController.h 2013-06-18 19:07:26 +0000
94@@ -89,6 +89,9 @@
95
96 bool Visible();
97
98+ bool StartDetailMode();
99+ bool StopDetailMode();
100+
101 void Next();
102 void Prev();
103
104
105=== modified file 'launcher/SwitcherControllerImpl.h'
106--- launcher/SwitcherControllerImpl.h 2013-02-26 16:27:23 +0000
107+++ launcher/SwitcherControllerImpl.h 2013-06-18 19:07:26 +0000
108@@ -56,6 +56,11 @@
109 void NextDetail();
110 void PrevDetail();
111
112+ void NextDetailRow();
113+ void PrevDetailRow();
114+ bool HasNextDetailRow() const;
115+ bool HasPrevDetailRow() const;
116+
117 bool IsDetailViewShown();
118 void SetDetail(bool detail, unsigned int min_windows = 1);
119
120
121=== modified file 'launcher/SwitcherModel.cpp'
122--- launcher/SwitcherModel.cpp 2013-02-14 16:26:13 +0000
123+++ launcher/SwitcherModel.cpp 2013-06-18 19:07:26 +0000
124@@ -38,6 +38,7 @@
125 , applications_(icons)
126 , index_(0)
127 , last_index_(0)
128+ , row_index_(0)
129 {
130 // When using Webapps, there are more than one active icon, so let's just pick
131 // up the first one found which is the web browser.
132@@ -183,6 +184,7 @@
133
134 detail_selection = false;
135 detail_selection_index = 0;
136+ row_index_ = 0;
137 selection_changed.emit(Selection());
138 }
139
140@@ -197,6 +199,7 @@
141
142 detail_selection = false;
143 detail_selection_index = 0;
144+ row_index_ = 0;
145 selection_changed.emit(Selection());
146 }
147
148@@ -209,6 +212,8 @@
149 detail_selection_index = detail_selection_index + 1;
150 else
151 detail_selection_index = 0;
152+
153+ UpdateRowIndex();
154 }
155
156 void SwitcherModel::PrevDetail()
157@@ -220,6 +225,98 @@
158 detail_selection_index = detail_selection_index - 1;
159 else
160 detail_selection_index = DetailXids().size() - 1;
161+
162+ UpdateRowIndex();
163+}
164+
165+void SwitcherModel::UpdateRowIndex()
166+{
167+ int current_index = detail_selection_index;
168+ unsigned int current_row = 0;
169+
170+ for (auto r : row_sizes_)
171+ {
172+ current_index -= r;
173+
174+ if (current_index < 0)
175+ {
176+ row_index_ = current_row;
177+ return;
178+ }
179+
180+ current_row++;
181+ }
182+}
183+
184+unsigned int SwitcherModel::SumNRows(unsigned int n) const
185+{
186+ unsigned int total = 0;
187+
188+ if (n < row_sizes_.size())
189+ for (unsigned int i = 0; i <= n; ++i)
190+ total += row_sizes_[i];
191+
192+ return total;
193+}
194+
195+bool SwitcherModel::DetailIndexInLeftHalfOfRow() const
196+{
197+ unsigned int half = row_sizes_[row_index_]/2;
198+ unsigned int total_above = (row_index_ > 0 ? SumNRows(row_index_ - 1) : 0);
199+ unsigned int diff = detail_selection_index - total_above;
200+
201+ return (diff < half);
202+}
203+
204+void SwitcherModel::NextDetailRow()
205+{
206+ if (HasNextDetailRow())
207+ {
208+ unsigned int current_row = row_sizes_[row_index_];
209+ unsigned int next_row = row_sizes_[row_index_ + 1];
210+ unsigned int increment = current_row;
211+
212+ if (!DetailIndexInLeftHalfOfRow())
213+ increment = next_row;
214+
215+ detail_selection_index = detail_selection_index + increment;
216+ row_index_++;
217+ }
218+}
219+
220+void SwitcherModel::PrevDetailRow()
221+{
222+ if (row_index_ > 0)
223+ {
224+ unsigned int current_row = row_sizes_[row_index_];
225+ unsigned int prev_row = row_sizes_[row_index_ - 1];
226+ unsigned int decrement = current_row;
227+
228+ if (DetailIndexInLeftHalfOfRow())
229+ decrement = prev_row;
230+
231+ detail_selection_index = detail_selection_index - decrement;
232+ row_index_--;
233+ }
234+ else
235+ {
236+ detail_selection_index = detail_selection_index - 1;
237+ }
238+}
239+
240+bool SwitcherModel::HasNextDetailRow() const
241+{
242+ return (row_sizes_.size() && row_index_ < row_sizes_.size() - 1);
243+}
244+
245+bool SwitcherModel::HasPrevDetailRow() const
246+{
247+ return (detail_selection_index > (unsigned int) 0);
248+}
249+
250+void SwitcherModel::SetRowSizes(std::vector<int> const& row_sizes)
251+{
252+ row_sizes_ = row_sizes;
253 }
254
255 void SwitcherModel::Select(AbstractLauncherIcon::Ptr const& selection)
256
257=== modified file 'launcher/SwitcherModel.h'
258--- launcher/SwitcherModel.h 2013-02-05 01:38:11 +0000
259+++ launcher/SwitcherModel.h 2013-06-18 19:07:26 +0000
260@@ -90,6 +90,13 @@
261 void NextDetail();
262 void PrevDetail();
263
264+ void NextDetailRow();
265+ void PrevDetailRow();
266+ bool HasNextDetailRow() const;
267+ bool HasPrevDetailRow() const;
268+
269+ void SetRowSizes(std::vector<int> const& row_sizes);
270+
271 void Select(launcher::AbstractLauncherIcon::Ptr const& selection);
272 void Select(unsigned int index);
273
274@@ -101,10 +108,16 @@
275 void AddProperties(GVariantBuilder* builder);
276
277 private:
278+ void UpdateRowIndex();
279+ unsigned int SumNRows(unsigned int n) const;
280+ bool DetailIndexInLeftHalfOfRow() const;
281+
282 Applications applications_;
283 unsigned int index_;
284 unsigned int last_index_;
285+ unsigned int row_index_;
286 launcher::AbstractLauncherIcon::Ptr last_active_application_;
287+ std::vector<int> row_sizes_;
288 };
289
290 }
291
292=== modified file 'launcher/SwitcherView.cpp'
293--- launcher/SwitcherView.cpp 2013-04-12 22:48:37 +0000
294+++ launcher/SwitcherView.cpp 2013-06-18 19:07:26 +0000
295@@ -277,6 +277,7 @@
296
297 nux::Geometry layout_geo;
298 layout_system_.LayoutWindows(render_targets_, max_bounds, layout_geo);
299+ model_->SetRowSizes(layout_system_.GetRowSizes(render_targets_, max_bounds));
300
301 return layout_geo;
302 }
303
304=== modified file 'plugins/unityshell/src/unityshell.cpp'
305--- plugins/unityshell/src/unityshell.cpp 2013-05-29 14:52:11 +0000
306+++ plugins/unityshell/src/unityshell.cpp 2013-06-18 19:07:26 +0000
307@@ -321,8 +321,8 @@
308 optionSetAltTabPrevAllInitiate(boost::bind(&UnityScreen::altTabPrevAllInitiate, this, _1, _2, _3));
309 optionSetAltTabPrevInitiate(boost::bind(&UnityScreen::altTabPrevInitiate, this, _1, _2, _3));
310
311- optionSetAltTabDetailStartInitiate(boost::bind(&UnityScreen::altTabDetailStartInitiate, this, _1, _2, _3));
312- optionSetAltTabDetailStopInitiate(boost::bind(&UnityScreen::altTabDetailStopInitiate, this, _1, _2, _3));
313+ optionSetAltTabDetailStartInitiate(boost::bind(&UnityScreen::altTabDetailStart, this, _1, _2, _3));
314+ optionSetAltTabDetailStopInitiate(boost::bind(&UnityScreen::altTabDetailStop, this, _1, _2, _3));
315
316 optionSetAltTabNextWindowInitiate(boost::bind(&UnityScreen::altTabNextWindowInitiate, this, _1, _2, _3));
317 optionSetAltTabNextWindowTerminate(boost::bind(&UnityScreen::altTabTerminateCommon, this, _1, _2, _3));
318@@ -1997,26 +1997,14 @@
319 return false;
320 }
321
322-bool UnityScreen::altTabDetailStartInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
323+bool UnityScreen::altTabDetailStart(CompAction* action, CompAction::State state, CompOption::Vector& options)
324 {
325- if (switcher_controller_->Visible())
326- {
327- switcher_controller_->SetDetail(true);
328- return true;
329- }
330-
331- return false;
332+ return switcher_controller_->StartDetailMode();
333 }
334
335-bool UnityScreen::altTabDetailStopInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
336+bool UnityScreen::altTabDetailStop(CompAction* action, CompAction::State state, CompOption::Vector& options)
337 {
338- if (switcher_controller_->Visible())
339- {
340- switcher_controller_->SetDetail(false);
341- return true;
342- }
343-
344- return false;
345+ return switcher_controller_->StopDetailMode();
346 }
347
348 bool UnityScreen::altTabNextWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
349
350=== modified file 'plugins/unityshell/src/unityshell.h'
351--- plugins/unityshell/src/unityshell.h 2013-05-17 22:53:57 +0000
352+++ plugins/unityshell/src/unityshell.h 2013-06-18 19:07:26 +0000
353@@ -152,8 +152,8 @@
354 bool altTabPrevInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
355 bool altTabForwardAllInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
356 bool altTabPrevAllInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
357- bool altTabDetailStartInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
358- bool altTabDetailStopInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
359+ bool altTabDetailStart(CompAction* action, CompAction::State state, CompOption::Vector& options);
360+ bool altTabDetailStop(CompAction* action, CompAction::State state, CompOption::Vector& options);
361 bool altTabNextWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
362 bool altTabPrevWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options);
363
364
365=== modified file 'tests/test_layout_system.cpp'
366--- tests/test_layout_system.cpp 2013-01-25 21:06:34 +0000
367+++ tests/test_layout_system.cpp 2013-06-18 19:07:26 +0000
368@@ -21,6 +21,8 @@
369 #include "LayoutSystem.h"
370 #include "StandaloneWindowManager.h"
371
372+#include <vector>
373+
374 namespace unity
375 {
376 namespace ui
377@@ -153,6 +155,52 @@
378 EXPECT_EQ(final_bounds.Intersect(windows_area), windows_area);
379 }
380
381+TEST_F(TestLayoutSystem, GetRowSizesEven)
382+{
383+ nux::Geometry max_bounds(0, 0, 200, 100);
384+ nux::Geometry final_bounds;
385+
386+ Window xid = 3;
387+ AddFakeWindowToWM(xid, nux::Geometry(4, 5, 200, 200));
388+ lwindows.push_back(std::make_shared<LayoutWindow>(xid));
389+
390+ xid = 4;
391+ AddFakeWindowToWM(xid, nux::Geometry(10, 20, 200, 200));
392+ lwindows.push_back(std::make_shared<LayoutWindow>(xid));
393+
394+ ls.LayoutWindows(lwindows, max_bounds, final_bounds);
395+
396+ std::vector<int> const& row_sizes = ls.GetRowSizes(lwindows, max_bounds);
397+ EXPECT_EQ(row_sizes.size(), 2);
398+ EXPECT_EQ(row_sizes[0], 2);
399+ EXPECT_EQ(row_sizes[1], 2);
400+}
401+
402+TEST_F(TestLayoutSystem, GetRowSizesUnEven)
403+{
404+ nux::Geometry max_bounds(0, 0, 200, 100);
405+ nux::Geometry final_bounds;
406+
407+ Window xid = 3;
408+ AddFakeWindowToWM(xid, nux::Geometry(4, 5, 200, 200));
409+ lwindows.push_back(std::make_shared<LayoutWindow>(xid));
410+
411+ xid = 4;
412+ AddFakeWindowToWM(xid, nux::Geometry(10, 20, 200, 200));
413+ lwindows.push_back(std::make_shared<LayoutWindow>(xid));
414+
415+ xid = 5;
416+ AddFakeWindowToWM(xid, nux::Geometry(10, 20, 200, 200));
417+ lwindows.push_back(std::make_shared<LayoutWindow>(xid));
418+
419+ ls.LayoutWindows(lwindows, max_bounds, final_bounds);
420+
421+ std::vector<int> const& row_sizes = ls.GetRowSizes(lwindows, max_bounds);
422+ EXPECT_EQ(row_sizes.size(), 2);
423+ EXPECT_EQ(row_sizes[0], 2);
424+ EXPECT_EQ(row_sizes[1], 3);
425+}
426+
427 }
428 }
429 }
430
431=== modified file 'tests/test_switcher_controller.cpp'
432--- tests/test_switcher_controller.cpp 2013-06-14 16:10:26 +0000
433+++ tests/test_switcher_controller.cpp 2013-06-18 19:07:26 +0000
434@@ -77,6 +77,77 @@
435 EXPECT_FALSE(model->detail_selection());
436 }
437
438+TEST_F(TestSwitcherController, StartDetailMode)
439+{
440+ controller_->Show(ShowMode::ALL, SortMode::LAUNCHER_ORDER, icons_);
441+ controller_->InitiateDetail();
442+ controller_->StartDetailMode();
443+
444+ EXPECT_TRUE(controller_->IsDetailViewShown());
445+}
446+
447+TEST_F(TestSwitcherController, StopDetailMode)
448+{
449+ controller_->Show(ShowMode::ALL, SortMode::LAUNCHER_ORDER, icons_);
450+ controller_->InitiateDetail();
451+
452+ controller_->StartDetailMode();
453+ EXPECT_TRUE(controller_->IsDetailViewShown());
454+
455+ controller_->StopDetailMode();
456+ EXPECT_FALSE(controller_->IsDetailViewShown());
457+}
458+
459+TEST_F(TestSwitcherController, StartDetailModeMovesNextRows)
460+{
461+ controller_->Show(ShowMode::ALL, SortMode::LAUNCHER_ORDER, icons_);
462+ controller_->Select(2);
463+ controller_->InitiateDetail();
464+
465+ controller_->StartDetailMode();
466+ EXPECT_TRUE(controller_->IsDetailViewShown());
467+
468+ auto view = controller_->GetView();
469+ auto model = view->GetModel();
470+ model->SetRowSizes({2,2});
471+
472+ controller_->StartDetailMode();
473+
474+ // Grid: Assert we have gone down a row from index 0 -> 2
475+ // 0, 1,
476+ // 2, 3
477+ EXPECT_FALSE(model->HasNextDetailRow());
478+ EXPECT_TRUE(model->HasPrevDetailRow());
479+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 2);
480+}
481+
482+TEST_F(TestSwitcherController, StopDetailModeMovesPrevRows)
483+{
484+ controller_->Show(ShowMode::ALL, SortMode::LAUNCHER_ORDER, icons_);
485+ controller_->Select(2);
486+ controller_->InitiateDetail();
487+
488+ controller_->StartDetailMode();
489+ EXPECT_TRUE(controller_->IsDetailViewShown());
490+
491+ auto view = controller_->GetView();
492+ auto model = view->GetModel();
493+ model->SetRowSizes({2,2});
494+
495+ controller_->StartDetailMode();
496+ controller_->StopDetailMode();
497+
498+ // Assert we have gone up a row from index 2 -> 0
499+ // 0, 1,
500+ // 2, 3
501+ EXPECT_TRUE(model->HasNextDetailRow());
502+ EXPECT_FALSE(model->HasPrevDetailRow());
503+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 0);
504+
505+ // Now we are in index 0, stoping detail mode must exit detail mode
506+ controller_->StopDetailMode();
507+ EXPECT_FALSE(controller_->IsDetailViewShown());
508+}
509
510 TEST_F(TestSwitcherController, ShowSwitcher)
511 {
512
513=== modified file 'tests/test_switcher_model.cpp'
514--- tests/test_switcher_model.cpp 2013-02-15 15:32:11 +0000
515+++ tests/test_switcher_model.cpp 2013-06-18 19:07:26 +0000
516@@ -80,6 +80,7 @@
517 EXPECT_EQ(model->LastSelection(), icons_.front());
518 EXPECT_EQ(model->SelectionIndex(), 0);
519 EXPECT_EQ(model->LastSelectionIndex(), 0);
520+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 0);
521 }
522
523
524@@ -178,4 +179,153 @@
525 EXPECT_NE(model->DetailXids().front(), base_model->DetailXids().front());
526 }
527
528+TEST_F(TestSwitcherModel, TestHasNextDetailRow)
529+{
530+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
531+ model->detail_selection = true;
532+ model->SetRowSizes({2,2});
533+
534+ EXPECT_TRUE(model->HasNextDetailRow());
535+
536+ model->NextDetailRow();
537+ EXPECT_FALSE(model->HasNextDetailRow());
538+}
539+
540+TEST_F(TestSwitcherModel, TestHasPrevDetailRow)
541+{
542+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
543+ model->detail_selection = true;
544+ model->SetRowSizes({2,2});
545+
546+ model->NextDetail();
547+ EXPECT_TRUE(model->HasPrevDetailRow());
548+
549+ model->PrevDetailRow();
550+ EXPECT_FALSE(model->HasPrevDetailRow());
551+}
552+
553+TEST_F(TestSwitcherModel, TestHasNextThenPrevDetailRow)
554+{
555+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
556+ model->detail_selection = true;
557+ model->SetRowSizes({2,2});
558+
559+ EXPECT_TRUE(model->HasNextDetailRow());
560+
561+ model->NextDetailRow();
562+ EXPECT_FALSE(model->HasNextDetailRow());
563+
564+ EXPECT_TRUE(model->HasPrevDetailRow());
565+ model->PrevDetailRow();
566+ EXPECT_FALSE(model->HasPrevDetailRow());
567+}
568+
569+TEST_F(TestSwitcherModel, TestNextDetailRow)
570+{
571+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
572+ model->detail_selection = true;
573+ model->SetRowSizes({2,2});
574+
575+ model->NextDetailRow();
576+
577+ // Expect going form index 0 -> 2
578+ // 0, 1
579+ // 2, 3
580+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 2);
581+}
582+
583+TEST_F(TestSwitcherModel, TestNextDetailThenNextDetailRow)
584+{
585+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
586+ model->detail_selection = true;
587+ model->SetRowSizes({2,2});
588+
589+ model->NextDetail();
590+ model->NextDetailRow();
591+
592+ // Expect going form index 1 -> 3
593+ // 0, 1
594+ // 2, 3
595+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 3);
596+}
597+
598+TEST_F(TestSwitcherModel, TestPrevDetailRow)
599+{
600+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
601+ model->detail_selection = true;
602+ model->SetRowSizes({2,2});
603+
604+ model->NextDetailRow();
605+ model->PrevDetailRow();
606+
607+ // Expect going form index 0 -> 2, then index 2 -> 0
608+ // 0, 1
609+ // 2, 3
610+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 0);
611+}
612+
613+TEST_F(TestSwitcherModel, TestNextDetailThenPrevDetailRow)
614+{
615+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
616+ model->detail_selection = true;
617+ model->SetRowSizes({2,2});
618+
619+ model->NextDetail();
620+ model->NextDetailRow();
621+
622+ model->PrevDetailRow();
623+
624+ // Expect going form index 1 -> 3, then index 3 -> 1
625+ // 0, 1
626+ // 2, 3
627+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 1);
628+}
629+
630+TEST_F(TestSwitcherModel, TestUnEvenNextDetailRow)
631+{
632+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
633+ model->detail_selection = true;
634+ model->SetRowSizes({3,2});
635+
636+ model->NextDetailRow();
637+
638+ // Expect going form index 0 -> 3
639+ // 0, 1, 2,
640+ // 3, 4
641+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 3);
642+}
643+
644+TEST_F(TestSwitcherModel, TestUnEvenPrevDetailRow)
645+{
646+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
647+ model->detail_selection = true;
648+ model->SetRowSizes({3,2});
649+
650+ model->NextDetailRow();
651+ model->PrevDetailRow();
652+
653+ // Expect going form index 0 -> 3, then 3 -> 0
654+ // 0, 1, 2,
655+ // 3, 4
656+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 0);
657+}
658+
659+TEST_F(TestSwitcherModel, TestNextPrevDetailRowMovesLeftInTopRow)
660+{
661+ SwitcherModel::Ptr model(new SwitcherModel(icons_));
662+ model->detail_selection = true;
663+ model->SetRowSizes({3,2});
664+
665+ model->NextDetail();
666+ model->NextDetail();
667+ model->PrevDetailRow();
668+ model->PrevDetailRow();
669+
670+ // Expect going form index 0 -> 1, then 1 -> 2, then 2 -> 1, 1 -> 0
671+ // since PrevDetailRow must go to the index 0 of at the top of the row
672+ // 0, 1, 2,
673+ // 3, 4
674+ EXPECT_EQ(static_cast<unsigned int>(model->detail_selection_index), 0);
675+}
676+
677 }
678
679=== modified file 'unity-shared/LayoutSystem.cpp'
680--- unity-shared/LayoutSystem.cpp 2013-02-20 21:40:31 +0000
681+++ unity-shared/LayoutSystem.cpp 2013-06-18 19:07:26 +0000
682@@ -35,7 +35,7 @@
683 LayoutGridWindows(windows, max_bounds, final_bounds);
684 }
685
686-nux::Size LayoutSystem::GridSizeForWindows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds)
687+nux::Size LayoutSystem::GridSizeForWindows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds) const
688 {
689 unsigned count = windows.size();
690
691@@ -138,7 +138,18 @@
692 return CompressAndPadRow (row, row_bounds);
693 }
694
695-std::vector<LayoutWindow::Vector> LayoutSystem::GetRows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds)
696+std::vector<int> LayoutSystem::GetRowSizes(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds) const
697+{
698+ std::vector<LayoutWindow::Vector> const& rows = GetRows(windows, max_bounds);
699+ std::vector<int> row_sizes;
700+
701+ for (auto r : rows)
702+ row_sizes.push_back(r.size());
703+
704+ return row_sizes;
705+}
706+
707+std::vector<LayoutWindow::Vector> LayoutSystem::GetRows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds) const
708 {
709 std::vector<LayoutWindow::Vector> rows;
710
711
712=== modified file 'unity-shared/LayoutSystem.h'
713--- unity-shared/LayoutSystem.h 2012-11-13 19:16:59 +0000
714+++ unity-shared/LayoutSystem.h 2013-06-18 19:07:26 +0000
715@@ -56,6 +56,7 @@
716 LayoutSystem();
717
718 void LayoutWindows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds, nux::Geometry& final_bounds);
719+ std::vector<int> GetRowSizes(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds) const;
720
721 protected:
722 void LayoutGridWindows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds, nux::Geometry& final_bounds);
723@@ -63,9 +64,9 @@
724 nux::Geometry LayoutRow(LayoutWindow::Vector const& row, nux::Geometry const& row_bounds);
725 nux::Geometry CompressAndPadRow(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds);
726
727- std::vector<LayoutWindow::Vector> GetRows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds);
728+ nux::Size GridSizeForWindows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds) const;
729
730- nux::Size GridSizeForWindows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds);
731+ std::vector<LayoutWindow::Vector> GetRows(LayoutWindow::Vector const& windows, nux::Geometry const& max_bounds) const;
732
733 nux::Geometry ScaleBoxIntoBox(nux::Geometry const& bounds, nux::Geometry const& box);
734 };