43
43
nux::logging::Logger logger("unity.dash.view");
47
// This is so we can access some protected members in nux::VLayout and
48
// break the natural key navigation path.
49
class DashLayout: public nux::VLayout
52
DashLayout(NUX_FILE_LINE_DECL)
53
: nux::VLayout(NUX_FILE_LINE_PARAM)
57
void SetSpecialArea(nux::Area* area)
63
nux::Area* KeyNavIteration(nux::KeyNavDirection direction)
65
if (direction == nux::KEY_NAV_DOWN && area_ && area_->HasKeyFocus())
68
return nux::VLayout::KeyNavIteration(direction);
46
75
NUX_IMPLEMENT_OBJECT_TYPE(DashView);
48
77
DashView::DashView()
49
78
: nux::View(NUX_TRACKER_LOCATION)
79
, home_lens_(new HomeLens(_("Home"), _("Home screen"), _("Search")))
50
80
, active_lens_view_(0)
51
81
, last_activated_uri_("")
52
82
, searching_timeout_id_(0)
53
83
, search_in_progress_(false)
54
84
, activate_on_finish_(false)
85
, hide_message_delay_id_(0)
57
88
renderer_.SetOwner(this);
75
108
if (searching_timeout_id_)
76
109
g_source_remove (searching_timeout_id_);
110
if (hide_message_delay_id_)
111
g_source_remove(hide_message_delay_id_);
114
void DashView::SetMonitorOffset(int x, int y)
116
renderer_.x_offset = x;
117
renderer_.y_offset = y;
79
120
void DashView::AboutToShow()
81
122
ubus_manager_.SendMessage(UBUS_BACKGROUND_REQUEST_COLOUR_EMIT);
83
124
search_bar_->text_entry()->SelectAll();
126
/* Give the lenses a chance to prep data before we map them */
127
lens_bar_->Activate(active_lens_view_->lens()->id());
128
if (active_lens_view_->lens()->id() == "home.lens")
130
for (auto lens : lenses_.GetLenses())
132
lens->view_type = ViewType::HOME_VIEW;
133
LOG_DEBUG(logger) << "Setting ViewType " << ViewType::HOME_VIEW
134
<< " on '" << lens->id() << "'";
137
home_lens_->view_type = ViewType::LENS_VIEW;
138
LOG_DEBUG(logger) << "Setting ViewType " << ViewType::LENS_VIEW
139
<< " on '" << home_lens_->id() << "'";
84
142
renderer_.AboutToShow();
90
148
renderer_.AboutToHide();
150
for (auto lens : lenses_.GetLenses())
152
lens->view_type = ViewType::HIDDEN;
153
LOG_DEBUG(logger) << "Setting ViewType " << ViewType::HIDDEN
154
<< " on '" << lens->id() << "'";
157
home_lens_->view_type = ViewType::HIDDEN;
158
LOG_DEBUG(logger) << "Setting ViewType " << ViewType::HIDDEN
159
<< " on '" << home_lens_->id() << "'";
93
162
void DashView::SetupViews()
95
164
layout_ = new nux::VLayout();
96
165
SetLayout(layout_);
98
content_layout_ = new nux::VLayout();
167
content_layout_ = new DashLayout(NUX_TRACKER_LOCATION);
99
168
content_layout_->SetHorizontalExternalMargin(0);
100
169
content_layout_->SetVerticalExternalMargin(0);
107
176
search_bar_->live_search_reached.connect(sigc::mem_fun(this, &DashView::OnLiveSearchReached));
108
177
search_bar_->showing_filters.changed.connect([&] (bool showing) { if (active_lens_view_) active_lens_view_->filters_expanded = showing; QueueDraw(); });
109
178
content_layout_->AddView(search_bar_, 0, nux::MINOR_POSITION_LEFT);
179
content_layout_->SetSpecialArea(search_bar_->show_filters());
111
181
lenses_layout_ = new nux::VLayout();
112
182
content_layout_->AddView(lenses_layout_, 1, nux::MINOR_POSITION_LEFT);
114
home_view_ = new HomeView();
184
home_view_ = new LensView(home_lens_, nullptr);
185
AddChild(home_view_);
115
186
active_lens_view_ = home_view_;
116
lens_views_["home.lens"] = home_view_;
187
lens_views_[home_lens_->id] = home_view_;
117
188
lenses_layout_->AddView(home_view_);
119
190
lens_bar_ = new LensBar();
120
192
lens_bar_->lens_activated.connect(sigc::mem_fun(this, &DashView::OnLensBarActivated));
121
193
content_layout_->AddView(lens_bar_, 0, nux::MINOR_POSITION_CENTER);
182
254
width = MAX(width, tile_width * 6);
184
width += 19 + 32; // add the left padding and the group plugin padding
256
width += 19 + 40; // add the left padding and the group plugin padding
186
258
height = search_bar_->GetGeometry().height;
187
259
height += tile_height * 3;
380
gboolean DashView::HideResultMessageCb(gpointer data)
382
DashView *self = static_cast<DashView*>(data);
384
self->active_lens_view_->HideResultsMessage();
385
self->hide_message_delay_id_ = 0;
309
390
void DashView::OnSearchChanged(std::string const& search_string)
311
392
LOG_DEBUG(logger) << "Search changed: " << search_string;
317
398
if (searching_timeout_id_)
319
400
g_source_remove (searching_timeout_id_);
401
searching_timeout_id_ = 0;
321
404
// 250ms for the Search method call, rest for the actual search
322
405
searching_timeout_id_ = g_timeout_add (500, &DashView::ResetSearchStateCb, this);
408
if (hide_message_delay_id_)
410
g_source_remove(hide_message_delay_id_);
411
hide_message_delay_id_ = 0;
414
// 150ms to hide the no reults message if its take a while to return results
415
hide_message_delay_id_ = g_timeout_add (150, &DashView::HideResultMessageCb, this);
337
430
std::string id = lens->id;
338
431
lens_bar_->AddLens(lens);
339
home_view_->AddLens(lens);
341
LensView* view = new LensView(lens);
433
LensView* view = new LensView(lens, search_bar_->show_filters());
342
435
view->SetVisible(false);
343
436
view->uri_activated.connect(sigc::mem_fun(this, &DashView::OnUriActivated));
344
437
lenses_layout_->AddView(view, 1);
362
455
for (auto it: lens_views_)
364
457
bool id_matches = it.first == id;
458
ViewType view_type = id_matches ? LENS_VIEW : (view == home_view_ ? HOME_VIEW : HIDDEN);
365
459
it.second->SetVisible(id_matches);
366
it.second->view_type = id_matches ? LENS_VIEW : (view == home_view_ ? HOME_VIEW : HIDDEN);
460
it.second->view_type = view_type;
462
LOG_DEBUG(logger) << "Setting ViewType " << view_type
463
<< " on '" << it.first << "'";
369
466
search_bar_->search_string = view->search_string;
370
if (view != home_view_)
371
search_bar_->search_hint = view->lens()->search_hint;
373
search_bar_->search_hint = _("Search");
467
search_bar_->search_hint = view->lens()->search_hint;
374
469
bool expanded = view->filters_expanded;
375
470
search_bar_->showing_filters = expanded;
472
nux::GetWindowCompositor().SetKeyFocusArea(default_focus());
377
474
search_bar_->text_entry()->SelectAll();
379
476
search_bar_->can_refine_search = view->can_refine_search();
478
if (hide_message_delay_id_)
480
g_source_remove(hide_message_delay_id_);
481
hide_message_delay_id_ = 0;
381
484
view->QueueDraw();
385
488
void DashView::OnSearchFinished(Lens::Hints const& hints)
387
Lens::Hints::const_iterator it;
388
it = hints.find("no-results-hint");
390
if (it != hints.end())
490
if (hide_message_delay_id_)
392
LOG_DEBUG(logger) << "We have no-results-hint: " << g_variant_get_string (it->second, NULL);
492
g_source_remove(hide_message_delay_id_);
493
hide_message_delay_id_ = 0;
496
active_lens_view_->CheckNoResults(hints);
395
498
std::string search_string = search_bar_->search_string;
396
499
if (active_lens_view_ && active_lens_view_->search_string == search_string)
572
676
void DashView::AddProperties(GVariantBuilder* builder)
575
nux::Area * DashView::KeyNavIteration(nux::KeyNavDirection direction)
577
// We don't want to eat the tab as it's used for IM stuff
578
if (!search_bar_->im_active())
678
int num_rows = 1; // The search bar
680
if (active_lens_view_)
681
num_rows += active_lens_view_->GetNumRows();
683
unity::variant::BuilderWrapper wrapper(builder);
684
wrapper.add("num-rows", num_rows);
687
nux::Area* DashView::KeyNavIteration(nux::KeyNavDirection direction)
689
if (direction == nux::KEY_NAV_DOWN && search_bar_ && active_lens_view_)
580
if (direction == KEY_NAV_TAB_NEXT)
581
lens_bar_->ActivateNext();
582
else if (direction == KEY_NAV_TAB_PREVIOUS)
583
lens_bar_->ActivatePrevious();
691
auto show_filters = search_bar_->show_filters();
692
auto fscroll_view = active_lens_view_->fscroll_view();
694
if (show_filters && show_filters->HasKeyFocus())
696
if (fscroll_view->IsVisible() && fscroll_view)
697
return fscroll_view->KeyNavIteration(direction);
699
return active_lens_view_->KeyNavIteration(direction);
597
714
// Do what nux::View does, but if the event isn't a key navigation,
598
715
// designate the text entry to process it.
717
bool ctrl = (special_keys_state & NUX_STATE_CTRL);
600
719
nux::KeyNavDirection direction = KEY_NAV_NONE;
601
720
switch (x11_key_code)
623
744
// Not sure if Enter should be a navigation key
624
745
direction = KEY_NAV_ENTER;
748
// Maybe we should not do it here, but it needs to be checked where
749
// we are able to know if alt is pressed.
750
if (special_keys_state & NUX_STATE_ALT)
752
ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
627
756
direction = KEY_NAV_NONE;
760
// We should not do it here, but I really don't want to make DashView
761
// focusable and I'm not able to know if ctrl is pressed in
762
// DashView::KeyNavIteration.
763
nux::InputArea* focus_area = nux::GetWindowCompositor().GetKeyFocusArea();
765
if (key_symbol == nux::NUX_KEYDOWN)
767
std::list<nux::Area*> tabs;
768
for (auto category : active_lens_view_->categories())
770
if (category->IsVisible())
771
tabs.push_back(category);
774
if (search_bar_ && search_bar_->show_filters() &&
775
search_bar_->show_filters()->IsVisible())
777
tabs.push_back(search_bar_->show_filters());
780
if (active_lens_view_->filter_bar() && active_lens_view_->fscroll_view() &&
781
active_lens_view_->fscroll_view()->IsVisible())
783
for (auto filter : active_lens_view_->filter_bar()->GetLayout()->GetChildren())
785
tabs.push_back(filter);
789
if (direction == KEY_NAV_TAB_PREVIOUS)
793
lens_bar_->ActivatePrevious();
797
auto rbegin = tabs.rbegin();
798
auto rend = tabs.rend();
800
bool use_the_prev = false;
801
for (auto tab = rbegin; tab != rend; ++tab)
803
const auto& tab_ptr = *tab;
809
use_the_prev = focus_area->IsChildOf(tab_ptr);
812
for (auto tab = rbegin; tab != rend; ++tab)
816
else if (direction == KEY_NAV_TAB_NEXT)
820
lens_bar_->ActivateNext();
824
bool use_the_next = false;
825
for (auto tab : tabs)
831
use_the_next = focus_area->IsChildOf(tab);
834
for (auto tab : tabs)
635
else if (direction == KEY_NAV_NONE || search_bar_->im_active)
840
if (direction == KEY_NAV_NONE || search_bar_->im_active)
637
842
// then send the event to the search entry
638
843
return search_bar_->text_entry();