"Fossies" - the Fresh Open Source Software Archive

Member "google-gadgets-for-linux-0.11.2/ggadget/div_element.cc" (9 Jun 2009, 6432 Bytes) of package /linux/misc/old/google-gadgets-for-linux-0.11.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2   Copyright 2008 Google Inc.
    3 
    4   Licensed under the Apache License, Version 2.0 (the "License");
    5   you may not use this file except in compliance with the License.
    6   You may obtain a copy of the License at
    7 
    8        http://www.apache.org/licenses/LICENSE-2.0
    9 
   10   Unless required by applicable law or agreed to in writing, software
   11   distributed under the License is distributed on an "AS IS" BASIS,
   12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13   See the License for the specific language governing permissions and
   14   limitations under the License.
   15 */
   16 
   17 #include <cmath>
   18 #include "div_element.h"
   19 #include "canvas_interface.h"
   20 #include "canvas_utils.h"
   21 #include "elements.h"
   22 #include "logger.h"
   23 #include "texture.h"
   24 #include "view.h"
   25 #include "small_object.h"
   26 
   27 namespace ggadget {
   28 
   29 class DivElement::Impl : public SmallObject<> {
   30  public:
   31   Impl(DivElement *owner)
   32       : owner_(owner),
   33         background_texture_(NULL),
   34         background_mode_(BACKGROUND_MODE_TILE),
   35         layout_recurse_depth_(0),
   36         last_client_width_(0),
   37         last_client_height_(0) {
   38   }
   39   ~Impl() {
   40     delete background_texture_;
   41     background_texture_ = NULL;
   42   }
   43 
   44   DivElement *owner_;
   45   Texture *background_texture_;
   46   BackgroundMode background_mode_;
   47   int layout_recurse_depth_;
   48   int last_client_width_;
   49   int last_client_height_;
   50 };
   51 
   52 DivElement::DivElement(View *view, const char *name)
   53     : ScrollingElement(view, "div", name, true),
   54       impl_(new Impl(this)) {
   55 }
   56 
   57 DivElement::DivElement(View *view, const char *tag_name, const char *name)
   58     : ScrollingElement(view, tag_name, name, true),
   59       impl_(new Impl(this)) {
   60 }
   61 
   62 void DivElement::DoClassRegister() {
   63   ScrollingElement::DoClassRegister();
   64   RegisterProperty("autoscroll",
   65                    NewSlot(&ScrollingElement::IsAutoscroll),
   66                    NewSlot(&ScrollingElement::SetAutoscroll));
   67   RegisterProperty("background",
   68                    NewSlot(&DivElement::GetBackground),
   69                    NewSlot(&DivElement::SetBackground));
   70   // "backgroundMode" is for native use only.
   71   // JS can use <img stretchMode="true"> to get the similar effect.
   72 }
   73 
   74 DivElement::~DivElement() {
   75   delete impl_;
   76   impl_ = NULL;
   77 }
   78 
   79 void DivElement::Layout() {
   80   ScrollingElement::Layout();
   81   double children_width = 0, children_height = 0;
   82   GetChildrenExtents(&children_width, &children_height);
   83 
   84   int x_range = static_cast<int>(ceil(children_width - GetClientWidth()));
   85   int y_range = static_cast<int>(ceil(children_height - GetClientHeight()));
   86 
   87   if (x_range < 0) x_range = 0;
   88   if (y_range < 0) y_range = 0;
   89 
   90   int client_height = static_cast<int>(round(GetClientHeight()));
   91   int client_width = static_cast<int>(round(GetClientWidth()));
   92   if (client_height != impl_->last_client_height_) {
   93     impl_->last_client_height_ = client_height;
   94     SetYPageStep(client_height);
   95   }
   96   if (client_width != impl_->last_client_width_) {
   97     impl_->last_client_width_ = client_width;
   98     SetXPageStep(client_width);
   99   }
  100 
  101   // Check the resurce depth to prevent infinite recursion when updating the
  102   // scroll bar. This may be caused by rare case that the children height
  103   // reduces while the width reduces.
  104   // Check y_range > 0 to let the recursion stop after the scrollbar is shown,
  105   if (UpdateScrollBar(x_range, y_range) &&
  106       (y_range > 0 || impl_->layout_recurse_depth_ < 2)) {
  107     impl_->layout_recurse_depth_++;
  108     // Layout again to reflect visibility change of the scroll bars.
  109     Layout();
  110     impl_->layout_recurse_depth_--;
  111   }
  112 }
  113 
  114 void DivElement::DoDraw(CanvasInterface *canvas) {
  115   if (impl_->background_texture_) {
  116     const ImageInterface *texture_image =
  117         impl_->background_texture_->GetImage();
  118     if (!texture_image || impl_->background_mode_ == BACKGROUND_MODE_TILE) {
  119       impl_->background_texture_->Draw(canvas, 0, 0, GetPixelWidth(),
  120                                        GetPixelHeight());
  121     } else if (impl_->background_mode_ == BACKGROUND_MODE_STRETCH) {
  122       texture_image->StretchDraw(canvas, 0, 0,
  123                                  GetPixelWidth(), GetPixelHeight());
  124     } else {
  125       StretchMiddleDrawImage(texture_image, canvas, 0, 0,
  126                              GetPixelWidth(), GetPixelHeight(),
  127                              -1, -1, -1, -1);
  128     }
  129   }
  130 
  131   canvas->TranslateCoordinates(-GetScrollXPosition(),
  132                                -GetScrollYPosition());
  133   DrawChildren(canvas);
  134   canvas->TranslateCoordinates(GetScrollXPosition(),
  135                                GetScrollYPosition());
  136   DrawScrollbar(canvas);
  137 }
  138 
  139 Variant DivElement::GetBackground() const {
  140   return Variant(Texture::GetSrc(impl_->background_texture_));
  141 }
  142 
  143 void DivElement::SetBackground(const Variant &background) {
  144   if (background != GetBackground()) {
  145     delete impl_->background_texture_;
  146     impl_->background_texture_ = GetView()->LoadTexture(background);
  147     QueueDraw();
  148   }
  149 }
  150 
  151 DivElement::BackgroundMode DivElement::GetBackgroundMode() const {
  152   return impl_->background_mode_;
  153 }
  154 
  155 void DivElement::SetBackgroundMode(BackgroundMode mode) {
  156   if (mode != impl_->background_mode_) {
  157     impl_->background_mode_ = mode;
  158     QueueDraw();
  159   }
  160 }
  161 
  162 BasicElement *DivElement::CreateInstance(View *view, const char *name) {
  163   return new DivElement(view, name);
  164 }
  165 
  166 EventResult DivElement::HandleKeyEvent(const KeyboardEvent &event) {
  167   static const int kLineHeight = 5;
  168   static const int kLineWidth = 5;
  169 
  170   EventResult result = EVENT_RESULT_UNHANDLED;
  171   if (IsAutoscroll() && event.GetType() == Event::EVENT_KEY_DOWN) {
  172     result = EVENT_RESULT_HANDLED;
  173     switch (event.GetKeyCode()) {
  174       case KeyboardEvent::KEY_UP:
  175         ScrollY(-kLineHeight);
  176         break;
  177       case KeyboardEvent::KEY_DOWN:
  178         ScrollY(kLineHeight);
  179         break;
  180       case KeyboardEvent::KEY_LEFT:
  181         ScrollX(-kLineWidth);
  182         break;
  183       case KeyboardEvent::KEY_RIGHT:
  184         ScrollX(kLineWidth);
  185         break;
  186       case KeyboardEvent::KEY_PAGE_UP:
  187         ScrollY(-static_cast<int>(ceil(GetClientHeight())));
  188         break;
  189       case KeyboardEvent::KEY_PAGE_DOWN:
  190         ScrollY(static_cast<int>(ceil(GetClientHeight())));
  191         break;
  192       default:
  193         result = EVENT_RESULT_UNHANDLED;
  194         break;
  195     }
  196   }
  197   return result;
  198 }
  199 
  200 bool DivElement::HasOpaqueBackground() const {
  201   return impl_->background_texture_ ?
  202          impl_->background_texture_->IsFullyOpaque() :
  203          false;
  204 }
  205 
  206 } // namespace ggadget