Merge lp:~mandel/unity/add-action-link into lp:unity

Proposed by Manuel de la Peña
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
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).

To post a comment you must log in.
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

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
35 +{
36 +
37 +
38 +nux::logging::Logger logger("unity.dash.actionlink");
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::CairoWrapper(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?

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Please, add tests too.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

56 +ActionLink::~ActionLink()
57 +{
58 +}

Get rid of it

Revision history for this message
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! ;)

review: Approve
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

50 + SetAcceptKeyNavFocusOnMouseDown(false);
51 + SetAcceptKeyNavFocusOnMouseEnter(true);

Since you have an Init function, you should put these in there.

73 + SetMinimumHeight(40);

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_text_->SetTextAlignment(nux::StaticCairoText::NUX_ALIGN_CENTRE);
106 + static_text_->SetUnderline(nux::StaticCairoText::NUX_UNDERLINE_SINGLE)

Since this is a general control these should be options on the action link, which are defaulted to these values. (SetTextAlignment/SetTextUnderline)

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.

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

LGTM.
All tests run successfully.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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