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 "content/public/browser/web_contents.h"
16 #include "grit/generated_resources.h"
17 #import "ui/base/cocoa/flipped_view.h"
18 #import "ui/base/cocoa/menu_controller.h"
19 #import "ui/base/models/menu_model.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h"
23 // Controller for UI events on items in the media galleries dialog.
24 @interface MediaGalleriesCocoaController : NSObject {
26 MediaGalleriesDialogCocoa* dialog_;
29 @property(assign, nonatomic) MediaGalleriesDialogCocoa* dialog;
31 - (void)onAcceptButton:(id)sender;
32 - (void)onCancelButton:(id)sender;
33 - (void)onAddFolderClicked:(id)sender;
37 @implementation MediaGalleriesCocoaController
39 @synthesize dialog = dialog_;
41 - (void)onAcceptButton:(id)sender {
42 dialog_->OnAcceptClicked();
45 - (void)onCancelButton:(id)sender {
46 dialog_->OnCancelClicked();
49 - (void)onAddFolderClicked:(id)sender {
51 dialog_->OnAddFolderClicked();
58 const CGFloat kCheckboxMargin = 10;
59 const CGFloat kCheckboxMaxWidth = 440;
60 const CGFloat kScrollAreaHeight = 220;
64 MediaGalleriesDialogCocoa::MediaGalleriesDialogCocoa(
65 MediaGalleriesDialogController* controller,
66 MediaGalleriesCocoaController* cocoa_controller)
67 : controller_(controller),
69 cocoa_controller_([cocoa_controller retain]) {
70 [cocoa_controller_ setDialog:this];
72 alert_.reset([[ConstrainedWindowAlert alloc] init]);
74 [alert_ setMessageText:base::SysUTF16ToNSString(controller_->GetHeader())];
75 [alert_ setInformativeText:
76 base::SysUTF16ToNSString(controller_->GetSubtext())];
77 [alert_ addButtonWithTitle:
78 l10n_util::GetNSString(IDS_MEDIA_GALLERIES_DIALOG_CONFIRM)
79 keyEquivalent:kKeyEquivalentReturn
80 target:cocoa_controller_
81 action:@selector(onAcceptButton:)];
82 [alert_ addButtonWithTitle:
83 l10n_util::GetNSString(IDS_MEDIA_GALLERIES_DIALOG_CANCEL)
84 keyEquivalent:kKeyEquivalentEscape
85 target:cocoa_controller_
86 action:@selector(onCancelButton:)];
87 [alert_ addButtonWithTitle:
88 l10n_util::GetNSString(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY)
89 keyEquivalent:kKeyEquivalentNone
90 target:cocoa_controller_
91 action:@selector(onAddFolderClicked:)];
92 [[alert_ closeButton] setTarget:cocoa_controller_];
93 [[alert_ closeButton] setAction:@selector(onCancelButton:)];
97 // May be NULL during tests.
98 if (controller->web_contents()) {
99 base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
100 [[CustomConstrainedWindowSheet alloc]
101 initWithCustomWindow:[alert_ window]]);
102 window_.reset(new ConstrainedWindowMac(
103 this, controller->web_contents(), sheet));
107 MediaGalleriesDialogCocoa::~MediaGalleriesDialogCocoa() {
110 void MediaGalleriesDialogCocoa::InitDialogControls() {
111 main_container_.reset([[NSBox alloc] init]);
112 [main_container_ setBoxType:NSBoxCustom];
113 [main_container_ setBorderType:NSLineBorder];
114 [main_container_ setBorderWidth:1];
115 [main_container_ setCornerRadius:0];
116 [main_container_ setContentViewMargins:NSZeroSize];
117 [main_container_ setTitlePosition:NSNoTitle];
118 [main_container_ setBorderColor:[NSColor colorWithCalibratedRed:0.625
123 base::scoped_nsobject<NSScrollView> scroll_view(
124 [[NSScrollView alloc] initWithFrame:
125 NSMakeRect(0, 0, kCheckboxMaxWidth, kScrollAreaHeight)]);
126 [scroll_view setHasVerticalScroller:YES];
127 [scroll_view setHasHorizontalScroller:NO];
128 [scroll_view setBorderType:NSNoBorder];
129 [scroll_view setAutohidesScrollers:YES];
130 [[main_container_ contentView] addSubview:scroll_view];
132 // Add gallery permission checkboxes inside the scrolling view.
133 checkbox_container_.reset([[FlippedView alloc] initWithFrame:NSZeroRect]);
135 CGFloat y_pos = CreateCheckboxes(0, controller_->AttachedPermissions());
137 if (!controller_->UnattachedPermissions().empty()) {
138 y_pos = CreateCheckboxSeparator(y_pos);
139 y_pos = CreateCheckboxes(y_pos, controller_->UnattachedPermissions());
142 // Give the container a reasonable initial size so that the scroll_view can
143 // figure out the content size.
144 [checkbox_container_ setFrameSize:NSMakeSize(kCheckboxMaxWidth, y_pos)];
145 [scroll_view setDocumentView:checkbox_container_];
146 [checkbox_container_ setFrameSize:NSMakeSize([scroll_view contentSize].width,
149 // Resize to pack the scroll view if possible.
150 NSRect scroll_frame = [scroll_view frame];
151 if (NSHeight(scroll_frame) > NSHeight([checkbox_container_ frame])) {
152 scroll_frame.size.height = NSHeight([checkbox_container_ frame]);
153 [scroll_view setFrameSize:scroll_frame.size];
156 [main_container_ setFrameFromContentFrame:scroll_frame];
157 [main_container_ setFrameOrigin:NSZeroPoint];
158 [alert_ setAccessoryView:main_container_];
160 // As a safeguard against the user skipping reading over the dialog and just
161 // confirming, the button will be unavailable for dialogs without any checks
162 // until the user toggles something.
163 [[[alert_ buttons] objectAtIndex:0] setEnabled:
164 controller_->IsAcceptAllowed()];
169 CGFloat MediaGalleriesDialogCocoa::CreateCheckboxes(
171 const MediaGalleriesDialogController::GalleryPermissionsVector&
173 for (MediaGalleriesDialogController::GalleryPermissionsVector::
174 const_iterator iter = permissions.begin();
175 iter != permissions.end(); iter++) {
176 const MediaGalleriesDialogController::GalleryPermission& permission = *iter;
177 base::scoped_nsobject<MediaGalleryListEntry> checkbox_entry(
178 [[MediaGalleryListEntry alloc]
179 initWithFrame:NSZeroRect
181 prefId:permission.gallery_id
182 galleryName:permission.pref_info.GetGalleryDisplayName()
183 subscript:permission.pref_info.GetGalleryAdditionalDetails()
184 tooltip:permission.pref_info.GetGalleryTooltip()
185 showFolderViewer:false]);
187 [checkbox_entry setState:permission.allowed];
189 [checkbox_entry setFrameOrigin:NSMakePoint(0, y_pos)];
190 y_pos = NSMaxY([checkbox_entry frame]) + kCheckboxMargin;
192 [checkbox_container_ addSubview:checkbox_entry];
198 CGFloat MediaGalleriesDialogCocoa::CreateCheckboxSeparator(CGFloat y_pos) {
199 base::scoped_nsobject<NSBox> separator(
200 [[NSBox alloc] initWithFrame:NSMakeRect(
201 0, y_pos + kCheckboxMargin * 0.5, kCheckboxMaxWidth, 1.0)]);
202 [separator setBoxType:NSBoxSeparator];
203 [separator setBorderType:NSLineBorder];
204 [separator setAlphaValue:0.2];
205 [checkbox_container_ addSubview:separator];
206 y_pos += kCheckboxMargin * 0.5 + 4;
208 base::scoped_nsobject<NSTextField> unattached_label(
209 [[NSTextField alloc] initWithFrame:NSZeroRect]);
210 [unattached_label setEditable:NO];
211 [unattached_label setSelectable:NO];
212 [unattached_label setBezeled:NO];
213 [unattached_label setAttributedStringValue:
214 constrained_window::GetAttributedLabelString(
215 base::SysUTF16ToNSString(
216 controller_->GetUnattachedLocationsHeader()),
217 chrome_style::kTextFontStyle,
218 NSNaturalTextAlignment,
219 NSLineBreakByClipping
221 [unattached_label sizeToFit];
222 NSSize unattached_label_size = [unattached_label frame].size;
223 [unattached_label setFrame:NSMakeRect(
224 kCheckboxMargin, y_pos + kCheckboxMargin,
225 kCheckboxMaxWidth, unattached_label_size.height)];
226 [checkbox_container_ addSubview:unattached_label];
227 y_pos = NSMaxY([unattached_label frame]) + kCheckboxMargin;
232 void MediaGalleriesDialogCocoa::OnAcceptClicked() {
236 window_->CloseWebContentsModalDialog();
239 void MediaGalleriesDialogCocoa::OnCancelClicked() {
241 window_->CloseWebContentsModalDialog();
244 void MediaGalleriesDialogCocoa::OnAddFolderClicked() {
245 controller_->OnAddFolderClicked();
248 void MediaGalleriesDialogCocoa::UpdateGalleries() {
249 InitDialogControls();
252 void MediaGalleriesDialogCocoa::OnConstrainedWindowClosed(
253 ConstrainedWindowMac* window) {
254 controller_->DialogFinished(accepted_);
257 void MediaGalleriesDialogCocoa::OnCheckboxToggled(GalleryDialogId gallery_id,
259 controller_->DidToggleGallery(gallery_id, checked);
261 [[[alert_ buttons] objectAtIndex:0] setEnabled:
262 controller_->IsAcceptAllowed()];
265 ui::MenuModel* MediaGalleriesDialogCocoa::GetContextMenu(
266 GalleryDialogId gallery_id) {
267 return controller_->GetContextMenu(gallery_id);
271 MediaGalleriesDialog* MediaGalleriesDialog::Create(
272 MediaGalleriesDialogController* controller) {
273 base::scoped_nsobject<MediaGalleriesCocoaController> cocoa_controller(
274 [[MediaGalleriesCocoaController alloc] init]);
275 return new MediaGalleriesDialogCocoa(controller, cocoa_controller);