Home | History | Annotate | Download | only in pdf
      1 // Copyright (c) 2010 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/button.h"
      6 
      7 #include "base/logging.h"
      8 #include "pdf/draw_utils.h"
      9 #include "ppapi/cpp/input_event.h"
     10 
     11 namespace chrome_pdf {
     12 
     13 Button::Button()
     14     : style_(BUTTON_CLICKABLE), state_(BUTTON_NORMAL), is_pressed_(false) {
     15 }
     16 
     17 Button::~Button() {
     18 }
     19 
     20 bool Button::CreateButton(uint32 id,
     21                           const pp::Point& origin,
     22                           bool visible,
     23                           Control::Owner* owner,
     24                           ButtonStyle style,
     25                           const pp::ImageData& face_normal,
     26                           const pp::ImageData& face_highlighted,
     27                           const pp::ImageData& face_pressed) {
     28   DCHECK(face_normal.size().GetArea());
     29   DCHECK(face_normal.size() == face_highlighted.size());
     30   DCHECK(face_normal.size() == face_pressed.size());
     31 
     32   pp::Rect rc(origin, face_normal.size());
     33   if (!Control::Create(id, rc, visible, owner))
     34     return false;
     35 
     36   style_ = style;
     37 
     38   normal_ = face_normal;
     39   highlighted_ = face_highlighted;
     40   pressed_ = face_pressed;
     41 
     42   return true;
     43 }
     44 
     45 
     46 void Button::Paint(pp::ImageData* image_data, const pp::Rect& rc) {
     47   if (!visible())
     48     return;
     49 
     50   pp::Rect draw_rc = rc.Intersect(rect());
     51   if (draw_rc.IsEmpty())
     52     return;
     53 
     54   pp::Point origin = draw_rc.point();
     55   draw_rc.Offset(-rect().x(), -rect().y());
     56 
     57   AlphaBlend(GetCurrentImage(), draw_rc, image_data, origin, transparency());
     58 }
     59 
     60 bool Button::HandleEvent(const pp::InputEvent& event) {
     61   if (!visible())
     62     return false;
     63 
     64   // Button handles mouse events only.
     65   pp::MouseInputEvent mouse_event(event);
     66    if (mouse_event.is_null())
     67     return false;
     68 
     69   pp::Point pt = mouse_event.GetPosition();
     70   if (!rect().Contains(pt) ||
     71       event.GetType() == PP_INPUTEVENT_TYPE_MOUSELEAVE) {
     72     ChangeState(BUTTON_NORMAL, false);
     73     owner()->SetEventCapture(id(), false);
     74     return false;
     75   }
     76 
     77   owner()->SetCursor(id(), PP_CURSORTYPE_POINTER);
     78   owner()->SetEventCapture(id(), true);
     79 
     80   bool handled = true;
     81   switch (event.GetType()) {
     82     case PP_INPUTEVENT_TYPE_MOUSEMOVE:
     83       if (state_ == BUTTON_NORMAL)
     84         ChangeState(BUTTON_HIGHLIGHTED, false);
     85       break;
     86     case PP_INPUTEVENT_TYPE_MOUSEDOWN:
     87       if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT) {
     88         ChangeState(BUTTON_PRESSED, false);
     89         is_pressed_ = true;
     90       }
     91       break;
     92     case PP_INPUTEVENT_TYPE_MOUSEUP:
     93       if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT &&
     94           is_pressed_) {
     95         OnButtonClicked();
     96         is_pressed_ = false;
     97       } else {
     98         // Since button has not been pressed, return false to allow other
     99         // controls (scrollbar) to process mouse button up.
    100         return false;
    101       }
    102       break;
    103     default:
    104       handled = false;
    105       break;
    106   }
    107 
    108   return handled;
    109 }
    110 
    111 void Button::OnEventCaptureReleased() {
    112   ChangeState(BUTTON_NORMAL, false);
    113 }
    114 
    115 void Button::Show(bool visible, bool invalidate) {
    116   // If button become invisible, remove pressed flag.
    117   if (!visible)
    118     is_pressed_ = false;
    119   Control::Show(visible, invalidate);
    120 }
    121 
    122 void Button::AdjustTransparency(uint8 transparency, bool invalidate) {
    123   // If button become invisible, remove pressed flag.
    124   if (transparency == kTransparentAlpha)
    125     is_pressed_ = false;
    126   Control::AdjustTransparency(transparency, invalidate);
    127 }
    128 
    129 void Button::SetPressedState(bool pressed) {
    130   if (style_ == BUTTON_STATE) {
    131     if (IsPressed() != pressed)
    132       ChangeState(pressed ? BUTTON_PRESSED_STICKY : BUTTON_NORMAL, true);
    133   }
    134 }
    135 
    136 const pp::ImageData& Button::GetCurrentImage() {
    137   switch (state_) {
    138     case BUTTON_NORMAL: return normal_;
    139     case BUTTON_HIGHLIGHTED: return highlighted_;
    140     case BUTTON_PRESSED:
    141     case BUTTON_PRESSED_STICKY: return pressed_;
    142   }
    143   NOTREACHED();
    144   return normal_;
    145 }
    146 
    147 void Button::ChangeState(ButtonState new_state, bool force) {
    148   if (style_ == BUTTON_STATE && !force) {
    149     // If button is a state button and pressed state is sticky,
    150     // user have to click on this button again to unpress it.
    151     if ((state_ == BUTTON_PRESSED_STICKY && new_state != BUTTON_PRESSED_STICKY)
    152         ||
    153         (state_ != BUTTON_PRESSED_STICKY && new_state == BUTTON_PRESSED_STICKY))
    154       return;
    155   }
    156 
    157   if (state_ != new_state) {
    158     state_ = new_state;
    159     owner()->Invalidate(id(), rect());
    160   }
    161 }
    162 
    163 void Button::OnButtonClicked() {
    164   switch (style_) {
    165     case BUTTON_CLICKABLE:
    166       ChangeState(BUTTON_HIGHLIGHTED, true);
    167       owner()->OnEvent(id(), EVENT_ID_BUTTON_CLICKED, NULL);
    168       break;
    169     case BUTTON_STATE:
    170       SetPressedState(!IsPressed());
    171       owner()->OnEvent(id(), EVENT_ID_BUTTON_STATE_CHANGED, NULL);
    172       break;
    173     default:
    174       NOTREACHED();
    175   }
    176 }
    177 
    178 }  // namespace chrome_pdf
    179 
    180