Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / extensions / media_galleries_dialog_cocoa.mm
blob976d672f7d82ee4bceba8aee51bcfe38c4ee5de7
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa.h"
7 #include "base/mac/scoped_nsobject.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "chrome/browser/ui/chrome_style.h"
10 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.h"
11 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
12 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.h"
13 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
14 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h"
15 #include "chrome/grit/generated_resources.h"
16 #include "content/public/browser/web_contents.h"
17 #import "ui/base/cocoa/flipped_view.h"
18 #import "ui/base/cocoa/menu_controller.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #import "ui/base/models/menu_model.h"
22 // Controller for UI events on items in the media galleries dialog.
23 @interface MediaGalleriesCocoaController : NSObject {
24  @private
25   MediaGalleriesDialogCocoa* dialog_;
28 @property(assign, nonatomic) MediaGalleriesDialogCocoa* dialog;
30 - (void)onAcceptButton:(id)sender;
31 - (void)onCancelButton:(id)sender;
32 - (void)onAuxiliaryButton:(id)sender;
34 @end
36 @implementation MediaGalleriesCocoaController
38 @synthesize dialog = dialog_;
40 - (void)onAcceptButton:(id)sender {
41   dialog_->OnAcceptClicked();
44 - (void)onCancelButton:(id)sender {
45   dialog_->OnCancelClicked();
48 - (void)onAuxiliaryButton:(id)sender {
49   DCHECK(dialog_);
50   dialog_->OnAuxiliaryButtonClicked();
53 @end
55 namespace {
57 const CGFloat kCheckboxMargin = 10;
58 const CGFloat kCheckboxMaxWidth = 440;
59 const CGFloat kScrollAreaHeight = 220;
61 }  // namespace
63 MediaGalleriesDialogCocoa::MediaGalleriesDialogCocoa(
64     MediaGalleriesDialogController* controller,
65     MediaGalleriesCocoaController* cocoa_controller)
66     : controller_(controller),
67       accepted_(false),
68       cocoa_controller_([cocoa_controller retain]) {
69   [cocoa_controller_ setDialog:this];
71   alert_.reset([[ConstrainedWindowAlert alloc] init]);
73   [alert_ setMessageText:base::SysUTF16ToNSString(controller_->GetHeader())];
74   [alert_ setInformativeText:
75       base::SysUTF16ToNSString(controller_->GetSubtext())];
76   [alert_ addButtonWithTitle:
77       base::SysUTF16ToNSString(controller_->GetAcceptButtonText())
78                keyEquivalent:kKeyEquivalentReturn
79                       target:cocoa_controller_
80                       action:@selector(onAcceptButton:)];
81   [alert_ addButtonWithTitle:
82       l10n_util::GetNSString(IDS_MEDIA_GALLERIES_DIALOG_CANCEL)
83                keyEquivalent:kKeyEquivalentEscape
84                       target:cocoa_controller_
85                       action:@selector(onCancelButton:)];
86   base::string16 auxiliaryButtonLabel = controller_->GetAuxiliaryButtonText();
87   if (!auxiliaryButtonLabel.empty()) {
88     [alert_ addButtonWithTitle:base::SysUTF16ToNSString(auxiliaryButtonLabel)
89                  keyEquivalent:kKeyEquivalentNone
90                         target:cocoa_controller_
91                         action:@selector(onAuxiliaryButton:)];
92   }
93   [[alert_ closeButton] setTarget:cocoa_controller_];
94   [[alert_ closeButton] setAction:@selector(onCancelButton:)];
96   InitDialogControls();
98   // May be NULL during tests.
99   if (controller->WebContents()) {
100     base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
101         [[CustomConstrainedWindowSheet alloc]
102             initWithCustomWindow:[alert_ window]]);
103     window_.reset(new ConstrainedWindowMac(
104         this, controller->WebContents(), sheet));
105   }
108 MediaGalleriesDialogCocoa::~MediaGalleriesDialogCocoa() {
111 void MediaGalleriesDialogCocoa::AcceptDialogForTesting() {
112   OnAcceptClicked();
115 void MediaGalleriesDialogCocoa::InitDialogControls() {
116   main_container_.reset([[NSBox alloc] init]);
117   [main_container_ setBoxType:NSBoxCustom];
118   [main_container_ setBorderType:NSLineBorder];
119   [main_container_ setBorderWidth:1];
120   [main_container_ setCornerRadius:0];
121   [main_container_ setContentViewMargins:NSZeroSize];
122   [main_container_ setTitlePosition:NSNoTitle];
123   [main_container_ setBorderColor:[NSColor disabledControlTextColor]];
125   base::scoped_nsobject<NSScrollView> scroll_view(
126       [[NSScrollView alloc] initWithFrame:
127           NSMakeRect(0, 0, kCheckboxMaxWidth, kScrollAreaHeight)]);
128   [scroll_view setHasVerticalScroller:YES];
129   [scroll_view setHasHorizontalScroller:NO];
130   [scroll_view setBorderType:NSNoBorder];
131   [scroll_view setAutohidesScrollers:YES];
132   [[main_container_ contentView] addSubview:scroll_view];
134   // Add gallery checkboxes inside the scrolling view.
135   checkbox_container_.reset([[FlippedView alloc] initWithFrame:NSZeroRect]);
137   std::vector<base::string16> headers = controller_->GetSectionHeaders();
138   CGFloat y_pos = 0;
139   for (size_t i = 0; i < headers.size(); i++) {
140     MediaGalleriesDialogController::Entries entries =
141         controller_->GetSectionEntries(i);
142     if (!entries.empty()) {
143       if (!headers[i].empty()) {
144         y_pos = CreateCheckboxSeparator(y_pos,
145                                         base::SysUTF16ToNSString(headers[i]));
146       }
147       y_pos = CreateCheckboxes(y_pos, entries);
148     }
149   }
151   // Give the container a reasonable initial size so that the scroll_view can
152   // figure out the content size.
153   [checkbox_container_ setFrameSize:NSMakeSize(kCheckboxMaxWidth, y_pos)];
154   [scroll_view setDocumentView:checkbox_container_];
155   [checkbox_container_ setFrameSize:NSMakeSize([scroll_view contentSize].width,
156                                                y_pos)];
158   // Resize to pack the scroll view if possible.
159   NSRect scroll_frame = [scroll_view frame];
160   if (NSHeight(scroll_frame) > NSHeight([checkbox_container_ frame])) {
161     scroll_frame.size.height = NSHeight([checkbox_container_ frame]);
162     [scroll_view setFrameSize:scroll_frame.size];
163   }
165   [main_container_ setFrameFromContentFrame:scroll_frame];
166   [main_container_ setFrameOrigin:NSZeroPoint];
167   [alert_ setAccessoryView:main_container_];
169   // As a safeguard against the user skipping reading over the dialog and just
170   // confirming, the button will be unavailable for dialogs without any checks
171   // until the user toggles something.
172   [[[alert_ buttons] objectAtIndex:0] setEnabled:
173       controller_->IsAcceptAllowed()];
175   [alert_ layout];
178 CGFloat MediaGalleriesDialogCocoa::CreateCheckboxes(
179     CGFloat y_pos,
180     const MediaGalleriesDialogController::Entries& entries) {
181   for (MediaGalleriesDialogController::Entries::const_iterator iter =
182        entries.begin(); iter != entries.end(); ++iter) {
183     const MediaGalleriesDialogController::Entry& entry = *iter;
184     base::scoped_nsobject<MediaGalleryListEntry> checkbox_entry(
185         [[MediaGalleryListEntry alloc]
186             initWithFrame:NSZeroRect
187                controller:this
188                  prefInfo:entry.pref_info
189          showFolderViewer:controller_->ShouldShowFolderViewer(entry)]);
191     [checkbox_entry setState:entry.selected];
193     [checkbox_entry setFrameOrigin:NSMakePoint(0, y_pos)];
194     y_pos = NSMaxY([checkbox_entry frame]) + kCheckboxMargin;
196     [checkbox_container_ addSubview:checkbox_entry];
197   }
199   return y_pos;
202 CGFloat MediaGalleriesDialogCocoa::CreateCheckboxSeparator(CGFloat y_pos,
203                                                            NSString* header) {
204   base::scoped_nsobject<NSBox> separator(
205       [[NSBox alloc] initWithFrame:NSMakeRect(
206           0, y_pos + kCheckboxMargin * 0.5, kCheckboxMaxWidth, 1.0)]);
207   [separator setBoxType:NSBoxSeparator];
208   [separator setBorderType:NSLineBorder];
209   [separator setAlphaValue:0.2];
210   [checkbox_container_ addSubview:separator];
211   y_pos += kCheckboxMargin * 0.5 + 4;
213   base::scoped_nsobject<NSTextField> unattached_label(
214       [[NSTextField alloc] initWithFrame:NSZeroRect]);
215   [unattached_label setEditable:NO];
216   [unattached_label setSelectable:NO];
217   [unattached_label setBezeled:NO];
218   [unattached_label setAttributedStringValue:
219       constrained_window::GetAttributedLabelString(
220           header,
221           chrome_style::kTextFontStyle,
222           NSNaturalTextAlignment,
223           NSLineBreakByClipping
224       )];
225   [unattached_label sizeToFit];
226   NSSize unattached_label_size = [unattached_label frame].size;
227   [unattached_label setFrame:NSMakeRect(
228       kCheckboxMargin, y_pos + kCheckboxMargin,
229       kCheckboxMaxWidth, unattached_label_size.height)];
230   [checkbox_container_ addSubview:unattached_label];
231   y_pos = NSMaxY([unattached_label frame]) + kCheckboxMargin;
233   return y_pos;
236 void MediaGalleriesDialogCocoa::OnAcceptClicked() {
237   accepted_ = true;
239   if (window_)
240     window_->CloseWebContentsModalDialog();
243 void MediaGalleriesDialogCocoa::OnCancelClicked() {
244   if (window_)
245     window_->CloseWebContentsModalDialog();
248 void MediaGalleriesDialogCocoa::OnAuxiliaryButtonClicked() {
249   controller_->DidClickAuxiliaryButton();
252 void MediaGalleriesDialogCocoa::UpdateGalleries() {
253   InitDialogControls();
256 void MediaGalleriesDialogCocoa::OnConstrainedWindowClosed(
257     ConstrainedWindowMac* window) {
258   controller_->DialogFinished(accepted_);
261 void MediaGalleriesDialogCocoa::OnCheckboxToggled(MediaGalleryPrefId pref_id,
262                                                   bool checked) {
263   controller_->DidToggleEntry(pref_id, checked);
265   [[[alert_ buttons] objectAtIndex:0] setEnabled:
266       controller_->IsAcceptAllowed()];
269 void MediaGalleriesDialogCocoa::OnFolderViewerClicked(
270     MediaGalleryPrefId prefId) {
271   controller_->DidClickOpenFolderViewer(prefId);
274 ui::MenuModel* MediaGalleriesDialogCocoa::GetContextMenu(
275     MediaGalleryPrefId pref_id) {
276   return controller_->GetContextMenu(pref_id);
279 // static
280 MediaGalleriesDialog* MediaGalleriesDialog::Create(
281     MediaGalleriesDialogController* controller) {
282   base::scoped_nsobject<MediaGalleriesCocoaController> cocoa_controller(
283       [[MediaGalleriesCocoaController alloc] init]);
284   return new MediaGalleriesDialogCocoa(controller, cocoa_controller);