1// Copyright (c) 2009 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#include "chrome/browser/ui/cocoa/constrained_window_mac.h"
6
7#import "chrome/browser/ui/cocoa/browser_window_controller.h"
8#include "content/browser/tab_contents/tab_contents.h"
9#include "content/browser/tab_contents/tab_contents_view.h"
10#import "third_party/GTM/AppKit/GTMWindowSheetController.h"
11
12ConstrainedWindowMacDelegateSystemSheet::
13ConstrainedWindowMacDelegateSystemSheet(id delegate, SEL didEndSelector)
14    : systemSheet_(nil),
15      delegate_([delegate retain]),
16      didEndSelector_(didEndSelector) {}
17
18ConstrainedWindowMacDelegateSystemSheet::
19    ~ConstrainedWindowMacDelegateSystemSheet() {}
20
21void ConstrainedWindowMacDelegateSystemSheet::set_sheet(id sheet) {
22  systemSheet_.reset([sheet retain]);
23}
24
25NSArray* ConstrainedWindowMacDelegateSystemSheet::GetSheetParameters(
26    id delegate,
27    SEL didEndSelector) {
28  return [NSArray arrayWithObjects:
29      [NSNull null],  // window, must be [NSNull null]
30      delegate,
31      [NSValue valueWithPointer:didEndSelector],
32      [NSValue valueWithPointer:NULL],  // context info for didEndSelector_.
33      nil];
34}
35
36void ConstrainedWindowMacDelegateSystemSheet::RunSheet(
37    GTMWindowSheetController* sheetController,
38    NSView* view) {
39  NSArray* params = GetSheetParameters(delegate_.get(), didEndSelector_);
40  [sheetController beginSystemSheet:systemSheet_
41                       modalForView:view
42                     withParameters:params];
43}
44
45ConstrainedWindowMacDelegateCustomSheet::
46ConstrainedWindowMacDelegateCustomSheet()
47    : customSheet_(nil),
48      delegate_(nil),
49      didEndSelector_(NULL) {}
50
51ConstrainedWindowMacDelegateCustomSheet::
52ConstrainedWindowMacDelegateCustomSheet(id delegate, SEL didEndSelector)
53    : customSheet_(nil),
54      delegate_([delegate retain]),
55      didEndSelector_(didEndSelector) {}
56
57ConstrainedWindowMacDelegateCustomSheet::
58~ConstrainedWindowMacDelegateCustomSheet() {}
59
60void ConstrainedWindowMacDelegateCustomSheet::init(NSWindow* sheet,
61                                                   id delegate,
62                                                   SEL didEndSelector) {
63    DCHECK(!delegate_.get());
64    DCHECK(!didEndSelector_);
65    customSheet_.reset([sheet retain]);
66    delegate_.reset([delegate retain]);
67    didEndSelector_ = didEndSelector;
68    DCHECK(delegate_.get());
69    DCHECK(didEndSelector_);
70  }
71
72void ConstrainedWindowMacDelegateCustomSheet::set_sheet(NSWindow* sheet) {
73  customSheet_.reset([sheet retain]);
74}
75
76void ConstrainedWindowMacDelegateCustomSheet::RunSheet(
77    GTMWindowSheetController* sheetController,
78    NSView* view) {
79  [sheetController beginSheet:customSheet_.get()
80                 modalForView:view
81                modalDelegate:delegate_.get()
82               didEndSelector:didEndSelector_
83                  contextInfo:NULL];
84}
85
86// static
87ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog(
88    TabContents* parent,
89    ConstrainedWindowMacDelegate* delegate) {
90  return new ConstrainedWindowMac(parent, delegate);
91}
92
93ConstrainedWindowMac::ConstrainedWindowMac(
94    TabContents* owner, ConstrainedWindowMacDelegate* delegate)
95    : owner_(owner),
96      delegate_(delegate),
97      controller_(nil),
98      should_be_visible_(false) {
99  DCHECK(owner);
100  DCHECK(delegate);
101}
102
103ConstrainedWindowMac::~ConstrainedWindowMac() {}
104
105void ConstrainedWindowMac::ShowConstrainedWindow() {
106  should_be_visible_ = true;
107  // The TabContents only has a native window if it is currently visible. In
108  // this case, open the sheet now. Else, Realize() will be called later, when
109  // our tab becomes visible.
110  NSWindow* browserWindow = owner_->view()->GetTopLevelNativeWindow();
111  NSWindowController* controller = [browserWindow windowController];
112  if (controller != nil) {
113    DCHECK([controller isKindOfClass:[BrowserWindowController class]]);
114    BrowserWindowController* browser_controller =
115        static_cast<BrowserWindowController*>(controller);
116    if ([browser_controller canAttachConstrainedWindow])
117      Realize(browser_controller);
118  }
119}
120
121void ConstrainedWindowMac::CloseConstrainedWindow() {
122  // Note: controller_ can be `nil` here if the sheet was never realized. That's
123  // ok.
124  [controller_ removeConstrainedWindow:this];
125  delegate_->DeleteDelegate();
126  owner_->WillClose(this);
127
128  delete this;
129}
130
131void ConstrainedWindowMac::Realize(BrowserWindowController* controller) {
132  if (!should_be_visible_)
133    return;
134
135  if (controller_ != nil) {
136    DCHECK(controller_ == controller);
137    return;
138  }
139  DCHECK(controller != nil);
140
141  // Remember the controller we're adding ourselves to, so that we can later
142  // remove us from it.
143  controller_ = controller;
144  [controller_ attachConstrainedWindow:this];
145  delegate_->set_sheet_open(true);
146}
147