Home | History | Annotate | Download | only in pdf
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "pdf/fading_controls.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/stl_util.h"
      9 #include "pdf/draw_utils.h"
     10 #include "pdf/resource_consts.h"
     11 #include "ppapi/cpp/input_event.h"
     12 
     13 namespace chrome_pdf {
     14 
     15 const uint32 kFadingAlphaShift = 64;
     16 const uint32 kSplashFadingAlphaShift = 16;
     17 
     18 FadingControls::FadingControls()
     19     : state_(NONE), current_transparency_(kOpaqueAlpha), fading_timer_id_(0),
     20       current_capture_control_(kInvalidControlId),
     21       fading_timeout_(kFadingTimeoutMs), alpha_shift_(kFadingAlphaShift),
     22       splash_(false), splash_timeout_(0) {
     23 }
     24 
     25 FadingControls::~FadingControls() {
     26   STLDeleteElements(&controls_);
     27 }
     28 
     29 bool FadingControls::CreateFadingControls(
     30     uint32 id, const pp::Rect& rc, bool visible,
     31     Control::Owner* owner, uint8 transparency) {
     32   current_transparency_ = transparency;
     33   return Control::Create(id, rc, visible, owner);
     34 }
     35 
     36 void FadingControls::Paint(pp::ImageData* image_data, const pp::Rect& rc) {
     37   // When this control is set to invisible the individual controls are not.
     38   // So we need to check for visible() here.
     39   if (!visible())
     40     return;
     41 
     42   std::list<Control*>::iterator iter;
     43   for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
     44     (*iter)->Paint(image_data, rc);
     45   }
     46 }
     47 
     48 bool FadingControls::HandleEvent(const pp::InputEvent& event) {
     49   if (!visible())
     50     return false;
     51 
     52   pp::MouseInputEvent mouse_event(event);
     53   if (mouse_event.is_null())
     54     return NotifyControls(event);
     55 
     56   pp::Point pt = mouse_event.GetPosition();
     57 
     58   bool is_mouse_click =
     59       mouse_event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN ||
     60       mouse_event.GetType() == PP_INPUTEVENT_TYPE_MOUSEUP;
     61 
     62   if (rect().Contains(pt)) {
     63     CancelSplashMode();
     64     FadeIn();
     65 
     66     // Eat mouse click if are invisible or just fading in.
     67     // That prevents accidental clicks on the controls for touch devices.
     68     bool eat_mouse_click =
     69         (state_ == FADING_IN || current_transparency_ == kTransparentAlpha);
     70     if (eat_mouse_click && is_mouse_click &&
     71         mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT)
     72       return true;  // Eat this event here.
     73   }
     74 
     75   if ((!rect().Contains(pt)) ||
     76       event.GetType() == PP_INPUTEVENT_TYPE_MOUSELEAVE) {
     77     if (!splash_)
     78       FadeOut();
     79     pp::MouseInputEvent event_leave(pp::MouseInputEvent(
     80         owner()->GetInstance(),
     81         PP_INPUTEVENT_TYPE_MOUSELEAVE,
     82         event.GetTimeStamp(),
     83         event.GetModifiers(),
     84         mouse_event.GetButton(),
     85         mouse_event.GetPosition(),
     86         mouse_event.GetClickCount(),
     87         mouse_event.GetMovement()));
     88     return NotifyControls(event_leave);
     89   }
     90 
     91   return NotifyControls(event);
     92 }
     93 
     94 void FadingControls::OnTimerFired(uint32 timer_id) {
     95   if (timer_id == fading_timer_id_) {
     96     int32 current_alpha = static_cast<int32>(current_transparency_);
     97     if (state_ == FADING_IN)
     98       current_alpha += alpha_shift_;
     99     else if (state_ == FADING_OUT)
    100       current_alpha -= alpha_shift_;
    101 
    102     if (current_alpha >= kOpaqueAlpha) {
    103       state_ = NONE;
    104       current_alpha = kOpaqueAlpha;
    105     } else if (current_alpha <= kTransparentAlpha) {
    106       state_ = NONE;
    107       current_alpha = kTransparentAlpha;
    108     }
    109     current_transparency_ = static_cast<uint8>(current_alpha);
    110 
    111     // Invalidate controls with new alpha transparency.
    112     std::list<Control*>::iterator iter;
    113     for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
    114       // We are going to invalidate the whole FadingControls area, to
    115       // allow simultaneous drawing.
    116       (*iter)->AdjustTransparency(current_transparency_, false);
    117     }
    118     owner()->Invalidate(id(), GetControlsRect());
    119 
    120     if (state_ != NONE)  // Fading still in progress.
    121       fading_timer_id_ = owner()->ScheduleTimer(id(), fading_timeout_);
    122     else
    123       OnFadingComplete();
    124   } else {
    125     // Dispatch timer to controls.
    126     std::list<Control*>::iterator iter;
    127     for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
    128       (*iter)->OnTimerFired(timer_id);
    129     }
    130   }
    131 }
    132 
    133 void FadingControls::EventCaptureReleased() {
    134   if (current_capture_control_ != kInvalidControlId) {
    135     // Remove previous catpure.
    136     Control* ctrl = GetControl(current_capture_control_);
    137     if (ctrl)
    138       ctrl->EventCaptureReleased();
    139   }
    140 }
    141 
    142 void FadingControls::MoveBy(const pp::Point& offset, bool invalidate) {
    143   std::list<Control*>::iterator iter;
    144   for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
    145     // We invalidate entire FadingControl later if needed.
    146     (*iter)->MoveBy(offset, false);
    147   }
    148   Control::MoveBy(offset, invalidate);
    149 }
    150 
    151 void FadingControls::OnEvent(uint32 control_id, uint32 event_id, void* data) {
    152   owner()->OnEvent(control_id, event_id, data);
    153 }
    154 
    155 void FadingControls::Invalidate(uint32 control_id, const pp::Rect& rc) {
    156   owner()->Invalidate(control_id, rc);
    157 }
    158 
    159 uint32 FadingControls::ScheduleTimer(uint32 control_id, uint32 timeout_ms) {
    160   // TODO(gene): implement timer routine properly.
    161   NOTIMPLEMENTED();
    162   //owner()->ScheduleTimer(control_id);
    163   return 0;
    164 }
    165 
    166 void FadingControls::SetEventCapture(uint32 control_id, bool set_capture) {
    167   if (control_id == current_capture_control_) {
    168     if (!set_capture)  // Remove event capture.
    169       current_capture_control_ = kInvalidControlId;
    170   } else {
    171     EventCaptureReleased();
    172     current_capture_control_ = control_id;
    173   }
    174 }
    175 
    176 void FadingControls::SetCursor(uint32 control_id,
    177                                PP_CursorType_Dev cursor_type) {
    178   owner()->SetCursor(control_id, cursor_type);
    179 }
    180 
    181 pp::Instance* FadingControls::GetInstance() {
    182   return owner()->GetInstance();
    183 }
    184 
    185 bool FadingControls::AddControl(Control* control) {
    186   DCHECK(control);
    187   if (control->owner() != this)
    188     return false;
    189   if (!rect().Contains(control->rect()))
    190     return false;
    191 
    192   control->AdjustTransparency(current_transparency_, false);
    193   controls_.push_back(control);
    194   return true;
    195 }
    196 
    197 void FadingControls::RemoveControl(uint32 control_id) {
    198   if (current_capture_control_ == control_id) {
    199     current_capture_control_ = kInvalidControlId;
    200   }
    201   std::list<Control*>::iterator iter;
    202   for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
    203     if ((*iter)->id() == control_id) {
    204       delete (*iter);
    205       controls_.erase(iter);
    206       break;
    207     }
    208   }
    209 }
    210 
    211 Control* FadingControls::GetControl(uint32 id) {
    212   std::list<Control*>::iterator iter;
    213   for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
    214     if ((*iter)->id() == id)
    215       return *iter;
    216   }
    217   return NULL;
    218 }
    219 
    220 pp::Rect FadingControls::GetControlsRect() {
    221   pp::Rect rc;
    222   std::list<Control*>::iterator iter;
    223   for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
    224     rc = rc.Union((*iter)->rect());
    225   }
    226   return rc;
    227 }
    228 
    229 bool FadingControls::ExpandLeft(int offset) {
    230   pp::Rect rc = rect();
    231   rc.set_width(rc.width() + offset);
    232   rc.set_x(rc.x() - offset);
    233   if (!rc.Contains(GetControlsRect()))
    234     return false;
    235   // No need to invalidate since we are expanding triggering area only.
    236   SetRect(rc, false);
    237   return true;
    238 }
    239 
    240 void FadingControls::Splash(uint32 time_ms) {
    241   splash_ = true;
    242   splash_timeout_ = time_ms;
    243   alpha_shift_ = kSplashFadingAlphaShift;
    244   FadeIn();
    245 }
    246 
    247 bool FadingControls::NotifyControls(const pp::InputEvent& event) {
    248   // First pass event to a control that current capture is set to.
    249   Control* ctrl = GetControl(current_capture_control_);
    250   if (ctrl) {
    251     if (ctrl->HandleEvent(event))
    252       return true;
    253   }
    254 
    255   std::list<Control*>::iterator iter;
    256   for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
    257     // Now pass event to all control except control with capture,
    258     // since we already passed to it above.
    259     if ((*iter) != ctrl && (*iter)->HandleEvent(event))
    260       return true;
    261   }
    262   return false;
    263 }
    264 
    265 void FadingControls::FadeIn() {
    266   bool already_visible =
    267       (state_ == NONE && current_transparency_ == kOpaqueAlpha);
    268   if (state_ != FADING_IN && !already_visible) {
    269     state_ = FADING_IN;
    270     fading_timer_id_ = owner()->ScheduleTimer(id(), fading_timeout_);
    271   }
    272   if (already_visible)
    273     OnFadingComplete();
    274 }
    275 
    276 void FadingControls::FadeOut() {
    277   bool already_invisible =
    278       (state_ == NONE && current_transparency_ == kTransparentAlpha);
    279   if (state_ != FADING_OUT && !already_invisible) {
    280     state_ = FADING_OUT;
    281     fading_timer_id_ = owner()->ScheduleTimer(id(), fading_timeout_);
    282   }
    283   if (already_invisible)
    284     OnFadingComplete();
    285 }
    286 
    287 void FadingControls::OnFadingComplete() {
    288   DCHECK(current_transparency_ == kOpaqueAlpha ||
    289       current_transparency_ == kTransparentAlpha);
    290   // In the splash mode following states are possible:
    291   // Fade-in complete: splash_==true, splash_timeout_ != 0
    292   //   We need to schedule timer for splash_timeout_.
    293   // Splash timeout complete: splash_==true, splash_timeout_ == 0
    294   //   We need to fade out still using splash settings.
    295   // Fade-out complete: current_transparency_ == kTransparentAlpha
    296   //   We need to cancel splash mode and go back to normal settings.
    297   if (splash_) {
    298     if (current_transparency_ == kOpaqueAlpha) {
    299       if (splash_timeout_) {
    300         fading_timer_id_ = owner()->ScheduleTimer(id(), splash_timeout_);
    301         splash_timeout_ = 0;
    302       } else {
    303         FadeOut();
    304       }
    305     } else {
    306       CancelSplashMode();
    307     }
    308   }
    309 }
    310 
    311 void FadingControls::CancelSplashMode() {
    312   splash_ = false;
    313   alpha_shift_ = kFadingAlphaShift;
    314 }
    315 
    316 }  // namespace chrome_pdf
    317