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