bug 155053, add spinbuttons widget, with native theming, r+sr=neil and roc

This commit is contained in:
enndeakin%sympatico.ca 2006-07-13 17:40:49 +00:00
Родитель 34dc892f80
Коммит 9cd7d5d3df
18 изменённых файлов: 377 добавлений и 2633 удалений

Просмотреть файл

@ -37,18 +37,30 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
.up {
list-style-image: url("chrome://global/skin/spinbtn-up.gif")
spinbuttons {
height: 24px;
min-height: 24px;
-moz-appearance: spinner;
cursor: default;
}
.up:hover:active {
list-style-image: url("chrome://global/skin/spinbtn-up-act.gif")
.spinbuttons-up {
-moz-appearance: none;
-moz-box-flex: 1;
min-width: 12px;
margin: 0;
padding: 0;
border: none !important;
background: none !important;
}
.down {
list-style-image: url("chrome://global/skin/spinbtn-dn.gif")
.spinbuttons-down {
-moz-appearance: none;
-moz-box-flex: 1;
min-width: 12px;
margin: 0;
padding: 0;
border: none !important;
background: none !important;
}
.down:hover:active {
list-style-image: url("chrome://global/skin/spinbtn-dn-act.gif")
}

Просмотреть файл

@ -37,18 +37,67 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
.up {
list-style-image: url("chrome://global/skin/spinbtn-up.gif")
spinbuttons {
cursor: default;
}
.up:hover:active {
list-style-image: url("chrome://global/skin/spinbtn-up-act.gif")
.spinbuttons-button {
min-width: 13px;
min-height: 11px;
margin: 0 !important;
border: 2px solid;
-moz-border-top-colors: ThreeDHighlight ThreeDLightShadow;
-moz-border-right-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-left-colors: ThreeDHighlight ThreeDLightShadow;
background-color: ThreeDFace;
}
.down {
list-style-image: url("chrome://global/skin/spinbtn-dn.gif")
.spinbuttons-button > .button-box {
border: 0;
padding: 0;
margin: 0;
}
.down:hover:active {
list-style-image: url("chrome://global/skin/spinbtn-dn-act.gif")
.spinbuttons-button[disabled="true"] > .button-box {
padding: 0 !important;
}
.spinbuttons-button:hover:active
{
border: 2px solid;
-moz-border-top-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-right-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-left-colors: ThreeDDarkShadow ThreeDShadow;
}
.spinbuttons-button[disabled="true"] {
border: 2px solid;
-moz-border-top-colors: ThreeDHighlight ThreeDLightShadow !important;
-moz-border-right-colors: ThreeDDarkShadow ThreeDShadow !important;
-moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow !important;
-moz-border-left-colors: ThreeDHighlight ThreeDLightShadow !important;
}
.spinbuttons-up {
-moz-appearance: spinner-upbutton;
background-image: url("chrome://global/skin/arrow/arrow-up.gif");
background-position: center center;
background-repeat: no-repeat;
}
.spinbuttons-up[disabled="true"] {
background-image: url("chrome://global/skin/arrow/arrow-up-dis.gif");
}
.spinbuttons-down {
-moz-appearance: spinner-downbutton;
background-image: url("chrome://global/skin/arrow/arrow-dn.gif");
background-position: center center;
background-repeat: no-repeat;
}
.spinbuttons-down[disabled="true"] {
background-image: url("chrome://global/skin/arrow/arrow-dn-dis.gif");
}

Просмотреть файл

@ -1,52 +0,0 @@
/* ***** 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
* Håkan Waara Portions created by Håkan Waara are Copyright (C) Håkan Waara. All Rights Reserved.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Håkan Waara (Original Author)
*
* 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 ***** */
.up {
list-style-image: url("chrome://global/skin/spinbuttons/btn-up.gif");
}
.up:hover:active {
list-style-image: url("chrome://global/skin/spinbuttons/btn-up-act.gif");
}
.down {
list-style-image: url("chrome://global/skin/spinbuttons/btn-dn.gif");
}
.down:hover:active {
list-style-image: url("chrome://global/skin/spinbuttons/btn-dn-act.gif");
}

Просмотреть файл

@ -43,19 +43,87 @@
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="spinbuttons"
extends="chrome://global/content/bindings/spinbuttons.xml#spinbuttons-baseline">
extends="chrome://global/content/bindings/general.xml#basecontrol">
<resources>
<stylesheet src="chrome://global/skin/spinbuttons.css"/>
</resources>
</binding>
<binding id="spinbuttons-baseline">
<content>
<xul:vbox flex="1" align="center">
<xul:image xbl:inherits="onclick=onup" id="upButton" class="up"/>
<xul:image xbl:inherits="onclick=ondown" id="downButton" class="down"/>
<xul:vbox class="spinbuttons-box" flex="1">
<xul:button anonid="increaseButton" type="repeat" flex="1"
class="spinbuttons-button spinbuttons-up"
xbl:inherits="disabled,disabled=increasedisabled"/>
<xul:button anonid="decreaseButton" type="repeat" flex="1"
class="spinbuttons-button spinbuttons-down"
xbl:inherits="disabled,disabled=decreasedisabled"/>
</xul:vbox>
</content>
<implementation>
<property name="_increaseButton" readonly="true">
<getter>
return document.getAnonymousElementByAttribute(this, "anonid", "increaseButton");
</getter>
</property>
<property name="_decreaseButton" readonly="true">
<getter>
return document.getAnonymousElementByAttribute(this, "anonid", "decreaseButton");
</getter>
</property>
<property name="increaseDisabled"
onget="return this._increaseButton.getAttribute('disabled');"
onset="if (val) this._increaseButton.setAttribute('disabled', 'true');
else this._increaseButton.removeAttribute('disabled'); return val;"/>
<property name="decreaseDisabled"
onget="return this._decreaseButton.getAttribute('disabled');"
onset="if (val) this._decreaseButton.setAttribute('disabled', 'true');
else this._decreaseButton.removeAttribute('disabled'); return val;"/>
</implementation>
<handlers>
<handler event="mousedown">
<![CDATA[
// on the Mac, the native theme draws the spinbutton as a single widget
// so a state attribute is set based on where the mouse button was pressed
if (event.originalTarget == this._increaseButton)
this.setAttribute("state", "up");
else if (event.originalTarget == this._decreaseButton)
this.setAttribute("state", "down");
]]>
</handler>
<handler event="mouseup">
this.removeAttribute("state");
</handler>
<handler event="mouseout">
this.removeAttribute("state");
</handler>
<handler event="command">
<![CDATA[
var eventname;
if (event.originalTarget == this._increaseButton)
eventname = "up";
else if (event.originalTarget == this._decreaseButton)
eventname = "down";
var evt = document.createEvent("Events");
evt.initEvent(eventname, true, true);
var cancel = this.dispatchEvent(evt);
if (this.hasAttribute("on" + eventname)) {
var fn = new Function("event", this.getAttribute("on" + eventname));
if (fn.call(this, event) == false)
cancel = true;
}
return !cancel;
]]>
</handler>
</handlers>
</binding>
</bindings>

Просмотреть файл

@ -37,18 +37,26 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
.up {
list-style-image: url("chrome://global/skin/spinbtn-up.gif")
spinbuttons {
height: 24px;
min-height: 24px;
-moz-appearance: spinner;
cursor: default;
}
.up:hover:active {
list-style-image: url("chrome://global/skin/spinbtn-up-act.gif")
.spinbuttons-up {
-moz-appearance: none;
-moz-box-flex: 1;
min-width: 12px;
margin: 0;
padding: 0;
}
.down {
list-style-image: url("chrome://global/skin/spinbtn-dn.gif")
.spinbuttons-down {
-moz-appearance: none;
-moz-box-flex: 1;
min-width: 12px;
margin: 0;
padding: 0;
}
.down:hover:active {
list-style-image: url("chrome://global/skin/spinbtn-dn-act.gif")
}

Просмотреть файл

@ -37,18 +37,61 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
.up {
list-style-image: url("chrome://global/skin/spinbtn-up.gif")
spinbuttons {
cursor: default;
}
.up:hover:active {
list-style-image: url("chrome://global/skin/spinbtn-up-act.gif")
.spinbuttons-button {
min-width: 13px;
min-height: 11px;
margin: 0 !important;
border: 2px solid;
-moz-border-top-colors: ThreeDHighlight ThreeDLightShadow;
-moz-border-right-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-left-colors: ThreeDHighlight ThreeDLightShadow;
background-color: ThreeDFace;
}
.down {
list-style-image: url("chrome://global/skin/spinbtn-dn.gif")
.spinbuttons-button > .button-box {
border: 0;
}
.down:hover:active {
list-style-image: url("chrome://global/skin/spinbtn-dn-act.gif")
.spinbuttons-button:hover:active
{
border: 2px solid;
-moz-border-top-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-right-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow;
-moz-border-left-colors: ThreeDDarkShadow ThreeDShadow;
}
.spinbuttons-button[disabled="true"] {
border: 2px solid;
-moz-border-top-colors: ThreeDHighlight ThreeDLightShadow !important;
-moz-border-right-colors: ThreeDDarkShadow ThreeDShadow !important;
-moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow !important;
-moz-border-left-colors: ThreeDHighlight ThreeDLightShadow !important;
}
.spinbuttons-up {
-moz-appearance: spinner-upbutton;
background-image: url("chrome://global/skin/arrow/arrow-up.gif");
background-position: center center;
background-repeat: no-repeat;
}
.spinbuttons-up[disabled="true"] {
background-image: url("chrome://global/skin/arrow/arrow-up-dis.gif");
}
.spinbuttons-down {
-moz-appearance: spinner-downbutton;
background-image: url("chrome://global/skin/arrow/arrow-dn.gif");
background-position: center center;
background-repeat: no-repeat;
}
.spinbuttons-down[disabled="true"] {
background-image: url("chrome://global/skin/arrow/arrow-dn-dis.gif");
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,290 +0,0 @@
/* -*- Mode: C; tab-width: 2; 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) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
/**
* gtkdrawing.h: GTK widget rendering utilities
*
* gtkdrawing provides an API for rendering GTK widgets in the
* current theme to a pixmap or window, without requiring an actual
* widget instantiation, similar to the Macintosh Appearance Manager
* or Windows XP's DrawThemeBackground() API.
*/
#ifndef _GTK_DRAWING_H_
#define _GTK_DRAWING_H_
#include <gdk/gdk.h>
#include <gtk/gtkstyle.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*** type definitions ***/
typedef struct {
guint8 active;
guint8 focused;
guint8 inHover;
guint8 disabled;
guint8 isDefault;
guint8 canDefault;
gint32 curpos; /* curpos and maxpos are used for scrollbars */
gint32 maxpos;
} GtkWidgetState;
typedef struct {
gint slider_width;
gint trough_border;
gint stepper_size;
gint stepper_spacing;
gint min_slider_size;
} MozGtkScrollbarMetrics;
/** flags for tab state **/
typedef enum {
/* the first tab in the group */
MOZ_GTK_TAB_FIRST = 1 << 0,
/* the tab just before the selected tab */
MOZ_GTK_TAB_BEFORE_SELECTED = 1 << 1,
/* the selected tab */
MOZ_GTK_TAB_SELECTED = 1 << 2
} GtkTabFlags;
/* function type for moz_gtk_enable_style_props */
typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint);
/*** result/error codes ***/
#define MOZ_GTK_SUCCESS 0
#define MOZ_GTK_UNKNOWN_WIDGET -1
#define MOZ_GTK_UNSAFE_THEME -2
/*** widget type constants ***/
typedef enum {
/* Paints a GtkButton. flags is a GtkReliefStyle. */
MOZ_GTK_BUTTON,
/* Paints a GtkCheckButton. flags is a boolean, 1=checked, 0=not checked. */
MOZ_GTK_CHECKBUTTON,
/* Paints a GtkRadioButton. flags is a boolean, 1=checked, 0=not checked. */
MOZ_GTK_RADIOBUTTON,
/**
* Paints the button of a GtkScrollbar. flags is a GtkArrowType giving
* the arrow direction.
*/
MOZ_GTK_SCROLLBAR_BUTTON,
/* Paints the trough (track) of a GtkScrollbar. */
MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL,
MOZ_GTK_SCROLLBAR_TRACK_VERTICAL,
/* Paints the slider (thumb) of a GtkScrollbar. */
MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL,
MOZ_GTK_SCROLLBAR_THUMB_VERTICAL,
/* Paints a GtkScale. */
MOZ_GTK_SCALE_HORIZONTAL,
MOZ_GTK_SCALE_VERTICAL,
/* Paints a GtkScale thumb. */
MOZ_GTK_SCALE_THUMB_HORIZONTAL,
MOZ_GTK_SCALE_THUMB_VERTICAL,
/* Paints the gripper of a GtkHandleBox. */
MOZ_GTK_GRIPPER,
/* Paints a GtkEntry. */
MOZ_GTK_ENTRY,
/* Paints a GtkOptionMenu. */
MOZ_GTK_DROPDOWN,
/* Paints a dropdown arrow (a GtkButton containing a down GtkArrow). */
MOZ_GTK_DROPDOWN_ARROW,
/* Paints the container part of a GtkCheckButton. */
MOZ_GTK_CHECKBUTTON_CONTAINER,
/* Paints the container part of a GtkRadioButton. */
MOZ_GTK_RADIOBUTTON_CONTAINER,
/* Paints the label of a GtkCheckButton (focus outline) */
MOZ_GTK_CHECKBUTTON_LABEL,
/* Paints the label of a GtkRadioButton (focus outline) */
MOZ_GTK_RADIOBUTTON_LABEL,
/* Paints the background of a GtkHandleBox. */
MOZ_GTK_TOOLBAR,
/* Paints a GtkToolTip */
MOZ_GTK_TOOLTIP,
/* Paints a GtkFrame (e.g. a status bar panel). */
MOZ_GTK_FRAME,
/* Paints a GtkProgressBar. */
MOZ_GTK_PROGRESSBAR,
/* Paints a progress chunk of a GtkProgressBar. */
MOZ_GTK_PROGRESS_CHUNK,
/* Paints a tab of a GtkNotebook. flags is a GtkTabFlags, defined above. */
MOZ_GTK_TAB,
/* Paints the background and border of a GtkNotebook. */
MOZ_GTK_TABPANELS,
/* Paints the background of the menu bar. */
MOZ_GTK_MENUBAR,
/* Paints the background of menus, context menus. */
MOZ_GTK_MENUPOPUP,
/* Paints items of menubar and popups. */
MOZ_GTK_MENUITEM,
MOZ_GTK_CHECKMENUITEM,
MOZ_GTK_RADIOMENUITEM,
/* Paints the background of a window, dialog or page. */
MOZ_GTK_WINDOW
} GtkThemeWidgetType;
/*** General library functions ***/
/**
* Initializes the drawing library. You must call this function
* prior to using any other functionality.
* returns: MOZ_GTK_SUCCESS if there were no errors
* MOZ_GTK_UNSAFE_THEME if the current theme engine is known
* to crash with gtkdrawing.
*/
gint moz_gtk_init();
/**
* Enable GTK+ 1.2.9+ theme enhancements. You must provide a pointer
* to the GTK+ 1.2.9+ function "gtk_style_get_prop_experimental".
* styleGetProp: pointer to gtk_style_get_prop_experimental
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint moz_gtk_enable_style_props(style_prop_t styleGetProp);
/**
* Perform cleanup of the drawing library. You should call this function
* when your program exits, or you no longer need the library.
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint moz_gtk_shutdown();
/*** Widget drawing ***/
/**
* Paint a widget in the current theme.
* widget: a constant giving the widget to paint
* rect: the bounding rectangle for the widget
* cliprect: a clipprect rectangle for this painting operation
* state: the state of the widget. ignored for some widgets.
* flags: widget-dependant flags; see the GtkThemeWidgetType definition.
*/
gint
moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
GdkRectangle* rect, GdkRectangle* cliprect,
GtkWidgetState* state, gint flags);
/*** Widget metrics ***/
/**
* Get the border size of a widget
* xthickness: [OUT] the widget's left/right border
* ythickness: [OUT] the widget's top/bottom border
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* xthickness,
gint* ythickness);
/**
* Get the desired size of a GtkCheckButton
* indicator_size: [OUT] the indicator size
* indicator_spacing: [OUT] the spacing between the indicator and its
* container
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint
moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing);
/**
* Get the desired size of a GtkRadioButton
* indicator_size: [OUT] the indicator size
* indicator_spacing: [OUT] the spacing between the indicator and its
* container
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint
moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing);
/** Get the focus metrics for a button, checkbox, or radio button.
* interior_focus: [OUT] whether the focus is drawn around the
* label (TRUE) or around the whole container (FALSE)
* focus_width: [OUT] the width of the focus line
* focus_pad: [OUT] the padding between the focus line and children
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint
moz_gtk_button_get_focus(gboolean* interior_focus,
gint* focus_width, gint* focus_pad);
gint
moz_gtk_checkbox_get_focus(gboolean* interior_focus,
gint* focus_width, gint* focus_pad);
gint
moz_gtk_radio_get_focus(gboolean* interior_focus,
gint* focus_width, gint* focus_pad);
/**
* Get the desired size of a GtkScale thumb
* orient: [IN] the scale orientation
* thumb_length: [OUT] the length of the thumb
* thumb_height: [OUT] the height of the thumb
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint
moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height);
/**
* Get the desired metrics for a GtkScrollbar
* metrics: [IN] struct which will contain the metrics
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint
moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics* metrics);
/**
* Get the desired size of a dropdown arrow button
* width: [OUT] the desired width
* height: [OUT] the desired height
*
* returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
*/
gint moz_gtk_get_dropdown_arrow_size(gint* width, gint* height);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

Просмотреть файл

@ -1,860 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
#include "nsNativeThemeGTK.h"
#include "nsThemeConstants.h"
#include "gtkdrawing.h"
#include "nsIObserverService.h"
#include "nsIServiceManager.h"
#include "nsIFrame.h"
#include "nsIPresShell.h"
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsIEventStateManager.h"
#include "nsIViewManager.h"
#include "nsINameSpaceManager.h"
#include "nsILookAndFeel.h"
#include "nsIDeviceContext.h"
#include "nsGfxCIID.h"
#include "nsTransform2D.h"
#include "nsIMenuFrame.h"
#include "nsIMenuParent.h"
#include "nsWidgetAtoms.h"
#include "prlink.h"
#include <gdk/gdkprivate.h>
#include <gdk/gdkx.h>
NS_IMPL_ISUPPORTS2(nsNativeThemeGTK, nsITheme, nsIObserver)
static int gLastXError;
nsNativeThemeGTK::nsNativeThemeGTK()
{
if (moz_gtk_init() != MOZ_GTK_SUCCESS) {
memset(mDisabledWidgetTypes, 0xff, sizeof(mDisabledWidgetTypes));
return;
}
// We have to call moz_gtk_shutdown before the event loop stops running.
nsCOMPtr<nsIObserverService> obsServ =
do_GetService("@mozilla.org/observer-service;1");
obsServ->AddObserver(this, "xpcom-shutdown", PR_FALSE);
memset(mDisabledWidgetTypes, 0, sizeof(mDisabledWidgetTypes));
memset(mSafeWidgetStates, 0, sizeof(mSafeWidgetStates));
#ifdef MOZ_WIDGET_GTK
// Look up the symbol for gtk_style_get_prop_experimental
PRLibrary* gtkLibrary;
PRFuncPtr stylePropFunc = PR_FindFunctionSymbolAndLibrary("gtk_style_get_prop_experimental", &gtkLibrary);
if (stylePropFunc) {
moz_gtk_enable_style_props((style_prop_t) stylePropFunc);
PR_UnloadLibrary(gtkLibrary);
}
#endif
}
nsNativeThemeGTK::~nsNativeThemeGTK() {
}
NS_IMETHODIMP
nsNativeThemeGTK::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *aData)
{
if (!nsCRT::strcmp(aTopic, "xpcom-shutdown")) {
moz_gtk_shutdown();
} else {
NS_NOTREACHED("unexpected topic");
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
void
nsNativeThemeGTK::RefreshWidgetWindow(nsIFrame* aFrame)
{
nsIPresShell *shell = GetPresShell(aFrame);
if (!shell)
return;
nsIViewManager* vm = shell->GetViewManager();
if (!vm)
return;
vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
}
static PRBool IsWidgetTypeDisabled(PRUint8* aDisabledVector, PRUint8 aWidgetType) {
return aDisabledVector[aWidgetType >> 3] & (1 << (aWidgetType & 7));
}
static void SetWidgetTypeDisabled(PRUint8* aDisabledVector, PRUint8 aWidgetType) {
aDisabledVector[aWidgetType >> 3] |= (1 << (aWidgetType & 7));
}
static inline PRUint16
GetWidgetStateKey(PRUint8 aWidgetType, GtkWidgetState *aWidgetState)
{
return (aWidgetState->active |
aWidgetState->focused << 1 |
aWidgetState->inHover << 2 |
aWidgetState->disabled << 3 |
aWidgetState->isDefault << 4 |
aWidgetType << 5);
}
static PRBool IsWidgetStateSafe(PRUint8* aSafeVector,
PRUint8 aWidgetType,
GtkWidgetState *aWidgetState)
{
PRUint8 key = GetWidgetStateKey(aWidgetType, aWidgetState);
return aSafeVector[key >> 3] & (1 << (key & 7));
}
static void SetWidgetStateSafe(PRUint8 *aSafeVector,
PRUint8 aWidgetType,
GtkWidgetState *aWidgetState)
{
PRUint8 key = GetWidgetStateKey(aWidgetType, aWidgetState);
aSafeVector[key >> 3] |= (1 << (key & 7));
}
PRBool
nsNativeThemeGTK::GetGtkWidgetAndState(PRUint8 aWidgetType, nsIFrame* aFrame,
GtkThemeWidgetType& aGtkWidgetType,
GtkWidgetState* aState,
gint* aWidgetFlags)
{
if (aState) {
if (!aFrame) {
// reset the entire struct to zero
memset(aState, 0, sizeof(GtkWidgetState));
} else {
// for dropdown textfields, look at the parent frame (textbox or menulist)
if (aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD)
aFrame = aFrame->GetParent();
// For XUL checkboxes and radio buttons, the state of the parent
// determines our state.
nsIFrame *stateFrame = aFrame;
if (aFrame && ((aWidgetFlags && (aWidgetType == NS_THEME_CHECKBOX ||
aWidgetType == NS_THEME_RADIO)) ||
aWidgetType == NS_THEME_CHECKBOX_LABEL ||
aWidgetType == NS_THEME_RADIO_LABEL)) {
nsIAtom* atom = nsnull;
nsIContent *content = aFrame->GetContent();
if (content->IsNodeOfType(nsINode::eXUL)) {
if (aWidgetType == NS_THEME_CHECKBOX_LABEL ||
aWidgetType == NS_THEME_RADIO_LABEL) {
// Adjust stateFrame so GetContentState finds the correct state.
stateFrame = aFrame = aFrame->GetParent()->GetParent();
} else {
// GetContentState knows to look one frame up for radio/checkbox
// widgets, so don't adjust stateFrame here.
aFrame = aFrame->GetParent();
}
} else if (content->Tag() == nsWidgetAtoms::input) {
atom = nsWidgetAtoms::mozinputchecked;
}
if (aWidgetFlags) {
if (!atom) {
atom = (aWidgetType == NS_THEME_CHECKBOX ||
aWidgetType == NS_THEME_CHECKBOX_LABEL) ? nsWidgetAtoms::checked
: nsWidgetAtoms::selected;
}
*aWidgetFlags = CheckBooleanAttr(aFrame, atom);
}
}
PRInt32 eventState = GetContentState(stateFrame, aWidgetType);
aState->disabled = IsDisabled(aFrame);
aState->active = (eventState & NS_EVENT_STATE_ACTIVE) == NS_EVENT_STATE_ACTIVE;
aState->focused = (eventState & NS_EVENT_STATE_FOCUS) == NS_EVENT_STATE_FOCUS;
aState->inHover = (eventState & NS_EVENT_STATE_HOVER) == NS_EVENT_STATE_HOVER;
aState->isDefault = FALSE; // XXX fix me
aState->canDefault = FALSE; // XXX fix me
// For these widget types, some element (either a child or parent)
// actually has element focus, so we check the focused attribute
// to see whether to draw in the focused state.
if (aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD ||
aWidgetType == NS_THEME_RADIO_CONTAINER ||
aWidgetType == NS_THEME_RADIO_LABEL ||
aWidgetType == NS_THEME_RADIO) {
aState->focused = IsFocused(aFrame);
}
if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL ||
aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL) {
// for scrollbars we need to go up two to go from the thumb to
// the slider to the actual scrollbar object
nsIFrame *tmpFrame = aFrame->GetParent()->GetParent();
aState->curpos = CheckIntAttr(tmpFrame, nsWidgetAtoms::curpos);
aState->maxpos = CheckIntAttr(tmpFrame, nsWidgetAtoms::maxpos);
}
// menu item state is determined by the attribute "_moz-menuactive",
// and not by the mouse hovering (accessibility). as a special case,
// menus which are children of a menu bar are only marked as prelight
// if they are open, not on normal hover.
if (aWidgetType == NS_THEME_MENUITEM ||
aWidgetType == NS_THEME_CHECKMENUITEM ||
aWidgetType == NS_THEME_RADIOMENUITEM) {
PRBool isTopLevel = PR_FALSE;
nsIMenuFrame *menuFrame;
CallQueryInterface(aFrame, &menuFrame);
if (menuFrame) {
nsIMenuParent *menuParent = menuFrame->GetMenuParent();
if (menuParent)
menuParent->IsMenuBar(isTopLevel);
}
if (isTopLevel) {
PRBool isOpen;
menuFrame->MenuIsOpen(isOpen);
aState->inHover = isOpen;
} else {
aState->inHover = CheckBooleanAttr(aFrame, nsWidgetAtoms::mozmenuactive);
}
aState->active = FALSE;
if (aWidgetType == NS_THEME_CHECKMENUITEM ||
aWidgetType == NS_THEME_RADIOMENUITEM) {
*aWidgetFlags = aFrame && aFrame->GetContent()->
AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::checked,
nsWidgetAtoms::_true, eIgnoreCase);
}
}
}
}
switch (aWidgetType) {
case NS_THEME_BUTTON:
case NS_THEME_TOOLBAR_BUTTON:
case NS_THEME_TOOLBAR_DUAL_BUTTON:
if (aWidgetFlags)
*aWidgetFlags = (aWidgetType == NS_THEME_BUTTON) ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE;
aGtkWidgetType = MOZ_GTK_BUTTON;
break;
case NS_THEME_CHECKBOX:
case NS_THEME_RADIO:
aGtkWidgetType = (aWidgetType == NS_THEME_RADIO) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON;
break;
case NS_THEME_SCROLLBAR_BUTTON_UP:
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
if (aWidgetFlags)
*aWidgetFlags = GtkArrowType(aWidgetType - NS_THEME_SCROLLBAR_BUTTON_UP);
aGtkWidgetType = MOZ_GTK_SCROLLBAR_BUTTON;
break;
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
aGtkWidgetType = MOZ_GTK_SCROLLBAR_TRACK_VERTICAL;
break;
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
aGtkWidgetType = MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL;
break;
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL;
break;
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
break;
case NS_THEME_SCALE_HORIZONTAL:
if (aWidgetFlags)
*aWidgetFlags = GTK_ORIENTATION_HORIZONTAL;
aGtkWidgetType = MOZ_GTK_SCALE_HORIZONTAL;
break;
case NS_THEME_SCALE_THUMB_HORIZONTAL:
if (aWidgetFlags)
*aWidgetFlags = GTK_ORIENTATION_HORIZONTAL;
aGtkWidgetType = MOZ_GTK_SCALE_THUMB_HORIZONTAL;
break;
case NS_THEME_SCALE_VERTICAL:
if (aWidgetFlags)
*aWidgetFlags = GTK_ORIENTATION_VERTICAL;
aGtkWidgetType = MOZ_GTK_SCALE_VERTICAL;
break;
case NS_THEME_SCALE_THUMB_VERTICAL:
if (aWidgetFlags)
*aWidgetFlags = GTK_ORIENTATION_VERTICAL;
aGtkWidgetType = MOZ_GTK_SCALE_THUMB_VERTICAL;
break;
case NS_THEME_TOOLBAR_GRIPPER:
aGtkWidgetType = MOZ_GTK_GRIPPER;
break;
case NS_THEME_TEXTFIELD:
case NS_THEME_DROPDOWN_TEXTFIELD:
aGtkWidgetType = MOZ_GTK_ENTRY;
break;
case NS_THEME_DROPDOWN:
aGtkWidgetType = MOZ_GTK_DROPDOWN;
break;
case NS_THEME_DROPDOWN_TEXT:
return PR_FALSE; // nothing to do, but prevents the bg from being drawn
case NS_THEME_DROPDOWN_BUTTON:
aGtkWidgetType = MOZ_GTK_DROPDOWN_ARROW;
break;
case NS_THEME_CHECKBOX_CONTAINER:
aGtkWidgetType = MOZ_GTK_CHECKBUTTON_CONTAINER;
break;
case NS_THEME_RADIO_CONTAINER:
aGtkWidgetType = MOZ_GTK_RADIOBUTTON_CONTAINER;
break;
case NS_THEME_CHECKBOX_LABEL:
aGtkWidgetType = MOZ_GTK_CHECKBUTTON_LABEL;
break;
case NS_THEME_RADIO_LABEL:
aGtkWidgetType = MOZ_GTK_RADIOBUTTON_LABEL;
break;
case NS_THEME_TOOLBAR:
aGtkWidgetType = MOZ_GTK_TOOLBAR;
break;
case NS_THEME_TOOLTIP:
aGtkWidgetType = MOZ_GTK_TOOLTIP;
break;
case NS_THEME_STATUSBAR_PANEL:
aGtkWidgetType = MOZ_GTK_FRAME;
break;
case NS_THEME_PROGRESSBAR:
case NS_THEME_PROGRESSBAR_VERTICAL:
aGtkWidgetType = MOZ_GTK_PROGRESSBAR;
break;
case NS_THEME_PROGRESSBAR_CHUNK:
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
aGtkWidgetType = MOZ_GTK_PROGRESS_CHUNK;
break;
case NS_THEME_TAB_PANELS:
aGtkWidgetType = MOZ_GTK_TABPANELS;
break;
case NS_THEME_TAB:
case NS_THEME_TAB_LEFT_EDGE:
case NS_THEME_TAB_RIGHT_EDGE:
{
if (aWidgetFlags) {
*aWidgetFlags = 0;
if (aWidgetType == NS_THEME_TAB &&
CheckBooleanAttr(aFrame, nsWidgetAtoms::selected))
*aWidgetFlags |= MOZ_GTK_TAB_SELECTED;
else if (aWidgetType == NS_THEME_TAB_LEFT_EDGE)
*aWidgetFlags |= MOZ_GTK_TAB_BEFORE_SELECTED;
if (aFrame->GetContent()->HasAttr(kNameSpaceID_None,
nsWidgetAtoms::firsttab))
*aWidgetFlags |= MOZ_GTK_TAB_FIRST;
}
aGtkWidgetType = MOZ_GTK_TAB;
}
break;
case NS_THEME_MENUBAR:
aGtkWidgetType = MOZ_GTK_MENUBAR;
break;
case NS_THEME_MENUPOPUP:
aGtkWidgetType = MOZ_GTK_MENUPOPUP;
break;
case NS_THEME_MENUITEM:
aGtkWidgetType = MOZ_GTK_MENUITEM;
break;
case NS_THEME_CHECKMENUITEM:
aGtkWidgetType = MOZ_GTK_CHECKMENUITEM;
break;
case NS_THEME_RADIOMENUITEM:
aGtkWidgetType = MOZ_GTK_RADIOMENUITEM;
break;
case NS_THEME_WINDOW:
case NS_THEME_DIALOG:
aGtkWidgetType = MOZ_GTK_WINDOW;
break;
default:
return PR_FALSE;
}
return PR_TRUE;
}
static int
NativeThemeErrorHandler(Display* dpy, XErrorEvent* error) {
gLastXError = error->error_code;
return 0;
}
NS_IMETHODIMP
nsNativeThemeGTK::DrawWidgetBackground(nsIRenderingContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
const nsRect& aRect,
const nsRect& aClipRect)
{
GtkWidgetState state;
GtkThemeWidgetType gtkWidgetType;
gint flags;
if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, &state,
&flags))
return NS_OK;
GdkWindow* window = NS_STATIC_CAST(GdkWindow*,
aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_GDK_DRAWABLE));
nsTransform2D* transformMatrix;
aContext->GetCurrentTransform(transformMatrix);
nsRect tr(aRect);
transformMatrix->TransformCoord(&tr.x, &tr.y, &tr.width, &tr.height);
GdkRectangle gdk_rect = {tr.x, tr.y, tr.width, tr.height};
nsRect cr(aClipRect);
transformMatrix->TransformCoord(&cr.x, &cr.y, &cr.width, &cr.height);
GdkRectangle gdk_clip = {cr.x, cr.y, cr.width, cr.height};
NS_ASSERTION(!IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType),
"Trying to render an unsafe widget!");
PRBool safeState = IsWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state);
XErrorHandler oldHandler = nsnull;
if (!safeState) {
gLastXError = 0;
oldHandler = XSetErrorHandler(NativeThemeErrorHandler);
}
moz_gtk_widget_paint(gtkWidgetType, window, &gdk_rect, &gdk_clip, &state,
flags);
if (!safeState) {
gdk_flush();
XSetErrorHandler(oldHandler);
if (gLastXError) {
#ifdef DEBUG
printf("GTK theme failed for widget type %d, error was %d, state was "
"[active=%d,focused=%d,inHover=%d,disabled=%d]\n",
aWidgetType, gLastXError, state.active, state.focused,
state.inHover, state.disabled);
#endif
NS_WARNING("GTK theme failed; disabling unsafe widget");
SetWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType);
// force refresh of the window, because the widget was not
// successfully drawn it must be redrawn using the default look
RefreshWidgetWindow(aFrame);
} else {
SetWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsNativeThemeGTK::GetWidgetBorder(nsIDeviceContext* aContext, nsIFrame* aFrame,
PRUint8 aWidgetType, nsMargin* aResult)
{
aResult->top = aResult->left = 0;
switch (aWidgetType) {
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
{
MozGtkScrollbarMetrics metrics;
moz_gtk_get_scrollbar_metrics(&metrics);
aResult->top = aResult->left = metrics.trough_border;
}
break;
case NS_THEME_TOOLBOX:
// gtk has no toolbox equivalent. So, although we map toolbox to
// gtk's 'toolbar' for purposes of painting the widget background,
// we don't use the toolbar border for toolbox.
break;
case NS_THEME_TOOLBAR_DUAL_BUTTON:
// TOOLBAR_DUAL_BUTTON is an interesting case. We want a border to draw
// around the entire button + dropdown, and also an inner border if you're
// over the button part. But, we want the inner button to be right up
// against the edge of the outer button so that the borders overlap.
// To make this happen, we draw a button border for the outer button,
// but don't reserve any space for it.
break;
default:
{
GtkThemeWidgetType gtkWidgetType;
if (GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nsnull,
nsnull))
moz_gtk_get_widget_border(gtkWidgetType, &aResult->left,
&aResult->top);
}
}
aResult->right = aResult->left;
aResult->bottom = aResult->top;
return NS_OK;
}
PRBool
nsNativeThemeGTK::GetWidgetPadding(nsIDeviceContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,
nsMargin* aResult)
{
if (aWidgetType == NS_THEME_BUTTON_FOCUS ||
aWidgetType == NS_THEME_TOOLBAR_BUTTON ||
aWidgetType == NS_THEME_TOOLBAR_DUAL_BUTTON) {
aResult->SizeTo(0, 0, 0, 0);
return PR_TRUE;
}
return PR_FALSE;
}
PRBool
nsNativeThemeGTK::GetWidgetOverflow(nsIDeviceContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,
nsRect* aResult)
{
nsIntMargin extraSize(0,0,0,0);
// Allow an extra one pixel above and below the thumb for certain
// GTK2 themes (Ximian Industrial, Bluecurve, Misty, at least);
// see moz_gtk_scrollbar_thumb_paint in gtk2drawing.c
switch (aWidgetType) {
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
extraSize.top = extraSize.bottom = 1;
break;
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
extraSize.left = extraSize.right = 1;
break;
default:
return PR_FALSE;
}
float p2t = aContext->DevUnitsToAppUnits();
nsMargin m(NSIntPixelsToTwips(extraSize.left, p2t),
NSIntPixelsToTwips(extraSize.top, p2t),
NSIntPixelsToTwips(extraSize.right, p2t),
NSIntPixelsToTwips(extraSize.bottom, p2t));
nsRect r(nsPoint(0, 0), aFrame->GetSize());
r.Inflate(m);
*aResult = r;
return PR_TRUE;
}
NS_IMETHODIMP
nsNativeThemeGTK::GetMinimumWidgetSize(nsIRenderingContext* aContext,
nsIFrame* aFrame, PRUint8 aWidgetType,
nsSize* aResult, PRBool* aIsOverridable)
{
aResult->width = aResult->height = 0;
*aIsOverridable = PR_TRUE;
switch (aWidgetType) {
case NS_THEME_SCROLLBAR_BUTTON_UP:
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
{
MozGtkScrollbarMetrics metrics;
moz_gtk_get_scrollbar_metrics(&metrics);
aResult->width = metrics.slider_width;
aResult->height = metrics.stepper_size;
*aIsOverridable = PR_FALSE;
}
break;
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
{
MozGtkScrollbarMetrics metrics;
moz_gtk_get_scrollbar_metrics(&metrics);
aResult->width = metrics.stepper_size;
aResult->height = metrics.slider_width;
*aIsOverridable = PR_FALSE;
}
break;
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
{
MozGtkScrollbarMetrics metrics;
moz_gtk_get_scrollbar_metrics(&metrics);
if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL) {
aResult->width = metrics.slider_width;
aResult->height = metrics.min_slider_size;
} else {
aResult->width = metrics.min_slider_size;
aResult->height = metrics.slider_width;
}
*aIsOverridable = PR_FALSE;
}
break;
case NS_THEME_SCALE_THUMB_HORIZONTAL:
case NS_THEME_SCALE_THUMB_VERTICAL:
{
gint thumb_length, thumb_height;
if (aWidgetType == NS_THEME_SCALE_THUMB_VERTICAL) {
moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_length, &thumb_height);
aResult->width = thumb_height;
aResult->height = thumb_length;
} else {
moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_HORIZONTAL, &thumb_length, &thumb_height);
aResult->width = thumb_length;
aResult->height = thumb_height;
}
*aIsOverridable = PR_FALSE;
}
break;
case NS_THEME_DROPDOWN_BUTTON:
{
moz_gtk_get_dropdown_arrow_size(&aResult->width, &aResult->height);
*aIsOverridable = PR_FALSE;
}
break;
case NS_THEME_CHECKBOX:
case NS_THEME_RADIO:
{
gint indicator_size, indicator_spacing;
if (aWidgetType == NS_THEME_CHECKBOX) {
moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing);
} else {
moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing);
}
// Include space for the indicator and the padding around it.
aResult->width = indicator_size + 3 * indicator_spacing;
aResult->height = indicator_size + 2 * indicator_spacing;
*aIsOverridable = PR_FALSE;
}
break;
case NS_THEME_CHECKBOX_CONTAINER:
case NS_THEME_RADIO_CONTAINER:
case NS_THEME_CHECKBOX_LABEL:
case NS_THEME_RADIO_LABEL:
case NS_THEME_BUTTON:
case NS_THEME_TOOLBAR_BUTTON:
{
// Just include our border, and let the box code augment the size.
nsCOMPtr<nsIDeviceContext> dc;
aContext->GetDeviceContext(*getter_AddRefs(dc));
nsMargin border;
nsNativeThemeGTK::GetWidgetBorder(dc, aFrame, aWidgetType, &border);
aResult->width = border.left + border.right;
aResult->height = border.top + border.bottom;
}
break;
}
return NS_OK;
}
NS_IMETHODIMP
nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
nsIAtom* aAttribute, PRBool* aShouldRepaint)
{
// Some widget types just never change state.
if (aWidgetType == NS_THEME_TOOLBOX ||
aWidgetType == NS_THEME_TOOLBAR ||
aWidgetType == NS_THEME_STATUSBAR ||
aWidgetType == NS_THEME_STATUSBAR_PANEL ||
aWidgetType == NS_THEME_STATUSBAR_RESIZER_PANEL ||
aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
aWidgetType == NS_THEME_PROGRESSBAR ||
aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL ||
aWidgetType == NS_THEME_MENUBAR ||
aWidgetType == NS_THEME_MENUPOPUP ||
aWidgetType == NS_THEME_TOOLTIP ||
aWidgetType == NS_THEME_WINDOW ||
aWidgetType == NS_THEME_DIALOG) {
*aShouldRepaint = PR_FALSE;
return NS_OK;
}
// XXXdwh Not sure what can really be done here. Can at least guess for
// specific widgets that they're highly unlikely to have certain states.
// For example, a toolbar doesn't care about any states.
if (!aAttribute) {
// Hover/focus/active changed. Always repaint.
*aShouldRepaint = PR_TRUE;
}
else {
// Check the attribute to see if it's relevant.
// disabled, checked, dlgtype, default, etc.
*aShouldRepaint = PR_FALSE;
if (aAttribute == nsWidgetAtoms::disabled ||
aAttribute == nsWidgetAtoms::checked ||
aAttribute == nsWidgetAtoms::selected ||
aAttribute == nsWidgetAtoms::focused ||
aAttribute == nsWidgetAtoms::mozmenuactive)
*aShouldRepaint = PR_TRUE;
}
return NS_OK;
}
NS_IMETHODIMP
nsNativeThemeGTK::ThemeChanged()
{
// this totally sucks. this method is really supposed to be
// static, which is why we can call it without any initialization.
static NS_DEFINE_CID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
nsCOMPtr<nsIDeviceContext> dctx = do_CreateInstance(kDeviceContextCID);
dctx->ClearCachedSystemFonts();
memset(mDisabledWidgetTypes, 0, sizeof(mDisabledWidgetTypes));
return NS_OK;
}
NS_IMETHODIMP_(PRBool)
nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
nsIFrame* aFrame,
PRUint8 aWidgetType)
{
if (aFrame) {
// For now don't support HTML.
if (aFrame->GetContent()->IsNodeOfType(nsINode::eHTML))
return PR_FALSE;
}
if (IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType))
return PR_FALSE;
switch (aWidgetType) {
case NS_THEME_BUTTON:
case NS_THEME_BUTTON_FOCUS:
case NS_THEME_RADIO:
case NS_THEME_CHECKBOX:
case NS_THEME_TOOLBOX: // N/A
case NS_THEME_TOOLBAR:
case NS_THEME_TOOLBAR_BUTTON:
case NS_THEME_TOOLBAR_DUAL_BUTTON: // so we can override the border with 0
// case NS_THEME_TOOLBAR_DUAL_BUTTON_DROPDOWN:
// case NS_THEME_TOOLBAR_SEPARATOR:
case NS_THEME_TOOLBAR_GRIPPER:
case NS_THEME_STATUSBAR:
case NS_THEME_STATUSBAR_PANEL:
// case NS_THEME_RESIZER: (n/a for gtk)
// case NS_THEME_LISTBOX:
// case NS_THEME_LISTBOX_LISTITEM:
// case NS_THEME_TREEVIEW:
// case NS_THEME_TREEVIEW_TREEITEM:
// case NS_THEME_TREEVIEW_TWISTY:
// case NS_THEME_TREEVIEW_LINE:
// case NS_THEME_TREEVIEW_HEADER:
// case NS_THEME_TREEVIEW_HEADER_CELL:
// case NS_THEME_TREEVIEW_HEADER_SORTARROW:
// case NS_THEME_TREEVIEW_TWISTY_OPEN:
case NS_THEME_PROGRESSBAR:
case NS_THEME_PROGRESSBAR_CHUNK:
case NS_THEME_PROGRESSBAR_VERTICAL:
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
case NS_THEME_TAB:
// case NS_THEME_TAB_PANEL:
case NS_THEME_TAB_LEFT_EDGE:
case NS_THEME_TAB_RIGHT_EDGE:
case NS_THEME_TAB_PANELS:
case NS_THEME_TOOLTIP:
// case NS_THEME_SPINNER:
// case NS_THEME_SPINNER_UP_BUTTON:
// case NS_THEME_SPINNER_DOWN_BUTTON:
// case NS_THEME_SCROLLBAR: (n/a for gtk)
case NS_THEME_SCROLLBAR_BUTTON_UP:
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
// case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL: (n/a for gtk)
// case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL: (n/a for gtk)
case NS_THEME_TEXTFIELD:
// case NS_THEME_TEXTFIELD_CARET:
case NS_THEME_DROPDOWN_BUTTON:
case NS_THEME_DROPDOWN_TEXTFIELD:
case NS_THEME_SCALE_HORIZONTAL:
case NS_THEME_SCALE_THUMB_HORIZONTAL:
case NS_THEME_SCALE_VERTICAL:
case NS_THEME_SCALE_THUMB_VERTICAL:
// case NS_THEME_SCALE_THUMB_START:
// case NS_THEME_SCALE_THUMB_END:
// case NS_THEME_SCALE_TICK:
case NS_THEME_CHECKBOX_CONTAINER:
case NS_THEME_RADIO_CONTAINER:
case NS_THEME_CHECKBOX_LABEL:
case NS_THEME_RADIO_LABEL:
#ifdef MOZ_WIDGET_GTK2
case NS_THEME_MENUBAR:
case NS_THEME_MENUPOPUP:
case NS_THEME_MENUITEM:
case NS_THEME_CHECKMENUITEM:
case NS_THEME_RADIOMENUITEM:
case NS_THEME_WINDOW:
case NS_THEME_DIALOG:
case NS_THEME_DROPDOWN:
case NS_THEME_DROPDOWN_TEXT:
#endif
return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
}
return PR_FALSE;
}
NS_IMETHODIMP_(PRBool)
nsNativeThemeGTK::WidgetIsContainer(PRUint8 aWidgetType)
{
// XXXdwh At some point flesh all of this out.
if (aWidgetType == NS_THEME_DROPDOWN_BUTTON ||
aWidgetType == NS_THEME_RADIO ||
aWidgetType == NS_THEME_CHECKBOX)
return PR_FALSE;
return PR_TRUE;
}

Просмотреть файл

@ -59,6 +59,7 @@ static GtkWidget* gCheckboxWidget;
static GtkWidget* gRadiobuttonWidget;
static GtkWidget* gHorizScrollbarWidget;
static GtkWidget* gVertScrollbarWidget;
static GtkWidget* gSpinWidget;
static GtkWidget* gHScaleWidget;
static GtkWidget* gVScaleWidget;
static GtkWidget* gEntryWidget;
@ -160,6 +161,16 @@ ensure_scrollbar_widget()
return MOZ_GTK_SUCCESS;
}
static gint
ensure_spin_widget()
{
if (!gSpinWidget) {
gSpinWidget = gtk_spin_button_new(NULL, 1, 0);
setup_widget_prototype(gSpinWidget);
}
return MOZ_GTK_SUCCESS;
}
static gint
ensure_scale_widget()
{
@ -809,6 +820,39 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
return MOZ_GTK_SUCCESS;
}
static gint
moz_gtk_spin_paint(GdkDrawable* drawable, GdkRectangle* rect, gboolean isDown,
GtkWidgetState* state)
{
GdkRectangle arrow_rect;
GtkStateType state_type = ConvertGtkState(state);
GtkShadowType shadow_type = state_type == GTK_STATE_ACTIVE ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
GtkStyle* style;
ensure_spin_widget();
style = gSpinWidget->style;
TSOffsetStyleGCs(style, rect->x, rect->y);
gtk_paint_box(style, drawable, state_type, shadow_type, NULL, gSpinWidget,
isDown ? "spinbutton_down" : "spinbutton_up",
rect->x, rect->y, rect->width, rect->height);
/* hard code these values */
arrow_rect.width = 6;
arrow_rect.height = 6;
arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2;
arrow_rect.y += isDown ? -1 : 1;
gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL,
gSpinWidget, "spinbutton",
isDown ? GTK_ARROW_DOWN : GTK_ARROW_UP, TRUE,
arrow_rect.x, arrow_rect.y,
arrow_rect.width, arrow_rect.height);
return MOZ_GTK_SUCCESS;
}
static gint
moz_gtk_scale_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
@ -1531,6 +1575,11 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* xthickness,
ensure_progress_widget();
w = gProgressWidget;
break;
case MOZ_GTK_SPINBUTTON_UP:
case MOZ_GTK_SPINBUTTON_DOWN:
ensure_spin_widget();
w = gSpinWidget;
break;
case MOZ_GTK_SCALE_HORIZONTAL:
ensure_scale_widget();
w = gHScaleWidget;
@ -1593,7 +1642,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* xthickness,
return MOZ_GTK_SUCCESS;
}
case MOZ_GTK_MENUBAR:
ensure_menu_bar_widget();
w = gMenuBarWidget;
@ -1733,6 +1781,11 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
case MOZ_GTK_SCALE_THUMB_VERTICAL:
return moz_gtk_scale_thumb_paint(drawable, rect, cliprect, state, (GtkOrientation) flags);
break;
case MOZ_GTK_SPINBUTTON_UP:
case MOZ_GTK_SPINBUTTON_DOWN:
return moz_gtk_spin_paint(drawable, rect,
(widget == MOZ_GTK_SPINBUTTON_DOWN), state);
break;
case MOZ_GTK_GRIPPER:
return moz_gtk_gripper_paint(drawable, rect, cliprect, state);
break;

Просмотреть файл

@ -118,6 +118,9 @@ typedef enum {
/* Paints a GtkScale thumb. */
MOZ_GTK_SCALE_THUMB_HORIZONTAL,
MOZ_GTK_SCALE_THUMB_VERTICAL,
/* Paints a GtkSpinButton */
MOZ_GTK_SPINBUTTON_UP,
MOZ_GTK_SPINBUTTON_DOWN,
/* Paints the gripper of a GtkHandleBox. */
MOZ_GTK_GRIPPER,
/* Paints a GtkEntry. */

Просмотреть файл

@ -320,6 +320,12 @@ nsNativeThemeGTK::GetGtkWidgetAndState(PRUint8 aWidgetType, nsIFrame* aFrame,
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
break;
case NS_THEME_SPINNER_UP_BUTTON:
aGtkWidgetType = MOZ_GTK_SPINBUTTON_UP;
break;
case NS_THEME_SPINNER_DOWN_BUTTON:
aGtkWidgetType = MOZ_GTK_SPINBUTTON_DOWN;
break;
case NS_THEME_SCALE_HORIZONTAL:
if (aWidgetFlags)
*aWidgetFlags = GTK_ORIENTATION_HORIZONTAL;
@ -869,6 +875,12 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsIRenderingContext* aContext,
aResult->height = border.top + border.bottom;
}
break;
case NS_THEME_SPINNER_UP_BUTTON:
case NS_THEME_SPINNER_DOWN_BUTTON:
// hard code these sizes
aResult->width = 14;
aResult->height = 13;
break;
}
return NS_OK;
@ -981,8 +993,8 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
case NS_THEME_TAB_PANELS:
case NS_THEME_TOOLTIP:
// case NS_THEME_SPINNER:
// case NS_THEME_SPINNER_UP_BUTTON:
// case NS_THEME_SPINNER_DOWN_BUTTON:
case NS_THEME_SPINNER_UP_BUTTON:
case NS_THEME_SPINNER_DOWN_BUTTON:
// case NS_THEME_SCROLLBAR: (n/a for gtk)
case NS_THEME_SCROLLBAR_BUTTON_UP:
case NS_THEME_SCROLLBAR_BUTTON_DOWN:

Просмотреть файл

@ -192,6 +192,23 @@ nsNativeThemeMac::DrawButton ( ThemeButtonKind inKind, const Rect& inBoxRect, PR
::DrawThemeButton ( &inBoxRect, inKind, &info, nsnull, mEraseProc, nsnull, 0L );
}
void
nsNativeThemeMac::DrawSpinButtons ( ThemeButtonKind inKind, const Rect& inBoxRect,
PRBool inDisabled, ThemeDrawState inDrawState,
ThemeButtonAdornment inAdornment, PRInt32 inState )
{
ThemeButtonDrawInfo info;
info.state= inDrawState;
info.value = kThemeButtonOff;
info.adornment = inAdornment;
if ( inDisabled )
info.state = kThemeStateUnavailableInactive;
::DrawThemeButton ( &inBoxRect, inKind, &info, nsnull, mEraseProc, nsnull, 0L );
}
void
nsNativeThemeMac::DrawToolbar ( const Rect& inBoxRect )
{
@ -441,6 +458,20 @@ nsNativeThemeMac::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame*
DrawButton ( kThemeMediumBevelButton, macRect, IsDefaultButton(aFrame), IsDisabled(aFrame),
kThemeButtonOff, kThemeAdornmentNone, eventState );
break;
case NS_THEME_SPINNER:
{
ThemeDrawState state = kThemeStateActive;
nsIContent* content = aFrame->GetContent();
if (content->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::state,
NS_LITERAL_STRING("up"), eCaseMatters))
state = kThemeStatePressedUp;
else if (content->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::state,
NS_LITERAL_STRING("down"), eCaseMatters))
state = kThemeStatePressedDown;
DrawSpinButtons ( kThemeIncDecButton, macRect, IsDisabled(aFrame),
state, kThemeAdornmentNone, eventState );
break;
}
case NS_THEME_TOOLBAR_BUTTON:
DrawButton ( kThemePushButton, macRect, IsDefaultButton(aFrame), IsDisabled(aFrame),
kThemeButtonOn, kThemeAdornmentNone, eventState );
@ -645,6 +676,14 @@ nsNativeThemeMac::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame*
break;
}
case NS_THEME_SPINNER:
{
SInt32 buttonHeight = 0;
::GetThemeMetric(kThemeMetricPushButtonHeight, &buttonHeight);
aResult->SizeTo(kAquaPushButtonEndcaps, buttonHeight);
break;
}
case NS_THEME_CHECKBOX:
{
SInt32 boxHeight = 0, boxWidth = 0;
@ -878,6 +917,7 @@ nsNativeThemeMac::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFr
case NS_THEME_BUTTON:
case NS_THEME_BUTTON_SMALL:
case NS_THEME_BUTTON_BEVEL:
case NS_THEME_SPINNER:
case NS_THEME_TOOLBAR:
case NS_THEME_STATUSBAR:
case NS_THEME_TEXTFIELD:

Просмотреть файл

@ -1,127 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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
* Mike Pinkerton (pinkerton@netscape.com).
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
#include <Appearance.h>
#include "nsITheme.h"
#include "nsCOMPtr.h"
#include "nsIAtom.h"
#include "nsILookAndFeel.h"
#include "nsIDeviceContext.h"
#include "nsNativeTheme.h"
class nsNativeThemeMac : private nsNativeTheme,
public nsITheme
{
public:
nsNativeThemeMac();
virtual ~nsNativeThemeMac();
NS_DECL_ISUPPORTS
// The nsITheme interface.
NS_IMETHOD DrawWidgetBackground(nsIRenderingContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
const nsRect& aRect,
const nsRect& aClipRect);
NS_IMETHOD GetWidgetBorder(nsIDeviceContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
nsMargin* aResult);
virtual PRBool GetWidgetPadding(nsIDeviceContext* aContext,
nsIFrame* aFrame,
PRUint8 aWidgetType,
nsMargin* aResult);
NS_IMETHOD GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame,
PRUint8 aWidgetType,
nsSize* aResult, PRBool* aIsOverridable);
NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
nsIAtom* aAttribute, PRBool* aShouldRepaint);
NS_IMETHOD ThemeChanged();
PRBool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame, PRUint8 aWidgetType);
PRBool WidgetIsContainer(PRUint8 aWidgetType);
protected:
// Some widths and margins. You'd think there would be metrics for these, but no.
enum {
kAquaPushButtonEndcaps = 14,
kAquaPushButtonTopBottom = 2,
kAquaSmallPushButtonEndcaps = 10,
kAquaDropdownLeftEndcap = 9,
kAquaDropwdonRightEndcap = 20 // wider on right to encompass the button
};
nsresult GetSystemColor(PRUint8 aWidgetType, nsILookAndFeel::nsColorID& aColorID);
nsresult GetSystemFont(PRUint8 aWidgetType, nsSystemFontID& aFont);
// Appearance Manager drawing routines
void DrawCheckbox ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState ) ;
void DrawSmallCheckbox ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState );
void DrawRadio ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState ) ;
void DrawSmallRadio ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState );
void DrawToolbar ( const Rect& inBoxRect ) ;
void DrawEditText ( const Rect& inBoxRect, PRBool inIsDisabled ) ;
void DrawListBox ( const Rect& inBoxRect, PRBool inIsDisabled ) ;
void DrawProgress ( const Rect& inBoxRect, PRBool inIsDisabled, PRBool inIsIndeterminate,
PRBool inIsHorizontal, PRInt32 inValue ) ;
void DrawTab ( const Rect& inBoxRect, PRBool inIsDisabled, PRBool inIsFrontmost,
PRBool inIsHorizontal, PRBool inTabBottom, PRInt32 inState ) ;
void DrawTabPanel ( const Rect& inBoxRect, PRBool inIsDisabled ) ;
void DrawScale ( const Rect& inBoxRect, PRBool inIsDisabled, PRInt32 inState,
PRBool inDirection, PRInt32 inCurrentValue,
PRInt32 inMinValue, PRInt32 inMaxValue ) ;
void DrawSeparator ( const Rect& inBoxRect, PRBool inIsDisabled ) ;
// void DrawScrollArrows ( const Rect& inScrollbarRect, PRBool inIsDisabled, PRInt32 inWidget, PRInt32 inState ) ;
void DrawButton ( ThemeButtonKind inKind, const Rect& inBoxRect, PRBool inIsDefault,
PRBool inDisabled, ThemeButtonValue inValue, ThemeButtonAdornment inAdornment, PRInt32 inState ) ;
void DrawCheckboxRadio ( ThemeButtonKind inKind, const Rect& inBoxRect, PRBool inChecked,
PRBool inDisabled, PRInt32 inState ) ;
void DrawMenu ( const Rect& inBoxRect, PRBool inIsDisabled ) ;
void DrawMenuItem ( const Rect& inBoxRect, ThemeMenuItemType itemType, PRBool inIsDisabled,
PRBool inHover) ;
private:
ThemeEraseUPP mEraseProc;
};

Просмотреть файл

@ -116,6 +116,10 @@
#define TKP_THUMB 3
#define TKP_THUMBVERT 6
// Spin constants
#define SPNP_UP 1
#define SPNP_DOWN 2
// Progress bar constants
#define PP_BAR 1
#define PP_BARVERT 2
@ -195,6 +199,7 @@ nsNativeThemeWin::nsNativeThemeWin() {
mRebarTheme = NULL;
mProgressTheme = NULL;
mScrollbarTheme = NULL;
mSpinTheme = NULL;
mScaleTheme = NULL;
mStatusbarTheme = NULL;
mTabTheme = NULL;
@ -332,6 +337,13 @@ nsNativeThemeWin::GetTheme(PRUint8 aWidgetType)
mScaleTheme = openTheme(NULL, L"Trackbar");
return mScaleTheme;
}
case NS_THEME_SPINNER_UP_BUTTON:
case NS_THEME_SPINNER_DOWN_BUTTON:
{
if (!mSpinTheme)
mSpinTheme = openTheme(NULL, L"Spin");
return mSpinTheme;
}
case NS_THEME_STATUSBAR:
case NS_THEME_STATUSBAR_PANEL:
case NS_THEME_STATUSBAR_RESIZER_PANEL:
@ -637,6 +649,26 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
}
return NS_OK;
}
case NS_THEME_SPINNER_UP_BUTTON:
case NS_THEME_SPINNER_DOWN_BUTTON: {
aPart = (aWidgetType == NS_THEME_SPINNER_UP_BUTTON) ?
SPNP_UP : SPNP_DOWN;
if (!aFrame)
aState = TS_NORMAL;
else if (IsDisabled(aFrame)) {
aState = TS_DISABLED;
}
else {
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
aState = TS_ACTIVE;
else if (eventState & NS_EVENT_STATE_HOVER)
aState = TS_HOVER;
else
aState = TS_NORMAL;
}
return NS_OK;
}
case NS_THEME_TOOLBOX:
case NS_THEME_STATUSBAR:
case NS_THEME_SCROLLBAR: {
@ -938,7 +970,7 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
// Draw focus rectangles for XP HTML checkboxes and radio buttons
// XXX it'd be nice to draw these outside of the frame
if ((aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_RADIO)
&& aFrame->GetContent()->IsNodeOfType(nsIContent::eHTML) ||
&& aFrame->GetContent()->IsNodeOfType(nsINode::eHTML) ||
aWidgetType == NS_THEME_SCALE_HORIZONTAL ||
aWidgetType == NS_THEME_SCALE_VERTICAL) {
PRInt32 contentState ;
@ -1124,12 +1156,18 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame*
// themes.
// In our app, we want these widgets to be able to really shrink down,
// so use the min-size request value (of 0).
SIZE sz;
getThemePartSize(theme, hdc, part, state, NULL, sizeReq, &sz);
aResult->width = sz.cx;
aResult->height = sz.cy;
if (aWidgetType == NS_THEME_SPINNER_UP_BUTTON ||
aWidgetType == NS_THEME_SPINNER_DOWN_BUTTON) {
aResult->width++;
aResult->height = aResult->height / 2 + 1;
}
return NS_OK;
}
@ -1191,6 +1229,10 @@ nsNativeThemeWin::CloseData()
closeTheme(mScaleTheme);
mScaleTheme = NULL;
}
if (mSpinTheme) {
closeTheme(mSpinTheme);
mSpinTheme = NULL;
}
if (mRebarTheme) {
closeTheme(mRebarTheme);
mRebarTheme = NULL;

Просмотреть файл

@ -124,6 +124,7 @@ private:
HANDLE mProgressTheme;
HANDLE mScrollbarTheme;
HANDLE mScaleTheme;
HANDLE mSpinTheme;
HANDLE mStatusbarTheme;
HANDLE mTabTheme;
HANDLE mTreeViewTheme;

Просмотреть файл

@ -92,6 +92,7 @@ WIDGET_ATOM(radio, "radio")
WIDGET_ATOM(readonly, "readonly")
WIDGET_ATOM(selected, "selected")
WIDGET_ATOM(sortdirection, "sortDirection")
WIDGET_ATOM(state, "state")
WIDGET_ATOM(_true, "true")
WIDGET_ATOM(type, "type")
WIDGET_ATOM(value, "value")

Просмотреть файл

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ***** 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
- Håkan Waara. Portions created by Håkan Waara are Copyright (C), Håkan Waara. All Rights Reserved.
- Portions created by the Initial Developer are Copyright (C) 2001
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Håkan Waara (Original Author)
-
- 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 ***** -->
<bindings id="spinbuttonsBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="spinbuttons"
extends="chrome://global/content/bindings/spinbuttons.xml#spinbuttons-baseline">
<resources>
<stylesheet src="chrome://global/skin/spinbuttons.css"/>
</resources>
</binding>
<binding id="spinbuttons-baseline">
<content>
<xul:vbox flex="1" align="center">
<xul:image xbl:inherits="onclick=onup" id="upButton" class="up"/>
<xul:image xbl:inherits="onclick=ondown" id="downButton" class="down"/>
</xul:vbox>
</content>
</binding>
</bindings>