views: Implement the window menu bar.
This commit is contained in:
		
					parent
					
						
							
								2ee7caccfe
							
						
					
				
			
			
				commit
				
					
						0f18d63f7f
					
				
			
		
					 6 changed files with 310 additions and 6 deletions
				
			
		
							
								
								
									
										2
									
								
								atom.gyp
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								atom.gyp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -143,6 +143,8 @@
 | 
			
		|||
      'atom/browser/ui/views/linux_frame_view.h',
 | 
			
		||||
      'atom/browser/ui/views/menu_bar.cc',
 | 
			
		||||
      'atom/browser/ui/views/menu_bar.h',
 | 
			
		||||
      'atom/browser/ui/views/menu_delegate.cc',
 | 
			
		||||
      'atom/browser/ui/views/menu_delegate.h',
 | 
			
		||||
      'atom/browser/ui/views/menu_layout.cc',
 | 
			
		||||
      'atom/browser/ui/views/menu_layout.h',
 | 
			
		||||
      'atom/browser/ui/views/win_frame_view.cc',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -304,6 +304,9 @@ void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) {
 | 
			
		|||
    AddChildViewAt(menu_bar_, 0);
 | 
			
		||||
    SetContentSize(content_size);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  menu_bar_->SetMenu(menu_model);
 | 
			
		||||
  Layout();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gfx::NativeWindow NativeWindowViews::GetNativeWindow() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,11 @@
 | 
			
		|||
 | 
			
		||||
#include "atom/browser/ui/views/menu_bar.h"
 | 
			
		||||
 | 
			
		||||
#include "ui/gfx/canvas.h"
 | 
			
		||||
#include "atom/browser/ui/views/menu_delegate.h"
 | 
			
		||||
#include "ui/base/models/menu_model.h"
 | 
			
		||||
#include "ui/views/background.h"
 | 
			
		||||
#include "ui/views/controls/button/menu_button.h"
 | 
			
		||||
#include "ui/views/layout/box_layout.h"
 | 
			
		||||
 | 
			
		||||
namespace atom {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,18 +21,75 @@ const SkColor kDefaultColor = SkColorSetARGB(255, 233, 233, 233);
 | 
			
		|||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
MenuBar::MenuBar() {
 | 
			
		||||
MenuBar::MenuBar()
 | 
			
		||||
    : menu_model_(NULL) {
 | 
			
		||||
  set_background(views::Background::CreateSolidBackground(kDefaultColor));
 | 
			
		||||
  SetLayoutManager(new views::BoxLayout(
 | 
			
		||||
      views::BoxLayout::kHorizontal, 0, 0, 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MenuBar::~MenuBar() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuBar::Paint(gfx::Canvas* canvas) {
 | 
			
		||||
  canvas->FillRect(bounds(), kDefaultColor);
 | 
			
		||||
void MenuBar::SetMenu(ui::MenuModel* model) {
 | 
			
		||||
  menu_model_ = model;
 | 
			
		||||
  RemoveAllChildViews(true);
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < model->GetItemCount(); ++i) {
 | 
			
		||||
    views::MenuButton* button =
 | 
			
		||||
        new views::MenuButton(this, model->GetLabelAt(i), this, false);
 | 
			
		||||
    button->set_tag(i);
 | 
			
		||||
    AddChildView(button);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int MenuBar::GetItemCount() const {
 | 
			
		||||
  return menu_model_->GetItemCount();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MenuBar::GetMenuButtonFromScreenPoint(const gfx::Point& point,
 | 
			
		||||
                                           ui::MenuModel** menu_model,
 | 
			
		||||
                                           views::MenuButton** button) {
 | 
			
		||||
  gfx::Point location(point);
 | 
			
		||||
  views::View::ConvertPointFromScreen(this, &location);
 | 
			
		||||
 | 
			
		||||
  if (location.x() < 0 || location.x() >= width() || location.y() < 0 ||
 | 
			
		||||
      location.y() >= height())
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < child_count(); ++i) {
 | 
			
		||||
    views::View* view = child_at(i);
 | 
			
		||||
    if (view->bounds().Contains(location) &&
 | 
			
		||||
        (menu_model_->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU)) {
 | 
			
		||||
      *menu_model = menu_model_->GetSubmenuModelAt(i);
 | 
			
		||||
      *button = static_cast<views::MenuButton*>(view);
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* MenuBar::GetClassName() const {
 | 
			
		||||
  return kViewClassName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuBar::ButtonPressed(views::Button* sender, const ui::Event& event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuBar::OnMenuButtonClicked(views::View* source,
 | 
			
		||||
                                  const gfx::Point& point) {
 | 
			
		||||
  if (!menu_model_)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  views::MenuButton* button = static_cast<views::MenuButton*>(source);
 | 
			
		||||
  int id = button->tag();
 | 
			
		||||
  ui::MenuModel::ItemType type = menu_model_->GetTypeAt(id);
 | 
			
		||||
  if (type != ui::MenuModel::TYPE_SUBMENU)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  menu_delegate_.reset(new MenuDelegate(this));
 | 
			
		||||
  menu_delegate_->RunMenu(menu_model_->GetSubmenuModelAt(id), button);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace atom
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,21 +5,56 @@
 | 
			
		|||
#ifndef ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_
 | 
			
		||||
#define ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_
 | 
			
		||||
 | 
			
		||||
#include "ui/views/controls/button/button.h"
 | 
			
		||||
#include "ui/views/controls/button/menu_button_listener.h"
 | 
			
		||||
#include "ui/views/view.h"
 | 
			
		||||
 | 
			
		||||
namespace ui {
 | 
			
		||||
class MenuModel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace views {
 | 
			
		||||
class MenuButton;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace atom {
 | 
			
		||||
 | 
			
		||||
class MenuBar : public views::View {
 | 
			
		||||
class MenuDelegate;
 | 
			
		||||
 | 
			
		||||
class MenuBar : public views::View,
 | 
			
		||||
                public views::ButtonListener,
 | 
			
		||||
                public views::MenuButtonListener {
 | 
			
		||||
 public:
 | 
			
		||||
  MenuBar();
 | 
			
		||||
  virtual ~MenuBar();
 | 
			
		||||
 | 
			
		||||
  // Replaces current menu with a new one.
 | 
			
		||||
  void SetMenu(ui::MenuModel* menu_model);
 | 
			
		||||
 | 
			
		||||
  // Returns there are how many items in the root menu.
 | 
			
		||||
  int GetItemCount() const;
 | 
			
		||||
 | 
			
		||||
  // Get the menu under specified screen point.
 | 
			
		||||
  bool GetMenuButtonFromScreenPoint(const gfx::Point& point,
 | 
			
		||||
                                    ui::MenuModel** menu_model,
 | 
			
		||||
                                    views::MenuButton** button);
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  // views::View:
 | 
			
		||||
  virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
 | 
			
		||||
  virtual const char* GetClassName() const OVERRIDE;
 | 
			
		||||
 | 
			
		||||
  // views::ButtonListener:
 | 
			
		||||
  virtual void ButtonPressed(views::Button* sender,
 | 
			
		||||
                             const ui::Event& event) OVERRIDE;
 | 
			
		||||
 | 
			
		||||
  // views::MenuButtonListener:
 | 
			
		||||
  virtual void OnMenuButtonClicked(views::View* source,
 | 
			
		||||
                                   const gfx::Point& point) OVERRIDE;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  ui::MenuModel* menu_model_;
 | 
			
		||||
  scoped_ptr<MenuDelegate> menu_delegate_;
 | 
			
		||||
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(MenuBar);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										127
									
								
								atom/browser/ui/views/menu_delegate.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								atom/browser/ui/views/menu_delegate.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,127 @@
 | 
			
		|||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by the MIT license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "atom/browser/ui/views/menu_delegate.h"
 | 
			
		||||
 | 
			
		||||
#include "atom/browser/ui/views/menu_bar.h"
 | 
			
		||||
#include "base/stl_util.h"
 | 
			
		||||
#include "ui/views/controls/button/menu_button.h"
 | 
			
		||||
#include "ui/views/controls/menu/menu_model_adapter.h"
 | 
			
		||||
#include "ui/views/controls/menu/menu_runner.h"
 | 
			
		||||
#include "ui/views/widget/widget.h"
 | 
			
		||||
 | 
			
		||||
namespace atom {
 | 
			
		||||
 | 
			
		||||
MenuDelegate::MenuDelegate(MenuBar* menu_bar)
 | 
			
		||||
    : menu_bar_(menu_bar),
 | 
			
		||||
      id_(-1),
 | 
			
		||||
      items_(menu_bar_->GetItemCount()),
 | 
			
		||||
      delegates_(menu_bar_->GetItemCount()) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MenuDelegate::~MenuDelegate() {
 | 
			
		||||
  STLDeleteElements(&delegates_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuDelegate::RunMenu(ui::MenuModel* model, views::MenuButton* button) {
 | 
			
		||||
  gfx::Point screen_loc;
 | 
			
		||||
  views::View::ConvertPointToScreen(button, &screen_loc);
 | 
			
		||||
  // Subtract 1 from the height to make the popup flush with the button border.
 | 
			
		||||
  gfx::Rect bounds(screen_loc.x(), screen_loc.y(), button->width(),
 | 
			
		||||
                   button->height() - 1);
 | 
			
		||||
 | 
			
		||||
  id_ = button->tag();
 | 
			
		||||
  views::MenuItemView* item = BuildMenu(model);
 | 
			
		||||
 | 
			
		||||
  menu_runner_.reset(new views::MenuRunner(item));
 | 
			
		||||
  views::MenuRunner::RunResult result = menu_runner_->RunMenuAt(
 | 
			
		||||
      button->GetWidget()->GetTopLevelWidget(),
 | 
			
		||||
      button,
 | 
			
		||||
      bounds,
 | 
			
		||||
      views::MenuItemView::TOPRIGHT,
 | 
			
		||||
      ui::MENU_SOURCE_MOUSE,
 | 
			
		||||
      views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
 | 
			
		||||
  if (result == views::MenuRunner::MENU_DELETED)
 | 
			
		||||
    LOG(ERROR) << "Menu deleted when running";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
views::MenuItemView* MenuDelegate::BuildMenu(ui::MenuModel* model) {
 | 
			
		||||
  DCHECK_GE(id_, 0);
 | 
			
		||||
  DCHECK_LT(id_, items_.size());
 | 
			
		||||
 | 
			
		||||
  if (!items_[id_]) {
 | 
			
		||||
    views::MenuModelAdapter* delegate = new views::MenuModelAdapter(model);
 | 
			
		||||
    delegates_[id_] = delegate;
 | 
			
		||||
 | 
			
		||||
    views::MenuItemView* item = new views::MenuItemView(this);
 | 
			
		||||
    delegate->BuildMenu(item);
 | 
			
		||||
    items_[id_] = item;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return items_[id_];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuDelegate::ExecuteCommand(int id) {
 | 
			
		||||
  delegate()->ExecuteCommand(id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuDelegate::ExecuteCommand(int id, int mouse_event_flags) {
 | 
			
		||||
  delegate()->ExecuteCommand(id, mouse_event_flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MenuDelegate::IsTriggerableEvent(views::MenuItemView* source,
 | 
			
		||||
                                      const ui::Event& e) {
 | 
			
		||||
  return delegate()->IsTriggerableEvent(source, e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MenuDelegate::GetAccelerator(int id, ui::Accelerator* accelerator) {
 | 
			
		||||
  return delegate()->GetAccelerator(id, accelerator);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
base::string16 MenuDelegate::GetLabel(int id) const {
 | 
			
		||||
  return delegate()->GetLabel(id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const gfx::FontList* MenuDelegate::GetLabelFontList(int id) const {
 | 
			
		||||
  return delegate()->GetLabelFontList(id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MenuDelegate::IsCommandEnabled(int id) const {
 | 
			
		||||
  return delegate()->IsCommandEnabled(id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MenuDelegate::IsItemChecked(int id) const {
 | 
			
		||||
  return delegate()->IsItemChecked(id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuDelegate::SelectionChanged(views::MenuItemView* menu) {
 | 
			
		||||
  delegate()->SelectionChanged(menu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuDelegate::WillShowMenu(views::MenuItemView* menu) {
 | 
			
		||||
  delegate()->WillShowMenu(menu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MenuDelegate::WillHideMenu(views::MenuItemView* menu) {
 | 
			
		||||
  delegate()->WillHideMenu(menu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
views::MenuItemView* MenuDelegate::GetSiblingMenu(
 | 
			
		||||
    views::MenuItemView* menu,
 | 
			
		||||
    const gfx::Point& screen_point,
 | 
			
		||||
    views::MenuItemView::AnchorPosition* anchor,
 | 
			
		||||
    bool* has_mnemonics,
 | 
			
		||||
    views::MenuButton** button) {
 | 
			
		||||
  ui::MenuModel* model;
 | 
			
		||||
  if (!menu_bar_->GetMenuButtonFromScreenPoint(screen_point, &model, button))
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  *anchor = views::MenuItemView::TOPLEFT;
 | 
			
		||||
  *has_mnemonics = true;
 | 
			
		||||
 | 
			
		||||
  id_ = (*button)->tag();
 | 
			
		||||
  return BuildMenu(model);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace atom
 | 
			
		||||
							
								
								
									
										76
									
								
								atom/browser/ui/views/menu_delegate.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								atom/browser/ui/views/menu_delegate.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by the MIT license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#ifndef ATOM_BROWSER_UI_VIEWS_MENU_DELEGATE_H_
 | 
			
		||||
#define ATOM_BROWSER_UI_VIEWS_MENU_DELEGATE_H_
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "ui/views/controls/menu/menu_delegate.h"
 | 
			
		||||
 | 
			
		||||
namespace views {
 | 
			
		||||
class MenuModelAdapter;
 | 
			
		||||
class MenuRunner;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace ui {
 | 
			
		||||
class MenuModel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace atom {
 | 
			
		||||
 | 
			
		||||
class MenuBar;
 | 
			
		||||
 | 
			
		||||
class MenuDelegate : public views::MenuDelegate {
 | 
			
		||||
 public:
 | 
			
		||||
  MenuDelegate(MenuBar* menu_bar);
 | 
			
		||||
  virtual ~MenuDelegate();
 | 
			
		||||
 | 
			
		||||
  void RunMenu(ui::MenuModel* model, views::MenuButton* button);
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  // views::MenuDelegate:
 | 
			
		||||
  virtual void ExecuteCommand(int id) OVERRIDE;
 | 
			
		||||
  virtual void ExecuteCommand(int id, int mouse_event_flags) OVERRIDE;
 | 
			
		||||
  virtual bool IsTriggerableEvent(views::MenuItemView* source,
 | 
			
		||||
                                  const ui::Event& e) OVERRIDE;
 | 
			
		||||
  virtual bool GetAccelerator(int id,
 | 
			
		||||
                              ui::Accelerator* accelerator) OVERRIDE;
 | 
			
		||||
  virtual base::string16 GetLabel(int id) const OVERRIDE;
 | 
			
		||||
  virtual const gfx::FontList* GetLabelFontList(int id) const OVERRIDE;
 | 
			
		||||
  virtual bool IsCommandEnabled(int id) const OVERRIDE;
 | 
			
		||||
  virtual bool IsItemChecked(int id) const OVERRIDE;
 | 
			
		||||
  virtual void SelectionChanged(views::MenuItemView* menu) OVERRIDE;
 | 
			
		||||
  virtual void WillShowMenu(views::MenuItemView* menu) OVERRIDE;
 | 
			
		||||
  virtual void WillHideMenu(views::MenuItemView* menu) OVERRIDE;
 | 
			
		||||
  virtual views::MenuItemView* GetSiblingMenu(
 | 
			
		||||
      views::MenuItemView* menu,
 | 
			
		||||
      const gfx::Point& screen_point,
 | 
			
		||||
      views::MenuItemView::AnchorPosition* anchor,
 | 
			
		||||
      bool* has_mnemonics,
 | 
			
		||||
      views::MenuButton** button);
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // Gets the cached menu item view from the model.
 | 
			
		||||
  views::MenuItemView* BuildMenu(ui::MenuModel* model);
 | 
			
		||||
 | 
			
		||||
  // Returns delegate for current item.
 | 
			
		||||
  views::MenuDelegate* delegate() const { return delegates_[id_]; }
 | 
			
		||||
 | 
			
		||||
  MenuBar* menu_bar_;
 | 
			
		||||
  scoped_ptr<views::MenuRunner> menu_runner_;
 | 
			
		||||
 | 
			
		||||
  // Current item's id.
 | 
			
		||||
  int id_;
 | 
			
		||||
  // Cached menu items, managed by MenuRunner.
 | 
			
		||||
  std::vector<views::MenuItemView*> items_;
 | 
			
		||||
  // Cached menu delegates for each menu item, managed by us.
 | 
			
		||||
  std::vector<views::MenuDelegate*> delegates_;
 | 
			
		||||
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(MenuDelegate);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace atom
 | 
			
		||||
 | 
			
		||||
#endif  // ATOM_BROWSER_UI_VIEWS_MENU_DELEGATE_H_
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue