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 
Button()13 Button::Button()
14     : style_(BUTTON_CLICKABLE), state_(BUTTON_NORMAL), is_pressed_(false) {
15 }
16 
~Button()17 Button::~Button() {
18 }
19 
CreateButton(uint32 id,const pp::Point & origin,bool visible,Control::Owner * owner,ButtonStyle style,const pp::ImageData & face_normal,const pp::ImageData & face_highlighted,const pp::ImageData & face_pressed)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 
Paint(pp::ImageData * image_data,const pp::Rect & rc)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 
HandleEvent(const pp::InputEvent & event)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 
OnEventCaptureReleased()111 void Button::OnEventCaptureReleased() {
112   ChangeState(BUTTON_NORMAL, false);
113 }
114 
Show(bool visible,bool invalidate)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 
AdjustTransparency(uint8 transparency,bool invalidate)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 
SetPressedState(bool pressed)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 
GetCurrentImage()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 
ChangeState(ButtonState new_state,bool force)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 
OnButtonClicked()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