Merge lp:~mandel/unity/add-text-entry 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: 2849
Proposed branch: lp:~mandel/unity/add-text-entry
Merge into: lp:unity
Diff against target: 489 lines (+469/-0)
3 files modified
unity-shared/CMakeLists.txt (+1/-0)
unity-shared/TextInput.cpp (+366/-0)
unity-shared/TextInput.h (+102/-0)
To merge this branch: bzr merge lp:~mandel/unity/add-text-entry
Reviewer Review Type Date Requested Status
Nick Dedekind (community) Approve
PS Jenkins bot continuous-integration Pending
Review via email: mp+128504@code.launchpad.net

Commit message

- Add a text entry ui element that follows the design from the search bar so that previews can get input form the users (lp: #1063735).

Description of the change

- Add a text entry ui element that follows the design from the search bar so that previews can get input form the users (lp: #1063735).

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

Havent finished looking at it, but here are a few points I have so far.

53 +const int LIVE_SEARCH_TIMEOUT = 40;
55 +const int SPACE_BETWEEN_SPINNER_AND_TEXT = 5;
58 +const int SEARCH_ENTRY_RIGHT_BORDER = 10;

This isn't a search bar, and there is no spinner.

120 +TextInput::TextInput(NUX_FILE_LINE_DECL)
121 + : View(NUX_FILE_LINE_PARAM)
122 + , input_hint("")
123 + , last_width_(-1)
124 + , last_height_(-1)
125 +{
126 + Init();
127 +}
128 +
129 +TextInput::TextInput(bool show_filter_hint_, NUX_FILE_LINE_DECL)
130 + : View(NUX_FILE_LINE_PARAM)
131 + , input_hint("")
132 + , last_width_(-1)
133 + , last_height_(-1)

Not initialising the show_filter_hint_ member

174 + OnFontChanged(gtk_settings_get_default())

If you're not going to have a connection to the gtk font change signal, then it probably shouldn't be called OnFontChanged. Also, why no connection to gtk font update signal?

review: Needs Fixing
Revision history for this message
Manuel de la Peña (mandel) wrote :

> Havent finished looking at it, but here are a few points I have so far.
>
> 53 +const int LIVE_SEARCH_TIMEOUT = 40;
> 55 +const int SPACE_BETWEEN_SPINNER_AND_TEXT = 5;
> 58 +const int SEARCH_ENTRY_RIGHT_BORDER = 10;
>

Nice catch, I started based on the search bar and forgot to clean up those.

> This isn't a search bar, and there is no spinner.
>
> 120 +TextInput::TextInput(NUX_FILE_LINE_DECL)
> 121 + : View(NUX_FILE_LINE_PARAM)
> 122 + , input_hint("")
> 123 + , last_width_(-1)
> 124 + , last_height_(-1)
> 125 +{
> 126 + Init();
> 127 +}
> 128 +
> 129 +TextInput::TextInput(bool show_filter_hint_, NUX_FILE_LINE_DECL)
> 130 + : View(NUX_FILE_LINE_PARAM)
> 131 + , input_hint("")
> 132 + , last_width_(-1)
> 133 + , last_height_(-1)
>
> Not initialising the show_filter_hint_ member
>

Doing it.

> 174 + OnFontChanged(gtk_settings_get_default())
>
> If you're not going to have a connection to the gtk font change signal, then
> it probably shouldn't be called OnFontChanged. Also, why no connection to gtk
> font update signal?

Mistake in my part, connecting to the gtk signal is the way to go

Revision history for this message
Manuel de la Peña (mandel) wrote :

> > Havent finished looking at it, but here are a few points I have so far.
> >
> > 53 +const int LIVE_SEARCH_TIMEOUT = 40;
> > 55 +const int SPACE_BETWEEN_SPINNER_AND_TEXT = 5;
> > 58 +const int SEARCH_ENTRY_RIGHT_BORDER = 10;
> >
>
> Nice catch, I started based on the search bar and forgot to clean up those.
>
> > This isn't a search bar, and there is no spinner.
> >
> > 120 +TextInput::TextInput(NUX_FILE_LINE_DECL)
> > 121 + : View(NUX_FILE_LINE_PARAM)
> > 122 + , input_hint("")
> > 123 + , last_width_(-1)
> > 124 + , last_height_(-1)
> > 125 +{
> > 126 + Init();
> > 127 +}
> > 128 +
> > 129 +TextInput::TextInput(bool show_filter_hint_, NUX_FILE_LINE_DECL)
> > 130 + : View(NUX_FILE_LINE_PARAM)
> > 131 + , input_hint("")
> > 132 + , last_width_(-1)
> > 133 + , last_height_(-1)
> >
> > Not initialising the show_filter_hint_ member
> >
>
> Doing it.
>
> > 174 + OnFontChanged(gtk_settings_get_default())
> >
> > If you're not going to have a connection to the gtk font change signal, then
> > it probably shouldn't be called OnFontChanged. Also, why no connection to
> gtk
> > font update signal?
>
> Mistake in my part, connecting to the gtk signal is the way to go

Everything has been fixed in the latest version.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

In this way there is a lot of code duplication in SearchBar and TextInput. In some ways we can avoid this. What do you think?

Revision history for this message
Manuel de la Peña (mandel) wrote :

> In this way there is a lot of code duplication in SearchBar and TextInput. In
> some ways we can avoid this. What do you think?

I'm more than happy to re-factor the code, but is that something that all agree with? Bare in mind that there is a number of important differences between the two of them:

* timer for the searches
* spinner
* search icon (the magnifier)

We can surely make the text entry be flexible enough to be able to be hooked with signals that can be used for the searches and the timer. I'm not that sure about the changes to be done in the layout to accommodate the spinner and the icon.

Revision history for this message
Omer Akram (om26er) wrote :

19 + * Copyright (C) 2010-2011 Canonical Ltd
400 + * Copyright (C) 2010 Canonical Ltd

wrong years ?

33 + * Authored by: Manuel de la Pena

please add <email address hidden> as well.

Revision history for this message
Manuel de la Peña (mandel) wrote :

> 19 + * Copyright (C) 2010-2011 Canonical Ltd
> 400 + * Copyright (C) 2010 Canonical Ltd
>
> wrong years ?
>
> 33 + * Authored by: Manuel de la Pena
>
> please add <email address hidden> as well.
Fix, sorry I yy the headers.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> > In this way there is a lot of code duplication in SearchBar and TextInput.
> In
> > some ways we can avoid this. What do you think?
>
> I'm more than happy to re-factor the code, but is that something that all
> agree with? Bare in mind that there is a number of important differences
> between the two of them:
>
> * timer for the searches
> * spinner
> * search icon (the magnifier)
>
> We can surely make the text entry be flexible enough to be able to be hooked
> with signals that can be used for the searches and the timer. I'm not that
> sure about the changes to be done in the layout to accommodate the spinner and
> the icon.

Ok never mind ;) Will be done later.

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

Still a reference to SPACE_BETWEEN_SPINNER_AND_TEXT

203 + gchar* tmp = g_markup_escape_text(input_hint().c_str(), -1);
204 +
205 + hint_->SetText(tmp);
206 +
207 + g_free(tmp);

not wrong, but you should use glib::String since we have it.

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

137 + entry_layout_ = new nux::HLayout(NUX_TRACKER_LOCATION);

only one item in this layout, so you shouldnt actually need it.

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

LGTM.

review: Approve
Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

I don't see any test on it?

Revision history for this message
Manuel de la Peña (mandel) wrote :

Indeed, I really don't know how to test this thing... if you point me to an example I can always take a look and add them in a following branch.

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

Manuel, just give a look to the tests we alredy have in the tests subfolder (also give a look to test_im_text_entry.cpp, it should be good as a base); I think you sould basically try to test any new method you've added.

Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

You can ask to other unity-team members for how to use unit tests. I think that mmrazik and his team will be able to help you as well (there are quite a lot of tests in the unity trunk itself.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'unity-shared/CMakeLists.txt'
2--- unity-shared/CMakeLists.txt 2012-10-11 11:04:13 +0000
3+++ unity-shared/CMakeLists.txt 2012-10-17 10:34:19 +0000
4@@ -53,6 +53,7 @@
5 SearchBarSpinner.cpp
6 StaticCairoText.cpp
7 TextureCache.cpp
8+ TextInput.cpp
9 TextureThumbnailProvider.cpp
10 ThumbnailGenerator.cpp
11 Timer.cpp
12
13=== added file 'unity-shared/TextInput.cpp'
14--- unity-shared/TextInput.cpp 1970-01-01 00:00:00 +0000
15+++ unity-shared/TextInput.cpp 2012-10-17 10:34:19 +0000
16@@ -0,0 +1,366 @@
17+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
18+/*
19+ * Copyright (C) 2012 Canonical Ltd
20+ *
21+ * This program is free software: you can redistribute it and/or modify
22+ * it under the terms of the GNU General Public License version 3 as
23+ * published by the Free Software Foundation.
24+ *
25+ * This program is distributed in the hope that it will be useful,
26+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28+ * GNU General Public License for more detais.
29+ *
30+ * You shoud have received a copy of the GNU General Public License
31+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
32+ *
33+ * Authored by: Manuel de la Pena <manuel.delapena@canonical.com>
34+ */
35+
36+#include "config.h"
37+
38+#include <Nux/Nux.h>
39+#include <Nux/HLayout.h>
40+#include <Nux/VLayout.h>
41+#include <NuxCore/Logger.h>
42+
43+#include <UnityCore/Variant.h>
44+
45+#include <glib/gi18n-lib.h>
46+
47+#include "TextInput.h"
48+#include "CairoTexture.h"
49+
50+namespace
51+{
52+const float kExpandDefaultIconOpacity = 1.0f;
53+
54+const int SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT = 10;
55+const int LEFT_INTERNAL_PADDING = 6;
56+const int TEXT_INPUT_RIGHT_BORDER = 10;
57+
58+const int HIGHLIGHT_HEIGHT = 24;
59+
60+// Fonts
61+const std::string HINT_LABEL_FONT_SIZE = "12px";
62+const std::string HINT_LABEL_FONT_STYLE = "Italic";
63+const std::string HINT_LABEL_DEFAULT_FONT = "Ubuntu " + HINT_LABEL_FONT_STYLE + " " + HINT_LABEL_FONT_SIZE;
64+
65+const std::string PANGO_ENTRY_DEFAULT_FONT_FAMILY = "Ubuntu";
66+const int PANGO_ENTRY_FONT_SIZE = 14;
67+
68+}
69+
70+namespace
71+{
72+
73+nux::logging::Logger logger("unity");
74+
75+class ExpanderView : public nux::View
76+{
77+public:
78+ ExpanderView(NUX_FILE_LINE_DECL)
79+ : nux::View(NUX_FILE_LINE_PARAM)
80+ {
81+ SetAcceptKeyNavFocusOnMouseDown(false);
82+ SetAcceptKeyNavFocusOnMouseEnter(true);
83+ }
84+
85+protected:
86+ void Draw(nux::GraphicsEngine& graphics_engine, bool force_draw)
87+ {}
88+
89+ void DrawContent(nux::GraphicsEngine& graphics_engine, bool force_draw)
90+ {
91+ if (GetLayout())
92+ GetLayout()->ProcessDraw(graphics_engine, force_draw);
93+ }
94+
95+ bool AcceptKeyNavFocus()
96+ {
97+ return true;
98+ }
99+
100+ nux::Area* FindAreaUnderMouse(const nux::Point& mouse_position, nux::NuxEventType event_type)
101+ {
102+ bool mouse_inside = TestMousePointerInclusionFilterMouseWheel(mouse_position, event_type);
103+
104+ if (mouse_inside == false)
105+ return nullptr;
106+
107+ return this;
108+ }
109+};
110+
111+}
112+
113+namespace unity
114+{
115+
116+NUX_IMPLEMENT_OBJECT_TYPE(TextInput);
117+
118+TextInput::TextInput(NUX_FILE_LINE_DECL)
119+ : View(NUX_FILE_LINE_PARAM)
120+ , input_hint("")
121+ , last_width_(-1)
122+ , last_height_(-1)
123+{
124+ Init();
125+}
126+
127+void TextInput::Init()
128+{
129+ bg_layer_.reset(new nux::ColorLayer(nux::Color(0xff595853), true));
130+
131+ layout_ = new nux::HLayout(NUX_TRACKER_LOCATION);
132+ layout_->SetLeftAndRightPadding(LEFT_INTERNAL_PADDING, TEXT_INPUT_RIGHT_BORDER);
133+ layout_->SetSpaceBetweenChildren(SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT);
134+ SetLayout(layout_);
135+
136+ nux::HLayout* hint_layout = new nux::HLayout(NUX_TRACKER_LOCATION);
137+
138+ hint_ = new nux::StaticCairoText(" ");
139+ hint_->SetTextColor(nux::Color(1.0f, 1.0f, 1.0f, 0.5f));
140+ hint_->SetFont(HINT_LABEL_DEFAULT_FONT.c_str());
141+ hint_layout->AddView(hint_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
142+
143+ pango_entry_ = new IMTextEntry();
144+ pango_entry_->SetFontFamily(PANGO_ENTRY_DEFAULT_FONT_FAMILY.c_str());
145+ pango_entry_->SetFontSize(PANGO_ENTRY_FONT_SIZE);
146+ pango_entry_->cursor_moved.connect([&](int i) { QueueDraw(); });
147+ pango_entry_->mouse_down.connect(sigc::mem_fun(this, &TextInput::OnMouseButtonDown));
148+ pango_entry_->end_key_focus.connect(sigc::mem_fun(this, &TextInput::OnEndKeyFocus));
149+
150+ layered_layout_ = new nux::LayeredLayout();
151+ layered_layout_->AddLayout(hint_layout);
152+ layered_layout_->AddLayer(pango_entry_);
153+ layered_layout_->SetPaintAll(true);
154+ layered_layout_->SetActiveLayerN(1);
155+ layout_->AddView(layered_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FIX);
156+
157+ sig_manager_.Add<void, GtkSettings*, GParamSpec*>(gtk_settings_get_default(),
158+ "notify::gtk-font-name", sigc::mem_fun(this, &TextInput::OnFontChanged));
159+ OnFontChanged(gtk_settings_get_default());
160+
161+ input_string.SetGetterFunction(sigc::mem_fun(this, &TextInput::get_input_string));
162+ input_string.SetSetterFunction(sigc::mem_fun(this, &TextInput::set_input_string));
163+ im_active.SetGetterFunction(sigc::mem_fun(this, &TextInput::get_im_active));
164+ im_preedit.SetGetterFunction(sigc::mem_fun(this, &TextInput::get_im_preedit));
165+ input_hint.changed.connect([&](std::string const& s) { OnInputHintChanged(); });
166+
167+}
168+
169+void TextInput::OnFontChanged(GtkSettings* settings, GParamSpec* pspec)
170+{
171+ glib::String font_name;
172+ PangoFontDescription* desc;
173+ std::ostringstream font_desc;
174+
175+ g_object_get(settings, "gtk-font-name", &font_name, NULL);
176+
177+ desc = pango_font_description_from_string(font_name.Value());
178+ if (desc)
179+ {
180+ pango_entry_->SetFontFamily(pango_font_description_get_family(desc));
181+ pango_entry_->SetFontSize(PANGO_ENTRY_FONT_SIZE);
182+ pango_entry_->SetFontOptions(gdk_screen_get_font_options(gdk_screen_get_default()));
183+
184+ font_desc << pango_font_description_get_family(desc) << " " << HINT_LABEL_FONT_STYLE << " " << HINT_LABEL_FONT_SIZE;
185+ hint_->SetFont(font_desc.str().c_str());
186+
187+ font_desc.str("");
188+ font_desc.clear();
189+
190+ pango_font_description_free(desc);
191+ }
192+}
193+
194+void TextInput::OnInputHintChanged()
195+{
196+ glib::String tmp(g_markup_escape_text(input_hint().c_str(), -1));
197+ hint_->SetText(tmp);
198+}
199+
200+void TextInput::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
201+{
202+ nux::Geometry const& base = GetGeometry();
203+
204+ UpdateBackground(false);
205+
206+ GfxContext.PushClippingRectangle(base);
207+ nux::GetPainter().PaintBackground(GfxContext, base);
208+
209+ bg_layer_->SetGeometry(nux::Geometry(base.x, base.y, last_width_, last_height_));
210+ nux::GetPainter().RenderSinglePaintLayer(GfxContext,
211+ bg_layer_->GetGeometry(),
212+ bg_layer_.get());
213+
214+ GfxContext.PopClippingRectangle();
215+}
216+
217+void TextInput::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
218+{
219+ nux::Geometry const& geo = GetGeometry();
220+
221+ GfxContext.PushClippingRectangle(geo);
222+
223+ if (highlight_layer_ && ShouldBeHighlighted() && !IsFullRedraw())
224+ {
225+ nux::GetPainter().PushLayer(GfxContext, highlight_layer_->GetGeometry(), highlight_layer_.get());
226+ }
227+
228+
229+ if (!IsFullRedraw())
230+ {
231+ gPainter.PushLayer(GfxContext, bg_layer_->GetGeometry(), bg_layer_.get());
232+ }
233+ else
234+ {
235+ nux::GetPainter().PushPaintLayerStack();
236+ }
237+
238+ layout_->ProcessDraw(GfxContext, force_draw);
239+
240+ if (!IsFullRedraw())
241+ {
242+ gPainter.PopBackground();
243+ }
244+ else
245+ {
246+ nux::GetPainter().PopPaintLayerStack();
247+ }
248+
249+ GfxContext.PopClippingRectangle();
250+}
251+
252+void TextInput::UpdateBackground(bool force)
253+{
254+ int RADIUS = 5;
255+ nux::Geometry geo(GetGeometry());
256+ geo.width = layered_layout_->GetAbsoluteX() +
257+ layered_layout_->GetAbsoluteWidth() -
258+ GetAbsoluteX() +
259+ TEXT_INPUT_RIGHT_BORDER;
260+
261+ LOG_DEBUG(logger) << "height: "
262+ << geo.height << " - "
263+ << layered_layout_->GetGeometry().height << " - "
264+ << pango_entry_->GetGeometry().height;
265+
266+ if (geo.width == last_width_
267+ && geo.height == last_height_
268+ && force == false)
269+ return;
270+
271+ last_width_ = geo.width;
272+ last_height_ = geo.height;
273+
274+ nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, last_width_, last_height_);
275+ cairo_t* cr = cairo_graphics.GetContext();
276+
277+ cairo_graphics.DrawRoundedRectangle(cr,
278+ 1.0f,
279+ 0.5, 0.5,
280+ RADIUS,
281+ last_width_ - 1, last_height_ - 1,
282+ false);
283+
284+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
285+ cairo_set_source_rgba(cr, 0.0f, 0.0f, 0.0f, 0.35f);
286+ cairo_fill_preserve(cr);
287+ cairo_set_line_width(cr, 1);
288+ cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 0.7f);
289+ cairo_stroke(cr);
290+
291+ cairo_destroy(cr);
292+ nux::BaseTexture* texture2D = texture_from_cairo_graphics(cairo_graphics);
293+
294+ nux::TexCoordXForm texxform;
295+ texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
296+ texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
297+
298+ nux::ROPConfig rop;
299+ rop.Blend = true;
300+ rop.SrcBlend = GL_ONE;
301+ rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
302+
303+ bg_layer_.reset(new nux::TextureLayer(texture2D->GetDeviceTexture(),
304+ texxform,
305+ nux::color::White,
306+ true,
307+ rop));
308+
309+ texture2D->UnReference();
310+}
311+
312+void TextInput::OnMouseButtonDown(int x, int y, unsigned long button, unsigned long key)
313+{
314+ hint_->SetVisible(false);
315+}
316+
317+void TextInput::OnEndKeyFocus()
318+{
319+ hint_->SetVisible(input_string().empty());
320+}
321+
322+
323+nux::TextEntry* TextInput::text_entry() const
324+{
325+ return pango_entry_;
326+}
327+
328+std::string TextInput::get_input_string() const
329+{
330+ return pango_entry_->GetText();
331+}
332+
333+bool TextInput::set_input_string(std::string const& string)
334+{
335+ pango_entry_->SetText(string.c_str());
336+ return true;
337+}
338+
339+bool TextInput::get_im_active() const
340+{
341+ return pango_entry_->im_active();
342+}
343+
344+bool TextInput::get_im_preedit() const
345+{
346+ return pango_entry_->im_preedit();
347+}
348+
349+//
350+// Highlight
351+//
352+bool TextInput::ShouldBeHighlighted()
353+{
354+ return true;
355+}
356+
357+//
358+// Key navigation
359+//
360+bool TextInput::AcceptKeyNavFocus()
361+{
362+ return false;
363+}
364+
365+//
366+// Introspection
367+//
368+std::string TextInput::GetName() const
369+{
370+ return "TextInput";
371+}
372+
373+void TextInput::AddProperties(GVariantBuilder* builder)
374+{
375+ unity::variant::BuilderWrapper(builder)
376+ .add(GetAbsoluteGeometry())
377+ .add("has_focus", pango_entry_->HasKeyFocus())
378+ .add("input_string", pango_entry_->GetText())
379+ .add("im_active", pango_entry_->im_active());
380+}
381+
382+} // namespace unity
383
384=== added file 'unity-shared/TextInput.h'
385--- unity-shared/TextInput.h 1970-01-01 00:00:00 +0000
386+++ unity-shared/TextInput.h 2012-10-17 10:34:19 +0000
387@@ -0,0 +1,102 @@
388+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
389+/*
390+ * Copyright (C) 2012 Canonical Ltd
391+ *
392+ * This program is free software: you can redistribute it and/or modify
393+ * it under the terms of the GNU General Public License version 3 as
394+ * published by the Free Software Foundation.
395+ *
396+ * This program is distributed in the hope that it will be useful,
397+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
398+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
399+ * GNU General Public License for more details.
400+ *
401+ * You should have received a copy of the GNU General Public License
402+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
403+ *
404+ * Authored by: Manuel de la Pena <manuel.delapena@canonical.com>
405+ */
406+
407+#ifndef TEXTINPUT_H
408+#define TEXTINPUT_H
409+
410+#include <gtk/gtk.h>
411+#include <NuxCore/Property.h>
412+#include <Nux/LayeredLayout.h>
413+#include <Nux/VLayout.h>
414+#include <Nux/TextEntry.h>
415+#include <UnityCore/GLibSignal.h>
416+#include <UnityCore/GLibSource.h>
417+
418+#include "unity-shared/IconTexture.h"
419+#include "unity-shared/IMTextEntry.h"
420+#include "unity-shared/Introspectable.h"
421+#include "unity-shared/StaticCairoText.h"
422+
423+namespace nux
424+{
425+class AbstractPaintLayer;
426+class LinearLayout;
427+}
428+
429+namespace unity
430+{
431+
432+class TextInput : public unity::debug::Introspectable, public nux::View
433+{
434+ NUX_DECLARE_OBJECT_TYPE(TextInput, nux::View);
435+public:
436+ typedef nux::ObjectPtr<TextInput> Ptr;
437+ TextInput(NUX_FILE_LINE_PROTO);
438+ TextInput(bool show_filter_hint, NUX_FILE_LINE_PROTO);
439+
440+ nux::TextEntry* text_entry() const;
441+
442+ nux::RWProperty<std::string> input_string;
443+ nux::Property<std::string> input_hint;
444+ nux::ROProperty<bool> im_active;
445+ nux::ROProperty<bool> im_preedit;
446+
447+private:
448+
449+ void Init();
450+
451+ void OnFontChanged(GtkSettings* settings, GParamSpec* pspec=NULL);
452+ void OnInputHintChanged();
453+
454+ void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
455+ void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
456+
457+ void OnMouseButtonDown(int x, int y, unsigned long button_flags, unsigned long key_flags);
458+ void OnEndKeyFocus();
459+
460+ void UpdateBackground(bool force);
461+
462+ std::string get_input_string() const;
463+ bool set_input_string(std::string const& string);
464+ bool get_im_active() const;
465+ bool get_im_preedit() const;
466+
467+ std::string GetName() const;
468+ void AddProperties(GVariantBuilder* builder);
469+ bool AcceptKeyNavFocus();
470+
471+private:
472+ bool ShouldBeHighlighted();
473+
474+ std::unique_ptr<nux::AbstractPaintLayer> bg_layer_;
475+ std::unique_ptr<nux::AbstractPaintLayer> highlight_layer_;
476+ nux::HLayout* layout_;
477+ nux::LayeredLayout* layered_layout_;
478+ nux::StaticCairoText* hint_;
479+ IMTextEntry* pango_entry_;
480+
481+ int last_width_;
482+ int last_height_;
483+
484+ glib::SignalManager sig_manager_;
485+};
486+
487+}
488+
489+#endif