This source file includes following definitions.
- destroyed_flag_
- Activate
- PaintButton
- GetPreferredSize
- GetClassName
- OnMousePressed
- OnMouseReleased
- OnMouseExited
- OnGestureEvent
- OnKeyPressed
- OnKeyReleased
- GetAccessibleState
- PaintMenuMarker
- GetMaximumScreenXCoordinate
#include "ui/views/controls/button/menu_button.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_resources.h"
#include "grit/ui_strings.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/screen.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/menu_button_listener.h"
#include "ui/views/mouse_constants.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
using base::TimeTicks;
using base::TimeDelta;
namespace views {
static const int kDefaultMenuOffsetX = -2;
static const int kDefaultMenuOffsetY = -4;
const char MenuButton::kViewClassName[] = "MenuButton";
const int MenuButton::kMenuMarkerPaddingLeft = 3;
const int MenuButton::kMenuMarkerPaddingRight = -1;
MenuButton::MenuButton(ButtonListener* listener,
const base::string16& text,
MenuButtonListener* menu_button_listener,
bool show_menu_marker)
: TextButton(listener, text),
menu_visible_(false),
menu_offset_(kDefaultMenuOffsetX, kDefaultMenuOffsetY),
listener_(menu_button_listener),
show_menu_marker_(show_menu_marker),
menu_marker_(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
IDR_MENU_DROPARROW).ToImageSkia()),
destroyed_flag_(NULL) {
set_alignment(TextButton::ALIGN_LEFT);
}
MenuButton::~MenuButton() {
if (destroyed_flag_)
*destroyed_flag_ = true;
}
bool MenuButton::Activate() {
SetState(STATE_PRESSED);
if (listener_) {
gfx::Rect lb = GetLocalBounds();
gfx::Point menu_position(lb.right(), lb.bottom());
if (base::i18n::IsRTL())
menu_position.set_x(lb.x());
View::ConvertPointToScreen(this, &menu_position);
if (base::i18n::IsRTL())
menu_position.Offset(-menu_offset_.x(), menu_offset_.y());
else
menu_position.Offset(menu_offset_.x(), menu_offset_.y());
int max_x_coordinate = GetMaximumScreenXCoordinate();
if (max_x_coordinate && max_x_coordinate <= menu_position.x())
menu_position.set_x(max_x_coordinate - 1);
static_cast<internal::RootView*>(GetWidget()->GetRootView())->
SetMouseHandler(NULL);
menu_visible_ = true;
bool destroyed = false;
destroyed_flag_ = &destroyed;
listener_->OnMenuButtonClicked(this, menu_position);
if (destroyed) {
return false;
}
destroyed_flag_ = NULL;
menu_visible_ = false;
menu_closed_time_ = TimeTicks::Now();
SetState(STATE_NORMAL);
return false;
}
return true;
}
void MenuButton::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
TextButton::PaintButton(canvas, mode);
if (show_menu_marker_)
PaintMenuMarker(canvas);
}
gfx::Size MenuButton::GetPreferredSize() {
gfx::Size prefsize = TextButton::GetPreferredSize();
if (show_menu_marker_) {
prefsize.Enlarge(menu_marker_->width() + kMenuMarkerPaddingLeft +
kMenuMarkerPaddingRight,
0);
}
return prefsize;
}
const char* MenuButton::GetClassName() const {
return kViewClassName;
}
bool MenuButton::OnMousePressed(const ui::MouseEvent& event) {
RequestFocus();
if (state() != STATE_DISABLED) {
if (event.IsOnlyLeftMouseButton() &&
HitTestPoint(event.location()) &&
GetDragOperations(event.location()) == ui::DragDropTypes::DRAG_NONE) {
TimeDelta delta = TimeTicks::Now() - menu_closed_time_;
if (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks)
return Activate();
}
}
return true;
}
void MenuButton::OnMouseReleased(const ui::MouseEvent& event) {
if (GetDragOperations(event.location()) != ui::DragDropTypes::DRAG_NONE &&
state() != STATE_DISABLED && !InDrag() && event.IsOnlyLeftMouseButton() &&
HitTestPoint(event.location())) {
Activate();
} else {
TextButton::OnMouseReleased(event);
}
}
void MenuButton::OnMouseExited(const ui::MouseEvent& event) {
if ((state_ != STATE_DISABLED) && (!menu_visible_) && (!InDrag())) {
SetState(STATE_NORMAL);
}
}
void MenuButton::OnGestureEvent(ui::GestureEvent* event) {
if (state() != STATE_DISABLED && event->type() == ui::ET_GESTURE_TAP) {
if (Activate())
event->StopPropagation();
return;
}
TextButton::OnGestureEvent(event);
}
bool MenuButton::OnKeyPressed(const ui::KeyEvent& event) {
switch (event.key_code()) {
case ui::VKEY_SPACE:
if (event.IsAltDown())
break;
case ui::VKEY_RETURN:
case ui::VKEY_UP:
case ui::VKEY_DOWN: {
Activate();
return true;
}
default:
break;
}
return false;
}
bool MenuButton::OnKeyReleased(const ui::KeyEvent& event) {
return false;
}
void MenuButton::GetAccessibleState(ui::AXViewState* state) {
CustomButton::GetAccessibleState(state);
state->role = ui::AX_ROLE_POP_UP_BUTTON;
state->default_action = l10n_util::GetStringUTF16(IDS_APP_ACCACTION_PRESS);
state->AddStateFlag(ui::AX_STATE_HASPOPUP);
}
void MenuButton::PaintMenuMarker(gfx::Canvas* canvas) {
gfx::Insets insets = GetInsets();
gfx::Rect arrow_bounds(width() - insets.right() -
menu_marker_->width() - kMenuMarkerPaddingRight,
height() / 2 - menu_marker_->height() / 2,
menu_marker_->width(),
menu_marker_->height());
arrow_bounds.set_x(GetMirroredXForRect(arrow_bounds));
canvas->DrawImageInt(*menu_marker_, arrow_bounds.x(), arrow_bounds.y());
}
int MenuButton::GetMaximumScreenXCoordinate() {
if (!GetWidget()) {
NOTREACHED();
return 0;
}
gfx::Rect monitor_bounds = GetWidget()->GetWorkAreaBoundsInScreen();
return monitor_bounds.right() - 1;
}
}