1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gtk/nsPrintDialogGTK.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,611 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <gtk/gtk.h> 1.10 +#if (MOZ_WIDGET_GTK == 2) 1.11 +#include <gtk/gtkprintunixdialog.h> 1.12 +#else 1.13 +#include <gtk/gtkunixprint.h> 1.14 +#endif 1.15 +#include <stdlib.h> 1.16 + 1.17 +#include "mozilla/ArrayUtils.h" 1.18 + 1.19 +#include "mozcontainer.h" 1.20 +#include "nsIPrintSettings.h" 1.21 +#include "nsIWidget.h" 1.22 +#include "nsPrintDialogGTK.h" 1.23 +#include "nsPrintSettingsGTK.h" 1.24 +#include "nsString.h" 1.25 +#include "nsReadableUtils.h" 1.26 +#include "nsIFile.h" 1.27 +#include "nsNetUtil.h" 1.28 +#include "nsIStringBundle.h" 1.29 +#include "nsIPrintSettingsService.h" 1.30 +#include "nsIDOMWindow.h" 1.31 +#include "nsPIDOMWindow.h" 1.32 +#include "nsIBaseWindow.h" 1.33 +#include "nsIDocShellTreeItem.h" 1.34 +#include "nsIDocShell.h" 1.35 +#include "WidgetUtils.h" 1.36 + 1.37 +using namespace mozilla; 1.38 +using namespace mozilla::widget; 1.39 + 1.40 +static const char header_footer_tags[][4] = {"", "&T", "&U", "&D", "&P", "&PT"}; 1.41 + 1.42 +#define CUSTOM_VALUE_INDEX gint(ArrayLength(header_footer_tags)) 1.43 + 1.44 +static GtkWindow * 1.45 +get_gtk_window_for_nsiwidget(nsIWidget *widget) 1.46 +{ 1.47 + return GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); 1.48 +} 1.49 + 1.50 +static void 1.51 +ShowCustomDialog(GtkComboBox *changed_box, gpointer user_data) 1.52 +{ 1.53 + if (gtk_combo_box_get_active(changed_box) != CUSTOM_VALUE_INDEX) { 1.54 + g_object_set_data(G_OBJECT(changed_box), "previous-active", GINT_TO_POINTER(gtk_combo_box_get_active(changed_box))); 1.55 + return; 1.56 + } 1.57 + 1.58 + GtkWindow* printDialog = GTK_WINDOW(user_data); 1.59 + nsCOMPtr<nsIStringBundleService> bundleSvc = 1.60 + do_GetService(NS_STRINGBUNDLE_CONTRACTID); 1.61 + 1.62 + nsCOMPtr<nsIStringBundle> printBundle; 1.63 + bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle)); 1.64 + nsXPIDLString intlString; 1.65 + 1.66 + printBundle->GetStringFromName(MOZ_UTF16("headerFooterCustom"), getter_Copies(intlString)); 1.67 + GtkWidget* prompt_dialog = gtk_dialog_new_with_buttons(NS_ConvertUTF16toUTF8(intlString).get(), printDialog, 1.68 +#if (MOZ_WIDGET_GTK == 2) 1.69 + (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR), 1.70 +#else 1.71 + (GtkDialogFlags)(GTK_DIALOG_MODAL), 1.72 +#endif 1.73 + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, 1.74 + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, 1.75 + nullptr); 1.76 + gtk_dialog_set_default_response(GTK_DIALOG(prompt_dialog), GTK_RESPONSE_ACCEPT); 1.77 + gtk_dialog_set_alternative_button_order(GTK_DIALOG(prompt_dialog), 1.78 + GTK_RESPONSE_ACCEPT, 1.79 + GTK_RESPONSE_REJECT, 1.80 + -1); 1.81 + 1.82 + printBundle->GetStringFromName(MOZ_UTF16("customHeaderFooterPrompt"), getter_Copies(intlString)); 1.83 + GtkWidget* custom_label = gtk_label_new(NS_ConvertUTF16toUTF8(intlString).get()); 1.84 + GtkWidget* custom_entry = gtk_entry_new(); 1.85 + GtkWidget* question_icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); 1.86 + 1.87 + // To be convenient, prefill the textbox with the existing value, if any, and select it all so they can easily 1.88 + // both edit it and type in a new one. 1.89 + const char* current_text = (const char*) g_object_get_data(G_OBJECT(changed_box), "custom-text"); 1.90 + if (current_text) { 1.91 + gtk_entry_set_text(GTK_ENTRY(custom_entry), current_text); 1.92 + gtk_editable_select_region(GTK_EDITABLE(custom_entry), 0, -1); 1.93 + } 1.94 + gtk_entry_set_activates_default(GTK_ENTRY(custom_entry), TRUE); 1.95 + 1.96 + GtkWidget* custom_vbox = gtk_vbox_new(TRUE, 2); 1.97 + gtk_box_pack_start(GTK_BOX(custom_vbox), custom_label, FALSE, FALSE, 0); 1.98 + gtk_box_pack_start(GTK_BOX(custom_vbox), custom_entry, FALSE, FALSE, 5); // Make entry 5px underneath label 1.99 + GtkWidget* custom_hbox = gtk_hbox_new(FALSE, 2); 1.100 + gtk_box_pack_start(GTK_BOX(custom_hbox), question_icon, FALSE, FALSE, 0); 1.101 + gtk_box_pack_start(GTK_BOX(custom_hbox), custom_vbox, FALSE, FALSE, 10); // Make question icon 10px away from content 1.102 + gtk_container_set_border_width(GTK_CONTAINER(custom_hbox), 2); 1.103 + gtk_widget_show_all(custom_hbox); 1.104 + 1.105 + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(prompt_dialog))), 1.106 + custom_hbox, FALSE, FALSE, 0); 1.107 + gint diag_response = gtk_dialog_run(GTK_DIALOG(prompt_dialog)); 1.108 + 1.109 + if (diag_response == GTK_RESPONSE_ACCEPT) { 1.110 + const gchar* response_text = gtk_entry_get_text(GTK_ENTRY(custom_entry)); 1.111 + g_object_set_data_full(G_OBJECT(changed_box), "custom-text", strdup(response_text), (GDestroyNotify) free); 1.112 + g_object_set_data(G_OBJECT(changed_box), "previous-active", GINT_TO_POINTER(CUSTOM_VALUE_INDEX)); 1.113 + } else { 1.114 + // Go back to the previous index 1.115 + gint previous_active = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(changed_box), "previous-active")); 1.116 + gtk_combo_box_set_active(changed_box, previous_active); 1.117 + } 1.118 + 1.119 + gtk_widget_destroy(prompt_dialog); 1.120 +} 1.121 + 1.122 +class nsPrintDialogWidgetGTK { 1.123 + public: 1.124 + nsPrintDialogWidgetGTK(nsIDOMWindow *aParent, nsIPrintSettings *aPrintSettings); 1.125 + ~nsPrintDialogWidgetGTK() { gtk_widget_destroy(dialog); } 1.126 + NS_ConvertUTF16toUTF8 GetUTF8FromBundle(const char* aKey); 1.127 + const gint Run(); 1.128 + 1.129 + nsresult ImportSettings(nsIPrintSettings *aNSSettings); 1.130 + nsresult ExportSettings(nsIPrintSettings *aNSSettings); 1.131 + 1.132 + private: 1.133 + GtkWidget* dialog; 1.134 + GtkWidget* radio_as_laid_out; 1.135 + GtkWidget* radio_selected_frame; 1.136 + GtkWidget* radio_separate_frames; 1.137 + GtkWidget* shrink_to_fit_toggle; 1.138 + GtkWidget* print_bg_colors_toggle; 1.139 + GtkWidget* print_bg_images_toggle; 1.140 + GtkWidget* selection_only_toggle; 1.141 + GtkWidget* header_dropdown[3]; // {left, center, right} 1.142 + GtkWidget* footer_dropdown[3]; 1.143 + 1.144 + nsCOMPtr<nsIStringBundle> printBundle; 1.145 + 1.146 + bool useNativeSelection; 1.147 + 1.148 + GtkWidget* ConstructHeaderFooterDropdown(const char16_t *currentString); 1.149 + const char* OptionWidgetToString(GtkWidget *dropdown); 1.150 + 1.151 + /* Code to copy between GTK and NS print settings structures. 1.152 + * In the following, 1.153 + * "Import" means to copy from NS to GTK 1.154 + * "Export" means to copy from GTK to NS 1.155 + */ 1.156 + void ExportFramePrinting(nsIPrintSettings *aNS, GtkPrintSettings *aSettings); 1.157 + void ExportHeaderFooter(nsIPrintSettings *aNS); 1.158 +}; 1.159 + 1.160 +nsPrintDialogWidgetGTK::nsPrintDialogWidgetGTK(nsIDOMWindow *aParent, nsIPrintSettings *aSettings) 1.161 +{ 1.162 + nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent); 1.163 + NS_ASSERTION(widget, "Need a widget for dialog to be modal."); 1.164 + GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(widget); 1.165 + NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal."); 1.166 + 1.167 + nsCOMPtr<nsIStringBundleService> bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); 1.168 + bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle)); 1.169 + 1.170 + dialog = gtk_print_unix_dialog_new(GetUTF8FromBundle("printTitleGTK").get(), gtkParent); 1.171 + 1.172 + gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog), 1.173 + GtkPrintCapabilities( 1.174 + GTK_PRINT_CAPABILITY_PAGE_SET 1.175 + | GTK_PRINT_CAPABILITY_COPIES 1.176 + | GTK_PRINT_CAPABILITY_COLLATE 1.177 + | GTK_PRINT_CAPABILITY_REVERSE 1.178 + | GTK_PRINT_CAPABILITY_SCALE 1.179 + | GTK_PRINT_CAPABILITY_GENERATE_PDF 1.180 + | GTK_PRINT_CAPABILITY_GENERATE_PS 1.181 + ) 1.182 + ); 1.183 + 1.184 + // The vast majority of magic numbers in this widget construction are padding. e.g. for 1.185 + // the set_border_width below, 12px matches that of just about every other window. 1.186 + GtkWidget* custom_options_tab = gtk_vbox_new(FALSE, 0); 1.187 + gtk_container_set_border_width(GTK_CONTAINER(custom_options_tab), 12); 1.188 + GtkWidget* tab_label = gtk_label_new(GetUTF8FromBundle("optionsTabLabelGTK").get()); 1.189 + 1.190 + int16_t frameUIFlag; 1.191 + aSettings->GetHowToEnableFrameUI(&frameUIFlag); 1.192 + radio_as_laid_out = gtk_radio_button_new_with_mnemonic(nullptr, GetUTF8FromBundle("asLaidOut").get()); 1.193 + if (frameUIFlag == nsIPrintSettings::kFrameEnableNone) 1.194 + gtk_widget_set_sensitive(radio_as_laid_out, FALSE); 1.195 + 1.196 + radio_selected_frame = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out), 1.197 + GetUTF8FromBundle("selectedFrame").get()); 1.198 + if (frameUIFlag == nsIPrintSettings::kFrameEnableNone || 1.199 + frameUIFlag == nsIPrintSettings::kFrameEnableAsIsAndEach) 1.200 + gtk_widget_set_sensitive(radio_selected_frame, FALSE); 1.201 + 1.202 + radio_separate_frames = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out), 1.203 + GetUTF8FromBundle("separateFrames").get()); 1.204 + if (frameUIFlag == nsIPrintSettings::kFrameEnableNone) 1.205 + gtk_widget_set_sensitive(radio_separate_frames, FALSE); 1.206 + 1.207 + // "Print Frames" options label, bold and center-aligned 1.208 + GtkWidget* print_frames_label = gtk_label_new(nullptr); 1.209 + char* pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("printFramesTitleGTK").get()); 1.210 + gtk_label_set_markup(GTK_LABEL(print_frames_label), pangoMarkup); 1.211 + g_free(pangoMarkup); 1.212 + gtk_misc_set_alignment(GTK_MISC(print_frames_label), 0, 0); 1.213 + 1.214 + // Align the radio buttons slightly so they appear to fall under the aforementioned label as per the GNOME HIG 1.215 + GtkWidget* frames_radio_container = gtk_alignment_new(0, 0, 0, 0); 1.216 + gtk_alignment_set_padding(GTK_ALIGNMENT(frames_radio_container), 8, 0, 12, 0); 1.217 + 1.218 + // Radio buttons for the print frames options 1.219 + GtkWidget* frames_radio_list = gtk_vbox_new(TRUE, 2); 1.220 + gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_as_laid_out, FALSE, FALSE, 0); 1.221 + gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_selected_frame, FALSE, FALSE, 0); 1.222 + gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_separate_frames, FALSE, FALSE, 0); 1.223 + gtk_container_add(GTK_CONTAINER(frames_radio_container), frames_radio_list); 1.224 + 1.225 + // Check buttons for shrink-to-fit and print selection 1.226 + GtkWidget* check_buttons_container = gtk_vbox_new(TRUE, 2); 1.227 + shrink_to_fit_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("shrinkToFit").get()); 1.228 + gtk_box_pack_start(GTK_BOX(check_buttons_container), shrink_to_fit_toggle, FALSE, FALSE, 0); 1.229 + 1.230 + // GTK+2.18 and above allow us to add a "Selection" option to the main settings screen, 1.231 + // rather than adding an option on a custom tab like we must do on older versions. 1.232 + bool canSelectText; 1.233 + aSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &canSelectText); 1.234 + if (gtk_major_version > 2 || 1.235 + (gtk_major_version == 2 && gtk_minor_version >= 18)) { 1.236 + useNativeSelection = true; 1.237 + g_object_set(dialog, 1.238 + "support-selection", TRUE, 1.239 + "has-selection", canSelectText, 1.240 + "embed-page-setup", TRUE, 1.241 + nullptr); 1.242 + } else { 1.243 + useNativeSelection = false; 1.244 + selection_only_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("selectionOnly").get()); 1.245 + gtk_widget_set_sensitive(selection_only_toggle, canSelectText); 1.246 + gtk_box_pack_start(GTK_BOX(check_buttons_container), selection_only_toggle, FALSE, FALSE, 0); 1.247 + } 1.248 + 1.249 + // Check buttons for printing background 1.250 + GtkWidget* appearance_buttons_container = gtk_vbox_new(TRUE, 2); 1.251 + print_bg_colors_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGColors").get()); 1.252 + print_bg_images_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGImages").get()); 1.253 + gtk_box_pack_start(GTK_BOX(appearance_buttons_container), print_bg_colors_toggle, FALSE, FALSE, 0); 1.254 + gtk_box_pack_start(GTK_BOX(appearance_buttons_container), print_bg_images_toggle, FALSE, FALSE, 0); 1.255 + 1.256 + // "Appearance" options label, bold and center-aligned 1.257 + GtkWidget* appearance_label = gtk_label_new(nullptr); 1.258 + pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("printBGOptions").get()); 1.259 + gtk_label_set_markup(GTK_LABEL(appearance_label), pangoMarkup); 1.260 + g_free(pangoMarkup); 1.261 + gtk_misc_set_alignment(GTK_MISC(appearance_label), 0, 0); 1.262 + 1.263 + GtkWidget* appearance_container = gtk_alignment_new(0, 0, 0, 0); 1.264 + gtk_alignment_set_padding(GTK_ALIGNMENT(appearance_container), 8, 0, 12, 0); 1.265 + gtk_container_add(GTK_CONTAINER(appearance_container), appearance_buttons_container); 1.266 + 1.267 + GtkWidget* appearance_vertical_squasher = gtk_vbox_new(FALSE, 0); 1.268 + gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher), appearance_label, FALSE, FALSE, 0); 1.269 + gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher), appearance_container, FALSE, FALSE, 0); 1.270 + 1.271 + // "Header & Footer" options label, bold and center-aligned 1.272 + GtkWidget* header_footer_label = gtk_label_new(nullptr); 1.273 + pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("headerFooter").get()); 1.274 + gtk_label_set_markup(GTK_LABEL(header_footer_label), pangoMarkup); 1.275 + g_free(pangoMarkup); 1.276 + gtk_misc_set_alignment(GTK_MISC(header_footer_label), 0, 0); 1.277 + 1.278 + GtkWidget* header_footer_container = gtk_alignment_new(0, 0, 0, 0); 1.279 + gtk_alignment_set_padding(GTK_ALIGNMENT(header_footer_container), 8, 0, 12, 0); 1.280 + 1.281 + 1.282 + // --- Table for making the header and footer options --- 1.283 + GtkWidget* header_footer_table = gtk_table_new(3, 3, FALSE); // 3x3 table 1.284 + nsXPIDLString header_footer_str[3]; 1.285 + 1.286 + aSettings->GetHeaderStrLeft(getter_Copies(header_footer_str[0])); 1.287 + aSettings->GetHeaderStrCenter(getter_Copies(header_footer_str[1])); 1.288 + aSettings->GetHeaderStrRight(getter_Copies(header_footer_str[2])); 1.289 + 1.290 + for (unsigned int i = 0; i < ArrayLength(header_dropdown); i++) { 1.291 + header_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get()); 1.292 + // Those 4 magic numbers in the middle provide the position in the table. 1.293 + // The last two numbers mean 2 px padding on every side. 1.294 + gtk_table_attach(GTK_TABLE(header_footer_table), header_dropdown[i], i, (i + 1), 1.295 + 0, 1, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); 1.296 + } 1.297 + 1.298 + const char labelKeys[][7] = {"left", "center", "right"}; 1.299 + for (unsigned int i = 0; i < ArrayLength(labelKeys); i++) { 1.300 + gtk_table_attach(GTK_TABLE(header_footer_table), 1.301 + gtk_label_new(GetUTF8FromBundle(labelKeys[i]).get()), 1.302 + i, (i + 1), 1, 2, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); 1.303 + } 1.304 + 1.305 + aSettings->GetFooterStrLeft(getter_Copies(header_footer_str[0])); 1.306 + aSettings->GetFooterStrCenter(getter_Copies(header_footer_str[1])); 1.307 + aSettings->GetFooterStrRight(getter_Copies(header_footer_str[2])); 1.308 + 1.309 + for (unsigned int i = 0; i < ArrayLength(footer_dropdown); i++) { 1.310 + footer_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get()); 1.311 + gtk_table_attach(GTK_TABLE(header_footer_table), footer_dropdown[i], i, (i + 1), 1.312 + 2, 3, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); 1.313 + } 1.314 + // --- 1.315 + 1.316 + gtk_container_add(GTK_CONTAINER(header_footer_container), header_footer_table); 1.317 + 1.318 + GtkWidget* header_footer_vertical_squasher = gtk_vbox_new(FALSE, 0); 1.319 + gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher), header_footer_label, FALSE, FALSE, 0); 1.320 + gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher), header_footer_container, FALSE, FALSE, 0); 1.321 + 1.322 + // Construction of everything 1.323 + gtk_box_pack_start(GTK_BOX(custom_options_tab), print_frames_label, FALSE, FALSE, 0); 1.324 + gtk_box_pack_start(GTK_BOX(custom_options_tab), frames_radio_container, FALSE, FALSE, 0); 1.325 + gtk_box_pack_start(GTK_BOX(custom_options_tab), check_buttons_container, FALSE, FALSE, 10); // 10px padding 1.326 + gtk_box_pack_start(GTK_BOX(custom_options_tab), appearance_vertical_squasher, FALSE, FALSE, 10); 1.327 + gtk_box_pack_start(GTK_BOX(custom_options_tab), header_footer_vertical_squasher, FALSE, FALSE, 0); 1.328 + 1.329 + gtk_print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(dialog), custom_options_tab, tab_label); 1.330 + gtk_widget_show_all(custom_options_tab); 1.331 +} 1.332 + 1.333 +NS_ConvertUTF16toUTF8 1.334 +nsPrintDialogWidgetGTK::GetUTF8FromBundle(const char *aKey) 1.335 +{ 1.336 + nsXPIDLString intlString; 1.337 + printBundle->GetStringFromName(NS_ConvertUTF8toUTF16(aKey).get(), getter_Copies(intlString)); 1.338 + return NS_ConvertUTF16toUTF8(intlString); // Return the actual object so we don't lose reference 1.339 +} 1.340 + 1.341 +const char* 1.342 +nsPrintDialogWidgetGTK::OptionWidgetToString(GtkWidget *dropdown) 1.343 +{ 1.344 + gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(dropdown)); 1.345 + 1.346 + NS_ASSERTION(index <= CUSTOM_VALUE_INDEX, "Index of dropdown is higher than expected!"); 1.347 + 1.348 + if (index == CUSTOM_VALUE_INDEX) 1.349 + return (const char*) g_object_get_data(G_OBJECT(dropdown), "custom-text"); 1.350 + else 1.351 + return header_footer_tags[index]; 1.352 +} 1.353 + 1.354 +const gint 1.355 +nsPrintDialogWidgetGTK::Run() 1.356 +{ 1.357 + const gint response = gtk_dialog_run(GTK_DIALOG(dialog)); 1.358 + gtk_widget_hide(dialog); 1.359 + return response; 1.360 +} 1.361 + 1.362 +void 1.363 +nsPrintDialogWidgetGTK::ExportFramePrinting(nsIPrintSettings *aNS, GtkPrintSettings *aSettings) 1.364 +{ 1.365 + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_as_laid_out))) 1.366 + aNS->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); 1.367 + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_selected_frame))) 1.368 + aNS->SetPrintFrameType(nsIPrintSettings::kSelectedFrame); 1.369 + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_separate_frames))) 1.370 + aNS->SetPrintFrameType(nsIPrintSettings::kEachFrameSep); 1.371 + else 1.372 + aNS->SetPrintFrameType(nsIPrintSettings::kNoFrames); 1.373 +} 1.374 + 1.375 +void 1.376 +nsPrintDialogWidgetGTK::ExportHeaderFooter(nsIPrintSettings *aNS) 1.377 +{ 1.378 + const char* header_footer_str; 1.379 + header_footer_str = OptionWidgetToString(header_dropdown[0]); 1.380 + aNS->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get()); 1.381 + 1.382 + header_footer_str = OptionWidgetToString(header_dropdown[1]); 1.383 + aNS->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get()); 1.384 + 1.385 + header_footer_str = OptionWidgetToString(header_dropdown[2]); 1.386 + aNS->SetHeaderStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get()); 1.387 + 1.388 + header_footer_str = OptionWidgetToString(footer_dropdown[0]); 1.389 + aNS->SetFooterStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get()); 1.390 + 1.391 + header_footer_str = OptionWidgetToString(footer_dropdown[1]); 1.392 + aNS->SetFooterStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get()); 1.393 + 1.394 + header_footer_str = OptionWidgetToString(footer_dropdown[2]); 1.395 + aNS->SetFooterStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get()); 1.396 +} 1.397 + 1.398 +nsresult 1.399 +nsPrintDialogWidgetGTK::ImportSettings(nsIPrintSettings *aNSSettings) 1.400 +{ 1.401 + NS_PRECONDITION(aNSSettings, "aSettings must not be null"); 1.402 + NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); 1.403 + 1.404 + nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings)); 1.405 + if (!aNSSettingsGTK) 1.406 + return NS_ERROR_FAILURE; 1.407 + 1.408 + GtkPrintSettings* settings = aNSSettingsGTK->GetGtkPrintSettings(); 1.409 + GtkPageSetup* setup = aNSSettingsGTK->GetGtkPageSetup(); 1.410 + 1.411 + bool geckoBool; 1.412 + aNSSettings->GetShrinkToFit(&geckoBool); 1.413 + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle), geckoBool); 1.414 + 1.415 + aNSSettings->GetPrintBGColors(&geckoBool); 1.416 + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle), geckoBool); 1.417 + 1.418 + aNSSettings->GetPrintBGImages(&geckoBool); 1.419 + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle), geckoBool); 1.420 + 1.421 + gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog), settings); 1.422 + gtk_print_unix_dialog_set_page_setup(GTK_PRINT_UNIX_DIALOG(dialog), setup); 1.423 + 1.424 + return NS_OK; 1.425 +} 1.426 + 1.427 +nsresult 1.428 +nsPrintDialogWidgetGTK::ExportSettings(nsIPrintSettings *aNSSettings) 1.429 +{ 1.430 + NS_PRECONDITION(aNSSettings, "aSettings must not be null"); 1.431 + NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); 1.432 + 1.433 + GtkPrintSettings* settings = gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog)); 1.434 + GtkPageSetup* setup = gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog)); 1.435 + GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(dialog)); 1.436 + if (settings && setup && printer) { 1.437 + ExportFramePrinting(aNSSettings, settings); 1.438 + ExportHeaderFooter(aNSSettings); 1.439 + 1.440 + aNSSettings->SetOutputFormat(nsIPrintSettings::kOutputFormatNative); 1.441 + 1.442 + // Print-to-file is true by default. This must be turned off or else printing won't occur! 1.443 + // (We manually copy the spool file when this flag is set, because we love our embedders) 1.444 + // Even if it is print-to-file in GTK's case, GTK does The Right Thing when we send the job. 1.445 + aNSSettings->SetPrintToFile(false); 1.446 + 1.447 + aNSSettings->SetShrinkToFit(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle))); 1.448 + 1.449 + aNSSettings->SetPrintBGColors(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle))); 1.450 + aNSSettings->SetPrintBGImages(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle))); 1.451 + 1.452 + // Try to save native settings in the session object 1.453 + nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings)); 1.454 + if (aNSSettingsGTK) { 1.455 + aNSSettingsGTK->SetGtkPrintSettings(settings); 1.456 + aNSSettingsGTK->SetGtkPageSetup(setup); 1.457 + aNSSettingsGTK->SetGtkPrinter(printer); 1.458 + bool printSelectionOnly; 1.459 + if (useNativeSelection) { 1.460 + _GtkPrintPages pageSetting = (_GtkPrintPages)gtk_print_settings_get_print_pages(settings); 1.461 + printSelectionOnly = (pageSetting == _GTK_PRINT_PAGES_SELECTION); 1.462 + } else { 1.463 + printSelectionOnly = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(selection_only_toggle)); 1.464 + } 1.465 + aNSSettingsGTK->SetForcePrintSelectionOnly(printSelectionOnly); 1.466 + } 1.467 + } 1.468 + 1.469 + if (settings) 1.470 + g_object_unref(settings); 1.471 + return NS_OK; 1.472 +} 1.473 + 1.474 +GtkWidget* 1.475 +nsPrintDialogWidgetGTK::ConstructHeaderFooterDropdown(const char16_t *currentString) 1.476 +{ 1.477 +#if (MOZ_WIDGET_GTK == 2) 1.478 + GtkWidget* dropdown = gtk_combo_box_new_text(); 1.479 +#else 1.480 + GtkWidget* dropdown = gtk_combo_box_text_new(); 1.481 +#endif 1.482 + const char hf_options[][22] = {"headerFooterBlank", "headerFooterTitle", 1.483 + "headerFooterURL", "headerFooterDate", 1.484 + "headerFooterPage", "headerFooterPageTotal", 1.485 + "headerFooterCustom"}; 1.486 + 1.487 + for (unsigned int i = 0; i < ArrayLength(hf_options); i++) { 1.488 +#if (MOZ_WIDGET_GTK == 2) 1.489 + gtk_combo_box_append_text(GTK_COMBO_BOX(dropdown), GetUTF8FromBundle(hf_options[i]).get()); 1.490 +#else 1.491 + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(dropdown), nullptr, 1.492 + GetUTF8FromBundle(hf_options[i]).get()); 1.493 +#endif 1.494 + } 1.495 + 1.496 + bool shouldBeCustom = true; 1.497 + NS_ConvertUTF16toUTF8 currentStringUTF8(currentString); 1.498 + 1.499 + for (unsigned int i = 0; i < ArrayLength(header_footer_tags); i++) { 1.500 + if (!strcmp(currentStringUTF8.get(), header_footer_tags[i])) { 1.501 + gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), i); 1.502 + g_object_set_data(G_OBJECT(dropdown), "previous-active", GINT_TO_POINTER(i)); 1.503 + shouldBeCustom = false; 1.504 + break; 1.505 + } 1.506 + } 1.507 + 1.508 + if (shouldBeCustom) { 1.509 + gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), CUSTOM_VALUE_INDEX); 1.510 + g_object_set_data(G_OBJECT(dropdown), "previous-active", GINT_TO_POINTER(CUSTOM_VALUE_INDEX)); 1.511 + char* custom_string = strdup(currentStringUTF8.get()); 1.512 + g_object_set_data_full(G_OBJECT(dropdown), "custom-text", custom_string, (GDestroyNotify) free); 1.513 + } 1.514 + 1.515 + g_signal_connect(dropdown, "changed", (GCallback) ShowCustomDialog, dialog); 1.516 + return dropdown; 1.517 +} 1.518 + 1.519 +NS_IMPL_ISUPPORTS(nsPrintDialogServiceGTK, nsIPrintDialogService) 1.520 + 1.521 +nsPrintDialogServiceGTK::nsPrintDialogServiceGTK() 1.522 +{ 1.523 +} 1.524 + 1.525 +nsPrintDialogServiceGTK::~nsPrintDialogServiceGTK() 1.526 +{ 1.527 +} 1.528 + 1.529 +NS_IMETHODIMP 1.530 +nsPrintDialogServiceGTK::Init() 1.531 +{ 1.532 + return NS_OK; 1.533 +} 1.534 + 1.535 +NS_IMETHODIMP 1.536 +nsPrintDialogServiceGTK::Show(nsIDOMWindow *aParent, nsIPrintSettings *aSettings, 1.537 + nsIWebBrowserPrint *aWebBrowserPrint) 1.538 +{ 1.539 + NS_PRECONDITION(aParent, "aParent must not be null"); 1.540 + NS_PRECONDITION(aSettings, "aSettings must not be null"); 1.541 + 1.542 + nsPrintDialogWidgetGTK printDialog(aParent, aSettings); 1.543 + nsresult rv = printDialog.ImportSettings(aSettings); 1.544 + 1.545 + NS_ENSURE_SUCCESS(rv, rv); 1.546 + 1.547 + const gint response = printDialog.Run(); 1.548 + 1.549 + // Handle the result 1.550 + switch (response) { 1.551 + case GTK_RESPONSE_OK: // Proceed 1.552 + rv = printDialog.ExportSettings(aSettings); 1.553 + break; 1.554 + 1.555 + case GTK_RESPONSE_CANCEL: 1.556 + case GTK_RESPONSE_CLOSE: 1.557 + case GTK_RESPONSE_DELETE_EVENT: 1.558 + case GTK_RESPONSE_NONE: 1.559 + rv = NS_ERROR_ABORT; 1.560 + break; 1.561 + 1.562 + case GTK_RESPONSE_APPLY: // Print preview 1.563 + default: 1.564 + NS_WARNING("Unexpected response"); 1.565 + rv = NS_ERROR_ABORT; 1.566 + } 1.567 + return rv; 1.568 +} 1.569 + 1.570 +NS_IMETHODIMP 1.571 +nsPrintDialogServiceGTK::ShowPageSetup(nsIDOMWindow *aParent, 1.572 + nsIPrintSettings *aNSSettings) 1.573 +{ 1.574 + NS_PRECONDITION(aParent, "aParent must not be null"); 1.575 + NS_PRECONDITION(aNSSettings, "aSettings must not be null"); 1.576 + NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); 1.577 + 1.578 + nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent); 1.579 + NS_ASSERTION(widget, "Need a widget for dialog to be modal."); 1.580 + GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(widget); 1.581 + NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal."); 1.582 + 1.583 + nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings)); 1.584 + if (!aNSSettingsGTK) 1.585 + return NS_ERROR_FAILURE; 1.586 + 1.587 + // We need to init the prefs here because aNSSettings in its current form is a dummy in both uses of the word 1.588 + nsCOMPtr<nsIPrintSettingsService> psService = do_GetService("@mozilla.org/gfx/printsettings-service;1"); 1.589 + if (psService) { 1.590 + nsXPIDLString printName; 1.591 + aNSSettings->GetPrinterName(getter_Copies(printName)); 1.592 + if (!printName) { 1.593 + psService->GetDefaultPrinterName(getter_Copies(printName)); 1.594 + aNSSettings->SetPrinterName(printName.get()); 1.595 + } 1.596 + psService->InitPrintSettingsFromPrefs(aNSSettings, true, nsIPrintSettings::kInitSaveAll); 1.597 + } 1.598 + 1.599 + GtkPrintSettings* gtkSettings = aNSSettingsGTK->GetGtkPrintSettings(); 1.600 + GtkPageSetup* oldPageSetup = aNSSettingsGTK->GetGtkPageSetup(); 1.601 + 1.602 + GtkPageSetup* newPageSetup = gtk_print_run_page_setup_dialog(gtkParent, oldPageSetup, gtkSettings); 1.603 + 1.604 + aNSSettingsGTK->SetGtkPageSetup(newPageSetup); 1.605 + 1.606 + // Now newPageSetup has a refcount of 2 (SetGtkPageSetup will addref), put it to 1 so if 1.607 + // this gets replaced we don't leak. 1.608 + g_object_unref(newPageSetup); 1.609 + 1.610 + if (psService) 1.611 + psService->SavePrintSettingsToPrefs(aNSSettings, true, nsIPrintSettings::kInitSaveAll); 1.612 + 1.613 + return NS_OK; 1.614 +}