2006-08-30 22:06:44 +00:00
|
|
|
/* -*- 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):
|
|
|
|
* Vladimir Vukicevic <vladimir@pobox.com> (HITheme rewrite)
|
2006-11-28 23:07:13 +00:00
|
|
|
* Josh Aas <josh@mozilla.com>
|
2006-08-30 22:06:44 +00:00
|
|
|
*
|
|
|
|
* 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 "nsNativeThemeCocoa.h"
|
|
|
|
#include "nsIRenderingContext.h"
|
|
|
|
#include "nsRect.h"
|
|
|
|
#include "nsSize.h"
|
|
|
|
#include "nsThemeConstants.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsPresContext.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIFrame.h"
|
|
|
|
#include "nsIAtom.h"
|
|
|
|
#include "nsIEventStateManager.h"
|
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsPresContext.h"
|
|
|
|
#include "nsILookAndFeel.h"
|
|
|
|
#include "nsWidgetAtoms.h"
|
|
|
|
|
|
|
|
#include "gfxContext.h"
|
|
|
|
#include "gfxQuartzSurface.h"
|
|
|
|
|
2007-02-16 07:18:56 +00:00
|
|
|
#define DRAW_IN_FRAME_DEBUG 0
|
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
extern "C" {
|
2007-01-05 21:12:56 +00:00
|
|
|
CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define HITHEME_ORIENTATION kHIThemeOrientationNormal
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS1(nsNativeThemeCocoa, nsITheme)
|
|
|
|
|
|
|
|
static PRBool sInitializedBorders = PR_FALSE;
|
|
|
|
|
|
|
|
nsNativeThemeCocoa::nsNativeThemeCocoa()
|
|
|
|
{
|
|
|
|
if (!sInitializedBorders) {
|
|
|
|
sInitializedBorders = PR_TRUE;
|
|
|
|
sTextfieldBGTransparent = PR_FALSE;
|
|
|
|
sListboxBGTransparent = PR_TRUE;
|
|
|
|
sTextfieldDisabledBGColorID = nsILookAndFeel::eColor__moz_field;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsNativeThemeCocoa::~nsNativeThemeCocoa()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2007-01-05 21:12:56 +00:00
|
|
|
nsNativeThemeCocoa::DrawCheckboxRadio(CGContextRef cgContext, ThemeButtonKind inKind,
|
|
|
|
const HIRect& inBoxRect, PRBool inChecked,
|
|
|
|
PRBool inDisabled, PRInt32 inState)
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
HIThemeButtonDrawInfo bdi;
|
|
|
|
bdi.version = 0;
|
|
|
|
bdi.kind = inKind;
|
|
|
|
|
|
|
|
if (inDisabled)
|
2007-02-20 19:07:50 +00:00
|
|
|
bdi.state = kThemeStateUnavailable;
|
2006-08-30 22:06:44 +00:00
|
|
|
else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
|
|
|
|
bdi.state = kThemeStatePressed;
|
|
|
|
else
|
|
|
|
bdi.state = kThemeStateActive;
|
|
|
|
|
|
|
|
bdi.value = inChecked ? kThemeButtonOn : kThemeButtonOff;
|
|
|
|
bdi.adornment = (inState & NS_EVENT_STATE_FOCUS) ? kThemeAdornmentFocus : kThemeAdornmentNone;
|
|
|
|
|
2007-02-16 07:18:56 +00:00
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.8);
|
|
|
|
CGContextFillRect(cgContext, inBoxRect);
|
|
|
|
#endif
|
|
|
|
|
2007-01-05 21:12:56 +00:00
|
|
|
HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-01-05 21:12:56 +00:00
|
|
|
nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
|
|
|
|
const HIRect& inBoxRect, PRBool inIsDefault, PRBool inDisabled,
|
|
|
|
ThemeButtonValue inValue, ThemeButtonAdornment inAdornment,
|
|
|
|
PRInt32 inState)
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
HIThemeButtonDrawInfo bdi;
|
|
|
|
|
|
|
|
bdi.version = 0;
|
|
|
|
bdi.kind = inKind;
|
|
|
|
bdi.value = inValue;
|
|
|
|
bdi.adornment = inAdornment;
|
|
|
|
|
|
|
|
if (inDisabled)
|
2007-02-20 19:07:50 +00:00
|
|
|
bdi.state = kThemeStateUnavailable;
|
2006-08-30 22:06:44 +00:00
|
|
|
else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
|
|
|
|
bdi.state = kThemeStatePressed;
|
|
|
|
else
|
2007-02-20 19:07:50 +00:00
|
|
|
bdi.state = (inKind == kThemeArrowButton) ? kThemeStateUnavailable : kThemeStateActive;
|
2006-08-30 22:06:44 +00:00
|
|
|
|
2007-01-05 21:12:56 +00:00
|
|
|
if (inState & NS_EVENT_STATE_FOCUS)
|
2006-08-30 22:06:44 +00:00
|
|
|
bdi.adornment |= kThemeAdornmentFocus;
|
|
|
|
|
2006-12-13 21:37:34 +00:00
|
|
|
if (inIsDefault && !inDisabled)
|
2006-08-30 22:06:44 +00:00
|
|
|
bdi.adornment |= kThemeAdornmentDefault;
|
|
|
|
|
2007-02-17 02:48:58 +00:00
|
|
|
// Certain buttons draw outside their frame with nsITheme, we adjust for that here.
|
|
|
|
HIRect drawRect = inBoxRect;
|
|
|
|
if (inKind == kThemePushButton ||
|
|
|
|
inKind == kThemePopupButton) {
|
|
|
|
// these buttons draw one pixel too wide on each side and two pixels too
|
|
|
|
// far down on the bottom
|
|
|
|
drawRect.origin.x += 1;
|
|
|
|
drawRect.size.width -= 2;
|
|
|
|
drawRect.size.height -= 2;
|
|
|
|
}
|
|
|
|
|
2007-02-16 07:18:56 +00:00
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.8);
|
|
|
|
CGContextFillRect(cgContext, inBoxRect);
|
|
|
|
#endif
|
|
|
|
|
2007-02-17 02:48:58 +00:00
|
|
|
HIThemeDrawButton(&drawRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-01-05 21:12:56 +00:00
|
|
|
nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind,
|
|
|
|
const HIRect& inBoxRect, PRBool inDisabled,
|
|
|
|
ThemeDrawState inDrawState,
|
|
|
|
ThemeButtonAdornment inAdornment,
|
|
|
|
PRInt32 inState)
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
HIThemeButtonDrawInfo bdi;
|
|
|
|
bdi.version = 0;
|
|
|
|
bdi.kind = inKind;
|
|
|
|
bdi.state = inDrawState;
|
|
|
|
bdi.value = kThemeButtonOff;
|
|
|
|
bdi.adornment = inAdornment;
|
|
|
|
|
|
|
|
if (inDisabled)
|
2007-02-20 19:07:50 +00:00
|
|
|
bdi.state = kThemeStateUnavailable;
|
2006-08-30 22:06:44 +00:00
|
|
|
|
2007-01-05 21:12:56 +00:00
|
|
|
HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-01-05 21:12:56 +00:00
|
|
|
nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind,
|
|
|
|
const HIRect& inBoxRect, PRBool inIsDisabled, PRInt32 inState)
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
HIThemeFrameDrawInfo fdi;
|
|
|
|
fdi.version = 0;
|
|
|
|
fdi.kind = inKind;
|
2007-02-20 19:07:50 +00:00
|
|
|
fdi.state = inIsDisabled ? kThemeStateUnavailable : kThemeStateActive;
|
2007-02-16 18:18:48 +00:00
|
|
|
// We do not draw focus rings for frame widgets because their complex layout has nasty
|
|
|
|
// drawing bugs and it looks terrible.
|
|
|
|
// fdi.isFocused = (inState & NS_EVENT_STATE_FOCUS) != 0;
|
|
|
|
fdi.isFocused = 0;
|
|
|
|
|
|
|
|
// HIThemeDrawFrame takes the rect for the content area of the frame, not
|
|
|
|
// the bounding rect for the frame. Here we reduce the size of the rect we
|
|
|
|
// will pass to make it the size of the content.
|
|
|
|
HIRect drawRect = inBoxRect;
|
|
|
|
if (inKind == kHIThemeFrameTextFieldSquare) {
|
|
|
|
SInt32 frameOutset = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
|
|
|
|
drawRect.origin.x += frameOutset;
|
|
|
|
drawRect.origin.y += frameOutset;
|
|
|
|
drawRect.size.width -= frameOutset * 2;
|
|
|
|
drawRect.size.height -= frameOutset * 2;
|
|
|
|
}
|
2006-08-30 22:06:44 +00:00
|
|
|
|
2007-02-16 07:18:56 +00:00
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.8);
|
|
|
|
CGContextFillRect(cgContext, inBoxRect);
|
|
|
|
#endif
|
|
|
|
|
2007-02-16 18:18:48 +00:00
|
|
|
HIThemeDrawFrame(&drawRect, &fdi, cgContext, HITHEME_ORIENTATION);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-01-05 21:12:56 +00:00
|
|
|
nsNativeThemeCocoa::DrawProgress(CGContextRef cgContext,
|
2007-02-20 19:07:50 +00:00
|
|
|
const HIRect& inBoxRect, PRBool inIsIndeterminate,
|
2007-01-05 21:12:56 +00:00
|
|
|
PRBool inIsHorizontal, PRInt32 inValue)
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
HIThemeTrackDrawInfo tdi;
|
|
|
|
static SInt32 sPhase = 0;
|
|
|
|
|
|
|
|
tdi.version = 0;
|
|
|
|
tdi.kind = inIsIndeterminate ? kThemeMediumIndeterminateBar: kThemeMediumProgressBar;
|
|
|
|
tdi.bounds = inBoxRect;
|
|
|
|
tdi.min = 0;
|
|
|
|
tdi.max = 100;
|
|
|
|
tdi.value = inValue;
|
|
|
|
tdi.attributes = inIsHorizontal ? kThemeTrackHorizontal : 0;
|
2007-02-20 19:07:50 +00:00
|
|
|
tdi.enableState = kThemeTrackActive;
|
2006-08-30 22:06:44 +00:00
|
|
|
tdi.trackInfo.progress.phase = sPhase++; // animate for the next time we're called
|
|
|
|
|
2007-01-05 21:12:56 +00:00
|
|
|
HIThemeDrawTrack(&tdi, NULL, cgContext, HITHEME_ORIENTATION);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2007-02-20 19:07:50 +00:00
|
|
|
nsNativeThemeCocoa::DrawTabPanel(CGContextRef cgContext, const HIRect& inBoxRect)
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
HIThemeTabPaneDrawInfo tpdi;
|
|
|
|
|
2006-11-28 23:07:13 +00:00
|
|
|
tpdi.version = 0;
|
2006-08-30 22:06:44 +00:00
|
|
|
tpdi.state = kThemeStateActive;
|
2006-11-28 23:07:13 +00:00
|
|
|
tpdi.direction = kThemeTabNorth;
|
|
|
|
tpdi.size = kHIThemeTabSizeNormal;
|
2006-08-30 22:06:44 +00:00
|
|
|
|
2006-11-28 23:07:13 +00:00
|
|
|
HIThemeDrawTabPane(&inBoxRect, &tpdi, cgContext, HITHEME_ORIENTATION);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
2006-11-28 23:07:13 +00:00
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
void
|
2007-01-05 21:12:56 +00:00
|
|
|
nsNativeThemeCocoa::DrawScale(CGContextRef cgContext, const HIRect& inBoxRect,
|
|
|
|
PRBool inIsDisabled, PRInt32 inState,
|
|
|
|
PRBool inIsVertical, PRInt32 inCurrentValue,
|
|
|
|
PRInt32 inMinValue, PRInt32 inMaxValue)
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
HIThemeTrackDrawInfo tdi;
|
|
|
|
|
|
|
|
tdi.version = 0;
|
|
|
|
tdi.kind = kThemeMediumSlider;
|
|
|
|
tdi.bounds = inBoxRect;
|
|
|
|
tdi.min = inMinValue;
|
|
|
|
tdi.max = inMaxValue;
|
|
|
|
tdi.value = inCurrentValue;
|
|
|
|
tdi.attributes = kThemeTrackShowThumb;
|
|
|
|
if (!inIsVertical)
|
|
|
|
tdi.attributes |= kThemeTrackHorizontal;
|
|
|
|
if (inState & NS_EVENT_STATE_FOCUS)
|
|
|
|
tdi.attributes |= kThemeTrackHasFocus;
|
|
|
|
tdi.enableState = inIsDisabled ? kThemeTrackDisabled : kThemeTrackActive;
|
|
|
|
tdi.trackInfo.slider.thumbDir = kThemeThumbPlain;
|
|
|
|
tdi.trackInfo.slider.pressState = 0;
|
|
|
|
|
2007-01-05 21:12:56 +00:00
|
|
|
HIThemeDrawTrack(&tdi, NULL, cgContext, HITHEME_ORIENTATION);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-11-28 23:07:13 +00:00
|
|
|
nsNativeThemeCocoa::DrawTab(CGContextRef cgContext, const HIRect& inBoxRect,
|
|
|
|
PRBool inIsDisabled, PRBool inIsFrontmost,
|
|
|
|
PRBool inIsHorizontal, PRBool inTabBottom,
|
|
|
|
PRInt32 inState)
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
HIThemeTabDrawInfo tdi;
|
|
|
|
|
2006-11-28 23:07:13 +00:00
|
|
|
tdi.version = 0;
|
2006-08-30 22:06:44 +00:00
|
|
|
|
|
|
|
if (inIsFrontmost) {
|
|
|
|
if (inIsDisabled)
|
2007-02-20 19:07:50 +00:00
|
|
|
tdi.style = kThemeTabFrontUnavailable;
|
2006-08-30 22:06:44 +00:00
|
|
|
else
|
|
|
|
tdi.style = kThemeTabFront;
|
|
|
|
} else {
|
|
|
|
if (inIsDisabled)
|
2007-02-20 19:07:50 +00:00
|
|
|
tdi.style = kThemeTabNonFrontUnavailable;
|
2006-08-30 22:06:44 +00:00
|
|
|
else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
|
|
|
|
tdi.style = kThemeTabNonFrontPressed;
|
|
|
|
else
|
|
|
|
tdi.style = kThemeTabNonFront;
|
|
|
|
}
|
|
|
|
|
|
|
|
// don't yet support vertical tabs
|
|
|
|
tdi.direction = inTabBottom ? kThemeTabSouth : kThemeTabNorth;
|
|
|
|
tdi.size = kHIThemeTabSizeNormal;
|
2006-11-28 23:07:13 +00:00
|
|
|
tdi.adornment = kThemeAdornmentNone;
|
2006-08-30 22:06:44 +00:00
|
|
|
|
|
|
|
HIThemeDrawTab(&inBoxRect, &tdi, cgContext, HITHEME_ORIENTATION, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType, const nsRect& aRect,
|
|
|
|
const nsRect& aClipRect)
|
|
|
|
{
|
|
|
|
// setup to draw into the correct port
|
|
|
|
nsCOMPtr<nsIDeviceContext> dctx;
|
|
|
|
aContext->GetDeviceContext(*getter_AddRefs(dctx));
|
2007-02-07 07:46:44 +00:00
|
|
|
PRInt32 p2a = dctx->AppUnitsPerDevPixel();
|
2006-08-30 22:06:44 +00:00
|
|
|
|
|
|
|
nsRefPtr<gfxContext> thebesCtx = (gfxContext*)
|
|
|
|
aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
|
|
|
|
if (!thebesCtx)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2007-01-31 18:43:34 +00:00
|
|
|
thebesCtx->UpdateSurfaceClip();
|
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
double offsetX = 0.0, offsetY = 0.0;
|
|
|
|
nsRefPtr<gfxASurface> thebesSurface = thebesCtx->CurrentSurface(&offsetX, &offsetY);
|
|
|
|
if (thebesSurface->GetType() != gfxASurface::SurfaceTypeQuartz2) {
|
2007-02-16 07:18:56 +00:00
|
|
|
fprintf(stderr, "Expected surface of type Quartz2, got %d\n",
|
|
|
|
thebesSurface->GetType());
|
2006-08-30 22:06:44 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfxMatrix mat = thebesCtx->CurrentMatrix();
|
|
|
|
gfxQuartzSurface* quartzSurf = (gfxQuartzSurface*) (thebesSurface.get());
|
2007-02-08 16:25:10 +00:00
|
|
|
CGContextRef cgContext = quartzSurf->GetCGContext();
|
2006-08-30 22:06:44 +00:00
|
|
|
|
|
|
|
//fprintf (stderr, "surface: %p cgContext: %p\n", quartzSurf, cgContext);
|
|
|
|
|
|
|
|
if (cgContext == nsnull ||
|
2007-01-05 21:12:56 +00:00
|
|
|
((((unsigned long)cgContext) & 0xffff) == 0x3f3f)) {
|
2006-08-30 22:06:44 +00:00
|
|
|
fprintf (stderr, "********** Invalid CGContext!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Eventually we can just do a GetCTM and restore it with SetCTM,
|
|
|
|
// but for now do a full save/restore
|
|
|
|
CGAffineTransform mm0 = CGContextGetCTM(cgContext);
|
|
|
|
|
|
|
|
CGContextSaveGState(cgContext);
|
|
|
|
//CGContextSetCTM(cgContext, CGAffineTransformIdentity);
|
|
|
|
|
|
|
|
// I -think- that this context will always have an identity
|
|
|
|
// transform (since we don't maintain a transform on it in
|
|
|
|
// cairo-land, and instead push/pop as needed)
|
|
|
|
if (mat.HasNonTranslationOrFlip()) {
|
|
|
|
// If we have a scale, I think we've already lost; so don't round
|
|
|
|
// anything here
|
|
|
|
CGContextConcatCTM(cgContext,
|
2007-01-27 01:59:57 +00:00
|
|
|
CGAffineTransformMake(mat.xx, mat.xy,
|
|
|
|
mat.yx, mat.yy,
|
|
|
|
mat.x0, mat.y0));
|
2006-08-30 22:06:44 +00:00
|
|
|
} else {
|
|
|
|
// Otherwise, we round the x0/y0, because otherwise things get rendered badly
|
|
|
|
CGContextConcatCTM(cgContext,
|
2007-01-27 01:59:57 +00:00
|
|
|
CGAffineTransformMake(mat.xx, mat.xy,
|
|
|
|
mat.yx, mat.yy,
|
|
|
|
floor(mat.x0 + ROUND_CONST_FLOAT),
|
|
|
|
floor(mat.y0 + ROUND_CONST_FLOAT)));
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (1 /*aWidgetType == NS_THEME_TEXTFIELD*/) {
|
2007-01-31 18:43:34 +00:00
|
|
|
fprintf(stderr, "Native theme drawing widget %d [%p] dis:%d in rect [%d %d %d %d]\n",
|
|
|
|
aWidgetType, aFrame, IsDisabled(aFrame), aRect.x, aRect.y, aRect.width, aRect.height);
|
2007-02-16 07:18:56 +00:00
|
|
|
fprintf(stderr, "Native theme xform[0]: [%f %f %f %f %f %f]\n",
|
|
|
|
mm0.a, mm0.b, mm0.c, mm0.d, mm0.tx, mm0.ty);
|
2006-08-30 22:06:44 +00:00
|
|
|
CGAffineTransform mm = CGContextGetCTM(cgContext);
|
2007-01-05 21:12:56 +00:00
|
|
|
fprintf(stderr, "Native theme xform[1]: [%f %f %f %f %f %f]\n",
|
|
|
|
mm.a, mm.b, mm.c, mm.d, mm.tx, mm.ty);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-02-07 07:46:44 +00:00
|
|
|
CGRect macRect = CGRectMake(NSAppUnitsToIntPixels(aRect.x, p2a),
|
|
|
|
NSAppUnitsToIntPixels(aRect.y, p2a),
|
|
|
|
NSAppUnitsToIntPixels(aRect.width, p2a),
|
|
|
|
NSAppUnitsToIntPixels(aRect.height, p2a));
|
2006-08-30 22:06:44 +00:00
|
|
|
macRect.origin.x -= offsetX;
|
|
|
|
macRect.origin.y -= offsetY;
|
|
|
|
|
|
|
|
#if 0
|
2007-01-05 21:12:56 +00:00
|
|
|
fprintf(stderr, " --> macRect %f %f %f %f\n",
|
|
|
|
macRect.origin.x, macRect.origin.y, macRect.size.width, macRect.size.height);
|
2007-02-16 07:18:56 +00:00
|
|
|
CGRect bounds = CGContextGetClipBoundingBox(cgContext);
|
2007-01-31 18:43:34 +00:00
|
|
|
fprintf(stderr, " --> clip bounds: %f %f %f %f\n",
|
|
|
|
bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
|
|
|
|
|
|
|
|
//CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 1.0, 0.1);
|
|
|
|
//CGContextFillRect(cgContext, bounds);
|
2006-08-30 22:06:44 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
|
|
|
|
|
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_DIALOG: {
|
|
|
|
// XXXvlad -- I don't think we can just pass macRect here,
|
|
|
|
// due to pattern phase, but it seems like it works correctly
|
|
|
|
HIThemeBackgroundDrawInfo bdi = {
|
|
|
|
version: 0,
|
|
|
|
state: kThemeStateActive,
|
|
|
|
kind: kThemeBackgroundPlacard
|
|
|
|
};
|
|
|
|
|
2007-01-05 21:12:56 +00:00
|
|
|
HIThemeApplyBackground(&macRect, &bdi, cgContext, HITHEME_ORIENTATION);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_MENUPOPUP: {
|
|
|
|
HIThemeMenuDrawInfo mdi = {
|
|
|
|
version: 0,
|
|
|
|
menuType: IsDisabled(aFrame) ? kThemeMenuTypeInactive : kThemeMenuTypePopUp
|
|
|
|
};
|
|
|
|
|
2007-01-05 21:12:56 +00:00
|
|
|
HIThemeDrawMenuBackground(&macRect, &mdi, cgContext, HITHEME_ORIENTATION);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_MENUITEM: {
|
2007-02-08 16:25:10 +00:00
|
|
|
// maybe use kThemeMenuItemHierBackground or PopUpBackground instead of just Plain?
|
|
|
|
HIThemeMenuItemDrawInfo drawInfo = {
|
2006-08-30 22:06:44 +00:00
|
|
|
version: 0,
|
|
|
|
itemType: kThemeMenuItemPlain,
|
|
|
|
state: (IsDisabled(aFrame) ? kThemeMenuDisabled :
|
|
|
|
CheckBooleanAttr(aFrame, nsWidgetAtoms::mozmenuactive) ? kThemeMenuSelected :
|
|
|
|
kThemeMenuActive)
|
|
|
|
};
|
|
|
|
|
|
|
|
// XXX pass in the menu rect instead of always using the item rect
|
2007-02-08 16:25:10 +00:00
|
|
|
HIRect ignored;
|
|
|
|
HIThemeDrawMenuItem(&macRect, &macRect, &drawInfo, cgContext, HITHEME_ORIENTATION, &ignored);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TOOLTIP:
|
2007-01-05 21:12:56 +00:00
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 0.78, 1.0);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_CHECKBOX:
|
2007-01-05 21:12:56 +00:00
|
|
|
DrawCheckboxRadio(cgContext, kThemeCheckBox, macRect, IsChecked(aFrame), IsDisabled(aFrame), eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_RADIO:
|
2006-11-28 23:07:13 +00:00
|
|
|
DrawCheckboxRadio(cgContext, kThemeRadioButton, macRect, IsSelected(aFrame), IsDisabled(aFrame), eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_CHECKBOX_SMALL:
|
|
|
|
if (aRect.height == 15) {
|
|
|
|
// draw at 14x16, see comment in GetMinimumWidgetSize
|
|
|
|
// XXX this should probably happen earlier, before transform; this is very fragile
|
|
|
|
macRect.size.height += 1.0;
|
|
|
|
}
|
2006-11-28 23:07:13 +00:00
|
|
|
DrawCheckboxRadio(cgContext, kThemeSmallCheckBox, macRect, IsChecked(aFrame), IsDisabled(aFrame), eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_RADIO_SMALL:
|
|
|
|
if (aRect.height == 14) {
|
|
|
|
// draw at 14x15, see comment in GetMinimumWidgetSize
|
|
|
|
// XXX this should probably happen earlier, before transform; this is very fragile
|
|
|
|
macRect.size.height += 1.0;
|
|
|
|
}
|
2007-01-05 21:12:56 +00:00
|
|
|
DrawCheckboxRadio(cgContext, kThemeSmallRadioButton, macRect,
|
|
|
|
IsSelected(aFrame), IsDisabled(aFrame), eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_BUTTON:
|
|
|
|
case NS_THEME_BUTTON_SMALL:
|
2007-02-17 02:48:58 +00:00
|
|
|
// NS_THEME_BUTTON and NS_THEME_BUTTON_SMALL draw the same way because larger native pushbuttons
|
|
|
|
// are capable of drawing themselves at any size the small native pushbuttons can.
|
|
|
|
DrawButton(cgContext, kThemePushButton, macRect,
|
2007-01-05 21:12:56 +00:00
|
|
|
IsDefaultButton(aFrame), IsDisabled(aFrame),
|
|
|
|
kThemeButtonOn, kThemeAdornmentNone, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_BUTTON_BEVEL:
|
2007-01-05 21:12:56 +00:00
|
|
|
DrawButton(cgContext, kThemeMediumBevelButton, macRect,
|
|
|
|
IsDefaultButton(aFrame), IsDisabled(aFrame),
|
|
|
|
kThemeButtonOff, kThemeAdornmentNone, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_SPINNER: {
|
|
|
|
ThemeDrawState state = kThemeStateActive;
|
|
|
|
nsIContent* content = aFrame->GetContent();
|
|
|
|
if (content->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::state,
|
2007-01-05 21:12:56 +00:00
|
|
|
NS_LITERAL_STRING("up"), eCaseMatters)) {
|
2006-08-30 22:06:44 +00:00
|
|
|
state = kThemeStatePressedUp;
|
2007-01-05 21:12:56 +00:00
|
|
|
}
|
2006-08-30 22:06:44 +00:00
|
|
|
else if (content->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::state,
|
2007-01-05 21:12:56 +00:00
|
|
|
NS_LITERAL_STRING("down"), eCaseMatters)) {
|
2006-08-30 22:06:44 +00:00
|
|
|
state = kThemeStatePressedDown;
|
2007-01-05 21:12:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DrawSpinButtons(cgContext, kThemeIncDecButton, macRect, IsDisabled(aFrame),
|
|
|
|
state, kThemeAdornmentNone, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TOOLBAR_BUTTON:
|
2007-01-05 21:12:56 +00:00
|
|
|
DrawButton(cgContext, kThemePushButton, macRect,
|
|
|
|
IsDefaultButton(aFrame), IsDisabled(aFrame),
|
|
|
|
kThemeButtonOn, kThemeAdornmentNone, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TOOLBAR_SEPARATOR: {
|
2007-02-20 19:07:50 +00:00
|
|
|
HIThemeSeparatorDrawInfo sdi = { 0, kThemeStateActive };
|
2007-01-05 21:12:56 +00:00
|
|
|
HIThemeDrawSeparator(&macRect, &sdi, cgContext, HITHEME_ORIENTATION);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TOOLBAR:
|
|
|
|
case NS_THEME_TOOLBOX:
|
|
|
|
case NS_THEME_STATUSBAR: {
|
|
|
|
HIThemeHeaderDrawInfo hdi = { 0, kThemeStateActive, kHIThemeHeaderKindWindow };
|
2007-01-05 21:12:56 +00:00
|
|
|
HIThemeDrawHeader(&macRect, &hdi, cgContext, HITHEME_ORIENTATION);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN:
|
2007-01-05 21:12:56 +00:00
|
|
|
DrawButton(cgContext, kThemePopupButton, macRect,
|
|
|
|
IsDefaultButton(aFrame), IsDisabled(aFrame),
|
|
|
|
kThemeButtonOn, kThemeAdornmentNone, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
2007-01-22 19:54:36 +00:00
|
|
|
DrawButton (cgContext, kThemeArrowButton, macRect, PR_FALSE,
|
|
|
|
IsDisabled(aFrame), kThemeButtonOn,
|
|
|
|
kThemeAdornmentArrowDownArrow, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TEXTFIELD:
|
2006-12-13 21:13:42 +00:00
|
|
|
// HIThemeSetFill is not available on 10.3
|
2007-02-08 16:25:10 +00:00
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
2007-01-05 21:12:56 +00:00
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
DrawFrame(cgContext, kHIThemeFrameTextFieldSquare,
|
|
|
|
macRect, (IsDisabled(aFrame) || IsReadOnly(aFrame)), eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_PROGRESSBAR:
|
2007-02-20 19:07:50 +00:00
|
|
|
DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame),
|
|
|
|
PR_TRUE, GetProgressValue(aFrame));
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_PROGRESSBAR_VERTICAL:
|
2007-02-20 19:07:50 +00:00
|
|
|
DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame),
|
|
|
|
PR_FALSE, GetProgressValue(aFrame));
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_PROGRESSBAR_CHUNK:
|
|
|
|
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
|
|
|
|
// do nothing, covered by the progress bar cases above
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_TWISTY:
|
2007-01-05 21:12:56 +00:00
|
|
|
DrawButton(cgContext, kThemeDisclosureButton, macRect, PR_FALSE, IsDisabled(aFrame),
|
|
|
|
kThemeDisclosureRight, kThemeAdornmentNone, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_TWISTY_OPEN:
|
2007-01-05 21:12:56 +00:00
|
|
|
DrawButton(cgContext, kThemeDisclosureButton, macRect, PR_FALSE, IsDisabled(aFrame),
|
|
|
|
kThemeDisclosureDown, kThemeAdornmentNone, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_HEADER_CELL: {
|
|
|
|
TreeSortDirection sortDirection = GetTreeSortDirection(aFrame);
|
2007-01-05 21:12:56 +00:00
|
|
|
DrawButton(cgContext, kThemeListHeaderButton, macRect, PR_FALSE, IsDisabled(aFrame),
|
|
|
|
sortDirection == eTreeSortDirection_Natural ? kThemeButtonOff : kThemeButtonOn,
|
|
|
|
sortDirection == eTreeSortDirection_Descending ?
|
|
|
|
kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone, eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_TREEITEM:
|
|
|
|
case NS_THEME_TREEVIEW:
|
2007-02-08 16:25:10 +00:00
|
|
|
// HIThemeSetFill is not available on 10.3
|
|
|
|
// HIThemeSetFill(kThemeBrushWhite, NULL, cgContext, HITHEME_ORIENTATION);
|
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
2007-01-05 21:12:56 +00:00
|
|
|
CGContextFillRect(cgContext, macRect);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_HEADER:
|
|
|
|
// do nothing, taken care of by individual header cells
|
|
|
|
case NS_THEME_TREEVIEW_HEADER_SORTARROW:
|
|
|
|
// do nothing, taken care of by treeview header
|
|
|
|
case NS_THEME_TREEVIEW_LINE:
|
|
|
|
// do nothing, these lines don't exist on macos
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_SCALE_HORIZONTAL:
|
|
|
|
case NS_THEME_SCALE_VERTICAL: {
|
|
|
|
PRInt32 curpos = CheckIntAttr(aFrame, nsWidgetAtoms::curpos);
|
|
|
|
PRInt32 minpos = CheckIntAttr(aFrame, nsWidgetAtoms::minpos);
|
|
|
|
PRInt32 maxpos = CheckIntAttr(aFrame, nsWidgetAtoms::maxpos);
|
|
|
|
if (!maxpos)
|
|
|
|
maxpos = 100;
|
|
|
|
|
|
|
|
DrawScale(cgContext, macRect, IsDisabled(aFrame), eventState,
|
|
|
|
(aWidgetType == NS_THEME_SCALE_VERTICAL),
|
|
|
|
curpos, minpos, maxpos);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_SCALE_THUMB_HORIZONTAL:
|
|
|
|
case NS_THEME_SCALE_THUMB_VERTICAL:
|
|
|
|
// do nothing, drawn by scale
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_BUTTON_UP:
|
|
|
|
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
|
|
|
|
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
|
|
|
|
// Scrollbars are now native on mac, via nsNativeScrollbarFrame.
|
|
|
|
// So, this should never be called.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_LISTBOX:
|
2006-12-13 21:13:42 +00:00
|
|
|
// HIThemeSetFill is not available on 10.3
|
2007-02-08 16:25:10 +00:00
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
2007-01-05 21:12:56 +00:00
|
|
|
CGContextFillRect(cgContext, macRect);
|
2006-11-28 23:07:13 +00:00
|
|
|
DrawFrame(cgContext, kHIThemeFrameListBox,
|
|
|
|
macRect, (IsDisabled(aFrame) || IsReadOnly(aFrame)), eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TAB: {
|
2006-11-28 23:07:13 +00:00
|
|
|
DrawTab(cgContext, macRect,
|
|
|
|
IsDisabled(aFrame), IsSelectedTab(aFrame),
|
|
|
|
PR_TRUE, IsBottomTab(aFrame),
|
|
|
|
eventState);
|
2006-08-30 22:06:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TAB_PANELS:
|
2007-02-20 19:07:50 +00:00
|
|
|
DrawTabPanel(cgContext, macRect);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
CGContextRestoreGState(cgContext);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::GetWidgetBorder(nsIDeviceContext* aContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
|
|
|
nsMargin* aResult)
|
|
|
|
{
|
2007-02-08 16:25:10 +00:00
|
|
|
aResult->SizeTo(0, 0, 0, 0);
|
2007-01-05 21:12:56 +00:00
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_BUTTON:
|
2007-02-17 02:48:58 +00:00
|
|
|
case NS_THEME_BUTTON_SMALL:
|
2006-08-30 22:06:44 +00:00
|
|
|
aResult->SizeTo(kAquaPushButtonEndcaps, kAquaPushButtonTopBottom,
|
|
|
|
kAquaPushButtonEndcaps, kAquaPushButtonTopBottom);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN:
|
2007-01-22 19:54:36 +00:00
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
2006-08-30 22:06:44 +00:00
|
|
|
aResult->SizeTo(kAquaDropdownLeftEndcap, kAquaPushButtonTopBottom,
|
|
|
|
kAquaDropwdonRightEndcap, kAquaPushButtonTopBottom);
|
|
|
|
break;
|
|
|
|
|
2007-02-16 18:18:48 +00:00
|
|
|
case NS_THEME_TEXTFIELD: {
|
|
|
|
SInt32 frameOutset = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
|
|
|
|
aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset);
|
|
|
|
}
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_LISTBOX: {
|
|
|
|
SInt32 frameOutset = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset);
|
|
|
|
aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-02-08 16:25:10 +00:00
|
|
|
// return false here to indicate that CSS padding values should be used
|
2006-08-30 22:06:44 +00:00
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::GetWidgetPadding(nsIDeviceContext* aContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
|
|
|
nsMargin* aResult)
|
|
|
|
{
|
2007-02-16 18:18:48 +00:00
|
|
|
if (aWidgetType == NS_THEME_TEXTFIELD) {
|
|
|
|
SInt32 nativePadding = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricEditTextWhitespace, &nativePadding);
|
|
|
|
aResult->SizeTo(nativePadding, nativePadding, nativePadding, nativePadding);
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-02-17 02:48:58 +00:00
|
|
|
else if (aWidgetType == NS_THEME_BUTTON ||
|
|
|
|
aWidgetType == NS_THEME_BUTTON_SMALL) {
|
|
|
|
// The button draws with a shadow on the bottom so we have to move the text
|
|
|
|
// up one pixel to center it
|
|
|
|
aResult->SizeTo(0, -1, 0, 1);
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-02-16 18:18:48 +00:00
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-02-17 02:48:58 +00:00
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::GetWidgetOverflow(nsIDeviceContext* aContext, nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType, nsRect* aResult)
|
|
|
|
{
|
|
|
|
// We assume that all native widgets can draw a focus ring that will be less than
|
|
|
|
// or equal to 4 pixels thick.
|
|
|
|
nsIntMargin extraSize = nsIntMargin(4, 4, 4, 4);
|
|
|
|
PRInt32 p2a = aContext->AppUnitsPerDevPixel();
|
|
|
|
nsMargin m(NSIntPixelsToAppUnits(extraSize.left, p2a),
|
|
|
|
NSIntPixelsToAppUnits(extraSize.top, p2a),
|
|
|
|
NSIntPixelsToAppUnits(extraSize.right, p2a),
|
|
|
|
NSIntPixelsToAppUnits(extraSize.bottom, p2a));
|
|
|
|
nsRect r(nsPoint(0, 0), aFrame->GetSize());
|
|
|
|
r.Inflate(m);
|
|
|
|
*aResult = r;
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::GetMinimumWidgetSize(nsIRenderingContext* aContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
|
|
|
nsSize* aResult,
|
|
|
|
PRBool* aIsOverridable)
|
|
|
|
{
|
|
|
|
aResult->SizeTo(0,0);
|
|
|
|
*aIsOverridable = PR_TRUE;
|
|
|
|
|
|
|
|
switch (aWidgetType) {
|
2007-02-17 02:48:58 +00:00
|
|
|
// These are the same since a normal native pushbutton can become as small
|
|
|
|
// as the small native pushbutton.
|
2006-08-30 22:06:44 +00:00
|
|
|
case NS_THEME_BUTTON:
|
2007-02-17 02:48:58 +00:00
|
|
|
case NS_THEME_BUTTON_SMALL:
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
SInt32 buttonHeight = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricPushButtonHeight, &buttonHeight);
|
2007-01-05 21:12:56 +00:00
|
|
|
aResult->SizeTo(kAquaPushButtonEndcaps * 2, buttonHeight);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-02-17 02:48:58 +00:00
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
case NS_THEME_SPINNER:
|
|
|
|
{
|
|
|
|
SInt32 buttonHeight = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricPushButtonHeight, &buttonHeight);
|
|
|
|
aResult->SizeTo(kAquaPushButtonEndcaps, buttonHeight);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_CHECKBOX:
|
|
|
|
{
|
|
|
|
SInt32 boxHeight = 0, boxWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricCheckBoxWidth, &boxWidth);
|
|
|
|
::GetThemeMetric(kThemeMetricCheckBoxHeight, &boxHeight);
|
|
|
|
aResult->SizeTo(boxWidth, boxHeight);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
{
|
|
|
|
SInt32 radioHeight = 0, radioWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricRadioButtonWidth, &radioWidth);
|
|
|
|
::GetThemeMetric(kThemeMetricRadioButtonHeight, &radioHeight);
|
|
|
|
aResult->SizeTo(radioWidth, radioHeight);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_CHECKBOX_SMALL:
|
|
|
|
{
|
|
|
|
// Appearance manager (and the Aqua HIG) will tell us that a small
|
|
|
|
// checkbox is 14x16. This includes a transparent row at the bottom
|
|
|
|
// of the image. In order to allow the baseline for text to be aligned
|
|
|
|
// with the bottom of the checkbox, we report the size as 14x15, but
|
|
|
|
// we'll always tell appearance manager to draw it at 14x16. This
|
|
|
|
// will result in Gecko aligning text with the real bottom of the
|
|
|
|
// checkbox.
|
|
|
|
|
|
|
|
aResult->SizeTo(14, 15);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_RADIO_SMALL:
|
|
|
|
{
|
|
|
|
// Same as above, but appearance manager reports 14x15, and we
|
|
|
|
// tell gecko 14x14.
|
|
|
|
|
|
|
|
aResult->SizeTo(14, 14);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN:
|
2007-01-22 19:54:36 +00:00
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
2006-08-30 22:06:44 +00:00
|
|
|
{
|
|
|
|
SInt32 popupHeight = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricPopupButtonHeight, &popupHeight);
|
|
|
|
aResult->SizeTo(0, popupHeight);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_TEXTFIELD:
|
|
|
|
{
|
|
|
|
// at minimum, we should be tall enough for 9pt text.
|
|
|
|
// I'm using hardcoded values here because the appearance manager
|
|
|
|
// values for the frame size are incorrect.
|
2007-01-05 21:12:56 +00:00
|
|
|
aResult->SizeTo(0, (2 + 2) /* top */ + 9 + (1 + 1) /* bottom */);
|
2006-08-30 22:06:44 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_PROGRESSBAR:
|
|
|
|
{
|
|
|
|
SInt32 barHeight = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricNormalProgressBarThickness, &barHeight);
|
|
|
|
aResult->SizeTo(0, barHeight);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_TWISTY:
|
|
|
|
case NS_THEME_TREEVIEW_TWISTY_OPEN:
|
|
|
|
{
|
|
|
|
SInt32 twistyHeight = 0, twistyWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricDisclosureButtonWidth, &twistyWidth);
|
|
|
|
::GetThemeMetric(kThemeMetricDisclosureButtonHeight, &twistyHeight);
|
|
|
|
aResult->SizeTo(twistyWidth, twistyHeight);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_HEADER:
|
|
|
|
case NS_THEME_TREEVIEW_HEADER_CELL:
|
|
|
|
{
|
|
|
|
SInt32 headerHeight = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight);
|
|
|
|
aResult->SizeTo(0, headerHeight);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_SCALE_HORIZONTAL:
|
|
|
|
{
|
|
|
|
SInt32 scaleHeight = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricHSliderHeight, &scaleHeight);
|
|
|
|
aResult->SizeTo(scaleHeight, scaleHeight);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_SCALE_VERTICAL:
|
|
|
|
{
|
|
|
|
SInt32 scaleWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricVSliderWidth, &scaleWidth);
|
|
|
|
aResult->SizeTo(scaleWidth, scaleWidth);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-01-19 07:03:20 +00:00
|
|
|
case NS_THEME_SCROLLBAR_SMALL:
|
|
|
|
{
|
|
|
|
SInt32 scrollbarWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricSmallScrollBarWidth, &scrollbarWidth);
|
|
|
|
aResult->SizeTo(scrollbarWidth, scrollbarWidth);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-08-30 22:06:44 +00:00
|
|
|
case NS_THEME_SCROLLBAR:
|
|
|
|
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_THUMB_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
|
|
|
{
|
|
|
|
// yeah, i know i'm cheating a little here, but i figure that it
|
|
|
|
// really doesn't matter if the scrollbar is vertical or horizontal
|
|
|
|
// and the width metric is a really good metric for every piece
|
|
|
|
// of the scrollbar.
|
|
|
|
SInt32 scrollbarWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricScrollBarWidth, &scrollbarWidth);
|
|
|
|
aResult->SizeTo(scrollbarWidth, scrollbarWidth);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
|
|
|
|
nsIAtom* aAttribute, PRBool* aShouldRepaint)
|
|
|
|
{
|
|
|
|
// Some widget types just never change state.
|
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_TOOLBOX:
|
|
|
|
case NS_THEME_TOOLBAR:
|
|
|
|
case NS_THEME_TOOLBAR_BUTTON:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
|
|
|
case NS_THEME_STATUSBAR:
|
|
|
|
case NS_THEME_STATUSBAR_PANEL:
|
|
|
|
case NS_THEME_STATUSBAR_RESIZER_PANEL:
|
|
|
|
case NS_THEME_PROGRESSBAR_CHUNK:
|
|
|
|
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
|
|
|
|
case NS_THEME_PROGRESSBAR:
|
|
|
|
case NS_THEME_PROGRESSBAR_VERTICAL:
|
|
|
|
case NS_THEME_TOOLTIP:
|
|
|
|
case NS_THEME_TAB_PANELS:
|
|
|
|
case NS_THEME_TAB_PANEL:
|
|
|
|
case NS_THEME_TEXTFIELD:
|
|
|
|
case NS_THEME_DIALOG:
|
|
|
|
case NS_THEME_MENUPOPUP:
|
|
|
|
*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::mozmenuactive ||
|
|
|
|
aAttribute == nsWidgetAtoms::sortdirection)
|
|
|
|
*aShouldRepaint = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::ThemeChanged()
|
|
|
|
{
|
2007-01-05 21:12:56 +00:00
|
|
|
// This is unimplemented because we don't care if gecko changes its theme
|
|
|
|
// and Mac OS X doesn't have themes.
|
2006-08-30 22:06:44 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType)
|
|
|
|
{
|
2006-10-05 07:05:58 +00:00
|
|
|
#ifndef MOZ_MACBROWSER
|
|
|
|
// Only support HTML widgets in Camino builds
|
2006-08-30 22:06:44 +00:00
|
|
|
if (aFrame && aFrame->GetContent()->IsNodeOfType(nsINode::eHTML))
|
|
|
|
return PR_FALSE;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
PRBool retVal = PR_FALSE;
|
|
|
|
|
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_DIALOG:
|
|
|
|
case NS_THEME_WINDOW:
|
|
|
|
case NS_THEME_MENUPOPUP:
|
|
|
|
case NS_THEME_MENUITEM:
|
|
|
|
case NS_THEME_TOOLTIP:
|
|
|
|
|
|
|
|
case NS_THEME_CHECKBOX:
|
|
|
|
case NS_THEME_CHECKBOX_SMALL:
|
|
|
|
case NS_THEME_CHECKBOX_CONTAINER:
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
case NS_THEME_RADIO_SMALL:
|
|
|
|
case NS_THEME_RADIO_CONTAINER:
|
|
|
|
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:
|
|
|
|
//case NS_THEME_TOOLBOX:
|
|
|
|
//case NS_THEME_TOOLBAR_BUTTON:
|
|
|
|
case NS_THEME_PROGRESSBAR:
|
|
|
|
case NS_THEME_PROGRESSBAR_VERTICAL:
|
|
|
|
case NS_THEME_PROGRESSBAR_CHUNK:
|
|
|
|
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
|
|
|
|
case NS_THEME_TOOLBAR_SEPARATOR:
|
|
|
|
|
|
|
|
case NS_THEME_TAB_PANELS:
|
|
|
|
case NS_THEME_TAB:
|
|
|
|
case NS_THEME_TAB_LEFT_EDGE:
|
|
|
|
case NS_THEME_TAB_RIGHT_EDGE:
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_TWISTY:
|
|
|
|
case NS_THEME_TREEVIEW_TWISTY_OPEN:
|
|
|
|
case NS_THEME_TREEVIEW:
|
|
|
|
case NS_THEME_TREEVIEW_HEADER:
|
|
|
|
case NS_THEME_TREEVIEW_HEADER_CELL:
|
|
|
|
case NS_THEME_TREEVIEW_HEADER_SORTARROW:
|
|
|
|
case NS_THEME_TREEVIEW_TREEITEM:
|
|
|
|
case NS_THEME_TREEVIEW_LINE:
|
|
|
|
|
|
|
|
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_SCROLLBAR:
|
2007-01-19 07:03:20 +00:00
|
|
|
case NS_THEME_SCROLLBAR_SMALL:
|
2006-08-30 22:06:44 +00:00
|
|
|
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_THUMB_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
|
|
|
retVal = PR_TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_LISTBOX:
|
|
|
|
case NS_THEME_DROPDOWN:
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
|
|
|
case NS_THEME_DROPDOWN_TEXT:
|
|
|
|
// Support listboxes and dropdowns regardless of styling,
|
|
|
|
// since non-themed ones look totally wrong.
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retVal ? !IsWidgetStyled(aPresContext, aFrame, aWidgetType) : PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::WidgetIsContainer(PRUint8 aWidgetType)
|
|
|
|
{
|
2007-02-08 16:25:10 +00:00
|
|
|
// flesh this out at some point
|
2006-08-30 22:06:44 +00:00
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
case NS_THEME_CHECKBOX:
|
|
|
|
case NS_THEME_PROGRESSBAR:
|
|
|
|
return PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-02-16 01:53:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::ThemeDrawsFocusForWidget(nsPresContext* aPresContext, nsIFrame* aFrame, PRUint8 aWidgetType)
|
|
|
|
{
|
|
|
|
if (aWidgetType == NS_THEME_DROPDOWN ||
|
|
|
|
aWidgetType == NS_THEME_BUTTON ||
|
|
|
|
aWidgetType == NS_THEME_BUTTON_SMALL)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|