OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/ui/gtk/extensions/media_galleries_dialog_gtk.h" | |
6 | |
7 #include "base/auto_reset.h" | |
8 #include "base/strings/utf_string_conversions.h" | |
9 #include "chrome/browser/media_galleries/media_galleries_preferences.h" | |
10 #include "chrome/browser/ui/gtk/gtk_util.h" | |
11 #include "components/web_modal/web_contents_modal_dialog_manager.h" | |
12 #include "grit/generated_resources.h" | |
13 #include "ui/base/gtk/gtk_hig_constants.h" | |
14 #include "ui/base/l10n/l10n_util.h" | |
15 | |
16 using web_modal::WebContentsModalDialogManager; | |
17 | |
18 namespace { | |
19 | |
20 // Color used for additional attachment detail text for galleries. | |
21 const GdkColor kDeemphasizedTextColor = GDK_COLOR_RGB(0x96, 0x96, 0x96); | |
22 | |
23 // Width and height of the scrollable area in which galleries are shown. | |
24 const int kGalleryControlScrollableWidth = 280; | |
25 const int kGalleryControlScrollableHeight = 192; | |
26 | |
27 } // namespace | |
28 | |
29 typedef MediaGalleriesDialogController::GalleryPermissionsVector | |
30 GalleryPermissionsVector; | |
31 | |
32 MediaGalleriesDialogGtk::MediaGalleriesDialogGtk( | |
33 MediaGalleriesDialogController* controller) | |
34 : controller_(controller), | |
35 window_(NULL), | |
36 confirm_(NULL), | |
37 accepted_(false) { | |
38 contents_.reset(gtk_vbox_new(FALSE, ui::kContentAreaSpacing)); | |
39 g_object_ref_sink(contents_.get()); | |
40 g_signal_connect(contents_.get(), | |
41 "destroy", | |
42 G_CALLBACK(OnDestroyThunk), | |
43 this); | |
44 InitWidgets(); | |
45 | |
46 // May be NULL during tests. | |
47 if (controller->web_contents()) { | |
48 window_ = CreateWebContentsModalDialogGtk(contents_.get(), confirm_); | |
49 | |
50 WebContentsModalDialogManager* web_contents_modal_dialog_manager = | |
51 WebContentsModalDialogManager::FromWebContents( | |
52 controller->web_contents()); | |
53 web_contents_modal_dialog_manager->ShowDialog(window_); | |
54 } | |
55 } | |
56 | |
57 MediaGalleriesDialogGtk::~MediaGalleriesDialogGtk() { | |
58 } | |
59 | |
60 void MediaGalleriesDialogGtk::InitWidgets() { | |
61 gtk_util::RemoveAllChildren(contents_.get()); | |
62 checkbox_map_.clear(); | |
63 new_checkbox_map_.clear(); | |
64 confirm_ = NULL; | |
65 | |
66 GtkWidget* header = gtk_util::LeftAlignMisc(gtk_label_new( | |
67 base::UTF16ToUTF8(controller_->GetHeader()).c_str())); | |
68 gtk_box_pack_start(GTK_BOX(contents_.get()), header, FALSE, FALSE, 0); | |
69 | |
70 GtkWidget* subtext = | |
71 gtk_label_new(base::UTF16ToUTF8(controller_->GetSubtext()).c_str()); | |
72 gtk_label_set_line_wrap(GTK_LABEL(subtext), TRUE); | |
73 gtk_widget_set_size_request(subtext, 500, -1); | |
74 gtk_box_pack_start(GTK_BOX(contents_.get()), subtext, FALSE, FALSE, 0); | |
75 | |
76 // The checkboxes are added inside a scrollable area. | |
77 GtkWidget* scroll_window = | |
78 gtk_scrolled_window_new(NULL, NULL); | |
79 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), | |
80 GTK_POLICY_NEVER, | |
81 GTK_POLICY_AUTOMATIC); | |
82 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window), | |
83 GTK_SHADOW_ETCHED_IN); | |
84 | |
85 GtkWidget* checkbox_container = gtk_vbox_new(FALSE, ui::kControlSpacing); | |
86 gtk_widget_set_size_request(scroll_window, | |
87 kGalleryControlScrollableWidth, | |
88 kGalleryControlScrollableHeight); | |
89 gtk_container_set_border_width(GTK_CONTAINER(checkbox_container), | |
90 ui::kGroupIndent); | |
91 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll_window), | |
92 checkbox_container); | |
93 gtk_widget_show(checkbox_container); | |
94 gtk_box_pack_start(GTK_BOX(contents_.get()), scroll_window, | |
95 FALSE, FALSE, 0); | |
96 gtk_widget_show(scroll_window); | |
97 | |
98 // Attached galleries checkboxes | |
99 GalleryPermissionsVector permissions = controller_->AttachedPermissions(); | |
100 for (GalleryPermissionsVector::const_iterator iter = permissions.begin(); | |
101 iter != permissions.end(); ++iter) { | |
102 UpdateGalleryInContainer(iter->pref_info, iter->allowed, | |
103 checkbox_container); | |
104 } | |
105 | |
106 const GalleryPermissionsVector unattached_permissions = | |
107 controller_->UnattachedPermissions(); | |
108 if (!unattached_permissions.empty()) { | |
109 // Separator line and unattached volumes header text. | |
110 GtkWidget* separator = gtk_hseparator_new(); | |
111 gtk_box_pack_start(GTK_BOX(checkbox_container), separator, FALSE, FALSE, 0); | |
112 | |
113 GtkWidget* unattached_hbox = gtk_hbox_new(FALSE, ui::kLabelSpacing); | |
114 GtkWidget* unattached_text = gtk_label_new(base::UTF16ToUTF8( | |
115 controller_->GetUnattachedLocationsHeader()).c_str()); | |
116 gtk_label_set_line_wrap(GTK_LABEL(unattached_text), FALSE); | |
117 gtk_box_pack_start(GTK_BOX(unattached_hbox), unattached_text, | |
118 FALSE, FALSE, 0); | |
119 gtk_box_pack_start(GTK_BOX(checkbox_container), unattached_hbox, | |
120 FALSE, FALSE, 0); | |
121 | |
122 // Unattached galleries checkboxes | |
123 for (GalleryPermissionsVector::const_iterator iter = | |
124 unattached_permissions.begin(); | |
125 iter != unattached_permissions.end(); ++iter) { | |
126 UpdateGalleryInContainer(iter->pref_info, iter->allowed, | |
127 checkbox_container); | |
128 } | |
129 } | |
130 | |
131 GtkWidget* bottom_area = gtk_hbox_new(FALSE, ui::kControlSpacing); | |
132 | |
133 // Add gallery button. | |
134 GtkWidget* add_folder = gtk_button_new_with_label( | |
135 l10n_util::GetStringUTF8(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY).c_str()); | |
136 g_signal_connect(add_folder, "clicked", G_CALLBACK(OnAddFolderThunk), this); | |
137 gtk_box_pack_start(GTK_BOX(bottom_area), add_folder, FALSE, FALSE, 0); | |
138 | |
139 // Confirm/cancel button. | |
140 confirm_ = gtk_button_new_with_label(l10n_util::GetStringUTF8( | |
141 IDS_MEDIA_GALLERIES_DIALOG_CONFIRM).c_str()); | |
142 gtk_button_set_image( | |
143 GTK_BUTTON(confirm_), | |
144 gtk_image_new_from_stock(GTK_STOCK_APPLY, GTK_ICON_SIZE_BUTTON)); | |
145 g_signal_connect(confirm_, "clicked", G_CALLBACK(OnConfirmThunk), this); | |
146 gtk_box_pack_end(GTK_BOX(bottom_area), confirm_, FALSE, FALSE, 0); | |
147 | |
148 GtkWidget* cancel = gtk_button_new_with_label(l10n_util::GetStringUTF8( | |
149 IDS_MEDIA_GALLERIES_DIALOG_CANCEL).c_str()); | |
150 gtk_button_set_image( | |
151 GTK_BUTTON(cancel), | |
152 gtk_image_new_from_stock(GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON)); | |
153 g_signal_connect(cancel, "clicked", G_CALLBACK(OnCancelThunk), this); | |
154 gtk_box_pack_end(GTK_BOX(bottom_area), cancel, FALSE, FALSE, 0); | |
155 gtk_box_pack_start(GTK_BOX(contents_.get()), bottom_area, FALSE, FALSE, 0); | |
156 | |
157 // As a safeguard against the user skipping reading over the dialog and just | |
158 // confirming, the button will be unavailable for dialogs without any checks | |
159 // until the user toggles something. | |
160 gtk_widget_set_sensitive(confirm_, controller_->HasPermittedGalleries()); | |
161 | |
162 gtk_widget_show_all(contents_.get()); | |
163 } | |
164 | |
165 void MediaGalleriesDialogGtk::UpdateGalleries() { | |
166 InitWidgets(); | |
167 } | |
168 | |
169 void MediaGalleriesDialogGtk::UpdateGalleryInContainer( | |
170 const MediaGalleryPrefInfo& gallery, | |
171 bool permitted, | |
172 GtkWidget* checkbox_container) { | |
173 GtkWidget* hbox = gtk_hbox_new(FALSE, ui::kLabelSpacing); | |
174 GtkWidget* widget = gtk_check_button_new(); | |
175 g_signal_connect(widget, "toggled", G_CALLBACK(OnToggledThunk), this); | |
176 gtk_box_pack_start(GTK_BOX(checkbox_container), hbox, FALSE, FALSE, 0); | |
177 gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0); | |
178 std::string details = | |
179 base::UTF16ToUTF8(gallery.GetGalleryAdditionalDetails()); | |
180 GtkWidget* details_label = gtk_label_new(details.c_str()); | |
181 gtk_label_set_line_wrap(GTK_LABEL(details_label), FALSE); | |
182 gtk_util::SetLabelColor(details_label, &kDeemphasizedTextColor); | |
183 gtk_box_pack_start(GTK_BOX(hbox), details_label, FALSE, FALSE, 0); | |
184 | |
185 gtk_widget_show(hbox); | |
186 if (gallery.pref_id != kInvalidMediaGalleryPrefId) | |
187 checkbox_map_[gallery.pref_id] = widget; | |
188 else | |
189 new_checkbox_map_[widget] = gallery; | |
190 | |
191 std::string tooltip_text = base::UTF16ToUTF8(gallery.GetGalleryTooltip()); | |
192 gtk_widget_set_tooltip_text(widget, tooltip_text.c_str()); | |
193 | |
194 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), permitted); | |
195 std::string label = base::UTF16ToUTF8(gallery.GetGalleryDisplayName()); | |
196 // TODO(gbillock): Would be nice to add middle elide behavior here. | |
197 gtk_button_set_label(GTK_BUTTON(widget), label.c_str()); | |
198 } | |
199 | |
200 void MediaGalleriesDialogGtk::OnToggled(GtkWidget* widget) { | |
201 if (confirm_) | |
202 gtk_widget_set_sensitive(confirm_, TRUE); | |
203 | |
204 for (CheckboxMap::const_iterator iter = checkbox_map_.begin(); | |
205 iter != checkbox_map_.end(); ++iter) { | |
206 if (iter->second == widget) { | |
207 controller_->DidToggleGalleryId( | |
208 iter->first, | |
209 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); | |
210 return; | |
211 } | |
212 } | |
213 for (NewCheckboxMap::const_iterator iter = new_checkbox_map_.begin(); | |
214 iter != new_checkbox_map_.end(); ++iter) { | |
215 if (iter->first == widget) { | |
216 controller_->DidToggleNewGallery( | |
217 iter->second, | |
218 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); | |
219 return; | |
220 } | |
221 } | |
222 } | |
223 | |
224 void MediaGalleriesDialogGtk::OnAddFolder(GtkWidget* widget) { | |
225 controller_->OnAddFolderClicked(); | |
226 } | |
227 | |
228 void MediaGalleriesDialogGtk::OnConfirm(GtkWidget* widget) { | |
229 accepted_ = true; | |
230 | |
231 if (window_) | |
232 gtk_widget_destroy(window_); | |
233 } | |
234 | |
235 void MediaGalleriesDialogGtk::OnCancel(GtkWidget* widget) { | |
236 if (window_) | |
237 gtk_widget_destroy(window_); | |
238 } | |
239 | |
240 void MediaGalleriesDialogGtk::OnDestroy(GtkWidget* widget) { | |
241 controller_->DialogFinished(accepted_); | |
242 } | |
243 | |
244 // MediaGalleriesDialogController ---------------------------------------------- | |
245 | |
246 // static | |
247 MediaGalleriesDialog* MediaGalleriesDialog::Create( | |
248 MediaGalleriesDialogController* controller) { | |
249 return new MediaGalleriesDialogGtk(controller); | |
250 } | |
OLD | NEW |