Back to index

lightning-sunbird  0.9+nobinonly
nsLookAndFeel.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; 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.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Brian Ryner <bryner@brianryner.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsLookAndFeel.h"
00040 #include <gtk/gtkinvisible.h>
00041 
00042 #define GDK_COLOR_TO_NS_RGB(c) \
00043     ((nscolor) NS_RGB(c.red>>8, c.green>>8, c.blue>>8))
00044 
00045 nscolor nsLookAndFeel::sInfoText = 0;
00046 nscolor nsLookAndFeel::sInfoBackground = 0;
00047 nscolor nsLookAndFeel::sMenuText = 0;
00048 nscolor nsLookAndFeel::sMenuBackground = 0;
00049 nscolor nsLookAndFeel::sButtonBackground = 0;
00050 nscolor nsLookAndFeel::sButtonText = 0;
00051 nscolor nsLookAndFeel::sButtonOuterLightBorder = 0;
00052 nscolor nsLookAndFeel::sButtonInnerDarkBorder = 0;
00053 PRBool nsLookAndFeel::sColorsInitialized = PR_FALSE;
00054 
00055 //-------------------------------------------------------------------------
00056 //
00057 // Query interface implementation
00058 //
00059 //-------------------------------------------------------------------------
00060 nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel()
00061 {
00062   mWidget = gtk_invisible_new();
00063   gtk_widget_ensure_style(mWidget);
00064   mStyle = gtk_widget_get_style(mWidget);
00065 
00066   if (!sColorsInitialized)
00067     InitColors();
00068 }
00069 
00070 nsLookAndFeel::~nsLookAndFeel()
00071 {
00072   //  gtk_widget_destroy(mWidget);
00073   gtk_widget_unref(mWidget);
00074 }
00075 
00076 nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor& aColor)
00077 {
00078   nsresult res = NS_OK;
00079   aColor = 0; // default color black
00080 
00081   switch (aID) {
00082     // These colors don't seem to be used for anything anymore
00083     // in Mozilla.  The CSS2 colors below are used.
00084   case eColor_WindowBackground:
00085     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00086     break;
00087   case eColor_WindowForeground:
00088     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
00089     break;
00090   case eColor_WidgetBackground:
00091     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00092     break;
00093   case eColor_WidgetForeground:
00094     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
00095     break;
00096   case eColor_WidgetSelectBackground:
00097     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
00098     break;
00099   case eColor_WidgetSelectForeground:
00100     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
00101     break;
00102   case eColor_Widget3DHighlight:
00103     aColor = NS_RGB(0xa0,0xa0,0xa0);
00104     break;
00105   case eColor_Widget3DShadow:
00106     aColor = NS_RGB(0x40,0x40,0x40);
00107     break;
00108   case eColor_TextBackground:
00109     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00110     break;
00111   case eColor_TextForeground: 
00112     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
00113     break;
00114   case eColor_TextSelectBackground:
00115     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
00116     break;
00117   case eColor_TextSelectForeground:
00118     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
00119     break;
00120 
00121     // css2  http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
00122   case eColor_activeborder:
00123       // active window border
00124     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00125     break;
00126   case eColor_activecaption:
00127       // active window caption background
00128     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00129     break;
00130   case eColor_appworkspace:
00131       // MDI background color
00132     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00133     break;
00134   case eColor_background:
00135       // desktop background
00136     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00137     break;
00138   case eColor_captiontext:
00139       // text in active window caption, size box, and scrollbar arrow box (!)
00140     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
00141     break;
00142   case eColor_graytext:
00143       // disabled text
00144     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
00145     // or maybe mStyle->text?
00146     break;
00147   case eColor_highlight:
00148   case eColor__moz_menuhover:
00149       // background of selected item
00150     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
00151     break;
00152   case eColor_highlighttext:
00153   case eColor__moz_menuhovertext:
00154       // text of selected item
00155     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
00156     break;
00157   case eColor_inactiveborder:
00158       // inactive window border
00159     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00160     break;
00161   case eColor_inactivecaption:
00162       // inactive window caption
00163     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_INSENSITIVE]);
00164     break;
00165   case eColor_inactivecaptiontext:
00166       // text in inactive window caption
00167     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
00168     break;
00169   case eColor_infobackground:
00170       // tooltip background color
00171     aColor = sInfoBackground;
00172     break;
00173   case eColor_infotext:
00174       // tooltip text color
00175     aColor = sInfoText;
00176     break;
00177   case eColor_menu:
00178       // menu background
00179     aColor = sMenuBackground;
00180     break;
00181   case eColor_menutext:
00182       // menu text
00183     aColor = sMenuText;
00184     break;
00185   case eColor_scrollbar:
00186       // scrollbar gray area
00187     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_ACTIVE]);
00188     break;
00189 
00190   case eColor_threedface:
00191   case eColor_buttonface:
00192   case eColor__moz_buttonhoverface:
00193       // 3-D face color
00194     aColor = sButtonBackground;
00195     break;
00196 
00197   case eColor_buttontext:
00198   case eColor__moz_buttonhovertext:
00199       // text on push buttons
00200     aColor = sButtonText;
00201     break;
00202 
00203   case eColor_buttonhighlight:
00204       // 3-D highlighted edge color
00205   case eColor_threedhighlight:
00206       // 3-D highlighted outer edge color
00207     aColor = sButtonOuterLightBorder;
00208     break;
00209 
00210   case eColor_threedlightshadow:
00211       // 3-D highlighted inner edge color
00212     aColor = sButtonBackground; // always same as background in GTK code
00213     break;
00214 
00215   case eColor_buttonshadow:
00216       // 3-D shadow edge color
00217   case eColor_threedshadow:
00218       // 3-D shadow inner edge color
00219     aColor = sButtonInnerDarkBorder;
00220     break;
00221 
00222   case eColor_threeddarkshadow:
00223       // 3-D shadow outer edge color
00224     aColor = GDK_COLOR_TO_NS_RGB(mStyle->black);
00225     break;
00226 
00227   case eColor_window:
00228   case eColor_windowframe:
00229     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00230     break;
00231 
00232   case eColor_windowtext:
00233     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
00234     break;
00235 
00236   // from the CSS3 working draft (not yet finalized)
00237   // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color
00238 
00239   case eColor__moz_field:
00240     aColor = GDK_COLOR_TO_NS_RGB(mStyle->base[GTK_STATE_NORMAL]);
00241     break;
00242   case eColor__moz_fieldtext:
00243     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
00244     break;
00245   case eColor__moz_dialog:
00246   case eColor__moz_cellhighlight:
00247     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
00248     break;
00249   case eColor__moz_dialogtext:
00250   case eColor__moz_cellhighlighttext:
00251     aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
00252     break;
00253   case eColor__moz_dragtargetzone:
00254     aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
00255     break; 
00256   case eColor__moz_buttondefault:
00257       // default button border color
00258     aColor = GDK_COLOR_TO_NS_RGB(mStyle->black);
00259     break;
00260   default:
00261     /* default color is BLACK */
00262     aColor = 0;
00263     res    = NS_ERROR_FAILURE;
00264     break;
00265   }
00266 
00267   //  printf("%i, %i, %i\n", NS_GET_R(aColor), NS_GET_B(aColor), NS_GET_G(aColor));
00268 
00269   return res;
00270 }
00271 
00272 NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
00273 {
00274   nsresult res = NS_OK;
00275 
00276   res = nsXPLookAndFeel::GetMetric(aID, aMetric);
00277   if (NS_SUCCEEDED(res))
00278     return res;
00279   res = NS_OK;
00280 
00281   switch (aID) {
00282   case eMetric_WindowTitleHeight:
00283     aMetric = 0;
00284     break;
00285   case eMetric_WindowBorderWidth:
00286     // XXXldb Why is this commented out?
00287     //    aMetric = mStyle->klass->xthickness;
00288     break;
00289   case eMetric_WindowBorderHeight:
00290     // XXXldb Why is this commented out?
00291     //    aMetric = mStyle->klass->ythickness;
00292     break;
00293   case eMetric_Widget3DBorder:
00294     // XXXldb Why is this commented out?
00295     //    aMetric = 4;
00296     break;
00297   case eMetric_TextFieldHeight:
00298     {
00299       GtkRequisition req;
00300       GtkWidget *text = gtk_entry_new();
00301       // needed to avoid memory leak
00302       gtk_widget_ref(text);
00303       gtk_object_sink(GTK_OBJECT(text));
00304       gtk_widget_size_request(text,&req);
00305       aMetric = req.height;
00306       gtk_widget_destroy(text);
00307       gtk_widget_unref(text);
00308     }
00309     break;
00310   case eMetric_TextFieldBorder:
00311     aMetric = 2;
00312     break;
00313   case eMetric_TextVerticalInsidePadding:
00314     aMetric = 0;
00315     break;
00316   case eMetric_TextShouldUseVerticalInsidePadding:
00317     aMetric = 0;
00318     break;
00319   case eMetric_TextHorizontalInsideMinimumPadding:
00320     aMetric = 15;
00321     break;
00322   case eMetric_TextShouldUseHorizontalInsideMinimumPadding:
00323     aMetric = 1;
00324     break;
00325   case eMetric_ButtonHorizontalInsidePaddingNavQuirks:
00326     aMetric = 10;
00327     break;
00328   case eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks:
00329     aMetric = 8;
00330     break;
00331   case eMetric_CheckboxSize:
00332     aMetric = 15;
00333     break;
00334   case eMetric_RadioboxSize:
00335     aMetric = 15;
00336     break;
00337   case eMetric_ListShouldUseHorizontalInsideMinimumPadding:
00338     aMetric = 15;
00339     break;
00340   case eMetric_ListHorizontalInsideMinimumPadding:
00341     aMetric = 15;
00342     break;
00343   case eMetric_ListShouldUseVerticalInsidePadding:
00344     aMetric = 1;
00345     break;
00346   case eMetric_ListVerticalInsidePadding:
00347     aMetric = 1;
00348     break;
00349   case eMetric_CaretBlinkTime:
00350     aMetric = 500;
00351     break;
00352   case eMetric_CaretWidth:
00353     aMetric = 1;
00354     break;
00355   case eMetric_ShowCaretDuringSelection:
00356     aMetric = 0;
00357     break;
00358   case eMetric_SelectTextfieldsOnKeyFocus:
00359     // Select textfield content when focused by kbd
00360     // used by nsEventStateManager::sTextfieldSelectModel
00361     aMetric = 1;
00362     break;
00363   case eMetric_SubmenuDelay:
00364     aMetric = 200;
00365     break;
00366   case eMetric_MenusCanOverlapOSBar:
00367     // we want XUL popups to be able to overlap the task bar.
00368     aMetric = 1;
00369     break;
00370   case eMetric_SkipNavigatingDisabledMenuItem:
00371     aMetric = 1;
00372     break;
00373   case eMetric_DragFullWindow:
00374     aMetric = 1;
00375     break;
00376   case eMetric_DragThresholdX:
00377   case eMetric_DragThresholdY:
00378     // hardcoded in gtkdnd.c
00379     aMetric = 3;
00380     break;
00381   case eMetric_ScrollArrowStyle:
00382     aMetric = eMetric_ScrollArrowStyleSingle;
00383     break;
00384   case eMetric_ScrollSliderStyle:
00385     aMetric = eMetric_ScrollThumbStyleProportional;
00386     break;
00387   case eMetric_TreeOpenDelay:
00388     aMetric = 1000;
00389     break;
00390   case eMetric_TreeCloseDelay:
00391     aMetric = 1000;
00392     break;
00393   case eMetric_TreeLazyScrollDelay:
00394     aMetric = 150;
00395     break;
00396   case eMetric_TreeScrollDelay:
00397     aMetric = 100;
00398     break;
00399   case eMetric_TreeScrollLinesMax:
00400     aMetric = 3;
00401     break;
00402 
00403   default:
00404     aMetric = 0;
00405     res     = NS_ERROR_FAILURE;
00406   }
00407 
00408   return res;
00409 }
00410 
00411 NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetric)
00412 {
00413   nsresult res = NS_OK;
00414   res = nsXPLookAndFeel::GetMetric(aID, aMetric);
00415   if (NS_SUCCEEDED(res))
00416     return res;
00417   res = NS_OK;
00418 
00419   switch (aID) {
00420   case eMetricFloat_TextFieldVerticalInsidePadding:
00421     aMetric = 0.25f;
00422     break;
00423   case eMetricFloat_TextFieldHorizontalInsidePadding:
00424     aMetric = 0.95f; // large number on purpose so minimum padding is used
00425     break;
00426   case eMetricFloat_TextAreaVerticalInsidePadding:
00427     aMetric = 0.40f;    
00428     break;
00429   case eMetricFloat_TextAreaHorizontalInsidePadding:
00430     aMetric = 0.40f; // large number on purpose so minimum padding is used
00431     break;
00432   case eMetricFloat_ListVerticalInsidePadding:
00433     aMetric = 0.10f;
00434     break;
00435   case eMetricFloat_ListHorizontalInsidePadding:
00436     aMetric = 0.40f;
00437     break;
00438   case eMetricFloat_ButtonVerticalInsidePadding:
00439     aMetric = 0.25f;
00440     break;
00441   case eMetricFloat_ButtonHorizontalInsidePadding:
00442     aMetric = 0.25f;
00443     break;
00444   default:
00445     aMetric = -1.0;
00446     res = NS_ERROR_FAILURE;
00447   }
00448   return res;
00449 }
00450 
00451 void
00452 nsLookAndFeel::InitColors()
00453 {
00454   sColorsInitialized = PR_TRUE;
00455   GtkStyle *style;
00456   
00457   // tooltip foreground and background
00458   GtkTooltips *tooltips = gtk_tooltips_new();
00459   gtk_tooltips_force_window(tooltips);
00460   GtkWidget *tip_window = tooltips->tip_window;
00461   gtk_widget_set_rc_style(tip_window);
00462 
00463   style = gtk_widget_get_style(tip_window);
00464   sInfoBackground = GDK_COLOR_TO_NS_RGB(style->bg[GTK_STATE_NORMAL]);
00465   sInfoText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_NORMAL]);
00466 
00467   gtk_object_unref(GTK_OBJECT(tooltips));
00468 
00469 
00470   // menu foreground & menu background
00471   GtkWidget *accel_label = gtk_accel_label_new("M");
00472   GtkWidget *menuitem = gtk_menu_item_new();
00473   GtkWidget *menu = gtk_menu_new();
00474 
00475   gtk_container_add(GTK_CONTAINER(menuitem), accel_label);
00476   gtk_menu_append(GTK_MENU(menu), menuitem);
00477 
00478   gtk_widget_set_rc_style(accel_label);
00479   gtk_widget_set_rc_style(menu);
00480   gtk_widget_realize(menu);
00481   gtk_widget_realize(accel_label);
00482 
00483   style = gtk_widget_get_style(accel_label);
00484   sMenuText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_NORMAL]);
00485 
00486   style = gtk_widget_get_style(menu);
00487   sMenuBackground = GDK_COLOR_TO_NS_RGB(style->bg[GTK_STATE_NORMAL]);
00488 
00489   gtk_widget_unref(menu);
00490 
00491 
00492   // button styles
00493   GtkWidget *parent = gtk_fixed_new();
00494   GtkWidget *button = gtk_button_new();
00495   GtkWidget *label = gtk_label_new("M");
00496   GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
00497   
00498   gtk_container_add(GTK_CONTAINER(button), label);
00499   gtk_container_add(GTK_CONTAINER(parent), button);
00500   gtk_container_add(GTK_CONTAINER(window), parent);
00501 
00502   gtk_widget_set_rc_style(button);
00503   gtk_widget_set_rc_style(label);
00504 
00505   gtk_widget_realize(button);
00506   gtk_widget_realize(label);
00507 
00508   style = gtk_widget_get_style(label);
00509   sButtonText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_NORMAL]);
00510 
00511   style = gtk_widget_get_style(button);
00512   sButtonBackground = GDK_COLOR_TO_NS_RGB(style->bg[GTK_STATE_NORMAL]);
00513   sButtonOuterLightBorder =
00514     GDK_COLOR_TO_NS_RGB(style->light[GTK_STATE_NORMAL]);
00515   sButtonInnerDarkBorder =
00516     GDK_COLOR_TO_NS_RGB(style->dark[GTK_STATE_NORMAL]);
00517 
00518   gtk_widget_destroy(window);
00519 
00520 }