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