Merge lp:~mandel/unity/add-action-link into lp:unity
- add-action-link
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Nick Dedekind |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2949 |
Proposed branch: | lp:~mandel/unity/add-action-link |
Merge into: | lp:unity |
Prerequisite: | lp:~mandel/unity/add-text-entry |
Diff against target: |
739 lines (+610/-2) 7 files modified
dash/previews/ActionLink.cpp (+248/-0) dash/previews/ActionLink.h (+100/-0) dash/previews/CMakeLists.txt (+1/-0) tests/CMakeLists.txt (+1/-0) tests/test_action_link.cpp (+188/-0) unity-shared/StaticCairoText.cpp (+62/-2) unity-shared/StaticCairoText.h (+10/-0) |
To merge this branch: | bzr merge lp:~mandel/unity/add-action-link |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Nick Dedekind (community) | Approve | ||
Marco Trevisan (Treviño) | Approve | ||
PS Jenkins bot | continuous-integration | Pending | |
Review via email: mp+130107@code.launchpad.net |
Commit message
- Provide a re-usable UI element that looks and behaves like a url link (LP: #1067705).
Description of the change
- Provide a re-usable UI element that looks and behaves like a url link (LP: #1067705).
Nick Dedekind (nick-dedekind) wrote : | # |
apon furthur inspection, looks OK to leave it as a button.
Thought there was a bit more to a abstract button than there is.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Please, add tests too.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
56 +ActionLink:
57 +{
58 +}
Get rid of it
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Please get rid of the magic numbers in GetLinkAlpha replacing them with const values into an anonymous namespace, however that's globally nice, thanks! ;)
Nick Dedekind (nick-dedekind) wrote : | # |
50 + SetAcceptKeyNav
51 + SetAcceptKeyNav
Since you have an Init function, you should put these in there.
73 + SetMinimumHeigh
MAGIC. Is there a reason you need a minimum height and are not just using the layout's height calculated from the contents? If you do need it, use a const in anon namespace.
105 + static_
106 + static_
Since this is a general control these should be options on the action link, which are defaulted to these values. (SetTextAlignme
139 + if (cached_geometry_ != geo && geo.width > 0 && geo.height > 0)
140 + {
141 + cached_geometry_ = geo;
142 + }
There doesn't seem to be a purpose for the geometry caching that I can see, in which case you should be able to remove the ComputeContentSize override.
179 + nux::Geometry clip_geo = geo;
No need to make a copy of the geometry ref unless you're modifying it.
Nick Dedekind (nick-dedekind) wrote : | # |
LGTM.
All tests run successfully.
Preview Diff
1 | === added file 'dash/previews/ActionLink.cpp' |
2 | --- dash/previews/ActionLink.cpp 1970-01-01 00:00:00 +0000 |
3 | +++ dash/previews/ActionLink.cpp 2012-11-28 10:01:36 +0000 |
4 | @@ -0,0 +1,248 @@ |
5 | +/* |
6 | + * Copyright 2012 Canonical Ltd. |
7 | + * |
8 | + * This program is free software: you can redistribute it and/or modify it |
9 | + * under the terms of the GNU Lesser General Public License version 3, as |
10 | + * published by the Free Software Foundation. |
11 | + * |
12 | + * This program is distributed in the hope that it will be useful, but |
13 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
14 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
15 | + * PURPOSE. See the applicable version of the GNU Lesser General Public |
16 | + * License for more details. |
17 | + * |
18 | + * You should have received a copy of both the GNU Lesser General Public |
19 | + * License version 3 along with this program. If not, see |
20 | + * <http://www.gnu.org/licenses/> |
21 | + * |
22 | + * Authored by: Manuel de la Pena <manuel.delapena@canonical.com> |
23 | + * |
24 | + */ |
25 | + |
26 | +#include "ActionLink.h" |
27 | +#include <NuxCore/Logger.h> |
28 | +#include <Nux/VLayout.h> |
29 | +#include <UnityCore/Variant.h> |
30 | +#include "unity-shared/DashStyle.h" |
31 | +#include "unity-shared/IconTexture.h" |
32 | +#include "unity-shared/StaticCairoText.h" |
33 | + |
34 | +namespace |
35 | +{ |
36 | +nux::logging::Logger logger("unity.dash.actionlink"); |
37 | +const double LINK_NORMAL_ALPHA_VALUE = 4; |
38 | +const double LINK_HIGHLIGHTED_ALPHA_VALUE = 1; |
39 | +} |
40 | + |
41 | +namespace unity |
42 | +{ |
43 | +namespace dash |
44 | +{ |
45 | + |
46 | +ActionLink::ActionLink(std::string const& action_hint, std::string const& label, NUX_FILE_LINE_DECL) |
47 | + : nux::AbstractButton(NUX_FILE_LINE_PARAM) |
48 | + , action_hint_(action_hint) |
49 | + , aligment_(nux::StaticCairoText::NUX_ALIGN_CENTRE) |
50 | + , underline_(nux::StaticCairoText::NUX_UNDERLINE_SINGLE) |
51 | +{ |
52 | + Init(); |
53 | + BuildLayout(label); |
54 | +} |
55 | + |
56 | +std::string ActionLink::GetName() const |
57 | +{ |
58 | + return "ActionLink"; |
59 | +} |
60 | + |
61 | +void ActionLink::AddProperties(GVariantBuilder* builder) |
62 | +{ |
63 | + variant::BuilderWrapper(builder) |
64 | + .add(GetAbsoluteGeometry()) |
65 | + .add("action", action_hint_) |
66 | + .add("label", label_) |
67 | + .add("font-hint", font_hint) |
68 | + .add("active", active_) |
69 | + .add("text-aligment", text_aligment) |
70 | + .add("underline-state", underline_state); |
71 | +} |
72 | + |
73 | +void ActionLink::Init() |
74 | +{ |
75 | + SetAcceptKeyNavFocusOnMouseDown(false); |
76 | + SetAcceptKeyNavFocusOnMouseEnter(true); |
77 | + |
78 | + // set properties to ensure that we do redraw when one of them changes |
79 | + text_aligment.SetSetterFunction(sigc::mem_fun(this, &ActionLink::set_aligment)); |
80 | + text_aligment.SetGetterFunction(sigc::mem_fun(this, &ActionLink::get_aligment)); |
81 | + |
82 | + underline_state.SetSetterFunction(sigc::mem_fun(this, &ActionLink::set_underline)); |
83 | + underline_state.SetGetterFunction(sigc::mem_fun(this, &ActionLink::get_underline)); |
84 | + |
85 | + font_hint.SetSetterFunction(sigc::mem_fun(this, &ActionLink::set_font_hint)); |
86 | + font_hint.SetGetterFunction(sigc::mem_fun(this, &ActionLink::get_font_hint)); |
87 | + |
88 | + key_nav_focus_change.connect([&] (nux::Area*, bool, nux::KeyNavDirection) |
89 | + { |
90 | + QueueDraw(); |
91 | + }); |
92 | + |
93 | + key_nav_focus_activate.connect([&](nux::Area*) |
94 | + { |
95 | + if (GetInputEventSensitivity()) |
96 | + activate.emit(this, action_hint_); |
97 | + }); |
98 | +} |
99 | + |
100 | +void ActionLink::BuildLayout(std::string const& label) |
101 | +{ |
102 | + |
103 | + if (label != label_) |
104 | + { |
105 | + label_ = label; |
106 | + if (static_text_) |
107 | + { |
108 | + static_text_.Release(); |
109 | + static_text_ = NULL; |
110 | + } |
111 | + |
112 | + if (!label_.empty()) |
113 | + { |
114 | + static_text_ = new nux::StaticCairoText(label_, true, NUX_TRACKER_LOCATION); |
115 | + if (!font_hint_.empty()) |
116 | + static_text_->SetFont(font_hint_); |
117 | + static_text_->SetInputEventSensitivity(false); |
118 | + static_text_->SetTextAlignment(aligment_); |
119 | + static_text_->SetUnderline(underline_); |
120 | + } |
121 | + } |
122 | + |
123 | + RemoveLayout(); |
124 | + |
125 | + nux::VLayout* layout = new nux::VLayout(); |
126 | + if (static_text_) |
127 | + { |
128 | + layout->AddView(static_text_.GetPointer(), |
129 | + 1, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL, |
130 | + 100.0f, nux::NUX_LAYOUT_END); |
131 | + } |
132 | + SetLayout(layout); |
133 | + |
134 | + ComputeContentSize(); |
135 | + QueueDraw(); |
136 | +} |
137 | + |
138 | +int ActionLink::GetLinkAlpha(nux::ButtonVisualState state) |
139 | +{ |
140 | + if (state == nux::ButtonVisualState::VISUAL_STATE_PRELIGHT) |
141 | + return LINK_HIGHLIGHTED_ALPHA_VALUE; |
142 | + else |
143 | + return LINK_NORMAL_ALPHA_VALUE; |
144 | +} |
145 | + |
146 | +void ActionLink::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) |
147 | +{ |
148 | + nux::Geometry const& geo = GetGeometry(); |
149 | + |
150 | + gPainter.PaintBackground(GfxContext, geo); |
151 | + // set up our texture mode |
152 | + nux::TexCoordXForm texxform; |
153 | + texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT); |
154 | + texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); |
155 | + |
156 | + // clear what is behind us |
157 | + unsigned int alpha = 0, src = 0, dest = 0; |
158 | + |
159 | + // set the alpha of the text according to its state |
160 | + static_text_->SetTextAlpha(GetLinkAlpha(GetVisualState())); |
161 | + |
162 | + GfxContext.GetRenderStates().GetBlend(alpha, src, dest); |
163 | + GfxContext.GetRenderStates().SetBlend(true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); |
164 | + |
165 | + nux::Color col = nux::color::Black; |
166 | + col.alpha = 0; |
167 | + GfxContext.QRP_Color(geo.x, |
168 | + geo.y, |
169 | + geo.width, |
170 | + geo.height, |
171 | + col); |
172 | + |
173 | + GfxContext.GetRenderStates().SetBlend(alpha, src, dest); |
174 | + |
175 | + if (GetCompositionLayout()) |
176 | + { |
177 | + gPainter.PushPaintLayerStack(); |
178 | + { |
179 | + |
180 | + GfxContext.PushClippingRectangle(geo); |
181 | + gPainter.PushPaintLayerStack(); |
182 | + GetCompositionLayout()->ProcessDraw(GfxContext, force_draw); |
183 | + gPainter.PopPaintLayerStack(); |
184 | + GfxContext.PopClippingRectangle(); |
185 | + } |
186 | + gPainter.PopPaintLayerStack(); |
187 | + } |
188 | +} |
189 | + |
190 | +void ActionLink::RecvClick(int x, int y, unsigned long button_flags, unsigned long key_flags) |
191 | +{ |
192 | + activate.emit(this, action_hint_); |
193 | +} |
194 | + |
195 | +bool ActionLink::set_aligment(nux::StaticCairoText::AlignState aligment) |
196 | +{ |
197 | + if(static_text_ && aligment_ != aligment) |
198 | + { |
199 | + static_text_->SetTextAlignment(aligment_); |
200 | + aligment_ = aligment; |
201 | + ComputeContentSize(); |
202 | + QueueDraw(); |
203 | + } |
204 | + return true; |
205 | +} |
206 | + |
207 | +nux::StaticCairoText::AlignState ActionLink::get_aligment() |
208 | +{ |
209 | + return aligment_; |
210 | +} |
211 | + |
212 | +bool ActionLink::set_underline(nux::StaticCairoText::UnderlineState underline) |
213 | +{ |
214 | + if(static_text_ && underline_ != underline) |
215 | + { |
216 | + static_text_->SetUnderline(underline_); |
217 | + underline_ = underline; |
218 | + ComputeContentSize(); |
219 | + QueueDraw(); |
220 | + } |
221 | + return true; |
222 | +} |
223 | + |
224 | +nux::StaticCairoText::UnderlineState ActionLink::get_underline() |
225 | +{ |
226 | + return underline_; |
227 | +} |
228 | + |
229 | +bool ActionLink::set_font_hint(std::string font_hint) |
230 | +{ |
231 | + if(static_text_ && font_hint_ != font_hint) |
232 | + { |
233 | + static_text_->SetFont(font_hint_); |
234 | + font_hint_ = font_hint; |
235 | + ComputeContentSize(); |
236 | + QueueDraw(); |
237 | + } |
238 | + return true; |
239 | +} |
240 | + |
241 | +std::string ActionLink::get_font_hint() |
242 | +{ |
243 | + return font_hint_; |
244 | +} |
245 | + |
246 | +std::string ActionLink::GetLabel() const |
247 | +{ |
248 | + return label_; |
249 | +} |
250 | + |
251 | +} // namespace dash |
252 | +} // namespace unity |
253 | |
254 | === added file 'dash/previews/ActionLink.h' |
255 | --- dash/previews/ActionLink.h 1970-01-01 00:00:00 +0000 |
256 | +++ dash/previews/ActionLink.h 2012-11-28 10:01:36 +0000 |
257 | @@ -0,0 +1,100 @@ |
258 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
259 | +/* |
260 | + * Copyright 2012 Canonical Ltd. |
261 | + * |
262 | + * This program is free software: you can redistribute it and/or modify it |
263 | + * under the terms of the GNU Lesser General Public License version 3, as |
264 | + * published by the Free Software Foundation. |
265 | + * |
266 | + * This program is distributed in the hope that it will be useful, but |
267 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
268 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
269 | + * PURPOSE. See the applicable version of the GNU Lesser General Public |
270 | + * License for more details. |
271 | + * |
272 | + * You should have received a copy of both the GNU Lesser General Public |
273 | + * License version 3 along with this program. If not, see |
274 | + * <http://www.gnu.org/licenses/> |
275 | + * |
276 | + * Authored by: Manuel de la Pena <manuel.delapena@canonical.com> |
277 | + * |
278 | + */ |
279 | + |
280 | +#ifndef ACTIONLINK_H |
281 | +#define ACTIONLINK_H |
282 | + |
283 | +#include <Nux/Nux.h> |
284 | +#include <Nux/CairoWrapper.h> |
285 | +#include <Nux/AbstractButton.h> |
286 | +#include "unity-shared/Introspectable.h" |
287 | +#include "unity-shared/StaticCairoText.h" |
288 | + |
289 | + |
290 | +namespace unity |
291 | +{ |
292 | +class IconTexture; |
293 | + |
294 | +namespace dash |
295 | +{ |
296 | + |
297 | +class ActionLink : public nux::AbstractButton, public debug::Introspectable |
298 | +{ |
299 | +public: |
300 | + ActionLink(std::string const& action_hint, std::string const& label, NUX_FILE_LINE_PROTO); |
301 | + |
302 | + sigc::signal<void, ActionLink*, std::string const&> activate; |
303 | + |
304 | + nux::RWProperty<nux::StaticCairoText::AlignState> text_aligment; |
305 | + nux::RWProperty<nux::StaticCairoText::UnderlineState> underline_state; |
306 | + nux::RWProperty<std::string> font_hint; |
307 | + |
308 | + void Activate() {} |
309 | + void Deactivate() {} |
310 | + |
311 | + virtual bool AcceptKeyNavFocus() const { return true; } |
312 | + |
313 | + std::string GetLabel() const; |
314 | + std::string GetExtraText() const; |
315 | + |
316 | +protected: |
317 | + nux::ObjectPtr<nux::StaticCairoText> static_text_; |
318 | + |
319 | + int GetLinkAlpha(nux::ButtonVisualState state); |
320 | + |
321 | + void Draw(nux::GraphicsEngine& GfxContext, bool force_draw); |
322 | + void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) {} |
323 | + void RecvClick(int x, int y, unsigned long button_flags, unsigned long key_flags); |
324 | + |
325 | + void Init(); |
326 | + |
327 | + void BuildLayout(std::string const& label); |
328 | + |
329 | + // From debug::Introspectable |
330 | + std::string GetName() const; |
331 | + void AddProperties(GVariantBuilder* builder); |
332 | + |
333 | + // this methods/vars could be private but are protected to make testing |
334 | + // easier |
335 | + bool set_aligment(nux::StaticCairoText::AlignState aligment); |
336 | + nux::StaticCairoText::AlignState get_aligment(); |
337 | + |
338 | + bool set_underline(nux::StaticCairoText::UnderlineState underline); |
339 | + nux::StaticCairoText::UnderlineState get_underline(); |
340 | + |
341 | + bool set_font_hint(std::string font_hint); |
342 | + std::string get_font_hint(); |
343 | + |
344 | + std::string action_hint_; |
345 | + std::string font_hint_; |
346 | + nux::StaticCairoText::AlignState aligment_; |
347 | + nux::StaticCairoText::UnderlineState underline_; |
348 | +private: |
349 | + typedef std::unique_ptr<nux::CairoWrapper> NuxCairoPtr; |
350 | + |
351 | + |
352 | +}; |
353 | + |
354 | +} // namespace dash |
355 | +} // namespace unity |
356 | + |
357 | +#endif // ACTIONLINK_H |
358 | |
359 | === modified file 'dash/previews/CMakeLists.txt' |
360 | --- dash/previews/CMakeLists.txt 2012-11-26 16:09:53 +0000 |
361 | +++ dash/previews/CMakeLists.txt 2012-11-28 10:01:36 +0000 |
362 | @@ -26,6 +26,7 @@ |
363 | # |
364 | set (PREVIEWS_SOURCES |
365 | ActionButton.cpp |
366 | + ActionLink.cpp |
367 | ApplicationPreview.cpp |
368 | GenericPreview.cpp |
369 | MusicPreview.cpp |
370 | |
371 | === modified file 'tests/CMakeLists.txt' |
372 | --- tests/CMakeLists.txt 2012-11-24 15:34:32 +0000 |
373 | +++ tests/CMakeLists.txt 2012-11-28 10:01:36 +0000 |
374 | @@ -206,6 +206,7 @@ |
375 | # Tests that require X |
376 | add_executable(test-gtest |
377 | test_main.cpp |
378 | + test_action_link.cpp |
379 | test_application_launcher_icon.cpp |
380 | test_bfb_launcher_icon.cpp |
381 | test_dashview_impl.cpp |
382 | |
383 | === added file 'tests/test_action_link.cpp' |
384 | --- tests/test_action_link.cpp 1970-01-01 00:00:00 +0000 |
385 | +++ tests/test_action_link.cpp 2012-11-28 10:01:36 +0000 |
386 | @@ -0,0 +1,188 @@ |
387 | +/* |
388 | + * Copyright 2012 Canonical Ltd. |
389 | + * |
390 | + * This program is free software: you can redistribute it and/or modify it |
391 | + * under the terms of the GNU Lesser General Public License version 3, as |
392 | + * published by the Free Software Foundation. |
393 | + * |
394 | + * This program is distributed in the hope that it will be useful, but |
395 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
396 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
397 | + * PURPOSE. See the applicable version of the GNU Lesser General Public |
398 | + * License for more details. |
399 | + * |
400 | + * You should have received a copy of both the GNU Lesser General Public |
401 | + * License version 3 along with this program. If not, see |
402 | + * <http://www.gnu.org/licenses/> |
403 | + * |
404 | + * Authored by: Manuel de la Pena <manuel.delapena@canonical.com> |
405 | + * |
406 | + */ |
407 | + |
408 | +#include <gmock/gmock.h> |
409 | +#include <gtest/gtest.h> |
410 | + |
411 | +#include <unity-shared/StaticCairoText.h> |
412 | + |
413 | +#include "dash/previews/ActionLink.cpp" |
414 | +#include "test_utils.h" |
415 | + |
416 | +using namespace nux; |
417 | +using namespace unity; |
418 | +using namespace unity::dash; |
419 | + |
420 | +namespace unity |
421 | +{ |
422 | + |
423 | +namespace dash |
424 | +{ |
425 | + |
426 | +class ActionLinkMock : public ActionLink |
427 | +{ |
428 | + public: |
429 | + MOCK_METHOD0(QueueDraw, void()); |
430 | + MOCK_METHOD0(ComputeContentSize, long()); |
431 | + MOCK_METHOD2(CalculateBar, void(nux::GraphicsEngine&, bool)); |
432 | + |
433 | + ActionLinkMock(std::string const& action_hint, std::string const& label, NUX_FILE_LINE_PROTO) |
434 | + : ActionLink(action_hint, label){} |
435 | + ~ActionLinkMock(){} |
436 | + |
437 | + nux::ObjectPtr<nux::StaticCairoText> GetText() { return static_text_; } |
438 | + |
439 | + using ActionLink::GetLinkAlpha; |
440 | + using ActionLink::Draw; |
441 | + using ActionLink::DrawContent; |
442 | + using ActionLink::RecvClick; |
443 | + using ActionLink::GetName; |
444 | + using ActionLink::AddProperties; |
445 | + using ActionLink::set_aligment; |
446 | + using ActionLink::get_aligment; |
447 | + using ActionLink::set_underline; |
448 | + using ActionLink::get_underline; |
449 | + using ActionLink::set_font_hint; |
450 | + using ActionLink::get_font_hint; |
451 | + using ActionLink::action_hint_; |
452 | + using ActionLink::font_hint_; |
453 | + using ActionLink::aligment_; |
454 | + using ActionLink::underline_; |
455 | +}; |
456 | + |
457 | +class TestActionLink : public ::testing::Test |
458 | +{ |
459 | + protected: |
460 | + TestActionLink() : Test() |
461 | + { |
462 | + action_link = new ActionLinkMock("action_id", "display_name"); |
463 | + } |
464 | + nux::ObjectPtr<ActionLinkMock> action_link; |
465 | +}; |
466 | + |
467 | +TEST_F(TestActionLink, AligmentCorrectlySetDifferent) |
468 | +{ |
469 | + ActionLinkMock link("test", "test"); |
470 | + |
471 | + EXPECT_CALL(link, ComputeContentSize()).Times(1); |
472 | + EXPECT_CALL(link, QueueDraw()).Times(1); |
473 | + |
474 | + link.text_aligment.Set(nux::StaticCairoText::NUX_ALIGN_RIGHT); |
475 | +} |
476 | + |
477 | +TEST_F(TestActionLink, AligmentCorrectlySetSame) |
478 | +{ |
479 | + ActionLinkMock link("test", "test"); |
480 | + |
481 | + EXPECT_CALL(link, ComputeContentSize()).Times(0); |
482 | + EXPECT_CALL(link, QueueDraw()).Times(0); |
483 | + |
484 | + link.text_aligment.Set(link.text_aligment.Get()); |
485 | +} |
486 | + |
487 | +TEST_F(TestActionLink, AligmentCorrectlyRetrieved) |
488 | +{ |
489 | + nux::StaticCairoText::AlignState aligment = |
490 | + nux::StaticCairoText::NUX_ALIGN_RIGHT; |
491 | + action_link->aligment_ = aligment; |
492 | + EXPECT_EQ(aligment, action_link->text_aligment.Get()); |
493 | +} |
494 | + |
495 | +TEST_F(TestActionLink, UnderlineCorrectlySetDifferent) |
496 | +{ |
497 | + ActionLinkMock link("test", "test"); |
498 | + |
499 | + EXPECT_CALL(link, ComputeContentSize()).Times(1); |
500 | + EXPECT_CALL(link, QueueDraw()).Times(1); |
501 | + link.underline_state.Set(nux::StaticCairoText::NUX_UNDERLINE_NONE); |
502 | +} |
503 | + |
504 | +TEST_F(TestActionLink, UnderlineCorrectlySetSame) |
505 | +{ |
506 | + ActionLinkMock link("test", "test"); |
507 | + |
508 | + EXPECT_CALL(link, ComputeContentSize()).Times(0); |
509 | + EXPECT_CALL(link, QueueDraw()).Times(0); |
510 | + link.underline_state.Set(link.underline_state.Get()); |
511 | +} |
512 | + |
513 | +TEST_F(TestActionLink, UnderlineCorrectlyRetrieved) |
514 | +{ |
515 | + nux::StaticCairoText::UnderlineState underline = |
516 | + nux::StaticCairoText::NUX_UNDERLINE_DOUBLE; |
517 | + action_link->underline_ = underline; |
518 | + EXPECT_EQ(underline, action_link->underline_state.Get()); |
519 | +} |
520 | + |
521 | +TEST_F(TestActionLink, FontCorrectlySetDifferent) |
522 | +{ |
523 | + ActionLinkMock link("test", "test"); |
524 | + link.font_hint_ = "Ubuntu 10"; |
525 | + |
526 | + EXPECT_CALL(link, ComputeContentSize()).Times(1); |
527 | + EXPECT_CALL(link, QueueDraw()).Times(1); |
528 | + link.font_hint.Set("Ubuntu 11"); |
529 | +} |
530 | + |
531 | +TEST_F(TestActionLink, FontCorrectlySetSame) |
532 | +{ |
533 | + ActionLinkMock link("test", "test"); |
534 | + link.font_hint_ = "Ubuntu 10"; |
535 | + |
536 | + EXPECT_CALL(link, ComputeContentSize()).Times(0); |
537 | + EXPECT_CALL(link, QueueDraw()).Times(0); |
538 | + link.font_hint.Set(link.font_hint.Get()); |
539 | +} |
540 | + |
541 | +TEST_F(TestActionLink, FontCorrectlyRetrieved) |
542 | +{ |
543 | + std::string font_hint = "Ubuntu 11"; |
544 | + action_link->font_hint_ = font_hint; |
545 | + EXPECT_EQ(font_hint, action_link->font_hint.Get()); |
546 | +} |
547 | + |
548 | +TEST_F(TestActionLink, LinkAlphaOnPressed) |
549 | +{ |
550 | + ButtonVisualState state = ButtonVisualState::VISUAL_STATE_PRESSED; |
551 | + EXPECT_EQ(4, action_link->GetLinkAlpha(state)); |
552 | +} |
553 | + |
554 | +TEST_F(TestActionLink, LinkAlphaOnNormal) |
555 | +{ |
556 | + ButtonVisualState state = ButtonVisualState::VISUAL_STATE_NORMAL; |
557 | + EXPECT_EQ(4, action_link->GetLinkAlpha(state)); |
558 | +} |
559 | + |
560 | +TEST_F(TestActionLink, LinkAlphaOnPrelight) |
561 | +{ |
562 | + ButtonVisualState state = ButtonVisualState::VISUAL_STATE_PRELIGHT; |
563 | + EXPECT_EQ(1, action_link->GetLinkAlpha(state)); |
564 | +} |
565 | + |
566 | +TEST_F(TestActionLink, LinkAlphaOnDisabled) |
567 | +{ |
568 | + ButtonVisualState state = ButtonVisualState::VISUAL_STATE_DISABLED; |
569 | + EXPECT_EQ(4, action_link->GetLinkAlpha(state)); |
570 | +} |
571 | + |
572 | +} |
573 | + |
574 | +} |
575 | |
576 | === modified file 'unity-shared/StaticCairoText.cpp' |
577 | --- unity-shared/StaticCairoText.cpp 2012-11-22 10:46:13 +0000 |
578 | +++ unity-shared/StaticCairoText.cpp 2012-11-28 10:01:36 +0000 |
579 | @@ -54,6 +54,7 @@ |
580 | std::string GetEffectiveFont() const; |
581 | Size GetTextExtents() const; |
582 | |
583 | + void SetAttributes(PangoLayout* layout); |
584 | void DrawText(cairo_t* cr, int width, int height, int line_spacing, Color const& color); |
585 | |
586 | void UpdateTexture(); |
587 | @@ -75,6 +76,7 @@ |
588 | EllipsizeState ellipsize_; |
589 | AlignState align_; |
590 | AlignState valign_; |
591 | + UnderlineState underline_; |
592 | |
593 | std::string font_; |
594 | |
595 | @@ -97,6 +99,7 @@ |
596 | , ellipsize_(NUX_ELLIPSIZE_END) |
597 | , align_(NUX_ALIGN_LEFT) |
598 | , valign_(NUX_ALIGN_TOP) |
599 | + , underline_(NUX_UNDERLINE_NONE) |
600 | , lines_(-2) // should find out why -2... |
601 | // the desired height of the layout in Pango units if positive, or desired |
602 | // number of lines if negative. |
603 | @@ -312,6 +315,16 @@ |
604 | } |
605 | } |
606 | |
607 | +void StaticCairoText::SetTextAlpha(unsigned int alpha) |
608 | +{ |
609 | + if (pimpl->text_color_.alpha != alpha) |
610 | + { |
611 | + pimpl->text_color_.alpha = alpha; |
612 | + pimpl->UpdateTexture(); |
613 | + QueueDraw(); |
614 | + } |
615 | +} |
616 | + |
617 | void StaticCairoText::SetMaximumSize(int w, int h) |
618 | { |
619 | if (w != GetMaximumWidth()) |
620 | @@ -320,7 +333,7 @@ |
621 | View::SetMaximumSize(w, h); |
622 | pimpl->UpdateTexture(); |
623 | return; |
624 | - } |
625 | + } |
626 | |
627 | View::SetMaximumSize(w, h); |
628 | } |
629 | @@ -380,6 +393,18 @@ |
630 | return pimpl->font_; |
631 | } |
632 | |
633 | +void StaticCairoText::SetUnderline(UnderlineState underline) |
634 | +{ |
635 | + if (pimpl->underline_ != underline) |
636 | + { |
637 | + pimpl->underline_ = underline; |
638 | + pimpl->need_new_extent_cache_ = true; |
639 | + Size s = GetTextExtents(); |
640 | + SetMinimumHeight(s.height); |
641 | + NeedRedraw(); |
642 | + } |
643 | +} |
644 | + |
645 | int StaticCairoText::GetLineCount() const |
646 | { |
647 | return pimpl->actual_lines_; |
648 | @@ -489,6 +514,37 @@ |
649 | return result; |
650 | } |
651 | |
652 | +void StaticCairoText::Impl::SetAttributes(PangoLayout *layout) |
653 | +{ |
654 | + PangoAttrList* attr_list = NULL; |
655 | + PangoAttribute* underline_attr = NULL; |
656 | + |
657 | + attr_list = pango_layout_get_attributes(layout); |
658 | + if(!attr_list) |
659 | + { |
660 | + attr_list = pango_attr_list_new(); |
661 | + } |
662 | + |
663 | + PangoUnderline underline_type; |
664 | + |
665 | + switch(underline_){ |
666 | + case(NUX_UNDERLINE_SINGLE): |
667 | + underline_type = PANGO_UNDERLINE_SINGLE; |
668 | + break; |
669 | + case(NUX_UNDERLINE_DOUBLE): |
670 | + underline_type = PANGO_UNDERLINE_DOUBLE; |
671 | + break; |
672 | + case(NUX_UNDERLINE_LOW): |
673 | + underline_type = PANGO_UNDERLINE_LOW; |
674 | + break; |
675 | + default: |
676 | + underline_type = PANGO_UNDERLINE_NONE; |
677 | + } |
678 | + underline_attr = pango_attr_underline_new(underline_type); |
679 | + pango_attr_list_insert(attr_list, underline_attr); |
680 | + pango_layout_set_attributes(layout, attr_list); |
681 | +} |
682 | + |
683 | void StaticCairoText::Impl::DrawText(cairo_t* cr, |
684 | int width, |
685 | int height, |
686 | @@ -506,8 +562,9 @@ |
687 | |
688 | cairo_set_font_options(cr, gdk_screen_get_font_options(screen)); |
689 | layout = pango_cairo_create_layout(cr); |
690 | + |
691 | + |
692 | desc = pango_font_description_from_string(font.c_str()); |
693 | - |
694 | pango_layout_set_font_description(layout, desc); |
695 | pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); |
696 | pango_layout_set_ellipsize(layout, GetPangoEllipsizeMode()); |
697 | @@ -518,6 +575,9 @@ |
698 | pango_layout_set_spacing(layout, line_spacing * PANGO_SCALE); |
699 | |
700 | pango_layout_set_height(layout, lines_); |
701 | + |
702 | + SetAttributes(layout); |
703 | + |
704 | pangoCtx = pango_layout_get_context(layout); // is not ref'ed |
705 | pango_cairo_context_set_font_options(pangoCtx, |
706 | gdk_screen_get_font_options(screen)); |
707 | |
708 | === modified file 'unity-shared/StaticCairoText.h' |
709 | --- unity-shared/StaticCairoText.h 2012-11-22 10:46:13 +0000 |
710 | +++ unity-shared/StaticCairoText.h 2012-11-28 10:01:36 +0000 |
711 | @@ -51,6 +51,14 @@ |
712 | NUX_ALIGN_BOTTOM = NUX_ALIGN_RIGHT |
713 | }; |
714 | |
715 | + enum UnderlineState |
716 | + { |
717 | + NUX_UNDERLINE_NONE, |
718 | + NUX_UNDERLINE_SINGLE, |
719 | + NUX_UNDERLINE_DOUBLE, |
720 | + NUX_UNDERLINE_LOW |
721 | + }; |
722 | + |
723 | StaticCairoText(std::string const& text, NUX_FILE_LINE_PROTO); |
724 | StaticCairoText(std::string const& text, bool escape_text, NUX_FILE_LINE_PROTO); |
725 | ~StaticCairoText(); |
726 | @@ -67,12 +75,14 @@ |
727 | |
728 | // public API |
729 | void SetText(std::string const& text, bool escape_text = false); |
730 | + void SetTextAlpha(unsigned int alpha); |
731 | void SetTextColor(Color const& textColor); |
732 | void SetTextEllipsize(EllipsizeState state); |
733 | void SetTextAlignment(AlignState state); |
734 | void SetTextVerticalAlignment(AlignState state); |
735 | void SetFont(std::string const& font); |
736 | std::string GetFont(); |
737 | + void SetUnderline(UnderlineState underline); |
738 | void SetLines(int maximum_lines); |
739 | void SetLineSpacing(float line_spacing); |
740 |
Firstly, you need to watch out when copying classes. You should do a full code check to make sure there is nothing left over that isn't used in the new class, and anything (defs/comment) that references the old class.
I don't think this belongs to the AbstractButton scope; it's more in the StaticCairoText area, seeing as that's all a link really is as far as I'm aware (a label which you can click). You can then put the mouse/keyboard activation into the overriding class.
Other than that, here are a few code comments.
34 +namespace :Logger logger( "unity. dash.actionlink ");
35 +{
36 +
37 +
38 +nux::logging:
39 +}
remove extra white-space
99 +void ActionLink: :BuildLayout( std::string const& label, std::string const& extra_hint)
no extra_hint in an action link.
94 + cr_normal_ .reset( new nux::CairoWrapp er(geo,
95 + [](nux::Geometry const& geom, cairo_t* cr) {}));
You're not using the texture, so remove it from the class/drawing. (left over from ActionButton)
Underline: Can you not use font/markup to do the underlining instead of a fairly hacky hseparator?