Back to index

unity  6.0.0
QuicklistMenuItem.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright (C) 2010 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: Mirco Müller <mirco.mueller@canonical.com>
00018  *              Jay Taoko <jay.taoko@canonical.com>
00019  *              Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
00020  */
00021 
00022 #include <gdk/gdk.h>
00023 #include <gtk/gtk.h>
00024 
00025 #include <Nux/Nux.h>
00026 
00027 #include "QuicklistMenuItem.h"
00028 #include <UnityCore/Variant.h>
00029 
00030 #include <X11/Xlib.h>
00031 
00032 namespace unity
00033 {
00034 
00035 NUX_IMPLEMENT_OBJECT_TYPE(QuicklistMenuItem);
00036 
00037 static void
00038 OnPropertyChanged(gchar*             property,
00039                   GValue*            value,
00040                   QuicklistMenuItem* self);
00041 
00042 static void
00043 OnItemActivated(guint              timestamp,
00044                 QuicklistMenuItem* self);
00045 
00046 QuicklistMenuItem::QuicklistMenuItem(DbusmenuMenuitem* item,
00047                                      NUX_FILE_LINE_DECL) :
00048   View(NUX_FILE_LINE_PARAM)
00049 {
00050   if (item == 0)
00051   {
00052     g_warning("Invalid DbusmenuMenuitem in file %s at line %s.", G_STRFUNC, G_STRLOC);
00053   }
00054 
00055   Initialize(item, false);
00056 }
00057 
00058 QuicklistMenuItem::QuicklistMenuItem(DbusmenuMenuitem* item,
00059                                      bool              debug,
00060                                      NUX_FILE_LINE_DECL) :
00061   View(NUX_FILE_LINE_PARAM)
00062 {
00063   Initialize(item, debug);
00064 }
00065 
00066 void
00067 QuicklistMenuItem::Initialize(DbusmenuMenuitem* item, bool debug)
00068 {
00069   _text        = "";
00070   _color       = nux::Color(1.0f, 1.0f, 1.0f, 1.0f);
00071   _menuItem    = DBUSMENU_MENUITEM(g_object_ref(item));
00072   _debug       = debug;
00073   _item_type   = MENUITEM_TYPE_UNKNOWN;
00074 
00075   _normalTexture[0]   = NULL;
00076   _normalTexture[1]   = NULL;
00077   _prelightTexture[0] = NULL;
00078   _prelightTexture[1] = NULL;
00079 
00080   if (_menuItem)
00081   {
00082     g_signal_connect(_menuItem,
00083                      "property-changed",
00084                      G_CALLBACK(OnPropertyChanged),
00085                      this);
00086     g_signal_connect(_menuItem,
00087                      "item-activated",
00088                      G_CALLBACK(OnItemActivated),
00089                      this);
00090   }
00091 
00092   mouse_up.connect(sigc::mem_fun(this, &QuicklistMenuItem::RecvMouseUp));
00093   mouse_click.connect(sigc::mem_fun(this, &QuicklistMenuItem::RecvMouseClick));
00094   mouse_drag.connect(sigc::mem_fun(this, &QuicklistMenuItem::RecvMouseDrag));
00095   mouse_enter.connect(sigc::mem_fun(this, &QuicklistMenuItem::RecvMouseEnter));
00096   mouse_leave.connect(sigc::mem_fun(this, &QuicklistMenuItem::RecvMouseLeave));
00097 
00098   _prelight = false;
00099 }
00100 
00101 QuicklistMenuItem::~QuicklistMenuItem()
00102 {
00103   if (_normalTexture[0])
00104     _normalTexture[0]->UnReference();
00105 
00106   if (_normalTexture[1])
00107     _normalTexture[1]->UnReference();
00108 
00109   if (_prelightTexture[0])
00110     _prelightTexture[0]->UnReference();
00111 
00112   if (_prelightTexture[1])
00113     _prelightTexture[1]->UnReference();
00114 
00115   if (_menuItem)
00116     g_object_unref(_menuItem);
00117 }
00118 
00119 const gchar*
00120 QuicklistMenuItem::GetDefaultText()
00121 {
00122   return NULL;
00123 }
00124 
00125 void
00126 QuicklistMenuItem::InitializeText()
00127 {
00128   if (_menuItem)
00129     _text = GetText();
00130   else
00131     _text = GetDefaultText();
00132 
00133   int textWidth = 1;
00134   int textHeight = 1;
00135   GetTextExtents(textWidth, textHeight);
00136   SetMinimumSize(textWidth + ITEM_INDENT_ABS + 3 * ITEM_MARGIN,
00137                  textHeight + 2 * ITEM_MARGIN);
00138 }
00139 
00140 QuicklistMenuItemType QuicklistMenuItem::GetItemType()
00141 {
00142   return _item_type;
00143 }
00144 
00145 void
00146 QuicklistMenuItem::PreLayoutManagement()
00147 {
00148   View::PreLayoutManagement();
00149 }
00150 
00151 long
00152 QuicklistMenuItem::PostLayoutManagement(long layoutResult)
00153 {
00154   long result = View::PostLayoutManagement(layoutResult);
00155 
00156   return result;
00157 }
00158 
00159 void
00160 QuicklistMenuItem::Draw(nux::GraphicsEngine& gfxContext,
00161                         bool                 forceDraw)
00162 {
00163 }
00164 
00165 void
00166 QuicklistMenuItem::DrawContent(nux::GraphicsEngine& gfxContext,
00167                                bool                 forceDraw)
00168 {
00169 }
00170 
00171 void
00172 QuicklistMenuItem::PostDraw(nux::GraphicsEngine& gfxContext,
00173                             bool                 forceDraw)
00174 {
00175 }
00176 
00177 const gchar*
00178 QuicklistMenuItem::GetLabel()
00179 {
00180   if (_menuItem == 0)
00181     return 0;
00182   return dbusmenu_menuitem_property_get(_menuItem,
00183                                         DBUSMENU_MENUITEM_PROP_LABEL);
00184 }
00185 
00186 bool
00187 QuicklistMenuItem::GetEnabled()
00188 {
00189   if (_menuItem == 0)
00190     return false;
00191   return dbusmenu_menuitem_property_get_bool(_menuItem,
00192                                              DBUSMENU_MENUITEM_PROP_ENABLED);
00193 }
00194 
00195 bool
00196 QuicklistMenuItem::GetActive()
00197 {
00198   if (_menuItem == 0)
00199     return false;
00200   return dbusmenu_menuitem_property_get_int(_menuItem,
00201                                             DBUSMENU_MENUITEM_PROP_TOGGLE_STATE) == DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED;
00202 }
00203 
00204 bool
00205 QuicklistMenuItem::GetVisible()
00206 {
00207   if (_menuItem == 0)
00208     return false;
00209   return dbusmenu_menuitem_property_get_bool(_menuItem,
00210                                              DBUSMENU_MENUITEM_PROP_VISIBLE);
00211 }
00212 
00213 bool
00214 QuicklistMenuItem::GetSelectable()
00215 {
00216   return GetVisible() && GetEnabled();
00217 }
00218 
00219 void QuicklistMenuItem::ItemActivated()
00220 {
00221   if (_debug)
00222     sigChanged.emit(*this);
00223 
00224   std::cout << "ItemActivated() called" << std::endl;
00225 }
00226 
00227 gchar* QuicklistMenuItem::GetText()
00228 {
00229   const gchar *label;
00230   gchar *text;
00231 
00232   if (!_menuItem)
00233     return NULL;
00234 
00235   label = GetLabel();
00236 
00237   if (!label)
00238     return NULL;
00239 
00240   if (!IsMarkupEnabled())
00241   {
00242     text = g_markup_escape_text(label, -1);
00243   }
00244   else
00245   {
00246     text = g_strdup(label);
00247   }
00248 
00249   return text;
00250 }
00251 
00252 void QuicklistMenuItem::GetTextExtents(int& width, int& height)
00253 {
00254   GtkSettings* settings = gtk_settings_get_default();  // not ref'ed
00255   gchar*       fontName = NULL;
00256 
00257   g_object_get(settings, "gtk-font-name", &fontName, NULL);
00258   GetTextExtents(fontName, width, height);
00259   g_free(fontName);
00260 }
00261 
00262 void QuicklistMenuItem::GetTextExtents(const gchar* font,
00263                                        int&         width,
00264                                        int&         height)
00265 {
00266   cairo_surface_t*      surface  = NULL;
00267   cairo_t*              cr       = NULL;
00268   PangoLayout*          layout   = NULL;
00269   PangoFontDescription* desc     = NULL;
00270   PangoContext*         pangoCtx = NULL;
00271   PangoRectangle        logRect  = {0, 0, 0, 0};
00272   int                   dpi      = 0;
00273   GdkScreen*            screen   = gdk_screen_get_default();    // is not ref'ed
00274   GtkSettings*          settings = gtk_settings_get_default();  // is not ref'ed
00275 
00276   // sanity check
00277   if (!font)
00278     return;
00279 
00280   if (_text == "")
00281     return;
00282 
00283   surface = cairo_image_surface_create(CAIRO_FORMAT_A1, 1, 1);
00284   cr = cairo_create(surface);
00285   cairo_set_font_options(cr, gdk_screen_get_font_options(screen));
00286   layout = pango_cairo_create_layout(cr);
00287   desc = pango_font_description_from_string(font);
00288   pango_font_description_set_weight(desc, PANGO_WEIGHT_NORMAL);
00289   pango_layout_set_font_description(layout, desc);
00290   pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
00291   pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
00292   pango_layout_set_markup_with_accel(layout, _text.c_str(), -1, '_', NULL);
00293   pangoCtx = pango_layout_get_context(layout);  // is not ref'ed
00294   pango_cairo_context_set_font_options(pangoCtx,
00295                                        gdk_screen_get_font_options(screen));
00296   g_object_get(settings, "gtk-xft-dpi", &dpi, NULL);
00297   if (dpi == -1)
00298   {
00299     // use some default DPI-value
00300     pango_cairo_context_set_resolution(pangoCtx, 96.0f);
00301   }
00302   else
00303   {
00304     pango_cairo_context_set_resolution(pangoCtx,
00305                                        (float) dpi / (float) PANGO_SCALE);
00306   }
00307   pango_layout_context_changed(layout);
00308   pango_layout_get_extents(layout, NULL, &logRect);
00309 
00310   width  = logRect.width / PANGO_SCALE;
00311   height = logRect.height / PANGO_SCALE;
00312 
00313   // clean up
00314   pango_font_description_free(desc);
00315   g_object_unref(layout);
00316   cairo_destroy(cr);
00317   cairo_surface_destroy(surface);
00318 }
00319 
00320 static void
00321 OnPropertyChanged(gchar*             property,
00322                   GValue*            value,
00323                   QuicklistMenuItem* self)
00324 {
00325   //todo
00326   //self->UpdateTexture ();
00327 }
00328 
00329 static void
00330 OnItemActivated(guint              timestamp,
00331                 QuicklistMenuItem* self)
00332 {
00333   //todo:
00334   //self->ItemActivated ();
00335 }
00336 
00337 void QuicklistMenuItem::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
00338 {
00339   sigMouseReleased.emit(this, x, y);
00340 }
00341 
00342 void QuicklistMenuItem::RecvMouseClick(int x, int y, unsigned long button_flags, unsigned long key_flags)
00343 {
00344   if (!GetEnabled())
00345   {
00346     return;
00347   }
00348   sigMouseClick.emit(this, x, y);
00349 }
00350 
00351 void QuicklistMenuItem::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00352 {
00353   sigMouseDrag.emit(this, x, y);
00354 }
00355 
00356 void QuicklistMenuItem::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
00357 {
00358   sigMouseEnter.emit(this);
00359 }
00360 
00361 void QuicklistMenuItem::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
00362 {
00363   sigMouseLeave.emit(this);
00364 }
00365 
00366 void QuicklistMenuItem::DrawText(nux::CairoGraphics* cairo, int width, int height, nux::Color const& color)
00367 {
00368   if (_text == "" || cairo == nullptr)
00369     return;
00370 
00371   cairo_t*              cr         = cairo->GetContext();
00372   int                   textWidth  = 0;
00373   int                   textHeight = 0;
00374   PangoLayout*          layout     = NULL;
00375   PangoFontDescription* desc       = NULL;
00376   PangoContext*         pangoCtx   = NULL;
00377   int                   dpi        = 0;
00378   GdkScreen*            screen     = gdk_screen_get_default();    // not ref'ed
00379   GtkSettings*          settings   = gtk_settings_get_default();  // not ref'ed
00380   gchar*                fontName   = NULL;
00381 
00382   g_object_get(settings, "gtk-font-name", &fontName, NULL);
00383   GetTextExtents(fontName, textWidth, textHeight);
00384 
00385   cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
00386   cairo_set_source_rgba(cr, color.red, color.blue, color.green, color.alpha);
00387   cairo_set_font_options(cr, gdk_screen_get_font_options(screen));
00388   layout = pango_cairo_create_layout(cr);
00389   desc = pango_font_description_from_string(fontName);
00390   pango_layout_set_font_description(layout, desc);
00391   pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
00392   pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
00393   pango_layout_set_markup_with_accel(layout, _text.c_str(), -1, '_', NULL);
00394   pangoCtx = pango_layout_get_context(layout);  // is not ref'ed
00395   pango_cairo_context_set_font_options(pangoCtx,
00396                                        gdk_screen_get_font_options(screen));
00397   g_object_get(settings, "gtk-xft-dpi", &dpi, NULL);
00398   if (dpi == -1)
00399   {
00400     // use some default DPI-value
00401     pango_cairo_context_set_resolution(pangoCtx, 96.0f);
00402   }
00403   else
00404   {
00405     pango_cairo_context_set_resolution(pangoCtx,
00406                                        (float) dpi / (float) PANGO_SCALE);
00407   }
00408 
00409   pango_layout_context_changed(layout);
00410 
00411   cairo_move_to(cr,
00412                 2 * ITEM_MARGIN + ITEM_INDENT_ABS,
00413                 (float)(height - textHeight) / 2.0f);
00414   pango_cairo_show_layout(cr, layout);
00415 
00416   // clean up
00417   pango_font_description_free(desc);
00418   g_free(fontName);
00419   g_object_unref(layout);
00420   cairo_destroy(cr);
00421 }
00422 
00423 void QuicklistMenuItem::DrawPrelight(nux::CairoGraphics* cairo, int width, int height, nux::Color const& color)
00424 {
00425   if (!cairo)
00426     return;
00427 
00428   cairo_t* cr = cairo->GetContext();
00429 
00430   cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
00431   cairo_set_source_rgba(cr, color.red, color.blue, color.green, color.alpha);
00432   cairo->DrawRoundedRectangle(cr, 1.0f, 0.0f, 0.0f, ITEM_CORNER_RADIUS_ABS,
00433                               width, height);
00434   cairo_fill(cr);
00435   cairo_destroy(cr);
00436 }
00437 
00438 void
00439 QuicklistMenuItem::EnableLabelMarkup(bool enabled)
00440 {
00441   if (IsMarkupEnabled() != enabled)
00442   {
00443     dbusmenu_menuitem_property_set_bool(_menuItem, "unity-use-markup", enabled);
00444 
00445     _text = "";
00446     InitializeText();
00447   }
00448 }
00449 
00450 bool
00451 QuicklistMenuItem::IsMarkupEnabled()
00452 {
00453   gboolean markup;
00454 
00455   if (!_menuItem)
00456     return false;
00457 
00458   markup = dbusmenu_menuitem_property_get_bool(_menuItem, "unity-use-markup");
00459   return (markup != FALSE);
00460 }
00461 
00462 // Introspection
00463 
00464 std::string QuicklistMenuItem::GetName() const
00465 {
00466   return _name;
00467 }
00468 
00469 void QuicklistMenuItem::AddProperties(GVariantBuilder* builder)
00470 {
00471   unity::variant::BuilderWrapper(builder)
00472   .add(GetAbsoluteGeometry())
00473   .add("text", _text)
00474   .add("enabled", GetEnabled())
00475   .add("active", GetActive())
00476   .add("visible", GetVisible())
00477   .add("selectable", GetSelectable())
00478   .add("selected", _prelight);
00479 }
00480 
00481 } //NAMESPACE