This source file includes following definitions.
- menu
- running
- weak_factory_
- Release
- RunMenuAt
- Cancel
- closing_event_time
- DropMenuClosed
- SiblingMenuCreated
- MenuDone
- ShouldShowMnemonics
- holder_
- GetMenu
- RunMenuAt
- IsRunning
- Cancel
- closing_event_time
- SetRunnerHandler
#include "ui/views/controls/menu/menu_runner.h"
#include <set>
#include "base/memory/weak_ptr.h"
#include "ui/base/models/menu_model.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_controller_delegate.h"
#include "ui/views/controls/menu/menu_delegate.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner_handler.h"
#include "ui/views/widget/widget.h"
#if defined(OS_WIN)
#include "base/win/win_util.h"
#endif
namespace views {
namespace internal {
class MenuRunnerImpl : public internal::MenuControllerDelegate {
public:
explicit MenuRunnerImpl(MenuItemView* menu);
MenuItemView* menu() { return menu_; }
bool running() const { return running_; }
void Release();
MenuRunner::RunResult RunMenuAt(Widget* parent,
MenuButton* button,
const gfx::Rect& bounds,
MenuItemView::AnchorPosition anchor,
int32 types) WARN_UNUSED_RESULT;
void Cancel();
base::TimeDelta closing_event_time() const;
virtual void DropMenuClosed(NotifyType type, MenuItemView* menu) OVERRIDE;
virtual void SiblingMenuCreated(MenuItemView* menu) OVERRIDE;
private:
virtual ~MenuRunnerImpl();
MenuRunner::RunResult MenuDone(MenuItemView* result, int mouse_event_flags);
bool ShouldShowMnemonics(MenuButton* button);
MenuItemView* menu_;
std::set<MenuItemView*> sibling_menus_;
scoped_ptr<MenuDelegate> empty_delegate_;
bool running_;
bool delete_after_run_;
bool for_drop_;
MenuController* controller_;
bool owns_controller_;
base::TimeDelta closing_event_time_;
base::WeakPtrFactory<MenuRunnerImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MenuRunnerImpl);
};
MenuRunnerImpl::MenuRunnerImpl(MenuItemView* menu)
: menu_(menu),
running_(false),
delete_after_run_(false),
for_drop_(false),
controller_(NULL),
owns_controller_(false),
closing_event_time_(base::TimeDelta()),
weak_factory_(this) {
}
void MenuRunnerImpl::Release() {
if (running_) {
if (delete_after_run_)
return;
delete_after_run_ = true;
if (!empty_delegate_.get())
empty_delegate_.reset(new MenuDelegate());
menu_->set_delegate(empty_delegate_.get());
DCHECK(controller_);
controller_->Cancel(MenuController::EXIT_DESTROYED);
} else {
delete this;
}
}
MenuRunner::RunResult MenuRunnerImpl::RunMenuAt(
Widget* parent,
MenuButton* button,
const gfx::Rect& bounds,
MenuItemView::AnchorPosition anchor,
int32 types) {
closing_event_time_ = base::TimeDelta();
if (running_) {
return MenuRunner::NORMAL_EXIT;
}
MenuController* controller = MenuController::GetActiveInstance();
if (controller) {
if ((types & MenuRunner::IS_NESTED) != 0) {
if (!controller->IsBlockingRun()) {
controller->CancelAll();
controller = NULL;
}
} else {
controller->CancelAll();
if ((types & MenuRunner::FOR_DROP) == 0) {
return MenuRunner::NORMAL_EXIT;
}
controller = NULL;
}
}
running_ = true;
for_drop_ = (types & MenuRunner::FOR_DROP) != 0;
bool has_mnemonics = (types & MenuRunner::HAS_MNEMONICS) != 0 && !for_drop_;
owns_controller_ = false;
if (!controller) {
ui::NativeTheme* theme = parent ? parent->GetNativeTheme() :
ui::NativeTheme::instance();
controller = new MenuController(theme, !for_drop_, this);
owns_controller_ = true;
}
controller->set_is_combobox((types & MenuRunner::COMBOBOX) != 0);
controller_ = controller;
menu_->set_controller(controller_);
menu_->PrepareForRun(owns_controller_,
has_mnemonics,
!for_drop_ && ShouldShowMnemonics(button));
int mouse_event_flags = 0;
MenuItemView* result = controller->Run(parent, button, menu_, bounds, anchor,
(types & MenuRunner::CONTEXT_MENU) != 0,
&mouse_event_flags);
closing_event_time_ = controller->closing_event_time();
if (for_drop_) {
return MenuRunner::NORMAL_EXIT;
}
return MenuDone(result, mouse_event_flags);
}
void MenuRunnerImpl::Cancel() {
if (running_)
controller_->Cancel(MenuController::EXIT_ALL);
}
base::TimeDelta MenuRunnerImpl::closing_event_time() const {
return closing_event_time_;
}
void MenuRunnerImpl::DropMenuClosed(NotifyType type, MenuItemView* menu) {
MenuDone(NULL, 0);
if (type == NOTIFY_DELEGATE && menu->GetDelegate()) {
menu->GetDelegate()->DropMenuClosed(menu);
}
}
void MenuRunnerImpl::SiblingMenuCreated(MenuItemView* menu) {
if (menu != menu_ && sibling_menus_.count(menu) == 0)
sibling_menus_.insert(menu);
}
MenuRunnerImpl::~MenuRunnerImpl() {
delete menu_;
for (std::set<MenuItemView*>::iterator i = sibling_menus_.begin();
i != sibling_menus_.end(); ++i)
delete *i;
}
MenuRunner::RunResult MenuRunnerImpl::MenuDone(MenuItemView* result,
int mouse_event_flags) {
menu_->RemoveEmptyMenus();
menu_->set_controller(NULL);
if (owns_controller_) {
delete controller_;
owns_controller_ = false;
}
controller_ = NULL;
menu_->DestroyAllMenuHosts();
if (delete_after_run_) {
delete this;
return MenuRunner::MENU_DELETED;
}
running_ = false;
if (result && menu_->GetDelegate()) {
base::WeakPtr<MenuRunnerImpl> ref(weak_factory_.GetWeakPtr());
menu_->GetDelegate()->ExecuteCommand(result->GetCommand(),
mouse_event_flags);
if (!ref)
return MenuRunner::MENU_DELETED;
}
return MenuRunner::NORMAL_EXIT;
}
bool MenuRunnerImpl::ShouldShowMnemonics(MenuButton* button) {
bool show_mnemonics = button ? button->HasFocus() : false;
#if defined(OS_WIN)
if (!show_mnemonics)
show_mnemonics = base::win::IsAltPressed();
#endif
return show_mnemonics;
}
}
MenuRunner::MenuRunner(ui::MenuModel* menu_model)
: menu_model_adapter_(new MenuModelAdapter(menu_model)),
holder_(new internal::MenuRunnerImpl(menu_model_adapter_->CreateMenu())) {
}
MenuRunner::MenuRunner(MenuItemView* menu)
: holder_(new internal::MenuRunnerImpl(menu)) {
}
MenuRunner::~MenuRunner() {
holder_->Release();
}
MenuItemView* MenuRunner::GetMenu() {
return holder_->menu();
}
MenuRunner::RunResult MenuRunner::RunMenuAt(Widget* parent,
MenuButton* button,
const gfx::Rect& bounds,
MenuItemView::AnchorPosition anchor,
ui::MenuSourceType source_type,
int32 types) {
if (runner_handler_.get()) {
return runner_handler_->RunMenuAt(parent, button, bounds, anchor,
source_type, types);
}
if ((types & (IS_NESTED | FOR_DROP)) == 0 && parent) {
display_change_listener_.reset(
internal::DisplayChangeListener::Create(parent, this));
}
if (types & CONTEXT_MENU) {
switch (source_type) {
case ui::MENU_SOURCE_NONE:
case ui::MENU_SOURCE_KEYBOARD:
case ui::MENU_SOURCE_MOUSE:
anchor = MenuItemView::TOPLEFT;
break;
case ui::MENU_SOURCE_TOUCH:
case ui::MENU_SOURCE_TOUCH_EDIT_MENU:
anchor = MenuItemView::BOTTOMCENTER;
break;
default:
break;
}
}
return holder_->RunMenuAt(parent, button, bounds, anchor, types);
}
bool MenuRunner::IsRunning() const {
return holder_->running();
}
void MenuRunner::Cancel() {
holder_->Cancel();
}
base::TimeDelta MenuRunner::closing_event_time() const {
return holder_->closing_event_time();
}
void MenuRunner::SetRunnerHandler(
scoped_ptr<MenuRunnerHandler> runner_handler) {
runner_handler_ = runner_handler.Pass();
}
}