Back to index

lightning-sunbird  0.9+nobinonly
nsNativeThemeQt.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * David Hyatt (hyatt@netscape.com).
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Lars Knoll <knoll@kde.org>
00023  *   Zack Rusin <zack@kde.org>
00024  *   Tim Hill (tim@prismelite.com)
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or 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 "nsNativeThemeQt.h"
00041 #include "nsRenderingContextQt.h"
00042 #include "nsDeviceContextQt.h"
00043 #include "nsRect.h"
00044 #include "nsSize.h"
00045 #include "nsTransform2D.h"
00046 #include "nsThemeConstants.h"
00047 #include "nsILookAndFeel.h"
00048 #include "nsIServiceManager.h"
00049 #include "nsIEventStateManager.h"
00050 #include <malloc.h>
00051 
00052 #include <qapplication.h>
00053 #include <qstyle.h>
00054 #include <qpalette.h>
00055 #include <qcombobox.h>
00056 
00057 nsNativeThemeQt::nsNativeThemeQt()
00058 {
00059     combo = new QComboBox((QWidget *)0);
00060     combo->resize(0, 0);
00061     ThemeChanged();
00062 }
00063 
00064 nsNativeThemeQt::~nsNativeThemeQt()
00065 {
00066     delete combo;
00067 }
00068 
00069 NS_IMPL_ISUPPORTS1(nsNativeThemeQt, nsITheme)
00070 
00071 NS_IMETHODIMP
00072 nsNativeThemeQt::DrawWidgetBackground(nsIRenderingContext* aContext,
00073                                       nsIFrame* aFrame,
00074                                       PRUint8 aWidgetType,
00075                                       const nsRect& aRect,
00076                                       const nsRect& aClipRect)
00077 {
00078     nsRenderingContextQt *context = (nsRenderingContextQt *)aContext;
00079     QPainter *p = context->painter();
00080 
00081     //qDebug("aWidgetType = %d", aWidgetType);
00082     if (!p)
00083         return NS_OK;
00084 
00085     QStyle &s = qApp->style();
00086     const QColorGroup &cg = qApp->palette().active();
00087 
00088     QRect r = context->qRect(aRect);
00089     QRect cr = context->qRect(aClipRect);
00090     context->UpdateGC();
00091     //qDebug("rect=%d %d %d %d", aRect.x, aRect.y, aRect.width, aRect.height);
00092     p->save();
00093     p->translate(r.x(), r.y());
00094     r.moveBy(-r.x(), -r.y());
00095 
00096     QStyle::PrimitiveElement pe = QStyle::PE_CustomBase;
00097     QStyle::SFlags flags =  IsDisabled(aFrame) ?
00098                             QStyle::Style_Default :
00099                             QStyle::Style_Enabled;
00100 
00101     PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00102     //qDebug("eventState = %d",  eventState);
00103 
00104     if (eventState & NS_EVENT_STATE_HOVER)
00105         flags |= QStyle::Style_MouseOver;
00106     if (eventState & NS_EVENT_STATE_FOCUS)
00107         flags |= QStyle::Style_HasFocus;
00108     if (eventState & NS_EVENT_STATE_ACTIVE)
00109         flags |= QStyle::Style_Down;
00110 
00111     switch (aWidgetType) {
00112     case NS_THEME_RADIO:
00113         flags |= (IsChecked(aFrame) ? QStyle::Style_On : QStyle::Style_Off);
00114         pe = QStyle::PE_ExclusiveIndicator;
00115         break;
00116     case NS_THEME_CHECKBOX:
00117         flags |= (IsChecked(aFrame) ? QStyle::Style_On : QStyle::Style_Off);
00118         pe = QStyle::PE_Indicator;
00119         break;
00120     case NS_THEME_SCROLLBAR:
00121     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
00122     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
00123         p->fillRect(r, qApp->palette().brush(QPalette::Active, QColorGroup::Background));
00124         break;
00125     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
00126         flags |= QStyle::Style_Horizontal;
00127         // fall through
00128     case NS_THEME_SCROLLBAR_BUTTON_UP:
00129         pe = QStyle::PE_ScrollBarSubLine;
00130         break;
00131     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
00132         flags |= QStyle::Style_Horizontal;
00133         // fall through
00134     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
00135         pe = QStyle::PE_ScrollBarAddLine;
00136         break;
00137     case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL:
00138     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
00139         flags |= QStyle::Style_Horizontal;
00140         // fall through
00141     case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
00142     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
00143         pe = QStyle::PE_ScrollBarSlider;
00144         break;
00145     case NS_THEME_BUTTON_BEVEL:
00146         pe = QStyle::PE_ButtonBevel;
00147         flags |= QStyle::Style_Raised;
00148         break;
00149     case NS_THEME_BUTTON:
00150        pe = IsDefaultButton(aFrame) ? QStyle::PE_ButtonDefault : QStyle::PE_ButtonCommand;
00151         flags |= QStyle::Style_Raised;
00152         break;
00153     case NS_THEME_DROPDOWN:
00154         s.drawComplexControl(QStyle::CC_ComboBox, p, combo, r, cg, flags, QStyle::SC_ComboBoxFrame);
00155         break;
00156     case NS_THEME_DROPDOWN_BUTTON:
00157         r.moveBy(frameWidth, -frameWidth);
00158         r.setHeight(r.height() + 2*frameWidth);
00159         s.drawComplexControl(QStyle::CC_ComboBox, p, combo, r, cg, flags, QStyle::SC_ComboBoxArrow);
00160         break;
00161     case NS_THEME_DROPDOWN_TEXT:
00162     case NS_THEME_DROPDOWN_TEXTFIELD:
00163         break;
00164     case NS_THEME_TEXTFIELD:
00165     case NS_THEME_LISTBOX:
00166         pe = QStyle::PE_PanelLineEdit;
00167         break;
00168     default:
00169         break;
00170     }
00171     if (pe != QStyle::PE_CustomBase)
00172         s.drawPrimitive(pe, p, r, cg, flags);
00173     p->restore();
00174     return NS_OK;
00175 }
00176 
00177 NS_IMETHODIMP
00178 nsNativeThemeQt::GetWidgetBorder(nsIDeviceContext* aContext,
00179                                  nsIFrame* aFrame,
00180                                  PRUint8 aWidgetType,
00181                                  nsMargin* aResult)
00182 {
00183     (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
00184 
00185     switch(aWidgetType) {
00186     case NS_THEME_TEXTFIELD:
00187     case NS_THEME_LISTBOX:
00188         (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right =
00189                          frameWidth;
00190     }
00191 
00192     return NS_OK;
00193 }
00194 
00195 PRBool
00196 nsNativeThemeQt::GetWidgetPadding(nsIDeviceContext* ,
00197                                   nsIFrame*, PRUint8 aWidgetType,
00198                                   nsMargin* aResult)
00199 {
00200     //XXX: is this really correct?
00201     if (aWidgetType == NS_THEME_BUTTON_FOCUS ||
00202         aWidgetType == NS_THEME_TOOLBAR_BUTTON ||
00203         aWidgetType == NS_THEME_TOOLBAR_DUAL_BUTTON) {
00204         aResult->SizeTo(0, 0, 0, 0);
00205         return PR_TRUE;
00206     }
00207 
00208     return PR_FALSE;
00209 }
00210 
00211 NS_IMETHODIMP
00212 nsNativeThemeQt::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame,
00213                                       PRUint8 aWidgetType,
00214                                       nsSize* aResult, PRBool* aIsOverridable)
00215 {
00216     (*aResult).width = (*aResult).height = 0;
00217     *aIsOverridable = PR_TRUE;
00218 
00219     QStyle &s = qApp->style();
00220 
00221     switch (aWidgetType) {
00222     case NS_THEME_RADIO:
00223     case NS_THEME_CHECKBOX: {
00224         QRect rect = s.subRect(aWidgetType == NS_THEME_CHECKBOX
00225                                ? QStyle::SR_CheckBoxIndicator
00226                                : QStyle::SR_RadioButtonIndicator,
00227                                0);
00228         (*aResult).width = rect.width();
00229         (*aResult).height = rect.height();
00230         break;
00231     }
00232     case NS_THEME_SCROLLBAR_BUTTON_UP:
00233     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
00234     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
00235     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
00236         (*aResult).width = s.pixelMetric(QStyle::PM_ScrollBarExtent);
00237         (*aResult).height = (*aResult).width;
00238         *aIsOverridable = PR_FALSE;
00239         break;
00240     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
00241         (*aResult).width = s.pixelMetric(QStyle::PM_ScrollBarExtent);
00242         (*aResult).height = s.pixelMetric(QStyle::PM_ScrollBarSliderMin);
00243         *aIsOverridable = PR_FALSE;
00244         break;
00245     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
00246         (*aResult).width = s.pixelMetric(QStyle::PM_ScrollBarSliderMin);
00247         (*aResult).height = s.pixelMetric(QStyle::PM_ScrollBarExtent);
00248         *aIsOverridable = PR_FALSE;
00249         break;
00250     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
00251         break;
00252     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
00253         break;
00254     case NS_THEME_DROPDOWN_BUTTON: {
00255         QRect r = s.querySubControlMetrics(QStyle::CC_ComboBox, combo, QStyle::SC_ComboBoxArrow);
00256         (*aResult).width = r.width() - 2*frameWidth;
00257         (*aResult).height = r.height() - 2*frameWidth;
00258         break;
00259     }
00260     case NS_THEME_DROPDOWN:
00261     case NS_THEME_DROPDOWN_TEXT:
00262     case NS_THEME_DROPDOWN_TEXTFIELD:
00263     case NS_THEME_TEXTFIELD:
00264         break;
00265     }
00266     return NS_OK;
00267 }
00268 
00269 NS_IMETHODIMP
00270 nsNativeThemeQt::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
00271                                     nsIAtom* aAttribute, PRBool* aShouldRepaint)
00272 {
00273     *aShouldRepaint = TRUE;
00274     return NS_OK;
00275 }
00276 
00277 
00278 NS_IMETHODIMP
00279 nsNativeThemeQt::ThemeChanged()
00280 {
00281     QStyle & s = qApp->style();
00282     frameWidth = s.pixelMetric(QStyle::PM_DefaultFrameWidth);
00283     return NS_OK;
00284 }
00285 
00286 PRBool
00287 nsNativeThemeQt::ThemeSupportsWidget(nsPresContext* aPresContext,
00288                                      nsIFrame* aFrame,
00289                                      PRUint8 aWidgetType)
00290 {
00291     switch (aWidgetType) {
00292     case NS_THEME_SCROLLBAR:
00293     case NS_THEME_SCROLLBAR_BUTTON_UP:
00294     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
00295     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
00296     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
00297     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
00298     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
00299     case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL:
00300     case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
00301     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
00302     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
00303     case NS_THEME_RADIO:
00304     case NS_THEME_CHECKBOX:
00305     case NS_THEME_BUTTON_BEVEL:
00306     case NS_THEME_BUTTON:
00307     case NS_THEME_DROPDOWN:
00308     case NS_THEME_DROPDOWN_BUTTON:
00309     case NS_THEME_DROPDOWN_TEXT:
00310     case NS_THEME_DROPDOWN_TEXTFIELD:
00311     case NS_THEME_TEXTFIELD:
00312     case NS_THEME_LISTBOX:
00313         return PR_TRUE;
00314     default:
00315         break;
00316     }
00317     return PR_FALSE;
00318 }
00319 
00320 PRBool
00321 nsNativeThemeQt::WidgetIsContainer(PRUint8 aWidgetType)
00322 {
00323     // XXXdwh At some point flesh all of this out.
00324     if (aWidgetType == NS_THEME_DROPDOWN_BUTTON ||
00325         aWidgetType == NS_THEME_RADIO ||
00326         aWidgetType == NS_THEME_CHECKBOX)
00327         return PR_FALSE;
00328     return PR_TRUE;
00329 }