Back to index

lightning-sunbird  0.9+nobinonly
EmbedPrompter.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim:expandtab:shiftwidth=4:tabstop=4: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 2003
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *  Brian Ryner <bryner@brianryner.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "EmbedPrompter.h"
00041 #include "nsReadableUtils.h"
00042 
00043 enum {
00044     INCLUDE_USERNAME = 1 << 0,
00045     INCLUDE_PASSWORD = 1 << 1,
00046     INCLUDE_CHECKBOX = 1 << 2,
00047     INCLUDE_CANCEL   = 1 << 3
00048 };
00049 
00050 struct DialogDescription {
00051     int    flags;
00052     gchar* icon;
00053 };
00054 
00055 // This table contains the optional widgets and icons associated with
00056 // each type of dialog.
00057 
00058 static const DialogDescription DialogTable[] = {
00059     { 0,                      GTK_STOCK_DIALOG_WARNING  },  // ALERT
00060     { INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_WARNING  },  // ALERT_CHECK
00061     { INCLUDE_CANCEL,         GTK_STOCK_DIALOG_QUESTION },  // CONFIRM
00062     { INCLUDE_CHECKBOX |
00063       INCLUDE_CANCEL,         GTK_STOCK_DIALOG_QUESTION },  // CONFIRM_CHECK
00064     { INCLUDE_CANCEL |
00065       INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_QUESTION },  // PROMPT
00066     { INCLUDE_CANCEL |
00067       INCLUDE_USERNAME |
00068       INCLUDE_PASSWORD |
00069       INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_QUESTION },  // PROMPT_USER_PASS
00070     { INCLUDE_CANCEL |
00071       INCLUDE_PASSWORD |
00072       INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_QUESTION },  // PROMPT_PASS
00073     { INCLUDE_CANCEL,         GTK_STOCK_DIALOG_QUESTION },  // SELECT
00074     { INCLUDE_CANCEL |
00075       INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_QUESTION }   // UNIVERSAL
00076 };
00077 
00078 EmbedPrompter::EmbedPrompter(void)
00079     : mCheckValue(PR_FALSE),
00080       mItemList(nsnull),
00081       mItemCount(0),
00082       mButtonPressed(0),
00083       mConfirmResult(PR_FALSE),
00084       mSelectedItem(0),
00085       mWindow(NULL),
00086       mUserField(NULL),
00087       mPassField(NULL),
00088       mTextField(NULL),
00089       mOptionMenu(NULL),
00090       mCheckBox(NULL)
00091 {
00092 }
00093 
00094 EmbedPrompter::~EmbedPrompter(void)
00095 {
00096     if (mItemList)
00097         delete[] mItemList;
00098 }
00099 
00100 nsresult
00101 EmbedPrompter::Create(PromptType aType, GtkWindow* aParentWindow)
00102 {
00103     mWindow = gtk_dialog_new_with_buttons(mTitle.get(), aParentWindow,
00104                                           (GtkDialogFlags)0,
00105                                           NULL);
00106 
00107     // only add the dialog to the window group if the parent already has a window group,
00108     // so as not to break app's expectations about modal dialogs.
00109     if (aParentWindow && aParentWindow->group) {
00110         gtk_window_group_add_window (aParentWindow->group, GTK_WINDOW (mWindow));
00111     }
00112 
00113     // gtk will resize this for us as necessary
00114     gtk_window_set_default_size(GTK_WINDOW(mWindow), 100, 50);
00115 
00116     // this HBox will contain the icon, and a vbox which contains the
00117     // dialog text and other widgets.
00118     GtkWidget* dialogHBox = gtk_hbox_new(FALSE, 12);
00119 
00120 
00121     // Set up dialog properties according to the GNOME HIG
00122     // (http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-windows)
00123 
00124     gtk_container_set_border_width(GTK_CONTAINER(mWindow), 6);
00125     gtk_dialog_set_has_separator(GTK_DIALOG(mWindow), FALSE);
00126     gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(mWindow)->vbox), 12);
00127     gtk_container_set_border_width(GTK_CONTAINER(dialogHBox), 6);
00128 
00129 
00130     // This is the VBox which will contain the label and other controls.
00131     GtkWidget* contentsVBox = gtk_vbox_new(FALSE, 12);
00132 
00133     // get the stock icon for this dialog and put it in the box
00134     const gchar* iconDesc = DialogTable[aType].icon;
00135     GtkWidget* icon = gtk_image_new_from_stock(iconDesc, GTK_ICON_SIZE_DIALOG);
00136     gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0);
00137     gtk_box_pack_start(GTK_BOX(dialogHBox), icon, FALSE, FALSE, 0);
00138 
00139     // now pack the label into the vbox
00140     GtkWidget* label = gtk_label_new(mMessageText.get());
00141     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
00142     gtk_label_set_selectable(GTK_LABEL(label), TRUE);
00143     gtk_box_pack_start(GTK_BOX(contentsVBox), label, FALSE, FALSE, 0);
00144 
00145     int widgetFlags = DialogTable[aType].flags;
00146 
00147     if (widgetFlags & (INCLUDE_USERNAME | INCLUDE_PASSWORD)) {
00148 
00149         // If we're creating a username and/or password field, make an hbox
00150         // which will contain two vboxes, one for the labels and one for the
00151         // text fields.  This will let us line up the textfields.
00152 
00153         GtkWidget* userPassHBox = gtk_hbox_new(FALSE, 12);
00154         GtkWidget* userPassLabels = gtk_vbox_new(TRUE, 6);
00155         GtkWidget* userPassFields = gtk_vbox_new(TRUE, 6);
00156 
00157         if (widgetFlags & INCLUDE_USERNAME) {
00158             GtkWidget* userLabel = gtk_label_new("User Name:");
00159             gtk_box_pack_start(GTK_BOX(userPassLabels), userLabel, FALSE,
00160                                FALSE, 0);
00161 
00162             mUserField = gtk_entry_new();
00163 
00164             if (!mUser.IsEmpty())
00165                 gtk_entry_set_text(GTK_ENTRY(mUserField), mUser.get());
00166 
00167             gtk_entry_set_activates_default(GTK_ENTRY(mUserField), TRUE);
00168 
00169             gtk_box_pack_start(GTK_BOX(userPassFields), mUserField, FALSE,
00170                                FALSE, 0);
00171         }
00172         if (widgetFlags & INCLUDE_PASSWORD) {
00173             GtkWidget* passLabel = gtk_label_new("Password:");
00174             gtk_box_pack_start(GTK_BOX(userPassLabels), passLabel, FALSE,
00175                                FALSE, 0);
00176 
00177             mPassField = gtk_entry_new();
00178 
00179             if (!mPass.IsEmpty())
00180                 gtk_entry_set_text(GTK_ENTRY(mPassField), mPass.get());
00181 
00182             gtk_entry_set_visibility(GTK_ENTRY(mPassField), FALSE);
00183             gtk_entry_set_activates_default(GTK_ENTRY(mPassField), TRUE);
00184 
00185             gtk_box_pack_start(GTK_BOX(userPassFields), mPassField, FALSE,
00186                                FALSE, 0);
00187         }
00188 
00189         gtk_box_pack_start(GTK_BOX(userPassHBox), userPassLabels, FALSE,
00190                            FALSE, 0);
00191         gtk_box_pack_start(GTK_BOX(userPassHBox), userPassFields, FALSE,
00192                            FALSE, 0);
00193         gtk_box_pack_start(GTK_BOX(contentsVBox), userPassHBox, FALSE, FALSE, 0);
00194     }
00195 
00196     if (aType == TYPE_PROMPT) {
00197         mTextField = gtk_entry_new();
00198 
00199         if (!mTextValue.IsEmpty())
00200             gtk_entry_set_text(GTK_ENTRY(mTextField), mTextValue.get());
00201 
00202         gtk_entry_set_activates_default(GTK_ENTRY(mTextField), TRUE);
00203 
00204         gtk_box_pack_start(GTK_BOX(contentsVBox), mTextField, FALSE, FALSE, 0);
00205     }
00206 
00207     // Add a checkbox
00208     if ((widgetFlags & INCLUDE_CHECKBOX) && !mCheckMessage.IsEmpty()) {
00209         mCheckBox = gtk_check_button_new_with_label(mCheckMessage.get());
00210 
00211         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mCheckBox),
00212                                      mCheckValue);
00213         gtk_label_set_line_wrap(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mCheckBox))),
00214                             TRUE);
00215 
00216         gtk_box_pack_start(GTK_BOX(contentsVBox), mCheckBox, FALSE, FALSE, 0);
00217     }
00218 
00219     // Add a dropdown menu
00220     if (aType == TYPE_SELECT) {
00221         // Build up a GtkMenu containing the items
00222         GtkWidget* menu = gtk_menu_new();
00223         for (PRUint32 i = 0; i < mItemCount; ++i) {
00224             GtkWidget* item = gtk_menu_item_new_with_label(mItemList[i].get());
00225             gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
00226         }
00227 
00228         // Now create an OptionMenu and set this as the menu
00229         mOptionMenu = gtk_option_menu_new();
00230 
00231         gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), menu);
00232         gtk_box_pack_start(GTK_BOX(contentsVBox), mOptionMenu, FALSE, FALSE, 0);
00233     }
00234 
00235     if (aType == TYPE_UNIVERSAL) {
00236         // Create buttons based on the flags passed in.
00237         for (int i = EMBED_MAX_BUTTONS; i >= 0; --i) {
00238             if (!mButtonLabels[i].IsEmpty())
00239                 gtk_dialog_add_button(GTK_DIALOG(mWindow),
00240                                       mButtonLabels[i].get(), i);
00241         }
00242         gtk_dialog_set_default_response(GTK_DIALOG(mWindow), 0);
00243     } else {
00244         // Create standard ok and cancel buttons
00245         if (widgetFlags & INCLUDE_CANCEL)
00246             gtk_dialog_add_button(GTK_DIALOG(mWindow), GTK_STOCK_CANCEL,
00247                                   GTK_RESPONSE_CANCEL);
00248 
00249         GtkWidget* okButton = gtk_dialog_add_button(GTK_DIALOG(mWindow),
00250                                                     GTK_STOCK_OK,
00251                                                     GTK_RESPONSE_ACCEPT);
00252         gtk_widget_grab_default(okButton);
00253     }
00254 
00255     // Pack the contentsVBox into the dialogHBox and the dialog.
00256     gtk_box_pack_start(GTK_BOX(dialogHBox), contentsVBox, FALSE, FALSE, 0);
00257     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(mWindow)->vbox), dialogHBox, FALSE,
00258                        FALSE, 0);
00259 
00260     return NS_OK;
00261 }
00262 
00263 void
00264 EmbedPrompter::SetTitle(const PRUnichar *aTitle)
00265 {
00266     CopyUTF16toUTF8(aTitle, mTitle);
00267 }
00268 
00269 void
00270 EmbedPrompter::SetTextValue(const PRUnichar *aTextValue)
00271 {
00272     CopyUTF16toUTF8(aTextValue, mTextValue);
00273 }
00274 
00275 void
00276 EmbedPrompter::SetCheckMessage(const PRUnichar *aMessage)
00277 {
00278     CopyUTF16toUTF8(aMessage, mCheckMessage);
00279 }
00280 
00281 void
00282 EmbedPrompter::SetMessageText(const PRUnichar *aMessageText)
00283 {
00284     CopyUTF16toUTF8(aMessageText, mMessageText);
00285 }
00286 
00287 void
00288 EmbedPrompter::SetUser(const PRUnichar *aUser)
00289 {
00290     CopyUTF16toUTF8(aUser, mUser);
00291 }
00292 
00293 void
00294 EmbedPrompter::SetPassword(const PRUnichar *aPass)
00295 {
00296     CopyUTF16toUTF8(aPass, mPass);
00297 }
00298 
00299 void
00300 EmbedPrompter::SetCheckValue(const PRBool aValue)
00301 {
00302     mCheckValue = aValue;
00303 }
00304 
00305 void
00306 EmbedPrompter::SetItems(const PRUnichar** aItemArray, PRUint32 aCount)
00307 {
00308     if (mItemList)
00309         delete[] mItemList;
00310 
00311     mItemCount = aCount;
00312     mItemList = new nsCString[aCount];
00313     for (PRUint32 i = 0; i < aCount; ++i)
00314         CopyUTF16toUTF8(aItemArray[i], mItemList[i]);
00315 }
00316 
00317 void
00318 EmbedPrompter::SetButtons(const PRUnichar* aButton0Label,
00319                           const PRUnichar* aButton1Label,
00320                           const PRUnichar* aButton2Label)
00321 {
00322     CopyUTF16toUTF8(aButton0Label, mButtonLabels[0]);
00323     CopyUTF16toUTF8(aButton1Label, mButtonLabels[1]);
00324     CopyUTF16toUTF8(aButton2Label, mButtonLabels[2]);
00325 }
00326 
00327 void
00328 EmbedPrompter::GetCheckValue(PRBool *aValue)
00329 {
00330     *aValue = mCheckValue;
00331 }
00332 
00333 void
00334 EmbedPrompter::GetConfirmValue(PRBool *aConfirmValue)
00335 {
00336     *aConfirmValue = mConfirmResult;
00337 }
00338  
00339 void
00340 EmbedPrompter::GetTextValue(PRUnichar **aTextValue)
00341 {
00342     *aTextValue = UTF8ToNewUnicode(mTextValue);
00343 }
00344 
00345 void
00346 EmbedPrompter::GetUser(PRUnichar **aUser)
00347 {
00348     *aUser = UTF8ToNewUnicode(mUser);
00349 }
00350 
00351 void
00352 EmbedPrompter::GetPassword(PRUnichar **aPass)
00353 {
00354     *aPass = UTF8ToNewUnicode(mPass);
00355 }
00356 
00357 void
00358 EmbedPrompter::GetSelectedItem(PRInt32 *aIndex)
00359 {
00360     *aIndex = mSelectedItem;
00361 }
00362 
00363 void
00364 EmbedPrompter::GetButtonPressed(PRInt32 *aButton)
00365 {
00366     *aButton = mButtonPressed;
00367 }
00368 
00369 void
00370 EmbedPrompter::Run(void)
00371 {
00372     gtk_widget_show_all(mWindow);
00373     gint response = gtk_dialog_run(GTK_DIALOG(mWindow));
00374     switch (response) {
00375     case GTK_RESPONSE_NONE:
00376     case GTK_RESPONSE_CANCEL:
00377     case GTK_RESPONSE_DELETE_EVENT:
00378         mConfirmResult = PR_FALSE;
00379         break;
00380     case GTK_RESPONSE_ACCEPT:
00381         mConfirmResult = PR_TRUE;
00382         SaveDialogValues();
00383         break;
00384     default:
00385         mButtonPressed = response;
00386         SaveDialogValues();
00387     }
00388 
00389     gtk_widget_destroy(mWindow);
00390 }
00391 
00392 void
00393 EmbedPrompter::SaveDialogValues()
00394 {
00395     if (mUserField)
00396         mUser.Assign(gtk_entry_get_text(GTK_ENTRY(mUserField)));
00397 
00398     if (mPassField)
00399         mPass.Assign(gtk_entry_get_text(GTK_ENTRY(mPassField)));
00400 
00401     if (mCheckBox)
00402         mCheckValue = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mCheckBox));
00403 
00404     if (mTextField)
00405         mTextValue.Assign(gtk_entry_get_text(GTK_ENTRY(mTextField)));
00406 
00407     if (mOptionMenu)
00408         mSelectedItem = gtk_option_menu_get_history(GTK_OPTION_MENU(mOptionMenu));
00409 }