widget/gtk/nsPrintDialogGTK.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial