/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Modified: syd@netscape.com 10/18/99 wired in margins * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* Original Code: Syd Logan (syd@netscape.com) 3/12/99 */ #include #include #include "nspr.h" #include "nsPrintdGTK.h" /* A structure to hold widgets that need to be referenced in callbacks. We declare this statically in the caller entry point (as a field of UnixPrOps, below), and pass a pointer to the structure to Gtk+ for each signal handler registered. This avoids use of globals. */ typedef struct prwidgets { GtkWidget *toplevel; /* should be set to toplevel window */ GtkWidget *prDialog; GtkWidget *cmdEntry; GtkWidget *pathEntry; GtkWidget *browseButton; GtkWidget *fpfToggle; GtkWidget *greyToggle; GtkWidget *letterToggle; GtkWidget *legalToggle; GtkWidget *execToggle; GtkWidget *topSpinner; GtkWidget *bottomSpinner; GtkWidget *leftSpinner; GtkWidget *rightSpinner; GtkFileSelection *fsWidget; } PrWidgets; typedef struct unixprops { UnixPrData *prData; /* pointer to caller struct */ PrWidgets widgets; } UnixPrOps; /* user clicked cancel. tear things down, and set cancel field in caller data to PR_TRUE so printing will not happen */ static void CancelPrint (GtkWidget *widget, UnixPrOps *prOps) { gtk_main_quit(); gtk_widget_destroy( GTK_WIDGET(prOps->widgets.prDialog) ); prOps->prData->cancel = PR_TRUE; } /* user selected the Print button. Collect any remaining data from the widgets, and set cancel field in caller data to PR_FALSE so printing will be performed. Also, tear down dialog and exit inner main loop */ static void DoPrint (GtkWidget *widget, UnixPrOps *prOps) { strcpy( prOps->prData->command, gtk_entry_get_text( GTK_ENTRY( prOps->widgets.cmdEntry ) ) ); strcpy( prOps->prData->path, gtk_entry_get_text( GTK_ENTRY( prOps->widgets.pathEntry ) ) ); if ( GTK_TOGGLE_BUTTON( prOps->widgets.fpfToggle )->active == PR_TRUE ) prOps->prData->fpf = PR_TRUE; else prOps->prData->fpf = PR_FALSE; if ( GTK_TOGGLE_BUTTON( prOps->widgets.greyToggle )->active == PR_TRUE ) prOps->prData->grayscale = PR_TRUE; else prOps->prData->grayscale = PR_FALSE; if ( GTK_TOGGLE_BUTTON( prOps->widgets.letterToggle )->active == PR_TRUE ) prOps->prData->size = NS_LETTER_SIZE; else if ( GTK_TOGGLE_BUTTON( prOps->widgets.legalToggle )->active == PR_TRUE ) prOps->prData->size = NS_LEGAL_SIZE; else if ( GTK_TOGGLE_BUTTON( prOps->widgets.execToggle )->active == PR_TRUE ) prOps->prData->size = NS_EXECUTIVE_SIZE; else prOps->prData->size = NS_A4_SIZE; /* margins */ prOps->prData->top = gtk_spin_button_get_value_as_float( GTK_SPIN_BUTTON(prOps->widgets.topSpinner) ); prOps->prData->bottom = gtk_spin_button_get_value_as_float( GTK_SPIN_BUTTON(prOps->widgets.bottomSpinner) ); prOps->prData->left = gtk_spin_button_get_value_as_float( GTK_SPIN_BUTTON(prOps->widgets.leftSpinner) ); prOps->prData->right = gtk_spin_button_get_value_as_float( GTK_SPIN_BUTTON(prOps->widgets.rightSpinner) ); /* we got everything... bring down the dialog and tell caller it's o.k. to print */ gtk_main_quit(); gtk_widget_destroy( GTK_WIDGET(prOps->widgets.prDialog) ); prOps->prData->cancel = PR_FALSE; } /* User hit ok in file selection widget brought up by the browse button. snarf the selected file, stuff it in caller data */ static void ModifyPrPath (GtkWidget *widget, UnixPrOps *prOps) { strcpy( prOps->prData->path, gtk_file_selection_get_filename(prOps->widgets.fsWidget) ); gtk_entry_set_text (GTK_ENTRY (prOps->widgets.pathEntry), prOps->prData->path); gtk_widget_destroy( GTK_WIDGET(prOps->widgets.fsWidget) ); } /* user selected print to printer. de-sensitize print to file fields */ static void SwitchToPrinter (GtkWidget *widget, UnixPrOps *prOps) { gtk_widget_set_sensitive( prOps->widgets.cmdEntry, PR_TRUE ); gtk_widget_set_sensitive( prOps->widgets.pathEntry, PR_FALSE ); gtk_widget_set_sensitive( prOps->widgets.browseButton, PR_FALSE ); prOps->prData->toPrinter = PR_TRUE; } /* user selected print to file. de-sensitize print to printer fields */ static void SwitchToFile (GtkWidget *widget, UnixPrOps *prOps) { gtk_widget_set_sensitive( prOps->widgets.cmdEntry, PR_FALSE ); gtk_widget_set_sensitive( prOps->widgets.pathEntry, PR_TRUE ); gtk_widget_set_sensitive( prOps->widgets.browseButton, PR_TRUE ); prOps->prData->toPrinter = PR_FALSE; } /* user hit the browse button. Pop up a file selection widget and grab result */ static void GetPrPath (GtkWidget *widget, UnixPrOps *prOps) { GtkWidget *fs; fs = gtk_file_selection_new("File Browser"); gtk_file_selection_set_filename( GTK_FILE_SELECTION(fs), prOps->prData->path ); gtk_window_set_modal (GTK_WINDOW(fs),PR_TRUE); #if 0 /* XXX not sure what the toplevel window should be. */ gtk_window_set_transient_for (GTK_WINDOW (fs), GTK_WINDOW (prOps->widgets.toplevel)); #endif prOps->widgets.fsWidget = GTK_FILE_SELECTION(fs); gtk_signal_connect (GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), "clicked", GTK_SIGNAL_FUNC(ModifyPrPath), prOps); gtk_signal_connect_object (GTK_OBJECT( GTK_FILE_SELECTION(fs)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT (fs)); gtk_widget_show(fs); } /* create file data dialog. XXX widget should be NULL */ static void DoPrintGTK (GtkWidget *widget, UnixPrOps *prOps) { GtkWidget *separator, *dialog, *label, *vbox, *entry, *hbox, *button, *fileButton, *prButton, *table, *spinner1; GtkAdjustment *adj; prOps->widgets.prDialog = dialog = gtk_window_new( GTK_WINDOW_TOPLEVEL ); gtk_window_set_modal( GTK_WINDOW(dialog), PR_TRUE ); #if 0 /* not yet sure what the toplevel window should be */ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (prOps->widgets.toplevel)); #endif gtk_window_set_title( GTK_WINDOW(dialog), "Print" ); vbox = gtk_vbox_new (PR_FALSE, 0); gtk_container_add (GTK_CONTAINER (dialog), vbox); table = gtk_table_new (3, 3, PR_FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 5); gtk_table_set_col_spacings (GTK_TABLE (table), 5); gtk_container_set_border_width (GTK_CONTAINER (table), 10); gtk_box_pack_start (GTK_BOX (vbox), table, PR_TRUE, PR_TRUE, 5); label = gtk_label_new( "Print To:" ); gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, 0, GTK_EXPAND | GTK_FILL, 0, 0); button = prButton = gtk_radio_button_new_with_label (NULL, "Printer"); if ( prOps->prData->toPrinter == PR_TRUE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); gtk_table_attach (GTK_TABLE (table), button, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = fileButton = gtk_radio_button_new_with_label ( gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "File"); gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); if ( prOps->prData->toPrinter == PR_FALSE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); label = gtk_label_new( "Print Command:" ); gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, 0, GTK_EXPAND | GTK_FILL, 0, 0); entry = gtk_entry_new (); gtk_entry_set_text (GTK_ENTRY (entry), prOps->prData->command); gtk_table_attach (GTK_TABLE (table), entry, 1, 3, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); if ( prOps->prData->toPrinter == PR_FALSE ) gtk_widget_set_sensitive( entry, PR_FALSE ); prOps->widgets.cmdEntry = entry; label = gtk_label_new( "File Name:" ); gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, 0, GTK_EXPAND | GTK_FILL, 0, 0); entry = gtk_entry_new (); gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_entry_set_text (GTK_ENTRY (entry), prOps->prData->path); if ( prOps->prData->toPrinter == PR_TRUE ) gtk_widget_set_sensitive( entry, PR_FALSE ); prOps->widgets.pathEntry = entry; button = gtk_button_new_with_label ("Browse..."); gtk_table_attach (GTK_TABLE (table), button, 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (GetPrPath), prOps); if ( prOps->prData->toPrinter == PR_TRUE ) gtk_widget_set_sensitive( entry, PR_FALSE ); prOps->widgets.browseButton = button; separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (vbox), separator, PR_TRUE, PR_FALSE, 0); table = gtk_table_new (2, 4, PR_FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 5); gtk_table_set_col_spacings (GTK_TABLE (table), 5); gtk_container_set_border_width (GTK_CONTAINER (table), 10); gtk_box_pack_start (GTK_BOX (vbox), table, PR_TRUE, PR_FALSE, 0); label = gtk_label_new( "Print: " ); gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = gtk_radio_button_new_with_label (NULL, "First Page First"); if ( prOps->prData->fpf == PR_TRUE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); prOps->widgets.fpfToggle = button; gtk_table_attach (GTK_TABLE (table), button, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = gtk_radio_button_new_with_label ( gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "Last Page First"); if ( prOps->prData->fpf == PR_FALSE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); label = gtk_label_new( "Print: " ); gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = gtk_radio_button_new_with_label (NULL, "Greyscale"); prOps->widgets.greyToggle = button; if ( prOps->prData->grayscale == PR_TRUE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); gtk_table_attach (GTK_TABLE (table), button, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = gtk_radio_button_new_with_label ( gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "Color"); if ( prOps->prData->grayscale == PR_FALSE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); gtk_table_attach (GTK_TABLE (table), button, 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); label = gtk_label_new( "Paper Size: " ); gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = gtk_radio_button_new_with_label (NULL, "Letter (8 1/2 x 11 in.)"); prOps->widgets.letterToggle = button; if ( prOps->prData->size == NS_LETTER_SIZE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); gtk_table_attach (GTK_TABLE (table), button, 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = gtk_radio_button_new_with_label ( gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "Legal (8 1/2 x 14 in.)"); prOps->widgets.legalToggle = button; if ( prOps->prData->size == NS_LEGAL_SIZE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); gtk_table_attach (GTK_TABLE (table), button, 2, 3, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = gtk_radio_button_new_with_label ( gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "Executive (7 1/2 x 10 in.)"); prOps->widgets.execToggle = button; if ( prOps->prData->size == NS_EXECUTIVE_SIZE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); gtk_table_attach (GTK_TABLE (table), button, 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); button = gtk_radio_button_new_with_label ( gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "A4 (210 x 297 mm)"); if ( prOps->prData->size == NS_A4_SIZE ) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), PR_TRUE); gtk_table_attach (GTK_TABLE (table), button, 2, 3, 4, 5, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); /* margins */ separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (vbox), separator, PR_TRUE, PR_FALSE, 0); hbox = gtk_hbox_new (PR_FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, PR_FALSE, PR_FALSE, 5); label = gtk_label_new( "Margins (inches):" ); gtk_box_pack_start (GTK_BOX (hbox), label, PR_FALSE, PR_FALSE, 10); table = gtk_table_new (1, 2, PR_FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 5); gtk_table_set_col_spacings (GTK_TABLE (table), 5); gtk_container_set_border_width (GTK_CONTAINER (table), 10); gtk_box_pack_start (GTK_BOX (vbox), table, PR_TRUE, PR_FALSE, 0); hbox = gtk_hbox_new (PR_FALSE, 0); gtk_table_attach (GTK_TABLE (table), hbox, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); label = gtk_label_new( "Top: " ); gtk_box_pack_start (GTK_BOX (hbox), label, PR_TRUE, PR_FALSE, 0); adj = (GtkAdjustment *) gtk_adjustment_new ( prOps->prData->top, 0.0, 999.0, 0.25, 1.0, 0.0); prOps->widgets.topSpinner = spinner1 = gtk_spin_button_new (adj, 1.0, 2); gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE); gtk_widget_set_usize (spinner1, 60, 0); gtk_box_pack_start (GTK_BOX (hbox), spinner1, FALSE, TRUE, 0); label = gtk_label_new( "Bottom: " ); gtk_box_pack_start (GTK_BOX (hbox), label, PR_TRUE, PR_FALSE, 0); adj = (GtkAdjustment *) gtk_adjustment_new ( prOps->prData->bottom, 0.0, 999.0, 0.25, 1.0, 0.0); prOps->widgets.bottomSpinner = spinner1 = gtk_spin_button_new (adj, 1.0, 2); gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE); gtk_widget_set_usize (spinner1, 60, 0); gtk_box_pack_start (GTK_BOX (hbox), spinner1, FALSE, TRUE, 0); hbox = gtk_hbox_new (PR_FALSE, 0); gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); label = gtk_label_new( "Left: " ); gtk_box_pack_start (GTK_BOX (hbox), label, PR_TRUE, PR_FALSE, 0); adj = (GtkAdjustment *) gtk_adjustment_new ( prOps->prData->left, 0.0, 999.0, 0.25, 1.0, 0.0); prOps->widgets.leftSpinner = spinner1 = gtk_spin_button_new (adj, 1.0, 2); gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE); gtk_widget_set_usize (spinner1, 60, 0); gtk_box_pack_start (GTK_BOX (hbox), spinner1, FALSE, TRUE, 0); label = gtk_label_new( "Right: " ); gtk_box_pack_start (GTK_BOX (hbox), label, PR_TRUE, PR_FALSE, 0); adj = (GtkAdjustment *) gtk_adjustment_new ( prOps->prData->right, 0.0, 999.0, 0.25, 1.0, 0.0); prOps->widgets.rightSpinner = spinner1 = gtk_spin_button_new (adj, 1.0, 2); gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE); gtk_widget_set_usize (spinner1, 60, 0); gtk_box_pack_start (GTK_BOX (hbox), spinner1, FALSE, TRUE, 0); separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (vbox), separator, PR_TRUE, PR_FALSE, 0); hbox = gtk_hbox_new (PR_FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, PR_TRUE, PR_FALSE, 5); button = gtk_button_new_with_label ("Print"); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (DoPrint), prOps ); gtk_box_pack_start (GTK_BOX (hbox), button, PR_TRUE, PR_FALSE, 0); GTK_WIDGET_FLAGS (button) |= GTK_CAN_DEFAULT; gtk_widget_grab_default (button); button = gtk_button_new_with_label ("Cancel"); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC ( CancelPrint ), prOps); gtk_box_pack_start (GTK_BOX (hbox), button, PR_TRUE, PR_FALSE, 0); /* Do this here, otherwise, upon creation the callbacks will be triggered and the widgets these callbacks set sensitivity on do not exist yet */ gtk_signal_connect (GTK_OBJECT (prButton), "clicked", GTK_SIGNAL_FUNC (SwitchToPrinter), prOps); gtk_signal_connect (GTK_OBJECT (fileButton), "clicked", GTK_SIGNAL_FUNC (SwitchToFile), prOps); gtk_widget_show_all( dialog ); gtk_main (); } /* public interface to print dialog. Caller passes in preferences using argument, we return any changes and indication of whether to print or cancel. */ void UnixPrDialog( UnixPrData *prData ) { static UnixPrOps prOps; prOps.prData = prData; DoPrintGTK( (GtkWidget *) NULL, &prOps ); }