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