Merge lp:~stolowski/unity-scopes-api/value-slider-filter-changes into lp:unity-scopes-api/devel

Proposed by Paweł Stołowski
Status: Merged
Approved by: Marcus Tomlinson
Approved revision: 671
Merged at revision: 659
Proposed branch: lp:~stolowski/unity-scopes-api/value-slider-filter-changes
Merge into: lp:unity-scopes-api/devel
Prerequisite: lp:~stolowski/unity-scopes-api/range-input-filter-changes
Diff against target: 974 lines (+524/-156)
13 files modified
doc/tutorial.dox (+69/-0)
include/unity/scopes/ValueSliderFilter.h (+21/-53)
include/unity/scopes/ValueSliderLabels.h (+95/-0)
include/unity/scopes/internal/ValueSliderFilterImpl.h (+6/-9)
include/unity/scopes/internal/ValueSliderLabelsImpl.h (+57/-0)
src/scopes/CMakeLists.txt (+1/-0)
src/scopes/ValueSliderFilter.cpp (+6/-21)
src/scopes/ValueSliderLabels.cpp (+94/-0)
src/scopes/internal/CMakeLists.txt (+1/-0)
src/scopes/internal/ValueSliderFilterImpl.cpp (+22/-41)
src/scopes/internal/ValueSliderLabelsImpl.cpp (+106/-0)
test/gtest/scopes/Filters/Filters_test.cpp (+3/-1)
test/gtest/scopes/ValueSliderFilter/ValueSliderFilter_test.cpp (+43/-31)
To merge this branch: bzr merge lp:~stolowski/unity-scopes-api/value-slider-filter-changes
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michi Henning (community) Approve
Review via email: mp+279925@code.launchpad.net

This proposal supersedes a proposal from 2015-12-08.

Commit message

Changes to ValueSlider filter.

Description of the change

Changes to ValueSlider filter.

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
Michi Henning (michihenning) wrote :

Can we get rid of these warnings please?

/home/michi/src/unity-scopes-api/value-slider-filter-changes/src/scopes/FilterBase.cpp:57: warning: no uniquely matching class member found for
  void unity::scopes::FilterBase::set_title(std::string const &title)

/home/michi/src/unity-scopes-api/value-slider-filter-changes/src/scopes/FilterBase.cpp:62: warning: no uniquely matching class member found for
  std::string unity::scopes::FilterBase::title() const

+alone. Filter widgets need to be defined by creating appropriate filters inside the overriden SearchQueryBase::run() method, and then pushed
+to the UI similiar to how results are pushed.

I don't think it matters where they are pushed from, just that they are pushed? I think this needs to be re-worded a bit.

+The scope may nominate a single filter to act as "primary navigation". This is only possible if departments are not used at the same time (in which case departments
+become a primary navigation tool).

What happens if I don't pay attention and there are departments and a primary filter?

There are a few nit-picks about grammar and style, but I can do an edit pass once this merges.

Coverage shows that the tests don't use a filter with extra labels. It might be good to have a test case for that?

Looks good otherwise!

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Paweł Stołowski (stolowski) wrote :

> Can we get rid of these warnings please?
>
> /home/michi/src/unity-scopes-api/value-slider-filter-
> changes/src/scopes/FilterBase.cpp:57: warning: no uniquely matching class
> member found for
> void unity::scopes::FilterBase::set_title(std::string const &title)
>
> /home/michi/src/unity-scopes-api/value-slider-filter-
> changes/src/scopes/FilterBase.cpp:62: warning: no uniquely matching class
> member found for
> std::string unity::scopes::FilterBase::title() const

Ok, done, this wasn't anything at code level, only misplaced @cond \ @endcond directives which confused doxygen.

> +alone. Filter widgets need to be defined by creating appropriate filters
> inside the overriden SearchQueryBase::run() method, and then pushed
> +to the UI similiar to how results are pushed.
>
> I don't think it matters where they are pushed from, just that they are
> pushed? I think this needs to be re-worded a bit.
Ok, removed this bit.

> +The scope may nominate a single filter to act as "primary navigation". This
> is only possible if departments are not used at the same time (in which case
> departments
> +become a primary navigation tool).
>
> What happens if I don't pay attention and there are departments and a primary
> filter?
Ok, added a sentence to clarify this.

>
> There are a few nit-picks about grammar and style, but I can do an edit pass
> once this merges.
Cool, much appreciated, thank you!

>
> Coverage shows that the tests don't use a filter with extra labels. It might
> be good to have a test case for that?
Indeed. Updated the test to cover it.

>
> Looks good otherwise!

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Paweł Stołowski (stolowski) wrote :

Conflict in the changelog, re-merged devel

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

Looks good, thanks!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
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 'doc/tutorial.dox'
2--- doc/tutorial.dox 2015-10-29 02:35:50 +0000
3+++ doc/tutorial.dox 2016-03-03 11:46:10 +0000
4@@ -410,6 +410,75 @@
5 (because `cancelled()` and `run()` are called by different threads and, therefore, can be dispatched out of order).
6
7
8+\paragraph filters Filters
9+
10+Scopes API offers support for filter widgets, which provide means for filtering search results based on user input other than search query string
11+alone. Filter widgets need to be defined by creating appropriate filters inside the overriden SearchQueryBase::run() method, and then pushed
12+to the UI. It is recommended to push filters early before search results are pushed for best user experience.
13+
14+Here is an example of how filters can be created:
15+
16+\code{.cpp}
17+void run(SearchReplyProxy const& reply)
18+{
19+ OptionSelectorFilter::UPtr filter1 = OptionSelectorFilter::create("brand", "Brand");
20+ filter1->add_option("audi", "Audi");
21+ filter1->add_option("bmw", "BMW");
22+
23+ RangeInputFilter::SPtr filter2 = RangeInputFilter::create("price", Variant(0.0f), Variant::null(), "Min", "", "", "Max", "");
24+ ValueSliderFilter::SPtr filter3 = ValueSliderFilter::create("horsepower", 1, 135, 50, ValueSliderLabels("Min", "Max"));
25+
26+ Filters filters;
27+ filters.push_back(filter1);
28+ filters.push_back(filter2);
29+ filters.push_back(filter3);
30+
31+ reply->push(filters, query().filter_state());
32+
33+ // push search results here
34+\endcode
35+
36+Scopes are free to change filters at any time - with every execution of search the scope can omit any of the previously visible filters or add new ones, if that
37+makes sense for particular use cases.
38+
39+Filters act only as UI widgets - it is the responsibility of the scope to check their state and actually apply them to search results. The current value of a filter
40+becomes just another parameter of the search query that needs to be taken into account in the implementation of search handling inside run().
41+
42+To examine current state of the filters, pass the instance of unity::scopes::FilterState received with search query to respective methods of
43+the filters. For example:
44+
45+\code{.cpp}
46+void run(SearchReplyProxy const& reply)
47+{
48+ // filter creation code omitted here
49+ auto state = query().filter_state();
50+ int search_start = 0;
51+ int search_end = 1000;
52+ if (rangefilter->has_start_value(state)) {
53+ search_start = rangefilter->start_value(state);
54+ }
55+ if (rangefilter->has_end_value(state)) {
56+ search_end = rangefilter->end_value(state);
57+ }
58+
59+ // apply search_start and search_end to search logic
60+\endcode
61+
62+The scope may nominate a single filter to act as "primary navigation". This is only possible if departments are not used at the same time (in which case departments
63+become a primary navigation tool). An attempt to nominate a filter to be a "primary navigation" while departments are present is ignored by the UI and the
64+filter acts as a regular filter. Also, only a single-selection OptionSelectorFilter can currently be promoted to be primary navigation. To do this, set the display
65+hints to FilterBase::DisplayHints::Primary:
66+
67+\code{.cpp}
68+OptionSelectorFilter::UPtr filter1 = OptionSelectorFilter::create("brand", "Brand");
69+filter1->set_display_hints(FilterBase::DisplayHints::Primary);
70+filter1->add_option("audi", "Audi");
71+\endcode
72+
73+When a filter becomes a primary navigation filter, it gets displayed in the search box drop-down, below recent searches, so it's readily available for quick access.
74+Also, currently selected option is displayed as a "brick" in the search box, hinting the user about the context of current search. All the other filters can be
75+revealed via the filters panel icon.
76+
77 \paragraph handlingpreview Handling previews
78
79 Your scope is responsible for handling preview requests for results it has returned; you implement this by overriding
80
81=== modified file 'include/unity/scopes/ValueSliderFilter.h'
82--- include/unity/scopes/ValueSliderFilter.h 2014-11-03 05:31:30 +0000
83+++ include/unity/scopes/ValueSliderFilter.h 2016-03-03 11:46:10 +0000
84@@ -36,13 +36,14 @@
85 namespace experimental
86 {
87
88+class ValueSliderLabels;
89+
90 /**
91 \brief A value slider filter that allows for selecting a value within given range.
92
93-The ValueSliderFilter displays a static label, such as "Maximum size" and a slider that
94-allows for selecting a value within range defined by minimum and maximum values. The currently
95-selected value gets displayed using a label template provided by scope, e.g. "Less than %1 MB",
96-resulting in labels such as "Less than 40.5 MB".
97+The ValueSliderFilter allows for selecting a value within range defined by minimum and maximum values.
98+Both minimum and maximum values can have labels and in addition, the scope may provide extra labels
99+to mark other values from that range - these label will serve as a guidance to the user.
100 */
101 class UNITY_API ValueSliderFilter : public FilterBase
102 {
103@@ -52,62 +53,36 @@
104 /// @endcond
105
106 /**
107- \brief The type of value slider.
108-
109- The type should be set according to the behaviour of the filter:
110- ValueSliderFilter::SliderType::LessThan should be used if values lesser than selected value are to be returned, otherwise
111- ValueSliderFilter::SliderType::MoreThan should be used.
112- Note: the selected type is a display hint for the Shell only. It's up to the scope to set it properly and actually follow
113- it on search.
114- */
115- enum SliderType
116- {
117- LessThan, /**< Scope will search for values lesser than selected value */
118- MoreThan /**< Scope will search for values greater than selected value */
119- };
120-
121- /**
122 \brief Create ValueSliderFilter.
123
124 Creates ValueSliderFilter of ValueSliderFilter::SliderType::LessThan type.
125
126 \param id A unique identifier for the filter that can be used to identify it later among several filters.
127- \param label The label for the filter
128- \param label_template The template for value label, e.g. "Less than %1"
129 \param min The minimum allowed value
130 \param max The maximum allowed value
131+ \param default_value The default value of this filter, from the min..max range.
132+ \param value_labels The labels for min and max values as well as optional extra labels.
133 \return Instance of ValueSliderFilter.
134- \throws unity::LogicException on invalid (min, max) range.
135+ \throws unity::LogicException on invalid (min, max) range or erronous value_labels.
136 */
137- static ValueSliderFilter::UPtr create(std::string const& id, std::string const& label, std::string const& label_template, double min, double max);
138-
139- /**
140- \brief Change the type of this filter.
141-
142- \param tp The type of slider filter.
143- */
144- void set_slider_type(SliderType tp);
145+ static ValueSliderFilter::UPtr create(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& value_labels);
146
147 /**
148 \brief Change the default value of this filter.
149
150- The default value of this filter is by default the maximum value allowed. This value is used when calling unity::scopes::ValueSliderFilter::value_label()
151- and there is no state for this filter in unity::scopes::FilterState.
152+ The default value will be used by the shell if no value is present for this filter in the
153+ unity::scopes::FilterState (no value has been set by the user).
154
155 \param val The new default value.
156 */
157 void set_default_value(double val);
158
159 /**
160- \brief Get the type of this filter.
161-
162- \return The type of slider filter.
163- */
164- SliderType slider_type() const;
165-
166- /**
167 \brief Get the default value of this filter.
168
169+ The default value will be used by the shell if no value is present for this filter in the
170+ unity::scopes::FilterState (no value has been set by the user).
171+
172 \return The default value
173 */
174 double default_value() const;
175@@ -127,20 +102,6 @@
176 double max() const;
177
178 /**
179- \brief Get the label of this filter.
180-
181- \return The label
182- */
183- std::string label() const;
184-
185- /**
186- \brief Get the value label template of this filter.
187-
188- \return The value label template.
189- */
190- std::string value_label_template() const;
191-
192- /**
193 \brief Check if filter state object holds a value of this filter.
194
195 \return true if filter_state has a value of this filter.
196@@ -156,6 +117,13 @@
197 double value(FilterState const& filter_state) const;
198
199 /**
200+ \brief Get value labeles for this slider filter.
201+
202+ \return the value labels.
203+ */
204+ ValueSliderLabels const& labels() const;
205+
206+ /**
207 \brief Sets value of this filter instance in filter state object.
208
209 This is meant to be used to modify a FilterState received with a search request before sending it back to the client (UI shell).
210
211=== added file 'include/unity/scopes/ValueSliderLabels.h'
212--- include/unity/scopes/ValueSliderLabels.h 1970-01-01 00:00:00 +0000
213+++ include/unity/scopes/ValueSliderLabels.h 2016-03-03 11:46:10 +0000
214@@ -0,0 +1,95 @@
215+/*
216+ * Copyright (C) 2015 Canonical Ltd
217+ *
218+ * This program is free software: you can redistribute it and/or modify
219+ * it under the terms of the GNU Lesser General Public License version 3 as
220+ * published by the Free Software Foundation.
221+ *
222+ * This program is distributed in the hope that it will be useful,
223+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
224+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
225+ * GNU Lesser General Public License for more details.
226+ *
227+ * You should have received a copy of the GNU Lesser General Public License
228+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
229+ *
230+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
231+ */
232+
233+#pragma once
234+
235+#include <string>
236+#include <list>
237+#include <memory>
238+#include <unity/SymbolExport.h>
239+#include <unity/scopes/Variant.h>
240+
241+namespace unity
242+{
243+
244+namespace scopes
245+{
246+
247+namespace internal
248+{
249+class ValueSliderFilterImpl;
250+class ValueSliderLabelsImpl;
251+}
252+
253+namespace experimental
254+{
255+
256+typedef std::pair<double, std::string> ValueLabelPair;
257+typedef std::vector<ValueLabelPair> ValueLabelPairList;
258+
259+class UNITY_API ValueSliderLabels final
260+{
261+public:
262+ /**@name Copy and assignment
263+ Copy and assignment (move and non-move versions) have the usual value semantics.
264+ */
265+ //{@
266+ ValueSliderLabels(ValueSliderLabels const& other);
267+ ValueSliderLabels(ValueSliderLabels&&);
268+ ValueSliderLabels& operator=(ValueSliderLabels const& other);
269+ ValueSliderLabels& operator=(ValueSliderLabels&&);
270+ ~ValueSliderLabels();
271+ //@}
272+
273+ ValueSliderLabels(std::string const& min_label, std::string const& max_label);
274+ ValueSliderLabels(std::string const& min_label, std::string const& max_label, ValueLabelPairList const& extra_labels);
275+
276+ /**
277+ \brief Get the label for the minimum value of the filter.
278+ \return The label for minimum value
279+ */
280+ std::string min_label() const;
281+
282+ /**
283+ \brief Get the label for the maximum value of the filter.
284+ \return The label for maximum value
285+ */
286+ std::string max_label() const;
287+
288+ /**
289+ \brief Get the labels for intermediate values of the filter.
290+ */
291+ ValueLabelPairList extra_labels() const;
292+
293+ /// @cond
294+ VariantMap serialize() const;
295+ /// @endcond
296+
297+private:
298+ ValueSliderLabels(internal::ValueSliderLabelsImpl* pimpl);
299+ ValueSliderLabels(VariantMap const& var);
300+ std::unique_ptr<internal::ValueSliderLabelsImpl> p;
301+ friend class internal::ValueSliderLabelsImpl;
302+ friend class internal::ValueSliderFilterImpl;
303+};
304+
305+} // namespace experimental
306+
307+} // namespace scopes
308+
309+} // namespace unity
310
311=== modified file 'include/unity/scopes/internal/ValueSliderFilterImpl.h'
312--- include/unity/scopes/internal/ValueSliderFilterImpl.h 2015-11-12 14:20:36 +0000
313+++ include/unity/scopes/internal/ValueSliderFilterImpl.h 2016-03-03 11:46:10 +0000
314@@ -20,6 +20,8 @@
315
316 #include <unity/scopes/internal/FilterBaseImpl.h>
317 #include <unity/scopes/ValueSliderFilter.h>
318+#include <unity/scopes/ValueSliderLabels.h>
319+#include <unity/scopes/internal/ValueSliderLabelsImpl.h>
320
321 namespace unity
322 {
323@@ -37,19 +39,16 @@
324 class ValueSliderFilterImpl : public FilterBaseImpl
325 {
326 public:
327- ValueSliderFilterImpl(std::string const& id, std::string const& label, std::string const& label_template, double min, double max);
328+ ValueSliderFilterImpl(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& labels);
329 ValueSliderFilterImpl(VariantMap const& var);
330- void set_slider_type(ValueSliderFilter::SliderType tp);
331- ValueSliderFilter::SliderType slider_type() const;
332 void set_default_value(double val);
333- std::string label() const;
334 double min() const;
335 double max() const;
336 double default_value() const;
337- std::string value_label_template() const;
338 bool has_value(FilterState const& filter_state) const;
339 double value(FilterState const& filter_state) const;
340 void update_state(FilterState& filter_state, double value) const;
341+ ValueSliderLabels const& labels() const;
342 static ValueSliderFilter::SPtr create(VariantMap const& var);
343 static void update_state(FilterState& filter_state, std::string const& filter_id, double value);
344 void validate_display_hints() const override;
345@@ -61,12 +60,10 @@
346 void check_range(double val) const;
347
348 private:
349- std::string label_;
350- std::string label_template_;
351- ValueSliderFilter::SliderType slider_type_;
352- double default_val_;
353 double min_;
354 double max_;
355+ double default_val_;
356+ std::unique_ptr<ValueSliderLabels> labels_;
357 };
358
359 } // namespace internal
360
361=== added file 'include/unity/scopes/internal/ValueSliderLabelsImpl.h'
362--- include/unity/scopes/internal/ValueSliderLabelsImpl.h 1970-01-01 00:00:00 +0000
363+++ include/unity/scopes/internal/ValueSliderLabelsImpl.h 2016-03-03 11:46:10 +0000
364@@ -0,0 +1,57 @@
365+/*
366+ * Copyright (C) 2015 Canonical Ltd
367+ *
368+ * This program is free software: you can redistribute it and/or modify
369+ * it under the terms of the GNU Lesser General Public License version 3 as
370+ * published by the Free Software Foundation.
371+ *
372+ * This program is distributed in the hope that it will be useful,
373+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
374+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
375+ * GNU Lesser General Public License for more details.
376+ *
377+ * You should have received a copy of the GNU Lesser General Public License
378+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
379+ *
380+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
381+ */
382+
383+#pragma once
384+
385+#include <unity/scopes/ValueSliderLabels.h>
386+#include <unity/scopes/Variant.h>
387+
388+namespace unity
389+{
390+
391+namespace scopes
392+{
393+
394+namespace internal
395+{
396+
397+class ValueSliderLabelsImpl
398+{
399+public:
400+ ValueSliderLabelsImpl(std::string const& min_label, std::string const& max_label);
401+ ValueSliderLabelsImpl(std::string const& min_label, std::string const& max_label, std::vector<std::pair<double, std::string>> const& extra_labels);
402+ ValueSliderLabelsImpl(VariantMap const& var);
403+ ValueSliderLabelsImpl(ValueSliderLabelsImpl const&) = default;
404+
405+ std::string min_label() const;
406+ std::string max_label() const;
407+ std::vector<std::pair<double, std::string>> extra_labels() const;
408+ VariantMap serialize() const;
409+ void deserialize(VariantMap const& var);
410+
411+private:
412+ std::string min_label_;
413+ std::string max_label_;
414+ std::vector<std::pair<double, std::string>> extra_labels_;
415+};
416+
417+}
418+
419+}
420+
421+}
422
423=== modified file 'src/scopes/CMakeLists.txt'
424--- src/scopes/CMakeLists.txt 2015-04-09 15:59:17 +0000
425+++ src/scopes/CMakeLists.txt 2016-03-03 11:46:10 +0000
426@@ -55,6 +55,7 @@
427 ${CMAKE_CURRENT_SOURCE_DIR}/SearchReply.cpp
428 ${CMAKE_CURRENT_SOURCE_DIR}/SwitchFilter.cpp
429 ${CMAKE_CURRENT_SOURCE_DIR}/ValueSliderFilter.cpp
430+ ${CMAKE_CURRENT_SOURCE_DIR}/ValueSliderLabels.cpp
431 ${CMAKE_CURRENT_SOURCE_DIR}/VariantBuilder.cpp
432 ${CMAKE_CURRENT_SOURCE_DIR}/Variant.cpp
433 ${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp
434
435=== modified file 'src/scopes/ValueSliderFilter.cpp'
436--- src/scopes/ValueSliderFilter.cpp 2014-06-17 10:30:03 +0000
437+++ src/scopes/ValueSliderFilter.cpp 2016-03-03 11:46:10 +0000
438@@ -33,14 +33,9 @@
439 {
440 }
441
442-ValueSliderFilter::UPtr ValueSliderFilter::create(std::string const& id, std::string const& label, std::string const& label_template, double min, double max)
443-{
444- return std::unique_ptr<ValueSliderFilter>(new ValueSliderFilter(new internal::ValueSliderFilterImpl(id, label, label_template, min, max)));
445-}
446-
447-void ValueSliderFilter::set_slider_type(SliderType tp)
448-{
449- fwd()->set_slider_type(tp);
450+ValueSliderFilter::UPtr ValueSliderFilter::create(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& labels)
451+{
452+ return std::unique_ptr<ValueSliderFilter>(new ValueSliderFilter(new internal::ValueSliderFilterImpl(id, min, max, default_value, labels)));
453 }
454
455 void ValueSliderFilter::set_default_value(double val)
456@@ -48,11 +43,6 @@
457 fwd()->set_default_value(val);
458 }
459
460-ValueSliderFilter::SliderType ValueSliderFilter::slider_type() const
461-{
462- return fwd()->slider_type();
463-}
464-
465 double ValueSliderFilter::default_value() const
466 {
467 return fwd()->default_value();
468@@ -68,14 +58,9 @@
469 return fwd()->max();
470 }
471
472-std::string ValueSliderFilter::label() const
473-{
474- return fwd()->label();
475-}
476-
477-std::string ValueSliderFilter::value_label_template() const
478-{
479- return fwd()->value_label_template();
480+ValueSliderLabels const& ValueSliderFilter::labels() const
481+{
482+ return fwd()->labels();
483 }
484
485 bool ValueSliderFilter::has_value(FilterState const& filter_state) const
486
487=== added file 'src/scopes/ValueSliderLabels.cpp'
488--- src/scopes/ValueSliderLabels.cpp 1970-01-01 00:00:00 +0000
489+++ src/scopes/ValueSliderLabels.cpp 2016-03-03 11:46:10 +0000
490@@ -0,0 +1,94 @@
491+/*
492+ * Copyright (C) 2015 Canonical Ltd
493+ *
494+ * This program is free software: you can redistribute it and/or modify
495+ * it under the terms of the GNU Lesser General Public License version 3 as
496+ * published by the Free Software Foundation.
497+ *
498+ * This program is distributed in the hope that it will be useful,
499+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
500+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
501+ * GNU Lesser General Public License for more details.
502+ *
503+ * You should have received a copy of the GNU Lesser General Public License
504+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
505+ *
506+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
507+*/
508+
509+#include <unity/scopes/ValueSliderLabels.h>
510+#include <unity/scopes/internal/ValueSliderLabelsImpl.h>
511+
512+namespace unity
513+{
514+
515+namespace scopes
516+{
517+
518+namespace experimental
519+{
520+
521+ValueSliderLabels::ValueSliderLabels(internal::ValueSliderLabelsImpl* pimpl)
522+ : p(pimpl)
523+{
524+}
525+
526+ValueSliderLabels::ValueSliderLabels(std::string const& min_label, std::string const& max_label)
527+ : p(new internal::ValueSliderLabelsImpl(min_label, max_label))
528+{
529+}
530+
531+ValueSliderLabels::ValueSliderLabels(std::string const& min_label, std::string const& max_label, ValueLabelPairList const& extra_labels)
532+ : p(new internal::ValueSliderLabelsImpl(min_label, max_label, extra_labels))
533+{
534+}
535+
536+ValueSliderLabels::ValueSliderLabels(VariantMap const& var)
537+ : p(new internal::ValueSliderLabelsImpl(var))
538+{
539+}
540+
541+ValueSliderLabels::ValueSliderLabels(ValueSliderLabels const& other)
542+ : p(new internal::ValueSliderLabelsImpl(*(other.p)))
543+{
544+}
545+
546+ValueSliderLabels& ValueSliderLabels::operator=(ValueSliderLabels const& other)
547+{
548+ if (this != &other)
549+ {
550+ p.reset(new internal::ValueSliderLabelsImpl(*(other.p)));
551+ }
552+ return *this;
553+}
554+
555+ValueSliderLabels::ValueSliderLabels(ValueSliderLabels&&) = default;
556+ValueSliderLabels& ValueSliderLabels::operator=(ValueSliderLabels&&) = default;
557+
558+ValueSliderLabels::~ValueSliderLabels() = default;
559+
560+std::string ValueSliderLabels::min_label() const
561+{
562+ return p->min_label();
563+}
564+
565+std::string ValueSliderLabels::max_label() const
566+{
567+ return p->max_label();
568+}
569+
570+ValueLabelPairList ValueSliderLabels::extra_labels() const
571+{
572+ return p->extra_labels();
573+}
574+
575+VariantMap ValueSliderLabels::serialize() const
576+{
577+ return p->serialize();
578+}
579+
580+}
581+
582+}
583+
584+}
585
586=== modified file 'src/scopes/internal/CMakeLists.txt'
587--- src/scopes/internal/CMakeLists.txt 2015-03-27 17:18:09 +0000
588+++ src/scopes/internal/CMakeLists.txt 2016-03-03 11:46:10 +0000
589@@ -89,6 +89,7 @@
590 ${CMAKE_CURRENT_SOURCE_DIR}/UniqueID.cpp
591 ${CMAKE_CURRENT_SOURCE_DIR}/Utils.cpp
592 ${CMAKE_CURRENT_SOURCE_DIR}/ValueSliderFilterImpl.cpp
593+ ${CMAKE_CURRENT_SOURCE_DIR}/ValueSliderLabelsImpl.cpp
594 ${CMAKE_CURRENT_SOURCE_DIR}/VariantBuilderImpl.cpp
595 )
596 set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE)
597
598=== modified file 'src/scopes/internal/ValueSliderFilterImpl.cpp'
599--- src/scopes/internal/ValueSliderFilterImpl.cpp 2015-11-12 14:20:36 +0000
600+++ src/scopes/internal/ValueSliderFilterImpl.cpp 2016-03-03 11:46:10 +0000
601@@ -32,26 +32,26 @@
602 namespace internal
603 {
604
605-ValueSliderFilterImpl::ValueSliderFilterImpl(std::string const& id, std::string const& label, std::string const& label_template, double min, double max)
606+ValueSliderFilterImpl::ValueSliderFilterImpl(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& labels)
607 : FilterBaseImpl(id),
608- label_(label),
609- label_template_(label_template),
610- slider_type_(ValueSliderFilter::SliderType::LessThan),
611 min_(min),
612- max_(max)
613+ max_(max),
614+ default_val_(default_value),
615+ labels_(new ValueSliderLabels(labels))
616 {
617- if (label.empty())
618- {
619- throw InvalidArgumentException("ValueSliderFilterImpl(): Invalid empty label string");
620- }
621-
622- if (min < 0 || min >= max)
623+ if (min >= max)
624 {
625 std::stringstream err;
626 err << "ValueSliderFilterImpl::ValueSliderFilterImpl(): invalid min or max value for filter '" << id << "', min is " << min << ", max is " << max;
627 throw LogicException(err.str());
628 }
629- default_val_ = max;
630+ if (default_value < min || default_value > max)
631+ {
632+ std::stringstream err;
633+ err << "ValueSliderFilterImpl::ValueSliderFilterImpl(): invalid default value for filter '" << id << "', " << default_value << " not in " << min << "-"
634+ << max << " range";
635+ throw LogicException(err.str());
636+ }
637 }
638
639 ValueSliderFilterImpl::ValueSliderFilterImpl(VariantMap const& var)
640@@ -73,16 +73,6 @@
641 default_val_ = val;
642 }
643
644-void ValueSliderFilterImpl::set_slider_type(ValueSliderFilter::SliderType tp)
645-{
646- slider_type_ = tp;
647-}
648-
649-ValueSliderFilter::SliderType ValueSliderFilterImpl::slider_type() const
650-{
651- return slider_type_;
652-}
653-
654 double ValueSliderFilterImpl::default_value() const
655 {
656 return default_val_;
657@@ -98,14 +88,11 @@
658 return max_;
659 }
660
661-std::string ValueSliderFilterImpl::label() const
662-{
663- return label_;
664-}
665-
666-std::string ValueSliderFilterImpl::value_label_template() const
667-{
668- return label_template_;
669+ValueSliderLabels const& ValueSliderFilterImpl::labels() const
670+{
671+ // labels_ pointer is guaranteed to be initialized either by the regular ctor or when deserialized from a variant
672+ assert(labels_);
673+ return *labels_;
674 }
675
676 bool ValueSliderFilterImpl::has_value(FilterState const& filter_state) const
677@@ -119,7 +106,7 @@
678 {
679 try
680 {
681- double val = FilterBaseImpl::get(filter_state, id()).get_double(); // this can throw if of different type
682+ auto val = FilterBaseImpl::get(filter_state, id()).get_double(); // this can throw if of different type
683 check_range(val);
684 return val;
685 }
686@@ -154,28 +141,22 @@
687
688 void ValueSliderFilterImpl::serialize(VariantMap& var) const
689 {
690- var["label"] = label_;
691- var["label_template"] = label_template_;
692 var["min"] = Variant(min_);
693 var["max"] = Variant(max_);
694 var["default"] = Variant(default_val_);
695- var["slider_type"] = static_cast<int>(slider_type_);
696+ var["labels"] = Variant(labels_->serialize());
697 }
698
699 void ValueSliderFilterImpl::deserialize(VariantMap const& var)
700 {
701- auto it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "label");
702- label_ = it->second.get_string();
703- it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "label_template");
704- label_template_ = it->second.get_string();
705- it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "min");
706+ auto it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "min");
707 min_ = it->second.get_double();
708 it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "max");
709 max_ = it->second.get_double();
710 it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "default");
711 default_val_ = it->second.get_double();
712- it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "slider_type");
713- slider_type_ = static_cast<ValueSliderFilter::SliderType>(it->second.get_int());
714+ it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "labels");
715+ labels_.reset(new ValueSliderLabels(it->second.get_dict()));
716 }
717
718 std::string ValueSliderFilterImpl::filter_type() const
719
720=== added file 'src/scopes/internal/ValueSliderLabelsImpl.cpp'
721--- src/scopes/internal/ValueSliderLabelsImpl.cpp 1970-01-01 00:00:00 +0000
722+++ src/scopes/internal/ValueSliderLabelsImpl.cpp 2016-03-03 11:46:10 +0000
723@@ -0,0 +1,106 @@
724+/*
725+ * Copyright (C) 2015 Canonical Ltd
726+ *
727+ * This program is free software: you can redistribute it and/or modify
728+ * it under the terms of the GNU Lesser General Public License version 3 as
729+ * published by the Free Software Foundation.
730+ *
731+ * This program is distributed in the hope that it will be useful,
732+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
733+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
734+ * GNU Lesser General Public License for more details.
735+ *
736+ * You should have received a copy of the GNU Lesser General Public License
737+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
738+ *
739+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
740+ */
741+
742+#include <unity/scopes/internal/ValueSliderLabelsImpl.h>
743+#include <unity/scopes/internal/Utils.h>
744+#include <unity/UnityExceptions.h>
745+
746+namespace unity
747+{
748+
749+namespace scopes
750+{
751+
752+namespace internal
753+{
754+
755+ValueSliderLabelsImpl::ValueSliderLabelsImpl(std::string const& min_label, std::string const& max_label)
756+ : min_label_(min_label),
757+ max_label_(max_label)
758+{
759+}
760+
761+ValueSliderLabelsImpl::ValueSliderLabelsImpl(std::string const& min_label, std::string const& max_label, std::vector<std::pair<double, std::string>> const& extra_labels)
762+ : min_label_(min_label),
763+ max_label_(max_label),
764+ extra_labels_(extra_labels)
765+{
766+}
767+
768+ValueSliderLabelsImpl::ValueSliderLabelsImpl(VariantMap const& var)
769+{
770+ deserialize(var);
771+}
772+
773+std::string ValueSliderLabelsImpl::min_label() const
774+{
775+ return min_label_;
776+}
777+
778+std::string ValueSliderLabelsImpl::max_label() const
779+{
780+ return max_label_;
781+}
782+
783+std::vector<std::pair<double, std::string>> ValueSliderLabelsImpl::extra_labels() const
784+{
785+ return extra_labels_;
786+}
787+
788+VariantMap ValueSliderLabelsImpl::serialize() const
789+{
790+ VariantMap vm;
791+ VariantArray va;
792+ for (auto const& p: extra_labels_)
793+ {
794+ va.push_back(Variant(p.first));
795+ va.push_back(Variant(p.second));
796+ }
797+ vm["extra_labels"] = Variant(va);
798+ vm["min_label"] = Variant(min_label_);
799+ vm["max_label"] = Variant(max_label_);
800+ return vm;
801+}
802+
803+void ValueSliderLabelsImpl::deserialize(VariantMap const& var)
804+{
805+ auto it = find_or_throw("ValueSliderLabels::deserialize()", var, "min_label");
806+ min_label_ = it->second.get_string();
807+ it = find_or_throw("ValueSliderLabels::deserialize()", var, "max_label");
808+ max_label_ = it->second.get_string();
809+ it = var.find("extra_labels");
810+ if (it != var.end())
811+ {
812+ auto const va = it->second.get_array();
813+ for (auto it = va.begin(); it != va.end();)
814+ {
815+ auto const value = (it++)->get_double();
816+ if (it == va.end())
817+ {
818+ throw unity::InvalidArgumentException("ValueSliderLabels::deserialize(): invalid value-label array");
819+ }
820+ std::string const label = (it++)->get_string();
821+ extra_labels_.push_back(std::make_pair<>(value, label));
822+ }
823+ }
824+}
825+}
826+
827+}
828+
829+}
830
831=== modified file 'test/gtest/scopes/Filters/Filters_test.cpp'
832--- test/gtest/scopes/Filters/Filters_test.cpp 2016-03-03 11:46:10 +0000
833+++ test/gtest/scopes/Filters/Filters_test.cpp 2016-03-03 11:46:10 +0000
834@@ -20,12 +20,14 @@
835 #include <unity/scopes/internal/RuntimeImpl.h>
836 #include <unity/scopes/internal/ScopeImpl.h>
837 #include <unity/scopes/internal/FilterBaseImpl.h>
838+#include <unity/scopes/internal/ValueSliderLabelsImpl.h>
839 #include <unity/scopes/FilterOption.h>
840 #include <unity/scopes/RadioButtonsFilter.h>
841 #include <unity/scopes/RatingFilter.h>
842 #include <unity/scopes/RangeInputFilter.h>
843 #include <unity/scopes/SwitchFilter.h>
844 #include <unity/scopes/ValueSliderFilter.h>
845+#include <unity/scopes/ValueSliderLabels.h>
846 #include <unity/scopes/SearchMetadata.h>
847 #include <unity/UnityExceptions.h>
848 #include <gtest/gtest.h>
849@@ -227,7 +229,7 @@
850 }
851
852 {
853- ValueSliderFilter::SPtr filter1 = ValueSliderFilter::create("f1", "Max size", "Less than %f", 0.0f, 100.0f);
854+ ValueSliderFilter::SPtr filter1 = ValueSliderFilter::create("f1", 0, 100, 100, ValueSliderLabels("Min", "Max"));
855 auto var = filter1->serialize();
856
857 auto f = FilterBase::deserialize(var);
858
859=== modified file 'test/gtest/scopes/ValueSliderFilter/ValueSliderFilter_test.cpp'
860--- test/gtest/scopes/ValueSliderFilter/ValueSliderFilter_test.cpp 2015-11-12 12:45:41 +0000
861+++ test/gtest/scopes/ValueSliderFilter/ValueSliderFilter_test.cpp 2016-03-03 11:46:10 +0000
862@@ -19,6 +19,7 @@
863 #include <gtest/gtest.h>
864 #include <unity/scopes/FilterState.h>
865 #include <unity/scopes/ValueSliderFilter.h>
866+#include <unity/scopes/ValueSliderLabels.h>
867 #include <unity/scopes/internal/ValueSliderFilterImpl.h>
868 #include <unity/scopes/ScopeExceptions.h>
869 #include <unity/UnityExceptions.h>
870@@ -30,23 +31,32 @@
871 TEST(ValueSliderFilter, basic)
872 {
873 {
874- auto filter1 = ValueSliderFilter::create("f1", "Max size", "Less than %1", 1.0f, 100.0f);
875- EXPECT_EQ("f1", filter1->id());
876- EXPECT_EQ("Max size", filter1->label());
877- EXPECT_EQ("Less than %1", filter1->value_label_template());
878- EXPECT_EQ(100.0f, filter1->default_value());
879- EXPECT_EQ(1.0f, filter1->min());
880- EXPECT_EQ(100.0f, filter1->max());
881- EXPECT_EQ(ValueSliderFilter::SliderType::LessThan, filter1->slider_type());
882- filter1->set_slider_type(ValueSliderFilter::SliderType::MoreThan);
883- filter1->set_default_value(2.0f);
884- EXPECT_EQ(ValueSliderFilter::SliderType::MoreThan, filter1->slider_type());
885- EXPECT_EQ(2.0f, filter1->default_value());
886- }
887-
888- {
889- EXPECT_THROW(ValueSliderFilter::create("f1", "Max size", "Less than %1", 10.0f, 1.0f), unity::LogicException);
890- EXPECT_THROW(ValueSliderFilter::create("f1", "Max size", "Less than %1", -1.0f, 10.0f), unity::LogicException);
891+ auto filter1 = ValueSliderFilter::create("f1", 1, 100, 100, ValueSliderLabels("Min", "Max"));
892+ EXPECT_EQ("f1", filter1->id());
893+ EXPECT_EQ("Min", filter1->labels().min_label());
894+ EXPECT_EQ("Max", filter1->labels().max_label());
895+ EXPECT_EQ(100, filter1->default_value());
896+ EXPECT_EQ(1, filter1->min());
897+ EXPECT_EQ(100, filter1->max());
898+ filter1->set_default_value(2);
899+ EXPECT_EQ(2, filter1->default_value());
900+ }
901+ {
902+ auto filter1 = ValueSliderFilter::create("f1", 1, 100, 50, ValueSliderLabels("Min", "Max", {{10, "Ten"}, {50, "Fifty"}}));
903+ EXPECT_EQ("f1", filter1->id());
904+ EXPECT_EQ("Min", filter1->labels().min_label());
905+ EXPECT_EQ("Max", filter1->labels().max_label());
906+ EXPECT_EQ(2, filter1->labels().extra_labels().size());
907+ EXPECT_EQ("Ten", filter1->labels().extra_labels()[0].second);
908+ EXPECT_EQ("Fifty", filter1->labels().extra_labels()[1].second);
909+ EXPECT_EQ(50, filter1->default_value());
910+ EXPECT_EQ(1, filter1->min());
911+ EXPECT_EQ(100, filter1->max());
912+ }
913+ {
914+ EXPECT_THROW(ValueSliderFilter::create("f1", 10, 1, 1, ValueSliderLabels("Min", "Max")), unity::LogicException);
915+ EXPECT_THROW(ValueSliderFilter::create("f1", 10, 10, 1, ValueSliderLabels("Min", "Max")), unity::LogicException);
916+ EXPECT_THROW(ValueSliderFilter::create("f1", 1, 10, 20, ValueSliderLabels("Min", "Max")), unity::LogicException);
917 }
918 }
919
920@@ -54,38 +64,40 @@
921 {
922 {
923 FilterState fstate;
924- auto filter1 = ValueSliderFilter::create("f1", "Max size", "Less than %1", 1.0f, 100.0f);
925+ auto filter1 = ValueSliderFilter::create("f1", 1, 100, 100, ValueSliderLabels("Min", "Max"));
926 EXPECT_FALSE(filter1->has_value(fstate));
927 EXPECT_THROW(filter1->value(fstate), unity::scopes::NotFoundException);
928 }
929
930 {
931 FilterState fstate;
932- auto filter1 = ValueSliderFilter::create("f1", "Max size", "Less than %1", 1.0f, 100.0f);
933- filter1->update_state(fstate, 33.0f);
934+ auto filter1 = ValueSliderFilter::create("f1", 1, 100, 100, ValueSliderLabels("Min", "Max"));
935+ filter1->update_state(fstate, 33);
936 EXPECT_TRUE(filter1->has_value(fstate));
937- EXPECT_EQ(33.0f, filter1->value(fstate));
938- EXPECT_THROW(filter1->update_state(fstate, 0.0f), unity::LogicException);
939- EXPECT_THROW(filter1->update_state(fstate, 999.0f), unity::LogicException);
940+ EXPECT_EQ(33, filter1->value(fstate));
941+ EXPECT_THROW(filter1->update_state(fstate, 0), unity::LogicException);
942+ EXPECT_THROW(filter1->update_state(fstate, 999), unity::LogicException);
943 }
944 }
945
946 TEST(ValueSliderFilter, serialize)
947 {
948- auto filter1 = ValueSliderFilter::create("f1", "Max size", "Less than %1", 1.0f, 100.0f);
949+ auto filter1 = ValueSliderFilter::create("f1", 1, 100, 100, ValueSliderLabels("Min", "Max", {{10, "Ten"}}));
950 auto var = filter1->serialize();
951
952 auto filter2 = internal::ValueSliderFilterImpl::create(var);
953- EXPECT_EQ("f1", filter1->id());
954- EXPECT_EQ("Max size", filter1->label());
955- EXPECT_EQ("Less than %1", filter1->value_label_template());
956- EXPECT_EQ(1.0f, filter1->min());
957- EXPECT_EQ(100.0f, filter1->max());
958- EXPECT_EQ(ValueSliderFilter::SliderType::LessThan, filter1->slider_type());
959+ EXPECT_EQ("f1", filter2->id());
960+ EXPECT_EQ("Min", filter2->labels().min_label());
961+ EXPECT_EQ("Max", filter2->labels().max_label());
962+ EXPECT_EQ(1, filter2->labels().extra_labels().size());
963+ EXPECT_EQ(10, filter2->labels().extra_labels()[0].first);
964+ EXPECT_EQ("Ten", filter2->labels().extra_labels()[0].second);
965+ EXPECT_EQ(1, filter2->min());
966+ EXPECT_EQ(100, filter2->max());
967 }
968
969 TEST(ValueSliderFilter, display_hints)
970 {
971- auto filter = ValueSliderFilter::create("f1", "Max size", "Less than %1", 1.0f, 100.0f);
972+ auto filter = ValueSliderFilter::create("f1", 1, 100, 1, ValueSliderLabels("Min", "Max"));
973 EXPECT_THROW(filter->set_display_hints(FilterBase::DisplayHints::Primary), unity::InvalidArgumentException);
974 }

Subscribers

People subscribed via source and target branches

to all changes: