2007-03-22 10:30:00 -07: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)
|
|
|
|
* Josh Aas <josh@mozilla.com>
|
2007-04-10 17:25:11 -07:00
|
|
|
* Colin Barrett <cbarrett@mozilla.com>
|
2008-02-20 03:33:27 -08:00
|
|
|
* Matthew Gregan <kinetik@flim.org>
|
2007-03-22 10:30:00 -07: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"
|
2008-02-20 17:01:27 -08:00
|
|
|
#include "nsObjCExceptions.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#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"
|
2007-12-23 11:22:47 -08:00
|
|
|
#include "nsToolkit.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "gfxContext.h"
|
|
|
|
#include "gfxQuartzSurface.h"
|
2008-02-20 03:33:27 -08:00
|
|
|
#include "gfxQuartzNativeDrawing.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#define DRAW_IN_FRAME_DEBUG 0
|
2007-04-10 17:25:11 -07:00
|
|
|
#define SCROLLBARS_VISUAL_DEBUG 0
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-08-07 12:36:40 -07:00
|
|
|
// private Quartz routines needed here
|
2007-03-22 10:30:00 -07:00
|
|
|
extern "C" {
|
|
|
|
CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
|
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
// Copied from nsLookAndFeel.h
|
|
|
|
// Apple hasn't defined a constant for scollbars with two arrows on each end, so we'll use this one.
|
|
|
|
static const int kThemeScrollBarArrowsBoth = 2;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#define HITHEME_ORIENTATION kHIThemeOrientationNormal
|
2008-01-08 18:52:36 -08:00
|
|
|
#define MAX_FOCUS_RING_WIDTH 4
|
|
|
|
|
|
|
|
// These enums are for indexing into the margin array.
|
|
|
|
enum {
|
|
|
|
tigerOS,
|
|
|
|
leopardOS
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
miniControlSize,
|
|
|
|
smallControlSize,
|
|
|
|
regularControlSize
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
leftMargin,
|
|
|
|
topMargin,
|
|
|
|
rightMargin,
|
|
|
|
bottomMargin
|
|
|
|
};
|
|
|
|
|
|
|
|
static int EnumSizeForCocoaSize(NSControlSize cocoaControlSize) {
|
|
|
|
if (cocoaControlSize == NSMiniControlSize)
|
|
|
|
return miniControlSize;
|
|
|
|
else if (cocoaControlSize == NSSmallControlSize)
|
|
|
|
return smallControlSize;
|
|
|
|
else
|
|
|
|
return regularControlSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void InflateControlRect(NSRect* rect, NSControlSize cocoaControlSize, const float marginSet[][3][4])
|
|
|
|
{
|
|
|
|
static int osIndex = nsToolkit::OnLeopardOrLater() ? leopardOS : tigerOS;
|
|
|
|
int controlSize = EnumSizeForCocoaSize(cocoaControlSize);
|
|
|
|
const float* buttonMargins = marginSet[osIndex][controlSize];
|
|
|
|
rect->origin.x -= buttonMargins[leftMargin];
|
|
|
|
rect->origin.y -= buttonMargins[bottomMargin];
|
|
|
|
rect->size.width += buttonMargins[leftMargin] + buttonMargins[rightMargin];
|
|
|
|
rect->size.height += buttonMargins[bottomMargin] + buttonMargins[topMargin];
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-05-08 05:54:48 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMPL_ISUPPORTS1(nsNativeThemeCocoa, nsITheme)
|
|
|
|
|
|
|
|
|
|
|
|
nsNativeThemeCocoa::nsNativeThemeCocoa()
|
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
mPushButtonCell = [[NSButtonCell alloc] initTextCell:nil];
|
|
|
|
[mPushButtonCell setButtonType:NSMomentaryPushInButton];
|
|
|
|
[mPushButtonCell setHighlightsBy:NSPushInCellMask];
|
2008-01-13 20:48:33 -08:00
|
|
|
|
|
|
|
mRadioButtonCell = [[NSButtonCell alloc] initTextCell:nil];
|
|
|
|
[mRadioButtonCell setButtonType:NSRadioButton];
|
|
|
|
[mRadioButtonCell setBezelStyle:NSRoundedBezelStyle];
|
|
|
|
[mRadioButtonCell setHighlightsBy:NSPushInCellMask];
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsNativeThemeCocoa::~nsNativeThemeCocoa()
|
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
[mPushButtonCell release];
|
2008-01-13 20:48:33 -08:00
|
|
|
[mRadioButtonCell release];
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-13 20:48:33 -08:00
|
|
|
nsNativeThemeCocoa::DrawCheckbox(CGContextRef cgContext, ThemeButtonKind inKind,
|
|
|
|
const HIRect& inBoxRect, PRBool inChecked,
|
2008-05-09 11:12:39 -07:00
|
|
|
PRBool inDisabled, PRInt32 inState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
HIThemeButtonDrawInfo bdi;
|
|
|
|
bdi.version = 0;
|
|
|
|
bdi.kind = inKind;
|
|
|
|
|
|
|
|
if (inDisabled)
|
|
|
|
bdi.state = kThemeStateUnavailable;
|
|
|
|
else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
|
|
|
|
bdi.state = kThemeStatePressed;
|
|
|
|
else
|
2008-05-09 11:12:39 -07:00
|
|
|
bdi.state = kThemeStateActive;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
bdi.value = inChecked ? kThemeButtonOn : kThemeButtonOff;
|
2008-05-09 11:12:39 -07:00
|
|
|
bdi.adornment = (inState & NS_EVENT_STATE_FOCUS) ? kThemeAdornmentFocus : kThemeAdornmentNone;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-05-17 19:01:02 -07:00
|
|
|
HIRect drawFrame = inBoxRect;
|
2008-03-14 12:29:32 -07:00
|
|
|
|
|
|
|
// on Tiger, shift the checkbox rendering down 1px to get the frame
|
|
|
|
// in the right spot
|
|
|
|
if (!nsToolkit::OnLeopardOrLater() && inKind == kThemeSmallCheckBox)
|
2007-05-17 19:01:02 -07:00
|
|
|
drawFrame.origin.y += 1;
|
|
|
|
|
|
|
|
HIThemeDrawButton(&drawFrame, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
2008-03-14 12:29:32 -07:00
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
|
2007-03-22 10:30:00 -07:00
|
|
|
CGContextFillRect(cgContext, inBoxRect);
|
|
|
|
#endif
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
/*
|
|
|
|
* Draw the given NSCell into the given cgContext.
|
|
|
|
*
|
|
|
|
* destRect - the size and position of the resulting control rectangle
|
|
|
|
* controlSize - the NSControlSize which will be given to the NSCell before
|
|
|
|
* asking it to render
|
|
|
|
* naturalWidth, naturalHeight - The natural dimensions of this control.
|
|
|
|
* If the control rect size is not equal to either of these, a scale
|
|
|
|
* will be applied to the context so that rendering the control at the
|
|
|
|
* natural size will result in it filling the destRect space.
|
|
|
|
* If a control has no natural dimensions in either/both axes, pass 0.0f.
|
|
|
|
* minWidth, minHeight - The minimum dimensions of this control.
|
|
|
|
* If the control rect size is less than the minimum for a given axis,
|
|
|
|
* a scale will be applied to the context so that the minimum is used
|
|
|
|
* for drawing. If a control has no minimum dimensions in either/both
|
|
|
|
* axes, pass 0.0f.
|
|
|
|
* marginSet - an array of margins; a multidimensional array of [2][3][4],
|
|
|
|
* with the first two array elements being margins for Tiger or Leopard,
|
|
|
|
* the next three being control size (mini, small, regular), and the 4
|
|
|
|
* being the 4 margin values.
|
|
|
|
* doSaveCTM - whether this routine should bother to save the CTM before
|
|
|
|
* manipuating; if the caller has already done this, pass PR_FALSE.
|
|
|
|
*/
|
2008-01-13 20:48:33 -08:00
|
|
|
void
|
2008-03-04 12:51:54 -08:00
|
|
|
nsNativeThemeCocoa::DrawCellWithScaling(NSCell *cell,
|
|
|
|
CGContextRef cgContext,
|
|
|
|
const HIRect& destRect,
|
|
|
|
NSControlSize controlSize,
|
|
|
|
float naturalWidth, float naturalHeight,
|
|
|
|
float minWidth, float minHeight,
|
|
|
|
const float marginSet[][3][4],
|
|
|
|
PRBool doSaveCTM)
|
2008-01-13 20:48:33 -08:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-03-04 13:07:04 -08:00
|
|
|
NSRect drawRect = NSMakeRect(destRect.origin.x, destRect.origin.y, destRect.size.width, destRect.size.height);
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
CGAffineTransform savedCTM;
|
2008-03-14 12:29:32 -07:00
|
|
|
NSGraphicsContext* savedContext = NULL;
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
float xscale = 1.0f, yscale = 1.0f;
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
if (naturalWidth != 0.0f) {
|
|
|
|
xscale = drawRect.size.width / naturalWidth;
|
|
|
|
drawRect.size.width = naturalWidth;
|
|
|
|
}
|
|
|
|
else if (minWidth != 0.0f &&
|
|
|
|
drawRect.size.width < minWidth)
|
|
|
|
{
|
|
|
|
xscale = drawRect.size.width / minWidth;
|
|
|
|
drawRect.size.width = minWidth;
|
2008-01-13 20:48:33 -08:00
|
|
|
}
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
if (naturalHeight != 0.0f) {
|
|
|
|
yscale = drawRect.size.height / naturalHeight;
|
|
|
|
drawRect.size.height = naturalHeight;
|
|
|
|
}
|
|
|
|
else if (minHeight != 0.0f &&
|
|
|
|
drawRect.size.height < minHeight)
|
|
|
|
{
|
|
|
|
yscale = drawRect.size.height / minHeight;
|
|
|
|
drawRect.size.height = minHeight;
|
|
|
|
}
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-03-14 12:29:32 -07:00
|
|
|
if (doSaveCTM)
|
|
|
|
savedCTM = CGContextGetCTM(cgContext);
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-03-14 12:29:32 -07:00
|
|
|
if (xscale == 1.0f && yscale == 1.0f) {
|
|
|
|
// Inflate the rect Gecko gave us by the margin for the control.
|
|
|
|
InflateControlRect(&drawRect, controlSize, marginSet);
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-03-14 12:29:32 -07:00
|
|
|
// Set up the graphics context we've been asked to draw to.
|
|
|
|
savedContext = [NSGraphicsContext currentContext];
|
|
|
|
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]];
|
|
|
|
|
|
|
|
[cell drawWithFrame:drawRect inView:[NSView focusView]];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
float w = ceil(drawRect.size.width);
|
|
|
|
float h = ceil(drawRect.size.height);
|
|
|
|
|
|
|
|
NSRect tmpRect = NSMakeRect(0.0f, 0.0f, w, h);
|
|
|
|
|
|
|
|
// inflate to figure out the frame we need to tell NSCell to draw in, to get something that's 0,0,w,h
|
|
|
|
InflateControlRect(&tmpRect, controlSize, marginSet);
|
|
|
|
|
|
|
|
// and then, expand by MAX_FOCUS_RING_WIDTH size to make sure we can capture any focus ring
|
|
|
|
w += MAX_FOCUS_RING_WIDTH * 2.0;
|
|
|
|
h += MAX_FOCUS_RING_WIDTH * 2.0;
|
|
|
|
|
|
|
|
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
|
|
|
|
CGContextRef ctx = CGBitmapContextCreate(NULL,
|
|
|
|
(int) w, (int) h,
|
|
|
|
8, (int) w * 4,
|
|
|
|
rgb, kCGImageAlphaPremultipliedFirst);
|
|
|
|
CGColorSpaceRelease(rgb);
|
|
|
|
|
|
|
|
CGContextTranslateCTM(ctx, MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH);
|
|
|
|
|
|
|
|
savedContext = [NSGraphicsContext currentContext];
|
|
|
|
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]];
|
|
|
|
|
|
|
|
[cell drawWithFrame:tmpRect inView:[NSView focusView]];
|
|
|
|
|
|
|
|
[NSGraphicsContext setCurrentContext:savedContext];
|
|
|
|
|
|
|
|
CGImageRef img = CGBitmapContextCreateImage(ctx);
|
|
|
|
|
|
|
|
// Drop the image into the original destination rectangle, scaling to fit
|
|
|
|
// XXX in theory we should scale this MAX_FOCUS_RING_WIDTH here by xscale/yscale,
|
|
|
|
// but in practice, this looks better.
|
|
|
|
CGContextDrawImage(cgContext, CGRectMake(destRect.origin.x - MAX_FOCUS_RING_WIDTH,
|
|
|
|
destRect.origin.y - MAX_FOCUS_RING_WIDTH,
|
|
|
|
destRect.size.width + MAX_FOCUS_RING_WIDTH * 2,
|
|
|
|
destRect.size.height + MAX_FOCUS_RING_WIDTH * 2),
|
|
|
|
img);
|
|
|
|
|
|
|
|
CGImageRelease(img);
|
|
|
|
CGContextRelease(ctx);
|
|
|
|
}
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
if (doSaveCTM)
|
|
|
|
CGContextSetCTM(cgContext, savedCTM);
|
|
|
|
|
2008-03-14 12:29:32 -07:00
|
|
|
[NSGraphicsContext setCurrentContext:savedContext];
|
|
|
|
|
2008-01-13 20:48:33 -08:00
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
2008-03-14 12:29:32 -07:00
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
|
2008-03-04 12:51:54 -08:00
|
|
|
CGContextFillRect(cgContext, destRect);
|
2008-01-13 20:48:33 -08:00
|
|
|
#endif
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2008-01-13 20:48:33 -08:00
|
|
|
}
|
2008-05-09 11:12:39 -07:00
|
|
|
|
2008-03-14 12:29:32 -07:00
|
|
|
// These are the sizes that Gecko needs to request to draw if it wants
|
|
|
|
// to get a standard-sized Aqua radio button drawn. Note that the rects
|
|
|
|
// that draw these are actually a little bigger.
|
|
|
|
#define NATURAL_MINI_RADIO_BUTTON_WIDTH 11
|
|
|
|
#define NATURAL_MINI_RADIO_BUTTON_HEIGHT 11
|
|
|
|
#define NATURAL_SMALL_RADIO_BUTTON_WIDTH 14
|
|
|
|
#define NATURAL_SMALL_RADIO_BUTTON_HEIGHT 14
|
|
|
|
#define NATURAL_REGULAR_RADIO_BUTTON_WIDTH 16
|
|
|
|
#define NATURAL_REGULAR_RADIO_BUTTON_HEIGHT 16
|
|
|
|
|
|
|
|
// These were calculated by testing all three sizes on the respective operating system.
|
|
|
|
static const float radioButtonMargins[2][3][4] =
|
|
|
|
{
|
|
|
|
{ // Tiger
|
|
|
|
{0, 0, 0, 0}, // mini - if we ever use this we'll have to calculate it
|
|
|
|
{0, 0, 0, 0}, // small - if we ever use this we'll have to calculate it
|
|
|
|
{0, 3, 0, -3} // regular
|
|
|
|
},
|
|
|
|
{ // Leopard
|
|
|
|
{0, 4, 0, -4}, // mini
|
|
|
|
{0, 3, 0, -3}, // small
|
|
|
|
{0, 3, 0, -3} // regular
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawRadioButton(CGContextRef cgContext, const HIRect& inBoxRect, PRBool inSelected,
|
2008-05-09 11:12:39 -07:00
|
|
|
PRBool inDisabled, PRInt32 inState)
|
2008-03-04 12:51:54 -08:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
NSRect drawRect = NSMakeRect(inBoxRect.origin.x, inBoxRect.origin.y, inBoxRect.size.width, inBoxRect.size.height);
|
|
|
|
|
2008-05-09 11:12:39 -07:00
|
|
|
[mRadioButtonCell setEnabled:!inDisabled];
|
2008-03-04 12:51:54 -08:00
|
|
|
[mRadioButtonCell setShowsFirstResponder:(inState & NS_EVENT_STATE_FOCUS)];
|
|
|
|
[mRadioButtonCell setState:(inSelected ? NSOnState : NSOffState)];
|
|
|
|
[mRadioButtonCell setHighlighted:((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))];
|
|
|
|
|
|
|
|
// Always use a regular size control because for some reason NSCell doesn't respect other
|
|
|
|
// size choices here. Maybe because of a rendering context/ctm setup it doesn't like?
|
|
|
|
NSControlSize controlSize = NSRegularControlSize;
|
|
|
|
[mRadioButtonCell setControlSize:controlSize];
|
|
|
|
|
|
|
|
DrawCellWithScaling(mRadioButtonCell, cgContext, inBoxRect, controlSize,
|
|
|
|
NATURAL_REGULAR_RADIO_BUTTON_WIDTH, NATURAL_REGULAR_RADIO_BUTTON_HEIGHT,
|
|
|
|
0.0f, 0.0f,
|
|
|
|
radioButtonMargins, PR_TRUE);
|
|
|
|
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
2008-01-13 20:48:33 -08:00
|
|
|
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
// These are the sizes that Gecko needs to request to draw if it wants
|
|
|
|
// to get a standard-sized Aqua rounded bevel button drawn. Note that
|
|
|
|
// the rects that draw these are actually a little bigger.
|
|
|
|
#define NATURAL_MINI_ROUNDED_BUTTON_MIN_WIDTH 18
|
|
|
|
#define NATURAL_MINI_ROUNDED_BUTTON_HEIGHT 16
|
|
|
|
#define NATURAL_SMALL_ROUNDED_BUTTON_MIN_WIDTH 26
|
|
|
|
#define NATURAL_SMALL_ROUNDED_BUTTON_HEIGHT 19
|
|
|
|
#define NATURAL_REGULAR_ROUNDED_BUTTON_MIN_WIDTH 30
|
|
|
|
#define NATURAL_REGULAR_ROUNDED_BUTTON_HEIGHT 22
|
|
|
|
|
|
|
|
// These were calculated by testing all three sizes on the respective operating system.
|
|
|
|
static const float pushButtonMargins[2][3][4] =
|
|
|
|
{
|
|
|
|
{ // Tiger
|
|
|
|
{1, 1, 1, 1}, // mini
|
|
|
|
{5, 1, 5, 1}, // small
|
|
|
|
{6, 0, 6, 2} // regular
|
|
|
|
},
|
|
|
|
{ // Leopard
|
|
|
|
{0, 0, 0, 0}, // mini
|
|
|
|
{4, 0, 4, 1}, // small
|
|
|
|
{5, 0, 5, 2} // regular
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
// The height at which we start doing square buttons instead of rounded buttons
|
|
|
|
// Rounded buttons look bad if drawn at a height greater than 26, so at that point
|
|
|
|
// we switch over to doing square buttons which looks fine at any size.
|
|
|
|
#define DO_SQUARE_BUTTON_HEIGHT 26
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect, PRBool inIsDefault,
|
2008-05-09 11:12:39 -07:00
|
|
|
PRBool inDisabled, PRInt32 inState)
|
2007-12-23 11:22:47 -08:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
NSRect drawRect = NSMakeRect(inBoxRect.origin.x, inBoxRect.origin.y, inBoxRect.size.width, inBoxRect.size.height);
|
|
|
|
|
|
|
|
[mPushButtonCell setEnabled:!inDisabled];
|
2008-05-09 11:12:39 -07:00
|
|
|
[mPushButtonCell setHighlighted:((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER) || (inIsDefault && !inDisabled))];
|
|
|
|
[mPushButtonCell setShowsFirstResponder:(inState & NS_EVENT_STATE_FOCUS)];
|
2008-01-08 18:52:36 -08:00
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
CGAffineTransform savedCTM = CGContextGetCTM(cgContext);
|
2007-12-23 11:22:47 -08:00
|
|
|
|
|
|
|
// This flips the image in place and is necessary to work around a bug in the way
|
|
|
|
// NSButtonCell draws buttons.
|
|
|
|
CGContextScaleCTM(cgContext, 1.0f, -1.0f);
|
|
|
|
CGContextTranslateCTM(cgContext, 0.0f, -(2.0 * drawRect.origin.y + drawRect.size.height));
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
// Set up the graphics context we've been asked to draw to.
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
// If the button is tall enough, draw the square button style so that buttons with
|
|
|
|
// non-standard content look good. Otherwise draw normal rounded aqua buttons.
|
2008-03-04 12:51:54 -08:00
|
|
|
if (drawRect.size.height > DO_SQUARE_BUTTON_HEIGHT) {
|
|
|
|
NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
|
|
|
|
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]];
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
[mPushButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
|
|
|
|
[mPushButtonCell drawWithFrame:drawRect inView:[NSView focusView]];
|
2008-03-04 12:51:54 -08:00
|
|
|
|
|
|
|
[NSGraphicsContext setCurrentContext:savedContext];
|
|
|
|
} else {
|
2007-12-23 11:22:47 -08:00
|
|
|
[mPushButtonCell setBezelStyle:NSRoundedBezelStyle];
|
|
|
|
|
|
|
|
// Figure out what size cell control we're going to draw and grab its
|
|
|
|
// natural height and min width.
|
|
|
|
NSControlSize controlSize = NSRegularControlSize;
|
|
|
|
float naturalHeight = NATURAL_REGULAR_ROUNDED_BUTTON_HEIGHT;
|
|
|
|
float minWidth = NATURAL_REGULAR_ROUNDED_BUTTON_MIN_WIDTH;
|
|
|
|
if (drawRect.size.height <= NATURAL_MINI_ROUNDED_BUTTON_HEIGHT &&
|
|
|
|
drawRect.size.width >= NATURAL_MINI_ROUNDED_BUTTON_MIN_WIDTH) {
|
|
|
|
controlSize = NSMiniControlSize;
|
|
|
|
naturalHeight = NATURAL_MINI_ROUNDED_BUTTON_HEIGHT;
|
|
|
|
minWidth = NATURAL_MINI_ROUNDED_BUTTON_MIN_WIDTH;
|
|
|
|
}
|
|
|
|
else if (drawRect.size.height <= NATURAL_SMALL_ROUNDED_BUTTON_HEIGHT &&
|
|
|
|
drawRect.size.width >= NATURAL_SMALL_ROUNDED_BUTTON_MIN_WIDTH) {
|
|
|
|
controlSize = NSSmallControlSize;
|
|
|
|
naturalHeight = NATURAL_SMALL_ROUNDED_BUTTON_HEIGHT;
|
|
|
|
minWidth = NATURAL_SMALL_ROUNDED_BUTTON_MIN_WIDTH;
|
|
|
|
}
|
|
|
|
[mPushButtonCell setControlSize:controlSize];
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
DrawCellWithScaling(mPushButtonCell, cgContext, inBoxRect, controlSize,
|
|
|
|
0.0f, naturalHeight,
|
|
|
|
minWidth, 0.0f,
|
|
|
|
pushButtonMargins, PR_FALSE);
|
2007-12-23 11:22:47 -08:00
|
|
|
}
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
CGContextSetCTM (cgContext, savedCTM);
|
2007-12-23 11:22:47 -08:00
|
|
|
|
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
2008-03-14 12:29:32 -07:00
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
|
2007-12-23 11:22:47 -08:00
|
|
|
CGContextFillRect(cgContext, inBoxRect);
|
|
|
|
#endif
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-12-23 11:22:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
|
|
|
|
const HIRect& inBoxRect, PRBool inIsDefault, PRBool inDisabled,
|
|
|
|
ThemeButtonValue inValue, ThemeButtonAdornment inAdornment,
|
2008-05-09 11:12:39 -07:00
|
|
|
PRInt32 inState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-05-02 16:47:53 -07:00
|
|
|
HIThemeButtonDrawInfo bdi;
|
2007-03-22 10:30:00 -07:00
|
|
|
bdi.version = 0;
|
|
|
|
bdi.kind = inKind;
|
|
|
|
bdi.value = inValue;
|
|
|
|
bdi.adornment = inAdornment;
|
2007-05-02 16:47:53 -07:00
|
|
|
|
2008-05-09 11:12:39 -07:00
|
|
|
if (inDisabled)
|
2007-03-22 10:30:00 -07:00
|
|
|
bdi.state = kThemeStateUnavailable;
|
2008-05-09 11:12:39 -07:00
|
|
|
else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
|
2007-03-22 10:30:00 -07:00
|
|
|
bdi.state = kThemeStatePressed;
|
2008-05-09 11:12:39 -07:00
|
|
|
else
|
|
|
|
bdi.state = (inKind == kThemeArrowButton) ? kThemeStateUnavailable : kThemeStateActive;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (inState & NS_EVENT_STATE_FOCUS)
|
|
|
|
bdi.adornment |= kThemeAdornmentFocus;
|
|
|
|
|
|
|
|
if (inIsDefault && !inDisabled)
|
|
|
|
bdi.adornment |= kThemeAdornmentDefault;
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
HIRect drawFrame = inBoxRect;
|
2008-03-19 16:01:34 -07:00
|
|
|
PRBool needsScaling = PR_FALSE;
|
|
|
|
int drawWidth = 0, drawHeight = 0;
|
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
if (inKind == kThemePopupButton) {
|
2008-03-19 16:01:34 -07:00
|
|
|
/* popup buttons draw outside their frame by 1 pixel on each side and
|
|
|
|
* two on the bottom but of the bottom two pixels one is a 'shadow'
|
|
|
|
* and not the frame itself. That extra pixel should be handled
|
|
|
|
* by GetWidgetOverflow, but we already extend each widget's overflow
|
|
|
|
* by 4px to handle a potential focus ring.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (nsToolkit::OnLeopardOrLater()) {
|
|
|
|
/* Leopard will happily scale up for buttons that are sized 20px or higher,
|
|
|
|
* drawing 1px below the actual requested area. (So 20px == 21px.)
|
|
|
|
* but anything below that will be clamped:
|
|
|
|
* requested: 20 actual: 21 (handled above)
|
|
|
|
* requested: 19 actual: 18 <- note that there is no way to draw a dropdown that's exactly 20 px in size
|
|
|
|
* requested: 18 actual: 18
|
|
|
|
* requested: 17 actual: 18
|
|
|
|
* requested: 16 actual: 15 (min size)
|
|
|
|
* For those, draw to a buffer and scale
|
|
|
|
*/
|
|
|
|
if (drawFrame.size.height != 18 && drawFrame.size.height != 15) {
|
|
|
|
if (drawFrame.size.height > 20) {
|
|
|
|
drawFrame.size.width -= 2;
|
|
|
|
drawFrame.origin.x += 1;
|
|
|
|
drawFrame.size.height -= 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// pick which native height to use for the small scale
|
|
|
|
float nativeHeight = 15.0f;
|
|
|
|
if (drawFrame.size.height > 16)
|
|
|
|
nativeHeight = 18.0f;
|
|
|
|
|
|
|
|
drawWidth = (int) drawFrame.size.width;
|
|
|
|
drawHeight = (int) nativeHeight;
|
|
|
|
|
|
|
|
needsScaling = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// leave things alone on Tiger
|
|
|
|
drawFrame.size.height -= 1;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-05-02 16:47:53 -07:00
|
|
|
|
2008-03-19 16:01:34 -07:00
|
|
|
if (!needsScaling) {
|
|
|
|
HIThemeDrawButton(&drawFrame, &bdi, cgContext, kHIThemeOrientationNormal, NULL);
|
|
|
|
} else {
|
|
|
|
int w = drawWidth + MAX_FOCUS_RING_WIDTH*2;
|
|
|
|
int h = drawHeight + MAX_FOCUS_RING_WIDTH*2;
|
|
|
|
|
|
|
|
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
|
|
|
|
CGContextRef ctx = CGBitmapContextCreate(NULL, w, h, 8, w * 4,
|
|
|
|
rgb, kCGImageAlphaPremultipliedFirst);
|
|
|
|
CGColorSpaceRelease(rgb);
|
|
|
|
|
|
|
|
// Flip the context
|
|
|
|
CGContextTranslateCTM(ctx, 0.0f, h);
|
|
|
|
CGContextScaleCTM(ctx, 1.0f, -1.0f);
|
|
|
|
|
|
|
|
// then draw the button (offset by the focus ring size
|
|
|
|
CGRect tmpFrame = CGRectMake(MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH, drawWidth, drawHeight);
|
|
|
|
HIThemeDrawButton(&tmpFrame, &bdi, ctx, kHIThemeOrientationNormal, NULL);
|
|
|
|
|
|
|
|
CGImageRef img = CGBitmapContextCreateImage(ctx);
|
|
|
|
CGRect imgRect = CGRectMake(drawFrame.origin.x - MAX_FOCUS_RING_WIDTH,
|
|
|
|
drawFrame.origin.y - MAX_FOCUS_RING_WIDTH,
|
|
|
|
drawFrame.size.width + MAX_FOCUS_RING_WIDTH * 2.0,
|
|
|
|
drawFrame.size.height + MAX_FOCUS_RING_WIDTH * 2.0);
|
|
|
|
|
|
|
|
// And then flip the main context here so that the image gets drawn right-side up
|
|
|
|
CGAffineTransform ctm = CGContextGetCTM (cgContext);
|
|
|
|
|
|
|
|
CGContextTranslateCTM (cgContext, imgRect.origin.x, imgRect.origin.y + imgRect.size.height);
|
|
|
|
CGContextScaleCTM (cgContext, 1.0, -1.0);
|
|
|
|
|
|
|
|
imgRect.origin.x = imgRect.origin.y = 0.0f;
|
|
|
|
|
|
|
|
// See comment about why we don't scale MAX_FOCUS_RING in DrawCellWithScaling
|
|
|
|
CGContextDrawImage(cgContext, imgRect, img);
|
|
|
|
|
|
|
|
CGContextSetCTM (cgContext, ctm);
|
|
|
|
|
|
|
|
CGImageRelease(img);
|
|
|
|
CGContextRelease(ctx);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
2008-03-19 16:01:34 -07:00
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
|
2007-03-22 10:30:00 -07:00
|
|
|
CGContextFillRect(cgContext, inBoxRect);
|
|
|
|
#endif
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind,
|
|
|
|
const HIRect& inBoxRect, PRBool inDisabled,
|
2007-08-27 21:05:12 -07:00
|
|
|
ThemeDrawState inDrawState,
|
|
|
|
ThemeButtonAdornment inAdornment,
|
2008-05-09 11:12:39 -07:00
|
|
|
PRInt32 inState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
HIThemeButtonDrawInfo bdi;
|
|
|
|
bdi.version = 0;
|
|
|
|
bdi.kind = inKind;
|
|
|
|
bdi.state = inDrawState;
|
|
|
|
bdi.value = kThemeButtonOff;
|
|
|
|
bdi.adornment = inAdornment;
|
|
|
|
|
|
|
|
if (inDisabled)
|
|
|
|
bdi.state = kThemeStateUnavailable;
|
|
|
|
|
|
|
|
HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind,
|
2008-05-09 11:12:39 -07:00
|
|
|
const HIRect& inBoxRect, PRBool inIsDisabled, PRInt32 inState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
HIThemeFrameDrawInfo fdi;
|
|
|
|
fdi.version = 0;
|
|
|
|
fdi.kind = inKind;
|
|
|
|
fdi.state = inIsDisabled ? kThemeStateUnavailable : kThemeStateActive;
|
2008-02-07 03:39:04 -08:00
|
|
|
// for some reason focus rings on listboxes draw incorrectly
|
|
|
|
if (inKind == kHIThemeFrameListBox)
|
|
|
|
fdi.isFocused = 0;
|
|
|
|
else
|
|
|
|
fdi.isFocused = (inState & NS_EVENT_STATE_FOCUS) != 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// 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);
|
2007-08-28 00:21:04 -07:00
|
|
|
drawRect.origin.x += frameOutset;
|
|
|
|
drawRect.origin.y += frameOutset;
|
|
|
|
drawRect.size.width -= frameOutset * 2;
|
|
|
|
drawRect.size.height -= frameOutset * 2;
|
|
|
|
}
|
|
|
|
else if (inKind == kHIThemeFrameListBox) {
|
|
|
|
SInt32 frameOutset = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset);
|
2007-03-22 10:30:00 -07:00
|
|
|
drawRect.origin.x += frameOutset;
|
|
|
|
drawRect.origin.y += frameOutset;
|
|
|
|
drawRect.size.width -= frameOutset * 2;
|
|
|
|
drawRect.size.height -= frameOutset * 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
2008-03-14 12:29:32 -07:00
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
|
2007-03-22 10:30:00 -07:00
|
|
|
CGContextFillRect(cgContext, inBoxRect);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
HIThemeDrawFrame(&drawRect, &fdi, cgContext, HITHEME_ORIENTATION);
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
2008-05-09 11:12:39 -07:00
|
|
|
nsNativeThemeCocoa::DrawProgress(CGContextRef cgContext,
|
|
|
|
const HIRect& inBoxRect, PRBool inIsIndeterminate,
|
|
|
|
PRBool inIsHorizontal, PRInt32 inValue)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
HIThemeTrackDrawInfo tdi;
|
2008-04-07 15:56:43 -07:00
|
|
|
|
|
|
|
PRInt32 stepsPerSecond = inIsIndeterminate ? 60 : 30;
|
|
|
|
PRInt32 milliSecondsPerStep = 1000 / stepsPerSecond;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
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;
|
2008-05-09 11:12:39 -07:00
|
|
|
tdi.enableState = kThemeTrackActive;
|
2008-04-07 15:56:43 -07:00
|
|
|
tdi.trackInfo.progress.phase = PR_IntervalToMilliseconds(PR_IntervalNow()) /
|
|
|
|
milliSecondsPerStep % 16;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
HIThemeDrawTrack(&tdi, NULL, cgContext, HITHEME_ORIENTATION);
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2008-05-09 11:12:39 -07:00
|
|
|
nsNativeThemeCocoa::DrawTabPanel(CGContextRef cgContext, const HIRect& inBoxRect)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
HIThemeTabPaneDrawInfo tpdi;
|
|
|
|
|
|
|
|
tpdi.version = 0;
|
2008-05-09 11:12:39 -07:00
|
|
|
tpdi.state = kThemeStateActive;
|
2007-03-22 10:30:00 -07:00
|
|
|
tpdi.direction = kThemeTabNorth;
|
|
|
|
tpdi.size = kHIThemeTabSizeNormal;
|
|
|
|
|
|
|
|
HIThemeDrawTabPane(&inBoxRect, &tpdi, cgContext, HITHEME_ORIENTATION);
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawScale(CGContextRef cgContext, const HIRect& inBoxRect,
|
|
|
|
PRBool inIsDisabled, PRInt32 inState,
|
2007-04-09 15:39:57 -07:00
|
|
|
PRBool inIsVertical, PRBool inIsReverse,
|
2008-05-09 11:12:39 -07:00
|
|
|
PRInt32 inCurrentValue,
|
|
|
|
PRInt32 inMinValue, PRInt32 inMaxValue)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-03-22 10:30:00 -07: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;
|
2007-04-09 15:39:57 -07:00
|
|
|
if (inIsReverse)
|
|
|
|
tdi.attributes |= kThemeTrackRightToLeft;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (inState & NS_EVENT_STATE_FOCUS)
|
|
|
|
tdi.attributes |= kThemeTrackHasFocus;
|
2008-05-09 11:12:39 -07:00
|
|
|
tdi.enableState = inIsDisabled ? kThemeTrackDisabled : kThemeTrackActive;
|
2007-03-22 10:30:00 -07:00
|
|
|
tdi.trackInfo.slider.thumbDir = kThemeThumbPlain;
|
|
|
|
tdi.trackInfo.slider.pressState = 0;
|
|
|
|
|
|
|
|
HIThemeDrawTrack(&tdi, NULL, cgContext, HITHEME_ORIENTATION);
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawTab(CGContextRef cgContext, const HIRect& inBoxRect,
|
|
|
|
PRBool inIsDisabled, PRBool inIsFrontmost,
|
|
|
|
PRBool inIsHorizontal, PRBool inTabBottom,
|
2008-05-09 11:12:39 -07:00
|
|
|
PRInt32 inState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
HIThemeTabDrawInfo tdi;
|
|
|
|
|
|
|
|
tdi.version = 0;
|
|
|
|
|
|
|
|
if (inIsFrontmost) {
|
|
|
|
if (inIsDisabled)
|
|
|
|
tdi.style = kThemeTabFrontUnavailable;
|
|
|
|
else
|
2008-05-09 11:12:39 -07:00
|
|
|
tdi.style = kThemeTabFront;
|
2007-03-22 10:30:00 -07:00
|
|
|
} else {
|
|
|
|
if (inIsDisabled)
|
|
|
|
tdi.style = kThemeTabNonFrontUnavailable;
|
|
|
|
else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
|
|
|
|
tdi.style = kThemeTabNonFrontPressed;
|
|
|
|
else
|
2008-05-09 11:12:39 -07:00
|
|
|
tdi.style = kThemeTabNonFront;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// don't yet support vertical tabs
|
|
|
|
tdi.direction = inTabBottom ? kThemeTabSouth : kThemeTabNorth;
|
|
|
|
tdi.size = kHIThemeTabSizeNormal;
|
|
|
|
tdi.adornment = kThemeAdornmentNone;
|
|
|
|
|
|
|
|
HIThemeDrawTab(&inBoxRect, &tdi, cgContext, HITHEME_ORIENTATION, NULL);
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
static inline UInt8
|
2007-04-10 17:25:11 -07:00
|
|
|
ConvertToPressState(PRInt32 aButtonState, UInt8 aPressState)
|
|
|
|
{
|
|
|
|
// If the button is pressed, return the press state passed in. Otherwise, return 0.
|
|
|
|
return ((aButtonState & NS_EVENT_STATE_ACTIVE) && (aButtonState & NS_EVENT_STATE_HOVER)) ? aPressState : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::GetScrollbarPressStates(nsIFrame *aFrame, PRInt32 aButtonStates[])
|
|
|
|
{
|
|
|
|
static nsIContent::AttrValuesArray attributeValues[] = {
|
|
|
|
&nsWidgetAtoms::scrollbarUpTop,
|
|
|
|
&nsWidgetAtoms::scrollbarDownTop,
|
|
|
|
&nsWidgetAtoms::scrollbarUpBottom,
|
|
|
|
&nsWidgetAtoms::scrollbarDownBottom,
|
|
|
|
nsnull
|
|
|
|
};
|
|
|
|
|
|
|
|
// Get the state of any scrollbar buttons in our child frames
|
|
|
|
for (nsIFrame *childFrame = aFrame->GetFirstChild(nsnull);
|
|
|
|
childFrame;
|
|
|
|
childFrame = childFrame->GetNextSibling()) {
|
|
|
|
|
|
|
|
nsIContent *childContent = childFrame->GetContent();
|
|
|
|
if (!childContent) continue;
|
|
|
|
PRInt32 attrIndex = childContent->FindAttrValueIn(kNameSpaceID_None, nsWidgetAtoms::sbattr,
|
|
|
|
attributeValues, eCaseMatters);
|
|
|
|
if (attrIndex < 0) continue;
|
|
|
|
|
|
|
|
PRInt32 currentState = GetContentState(childFrame, NS_THEME_BUTTON);
|
|
|
|
aButtonStates[attrIndex] = currentState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-03 13:05:15 -07:00
|
|
|
// Both of the following sets of numbers were derived by loading the testcase in
|
|
|
|
// bmo bug 380185 in Safari and observing its behavior for various heights of scrollbar.
|
2007-07-03 11:49:44 -07:00
|
|
|
// These magic numbers are the minimum sizes we can draw a scrollbar and still
|
|
|
|
// have room for everything to display, including the thumb
|
|
|
|
#define MIN_SCROLLBAR_SIZE_WITH_THUMB 61
|
|
|
|
#define MIN_SMALL_SCROLLBAR_SIZE_WITH_THUMB 49
|
|
|
|
// And these are the minimum sizes if we don't draw the thumb
|
|
|
|
#define MIN_SCROLLBAR_SIZE 56
|
|
|
|
#define MIN_SMALL_SCROLLBAR_SIZE 46
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::GetScrollbarDrawInfo(HIThemeTrackDrawInfo& aTdi, nsIFrame *aFrame,
|
|
|
|
const HIRect& aRect, PRBool aShouldGetButtonStates)
|
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-03-26 22:36:20 -07:00
|
|
|
PRInt32 curpos = CheckIntAttr(aFrame, nsWidgetAtoms::curpos, 0);
|
|
|
|
PRInt32 minpos = CheckIntAttr(aFrame, nsWidgetAtoms::minpos, 0);
|
|
|
|
PRInt32 maxpos = CheckIntAttr(aFrame, nsWidgetAtoms::maxpos, 100);
|
|
|
|
PRInt32 thumbSize = CheckIntAttr(aFrame, nsWidgetAtoms::pageincrement, 10);
|
2007-04-10 17:25:11 -07:00
|
|
|
|
|
|
|
PRBool isHorizontal = aFrame->GetContent()->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::orient,
|
|
|
|
nsWidgetAtoms::horizontal, eCaseMatters);
|
|
|
|
PRBool isSmall = aFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL;
|
|
|
|
|
|
|
|
aTdi.version = 0;
|
|
|
|
aTdi.kind = isSmall ? kThemeSmallScrollBar : kThemeMediumScrollBar;
|
|
|
|
aTdi.bounds = aRect;
|
|
|
|
aTdi.min = minpos;
|
|
|
|
aTdi.max = maxpos;
|
|
|
|
aTdi.value = curpos;
|
2007-07-03 11:49:44 -07:00
|
|
|
aTdi.attributes = 0;
|
2007-10-05 14:01:42 -07:00
|
|
|
aTdi.enableState = kThemeTrackActive;
|
2007-04-10 17:25:11 -07:00
|
|
|
if (isHorizontal)
|
|
|
|
aTdi.attributes |= kThemeTrackHorizontal;
|
|
|
|
|
2008-03-26 22:36:20 -07:00
|
|
|
aTdi.trackInfo.scrollbar.viewsize = (SInt32)thumbSize;
|
2007-04-10 17:25:11 -07:00
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
/* Only display features if we have enough room for them.
|
|
|
|
* Gecko still maintains the scrollbar info; this is just a visual issue (bug 380185).
|
|
|
|
*/
|
2008-03-26 22:36:20 -07:00
|
|
|
PRInt32 longSideLength = (PRInt32)(isHorizontal ? (aRect.size.width) : (aRect.size.height));
|
2007-07-03 13:05:15 -07:00
|
|
|
if (longSideLength >= (isSmall ? MIN_SMALL_SCROLLBAR_SIZE_WITH_THUMB : MIN_SCROLLBAR_SIZE_WITH_THUMB)) {
|
2007-07-03 11:49:44 -07:00
|
|
|
aTdi.attributes |= kThemeTrackShowThumb;
|
|
|
|
}
|
2007-07-03 13:05:15 -07:00
|
|
|
else if (longSideLength < (isSmall ? MIN_SMALL_SCROLLBAR_SIZE : MIN_SCROLLBAR_SIZE)) {
|
2007-07-03 11:49:44 -07:00
|
|
|
aTdi.enableState = kThemeTrackNothingToScroll;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
// Only go get these scrollbar button states if we need it. For example, there's no reaon to look up scrollbar button
|
|
|
|
// states when we're only creating a TrackDrawInfo to determine the size of the thumb.
|
|
|
|
if (aShouldGetButtonStates) {
|
|
|
|
PRInt32 buttonStates[] = {0, 0, 0, 0};
|
|
|
|
GetScrollbarPressStates(aFrame, buttonStates);
|
|
|
|
ThemeScrollBarArrowStyle arrowStyle;
|
|
|
|
::GetThemeScrollBarArrowStyle(&arrowStyle);
|
|
|
|
// If all four buttons are visible
|
|
|
|
if (arrowStyle == kThemeScrollBarArrowsBoth) {
|
|
|
|
aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) |
|
|
|
|
ConvertToPressState(buttonStates[1], kThemeTopInsideArrowPressed) |
|
|
|
|
ConvertToPressState(buttonStates[2], kThemeBottomInsideArrowPressed) |
|
|
|
|
ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed);
|
|
|
|
} else {
|
|
|
|
// It seems that unless all four buttons are showing, kThemeTopOutsideArrowPressed is the correct constant for
|
|
|
|
// the up scrollbar button.
|
|
|
|
aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) |
|
2008-04-08 23:38:01 -07:00
|
|
|
ConvertToPressState(buttonStates[1], kThemeBottomOutsideArrowPressed) |
|
2007-04-10 17:25:11 -07:00
|
|
|
ConvertToPressState(buttonStates[2], kThemeTopOutsideArrowPressed) |
|
|
|
|
ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed);
|
|
|
|
}
|
|
|
|
}
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-04-10 17:25:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawScrollbar(CGContextRef aCGContext, const HIRect& aBoxRect, nsIFrame *aFrame)
|
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
// HIThemeDrawTrack is buggy with rotations and scaling
|
|
|
|
CGAffineTransform savedCTM = CGContextGetCTM(aCGContext);
|
|
|
|
PRBool drawDirect;
|
|
|
|
HIRect drawRect = aBoxRect;
|
|
|
|
|
|
|
|
if (savedCTM.a == 1.0f && savedCTM.b == 0.0f &&
|
|
|
|
savedCTM.c == 0.0f && (savedCTM.d == 1.0f || savedCTM.d == -1.0f))
|
|
|
|
{
|
|
|
|
drawDirect = TRUE;
|
|
|
|
} else {
|
|
|
|
drawRect.origin.x = drawRect.origin.y = 0.0f;
|
|
|
|
drawDirect = FALSE;
|
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
HIThemeTrackDrawInfo tdi;
|
2007-10-05 14:01:42 -07:00
|
|
|
GetScrollbarDrawInfo(tdi, aFrame, drawRect, PR_TRUE); //True means we want the press states
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
if (drawDirect) {
|
2007-10-05 14:01:42 -07:00
|
|
|
::HIThemeDrawTrack(&tdi, NULL, aCGContext, HITHEME_ORIENTATION);
|
2008-03-04 12:51:54 -08:00
|
|
|
} else {
|
|
|
|
// Note that NSScroller can draw transformed just fine, but HITheme can't.
|
|
|
|
// However, we can't make NSScroller's parts light up easily (depressed buttons, etc.)
|
|
|
|
// This is very frustrating.
|
|
|
|
|
|
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
|
|
CGContextRef bitmapctx = CGBitmapContextCreate(NULL,
|
|
|
|
(size_t) ceil(drawRect.size.width),
|
|
|
|
(size_t) ceil(drawRect.size.height),
|
|
|
|
8,
|
|
|
|
(size_t) ceil(drawRect.size.width) * 4,
|
|
|
|
colorSpace,
|
|
|
|
kCGImageAlphaPremultipliedFirst);
|
|
|
|
CGColorSpaceRelease(colorSpace);
|
|
|
|
|
|
|
|
// HITheme always wants to draw into a flipped context, or things
|
|
|
|
// get confused.
|
|
|
|
CGContextTranslateCTM(bitmapctx, 0.0f, aBoxRect.size.height);
|
|
|
|
CGContextScaleCTM(bitmapctx, 1.0f, -1.0f);
|
|
|
|
|
|
|
|
HIThemeDrawTrack(&tdi, NULL, bitmapctx, HITHEME_ORIENTATION);
|
|
|
|
|
|
|
|
CGImageRef bitmap = CGBitmapContextCreateImage(bitmapctx);
|
|
|
|
|
|
|
|
CGAffineTransform ctm = CGContextGetCTM(aCGContext);
|
|
|
|
|
|
|
|
// We need to unflip, so that we can do a DrawImage without getting a flipped image.
|
|
|
|
CGContextTranslateCTM(aCGContext, 0.0f, aBoxRect.size.height);
|
2007-10-05 14:01:42 -07:00
|
|
|
CGContextScaleCTM(aCGContext, 1.0f, -1.0f);
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
CGContextDrawImage(aCGContext, aBoxRect, bitmap);
|
|
|
|
|
|
|
|
CGContextSetCTM(aCGContext, ctm);
|
2007-10-05 14:01:42 -07:00
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
CGImageRelease(bitmap);
|
|
|
|
CGContextRelease(bitmapctx);
|
2007-10-05 14:01:42 -07:00
|
|
|
}
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-04-10 17:25:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsIFrame*
|
|
|
|
nsNativeThemeCocoa::GetParentScrollbarFrame(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
// Walk our parents to find a scrollbar frame
|
|
|
|
nsIFrame *scrollbarFrame = aFrame;
|
|
|
|
do {
|
|
|
|
if (scrollbarFrame->GetType() == nsWidgetAtoms::scrollbarFrame) break;
|
|
|
|
} while ((scrollbarFrame = scrollbarFrame->GetParent()));
|
|
|
|
|
|
|
|
// We return null if we can't find a parent scrollbar frame
|
|
|
|
return scrollbarFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType, const nsRect& aRect,
|
|
|
|
const nsRect& aClipRect)
|
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// setup to draw into the correct port
|
|
|
|
nsCOMPtr<nsIDeviceContext> dctx;
|
|
|
|
aContext->GetDeviceContext(*getter_AddRefs(dctx));
|
|
|
|
PRInt32 p2a = dctx->AppUnitsPerDevPixel();
|
|
|
|
|
2008-02-20 03:33:27 -08:00
|
|
|
gfxRect nativeClipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
|
|
|
|
gfxRect nativeWidgetRect(aRect.x, aRect.y, aRect.width, aRect.height);
|
|
|
|
nativeWidgetRect.ScaleInverse(gfxFloat(p2a));
|
|
|
|
nativeClipRect.ScaleInverse(gfxFloat(p2a));
|
|
|
|
|
2007-12-18 15:01:15 -08:00
|
|
|
nsRefPtr<gfxContext> thebesCtx = aContext->ThebesContext();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!thebesCtx)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2008-02-20 03:33:27 -08:00
|
|
|
gfxQuartzNativeDrawing nativeDrawing(thebesCtx, nativeClipRect);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-02-20 03:33:27 -08:00
|
|
|
CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
|
2007-07-18 07:40:19 -07:00
|
|
|
if (cgContext == nsnull) {
|
2008-01-25 16:26:48 -08:00
|
|
|
// The Quartz surface handles 0x0 surfaces by internally
|
|
|
|
// making all operations no-ops; there's no cgcontext created for them.
|
|
|
|
// Unfortunately, this means that callers that want to render
|
|
|
|
// directly to the CGContext need to be aware of this quirk.
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (1 /*aWidgetType == NS_THEME_TEXTFIELD*/) {
|
|
|
|
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-09-28 23:12:39 -07:00
|
|
|
fprintf(stderr, "Cairo matrix: [%f %f %f %f %f %f]\n",
|
|
|
|
mat.xx, mat.yx, mat.xy, mat.yy, mat.x0, mat.y0);
|
2007-03-22 10:30:00 -07: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);
|
|
|
|
CGAffineTransform mm = CGContextGetCTM(cgContext);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
CGRect macRect = CGRectMake(NSAppUnitsToIntPixels(aRect.x, p2a),
|
|
|
|
NSAppUnitsToIntPixels(aRect.y, p2a),
|
|
|
|
NSAppUnitsToIntPixels(aRect.width, p2a),
|
|
|
|
NSAppUnitsToIntPixels(aRect.height, p2a));
|
2007-08-07 12:36:40 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#if 0
|
|
|
|
fprintf(stderr, " --> macRect %f %f %f %f\n",
|
|
|
|
macRect.origin.x, macRect.origin.y, macRect.size.width, macRect.size.height);
|
|
|
|
CGRect bounds = CGContextGetClipBoundingBox(cgContext);
|
|
|
|
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);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PRInt32 eventState = GetContentState(aFrame, aWidgetType);
|
|
|
|
|
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_DIALOG: {
|
2007-11-13 13:00:24 -08:00
|
|
|
HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION);
|
2007-03-22 10:30:00 -07:00
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_MENUPOPUP: {
|
|
|
|
HIThemeMenuDrawInfo mdi = {
|
|
|
|
version: 0,
|
|
|
|
menuType: IsDisabled(aFrame) ? kThemeMenuTypeInactive : kThemeMenuTypePopUp
|
|
|
|
};
|
|
|
|
|
|
|
|
HIThemeDrawMenuBackground(&macRect, &mdi, cgContext, HITHEME_ORIENTATION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_MENUITEM: {
|
|
|
|
// maybe use kThemeMenuItemHierBackground or PopUpBackground instead of just Plain?
|
|
|
|
HIThemeMenuItemDrawInfo drawInfo = {
|
|
|
|
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
|
|
|
|
HIRect ignored;
|
|
|
|
HIThemeDrawMenuItem(&macRect, &macRect, &drawInfo, cgContext, HITHEME_ORIENTATION, &ignored);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-02-24 05:41:22 -08:00
|
|
|
case NS_THEME_MENUSEPARATOR: {
|
|
|
|
ThemeMenuState menuState;
|
|
|
|
if (IsDisabled(aFrame)) {
|
|
|
|
menuState = kThemeMenuDisabled;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
menuState = CheckBooleanAttr(aFrame, nsWidgetAtoms::mozmenuactive) ?
|
|
|
|
kThemeMenuSelected : kThemeMenuActive;
|
|
|
|
}
|
|
|
|
|
|
|
|
HIThemeMenuItemDrawInfo midi = { 0, kThemeMenuItemPlain, menuState };
|
|
|
|
HIThemeDrawMenuSeparator(&macRect, &macRect, &midi, cgContext, HITHEME_ORIENTATION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_TOOLTIP:
|
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 0.78, 1.0);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_CHECKBOX:
|
2008-05-09 11:12:39 -07:00
|
|
|
DrawCheckbox(cgContext, kThemeCheckBox, macRect, IsChecked(aFrame), IsDisabled(aFrame), eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_CHECKBOX_SMALL:
|
2008-05-09 11:12:39 -07:00
|
|
|
DrawCheckbox(cgContext, kThemeSmallCheckBox, macRect, IsChecked(aFrame), IsDisabled(aFrame), eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
case NS_THEME_RADIO_SMALL:
|
2008-05-09 11:12:39 -07:00
|
|
|
DrawRadioButton(cgContext, macRect, IsSelected(aFrame), IsDisabled(aFrame), eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_BUTTON:
|
2008-05-09 11:12:39 -07:00
|
|
|
DrawPushButton(cgContext, macRect, IsDefaultButton(aFrame), IsDisabled(aFrame), eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_BUTTON_BEVEL:
|
|
|
|
DrawButton(cgContext, kThemeMediumBevelButton, macRect,
|
|
|
|
IsDefaultButton(aFrame), IsDisabled(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
kThemeButtonOff, kThemeAdornmentNone, eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
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(cgContext, kThemeIncDecButton, macRect, IsDisabled(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
state, kThemeAdornmentNone, eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TOOLBAR_BUTTON:
|
|
|
|
DrawButton(cgContext, kThemePushButton, macRect,
|
|
|
|
IsDefaultButton(aFrame), IsDisabled(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
kThemeButtonOn, kThemeAdornmentNone, eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TOOLBAR_SEPARATOR: {
|
|
|
|
HIThemeSeparatorDrawInfo sdi = { 0, kThemeStateActive };
|
|
|
|
HIThemeDrawSeparator(&macRect, &sdi, cgContext, HITHEME_ORIENTATION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TOOLBAR:
|
|
|
|
case NS_THEME_TOOLBOX:
|
|
|
|
case NS_THEME_STATUSBAR: {
|
|
|
|
HIThemeHeaderDrawInfo hdi = { 0, kThemeStateActive, kHIThemeHeaderKindWindow };
|
|
|
|
HIThemeDrawHeader(&macRect, &hdi, cgContext, HITHEME_ORIENTATION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN:
|
|
|
|
DrawButton(cgContext, kThemePopupButton, macRect,
|
|
|
|
IsDefaultButton(aFrame), IsDisabled(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
kThemeButtonOn, kThemeAdornmentNone, eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
2008-05-09 11:12:39 -07:00
|
|
|
DrawButton (cgContext, kThemeArrowButton, macRect, PR_FALSE,
|
|
|
|
IsDisabled(aFrame), kThemeButtonOn,
|
|
|
|
kThemeAdornmentArrowDownArrow, eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
2008-03-13 13:24:29 -07:00
|
|
|
case NS_THEME_GROUPBOX: {
|
|
|
|
HIThemeGroupBoxDrawInfo gdi = { 0, kThemeStateActive, kHIThemeGroupBoxKindPrimary };
|
|
|
|
HIThemeDrawGroupBox(&macRect, &gdi, cgContext, HITHEME_ORIENTATION);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_TEXTFIELD:
|
|
|
|
// HIThemeSetFill is not available on 10.3
|
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
2008-02-07 13:54:24 -08:00
|
|
|
|
|
|
|
// XUL textboxes set the native appearance on the containing box, while
|
|
|
|
// concrete focus is set on the html:input element within it. We can
|
|
|
|
// though, check the focused attribute of xul textboxes in this case.
|
|
|
|
if (aFrame->GetContent()->IsNodeOfType(nsINode::eXUL) &&
|
|
|
|
IsFocused(aFrame)) {
|
|
|
|
eventState |= NS_EVENT_STATE_FOCUS;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
DrawFrame(cgContext, kHIThemeFrameTextFieldSquare,
|
|
|
|
macRect, (IsDisabled(aFrame) || IsReadOnly(aFrame)), eventState);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_PROGRESSBAR:
|
|
|
|
DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
PR_TRUE, GetProgressValue(aFrame));
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_PROGRESSBAR_VERTICAL:
|
|
|
|
DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
PR_FALSE, GetProgressValue(aFrame));
|
2007-03-22 10:30:00 -07: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:
|
|
|
|
DrawButton(cgContext, kThemeDisclosureButton, macRect, PR_FALSE, IsDisabled(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
kThemeDisclosureRight, kThemeAdornmentNone, eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_TWISTY_OPEN:
|
|
|
|
DrawButton(cgContext, kThemeDisclosureButton, macRect, PR_FALSE, IsDisabled(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
kThemeDisclosureDown, kThemeAdornmentNone, eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_HEADER_CELL: {
|
|
|
|
TreeSortDirection sortDirection = GetTreeSortDirection(aFrame);
|
|
|
|
DrawButton(cgContext, kThemeListHeaderButton, macRect, PR_FALSE, IsDisabled(aFrame),
|
|
|
|
sortDirection == eTreeSortDirection_Natural ? kThemeButtonOff : kThemeButtonOn,
|
|
|
|
sortDirection == eTreeSortDirection_Descending ?
|
2008-05-09 11:12:39 -07:00
|
|
|
kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone, eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_TREEITEM:
|
|
|
|
case NS_THEME_TREEVIEW:
|
|
|
|
// HIThemeSetFill is not available on 10.3
|
|
|
|
// HIThemeSetFill(kThemeBrushWhite, NULL, cgContext, HITHEME_ORIENTATION);
|
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
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: {
|
2008-03-26 22:36:20 -07:00
|
|
|
PRInt32 curpos = CheckIntAttr(aFrame, nsWidgetAtoms::curpos, 0);
|
|
|
|
PRInt32 minpos = CheckIntAttr(aFrame, nsWidgetAtoms::minpos, 0);
|
|
|
|
PRInt32 maxpos = CheckIntAttr(aFrame, nsWidgetAtoms::maxpos, 100);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!maxpos)
|
|
|
|
maxpos = 100;
|
|
|
|
|
2007-04-09 15:39:57 -07:00
|
|
|
PRBool reverse = aFrame->GetContent()->
|
|
|
|
AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::dir,
|
|
|
|
NS_LITERAL_STRING("reverse"), eCaseMatters);
|
2007-03-22 10:30:00 -07:00
|
|
|
DrawScale(cgContext, macRect, IsDisabled(aFrame), eventState,
|
2007-04-09 15:39:57 -07:00
|
|
|
(aWidgetType == NS_THEME_SCALE_VERTICAL), reverse,
|
2008-05-09 11:12:39 -07:00
|
|
|
curpos, minpos, maxpos);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_SCALE_THUMB_HORIZONTAL:
|
|
|
|
case NS_THEME_SCALE_THUMB_VERTICAL:
|
|
|
|
// do nothing, drawn by scale
|
|
|
|
break;
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
case NS_THEME_SCROLLBAR_SMALL:
|
|
|
|
case NS_THEME_SCROLLBAR: {
|
|
|
|
DrawScrollbar(cgContext, macRect, aFrame);
|
|
|
|
}
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
|
2007-04-10 17:25:11 -07:00
|
|
|
#if SCROLLBARS_VISUAL_DEBUG
|
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 0, 0.6);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
break;
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_SCROLLBAR_BUTTON_UP:
|
2007-04-10 17:25:11 -07:00
|
|
|
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
|
|
|
|
#if SCROLLBARS_VISUAL_DEBUG
|
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 0, 0, 0.6);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
break;
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
|
2007-04-10 17:25:11 -07:00
|
|
|
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
|
|
|
|
#if SCROLLBARS_VISUAL_DEBUG
|
|
|
|
CGContextSetRGBFillColor(cgContext, 0, 1.0, 0, 0.6);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
break;
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
2007-04-10 17:25:11 -07:00
|
|
|
// do nothing, drawn by scrollbar
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
2007-05-06 19:06:58 -07:00
|
|
|
|
|
|
|
case NS_THEME_TEXTFIELD_MULTILINE: {
|
|
|
|
// we have to draw this by hand because there is no HITheme value for it
|
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
|
|
|
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
|
|
|
|
CGContextSetLineWidth(cgContext, 1.0);
|
|
|
|
CGContextSetShouldAntialias(cgContext, false);
|
|
|
|
|
|
|
|
// stroke everything but the top line of the text area
|
|
|
|
CGContextSetRGBStrokeColor(cgContext, 0.6, 0.6, 0.6, 1.0);
|
|
|
|
CGContextBeginPath(cgContext);
|
|
|
|
CGContextMoveToPoint(cgContext, macRect.origin.x, macRect.origin.y + 1);
|
|
|
|
CGContextAddLineToPoint(cgContext, macRect.origin.x, macRect.origin.y + macRect.size.height);
|
|
|
|
CGContextAddLineToPoint(cgContext, macRect.origin.x + macRect.size.width - 1, macRect.origin.y + macRect.size.height);
|
|
|
|
CGContextAddLineToPoint(cgContext, macRect.origin.x + macRect.size.width - 1, macRect.origin.y + 1);
|
|
|
|
CGContextStrokePath(cgContext);
|
|
|
|
|
|
|
|
// stroke the line across the top of the text area
|
|
|
|
CGContextSetRGBStrokeColor(cgContext, 0.4510, 0.4510, 0.4510, 1.0);
|
|
|
|
CGContextBeginPath(cgContext);
|
|
|
|
CGContextMoveToPoint(cgContext, macRect.origin.x, macRect.origin.y + 1);
|
|
|
|
CGContextAddLineToPoint(cgContext, macRect.origin.x + macRect.size.width - 1, macRect.origin.y + 1);
|
|
|
|
CGContextStrokePath(cgContext);
|
2008-02-07 03:39:04 -08:00
|
|
|
|
|
|
|
// draw a focus ring
|
|
|
|
if (eventState & NS_EVENT_STATE_FOCUS) {
|
2008-02-07 04:37:51 -08:00
|
|
|
// We need to bring the rectangle in by 1 pixel on each side.
|
|
|
|
CGRect cgr = CGRectMake(macRect.origin.x + 1,
|
|
|
|
macRect.origin.y + 1,
|
|
|
|
macRect.size.width - 2,
|
|
|
|
macRect.size.height - 2);
|
2008-02-07 03:39:04 -08:00
|
|
|
HIThemeDrawFocusRect(&cgr, true, cgContext, kHIThemeOrientationNormal);
|
|
|
|
}
|
2007-05-06 19:06:58 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_LISTBOX:
|
|
|
|
// HIThemeSetFill is not available on 10.3
|
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
2008-05-09 11:12:39 -07:00
|
|
|
DrawFrame(cgContext, kHIThemeFrameListBox,
|
|
|
|
macRect, (IsDisabled(aFrame) || IsReadOnly(aFrame)), eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TAB: {
|
|
|
|
DrawTab(cgContext, macRect,
|
|
|
|
IsDisabled(aFrame), IsSelectedTab(aFrame),
|
|
|
|
PR_TRUE, IsBottomTab(aFrame),
|
2008-05-09 11:12:39 -07:00
|
|
|
eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TAB_PANELS:
|
2008-05-09 11:12:39 -07:00
|
|
|
DrawTabPanel(cgContext, macRect);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-02-20 03:33:27 -08:00
|
|
|
nativeDrawing.EndNativeDrawing();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-05-28 22:31:04 -07:00
|
|
|
|
2007-05-22 12:35:18 -07:00
|
|
|
static const int kAquaDropdownLeftBorder = 5;
|
2007-05-28 22:31:04 -07:00
|
|
|
static const int kAquaDropdownRightBorder = 22;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::GetWidgetBorder(nsIDeviceContext* aContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
|
|
|
nsMargin* aResult)
|
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
aResult->SizeTo(0, 0, 0, 0);
|
|
|
|
|
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_BUTTON:
|
2007-12-23 11:22:47 -08:00
|
|
|
{
|
|
|
|
aResult->SizeTo(7, 1, 7, 3);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
2007-12-23 11:22:47 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN:
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
2007-09-15 09:39:11 -07:00
|
|
|
aResult->SizeTo(kAquaDropdownLeftBorder, 2, kAquaDropdownRightBorder, 2);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
2007-09-03 08:25:15 -07:00
|
|
|
|
|
|
|
case NS_THEME_TEXTFIELD:
|
|
|
|
{
|
2007-03-22 10:30:00 -07:00
|
|
|
SInt32 frameOutset = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
|
2007-09-03 08:25:15 -07:00
|
|
|
|
|
|
|
SInt32 textPadding = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricEditTextWhitespace, &textPadding);
|
|
|
|
|
|
|
|
frameOutset += textPadding;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset);
|
|
|
|
break;
|
2007-09-03 08:25:15 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-05-06 19:06:58 -07:00
|
|
|
case NS_THEME_TEXTFIELD_MULTILINE:
|
|
|
|
aResult->SizeTo(1, 1, 1, 1);
|
|
|
|
break;
|
2007-09-03 08:25:15 -07:00
|
|
|
|
|
|
|
case NS_THEME_LISTBOX:
|
|
|
|
{
|
2007-03-22 10:30:00 -07:00
|
|
|
SInt32 frameOutset = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset);
|
|
|
|
aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset);
|
|
|
|
break;
|
2007-09-03 08:25:15 -07:00
|
|
|
}
|
2007-05-06 19:06:58 -07:00
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
|
|
|
{
|
|
|
|
// There's only an endcap to worry about when both arrows are on the bottom
|
|
|
|
ThemeScrollBarArrowStyle arrowStyle;
|
|
|
|
::GetThemeScrollBarArrowStyle(&arrowStyle);
|
|
|
|
if (arrowStyle == kThemeScrollBarArrowsLowerRight) {
|
|
|
|
PRBool isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL);
|
|
|
|
|
|
|
|
nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
|
|
|
|
if (!scrollbarFrame) return NS_ERROR_FAILURE;
|
|
|
|
PRBool isSmall = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
|
|
|
|
|
|
|
|
// There isn't a metric for this, so just hardcode a best guess at the value.
|
|
|
|
// This value is even less exact due to the fact that the endcap is partially concave.
|
|
|
|
PRInt32 endcapSize = isSmall ? 5 : 6;
|
|
|
|
|
|
|
|
if (isHorizontal)
|
|
|
|
aResult->SizeTo(endcapSize, 0, 0, 0);
|
|
|
|
else
|
|
|
|
aResult->SizeTo(0, endcapSize, 0, 0);
|
|
|
|
}
|
|
|
|
break;
|
2007-09-03 08:25:15 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-09-03 08:25:15 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
|
2007-09-03 08:25:15 -07:00
|
|
|
// Return PR_FALSE here to indicate that CSS padding values should be used. There is
|
|
|
|
// no reason to make a distinction between padding and border values, just specify
|
|
|
|
// whatever values you want in GetWidgetBorder and only use this to return PR_TRUE
|
|
|
|
// if you want to override CSS padding values.
|
2007-03-22 10:30:00 -07:00
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::GetWidgetPadding(nsIDeviceContext* aContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
|
|
|
nsMargin* aResult)
|
|
|
|
{
|
2007-11-17 11:33:51 -08:00
|
|
|
// We don't want CSS padding being used for certain widgets.
|
|
|
|
// See bug 381639 for an example of why.
|
2008-03-07 09:57:34 -08:00
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_BUTTON:
|
|
|
|
// Radios and checkboxes return a fixed size in GetMinimumWidgetSize
|
|
|
|
// and have a meaningful baseline, so they can't have
|
|
|
|
// author-specified padding.
|
|
|
|
case NS_THEME_CHECKBOX:
|
|
|
|
case NS_THEME_CHECKBOX_SMALL:
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
case NS_THEME_RADIO_SMALL:
|
|
|
|
aResult->SizeTo(0, 0, 0, 0);
|
|
|
|
return PR_TRUE;
|
2007-11-17 11:33:51 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::GetWidgetOverflow(nsIDeviceContext* aContext, nsIFrame* aFrame,
|
2008-04-01 16:34:20 -07:00
|
|
|
PRUint8 aWidgetType, nsRect* aOverflowRect)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_BUTTON:
|
|
|
|
case NS_THEME_TEXTFIELD:
|
2007-05-06 19:06:58 -07:00
|
|
|
case NS_THEME_TEXTFIELD_MULTILINE:
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_LISTBOX:
|
|
|
|
case NS_THEME_DROPDOWN:
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
|
|
|
case NS_THEME_CHECKBOX:
|
|
|
|
case NS_THEME_CHECKBOX_SMALL:
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
case NS_THEME_RADIO_SMALL:
|
|
|
|
{
|
|
|
|
// We assume that the above widgets can draw a focus ring that will be less than
|
|
|
|
// or equal to 4 pixels thick.
|
2008-01-08 18:52:36 -08:00
|
|
|
nsIntMargin extraSize = nsIntMargin(MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH);
|
2007-03-22 10:30:00 -07:00
|
|
|
PRInt32 p2a = aContext->AppUnitsPerDevPixel();
|
|
|
|
nsMargin m(NSIntPixelsToAppUnits(extraSize.left, p2a),
|
|
|
|
NSIntPixelsToAppUnits(extraSize.top, p2a),
|
|
|
|
NSIntPixelsToAppUnits(extraSize.right, p2a),
|
|
|
|
NSIntPixelsToAppUnits(extraSize.bottom, p2a));
|
2008-04-01 16:34:20 -07:00
|
|
|
aOverflowRect->Inflate(m);
|
2007-03-22 10:30:00 -07:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::GetMinimumWidgetSize(nsIRenderingContext* aContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
|
|
|
nsSize* aResult,
|
|
|
|
PRBool* aIsOverridable)
|
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
aResult->SizeTo(0,0);
|
|
|
|
*aIsOverridable = PR_TRUE;
|
|
|
|
|
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_BUTTON:
|
|
|
|
{
|
2007-12-23 11:22:47 -08:00
|
|
|
aResult->SizeTo(NATURAL_MINI_ROUNDED_BUTTON_MIN_WIDTH, NATURAL_MINI_ROUNDED_BUTTON_HEIGHT);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_SPINNER:
|
|
|
|
{
|
2007-09-18 02:17:51 -07:00
|
|
|
SInt32 buttonHeight = 0, buttonWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricLittleArrowsWidth, &buttonWidth);
|
|
|
|
::GetThemeMetric(kThemeMetricLittleArrowsHeight, &buttonHeight);
|
|
|
|
aResult->SizeTo(buttonWidth, buttonHeight);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
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_CHECKBOX_SMALL:
|
|
|
|
{
|
2007-05-17 19:01:02 -07:00
|
|
|
SInt32 boxHeight = 0, boxWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &boxWidth);
|
|
|
|
::GetThemeMetric(kThemeMetricSmallCheckBoxHeight, &boxHeight);
|
|
|
|
aResult->SizeTo(boxWidth, boxHeight - 1);
|
2007-03-22 10:30:00 -07:00
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
{
|
2008-01-13 20:48:33 -08:00
|
|
|
aResult->SizeTo(NATURAL_REGULAR_RADIO_BUTTON_WIDTH, NATURAL_REGULAR_RADIO_BUTTON_HEIGHT);
|
2007-03-22 10:30:00 -07:00
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_RADIO_SMALL:
|
|
|
|
{
|
2008-01-13 20:48:33 -08:00
|
|
|
aResult->SizeTo(NATURAL_SMALL_RADIO_BUTTON_WIDTH, NATURAL_SMALL_RADIO_BUTTON_HEIGHT);
|
2007-03-22 10:30:00 -07:00
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN:
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
|
|
|
{
|
|
|
|
SInt32 popupHeight = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricPopupButtonHeight, &popupHeight);
|
|
|
|
aResult->SizeTo(0, popupHeight);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_TEXTFIELD:
|
2007-05-06 19:06:58 -07:00
|
|
|
case NS_THEME_TEXTFIELD_MULTILINE:
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// 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.
|
|
|
|
aResult->SizeTo(0, (2 + 2) /* top */ + 9 + (1 + 1) /* bottom */);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_SCROLLBAR_SMALL:
|
|
|
|
{
|
|
|
|
SInt32 scrollbarWidth = 0;
|
|
|
|
::GetThemeMetric(kThemeMetricSmallScrollBarWidth, &scrollbarWidth);
|
|
|
|
aResult->SizeTo(scrollbarWidth, scrollbarWidth);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
2007-04-10 17:25:11 -07:00
|
|
|
|
|
|
|
// Get the rect of the thumb from HITheme, so we can return it to Gecko, which has different ideas about
|
|
|
|
// how big the thumb should be. This is kind of a hack.
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
|
|
|
|
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
2007-04-10 17:25:11 -07:00
|
|
|
{
|
|
|
|
// Find our parent scrollbar frame. If we can't, abort.
|
|
|
|
nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
|
|
|
|
if (!scrollbarFrame) return NS_ERROR_FAILURE;
|
|
|
|
|
2007-05-15 15:19:54 -07:00
|
|
|
nsRect scrollbarRect = scrollbarFrame->GetRect();
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
|
|
|
|
if (scrollbarRect.IsEmpty()) {
|
|
|
|
// just return (0,0)
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-10 17:25:11 -07:00
|
|
|
// We need to get the device context to convert from app units :(
|
|
|
|
nsCOMPtr<nsIDeviceContext> dctx;
|
|
|
|
aContext->GetDeviceContext(*getter_AddRefs(dctx));
|
|
|
|
PRInt32 p2a = dctx->AppUnitsPerDevPixel();
|
|
|
|
CGRect macRect = CGRectMake(NSAppUnitsToIntPixels(scrollbarRect.x, p2a),
|
|
|
|
NSAppUnitsToIntPixels(scrollbarRect.y, p2a),
|
|
|
|
NSAppUnitsToIntPixels(scrollbarRect.width, p2a),
|
|
|
|
NSAppUnitsToIntPixels(scrollbarRect.height, p2a));
|
|
|
|
|
|
|
|
// False here means not to get scrollbar button state information.
|
|
|
|
HIThemeTrackDrawInfo tdi;
|
|
|
|
GetScrollbarDrawInfo(tdi, scrollbarFrame, macRect, PR_FALSE);
|
|
|
|
|
|
|
|
HIRect thumbRect;
|
|
|
|
::HIThemeGetTrackPartBounds(&tdi, kControlIndicatorPart, &thumbRect);
|
|
|
|
|
|
|
|
// HITheme is just lying to us, I guess...
|
|
|
|
PRInt32 thumbAdjust = ((scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ?
|
|
|
|
2 : 4);
|
|
|
|
|
|
|
|
if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL)
|
|
|
|
aResult->SizeTo(nscoord(thumbRect.size.width), nscoord(thumbRect.size.height - thumbAdjust));
|
|
|
|
else
|
|
|
|
aResult->SizeTo(nscoord(thumbRect.size.width - thumbAdjust), nscoord(thumbRect.size.height));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NS_THEME_SCROLLBAR:
|
2007-03-22 10:30:00 -07:00
|
|
|
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.
|
2007-04-10 17:25:11 -07:00
|
|
|
|
|
|
|
nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
|
|
|
|
if (!scrollbarFrame) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
PRInt32 themeMetric = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ?
|
|
|
|
kThemeMetricSmallScrollBarWidth :
|
|
|
|
kThemeMetricScrollBarWidth;
|
2007-03-22 10:30:00 -07:00
|
|
|
SInt32 scrollbarWidth = 0;
|
2007-04-10 17:25:11 -07:00
|
|
|
::GetThemeMetric(themeMetric, &scrollbarWidth);
|
2007-03-22 10:30:00 -07:00
|
|
|
aResult->SizeTo(scrollbarWidth, scrollbarWidth);
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
2007-04-10 17:25:11 -07: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:
|
|
|
|
{
|
|
|
|
nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
|
|
|
|
if (!scrollbarFrame) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Since there is no NS_THEME_SCROLLBAR_BUTTON_UP_SMALL we need to ask the parent what appearance style it has.
|
|
|
|
PRInt32 themeMetric = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ?
|
|
|
|
kThemeMetricSmallScrollBarWidth :
|
|
|
|
kThemeMetricScrollBarWidth;
|
|
|
|
SInt32 scrollbarWidth = 0;
|
|
|
|
::GetThemeMetric(themeMetric, &scrollbarWidth);
|
|
|
|
|
|
|
|
// It seems that for both sizes of scrollbar, the buttons are one pixel "longer".
|
|
|
|
if (aWidgetType == NS_THEME_SCROLLBAR_BUTTON_LEFT || aWidgetType == NS_THEME_SCROLLBAR_BUTTON_RIGHT)
|
|
|
|
aResult->SizeTo(scrollbarWidth+1, scrollbarWidth);
|
|
|
|
else
|
|
|
|
aResult->SizeTo(scrollbarWidth, scrollbarWidth+1);
|
|
|
|
|
|
|
|
*aIsOverridable = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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_TOOLTIP:
|
|
|
|
case NS_THEME_TAB_PANELS:
|
|
|
|
case NS_THEME_TAB_PANEL:
|
|
|
|
case NS_THEME_DIALOG:
|
|
|
|
case NS_THEME_MENUPOPUP:
|
2008-03-13 13:24:29 -07:00
|
|
|
case NS_THEME_GROUPBOX:
|
2007-03-22 10:30:00 -07:00
|
|
|
*aShouldRepaint = PR_FALSE;
|
|
|
|
return NS_OK;
|
2008-04-07 15:56:43 -07:00
|
|
|
case NS_THEME_PROGRESSBAR_CHUNK:
|
|
|
|
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
|
|
|
|
case NS_THEME_PROGRESSBAR:
|
|
|
|
case NS_THEME_PROGRESSBAR_VERTICAL:
|
|
|
|
*aShouldRepaint = (aAttribute == nsWidgetAtoms::step);
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 ||
|
2007-05-22 17:10:02 -07:00
|
|
|
aAttribute == nsWidgetAtoms::sortdirection ||
|
2008-01-13 20:48:33 -08:00
|
|
|
aAttribute == nsWidgetAtoms::focused ||
|
2007-05-22 17:10:02 -07:00
|
|
|
aAttribute == nsWidgetAtoms::_default)
|
2007-03-22 10:30:00 -07:00
|
|
|
*aShouldRepaint = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNativeThemeCocoa::ThemeChanged()
|
|
|
|
{
|
|
|
|
// This is unimplemented because we don't care if gecko changes its theme
|
|
|
|
// and Mac OS X doesn't have themes.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType)
|
|
|
|
{
|
|
|
|
if (aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
|
|
|
|
return PR_FALSE;
|
|
|
|
|
2007-08-27 20:39:19 -07:00
|
|
|
// if this is a dropdown button in a combobox the answer is always no
|
|
|
|
if (aWidgetType == NS_THEME_DROPDOWN_BUTTON) {
|
|
|
|
nsIFrame* parentFrame = aFrame->GetParent();
|
|
|
|
if (parentFrame && (parentFrame->GetType() == nsWidgetAtoms::comboboxControlFrame))
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
switch (aWidgetType) {
|
2007-08-27 20:39:19 -07:00
|
|
|
case NS_THEME_LISTBOX:
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_DIALOG:
|
|
|
|
case NS_THEME_WINDOW:
|
|
|
|
case NS_THEME_MENUPOPUP:
|
|
|
|
case NS_THEME_MENUITEM:
|
2008-02-24 05:41:22 -08:00
|
|
|
case NS_THEME_MENUSEPARATOR:
|
2007-03-22 10:30:00 -07:00
|
|
|
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:
|
2008-03-13 13:24:29 -07:00
|
|
|
case NS_THEME_GROUPBOX:
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_BUTTON:
|
|
|
|
case NS_THEME_BUTTON_BEVEL:
|
|
|
|
case NS_THEME_SPINNER:
|
|
|
|
case NS_THEME_TOOLBAR:
|
|
|
|
case NS_THEME_STATUSBAR:
|
|
|
|
case NS_THEME_TEXTFIELD:
|
2007-05-06 19:06:58 -07:00
|
|
|
case NS_THEME_TEXTFIELD_MULTILINE:
|
2007-03-22 10:30:00 -07:00
|
|
|
//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:
|
|
|
|
case NS_THEME_SCROLLBAR_SMALL:
|
|
|
|
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_TRACK_VERTICAL:
|
|
|
|
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN:
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
|
|
|
case NS_THEME_DROPDOWN_TEXT:
|
2007-08-27 20:39:19 -07:00
|
|
|
return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-08-27 20:39:19 -07:00
|
|
|
return PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::WidgetIsContainer(PRUint8 aWidgetType)
|
|
|
|
{
|
|
|
|
// flesh this out at some point
|
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
|
|
|
case NS_THEME_RADIO:
|
2007-05-17 19:01:02 -07:00
|
|
|
case NS_THEME_RADIO_SMALL:
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_CHECKBOX:
|
2007-05-17 19:01:02 -07:00
|
|
|
case NS_THEME_CHECKBOX_SMALL:
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_PROGRESSBAR:
|
|
|
|
return PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::ThemeDrawsFocusForWidget(nsPresContext* aPresContext, nsIFrame* aFrame, PRUint8 aWidgetType)
|
|
|
|
{
|
|
|
|
if (aWidgetType == NS_THEME_DROPDOWN ||
|
2008-01-13 20:48:33 -08:00
|
|
|
aWidgetType == NS_THEME_BUTTON ||
|
|
|
|
aWidgetType == NS_THEME_RADIO ||
|
|
|
|
aWidgetType == NS_THEME_RADIO_SMALL ||
|
|
|
|
aWidgetType == NS_THEME_CHECKBOX ||
|
|
|
|
aWidgetType == NS_THEME_CHECKBOX_SMALL)
|
2007-03-22 10:30:00 -07:00
|
|
|
return PR_TRUE;
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2007-05-17 20:04:04 -07:00
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsNativeThemeCocoa::ThemeNeedsComboboxDropmarker()
|
|
|
|
{
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|