Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa_test / pdf / button.cc
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