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 {
25 MediaGalleriesDialogCocoa* dialog_;
28 @property(assign, nonatomic) MediaGalleriesDialogCocoa* dialog;
30 - (void)onAcceptButton:(id)sender;
31 - (void)onCancelButton:(id)sender;
32 - (void)onAuxiliaryButton:(id)sender;
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 {
50 dialog_->OnAuxiliaryButtonClicked();
57 const CGFloat kCheckboxMargin = 10;
58 const CGFloat kCheckboxMaxWidth = 440;
59 const CGFloat kScrollAreaHeight = 220;
63 MediaGalleriesDialogCocoa::MediaGalleriesDialogCocoa(
64 MediaGalleriesDialogController* controller,
65 MediaGalleriesCocoaController* cocoa_controller)
66 : controller_(controller),
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:)];
93 [[alert_ closeButton] setTarget:cocoa_controller_];
94 [[alert_ closeButton] setAction:@selector(onCancelButton:)];
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));
108 MediaGalleriesDialogCocoa::~MediaGalleriesDialogCocoa() {
111 void MediaGalleriesDialogCocoa::AcceptDialogForTesting() {
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();
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]));
147 y_pos = CreateCheckboxes(y_pos, entries);
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,
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];
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()];
178 CGFloat MediaGalleriesDialogCocoa::CreateCheckboxes(
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
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];
202 CGFloat MediaGalleriesDialogCocoa::CreateCheckboxSeparator(CGFloat y_pos,
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(
221 chrome_style::kTextFontStyle,
222 NSNaturalTextAlignment,
223 NSLineBreakByClipping
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;
236 void MediaGalleriesDialogCocoa::OnAcceptClicked() {
240 window_->CloseWebContentsModalDialog();
243 void MediaGalleriesDialogCocoa::OnCancelClicked() {
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,
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);
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);