Back to index

lightning-sunbird  0.9+nobinonly
nsComponentsDlg.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Samir Gehani <sgehani@netscape.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 "nsComponentsDlg.h"
00041 #include "nsXInstaller.h"
00042 #include "check_on.xpm"
00043 #include "check_off.xpm"
00044 #include <gdk/gdkkeysyms.h>
00045 
00046 static nsSetupType     *sCustomST; // cache a pointer to the custom setup type
00047 static GtkWidget       *sDescLong;
00048 static gint             sCurrRowSelected;
00049 
00050 nsComponentsDlg::nsComponentsDlg() :
00051     mMsg0(NULL),
00052     mCompList(NULL)
00053 {
00054 }
00055 
00056 nsComponentsDlg::~nsComponentsDlg()
00057 {
00058     XI_IF_FREE(mMsg0);
00059     XI_IF_DELETE(mCompList);
00060 }
00061 
00062 void
00063 nsComponentsDlg::Back(GtkWidget *aWidget, gpointer aData)
00064 {
00065     DUMP("Back");
00066     if (aData != gCtx->cdlg) return;
00067 
00068     // hide this notebook page
00069     gCtx->cdlg->Hide(nsXInstallerDlg::BACKWARD_MOVE);
00070 
00071     // disconnect this dlg's nav btn signal handlers
00072     gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
00073     gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
00074 
00075     gCtx->sdlg->Show(nsXInstallerDlg::BACKWARD_MOVE);
00076 }
00077 
00078 void
00079 nsComponentsDlg::Next(GtkWidget *aWidget, gpointer aData)
00080 {
00081     DUMP("Next");
00082     if (aData != gCtx->cdlg) return;
00083 
00084        if (OK != nsSetupTypeDlg::VerifyDiskSpace())
00085            return;
00086 
00087     // hide this notebook page
00088     gCtx->cdlg->Hide(nsXInstallerDlg::FORWARD_MOVE);
00089 
00090     // disconnect this dlg's nav btn signal handlers
00091     gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
00092     gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
00093 
00094     // show the next dlg
00095     gCtx->idlg->Show(nsXInstallerDlg::FORWARD_MOVE);
00096 }
00097 
00098 int
00099 nsComponentsDlg::Parse(nsINIParser *aParser)
00100 {
00101     int err = OK;
00102     char *showDlg = NULL;
00103     int bufsize = 0;
00104 
00105     char *currSec = (char *) malloc(strlen(COMPONENT) + 3);
00106     if (!currSec) return E_MEM;
00107     XI_VERIFY(gCtx);
00108 
00109     /* optional keys */
00110     err = aParser->GetStringAlloc(DLG_COMPONENTS, MSG0, &mMsg0, &bufsize);
00111     if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
00112 
00113     bufsize = 5;
00114     err = aParser->GetStringAlloc(DLG_COMPONENTS, SHOW_DLG, &showDlg, &bufsize);
00115     if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
00116     if (bufsize != 0 && showDlg)
00117     {
00118         if (0 == strncmp(showDlg, "TRUE", 4))
00119             mShowDlg = nsXInstallerDlg::SHOW_DIALOG;
00120         else if (0 == strncmp(showDlg, "FALSE", 5))
00121             mShowDlg = nsXInstallerDlg::SKIP_DIALOG;
00122     }
00123 
00124     bufsize = 0;
00125     err = aParser->GetStringAlloc(DLG_COMPONENTS, TITLE, &mTitle, &bufsize);
00126     if (err != OK  && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
00127     if (bufsize == 0)
00128             XI_IF_FREE(mTitle); 
00129 
00130 BAIL:
00131     XI_IF_FREE(currSec);
00132 
00133     return err;
00134 }
00135 
00136 int
00137 nsComponentsDlg::Show(int aDirection)
00138 {
00139     int err = OK;
00140     int customSTIndex = 0, i;
00141     int numRows = 0;
00142     int currRow = 0;
00143     GtkWidget *hbox = NULL;
00144 
00145     XI_VERIFY(gCtx);
00146     XI_VERIFY(gCtx->notebook);
00147 
00148     if (mWidgetsInit == FALSE)
00149     {
00150         customSTIndex = gCtx->sdlg->GetNumSetupTypes();
00151         sCustomST = gCtx->sdlg->GetSetupTypeList();
00152         for (i=1; i<customSTIndex; i++)
00153             sCustomST = sCustomST->GetNext();
00154         DUMP(sCustomST->GetDescShort());
00155 
00156         // create a new table and add it as a page of the notebook
00157         mTable = gtk_table_new(5, 1, FALSE);
00158         gtk_notebook_append_page(GTK_NOTEBOOK(gCtx->notebook), mTable, NULL);
00159         mPageNum = gtk_notebook_get_current_page(GTK_NOTEBOOK(gCtx->notebook));
00160         gtk_widget_show(mTable);
00161 
00162         // 1st row: a label (msg0)
00163         // insert a static text widget in the first row
00164         GtkWidget *msg0 = gtk_label_new(mMsg0);
00165         hbox = gtk_hbox_new(FALSE, 0);
00166         gtk_box_pack_start(GTK_BOX(hbox), msg0, FALSE, FALSE, 0);
00167         gtk_widget_show(hbox);
00168         gtk_table_attach(GTK_TABLE(mTable), hbox, 0, 1, 1, 2,
00169                          static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00170                                   GTK_FILL, 20, 20);
00171         gtk_widget_show(msg0);
00172 
00173         // 2nd row: a CList with a check box for each row (short desc)
00174         GtkWidget *list = NULL;
00175         GtkWidget *scrollwin = NULL;
00176         GtkStyle *style = NULL;
00177         GdkBitmap *ch_mask = NULL;
00178         GdkPixmap *checked = NULL;
00179         GdkBitmap *un_mask = NULL;
00180         GdkPixmap *unchecked = NULL;
00181         gchar *dummy[2] = { " ", " " };
00182         nsComponent *currComp = sCustomST->GetComponents()->GetHead();
00183         GtkWidget *descLongTable = NULL;
00184         GtkWidget *frame = NULL;
00185 
00186         scrollwin = gtk_scrolled_window_new(NULL, NULL);
00187         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
00188             GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
00189 
00190         list = gtk_clist_new(2);
00191         gtk_clist_set_selection_mode(GTK_CLIST(list), GTK_SELECTION_BROWSE);
00192         gtk_clist_column_titles_hide(GTK_CLIST(list));
00193         gtk_clist_set_column_auto_resize(GTK_CLIST(list), 0, TRUE);
00194         gtk_clist_set_column_auto_resize(GTK_CLIST(list), 1, TRUE);
00195 
00196         // determine number of rows we'll need
00197         numRows = sCustomST->GetComponents()->GetLengthVisible();
00198         for (i = 0; i < numRows; i++)
00199             gtk_clist_append(GTK_CLIST(list), dummy);
00200     
00201         style = gtk_widget_get_style(gCtx->window);
00202         checked = gdk_pixmap_create_from_xpm_d(gCtx->window->window, &ch_mask, 
00203                   &style->bg[GTK_STATE_NORMAL], (gchar **)check_on_xpm);
00204         unchecked = gdk_pixmap_create_from_xpm_d(gCtx->window->window, &un_mask,
00205                     &style->bg[GTK_STATE_NORMAL], (gchar **)check_off_xpm);
00206 
00207         while ((currRow < numRows) && currComp) // paranoia!
00208         {
00209             if (!currComp->IsInvisible())
00210             {
00211                 if (currComp->IsSelected()) 
00212                     gtk_clist_set_pixmap(GTK_CLIST(list), currRow, 0, 
00213                                          checked, ch_mask);
00214                 else
00215                     gtk_clist_set_pixmap(GTK_CLIST(list), currRow, 0, 
00216                                          unchecked, un_mask);
00217 
00218                 gtk_clist_set_text(GTK_CLIST(list), currRow, 1,
00219                                    currComp->GetDescShort());
00220                 currRow++;
00221             }
00222 
00223             currComp = currComp->GetNext();
00224         }
00225 
00226         // by default, first row selected upon Show()
00227         sCurrRowSelected = 0; 
00228 
00229         gtk_signal_connect(GTK_OBJECT(list), "select_row",
00230                            GTK_SIGNAL_FUNC(RowSelected), NULL);
00231         gtk_signal_connect(GTK_OBJECT(list), "key_press_event",
00232                            GTK_SIGNAL_FUNC(KeyPressed), NULL);
00233         gtk_container_add(GTK_CONTAINER(scrollwin), list);
00234         gtk_widget_show(list);
00235         gtk_widget_show(scrollwin);
00236 
00237         hbox = gtk_hbox_new(FALSE, 0);
00238         gtk_box_pack_start(GTK_BOX(hbox), scrollwin, TRUE, TRUE, 0);
00239         gtk_widget_show(hbox);
00240         gtk_table_attach(GTK_TABLE(mTable), hbox, 0, 1, 2, 3,
00241                          static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00242                      static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
00243                       20, 0);
00244 
00245         // XXX     3rd row: labels for ds avail and ds reqd
00246 
00247         // 4th row: a frame with a label (long desc)
00248         descLongTable = gtk_table_new(1, 1, FALSE);
00249         gtk_widget_show(descLongTable);
00250 
00251         gtk_table_attach(GTK_TABLE(mTable), descLongTable, 0, 1, 4, 5,
00252             static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
00253             static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
00254                      20, 20);
00255         frame = gtk_frame_new(gCtx->Res("DESCRIPTION"));
00256         gtk_table_attach_defaults(GTK_TABLE(descLongTable), frame, 0, 1, 0, 1);
00257         gtk_widget_show(frame);
00258 
00259         sDescLong = gtk_label_new(
00260             sCustomST->GetComponents()->GetFirstVisible()->GetDescLong());
00261         gtk_label_set_line_wrap(GTK_LABEL(sDescLong), TRUE);
00262         hbox = gtk_hbox_new(FALSE, 0);
00263         gtk_box_pack_start(GTK_BOX(hbox), sDescLong, FALSE, FALSE, 20);
00264         gtk_widget_show(hbox);
00265 
00266         gtk_table_attach_defaults(GTK_TABLE(descLongTable), hbox, 0, 1, 0, 1);
00267         gtk_widget_show(sDescLong);
00268 
00269         mWidgetsInit = TRUE;
00270     }
00271     else
00272     {
00273         gtk_notebook_set_page(GTK_NOTEBOOK(gCtx->notebook), mPageNum);
00274         gtk_widget_show(mTable);
00275     }
00276 
00277     // signal connect the buttons
00278     gCtx->backID = gtk_signal_connect(GTK_OBJECT(gCtx->back), "clicked",
00279                    GTK_SIGNAL_FUNC(nsComponentsDlg::Back), gCtx->cdlg);
00280     gCtx->nextID = gtk_signal_connect(GTK_OBJECT(gCtx->next), "clicked",
00281                    GTK_SIGNAL_FUNC(nsComponentsDlg::Next), gCtx->cdlg);
00282 
00283     // show back btn again after setup type dlg where we couldn't go back
00284     gtk_widget_set_sensitive(gCtx->back, TRUE);
00285 
00286     if (aDirection == nsXInstallerDlg::BACKWARD_MOVE) // from install dlg
00287       gtk_button_set_label(GTK_BUTTON(gCtx->next), GTK_STOCK_GO_FORWARD);
00288 
00289     return err;
00290 }
00291 
00292 int
00293 nsComponentsDlg::Hide(int aDirection)
00294 {
00295     gtk_widget_hide(mTable);
00296 
00297     return OK;
00298 }
00299 
00300 int
00301 nsComponentsDlg::SetMsg0(char *aMsg)
00302 {
00303     if (!aMsg)
00304         return E_PARAM;
00305 
00306     mMsg0 = aMsg;
00307     
00308     return OK;
00309 }
00310 
00311 char *
00312 nsComponentsDlg::GetMsg0()
00313 {
00314     if (mMsg0)
00315         return mMsg0;
00316 
00317     return NULL;
00318 }
00319 
00320 int
00321 nsComponentsDlg::SetCompList(nsComponentList *aCompList)
00322 {
00323     if (!aCompList)
00324         return E_PARAM;
00325 
00326     mCompList = aCompList;
00327 
00328     return OK;
00329 }
00330 
00331 nsComponentList *
00332 nsComponentsDlg::GetCompList()
00333 {
00334     if (mCompList)
00335         return mCompList;
00336 
00337     return NULL;
00338 }
00339 
00340 void
00341 nsComponentsDlg::RowSelected(GtkWidget *aWidget, gint aRow, gint aColumn,
00342                              GdkEventButton *aEvent, gpointer aData)
00343 {
00344     DUMP("RowSelected");
00345 
00346     sCurrRowSelected = aRow;
00347 
00348     // only toggle row selection state for clicks on the row
00349     if (aColumn == -1 && !aEvent)
00350         return;
00351 
00352     ToggleRowSelection(aWidget, aRow,
00353                        (aColumn == 0 && aEvent->button == 1));
00354 }
00355 
00356 gboolean
00357 nsComponentsDlg::KeyPressed(GtkWidget *aWidget, GdkEventKey *aEvent, 
00358                             gpointer aData)
00359 {
00360   DUMP("KeyPressed");
00361 
00362   if (aEvent->keyval == GDK_space)
00363       ToggleRowSelection(aWidget, sCurrRowSelected, TRUE);
00364 
00365   return FALSE;
00366 }
00367 
00368 void
00369 nsComponentsDlg::ToggleRowSelection(GtkWidget *aWidget, gint aRow,
00370                                     gboolean aToggleState)
00371 {
00372     int numRows = 0, currRow = 0;
00373     GtkStyle *style = NULL;
00374     GdkBitmap *ch_mask = NULL;
00375     GdkPixmap *checked = NULL;
00376     GdkBitmap *un_mask = NULL;
00377     GdkPixmap *unchecked = NULL;
00378     nsComponent *currComp = sCustomST->GetComponents()->GetHead();
00379     
00380     style = gtk_widget_get_style(gCtx->window);
00381     checked = gdk_pixmap_create_from_xpm_d(gCtx->window->window, &ch_mask, 
00382               &style->bg[GTK_STATE_NORMAL], (gchar **)check_on_xpm);
00383     unchecked = gdk_pixmap_create_from_xpm_d(gCtx->window->window, &un_mask,
00384                 &style->bg[GTK_STATE_NORMAL], (gchar **)check_off_xpm);
00385 
00386     numRows = sCustomST->GetComponents()->GetLengthVisible();
00387     while ((currRow < numRows) && currComp) // paranoia!
00388     {
00389         if (!currComp->IsInvisible())
00390         {
00391             if (aRow == currRow)
00392             {
00393                 // update long desc
00394                 gtk_label_set_text(GTK_LABEL(sDescLong),
00395                                    currComp->GetDescLong());
00396                 gtk_widget_show(sDescLong);
00397 
00398                 if (aToggleState) {
00399                   if (currComp->IsSelected()) {
00400                     DUMP("Toggling off...");
00401                     currComp->SetUnselected();
00402                   } else {
00403                     DUMP("Toggling on...");
00404                     currComp->SetSelected();
00405                   }
00406                 }
00407                 currComp->ResolveDependees(currComp->IsSelected(),
00408                                             sCustomST->GetComponents());
00409                 break;
00410             }
00411             currRow++;
00412         }
00413         currComp = currComp->GetNext();
00414     }
00415 
00416     // after resolving dependees redraw all checkboxes in one fell swoop
00417     currRow = 0;
00418     currComp = sCustomST->GetComponents()->GetHead();
00419     while ((currRow < numRows) && currComp) // paranoia!
00420     {
00421         if (!currComp->IsInvisible())
00422         {
00423             if (currComp->IsSelected())
00424             {
00425                 gtk_clist_set_pixmap(GTK_CLIST(aWidget), currRow, 0, 
00426                                      checked, ch_mask);
00427             }
00428             else
00429             {
00430                 gtk_clist_set_pixmap(GTK_CLIST(aWidget), currRow, 0, 
00431                                      unchecked, un_mask);
00432             }
00433             currRow++;
00434         }
00435         currComp = currComp->GetNext();
00436     }
00437 }