// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "pdf/button.h" #include "base/logging.h" #include "pdf/draw_utils.h" #include "ppapi/cpp/input_event.h" namespace chrome_pdf { Button::Button() : style_(BUTTON_CLICKABLE), state_(BUTTON_NORMAL), is_pressed_(false) { } Button::~Button() { } bool Button::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) { DCHECK(face_normal.size().GetArea()); DCHECK(face_normal.size() == face_highlighted.size()); DCHECK(face_normal.size() == face_pressed.size()); pp::Rect rc(origin, face_normal.size()); if (!Control::Create(id, rc, visible, owner)) return false; style_ = style; normal_ = face_normal; highlighted_ = face_highlighted; pressed_ = face_pressed; return true; } void Button::Paint(pp::ImageData* image_data, const pp::Rect& rc) { if (!visible()) return; pp::Rect draw_rc = rc.Intersect(rect()); if (draw_rc.IsEmpty()) return; pp::Point origin = draw_rc.point(); draw_rc.Offset(-rect().x(), -rect().y()); AlphaBlend(GetCurrentImage(), draw_rc, image_data, origin, transparency()); } bool Button::HandleEvent(const pp::InputEvent& event) { if (!visible()) return false; // Button handles mouse events only. pp::MouseInputEvent mouse_event(event); if (mouse_event.is_null()) return false; pp::Point pt = mouse_event.GetPosition(); if (!rect().Contains(pt) || event.GetType() == PP_INPUTEVENT_TYPE_MOUSELEAVE) { ChangeState(BUTTON_NORMAL, false); owner()->SetEventCapture(id(), false); return false; } owner()->SetCursor(id(), PP_CURSORTYPE_POINTER); owner()->SetEventCapture(id(), true); bool handled = true; switch (event.GetType()) { case PP_INPUTEVENT_TYPE_MOUSEMOVE: if (state_ == BUTTON_NORMAL) ChangeState(BUTTON_HIGHLIGHTED, false); break; case PP_INPUTEVENT_TYPE_MOUSEDOWN: if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT) { ChangeState(BUTTON_PRESSED, false); is_pressed_ = true; } break; case PP_INPUTEVENT_TYPE_MOUSEUP: if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT && is_pressed_) { OnButtonClicked(); is_pressed_ = false; } else { // Since button has not been pressed, return false to allow other // controls (scrollbar) to process mouse button up. return false; } break; default: handled = false; break; } return handled; } void Button::OnEventCaptureReleased() { ChangeState(BUTTON_NORMAL, false); } void Button::Show(bool visible, bool invalidate) { // If button become invisible, remove pressed flag. if (!visible) is_pressed_ = false; Control::Show(visible, invalidate); } void Button::AdjustTransparency(uint8 transparency, bool invalidate) { // If button become invisible, remove pressed flag. if (transparency == kTransparentAlpha) is_pressed_ = false; Control::AdjustTransparency(transparency, invalidate); } void Button::SetPressedState(bool pressed) { if (style_ == BUTTON_STATE) { if (IsPressed() != pressed) ChangeState(pressed ? BUTTON_PRESSED_STICKY : BUTTON_NORMAL, true); } } const pp::ImageData& Button::GetCurrentImage() { switch (state_) { case BUTTON_NORMAL: return normal_; case BUTTON_HIGHLIGHTED: return highlighted_; case BUTTON_PRESSED: case BUTTON_PRESSED_STICKY: return pressed_; } NOTREACHED(); return normal_; } void Button::ChangeState(ButtonState new_state, bool force) { if (style_ == BUTTON_STATE && !force) { // If button is a state button and pressed state is sticky, // user have to click on this button again to unpress it. if ((state_ == BUTTON_PRESSED_STICKY && new_state != BUTTON_PRESSED_STICKY) || (state_ != BUTTON_PRESSED_STICKY && new_state == BUTTON_PRESSED_STICKY)) return; } if (state_ != new_state) { state_ = new_state; owner()->Invalidate(id(), rect()); } } void Button::OnButtonClicked() { switch (style_) { case BUTTON_CLICKABLE: ChangeState(BUTTON_HIGHLIGHTED, true); owner()->OnEvent(id(), EVENT_ID_BUTTON_CLICKED, NULL); break; case BUTTON_STATE: SetPressedState(!IsPressed()); owner()->OnEvent(id(), EVENT_ID_BUTTON_STATE_CHANGED, NULL); break; default: NOTREACHED(); } } } // namespace chrome_pdf