Back to index

unity  6.0.0
PanelIndicatorEntryView.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright (C) 2010-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: Neil Jagdish Patel <neil.patel@canonical.com>
00018  *              Marco Trevisan (TreviƱo) <3v1n0@ubuntu.com>
00019  */
00020 
00021 #include <Nux/Nux.h>
00022 #include <Nux/HLayout.h>
00023 #include <Nux/VLayout.h>
00024 
00025 #include <NuxGraphics/GLThread.h>
00026 #include <Nux/BaseWindow.h>
00027 #include <Nux/WindowCompositor.h>
00028 #include <UnityCore/Variant.h>
00029 
00030 #include <glib.h>
00031 #include <gdk-pixbuf/gdk-pixbuf.h>
00032 #include <gtk/gtk.h>
00033 #include <time.h>
00034 #include <boost/algorithm/string.hpp>
00035 
00036 #include "unity-shared/CairoTexture.h"
00037 #include "PanelIndicatorEntryView.h"
00038 #include "unity-shared/PanelStyle.h"
00039 #include "unity-shared/WindowManager.h"
00040 
00041 
00042 namespace unity
00043 {
00044 
00045 namespace
00046 {
00047 const int DEFAULT_SPACING = 3;
00048 }
00049 
00050 using namespace indicator;
00051 
00052 PanelIndicatorEntryView::PanelIndicatorEntryView(Entry::Ptr const& proxy, int padding,
00053                                                  IndicatorEntryType type)
00054   : TextureArea(NUX_TRACKER_LOCATION)
00055   , proxy_(proxy)
00056   , spacing_(DEFAULT_SPACING)
00057   , left_padding_(padding < 0 ? 0 : padding)
00058   , right_padding_(left_padding_)
00059   , type_(type)
00060   , entry_texture_(nullptr)
00061   , opacity_(1.0f)
00062   , draw_active_(false)
00063   , overlay_showing_(false)
00064   , disabled_(false)
00065   , focused_(true)
00066 {
00067   proxy_->active_changed.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::OnActiveChanged));
00068   proxy_->updated.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::Refresh));
00069 
00070   InputArea::mouse_down.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::OnMouseDown));
00071   InputArea::mouse_up.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::OnMouseUp));
00072 
00073   InputArea::SetAcceptMouseWheelEvent(true);
00074 
00075   if (type_ != MENU)
00076     InputArea::mouse_wheel.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::OnMouseWheel));
00077 
00078   panel::Style::Instance().changed.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::Refresh));
00079 
00080   Refresh();
00081 }
00082 
00083 PanelIndicatorEntryView::~PanelIndicatorEntryView()
00084 {
00085   // Nothing to do...
00086 }
00087 
00088 void PanelIndicatorEntryView::OnActiveChanged(bool is_active)
00089 {
00090   active_changed.emit(this, is_active);
00091 
00092   if (draw_active_ && !is_active)
00093   {
00094     draw_active_ = false;
00095     Refresh();
00096   }
00097 }
00098 
00099 void PanelIndicatorEntryView::ShowMenu(int button)
00100 {
00101   auto wm = WindowManager::Default();
00102 
00103   if (!wm->IsExpoActive() && !wm->IsScaleActive())
00104   {
00105     proxy_->ShowMenu(GetAbsoluteX(),
00106                      GetAbsoluteY() + panel::Style::Instance().panel_height,
00107                      button,
00108                      time(nullptr));
00109   }
00110 }
00111 
00112 void PanelIndicatorEntryView::OnMouseDown(int x, int y, long button_flags, long key_flags)
00113 {
00114   if (proxy_->active() || IsDisabled())
00115     return;
00116 
00117   if (((IsLabelVisible() && IsLabelSensitive()) ||
00118        (IsIconVisible() && IsIconSensitive())))
00119   {
00120     int button = nux::GetEventButton(button_flags);
00121 
00122     if (button == 2 && type_ == INDICATOR)
00123       SetOpacity(0.75f);
00124     else
00125       ShowMenu(button);
00126   }
00127 
00128   Refresh();
00129 }
00130 
00131 void PanelIndicatorEntryView::OnMouseUp(int x, int y, long button_flags, long key_flags)
00132 {
00133   if (proxy_->active() || IsDisabled())
00134     return;
00135 
00136   int button = nux::GetEventButton(button_flags);
00137 
00138   nux::Geometry geo = GetAbsoluteGeometry();
00139   int px = geo.x + x;
00140   int py = geo.y + y;
00141 
00142   if (((IsLabelVisible() && IsLabelSensitive()) ||
00143        (IsIconVisible() && IsIconSensitive())) &&
00144       button == 2 && type_ == INDICATOR)
00145   {
00146     if (geo.IsPointInside(px, py))
00147       proxy_->SecondaryActivate(time(nullptr));
00148 
00149     SetOpacity(1.0f);
00150   }
00151 
00152   Refresh();
00153 }
00154 
00155 void PanelIndicatorEntryView::OnMouseWheel(int x, int y, int delta,
00156                                            unsigned long mouse_state,
00157                                            unsigned long key_state)
00158 {
00159   if (!IsDisabled())
00160     proxy_->Scroll(delta);
00161 }
00162 
00163 void PanelIndicatorEntryView::Activate(int button)
00164 {
00165   SetActiveState(true, button);
00166 }
00167 
00168 void PanelIndicatorEntryView::Unactivate()
00169 {
00170   SetActiveState(false, 0);
00171 }
00172 
00173 void PanelIndicatorEntryView::SetActiveState(bool active, int button)
00174 {
00175   if (draw_active_ != active)
00176   {
00177     draw_active_ = active;
00178     Refresh();
00179 
00180     if (active)
00181       ShowMenu(button);
00182   }
00183 }
00184 
00185 glib::Object<GdkPixbuf> PanelIndicatorEntryView::MakePixbuf()
00186 {
00187   glib::Object<GdkPixbuf> pixbuf;
00188   GtkIconTheme* theme = gtk_icon_theme_get_default();
00189   int image_type = proxy_->image_type();
00190 
00191   if (image_type == GTK_IMAGE_PIXBUF)
00192   {
00193     gsize len = 0;
00194     guchar* decoded = g_base64_decode(proxy_->image_data().c_str(), &len);
00195 
00196     glib::Object<GInputStream> stream(g_memory_input_stream_new_from_data(decoded,
00197                                                                           len,
00198                                                                           nullptr));
00199 
00200     pixbuf = gdk_pixbuf_new_from_stream(stream, nullptr, nullptr);
00201 
00202     g_free(decoded);
00203     g_input_stream_close(stream, nullptr, nullptr);
00204   }
00205   else if (image_type == GTK_IMAGE_STOCK ||
00206            image_type == GTK_IMAGE_ICON_NAME)
00207   {
00208     pixbuf = gtk_icon_theme_load_icon(theme, proxy_->image_data().c_str(), 22,
00209                                       (GtkIconLookupFlags)0, nullptr);
00210   }
00211   else if (image_type == GTK_IMAGE_GICON)
00212   {
00213     glib::Object<GIcon> icon(g_icon_new_for_string(proxy_->image_data().c_str(), nullptr));
00214 
00215     GtkIconInfo* info = gtk_icon_theme_lookup_by_gicon(theme, icon, 22,
00216                                                        (GtkIconLookupFlags)0);
00217     if (info)
00218     {
00219       pixbuf = gtk_icon_info_load_icon(info, nullptr);
00220       gtk_icon_info_free(info);
00221     }
00222   }
00223 
00224   return pixbuf;
00225 }
00226 
00227 void PanelIndicatorEntryView::DrawEntryPrelight(cairo_t* cr, unsigned int width, unsigned int height)
00228 {
00229   GtkStyleContext* style_context = panel::Style::Instance().GetStyleContext();
00230 
00231   gtk_style_context_save(style_context);
00232 
00233   GtkWidgetPath* widget_path = gtk_widget_path_new();
00234   gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_BAR);
00235   gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_ITEM);
00236   gtk_widget_path_iter_set_name(widget_path, -1 , "UnityPanelWidget");
00237 
00238   gtk_style_context_set_path(style_context, widget_path);
00239   gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUBAR);
00240   gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUITEM);
00241   gtk_style_context_set_state(style_context, GTK_STATE_FLAG_PRELIGHT);
00242 
00243   gtk_render_background(style_context, cr, 0, 0, width, height);
00244   gtk_render_frame(style_context, cr, 0, 0, width, height);
00245 
00246   gtk_widget_path_free(widget_path);
00247 
00248   gtk_style_context_restore(style_context);
00249 }
00250 
00251 void PanelIndicatorEntryView::DrawEntryContent(cairo_t *cr, unsigned int width, unsigned int height, glib::Object<GdkPixbuf> const& pixbuf, glib::Object<PangoLayout> const& layout)
00252 {
00253   int x = left_padding_;
00254 
00255   if (IsActive())
00256     DrawEntryPrelight(cr, width, height);
00257 
00258   if (pixbuf && IsIconVisible())
00259   {
00260     GtkStyleContext* style_context = panel::Style::Instance().GetStyleContext();
00261     unsigned int icon_width = gdk_pixbuf_get_width(pixbuf);
00262 
00263     gtk_style_context_save(style_context);
00264 
00265     GtkWidgetPath* widget_path = gtk_widget_path_new();
00266     gint pos = gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_BAR);
00267     pos = gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_ITEM);
00268     gtk_widget_path_iter_set_name(widget_path, pos, "UnityPanelWidget");
00269 
00270     gtk_style_context_set_path(style_context, widget_path);
00271     gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUBAR);
00272     gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUITEM);
00273 
00274     if (!IsFocused())
00275     {
00276       gtk_style_context_set_state(style_context, GTK_STATE_FLAG_BACKDROP);
00277     }
00278     else if (IsActive())
00279     {
00280       gtk_style_context_set_state(style_context, GTK_STATE_FLAG_PRELIGHT);
00281     }
00282 
00283     int y = (int)((height - gdk_pixbuf_get_height(pixbuf)) / 2);
00284     if (overlay_showing_ && !IsActive())
00285     {
00286       /* Most of the images we get are straight pixbufs (annoyingly), so when
00287        * the Overlay opens, we use the pixbuf as a mask to punch out an icon from
00288        * a white square. It works surprisingly well for most symbolic-type
00289        * icon themes/icons.
00290        */
00291       cairo_save(cr);
00292 
00293       cairo_push_group(cr);
00294       gdk_cairo_set_source_pixbuf(cr, pixbuf, x, y);
00295       cairo_paint_with_alpha(cr, (IsIconSensitive() && IsFocused()) ? 1.0 : 0.5);
00296 
00297       cairo_pattern_t* pat = cairo_pop_group(cr);
00298 
00299       cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 1.0f);
00300       cairo_rectangle(cr, x, y, width, height);
00301       cairo_mask(cr, pat);
00302 
00303       cairo_pattern_destroy(pat);
00304       cairo_restore(cr);
00305     }
00306     else
00307     {
00308       cairo_push_group(cr);
00309       gtk_render_icon(style_context, cr, pixbuf, x, y);
00310       cairo_pop_group_to_source(cr);
00311       cairo_paint_with_alpha(cr, (IsIconSensitive() && IsFocused()) ? 1.0 : 0.5);
00312     }
00313 
00314     gtk_widget_path_free(widget_path);
00315 
00316     gtk_style_context_restore(style_context);
00317 
00318     x += icon_width + spacing_;
00319   }
00320 
00321   if (layout)
00322   {
00323     PangoRectangle log_rect;
00324     pango_layout_get_extents(layout, nullptr, &log_rect);
00325     unsigned int text_height = log_rect.height / PANGO_SCALE;
00326     unsigned int text_width = log_rect.width / PANGO_SCALE;
00327 
00328     pango_cairo_update_layout(cr, layout);
00329 
00330     GtkStyleContext* style_context = panel::Style::Instance().GetStyleContext();
00331 
00332     gtk_style_context_save(style_context);
00333 
00334     GtkWidgetPath* widget_path = gtk_widget_path_new();
00335     gint pos = gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_BAR);
00336     pos = gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_ITEM);
00337     gtk_widget_path_iter_set_name(widget_path, pos, "UnityPanelWidget");
00338 
00339     gtk_style_context_set_path(style_context, widget_path);
00340     gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUBAR);
00341     gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUITEM);
00342 
00343     if (!IsFocused())
00344     {
00345       gtk_style_context_set_state(style_context, GTK_STATE_FLAG_BACKDROP);
00346     }
00347     else if (IsActive())
00348     {
00349       gtk_style_context_set_state(style_context, GTK_STATE_FLAG_PRELIGHT);
00350     }
00351 
00352     int y = (height - text_height) / 2;
00353 
00354 
00355     unsigned int text_space = GetMaximumWidth() - x - right_padding_;
00356 
00357     if (text_width > text_space)
00358     {
00359       cairo_pattern_t* linpat;
00360       int out_pixels = text_width - text_space;
00361       const int fading_pixels = 15;
00362 
00363       int fading_width = out_pixels < fading_pixels ? out_pixels : fading_pixels;
00364 
00365       cairo_push_group(cr);
00366       if (overlay_showing_)
00367       {
00368         cairo_move_to(cr, x, y);
00369         cairo_set_source_rgb(cr, 1.0f, 1.0f, 1.0f);
00370         pango_cairo_show_layout(cr, layout);
00371       }
00372       else
00373       {
00374         gtk_render_layout(style_context, cr, x, y, layout);
00375       }
00376       cairo_pop_group_to_source(cr);
00377 
00378       int right_margin = width - right_padding_;
00379       linpat = cairo_pattern_create_linear(right_margin - fading_width, y, right_margin, y);
00380       cairo_pattern_add_color_stop_rgba(linpat, 0, 0, 0, 0, 1);
00381       cairo_pattern_add_color_stop_rgba(linpat, 1, 0, 0, 0, 0);
00382       cairo_mask(cr, linpat);
00383       cairo_pattern_destroy(linpat);
00384     }
00385     else
00386     {
00387       if (overlay_showing_)
00388       {
00389         cairo_move_to(cr, x, y);
00390         cairo_set_source_rgb(cr, 1.0f, 1.0f, 1.0f);
00391         pango_cairo_show_layout(cr, layout);
00392       }
00393       else
00394       {
00395         gtk_render_layout(style_context, cr, x, y, layout);
00396       }
00397     }
00398 
00399     gtk_widget_path_free(widget_path);
00400     gtk_style_context_restore(style_context);
00401   }
00402 }
00403 
00404 // We need to do a couple of things here:
00405 // 1. Figure out our width
00406 // 2. Figure out if we're active
00407 // 3. Paint something
00408 void PanelIndicatorEntryView::Refresh()
00409 {
00410   if (!proxy_->visible())
00411   {
00412     SetVisible(false);
00413     // This will destroy the object texture. No need to manually delete the pointer
00414     entry_texture_ = nullptr;
00415     SetColor(nux::color::Transparent);
00416 
00417     QueueDraw();
00418     refreshed.emit(this);
00419 
00420     return;
00421   }
00422 
00423   glib::Object<PangoLayout> layout;
00424   cairo_t* cr;
00425 
00426   std::string label = GetLabel();
00427   glib::Object<GdkPixbuf> const& pixbuf = MakePixbuf();
00428 
00429   unsigned int width = 0;
00430   unsigned int icon_width = 0;
00431   unsigned int height = panel::Style::Instance().panel_height;
00432   unsigned int text_width = 0;
00433 
00434   // First lets figure out our size
00435   if (pixbuf && IsIconVisible())
00436   {
00437     width = gdk_pixbuf_get_width(pixbuf);
00438     icon_width = width;
00439   }
00440 
00441   if (!label.empty() && IsLabelVisible())
00442   {
00443     using namespace panel;
00444     PangoContext* cxt;
00445     PangoAttrList* attrs = nullptr;
00446     PangoRectangle log_rect;
00447     GdkScreen* screen = gdk_screen_get_default();
00448     PangoFontDescription* desc = nullptr;
00449     PanelItem panel_item = (type_ == MENU) ? PanelItem::MENU : PanelItem::INDICATOR;
00450 
00451     Style& panel_style = Style::Instance();
00452     std::string const& font_description = panel_style.GetFontDescription(panel_item);
00453     int dpi = panel_style.GetTextDPI();
00454 
00455     if (proxy_->show_now())
00456     {
00457       if (!pango_parse_markup(label.c_str(), -1, '_', &attrs, nullptr, nullptr, nullptr))
00458       {
00459         g_debug("pango_parse_markup failed");
00460       }
00461     }
00462 
00463     desc = pango_font_description_from_string(font_description.c_str());
00464     pango_font_description_set_weight(desc, PANGO_WEIGHT_NORMAL);
00465 
00466     nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, 1, 1);
00467     cr = cairo_graphics.GetContext();
00468 
00469     layout = pango_cairo_create_layout(cr);
00470     if (attrs)
00471     {
00472       pango_layout_set_attributes(layout, attrs);
00473       pango_attr_list_unref(attrs);
00474     }
00475 
00476     pango_layout_set_font_description(layout, desc);
00477 
00478     boost::erase_all(label, "_");
00479     pango_layout_set_text(layout, label.c_str(), -1);
00480 
00481     cxt = pango_layout_get_context(layout);
00482     pango_cairo_context_set_font_options(cxt, gdk_screen_get_font_options(screen));
00483     pango_cairo_context_set_resolution(cxt, dpi / static_cast<float>(PANGO_SCALE));
00484     pango_layout_context_changed(layout);
00485 
00486     pango_layout_get_extents(layout, nullptr, &log_rect);
00487     text_width = log_rect.width / PANGO_SCALE;
00488 
00489     if (icon_width)
00490       width += spacing_;
00491     width += text_width;
00492 
00493     pango_font_description_free(desc);
00494     cairo_destroy(cr);
00495   }
00496 
00497   if (width)
00498     width += left_padding_ + right_padding_;
00499 
00500   width = std::min<int>(width, GetMaximumWidth());
00501   SetMinimumWidth(width);
00502 
00503   nux::CairoGraphics cg(CAIRO_FORMAT_ARGB32, width, height);
00504   cr = cg.GetContext();
00505   cairo_set_line_width(cr, 1);
00506   cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
00507   cairo_paint(cr);
00508 
00509   cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
00510   DrawEntryContent(cr, width, height, pixbuf, layout);
00511 
00512   entry_texture_ = texture_ptr_from_cairo_graphics(cg);
00513   SetTexture(entry_texture_.GetPointer());
00514   cairo_destroy(cr);
00515 
00516   SetVisible(true);
00517   refreshed.emit(this);
00518   QueueDraw();
00519 }
00520 
00521 void PanelIndicatorEntryView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
00522 {
00523   nux::Geometry const& geo = GetGeometry();
00524   GfxContext.PushClippingRectangle(geo);
00525 
00526   if (cached_geo_ != geo)
00527   {
00528     Refresh();
00529     cached_geo_ = geo;
00530   }
00531 
00532   if (entry_texture_ && opacity_ > 0.0f)
00533   {
00534     /* "Clear" out the background */
00535     nux::ROPConfig rop;
00536     rop.Blend = true;
00537     rop.SrcBlend = GL_ONE;
00538     rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
00539 
00540     nux::ColorLayer layer(nux::color::Transparent, true, rop);
00541     nux::GetPainter().PushDrawLayer(GfxContext, geo, &layer);
00542 
00543     nux::TexCoordXForm texxform;
00544     GfxContext.QRP_1Tex(geo.x, geo.y, geo.width, geo.height,
00545                         entry_texture_->GetDeviceTexture(), texxform,
00546                         nux::color::White * opacity_);
00547   }
00548 
00549   GfxContext.PopClippingRectangle();
00550 }
00551 
00552 void PanelIndicatorEntryView::OverlayShown()
00553 {
00554   overlay_showing_ = true;
00555   Refresh();
00556 }
00557 
00558 void PanelIndicatorEntryView::OverlayHidden()
00559 {
00560   overlay_showing_ = false;
00561   Refresh();
00562 }
00563 
00564 void PanelIndicatorEntryView::SetOpacity(double opacity)
00565 {
00566   opacity = CLAMP(opacity, 0.0f, 1.0f);
00567 
00568   if (opacity_ != opacity)
00569   {
00570     opacity_ = opacity;
00571     SetInputEventSensitivity(opacity_ != 0.0f);
00572     QueueDraw();
00573   }
00574 }
00575 
00576 double PanelIndicatorEntryView::GetOpacity()
00577 {
00578   return opacity_;
00579 }
00580 
00581 PanelIndicatorEntryView::IndicatorEntryType PanelIndicatorEntryView::GetType() const
00582 {
00583   return type_;
00584 }
00585 
00586 std::string PanelIndicatorEntryView::GetLabel() const
00587 {
00588   if (proxy_.get())
00589   {
00590     return proxy_->label();
00591   }
00592 
00593   return "";
00594 }
00595 
00596 bool PanelIndicatorEntryView::IsLabelVisible() const
00597 {
00598   if (proxy_.get())
00599   {
00600     return proxy_->label_visible();
00601   }
00602 
00603   return false;
00604 }
00605 
00606 bool PanelIndicatorEntryView::IsLabelSensitive() const
00607 {
00608   if (proxy_.get())
00609   {
00610     return proxy_->label_sensitive();
00611   }
00612 
00613   return false;
00614 }
00615 
00616 bool PanelIndicatorEntryView::IsIconVisible() const
00617 {
00618   if (proxy_.get())
00619   {
00620     return proxy_->image_visible();
00621   }
00622 
00623   return false;
00624 }
00625 
00626 bool PanelIndicatorEntryView::IsIconSensitive() const
00627 {
00628   if (proxy_.get())
00629   {
00630     return proxy_->image_sensitive();
00631   }
00632 
00633   return false;
00634 }
00635 
00636 std::string PanelIndicatorEntryView::GetName() const
00637 {
00638   return "IndicatorEntry";
00639 }
00640 
00641 void PanelIndicatorEntryView::AddProperties(GVariantBuilder* builder)
00642 {
00643   std::string type_name;
00644 
00645   switch (GetType())
00646   {
00647     case INDICATOR:
00648       type_name = "indicator";
00649       break;
00650     case MENU:
00651       type_name = "menu";
00652       break;
00653     default:
00654       type_name = "other";
00655   }
00656 
00657   variant::BuilderWrapper(builder)
00658   .add(GetAbsoluteGeometry())
00659   .add("entry_id", GetEntryID())
00660   .add("name_hint", proxy_->name_hint())
00661   .add("type", type_name)
00662   .add("priority", proxy_->priority())
00663   .add("label", GetLabel())
00664   .add("label_sensitive", IsLabelSensitive())
00665   .add("label_visible", IsLabelVisible())
00666   .add("icon_sensitive", IsIconSensitive())
00667   .add("icon_visible", IsIconVisible())
00668   .add("visible", IsVisible() && GetOpacity() != 0.0f)
00669   .add("opacity", GetOpacity())
00670   .add("active", proxy_->active())
00671   .add("menu_x", proxy_->geometry().x)
00672   .add("menu_y", proxy_->geometry().y)
00673   .add("menu_width", proxy_->geometry().width)
00674   .add("menu_height", proxy_->geometry().height)
00675   .add("focused", IsFocused());
00676 }
00677 
00678 bool PanelIndicatorEntryView::GetShowNow() const
00679 {
00680   return proxy_.get() ? proxy_->show_now() : false;
00681 }
00682 
00683 void PanelIndicatorEntryView::GetGeometryForSync(EntryLocationMap& locations)
00684 {
00685   if (!IsVisible())
00686     return;
00687 
00688   locations[GetEntryID()] = GetAbsoluteGeometry();
00689 }
00690 
00691 bool PanelIndicatorEntryView::IsSensitive() const
00692 {
00693   if (proxy_.get())
00694   {
00695     return IsIconSensitive() || IsLabelSensitive();
00696   }
00697   return false;
00698 }
00699 
00700 bool PanelIndicatorEntryView::IsVisible()
00701 {
00702   if (proxy_.get())
00703   {
00704     return TextureArea::IsVisible() && proxy_->visible();
00705   }
00706 
00707   return TextureArea::IsVisible();
00708 }
00709 
00710 bool PanelIndicatorEntryView::IsActive() const
00711 {
00712   return draw_active_;
00713 }
00714 
00715 std::string PanelIndicatorEntryView::GetEntryID() const
00716 {
00717   if (proxy_.get())
00718   {
00719     return proxy_->id();
00720   }
00721 
00722   return "";
00723 }
00724 
00725 int PanelIndicatorEntryView::GetEntryPriority() const
00726 {
00727   if (proxy_.get())
00728   {
00729     return proxy_->priority();
00730   }
00731   return -1;
00732 }
00733 
00734 void PanelIndicatorEntryView::SetDisabled(bool disabled)
00735 {
00736   disabled_ = disabled;
00737 }
00738 
00739 bool PanelIndicatorEntryView::IsDisabled()
00740 {
00741   return (disabled_ || !proxy_.get() || !IsSensitive());
00742 }
00743 
00744 void PanelIndicatorEntryView::SetFocusedState(bool focused)
00745 {
00746   if (focused_ != focused)
00747   {
00748     focused_ = focused;
00749     Refresh();
00750   }
00751 }
00752 
00753 bool PanelIndicatorEntryView::IsFocused() const
00754 {
00755   return focused_;
00756 }
00757 
00758 } // namespace unity