|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include <gtk/gtk.h> |
|
7 #if (MOZ_WIDGET_GTK == 2) |
|
8 #include <gtk/gtkprintunixdialog.h> |
|
9 #else |
|
10 #include <gtk/gtkunixprint.h> |
|
11 #endif |
|
12 #include <stdlib.h> |
|
13 |
|
14 #include "mozilla/ArrayUtils.h" |
|
15 |
|
16 #include "mozcontainer.h" |
|
17 #include "nsIPrintSettings.h" |
|
18 #include "nsIWidget.h" |
|
19 #include "nsPrintDialogGTK.h" |
|
20 #include "nsPrintSettingsGTK.h" |
|
21 #include "nsString.h" |
|
22 #include "nsReadableUtils.h" |
|
23 #include "nsIFile.h" |
|
24 #include "nsNetUtil.h" |
|
25 #include "nsIStringBundle.h" |
|
26 #include "nsIPrintSettingsService.h" |
|
27 #include "nsIDOMWindow.h" |
|
28 #include "nsPIDOMWindow.h" |
|
29 #include "nsIBaseWindow.h" |
|
30 #include "nsIDocShellTreeItem.h" |
|
31 #include "nsIDocShell.h" |
|
32 #include "WidgetUtils.h" |
|
33 |
|
34 using namespace mozilla; |
|
35 using namespace mozilla::widget; |
|
36 |
|
37 static const char header_footer_tags[][4] = {"", "&T", "&U", "&D", "&P", "&PT"}; |
|
38 |
|
39 #define CUSTOM_VALUE_INDEX gint(ArrayLength(header_footer_tags)) |
|
40 |
|
41 static GtkWindow * |
|
42 get_gtk_window_for_nsiwidget(nsIWidget *widget) |
|
43 { |
|
44 return GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); |
|
45 } |
|
46 |
|
47 static void |
|
48 ShowCustomDialog(GtkComboBox *changed_box, gpointer user_data) |
|
49 { |
|
50 if (gtk_combo_box_get_active(changed_box) != CUSTOM_VALUE_INDEX) { |
|
51 g_object_set_data(G_OBJECT(changed_box), "previous-active", GINT_TO_POINTER(gtk_combo_box_get_active(changed_box))); |
|
52 return; |
|
53 } |
|
54 |
|
55 GtkWindow* printDialog = GTK_WINDOW(user_data); |
|
56 nsCOMPtr<nsIStringBundleService> bundleSvc = |
|
57 do_GetService(NS_STRINGBUNDLE_CONTRACTID); |
|
58 |
|
59 nsCOMPtr<nsIStringBundle> printBundle; |
|
60 bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle)); |
|
61 nsXPIDLString intlString; |
|
62 |
|
63 printBundle->GetStringFromName(MOZ_UTF16("headerFooterCustom"), getter_Copies(intlString)); |
|
64 GtkWidget* prompt_dialog = gtk_dialog_new_with_buttons(NS_ConvertUTF16toUTF8(intlString).get(), printDialog, |
|
65 #if (MOZ_WIDGET_GTK == 2) |
|
66 (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR), |
|
67 #else |
|
68 (GtkDialogFlags)(GTK_DIALOG_MODAL), |
|
69 #endif |
|
70 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, |
|
71 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
|
72 nullptr); |
|
73 gtk_dialog_set_default_response(GTK_DIALOG(prompt_dialog), GTK_RESPONSE_ACCEPT); |
|
74 gtk_dialog_set_alternative_button_order(GTK_DIALOG(prompt_dialog), |
|
75 GTK_RESPONSE_ACCEPT, |
|
76 GTK_RESPONSE_REJECT, |
|
77 -1); |
|
78 |
|
79 printBundle->GetStringFromName(MOZ_UTF16("customHeaderFooterPrompt"), getter_Copies(intlString)); |
|
80 GtkWidget* custom_label = gtk_label_new(NS_ConvertUTF16toUTF8(intlString).get()); |
|
81 GtkWidget* custom_entry = gtk_entry_new(); |
|
82 GtkWidget* question_icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); |
|
83 |
|
84 // To be convenient, prefill the textbox with the existing value, if any, and select it all so they can easily |
|
85 // both edit it and type in a new one. |
|
86 const char* current_text = (const char*) g_object_get_data(G_OBJECT(changed_box), "custom-text"); |
|
87 if (current_text) { |
|
88 gtk_entry_set_text(GTK_ENTRY(custom_entry), current_text); |
|
89 gtk_editable_select_region(GTK_EDITABLE(custom_entry), 0, -1); |
|
90 } |
|
91 gtk_entry_set_activates_default(GTK_ENTRY(custom_entry), TRUE); |
|
92 |
|
93 GtkWidget* custom_vbox = gtk_vbox_new(TRUE, 2); |
|
94 gtk_box_pack_start(GTK_BOX(custom_vbox), custom_label, FALSE, FALSE, 0); |
|
95 gtk_box_pack_start(GTK_BOX(custom_vbox), custom_entry, FALSE, FALSE, 5); // Make entry 5px underneath label |
|
96 GtkWidget* custom_hbox = gtk_hbox_new(FALSE, 2); |
|
97 gtk_box_pack_start(GTK_BOX(custom_hbox), question_icon, FALSE, FALSE, 0); |
|
98 gtk_box_pack_start(GTK_BOX(custom_hbox), custom_vbox, FALSE, FALSE, 10); // Make question icon 10px away from content |
|
99 gtk_container_set_border_width(GTK_CONTAINER(custom_hbox), 2); |
|
100 gtk_widget_show_all(custom_hbox); |
|
101 |
|
102 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(prompt_dialog))), |
|
103 custom_hbox, FALSE, FALSE, 0); |
|
104 gint diag_response = gtk_dialog_run(GTK_DIALOG(prompt_dialog)); |
|
105 |
|
106 if (diag_response == GTK_RESPONSE_ACCEPT) { |
|
107 const gchar* response_text = gtk_entry_get_text(GTK_ENTRY(custom_entry)); |
|
108 g_object_set_data_full(G_OBJECT(changed_box), "custom-text", strdup(response_text), (GDestroyNotify) free); |
|
109 g_object_set_data(G_OBJECT(changed_box), "previous-active", GINT_TO_POINTER(CUSTOM_VALUE_INDEX)); |
|
110 } else { |
|
111 // Go back to the previous index |
|
112 gint previous_active = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(changed_box), "previous-active")); |
|
113 gtk_combo_box_set_active(changed_box, previous_active); |
|
114 } |
|
115 |
|
116 gtk_widget_destroy(prompt_dialog); |
|
117 } |
|
118 |
|
119 class nsPrintDialogWidgetGTK { |
|
120 public: |
|
121 nsPrintDialogWidgetGTK(nsIDOMWindow *aParent, nsIPrintSettings *aPrintSettings); |
|
122 ~nsPrintDialogWidgetGTK() { gtk_widget_destroy(dialog); } |
|
123 NS_ConvertUTF16toUTF8 GetUTF8FromBundle(const char* aKey); |
|
124 const gint Run(); |
|
125 |
|
126 nsresult ImportSettings(nsIPrintSettings *aNSSettings); |
|
127 nsresult ExportSettings(nsIPrintSettings *aNSSettings); |
|
128 |
|
129 private: |
|
130 GtkWidget* dialog; |
|
131 GtkWidget* radio_as_laid_out; |
|
132 GtkWidget* radio_selected_frame; |
|
133 GtkWidget* radio_separate_frames; |
|
134 GtkWidget* shrink_to_fit_toggle; |
|
135 GtkWidget* print_bg_colors_toggle; |
|
136 GtkWidget* print_bg_images_toggle; |
|
137 GtkWidget* selection_only_toggle; |
|
138 GtkWidget* header_dropdown[3]; // {left, center, right} |
|
139 GtkWidget* footer_dropdown[3]; |
|
140 |
|
141 nsCOMPtr<nsIStringBundle> printBundle; |
|
142 |
|
143 bool useNativeSelection; |
|
144 |
|
145 GtkWidget* ConstructHeaderFooterDropdown(const char16_t *currentString); |
|
146 const char* OptionWidgetToString(GtkWidget *dropdown); |
|
147 |
|
148 /* Code to copy between GTK and NS print settings structures. |
|
149 * In the following, |
|
150 * "Import" means to copy from NS to GTK |
|
151 * "Export" means to copy from GTK to NS |
|
152 */ |
|
153 void ExportFramePrinting(nsIPrintSettings *aNS, GtkPrintSettings *aSettings); |
|
154 void ExportHeaderFooter(nsIPrintSettings *aNS); |
|
155 }; |
|
156 |
|
157 nsPrintDialogWidgetGTK::nsPrintDialogWidgetGTK(nsIDOMWindow *aParent, nsIPrintSettings *aSettings) |
|
158 { |
|
159 nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent); |
|
160 NS_ASSERTION(widget, "Need a widget for dialog to be modal."); |
|
161 GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(widget); |
|
162 NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal."); |
|
163 |
|
164 nsCOMPtr<nsIStringBundleService> bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); |
|
165 bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle)); |
|
166 |
|
167 dialog = gtk_print_unix_dialog_new(GetUTF8FromBundle("printTitleGTK").get(), gtkParent); |
|
168 |
|
169 gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog), |
|
170 GtkPrintCapabilities( |
|
171 GTK_PRINT_CAPABILITY_PAGE_SET |
|
172 | GTK_PRINT_CAPABILITY_COPIES |
|
173 | GTK_PRINT_CAPABILITY_COLLATE |
|
174 | GTK_PRINT_CAPABILITY_REVERSE |
|
175 | GTK_PRINT_CAPABILITY_SCALE |
|
176 | GTK_PRINT_CAPABILITY_GENERATE_PDF |
|
177 | GTK_PRINT_CAPABILITY_GENERATE_PS |
|
178 ) |
|
179 ); |
|
180 |
|
181 // The vast majority of magic numbers in this widget construction are padding. e.g. for |
|
182 // the set_border_width below, 12px matches that of just about every other window. |
|
183 GtkWidget* custom_options_tab = gtk_vbox_new(FALSE, 0); |
|
184 gtk_container_set_border_width(GTK_CONTAINER(custom_options_tab), 12); |
|
185 GtkWidget* tab_label = gtk_label_new(GetUTF8FromBundle("optionsTabLabelGTK").get()); |
|
186 |
|
187 int16_t frameUIFlag; |
|
188 aSettings->GetHowToEnableFrameUI(&frameUIFlag); |
|
189 radio_as_laid_out = gtk_radio_button_new_with_mnemonic(nullptr, GetUTF8FromBundle("asLaidOut").get()); |
|
190 if (frameUIFlag == nsIPrintSettings::kFrameEnableNone) |
|
191 gtk_widget_set_sensitive(radio_as_laid_out, FALSE); |
|
192 |
|
193 radio_selected_frame = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out), |
|
194 GetUTF8FromBundle("selectedFrame").get()); |
|
195 if (frameUIFlag == nsIPrintSettings::kFrameEnableNone || |
|
196 frameUIFlag == nsIPrintSettings::kFrameEnableAsIsAndEach) |
|
197 gtk_widget_set_sensitive(radio_selected_frame, FALSE); |
|
198 |
|
199 radio_separate_frames = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out), |
|
200 GetUTF8FromBundle("separateFrames").get()); |
|
201 if (frameUIFlag == nsIPrintSettings::kFrameEnableNone) |
|
202 gtk_widget_set_sensitive(radio_separate_frames, FALSE); |
|
203 |
|
204 // "Print Frames" options label, bold and center-aligned |
|
205 GtkWidget* print_frames_label = gtk_label_new(nullptr); |
|
206 char* pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("printFramesTitleGTK").get()); |
|
207 gtk_label_set_markup(GTK_LABEL(print_frames_label), pangoMarkup); |
|
208 g_free(pangoMarkup); |
|
209 gtk_misc_set_alignment(GTK_MISC(print_frames_label), 0, 0); |
|
210 |
|
211 // Align the radio buttons slightly so they appear to fall under the aforementioned label as per the GNOME HIG |
|
212 GtkWidget* frames_radio_container = gtk_alignment_new(0, 0, 0, 0); |
|
213 gtk_alignment_set_padding(GTK_ALIGNMENT(frames_radio_container), 8, 0, 12, 0); |
|
214 |
|
215 // Radio buttons for the print frames options |
|
216 GtkWidget* frames_radio_list = gtk_vbox_new(TRUE, 2); |
|
217 gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_as_laid_out, FALSE, FALSE, 0); |
|
218 gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_selected_frame, FALSE, FALSE, 0); |
|
219 gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_separate_frames, FALSE, FALSE, 0); |
|
220 gtk_container_add(GTK_CONTAINER(frames_radio_container), frames_radio_list); |
|
221 |
|
222 // Check buttons for shrink-to-fit and print selection |
|
223 GtkWidget* check_buttons_container = gtk_vbox_new(TRUE, 2); |
|
224 shrink_to_fit_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("shrinkToFit").get()); |
|
225 gtk_box_pack_start(GTK_BOX(check_buttons_container), shrink_to_fit_toggle, FALSE, FALSE, 0); |
|
226 |
|
227 // GTK+2.18 and above allow us to add a "Selection" option to the main settings screen, |
|
228 // rather than adding an option on a custom tab like we must do on older versions. |
|
229 bool canSelectText; |
|
230 aSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &canSelectText); |
|
231 if (gtk_major_version > 2 || |
|
232 (gtk_major_version == 2 && gtk_minor_version >= 18)) { |
|
233 useNativeSelection = true; |
|
234 g_object_set(dialog, |
|
235 "support-selection", TRUE, |
|
236 "has-selection", canSelectText, |
|
237 "embed-page-setup", TRUE, |
|
238 nullptr); |
|
239 } else { |
|
240 useNativeSelection = false; |
|
241 selection_only_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("selectionOnly").get()); |
|
242 gtk_widget_set_sensitive(selection_only_toggle, canSelectText); |
|
243 gtk_box_pack_start(GTK_BOX(check_buttons_container), selection_only_toggle, FALSE, FALSE, 0); |
|
244 } |
|
245 |
|
246 // Check buttons for printing background |
|
247 GtkWidget* appearance_buttons_container = gtk_vbox_new(TRUE, 2); |
|
248 print_bg_colors_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGColors").get()); |
|
249 print_bg_images_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGImages").get()); |
|
250 gtk_box_pack_start(GTK_BOX(appearance_buttons_container), print_bg_colors_toggle, FALSE, FALSE, 0); |
|
251 gtk_box_pack_start(GTK_BOX(appearance_buttons_container), print_bg_images_toggle, FALSE, FALSE, 0); |
|
252 |
|
253 // "Appearance" options label, bold and center-aligned |
|
254 GtkWidget* appearance_label = gtk_label_new(nullptr); |
|
255 pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("printBGOptions").get()); |
|
256 gtk_label_set_markup(GTK_LABEL(appearance_label), pangoMarkup); |
|
257 g_free(pangoMarkup); |
|
258 gtk_misc_set_alignment(GTK_MISC(appearance_label), 0, 0); |
|
259 |
|
260 GtkWidget* appearance_container = gtk_alignment_new(0, 0, 0, 0); |
|
261 gtk_alignment_set_padding(GTK_ALIGNMENT(appearance_container), 8, 0, 12, 0); |
|
262 gtk_container_add(GTK_CONTAINER(appearance_container), appearance_buttons_container); |
|
263 |
|
264 GtkWidget* appearance_vertical_squasher = gtk_vbox_new(FALSE, 0); |
|
265 gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher), appearance_label, FALSE, FALSE, 0); |
|
266 gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher), appearance_container, FALSE, FALSE, 0); |
|
267 |
|
268 // "Header & Footer" options label, bold and center-aligned |
|
269 GtkWidget* header_footer_label = gtk_label_new(nullptr); |
|
270 pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("headerFooter").get()); |
|
271 gtk_label_set_markup(GTK_LABEL(header_footer_label), pangoMarkup); |
|
272 g_free(pangoMarkup); |
|
273 gtk_misc_set_alignment(GTK_MISC(header_footer_label), 0, 0); |
|
274 |
|
275 GtkWidget* header_footer_container = gtk_alignment_new(0, 0, 0, 0); |
|
276 gtk_alignment_set_padding(GTK_ALIGNMENT(header_footer_container), 8, 0, 12, 0); |
|
277 |
|
278 |
|
279 // --- Table for making the header and footer options --- |
|
280 GtkWidget* header_footer_table = gtk_table_new(3, 3, FALSE); // 3x3 table |
|
281 nsXPIDLString header_footer_str[3]; |
|
282 |
|
283 aSettings->GetHeaderStrLeft(getter_Copies(header_footer_str[0])); |
|
284 aSettings->GetHeaderStrCenter(getter_Copies(header_footer_str[1])); |
|
285 aSettings->GetHeaderStrRight(getter_Copies(header_footer_str[2])); |
|
286 |
|
287 for (unsigned int i = 0; i < ArrayLength(header_dropdown); i++) { |
|
288 header_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get()); |
|
289 // Those 4 magic numbers in the middle provide the position in the table. |
|
290 // The last two numbers mean 2 px padding on every side. |
|
291 gtk_table_attach(GTK_TABLE(header_footer_table), header_dropdown[i], i, (i + 1), |
|
292 0, 1, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); |
|
293 } |
|
294 |
|
295 const char labelKeys[][7] = {"left", "center", "right"}; |
|
296 for (unsigned int i = 0; i < ArrayLength(labelKeys); i++) { |
|
297 gtk_table_attach(GTK_TABLE(header_footer_table), |
|
298 gtk_label_new(GetUTF8FromBundle(labelKeys[i]).get()), |
|
299 i, (i + 1), 1, 2, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); |
|
300 } |
|
301 |
|
302 aSettings->GetFooterStrLeft(getter_Copies(header_footer_str[0])); |
|
303 aSettings->GetFooterStrCenter(getter_Copies(header_footer_str[1])); |
|
304 aSettings->GetFooterStrRight(getter_Copies(header_footer_str[2])); |
|
305 |
|
306 for (unsigned int i = 0; i < ArrayLength(footer_dropdown); i++) { |
|
307 footer_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get()); |
|
308 gtk_table_attach(GTK_TABLE(header_footer_table), footer_dropdown[i], i, (i + 1), |
|
309 2, 3, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); |
|
310 } |
|
311 // --- |
|
312 |
|
313 gtk_container_add(GTK_CONTAINER(header_footer_container), header_footer_table); |
|
314 |
|
315 GtkWidget* header_footer_vertical_squasher = gtk_vbox_new(FALSE, 0); |
|
316 gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher), header_footer_label, FALSE, FALSE, 0); |
|
317 gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher), header_footer_container, FALSE, FALSE, 0); |
|
318 |
|
319 // Construction of everything |
|
320 gtk_box_pack_start(GTK_BOX(custom_options_tab), print_frames_label, FALSE, FALSE, 0); |
|
321 gtk_box_pack_start(GTK_BOX(custom_options_tab), frames_radio_container, FALSE, FALSE, 0); |
|
322 gtk_box_pack_start(GTK_BOX(custom_options_tab), check_buttons_container, FALSE, FALSE, 10); // 10px padding |
|
323 gtk_box_pack_start(GTK_BOX(custom_options_tab), appearance_vertical_squasher, FALSE, FALSE, 10); |
|
324 gtk_box_pack_start(GTK_BOX(custom_options_tab), header_footer_vertical_squasher, FALSE, FALSE, 0); |
|
325 |
|
326 gtk_print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(dialog), custom_options_tab, tab_label); |
|
327 gtk_widget_show_all(custom_options_tab); |
|
328 } |
|
329 |
|
330 NS_ConvertUTF16toUTF8 |
|
331 nsPrintDialogWidgetGTK::GetUTF8FromBundle(const char *aKey) |
|
332 { |
|
333 nsXPIDLString intlString; |
|
334 printBundle->GetStringFromName(NS_ConvertUTF8toUTF16(aKey).get(), getter_Copies(intlString)); |
|
335 return NS_ConvertUTF16toUTF8(intlString); // Return the actual object so we don't lose reference |
|
336 } |
|
337 |
|
338 const char* |
|
339 nsPrintDialogWidgetGTK::OptionWidgetToString(GtkWidget *dropdown) |
|
340 { |
|
341 gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(dropdown)); |
|
342 |
|
343 NS_ASSERTION(index <= CUSTOM_VALUE_INDEX, "Index of dropdown is higher than expected!"); |
|
344 |
|
345 if (index == CUSTOM_VALUE_INDEX) |
|
346 return (const char*) g_object_get_data(G_OBJECT(dropdown), "custom-text"); |
|
347 else |
|
348 return header_footer_tags[index]; |
|
349 } |
|
350 |
|
351 const gint |
|
352 nsPrintDialogWidgetGTK::Run() |
|
353 { |
|
354 const gint response = gtk_dialog_run(GTK_DIALOG(dialog)); |
|
355 gtk_widget_hide(dialog); |
|
356 return response; |
|
357 } |
|
358 |
|
359 void |
|
360 nsPrintDialogWidgetGTK::ExportFramePrinting(nsIPrintSettings *aNS, GtkPrintSettings *aSettings) |
|
361 { |
|
362 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_as_laid_out))) |
|
363 aNS->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); |
|
364 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_selected_frame))) |
|
365 aNS->SetPrintFrameType(nsIPrintSettings::kSelectedFrame); |
|
366 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_separate_frames))) |
|
367 aNS->SetPrintFrameType(nsIPrintSettings::kEachFrameSep); |
|
368 else |
|
369 aNS->SetPrintFrameType(nsIPrintSettings::kNoFrames); |
|
370 } |
|
371 |
|
372 void |
|
373 nsPrintDialogWidgetGTK::ExportHeaderFooter(nsIPrintSettings *aNS) |
|
374 { |
|
375 const char* header_footer_str; |
|
376 header_footer_str = OptionWidgetToString(header_dropdown[0]); |
|
377 aNS->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get()); |
|
378 |
|
379 header_footer_str = OptionWidgetToString(header_dropdown[1]); |
|
380 aNS->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get()); |
|
381 |
|
382 header_footer_str = OptionWidgetToString(header_dropdown[2]); |
|
383 aNS->SetHeaderStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get()); |
|
384 |
|
385 header_footer_str = OptionWidgetToString(footer_dropdown[0]); |
|
386 aNS->SetFooterStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get()); |
|
387 |
|
388 header_footer_str = OptionWidgetToString(footer_dropdown[1]); |
|
389 aNS->SetFooterStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get()); |
|
390 |
|
391 header_footer_str = OptionWidgetToString(footer_dropdown[2]); |
|
392 aNS->SetFooterStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get()); |
|
393 } |
|
394 |
|
395 nsresult |
|
396 nsPrintDialogWidgetGTK::ImportSettings(nsIPrintSettings *aNSSettings) |
|
397 { |
|
398 NS_PRECONDITION(aNSSettings, "aSettings must not be null"); |
|
399 NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); |
|
400 |
|
401 nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings)); |
|
402 if (!aNSSettingsGTK) |
|
403 return NS_ERROR_FAILURE; |
|
404 |
|
405 GtkPrintSettings* settings = aNSSettingsGTK->GetGtkPrintSettings(); |
|
406 GtkPageSetup* setup = aNSSettingsGTK->GetGtkPageSetup(); |
|
407 |
|
408 bool geckoBool; |
|
409 aNSSettings->GetShrinkToFit(&geckoBool); |
|
410 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle), geckoBool); |
|
411 |
|
412 aNSSettings->GetPrintBGColors(&geckoBool); |
|
413 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle), geckoBool); |
|
414 |
|
415 aNSSettings->GetPrintBGImages(&geckoBool); |
|
416 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle), geckoBool); |
|
417 |
|
418 gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog), settings); |
|
419 gtk_print_unix_dialog_set_page_setup(GTK_PRINT_UNIX_DIALOG(dialog), setup); |
|
420 |
|
421 return NS_OK; |
|
422 } |
|
423 |
|
424 nsresult |
|
425 nsPrintDialogWidgetGTK::ExportSettings(nsIPrintSettings *aNSSettings) |
|
426 { |
|
427 NS_PRECONDITION(aNSSettings, "aSettings must not be null"); |
|
428 NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); |
|
429 |
|
430 GtkPrintSettings* settings = gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog)); |
|
431 GtkPageSetup* setup = gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog)); |
|
432 GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(dialog)); |
|
433 if (settings && setup && printer) { |
|
434 ExportFramePrinting(aNSSettings, settings); |
|
435 ExportHeaderFooter(aNSSettings); |
|
436 |
|
437 aNSSettings->SetOutputFormat(nsIPrintSettings::kOutputFormatNative); |
|
438 |
|
439 // Print-to-file is true by default. This must be turned off or else printing won't occur! |
|
440 // (We manually copy the spool file when this flag is set, because we love our embedders) |
|
441 // Even if it is print-to-file in GTK's case, GTK does The Right Thing when we send the job. |
|
442 aNSSettings->SetPrintToFile(false); |
|
443 |
|
444 aNSSettings->SetShrinkToFit(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle))); |
|
445 |
|
446 aNSSettings->SetPrintBGColors(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle))); |
|
447 aNSSettings->SetPrintBGImages(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle))); |
|
448 |
|
449 // Try to save native settings in the session object |
|
450 nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings)); |
|
451 if (aNSSettingsGTK) { |
|
452 aNSSettingsGTK->SetGtkPrintSettings(settings); |
|
453 aNSSettingsGTK->SetGtkPageSetup(setup); |
|
454 aNSSettingsGTK->SetGtkPrinter(printer); |
|
455 bool printSelectionOnly; |
|
456 if (useNativeSelection) { |
|
457 _GtkPrintPages pageSetting = (_GtkPrintPages)gtk_print_settings_get_print_pages(settings); |
|
458 printSelectionOnly = (pageSetting == _GTK_PRINT_PAGES_SELECTION); |
|
459 } else { |
|
460 printSelectionOnly = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(selection_only_toggle)); |
|
461 } |
|
462 aNSSettingsGTK->SetForcePrintSelectionOnly(printSelectionOnly); |
|
463 } |
|
464 } |
|
465 |
|
466 if (settings) |
|
467 g_object_unref(settings); |
|
468 return NS_OK; |
|
469 } |
|
470 |
|
471 GtkWidget* |
|
472 nsPrintDialogWidgetGTK::ConstructHeaderFooterDropdown(const char16_t *currentString) |
|
473 { |
|
474 #if (MOZ_WIDGET_GTK == 2) |
|
475 GtkWidget* dropdown = gtk_combo_box_new_text(); |
|
476 #else |
|
477 GtkWidget* dropdown = gtk_combo_box_text_new(); |
|
478 #endif |
|
479 const char hf_options[][22] = {"headerFooterBlank", "headerFooterTitle", |
|
480 "headerFooterURL", "headerFooterDate", |
|
481 "headerFooterPage", "headerFooterPageTotal", |
|
482 "headerFooterCustom"}; |
|
483 |
|
484 for (unsigned int i = 0; i < ArrayLength(hf_options); i++) { |
|
485 #if (MOZ_WIDGET_GTK == 2) |
|
486 gtk_combo_box_append_text(GTK_COMBO_BOX(dropdown), GetUTF8FromBundle(hf_options[i]).get()); |
|
487 #else |
|
488 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(dropdown), nullptr, |
|
489 GetUTF8FromBundle(hf_options[i]).get()); |
|
490 #endif |
|
491 } |
|
492 |
|
493 bool shouldBeCustom = true; |
|
494 NS_ConvertUTF16toUTF8 currentStringUTF8(currentString); |
|
495 |
|
496 for (unsigned int i = 0; i < ArrayLength(header_footer_tags); i++) { |
|
497 if (!strcmp(currentStringUTF8.get(), header_footer_tags[i])) { |
|
498 gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), i); |
|
499 g_object_set_data(G_OBJECT(dropdown), "previous-active", GINT_TO_POINTER(i)); |
|
500 shouldBeCustom = false; |
|
501 break; |
|
502 } |
|
503 } |
|
504 |
|
505 if (shouldBeCustom) { |
|
506 gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), CUSTOM_VALUE_INDEX); |
|
507 g_object_set_data(G_OBJECT(dropdown), "previous-active", GINT_TO_POINTER(CUSTOM_VALUE_INDEX)); |
|
508 char* custom_string = strdup(currentStringUTF8.get()); |
|
509 g_object_set_data_full(G_OBJECT(dropdown), "custom-text", custom_string, (GDestroyNotify) free); |
|
510 } |
|
511 |
|
512 g_signal_connect(dropdown, "changed", (GCallback) ShowCustomDialog, dialog); |
|
513 return dropdown; |
|
514 } |
|
515 |
|
516 NS_IMPL_ISUPPORTS(nsPrintDialogServiceGTK, nsIPrintDialogService) |
|
517 |
|
518 nsPrintDialogServiceGTK::nsPrintDialogServiceGTK() |
|
519 { |
|
520 } |
|
521 |
|
522 nsPrintDialogServiceGTK::~nsPrintDialogServiceGTK() |
|
523 { |
|
524 } |
|
525 |
|
526 NS_IMETHODIMP |
|
527 nsPrintDialogServiceGTK::Init() |
|
528 { |
|
529 return NS_OK; |
|
530 } |
|
531 |
|
532 NS_IMETHODIMP |
|
533 nsPrintDialogServiceGTK::Show(nsIDOMWindow *aParent, nsIPrintSettings *aSettings, |
|
534 nsIWebBrowserPrint *aWebBrowserPrint) |
|
535 { |
|
536 NS_PRECONDITION(aParent, "aParent must not be null"); |
|
537 NS_PRECONDITION(aSettings, "aSettings must not be null"); |
|
538 |
|
539 nsPrintDialogWidgetGTK printDialog(aParent, aSettings); |
|
540 nsresult rv = printDialog.ImportSettings(aSettings); |
|
541 |
|
542 NS_ENSURE_SUCCESS(rv, rv); |
|
543 |
|
544 const gint response = printDialog.Run(); |
|
545 |
|
546 // Handle the result |
|
547 switch (response) { |
|
548 case GTK_RESPONSE_OK: // Proceed |
|
549 rv = printDialog.ExportSettings(aSettings); |
|
550 break; |
|
551 |
|
552 case GTK_RESPONSE_CANCEL: |
|
553 case GTK_RESPONSE_CLOSE: |
|
554 case GTK_RESPONSE_DELETE_EVENT: |
|
555 case GTK_RESPONSE_NONE: |
|
556 rv = NS_ERROR_ABORT; |
|
557 break; |
|
558 |
|
559 case GTK_RESPONSE_APPLY: // Print preview |
|
560 default: |
|
561 NS_WARNING("Unexpected response"); |
|
562 rv = NS_ERROR_ABORT; |
|
563 } |
|
564 return rv; |
|
565 } |
|
566 |
|
567 NS_IMETHODIMP |
|
568 nsPrintDialogServiceGTK::ShowPageSetup(nsIDOMWindow *aParent, |
|
569 nsIPrintSettings *aNSSettings) |
|
570 { |
|
571 NS_PRECONDITION(aParent, "aParent must not be null"); |
|
572 NS_PRECONDITION(aNSSettings, "aSettings must not be null"); |
|
573 NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); |
|
574 |
|
575 nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent); |
|
576 NS_ASSERTION(widget, "Need a widget for dialog to be modal."); |
|
577 GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(widget); |
|
578 NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal."); |
|
579 |
|
580 nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings)); |
|
581 if (!aNSSettingsGTK) |
|
582 return NS_ERROR_FAILURE; |
|
583 |
|
584 // We need to init the prefs here because aNSSettings in its current form is a dummy in both uses of the word |
|
585 nsCOMPtr<nsIPrintSettingsService> psService = do_GetService("@mozilla.org/gfx/printsettings-service;1"); |
|
586 if (psService) { |
|
587 nsXPIDLString printName; |
|
588 aNSSettings->GetPrinterName(getter_Copies(printName)); |
|
589 if (!printName) { |
|
590 psService->GetDefaultPrinterName(getter_Copies(printName)); |
|
591 aNSSettings->SetPrinterName(printName.get()); |
|
592 } |
|
593 psService->InitPrintSettingsFromPrefs(aNSSettings, true, nsIPrintSettings::kInitSaveAll); |
|
594 } |
|
595 |
|
596 GtkPrintSettings* gtkSettings = aNSSettingsGTK->GetGtkPrintSettings(); |
|
597 GtkPageSetup* oldPageSetup = aNSSettingsGTK->GetGtkPageSetup(); |
|
598 |
|
599 GtkPageSetup* newPageSetup = gtk_print_run_page_setup_dialog(gtkParent, oldPageSetup, gtkSettings); |
|
600 |
|
601 aNSSettingsGTK->SetGtkPageSetup(newPageSetup); |
|
602 |
|
603 // Now newPageSetup has a refcount of 2 (SetGtkPageSetup will addref), put it to 1 so if |
|
604 // this gets replaced we don't leak. |
|
605 g_object_unref(newPageSetup); |
|
606 |
|
607 if (psService) |
|
608 psService->SavePrintSettingsToPrefs(aNSSettings, true, nsIPrintSettings::kInitSaveAll); |
|
609 |
|
610 return NS_OK; |
|
611 } |