Back to index

unity  6.0.0
PanelIndicatorsView.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright (C) 2011-2012 Canonical Ltd
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 3 as
00007  * published by the Free Software Foundation.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  *
00017  * Authored by: Marco Trevisan (TreviƱo) <3v1n0@ubuntu.com>
00018  *              Neil Jagdish Patel <neil.patel@canonical.com>
00019  */
00020 
00021 #include <Nux/Nux.h>
00022 #include <Nux/Area.h>
00023 #include <Nux/HLayout.h>
00024 
00025 #include <NuxCore/Logger.h>
00026 
00027 #include "PanelIndicatorsView.h"
00028 
00029 #include <UnityCore/Variant.h>
00030 #include <glib.h>
00031 
00032 namespace
00033 {
00034 nux::logging::Logger logger("unity.indicators");
00035 }
00036 
00037 namespace unity
00038 {
00039 using namespace indicator;
00040 
00041 NUX_IMPLEMENT_OBJECT_TYPE(PanelIndicatorsView);
00042 
00043 PanelIndicatorsView::PanelIndicatorsView()
00044 : View(NUX_TRACKER_LOCATION)
00045 , layout_(NULL)
00046 , opacity_(1.0f)
00047 {
00048   LOG_DEBUG(logger) << "Indicators View Added: ";
00049   layout_ = new nux::HLayout("", NUX_TRACKER_LOCATION);
00050   layout_->SetContentDistribution(nux::eStackRight);
00051 
00052   SetLayout(layout_);
00053 }
00054 
00055 PanelIndicatorsView::~PanelIndicatorsView()
00056 {
00057   for (auto ind : indicators_connections_)
00058   {
00059     for (auto conn : ind.second)
00060       conn.disconnect();
00061   }
00062 }
00063 
00064 void
00065 PanelIndicatorsView::AddIndicator(Indicator::Ptr const& indicator)
00066 {
00067   LOG_DEBUG(logger) << "IndicatorAdded: " << indicator->name();
00068   indicators_.push_back(indicator);
00069 
00070   std::vector<sigc::connection> connections;
00071 
00072   auto entry_added_conn = indicator->on_entry_added.connect(sigc::mem_fun(this, &PanelIndicatorsView::OnEntryAdded));
00073   connections.push_back(entry_added_conn);
00074 
00075   auto entry_removed_conn = indicator->on_entry_removed.connect(sigc::mem_fun(this, &PanelIndicatorsView::OnEntryRemoved));
00076   connections.push_back(entry_removed_conn);
00077 
00078   indicators_connections_[indicator] = connections;
00079 }
00080 
00081 void
00082 PanelIndicatorsView::RemoveIndicator(Indicator::Ptr const& indicator)
00083 {
00084   auto connections = indicators_connections_.find(indicator);
00085 
00086   if (connections != indicators_connections_.end()) {
00087     for (auto conn : connections->second)
00088       conn.disconnect();
00089 
00090     indicators_connections_.erase(indicator);
00091   }
00092 
00093   for (auto entry : indicator->GetEntries())
00094     OnEntryRemoved(entry->id());
00095 
00096   for (auto i = indicators_.begin(); i != indicators_.end(); i++)
00097   {
00098     if (*i == indicator)
00099     {
00100       indicators_.erase(i);
00101       break;
00102     }
00103   }
00104 
00105   LOG_DEBUG(logger) << "IndicatorRemoved: " << indicator->name();
00106 }
00107 
00108 PanelIndicatorsView::Indicators
00109 PanelIndicatorsView::GetIndicators()
00110 {
00111   return indicators_;
00112 }
00113 
00114 void
00115 PanelIndicatorsView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
00116 {
00117   nux::Geometry geo = GetGeometry();
00118 
00119   GfxContext.PushClippingRectangle(geo);
00120   nux::GetPainter().PaintBackground(GfxContext, geo);
00121   GfxContext.PopClippingRectangle();
00122 }
00123 
00124 void
00125 PanelIndicatorsView::SetMaximumEntriesWidth(int max_width)
00126 {
00127   unsigned int n_entries = 0;
00128 
00129   for (auto entry : entries_)
00130     if (entry.second->IsVisible())
00131       n_entries++;
00132 
00133   if (n_entries > 0)
00134   {
00135     for (auto entry : entries_)
00136     {
00137       if (entry.second->IsVisible() && n_entries > 0)
00138       {
00139         int max_entry_width = max_width / n_entries;
00140 
00141         if (entry.second->GetBaseWidth() > max_entry_width)
00142           entry.second->SetMaximumWidth(max_entry_width);
00143 
00144         max_width -= entry.second->GetBaseWidth();
00145         --n_entries;
00146       }
00147     }
00148   }
00149 }
00150 
00151 PanelIndicatorEntryView*
00152 PanelIndicatorsView::ActivateEntry(std::string const& entry_id, int button)
00153 {
00154   auto entry = entries_.find(entry_id);
00155 
00156   if (entry != entries_.end())
00157   {
00158     PanelIndicatorEntryView* view = entry->second;
00159 
00160     if (view->IsSensitive() && view->IsVisible())
00161       view->Activate(button);
00162 
00163     return view;
00164   }
00165 
00166   return nullptr;
00167 }
00168 
00169 bool
00170 PanelIndicatorsView::ActivateIfSensitive()
00171 {
00172   std::map<int, PanelIndicatorEntryView*> sorted_entries;
00173   
00174   for (auto entry : entries_)
00175     sorted_entries[entry.second->GetEntryPriority()] = entry.second;
00176   
00177   for (auto entry : sorted_entries)
00178   {
00179     PanelIndicatorEntryView* view = entry.second;
00180 
00181     if (view->IsSensitive() && view->IsVisible() && view->IsFocused())
00182     {
00183       /* Use the 0 button, it means it's a keyboard activation */
00184       view->Activate(0);
00185       return true;
00186     }
00187   }
00188 
00189   return false;
00190 }
00191 
00192 void
00193 PanelIndicatorsView::GetGeometryForSync(EntryLocationMap& locations)
00194 {
00195   for (auto entry : entries_)
00196     entry.second->GetGeometryForSync(locations);
00197 }
00198 
00199 PanelIndicatorEntryView*
00200 PanelIndicatorsView::ActivateEntryAt(int x, int y, int button)
00201 {
00202   PanelIndicatorEntryView* target = nullptr;
00203   bool found_old_active = false;
00204 
00205   //
00206   // Change the entry active status without waiting
00207   // for slow inter-process communication with unity-panel-service,
00208   // which causes visible lag in many cases.
00209   //
00210 
00211   for (auto entry : entries_)
00212   {
00213     PanelIndicatorEntryView* view = entry.second;
00214 
00215     if (!target && view->IsVisible() && view->IsFocused() &&
00216         view->IsSensitive() &&
00217         view->GetAbsoluteGeometry().IsPointInside(x, y))
00218     {
00219       view->Activate(button);
00220       target = view;
00221       break;
00222     }
00223     else if (target && view->IsActive())
00224     {
00225       view->Unactivate();
00226       found_old_active = true;
00227       break;
00228     }
00229   }
00230 
00231   if (target && !found_old_active)
00232   {
00233     for (auto entry : entries_)
00234     {
00235       PanelIndicatorEntryView* view = entry.second;
00236 
00237       if (view != target && view->IsActive())
00238       {
00239         view->Unactivate();
00240         break;
00241       }
00242     }
00243   }
00244 
00245   return target;
00246 }
00247 
00248 void
00249 PanelIndicatorsView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
00250 {
00251   GfxContext.PushClippingRectangle(GetGeometry());
00252   layout_->ProcessDraw(GfxContext, force_draw);
00253   GfxContext.PopClippingRectangle();
00254 }
00255 
00256 void
00257 PanelIndicatorsView::AddEntryView(PanelIndicatorEntryView* view,
00258                                   IndicatorEntryPosition pos)
00259 {
00260   if (!view)
00261     return;
00262 
00263   int entry_pos = pos;
00264 
00265   view->SetOpacity(opacity_);
00266   view->refreshed.connect(sigc::mem_fun(this, &PanelIndicatorsView::OnEntryRefreshed));
00267 
00268   if (entry_pos == IndicatorEntryPosition::AUTO)
00269   {
00270     entry_pos = nux::NUX_LAYOUT_BEGIN;
00271 
00272     if (view->GetEntryPriority() > -1)
00273     {
00274       for (auto area : layout_->GetChildren())
00275       {
00276         auto en = dynamic_cast<PanelIndicatorEntryView*>(area);
00277 
00278         if (en)
00279         {
00280           if (en && view->GetEntryPriority() <= en->GetEntryPriority())
00281             break;
00282 
00283           entry_pos++;
00284         }
00285       }
00286     }
00287   }
00288 
00289   layout_->AddView(view, 0, nux::eCenter, nux::eFull, 1.0, (nux::LayoutPosition) entry_pos);
00290 
00291   entries_[view->GetEntryID()] = view;
00292 
00293   AddChild(view);
00294   QueueRelayout();
00295   QueueDraw();
00296 
00297   on_indicator_updated.emit(view);
00298 }
00299 
00300 PanelIndicatorEntryView *
00301 PanelIndicatorsView::AddEntry(Entry::Ptr const& entry, int padding,
00302                               IndicatorEntryPosition pos, IndicatorEntryType type)
00303 {
00304   auto view = new PanelIndicatorEntryView(entry, padding, type);
00305   AddEntryView(view, pos);
00306 
00307   return view;
00308 }
00309 
00310 void
00311 PanelIndicatorsView::OnEntryAdded(Entry::Ptr const& entry)
00312 {
00313   AddEntry(entry);
00314 }
00315 
00316 void
00317 PanelIndicatorsView::OnEntryRefreshed(PanelIndicatorEntryView* view)
00318 {
00319   QueueRelayout();
00320   QueueDraw();
00321 
00322   on_indicator_updated.emit(view);
00323 }
00324 
00325 void
00326 PanelIndicatorsView::RemoveEntryView(PanelIndicatorEntryView* view)
00327 {
00328   if (!view)
00329     return;
00330 
00331   std::string const& entry_id = view->GetEntryID();
00332   RemoveChild(view);
00333   on_indicator_updated.emit(view);
00334   entries_.erase(entry_id);
00335   layout_->RemoveChildObject(view);
00336 
00337   QueueRelayout();
00338   QueueDraw();
00339 }
00340 
00341 void
00342 PanelIndicatorsView::RemoveEntry(std::string const& entry_id)
00343 {
00344   RemoveEntryView(entries_[entry_id]);
00345 }
00346 
00347 void
00348 PanelIndicatorsView::OnEntryRemoved(std::string const& entry_id)
00349 {
00350   RemoveEntry(entry_id);
00351 }
00352 
00353 void
00354 PanelIndicatorsView::OverlayShown()
00355 {
00356   for (auto entry: entries_)
00357     entry.second->OverlayShown();
00358 }
00359 
00360 void
00361 PanelIndicatorsView::OverlayHidden()
00362 {
00363   for (auto entry: entries_)
00364     entry.second->OverlayHidden();
00365 }
00366 
00367 double
00368 PanelIndicatorsView::GetOpacity()
00369 {
00370   return opacity_;
00371 }
00372 
00373 void
00374 PanelIndicatorsView::SetOpacity(double opacity)
00375 {
00376   opacity = CLAMP(opacity, 0.0f, 1.0f);
00377 
00378   for (auto entry: entries_)
00379     entry.second->SetOpacity(opacity);
00380 
00381   if (opacity_ != opacity)
00382   {
00383     opacity_ = opacity;
00384     NeedRedraw();
00385   }
00386 }
00387 
00388 std::string PanelIndicatorsView::GetName() const
00389 {
00390   return "Indicators";
00391 }
00392 
00393 void
00394 PanelIndicatorsView::AddProperties(GVariantBuilder* builder)
00395 {
00396   variant::BuilderWrapper(builder)
00397   .add(GetAbsoluteGeometry())
00398   .add("entries", entries_.size())
00399   .add("opacity", opacity_);
00400 }
00401 
00402 } // namespace unity