Back to index

unity  6.0.0
FilterRatingsButton.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2011 Canonical Ltd.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License version 3, as
00006  * published by the  Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful, but
00009  * WITHOUT ANY WARRANTY; without even the implied warranties of
00010  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00011  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00012  * License for more details.
00013  *
00014  * You should have received a copy of both the GNU Lesser General Public
00015  * License version 3 along with this program.  If not, see
00016  * <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Gordon Allott <gord.allott@canonical.com>
00019  *
00020  */
00021 
00022 #include <math.h>
00023 
00024 #include <Nux/Nux.h>
00025 #include <NuxCore/Logger.h>
00026 
00027 #include "unity-shared/DashStyle.h"
00028 #include "FilterRatingsButton.h"
00029 
00030 namespace
00031 {
00032 const int star_size = 28;
00033 const int star_gap  = 10;
00034 const int num_stars = 5;
00035 }
00036 
00037 namespace unity
00038 {
00039 namespace dash
00040 {
00041 FilterRatingsButton::FilterRatingsButton(NUX_FILE_LINE_DECL)
00042   : nux::ToggleButton(NUX_FILE_LINE_PARAM)
00043   , focused_star_(-1)
00044 {
00045   SetAcceptKeyNavFocusOnMouseDown(false);
00046   SetAcceptKeyNavFocusOnMouseEnter(true);
00047 
00048   mouse_up.connect(sigc::mem_fun(this, &FilterRatingsButton::RecvMouseUp));
00049   mouse_move.connect(sigc::mem_fun(this, &FilterRatingsButton::RecvMouseMove));
00050   mouse_drag.connect(sigc::mem_fun(this, &FilterRatingsButton::RecvMouseDrag));
00051 
00052   key_nav_focus_change.connect([&](nux::Area* area, bool has_focus, nux::KeyNavDirection direction)
00053   {
00054     if (has_focus && direction != nux::KEY_NAV_NONE)
00055       focused_star_ = 0;
00056     else if (!has_focus)
00057       focused_star_ = -1;
00058 
00059     QueueDraw();
00060   });
00061   key_nav_focus_activate.connect([&](nux::Area*) { filter_->rating = static_cast<float>(focused_star_+1)/num_stars; });
00062   key_down.connect(sigc::mem_fun(this, &FilterRatingsButton::OnKeyDown));
00063 }
00064 
00065 FilterRatingsButton::~FilterRatingsButton()
00066 {
00067 }
00068 
00069 void FilterRatingsButton::SetFilter(Filter::Ptr const& filter)
00070 {
00071   filter_ = std::static_pointer_cast<RatingsFilter>(filter);
00072   filter_->rating.changed.connect(sigc::mem_fun(this, &FilterRatingsButton::OnRatingsChanged));
00073   NeedRedraw();
00074 }
00075 
00076 std::string FilterRatingsButton::GetFilterType()
00077 {
00078   return "FilterRatingsButton";
00079 }
00080 
00081 void FilterRatingsButton::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
00082 {
00083   int rating = 0;
00084   if (filter_ && filter_->filtering)
00085     rating = static_cast<int>(filter_->rating * num_stars);
00086   // FIXME: 9/26/2011
00087   // We should probably support an API for saying whether the ratings
00088   // should or shouldn't support half stars...but our only consumer at
00089   // the moment is the applications lens which according to design
00090   // (Bug #839759) shouldn't. So for now just force rounding.
00091   //    int total_half_stars = rating % 2;
00092   //    int total_full_stars = rating / 2;
00093   int total_full_stars = rating;
00094 
00095   nux::Geometry const& geo = GetGeometry();
00096   nux::Geometry geo_star(geo);
00097   geo_star.width = star_size;
00098 
00099   gPainter.PaintBackground(GfxContext, geo);
00100   // set up our texture mode
00101   nux::TexCoordXForm texxform;
00102   texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
00103   texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
00104 
00105   // clear what is behind us
00106   unsigned int alpha = 0, src = 0, dest = 0;
00107 
00108   GfxContext.GetRenderStates().GetBlend(alpha, src, dest);
00109   GfxContext.GetRenderStates().SetBlend(true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
00110 
00111   nux::Color col = nux::color::Black;
00112   col.alpha = 0;
00113   GfxContext.QRP_Color(geo.x,
00114                        geo.y,
00115                        geo.width,
00116                        geo.height,
00117                        col);
00118 
00119   for (int index = 0; index < num_stars; ++index)
00120   {
00121        Style& style = Style::Instance();
00122     nux::BaseTexture* texture = style.GetStarSelectedIcon();
00123     if (index < total_full_stars)
00124     {
00125       if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_NORMAL)
00126         texture = style.GetStarSelectedIcon();
00127       else if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRELIGHT)
00128         texture = style.GetStarSelectedIcon();
00129       else if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRESSED)
00130         texture = style.GetStarSelectedIcon();
00131     }
00132     else
00133     {
00134       if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_NORMAL)
00135         texture = style.GetStarDeselectedIcon();
00136       else if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRELIGHT)
00137         texture = style.GetStarDeselectedIcon();
00138       else if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRESSED)
00139         texture = style.GetStarDeselectedIcon();
00140     }
00141 
00142     GfxContext.QRP_1Tex(geo_star.x,
00143                         geo_star.y,
00144                         geo_star.width,
00145                         geo_star.height,
00146                         texture->GetDeviceTexture(),
00147                         texxform,
00148                         nux::Color(1.0f, 1.0f, 1.0f, 1.0f));
00149 
00150     if (focused_star_ == index)
00151     {
00152       GfxContext.QRP_1Tex(geo_star.x,
00153                           geo_star.y,
00154                           geo_star.width,
00155                           geo_star.height,
00156                           style.GetStarHighlightIcon()->GetDeviceTexture(),
00157                           texxform,
00158                           nux::Color(1.0f, 1.0f, 1.0f, 0.5f));
00159     }
00160 
00161     geo_star.x += geo_star.width + star_gap;
00162 
00163   }
00164 
00165   GfxContext.GetRenderStates().SetBlend(alpha, src, dest);
00166 
00167 }
00168 
00169 static void _UpdateRatingToMouse(RatingsFilter::Ptr filter, int x)
00170 {
00171   int width = 180;
00172   float new_rating = (static_cast<float>(x) / width);
00173 
00174   // FIXME: change to * 2 once we decide to support also half-stars
00175   new_rating = ceil((num_stars * 1) * new_rating) / (num_stars * 1);
00176   new_rating = (new_rating > 1) ? 1 : ((new_rating < 0) ? 0 : new_rating);
00177 
00178   if (filter)
00179     filter->rating = new_rating;
00180 }
00181 
00182 void FilterRatingsButton::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
00183 {
00184   _UpdateRatingToMouse(filter_, x);
00185 }
00186 
00187 void FilterRatingsButton::RecvMouseDrag(int x, int y, int dx, int dy,
00188                                         unsigned long button_flags,
00189                                         unsigned long key_flags)
00190 {
00191   _UpdateRatingToMouse(filter_, x);
00192 }
00193 
00194 void FilterRatingsButton::OnRatingsChanged(int rating)
00195 {
00196   NeedRedraw();
00197 }
00198 
00199 void FilterRatingsButton::RecvMouseMove(int x, int y, int dx, int dy,
00200                                         unsigned long button_flags,
00201                                         unsigned long key_flags)
00202 {
00203   int width = 180;
00204   focused_star_ = std::max(0, std::min(static_cast<int>(ceil((static_cast<float>(x) / width) * num_stars) - 1), num_stars - 1));
00205 
00206   if (!HasKeyFocus())
00207     nux::GetWindowCompositor().SetKeyFocusArea(this);
00208 
00209   QueueDraw();
00210 }
00211 
00212 
00213 bool FilterRatingsButton::InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character)
00214 {
00215   nux::KeyNavDirection direction = nux::KEY_NAV_NONE;
00216 
00217   switch (keysym)
00218   {
00219     case NUX_VK_LEFT:
00220       direction = nux::KeyNavDirection::KEY_NAV_LEFT;
00221       break;
00222     case NUX_VK_RIGHT:
00223       direction = nux::KeyNavDirection::KEY_NAV_RIGHT;
00224       break;
00225     default:
00226       direction = nux::KeyNavDirection::KEY_NAV_NONE;
00227       break;
00228   }
00229 
00230   if (direction == nux::KeyNavDirection::KEY_NAV_NONE)
00231     return false;
00232   else if (direction == nux::KEY_NAV_LEFT && (focused_star_ <= 0))
00233     return false;
00234   else if (direction == nux::KEY_NAV_RIGHT && (focused_star_ >= num_stars - 1))
00235     return false;
00236   else
00237    return true;
00238 }
00239 
00240 
00241 void FilterRatingsButton::OnKeyDown(unsigned long event_type, unsigned long event_keysym,
00242                                     unsigned long event_state, const TCHAR* character,
00243                                     unsigned short key_repeat_count)
00244 {
00245   switch (event_keysym)
00246   {
00247     case NUX_VK_LEFT:
00248       --focused_star_;
00249       break;
00250     case NUX_VK_RIGHT:
00251       ++focused_star_;
00252       break;
00253     default:
00254       return;
00255   }
00256 
00257   QueueDraw();
00258 }
00259 
00260 bool FilterRatingsButton::AcceptKeyNavFocus()
00261 {
00262   return true;
00263 }
00264 
00265 } // namespace dash
00266 } // namespace unity