- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / extensions / media_galleries_dialog_gtk.cc
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       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(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(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 = UTF16ToUTF8(gallery.GetGalleryAdditionalDetails());
179   GtkWidget* details_label = gtk_label_new(details.c_str());
180   gtk_label_set_line_wrap(GTK_LABEL(details_label), FALSE);
181   gtk_util::SetLabelColor(details_label, &kDeemphasizedTextColor);
182   gtk_box_pack_start(GTK_BOX(hbox), details_label, FALSE, FALSE, 0);
183
184   gtk_widget_show(hbox);
185   if (gallery.pref_id != kInvalidMediaGalleryPrefId)
186     checkbox_map_[gallery.pref_id] = widget;
187   else
188     new_checkbox_map_[widget] = gallery;
189
190   std::string tooltip_text = UTF16ToUTF8(gallery.GetGalleryTooltip());
191   gtk_widget_set_tooltip_text(widget, tooltip_text.c_str());
192
193   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), permitted);
194   std::string label = UTF16ToUTF8(gallery.GetGalleryDisplayName());
195   // TODO(gbillock): Would be nice to add middle elide behavior here.
196   gtk_button_set_label(GTK_BUTTON(widget), label.c_str());
197 }
198
199 void MediaGalleriesDialogGtk::OnToggled(GtkWidget* widget) {
200   if (confirm_)
201     gtk_widget_set_sensitive(confirm_, TRUE);
202
203   for (CheckboxMap::const_iterator iter = checkbox_map_.begin();
204        iter != checkbox_map_.end(); ++iter) {
205     if (iter->second == widget) {
206       controller_->DidToggleGalleryId(
207           iter->first,
208           gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
209       return;
210     }
211   }
212   for (NewCheckboxMap::const_iterator iter = new_checkbox_map_.begin();
213        iter != new_checkbox_map_.end(); ++iter) {
214     if (iter->first == widget) {
215       controller_->DidToggleNewGallery(
216           iter->second,
217           gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
218       return;
219     }
220   }
221 }
222
223 void MediaGalleriesDialogGtk::OnAddFolder(GtkWidget* widget) {
224   controller_->OnAddFolderClicked();
225 }
226
227 void MediaGalleriesDialogGtk::OnConfirm(GtkWidget* widget) {
228   accepted_ = true;
229
230   if (window_)
231     gtk_widget_destroy(window_);
232 }
233
234 void MediaGalleriesDialogGtk::OnCancel(GtkWidget* widget) {
235   if (window_)
236     gtk_widget_destroy(window_);
237 }
238
239 void MediaGalleriesDialogGtk::OnDestroy(GtkWidget* widget) {
240   controller_->DialogFinished(accepted_);
241 }
242
243 // MediaGalleriesDialogController ----------------------------------------------
244
245 // static
246 MediaGalleriesDialog* MediaGalleriesDialog::Create(
247     MediaGalleriesDialogController* controller) {
248   return new MediaGalleriesDialogGtk(controller);
249 }