"Fossies" - the Fresh Open Source Software Archive

Member "google-gadgets-for-linux-0.11.2/ggadget/copy_element.cc" (28 Dec 2009, 6986 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 <string>
   18 
   19 #include "graphics_interface.h"
   20 #include "copy_element.h"
   21 #include "canvas_interface.h"
   22 #include "view.h"
   23 #include "small_object.h"
   24 
   25 namespace ggadget {
   26 
   27 class CopyElement::Impl : public SmallObject<> {
   28  public:
   29   Impl(CopyElement *owner)
   30     : owner_(owner),
   31       snapshot_(NULL),
   32       source_(NULL),
   33       refchange_connection_(NULL),
   34       update_connection_(NULL),
   35       frozen_(false) {
   36   }
   37 
   38   ~Impl() {
   39     // Clear the source.
   40     SetSrc(Variant());
   41     DestroyCanvas(snapshot_);
   42   }
   43 
   44   void OnSourceRefChange(int ref_count, int change) {
   45     GGL_UNUSED(ref_count);
   46     if (change == 0) {
   47       // The source's destructor is being called.
   48       refchange_connection_->Disconnect();
   49       refchange_connection_ = NULL;
   50       source_->Unref(true);
   51       source_ = NULL;
   52       UpdateSnapshot();
   53     }
   54   }
   55 
   56   void UpdateSnapshot() {
   57     if (frozen_) return;
   58 
   59     // Don't keep snapshot if there is no source or the source is invisible.
   60     if (!source_ || !source_->IsVisible()) {
   61       DestroyCanvas(snapshot_);
   62       snapshot_ = NULL;
   63       owner_->QueueDraw();
   64       return;
   65     }
   66 
   67     double width = source_->GetPixelWidth();
   68     double height = source_->GetPixelHeight();
   69     if (snapshot_ &&
   70         (snapshot_->GetWidth() != width || snapshot_->GetHeight() != height)) {
   71       DestroyCanvas(snapshot_);
   72       snapshot_ = NULL;
   73     }
   74 
   75     if (!snapshot_) {
   76       GraphicsInterface *gfx = owner_->GetView()->GetGraphics();
   77       if (gfx)
   78         snapshot_ = gfx->NewCanvas(width, height);
   79     }
   80 
   81     if (snapshot_) {
   82       snapshot_->ClearCanvas();
   83       owner_->GetView()->EnableClipRegion(false);
   84       source_->Draw(snapshot_);
   85       owner_->GetView()->EnableClipRegion(true);
   86     }
   87 
   88     owner_->QueueDraw();
   89   }
   90 
   91   void SetSrc(const Variant &src) {
   92     if (source_) {
   93       refchange_connection_->Disconnect();
   94       refchange_connection_ = NULL;
   95       update_connection_->Disconnect();
   96       update_connection_ = NULL;
   97       source_->Unref();
   98       source_ = NULL;
   99     }
  100 
  101     Variant::Type type = src.type();
  102     if (type == Variant::TYPE_STRING) {
  103       const char *src_name= VariantValue<const char*>()(src);
  104       if (src_name && *src_name) {
  105         source_ = owner_->GetView()->GetElementByName(src_name);
  106         // The source element is not added yet, save the name and try to load
  107         // it later.
  108         if (!source_)
  109           src_name_ = src_name;
  110       }
  111     } else if (type == Variant::TYPE_SCRIPTABLE) {
  112       ScriptableInterface *obj = VariantValue<ScriptableInterface *>()(src);
  113       if (obj && obj->IsInstanceOf(BasicElement::CLASS_ID))
  114         source_ = down_cast<BasicElement *>(obj);
  115     }
  116 
  117     if (source_) {
  118       source_->Ref();
  119       refchange_connection_ = source_->ConnectOnReferenceChange(
  120           NewSlot(this, &Impl::OnSourceRefChange));
  121       update_connection_ = source_->ConnectOnContentChanged(
  122           NewSlot(this, &Impl::UpdateSnapshot));
  123 
  124       UpdateSnapshot();
  125     } else if (snapshot_ && !frozen_) {
  126       DestroyCanvas(snapshot_);
  127       snapshot_ = NULL;
  128     }
  129   }
  130 
  131   Variant GetSrc() {
  132     return source_ ? Variant(source_->GetName()) : Variant();
  133   }
  134 
  135   CopyElement *owner_;
  136   CanvasInterface *snapshot_;
  137   BasicElement *source_;
  138   Connection *refchange_connection_;
  139   Connection *update_connection_;
  140   std::string src_name_;
  141   bool frozen_;
  142 };
  143 
  144 CopyElement::CopyElement(View *view, const char *name)
  145     : BasicElement(view, "copy", name, false),
  146       impl_(new Impl(this)) {
  147 }
  148 
  149 void CopyElement::DoClassRegister() {
  150   BasicElement::DoClassRegister();
  151   RegisterProperty("src",
  152                    NewSlot(&Impl::GetSrc, &CopyElement::impl_),
  153                    NewSlot(&Impl::SetSrc, &CopyElement::impl_));
  154 }
  155 
  156 CopyElement::~CopyElement() {
  157   delete impl_;
  158   impl_ = NULL;
  159 }
  160 
  161 bool CopyElement::IsFrozen() const {
  162   return impl_->frozen_;
  163 }
  164 
  165 void CopyElement::SetFrozen(bool frozen) {
  166   impl_->frozen_ = frozen;
  167   if (!frozen)
  168     impl_->UpdateSnapshot();
  169 }
  170 
  171 bool CopyElement::IsPointIn(double x, double y) const {
  172   // Return false directly if the point is outside the element boundary.
  173   if (!BasicElement::IsPointIn(x, y))
  174     return false;
  175 
  176   double opacity = 0;
  177   if (impl_->snapshot_) {
  178     x = x * impl_->snapshot_->GetWidth() / GetPixelWidth();
  179     y = y * impl_->snapshot_->GetHeight() / GetPixelHeight();
  180 
  181     if (!impl_->snapshot_->GetPointValue(x, y, NULL, &opacity))
  182       return true;
  183   }
  184 
  185   return opacity > 0;
  186 }
  187 
  188 void CopyElement::DoDraw(CanvasInterface *canvas) {
  189   if (impl_->snapshot_) {
  190     double w = GetPixelWidth();
  191     double h = GetPixelHeight();
  192     double sw = impl_->snapshot_->GetWidth();
  193     double sh = impl_->snapshot_->GetHeight();
  194     double cx = w / sw;
  195     double cy = h / sh;
  196     if (cx != 1 || cy != 1)
  197       canvas->ScaleCoordinates(cx, cy);
  198     canvas->DrawCanvas(0, 0, impl_->snapshot_);
  199   }
  200 }
  201 
  202 Variant CopyElement::GetSrc() const {
  203   return impl_->GetSrc();
  204 }
  205 
  206 void CopyElement::SetSrc(const Variant &src) {
  207   impl_->SetSrc(src);
  208 }
  209 
  210 void CopyElement::GetDefaultSize(double *width, double *height) const {
  211   ASSERT(width && height);
  212 
  213   // Try to set source again.
  214   if (!impl_->source_ && !impl_->src_name_.empty()) {
  215     impl_->SetSrc(Variant(impl_->src_name_));
  216     // Only try once.
  217     impl_->src_name_.clear();
  218   }
  219 
  220   if (impl_->frozen_) {
  221     *width = (impl_->snapshot_ ? impl_->snapshot_->GetWidth() : 0);
  222     *height = (impl_->snapshot_ ? impl_->snapshot_->GetHeight() : 0);
  223   } else {
  224     *width = (impl_->source_ ? impl_->source_->GetPixelWidth() : 0);
  225     *height = (impl_->source_ ? impl_->source_->GetPixelHeight() : 0);
  226   }
  227 }
  228 
  229 void CopyElement::MarkRedraw() {
  230   if (impl_->snapshot_) {
  231     DestroyCanvas(impl_->snapshot_);
  232     impl_->snapshot_ = NULL;
  233     impl_->UpdateSnapshot();
  234   }
  235 }
  236 
  237 bool CopyElement::HasOpaqueBackground() const {
  238   if (!impl_->frozen_ && impl_->source_)
  239     return impl_->source_->HasOpaqueBackground();
  240   return false;
  241 }
  242 
  243 BasicElement *CopyElement::CreateInstance(View *view, const char *name) {
  244   return new CopyElement(view, name);
  245 }
  246 
  247 double CopyElement::GetSrcWidth() const {
  248   if (impl_->source_)
  249     return impl_->source_->GetPixelWidth();
  250   if (impl_->snapshot_)
  251     return impl_->snapshot_->GetWidth();
  252   return 0;
  253 }
  254 
  255 double CopyElement::GetSrcHeight() const {
  256   if (impl_->source_)
  257     return impl_->source_->GetPixelHeight();
  258   if (impl_->snapshot_)
  259     return impl_->snapshot_->GetHeight();
  260   return 0;
  261 }
  262 
  263 
  264 } // namespace ggadget