1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#import "ui/views/controls/menu/menu_runner_impl_cocoa.h"
6
7#import "ui/base/cocoa/menu_controller.h"
8#include "ui/events/event_utils.h"
9#include "ui/gfx/geometry/rect.h"
10#include "ui/views/controls/menu/menu_runner_impl_adapter.h"
11
12namespace views {
13namespace internal {
14
15// static
16MenuRunnerImplInterface* MenuRunnerImplInterface::Create(
17    ui::MenuModel* menu_model,
18    int32 run_types) {
19  if ((run_types & MenuRunner::CONTEXT_MENU) != 0 &&
20      (run_types & MenuRunner::IS_NESTED) == 0) {
21    return new MenuRunnerImplCocoa(menu_model);
22  }
23
24  return new MenuRunnerImplAdapter(menu_model);
25}
26
27MenuRunnerImplCocoa::MenuRunnerImplCocoa(ui::MenuModel* menu)
28    : delete_after_run_(false), closing_event_time_(base::TimeDelta()) {
29  menu_controller_.reset(
30      [[MenuController alloc] initWithModel:menu useWithPopUpButtonCell:NO]);
31}
32
33bool MenuRunnerImplCocoa::IsRunning() const {
34  return [menu_controller_ isMenuOpen];
35}
36
37void MenuRunnerImplCocoa::Release() {
38  if (IsRunning()) {
39    if (delete_after_run_)
40      return;  // We already canceled.
41
42    delete_after_run_ = true;
43    [menu_controller_ cancel];
44  } else {
45    delete this;
46  }
47}
48
49MenuRunner::RunResult MenuRunnerImplCocoa::RunMenuAt(Widget* parent,
50                                                     MenuButton* button,
51                                                     const gfx::Rect& bounds,
52                                                     MenuAnchorPosition anchor,
53                                                     int32 run_types) {
54  DCHECK(run_types & MenuRunner::CONTEXT_MENU);
55  DCHECK(!IsRunning());
56  closing_event_time_ = base::TimeDelta();
57  [NSMenu popUpContextMenu:[menu_controller_ menu]
58                 withEvent:[NSApp currentEvent]
59                   forView:nil];
60  closing_event_time_ = ui::EventTimeForNow();
61
62  if (delete_after_run_) {
63    delete this;
64    return MenuRunner::MENU_DELETED;
65  }
66
67  return MenuRunner::NORMAL_EXIT;
68}
69
70void MenuRunnerImplCocoa::Cancel() {
71  [menu_controller_ cancel];
72}
73
74base::TimeDelta MenuRunnerImplCocoa::GetClosingEventTime() const {
75  return closing_event_time_;
76}
77
78MenuRunnerImplCocoa::~MenuRunnerImplCocoa() {
79}
80
81}  // namespace internal
82}  // namespace views
83