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/. */
7 #if (MOZ_WIDGET_GTK == 2)
8 #include <gtk/gtkprintunixdialog.h>
10 #include <gtk/gtkunixprint.h>
14 #include "mozilla/Util.h"
16 #include "mozcontainer.h"
17 #include "nsIPrintSettings.h"
18 #include "nsIWidget.h"
19 #include "nsPrintDialogGTK.h"
20 #include "nsPrintSettingsGTK.h"
22 #include "nsReadableUtils.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"
34 using namespace mozilla
;
35 using namespace mozilla::widget
;
37 static const char header_footer_tags
[][4] = {"", "&T", "&U", "&D", "&P", "&PT"};
39 #define CUSTOM_VALUE_INDEX gint(ArrayLength(header_footer_tags))
42 get_gtk_window_for_nsiwidget(nsIWidget
*widget
)
44 return GTK_WINDOW(widget
->GetNativeData(NS_NATIVE_SHELLWIDGET
));
48 ShowCustomDialog(GtkComboBox
*changed_box
, gpointer user_data
)
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
)));
55 GtkWindow
* printDialog
= GTK_WINDOW(user_data
);
56 nsCOMPtr
<nsIStringBundleService
> bundleSvc
=
57 do_GetService(NS_STRINGBUNDLE_CONTRACTID
);
59 nsCOMPtr
<nsIStringBundle
> printBundle
;
60 bundleSvc
->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle
));
61 nsXPIDLString intlString
;
63 printBundle
->GetStringFromName(NS_LITERAL_STRING("headerFooterCustom").get(), 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
),
68 (GtkDialogFlags
)(GTK_DIALOG_MODAL
),
70 GTK_STOCK_CANCEL
, GTK_RESPONSE_REJECT
,
71 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
73 gtk_dialog_set_default_response(GTK_DIALOG(prompt_dialog
), GTK_RESPONSE_ACCEPT
);
74 gtk_dialog_set_alternative_button_order(GTK_DIALOG(prompt_dialog
),
79 printBundle
->GetStringFromName(NS_LITERAL_STRING("customHeaderFooterPrompt").get(), 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
);
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");
88 gtk_entry_set_text(GTK_ENTRY(custom_entry
), current_text
);
89 gtk_editable_select_region(GTK_EDITABLE(custom_entry
), 0, -1);
91 gtk_entry_set_activates_default(GTK_ENTRY(custom_entry
), TRUE
);
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
);
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
));
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
));
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
);
116 gtk_widget_destroy(prompt_dialog
);
119 class nsPrintDialogWidgetGTK
{
121 nsPrintDialogWidgetGTK(nsIDOMWindow
*aParent
, nsIPrintSettings
*aPrintSettings
);
122 ~nsPrintDialogWidgetGTK() { gtk_widget_destroy(dialog
); }
123 NS_ConvertUTF16toUTF8
GetUTF8FromBundle(const char* aKey
);
126 nsresult
ImportSettings(nsIPrintSettings
*aNSSettings
);
127 nsresult
ExportSettings(nsIPrintSettings
*aNSSettings
);
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];
141 nsCOMPtr
<nsIStringBundle
> printBundle
;
143 bool useNativeSelection
;
145 GtkWidget
* ConstructHeaderFooterDropdown(const PRUnichar
*currentString
);
146 const char* OptionWidgetToString(GtkWidget
*dropdown
);
148 /* Code to copy between GTK and NS print settings structures.
150 * "Import" means to copy from NS to GTK
151 * "Export" means to copy from GTK to NS
153 void ExportFramePrinting(nsIPrintSettings
*aNS
, GtkPrintSettings
*aSettings
);
154 void ExportHeaderFooter(nsIPrintSettings
*aNS
);
157 nsPrintDialogWidgetGTK::nsPrintDialogWidgetGTK(nsIDOMWindow
*aParent
, nsIPrintSettings
*aSettings
)
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.");
164 nsCOMPtr
<nsIStringBundleService
> bundleSvc
= do_GetService(NS_STRINGBUNDLE_CONTRACTID
);
165 bundleSvc
->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle
));
167 dialog
= gtk_print_unix_dialog_new(GetUTF8FromBundle("printTitleGTK").get(), gtkParent
);
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
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());
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
);
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
);
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
);
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
);
209 gtk_misc_set_alignment(GTK_MISC(print_frames_label
), 0, 0);
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);
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
);
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);
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.
230 aSettings
->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB
, &canSelectText
);
231 if (gtk_major_version
> 2 ||
232 (gtk_major_version
== 2 && gtk_minor_version
>= 18)) {
233 useNativeSelection
= true;
235 "support-selection", TRUE
,
236 "has-selection", canSelectText
,
237 "embed-page-setup", TRUE
,
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);
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);
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
);
258 gtk_misc_set_alignment(GTK_MISC(appearance_label
), 0, 0);
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
);
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);
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
);
273 gtk_misc_set_alignment(GTK_MISC(header_footer_label
), 0, 0);
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);
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];
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]));
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);
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);
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]));
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);
313 gtk_container_add(GTK_CONTAINER(header_footer_container
), header_footer_table
);
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);
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);
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
);
330 NS_ConvertUTF16toUTF8
331 nsPrintDialogWidgetGTK::GetUTF8FromBundle(const char *aKey
)
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
339 nsPrintDialogWidgetGTK::OptionWidgetToString(GtkWidget
*dropdown
)
341 gint index
= gtk_combo_box_get_active(GTK_COMBO_BOX(dropdown
));
343 NS_ASSERTION(index
<= CUSTOM_VALUE_INDEX
, "Index of dropdown is higher than expected!");
345 if (index
== CUSTOM_VALUE_INDEX
)
346 return (const char*) g_object_get_data(G_OBJECT(dropdown
), "custom-text");
348 return header_footer_tags
[index
];
352 nsPrintDialogWidgetGTK::Run()
354 const gint response
= gtk_dialog_run(GTK_DIALOG(dialog
));
355 gtk_widget_hide(dialog
);
360 nsPrintDialogWidgetGTK::ExportFramePrinting(nsIPrintSettings
*aNS
, GtkPrintSettings
*aSettings
)
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
);
369 aNS
->SetPrintFrameType(nsIPrintSettings::kNoFrames
);
373 nsPrintDialogWidgetGTK::ExportHeaderFooter(nsIPrintSettings
*aNS
)
375 const char* header_footer_str
;
376 header_footer_str
= OptionWidgetToString(header_dropdown
[0]);
377 aNS
->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(header_footer_str
).get());
379 header_footer_str
= OptionWidgetToString(header_dropdown
[1]);
380 aNS
->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(header_footer_str
).get());
382 header_footer_str
= OptionWidgetToString(header_dropdown
[2]);
383 aNS
->SetHeaderStrRight(NS_ConvertUTF8toUTF16(header_footer_str
).get());
385 header_footer_str
= OptionWidgetToString(footer_dropdown
[0]);
386 aNS
->SetFooterStrLeft(NS_ConvertUTF8toUTF16(header_footer_str
).get());
388 header_footer_str
= OptionWidgetToString(footer_dropdown
[1]);
389 aNS
->SetFooterStrCenter(NS_ConvertUTF8toUTF16(header_footer_str
).get());
391 header_footer_str
= OptionWidgetToString(footer_dropdown
[2]);
392 aNS
->SetFooterStrRight(NS_ConvertUTF8toUTF16(header_footer_str
).get());
396 nsPrintDialogWidgetGTK::ImportSettings(nsIPrintSettings
*aNSSettings
)
398 NS_PRECONDITION(aNSSettings
, "aSettings must not be null");
399 NS_ENSURE_TRUE(aNSSettings
, NS_ERROR_FAILURE
);
401 nsCOMPtr
<nsPrintSettingsGTK
> aNSSettingsGTK(do_QueryInterface(aNSSettings
));
403 return NS_ERROR_FAILURE
;
405 GtkPrintSettings
* settings
= aNSSettingsGTK
->GetGtkPrintSettings();
406 GtkPageSetup
* setup
= aNSSettingsGTK
->GetGtkPageSetup();
409 aNSSettings
->GetShrinkToFit(&geckoBool
);
410 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle
), geckoBool
);
412 aNSSettings
->GetPrintBGColors(&geckoBool
);
413 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle
), geckoBool
);
415 aNSSettings
->GetPrintBGImages(&geckoBool
);
416 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle
), geckoBool
);
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
);
425 nsPrintDialogWidgetGTK::ExportSettings(nsIPrintSettings
*aNSSettings
)
427 NS_PRECONDITION(aNSSettings
, "aSettings must not be null");
428 NS_ENSURE_TRUE(aNSSettings
, NS_ERROR_FAILURE
);
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
);
437 aNSSettings
->SetOutputFormat(nsIPrintSettings::kOutputFormatNative
);
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);
444 aNSSettings
->SetShrinkToFit(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle
)));
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
)));
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
);
460 printSelectionOnly
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(selection_only_toggle
));
462 aNSSettingsGTK
->SetForcePrintSelectionOnly(printSelectionOnly
);
467 g_object_unref(settings
);
472 nsPrintDialogWidgetGTK::ConstructHeaderFooterDropdown(const PRUnichar
*currentString
)
474 #if (MOZ_WIDGET_GTK == 2)
475 GtkWidget
* dropdown
= gtk_combo_box_new_text();
477 GtkWidget
* dropdown
= gtk_combo_box_text_new();
479 const char hf_options
[][22] = {"headerFooterBlank", "headerFooterTitle",
480 "headerFooterURL", "headerFooterDate",
481 "headerFooterPage", "headerFooterPageTotal",
482 "headerFooterCustom"};
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());
488 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(dropdown
), nullptr,
489 GetUTF8FromBundle(hf_options
[i
]).get());
493 bool shouldBeCustom
= true;
494 NS_ConvertUTF16toUTF8
currentStringUTF8(currentString
);
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;
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
);
512 g_signal_connect(dropdown
, "changed", (GCallback
) ShowCustomDialog
, dialog
);
516 NS_IMPL_ISUPPORTS1(nsPrintDialogServiceGTK
, nsIPrintDialogService
)
518 nsPrintDialogServiceGTK::nsPrintDialogServiceGTK()
522 nsPrintDialogServiceGTK::~nsPrintDialogServiceGTK()
527 nsPrintDialogServiceGTK::Init()
533 nsPrintDialogServiceGTK::Show(nsIDOMWindow
*aParent
, nsIPrintSettings
*aSettings
,
534 nsIWebBrowserPrint
*aWebBrowserPrint
)
536 NS_PRECONDITION(aParent
, "aParent must not be null");
537 NS_PRECONDITION(aSettings
, "aSettings must not be null");
539 nsPrintDialogWidgetGTK
printDialog(aParent
, aSettings
);
540 nsresult rv
= printDialog
.ImportSettings(aSettings
);
542 NS_ENSURE_SUCCESS(rv
, rv
);
544 const gint response
= printDialog
.Run();
548 case GTK_RESPONSE_OK
: // Proceed
549 rv
= printDialog
.ExportSettings(aSettings
);
552 case GTK_RESPONSE_CANCEL
:
553 case GTK_RESPONSE_CLOSE
:
554 case GTK_RESPONSE_DELETE_EVENT
:
555 case GTK_RESPONSE_NONE
:
559 case GTK_RESPONSE_APPLY
: // Print preview
561 NS_WARNING("Unexpected response");
568 nsPrintDialogServiceGTK::ShowPageSetup(nsIDOMWindow
*aParent
,
569 nsIPrintSettings
*aNSSettings
)
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
);
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.");
580 nsCOMPtr
<nsPrintSettingsGTK
> aNSSettingsGTK(do_QueryInterface(aNSSettings
));
582 return NS_ERROR_FAILURE
;
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");
587 nsXPIDLString printName
;
588 aNSSettings
->GetPrinterName(getter_Copies(printName
));
590 psService
->GetDefaultPrinterName(getter_Copies(printName
));
591 aNSSettings
->SetPrinterName(printName
.get());
593 psService
->InitPrintSettingsFromPrefs(aNSSettings
, true, nsIPrintSettings::kInitSaveAll
);
596 GtkPrintSettings
* gtkSettings
= aNSSettingsGTK
->GetGtkPrintSettings();
597 GtkPageSetup
* oldPageSetup
= aNSSettingsGTK
->GetGtkPageSetup();
599 GtkPageSetup
* newPageSetup
= gtk_print_run_page_setup_dialog(gtkParent
, oldPageSetup
, gtkSettings
);
601 aNSSettingsGTK
->SetGtkPageSetup(newPageSetup
);
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
);
608 psService
->SavePrintSettingsToPrefs(aNSSettings
, true, nsIPrintSettings::kInitSaveAll
);