Index: ui/app_list/views/views_demo_app_mac.mm |
diff --git a/ui/app_list/views/views_demo_app_mac.mm b/ui/app_list/views/views_demo_app_mac.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..095d5edabf0966d3781c95ab5cda3c5a8ac35dd0 |
--- /dev/null |
+++ b/ui/app_list/views/views_demo_app_mac.mm |
@@ -0,0 +1,162 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/app_list/views/views_demo_app.h" |
+ |
+#import <Cocoa/Cocoa.h> |
+ |
+#include "base/logging.h" |
+#include "base/mac/scoped_nsobject.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/strings/sys_string_conversions.h" |
+ |
+@interface CocoaDemoAppImpl : NSObject<NSApplicationDelegate> { |
+ @private |
+ ViewsDemoApp* app_; // Weak. Owns us. |
+ ViewsDemoAppDelegate* delegate_; // Explicit ownership. |
+ base::scoped_nsobject<NSMenu> options_; |
+ base::scoped_nsobject<NSMutableArray> optionTargets_; |
+} |
+ |
+@property(assign, nonatomic) ViewsDemoApp* app; |
+@property(assign, nonatomic) ViewsDemoAppDelegate* delegate; |
+ |
+- (void)addOption:(const char*)description |
+ withCallback:(const base::Callback<void(bool)>&)callback |
+ initialState:(BOOL)isOn; |
+ |
+@end |
+ |
+@interface CallbackBridge : NSObject { |
+ @private |
+ NSMenuItem* menuItem_; |
+ base::Callback<void(bool)> callback_; |
+} |
+ |
+- (id)initWithCallback:(const base::Callback<void(bool)>&)callback |
+ forMenuItem:(NSMenuItem*)menuItem; |
+ |
+- (void)run:(id)sender; |
+ |
+@end |
+ |
+namespace { |
+ |
+class ViewsDemoAppMac : public ViewsDemoApp { |
+ public: |
+ ViewsDemoAppMac(ViewsDemoAppDelegate* delegate) |
+ : impl_([[CocoaDemoAppImpl alloc] init]) { |
+ [impl_ setApp:this]; |
+ [impl_ setDelegate:delegate]; |
+ [[NSApplication sharedApplication] setDelegate:impl_]; |
+ } |
+ |
+ virtual ~ViewsDemoAppMac() { |
+ [[NSApplication sharedApplication] setDelegate:nil]; |
+ ViewsDemoAppDelegate* delegate = [impl_ delegate]; |
+ [impl_ setDelegate:nil]; |
+ impl_.reset(); |
+ delete delegate; |
+ } |
+ |
+ virtual void Run() OVERRIDE { |
+ base::MessageLoopForUI message_loop; |
+ DCHECK([impl_ delegate]); |
+ [impl_ delegate]->Run(); |
+ } |
+ |
+ virtual void AddOption(const char* description, |
+ const base::Callback<void(bool)>& callback, |
+ bool initial_state) OVERRIDE { |
+ [impl_ addOption:description |
+ withCallback:callback |
+ initialState:initial_state]; |
+ } |
+ |
+ private: |
+ base::scoped_nsobject<CocoaDemoAppImpl> impl_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ViewsDemoAppMac); |
+}; |
+} |
+ |
+@implementation CocoaDemoAppImpl |
+ |
+@synthesize app = app_; |
+@synthesize delegate = delegate_; |
+ |
+- (void)addOption:(const char*)description |
+ withCallback:(const base::Callback<void(bool)>&)callback |
+ initialState:(BOOL)isOn { |
+ if (!options_) { |
+ options_.reset([[NSMenu alloc] initWithTitle:@"Options"]); |
+ optionTargets_.reset([[NSMutableArray alloc] initWithCapacity:1]); |
+ } |
+ |
+ NSString* title = base::SysUTF8ToNSString(description); |
+ NSMenuItem* item = [options_ addItemWithTitle:title |
+ action:@selector(run:) |
+ keyEquivalent:@""]; |
+ base::scoped_nsobject<CallbackBridge> bridge( |
+ [[CallbackBridge alloc] initWithCallback:callback forMenuItem:item]); |
+ [item setTarget:bridge]; |
+ [item setState:isOn ? NSOnState : NSOffState]; |
+ [optionTargets_ addObject:bridge]; |
+} |
+ |
+- (void)applicationDidFinishLaunching:(NSNotification*)aNotification { |
+ // To get key events, we need to set a main menu and have an activation |
+ // policy. |
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; |
+ base::scoped_nsobject<NSMenu> mainMenu([[NSMenu alloc] initWithTitle:@""]); |
+ NSMenuItem* appMenuItem = |
+ [mainMenu addItemWithTitle:@"" action:NULL keyEquivalent:@""]; |
+ [NSApp setMainMenu:mainMenu]; |
+ |
+ base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:@""]); |
+ NSString* appName = [[NSProcessInfo processInfo] processName]; |
+ NSString* quitTitle = [@"Quit " stringByAppendingString:appName]; |
+ [appMenu addItemWithTitle:quitTitle |
+ action:@selector(terminate:) |
+ keyEquivalent:@"q"]; |
+ [appMenuItem setSubmenu:appMenu]; |
+ |
+ app_->InitOnMainThread(); |
+ if (delegate_) |
+ delegate_->Init(); |
+ |
+ if (options_) { |
+ NSMenuItem* optionsMenuItem = |
+ [mainMenu addItemWithTitle:@"" action:NULL keyEquivalent:@""]; |
+ [optionsMenuItem setSubmenu:options_]; |
+ options_.reset(); |
+ } |
+} |
+ |
+@end |
+ |
+@implementation CallbackBridge |
+ |
+- (id)initWithCallback:(const base::Callback<void(bool)>&)callback |
+ forMenuItem:(NSMenuItem*)menuItem { |
+ if ((self = [super init])) { |
+ callback_ = callback; |
+ menuItem_ = menuItem; |
+ } |
+ return self; |
+} |
+ |
+- (void)run:(id)sender { |
+ BOOL newState = [menuItem_ state] == NSOnState ? NSOffState : NSOnState; |
+ [menuItem_ setState:newState]; |
+ callback_.Run(newState == NSOnState); |
+} |
+ |
+@end |
+ |
+// static |
+scoped_ptr<ViewsDemoApp> ViewsDemoApp::Create( |
+ scoped_ptr<ViewsDemoAppDelegate> delegate) { |
+ return scoped_ptr<ViewsDemoApp>(new ViewsDemoAppMac(delegate.release())); |
+} |