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>
|
2008-10-13 09:58:40 -07:00
|
|
|
* Markus Stange <mstange@themasta.com>
|
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"
|
2011-04-07 18:04:40 -07:00
|
|
|
#include "nsRenderingContext.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#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"
|
2011-04-21 10:35:52 -07:00
|
|
|
#include "nsEventStates.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsPresContext.h"
|
|
|
|
#include "nsILookAndFeel.h"
|
|
|
|
#include "nsWidgetAtoms.h"
|
2007-12-23 11:22:47 -08:00
|
|
|
#include "nsToolkit.h"
|
2008-09-16 01:21:06 -07:00
|
|
|
#include "nsCocoaWindow.h"
|
2008-10-15 06:01:10 -07:00
|
|
|
#include "nsNativeThemeColors.h"
|
2010-06-21 05:37:35 -07:00
|
|
|
#include "nsIScrollableFrame.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);
|
|
|
|
}
|
|
|
|
|
2008-10-13 09:58:40 -07:00
|
|
|
// Workaround for NSCell control tint drawing
|
|
|
|
// Without this workaround, NSCells are always drawn with the clear control tint
|
|
|
|
// as long as they're not attached to an NSControl which is a subview of an active window.
|
|
|
|
// XXXmstange Why doesn't Webkit need this?
|
|
|
|
@implementation NSCell (ControlTintWorkaround)
|
|
|
|
- (int)_realControlTint { return [self controlTint]; }
|
|
|
|
@end
|
|
|
|
|
2009-09-16 15:06:16 -07:00
|
|
|
// The purpose of this class is to provide objects that can be used when drawing
|
|
|
|
// NSCells using drawWithFrame:inView: without causing any harm. The only
|
|
|
|
// messages that will be sent to such an object are "isFlipped" and
|
|
|
|
// "currentEditor": isFlipped needs to return YES in order to avoid drawing bugs
|
|
|
|
// on 10.4 (see bug 465069); currentEditor (which isn't even a method of
|
|
|
|
// NSView) will be called when drawing search fields, and we only provide it in
|
|
|
|
// order to prevent "unrecognized selector" exceptions.
|
|
|
|
// There's no need to pass the actual NSView that we're drawing into to
|
|
|
|
// drawWithFrame:inView:. What's more, doing so even causes unnecessary
|
|
|
|
// invalidations as soon as we draw a focusring!
|
|
|
|
@interface CellDrawView : NSView
|
|
|
|
|
|
|
|
@end;
|
|
|
|
|
|
|
|
@implementation CellDrawView
|
|
|
|
|
|
|
|
- (BOOL)isFlipped
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSText*)currentEditor
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
2010-10-13 08:56:16 -07:00
|
|
|
// Workaround for Bug 542048
|
|
|
|
// On 64-bit, NSSearchFieldCells don't draw focus rings.
|
|
|
|
#if defined(__x86_64__)
|
|
|
|
|
|
|
|
static void DrawFocusRing(NSRect rect, float radius)
|
|
|
|
{
|
|
|
|
NSSetFocusRingStyle(NSFocusRingOnly);
|
|
|
|
NSBezierPath* path = [NSBezierPath bezierPath];
|
|
|
|
rect = NSInsetRect(rect, radius, radius);
|
|
|
|
[path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect), NSMinY(rect)) radius:radius startAngle:180.0 endAngle:270.0];
|
|
|
|
[path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(rect), NSMinY(rect)) radius:radius startAngle:270.0 endAngle:360.0];
|
|
|
|
[path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(rect), NSMaxY(rect)) radius:radius startAngle: 0.0 endAngle: 90.0];
|
|
|
|
[path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect), NSMaxY(rect)) radius:radius startAngle: 90.0 endAngle:180.0];
|
|
|
|
[path closePath];
|
|
|
|
[path fill];
|
|
|
|
}
|
|
|
|
|
|
|
|
@interface SearchFieldCellWithFocusRing : NSSearchFieldCell {} @end
|
|
|
|
|
|
|
|
@implementation SearchFieldCellWithFocusRing
|
|
|
|
|
|
|
|
- (void)drawWithFrame:(NSRect)rect inView:(NSView*)controlView
|
|
|
|
{
|
|
|
|
[super drawWithFrame:rect inView:controlView];
|
|
|
|
if ([self showsFirstResponder]) {
|
|
|
|
DrawFocusRing(rect, NSHeight(rect) / 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
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 {
|
2011-03-18 07:10:01 -07:00
|
|
|
leopardOS = 0
|
2008-01-08 18:52:36 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
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])
|
|
|
|
{
|
2008-10-13 09:58:40 -07:00
|
|
|
if (!marginSet)
|
|
|
|
return;
|
2010-02-23 15:30:39 -08:00
|
|
|
|
|
|
|
static int osIndex = leopardOS;
|
2008-01-08 18:52:36 -08:00
|
|
|
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
|
|
|
|
2009-08-03 15:25:20 -07:00
|
|
|
static NSWindow* NativeWindowForFrame(nsIFrame* aFrame,
|
2008-09-22 01:57:42 -07:00
|
|
|
nsIWidget** aTopLevelWidget = NULL)
|
2008-09-16 01:21:06 -07:00
|
|
|
{
|
|
|
|
if (!aFrame)
|
|
|
|
return nil;
|
|
|
|
|
2010-07-02 12:11:04 -07:00
|
|
|
nsIWidget* widget = aFrame->GetNearestWidget();
|
2008-09-16 01:21:06 -07:00
|
|
|
if (!widget)
|
|
|
|
return nil;
|
|
|
|
|
2009-08-03 15:25:20 -07:00
|
|
|
nsIWidget* topLevelWidget = widget->GetTopLevelWidget();
|
2008-09-22 01:57:42 -07:00
|
|
|
if (aTopLevelWidget)
|
|
|
|
*aTopLevelWidget = topLevelWidget;
|
2008-09-16 01:21:06 -07:00
|
|
|
|
|
|
|
return (NSWindow*)topLevelWidget->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
}
|
2007-05-08 05:54:48 -07:00
|
|
|
|
2008-09-22 01:57:42 -07:00
|
|
|
static BOOL FrameIsInActiveWindow(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
nsIWidget* topLevelWidget = NULL;
|
2009-08-03 15:25:20 -07:00
|
|
|
NSWindow* win = NativeWindowForFrame(aFrame, &topLevelWidget);
|
2008-09-22 01:57:42 -07:00
|
|
|
if (!topLevelWidget || !win)
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
// XUL popups, e.g. the toolbar customization popup, can't become key windows,
|
|
|
|
// but controls in these windows should still get the active look.
|
|
|
|
nsWindowType windowType;
|
|
|
|
topLevelWidget->GetWindowType(windowType);
|
2008-11-27 14:38:24 -08:00
|
|
|
if (windowType == eWindowType_popup)
|
|
|
|
return YES;
|
|
|
|
if ([win isSheet])
|
|
|
|
return [win isKeyWindow];
|
|
|
|
return [win isMainWindow] && ![win attachedSheet];
|
2008-09-22 01:57:42 -07:00
|
|
|
}
|
|
|
|
|
2010-11-13 00:19:38 -08:00
|
|
|
NS_IMPL_ISUPPORTS_INHERITED1(nsNativeThemeCocoa, nsNativeTheme, nsITheme)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
|
|
|
|
nsNativeThemeCocoa::nsNativeThemeCocoa()
|
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2011-04-08 23:56:56 -07:00
|
|
|
// provide a local autorelease pool, as this is called during startup
|
|
|
|
// before the main event-loop pool is in place
|
|
|
|
nsAutoreleasePool pool;
|
|
|
|
|
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];
|
2008-10-13 09:58:40 -07:00
|
|
|
|
|
|
|
mCheckboxCell = [[NSButtonCell alloc] initTextCell:nil];
|
|
|
|
[mCheckboxCell setButtonType:NSSwitchButton];
|
2009-01-29 23:19:41 -08:00
|
|
|
[mCheckboxCell setAllowsMixedState:YES];
|
2008-02-20 17:01:27 -08:00
|
|
|
|
2010-10-13 08:56:16 -07:00
|
|
|
#if defined(__x86_64__)
|
|
|
|
mSearchFieldCell = [[SearchFieldCellWithFocusRing alloc] initTextCell:@""];
|
|
|
|
#else
|
2010-02-23 15:30:39 -08:00
|
|
|
mSearchFieldCell = [[NSSearchFieldCell alloc] initTextCell:@""];
|
2010-10-13 08:56:16 -07:00
|
|
|
#endif
|
2008-12-06 03:40:58 -08:00
|
|
|
[mSearchFieldCell setBezelStyle:NSTextFieldRoundedBezel];
|
|
|
|
[mSearchFieldCell setBezeled:YES];
|
|
|
|
[mSearchFieldCell setEditable:YES];
|
|
|
|
[mSearchFieldCell setFocusRingType:NSFocusRingTypeExterior];
|
|
|
|
|
2009-01-31 08:49:29 -08:00
|
|
|
mDropdownCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO];
|
|
|
|
|
2010-02-23 15:30:39 -08:00
|
|
|
mComboBoxCell = [[NSComboBoxCell alloc] initTextCell:@""];
|
2009-02-11 07:54:10 -08:00
|
|
|
[mComboBoxCell setBezeled:YES];
|
|
|
|
[mComboBoxCell setEditable:YES];
|
|
|
|
[mComboBoxCell setFocusRingType:NSFocusRingTypeExterior];
|
|
|
|
|
2009-09-16 15:06:16 -07:00
|
|
|
mCellDrawView = [[CellDrawView alloc] init];
|
|
|
|
|
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-10-13 09:58:40 -07:00
|
|
|
[mCheckboxCell release];
|
2008-12-06 03:40:58 -08:00
|
|
|
[mSearchFieldCell release];
|
2009-01-31 08:49:29 -08:00
|
|
|
[mDropdownCell release];
|
2009-02-11 07:54:10 -08:00
|
|
|
[mComboBoxCell release];
|
2009-09-16 15:06:16 -07:00
|
|
|
[mCellDrawView release];
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-12-03 08:38:59 -08:00
|
|
|
// Limit on the area of the target rect (in pixels^2) in
|
|
|
|
// DrawCellWithScaling(), DrawButton() and DrawScrollbar(), above which we
|
|
|
|
// don't draw the object into a bitmap buffer. This is to avoid crashes in
|
2008-09-17 08:17:08 -07:00
|
|
|
// [NSGraphicsContext graphicsContextWithGraphicsPort:flipped:] and
|
|
|
|
// CGContextDrawImage(), and also to avoid very poor drawing performance in
|
2008-12-03 08:38:59 -08:00
|
|
|
// CGContextDrawImage() when it scales the bitmap (particularly if xscale or
|
|
|
|
// yscale is less than but near 1 -- e.g. 0.9). This value was determined
|
|
|
|
// by trial and error, on OS X 10.4.11 and 10.5.4, and on systems with
|
|
|
|
// different amounts of RAM.
|
|
|
|
#define BITMAP_MAX_AREA 500000
|
2008-09-17 08:17:08 -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
|
2008-10-13 09:58:40 -07:00
|
|
|
* naturalSize - The natural dimensions of this control.
|
2008-03-04 12:51:54 -08:00
|
|
|
* 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.
|
2008-10-13 09:58:40 -07:00
|
|
|
* minimumSize - The minimum dimensions of this control.
|
2008-03-04 12:51:54 -08:00
|
|
|
* 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],
|
2008-10-13 09:58:40 -07:00
|
|
|
* with the first dimension being the OS version (Tiger or Leopard),
|
|
|
|
* the second being the control size (mini, small, regular), and the third
|
|
|
|
* being the 4 margin values (left, top, right, bottom).
|
2008-12-06 03:40:58 -08:00
|
|
|
* view - The NSView that we're drawing into. As far as I can tell, it doesn't
|
|
|
|
* matter if this is really the right view; it just has to return YES when
|
|
|
|
* asked for isFlipped. Otherwise we'll get drawing bugs on 10.4.
|
2009-04-17 01:12:12 -07:00
|
|
|
* mirrorHorizontal - whether to mirror the cell horizontally
|
2008-03-04 12:51:54 -08:00
|
|
|
*/
|
2008-10-13 09:58:40 -07:00
|
|
|
static void DrawCellWithScaling(NSCell *cell,
|
|
|
|
CGContextRef cgContext,
|
|
|
|
const HIRect& destRect,
|
|
|
|
NSControlSize controlSize,
|
|
|
|
NSSize naturalSize,
|
|
|
|
NSSize minimumSize,
|
|
|
|
const float marginSet[][3][4],
|
2009-04-17 01:12:12 -07:00
|
|
|
NSView* view,
|
|
|
|
BOOL mirrorHorizontal)
|
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-10-13 09:58:40 -07:00
|
|
|
if (naturalSize.width != 0.0f)
|
|
|
|
drawRect.size.width = naturalSize.width;
|
|
|
|
if (naturalSize.height != 0.0f)
|
|
|
|
drawRect.size.height = naturalSize.height;
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-10-13 09:58:40 -07:00
|
|
|
// Keep aspect ratio when scaling if one dimension is free.
|
|
|
|
if (naturalSize.width == 0.0f && naturalSize.height != 0.0f)
|
|
|
|
drawRect.size.width = destRect.size.width * naturalSize.height / destRect.size.height;
|
|
|
|
if (naturalSize.height == 0.0f && naturalSize.width != 0.0f)
|
|
|
|
drawRect.size.height = destRect.size.height * naturalSize.width / destRect.size.width;
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-10-13 09:58:40 -07:00
|
|
|
// Honor minimum sizes.
|
|
|
|
if (drawRect.size.width < minimumSize.width)
|
|
|
|
drawRect.size.width = minimumSize.width;
|
|
|
|
if (drawRect.size.height < minimumSize.height)
|
|
|
|
drawRect.size.height = minimumSize.height;
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-11-09 14:30:46 -08:00
|
|
|
[NSGraphicsContext saveGraphicsState];
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-12-06 03:40:58 -08:00
|
|
|
// Only skip the buffer if the area of our cell (in pixels^2) is too large.
|
|
|
|
if (drawRect.size.width * drawRect.size.height > BITMAP_MAX_AREA) {
|
2008-03-14 12:29:32 -07:00
|
|
|
// 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-11-09 14:30:46 -08:00
|
|
|
NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
|
2008-03-14 12:29:32 -07:00
|
|
|
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]];
|
|
|
|
|
2008-12-06 03:40:58 -08:00
|
|
|
[cell drawWithFrame:drawRect inView:view];
|
2008-11-09 14:30:46 -08:00
|
|
|
|
|
|
|
[NSGraphicsContext setCurrentContext:savedContext];
|
2008-03-14 12:29:32 -07:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
float w = ceil(drawRect.size.width);
|
|
|
|
float h = ceil(drawRect.size.height);
|
2008-12-06 03:40:58 -08:00
|
|
|
NSRect tmpRect = NSMakeRect(MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH, w, h);
|
2008-03-14 12:29:32 -07:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2008-12-06 03:40:58 -08:00
|
|
|
// We need to flip the image twice in order to avoid drawing bugs on 10.4, see bug 465069.
|
|
|
|
// This is the first flip transform, applied to cgContext.
|
|
|
|
CGContextScaleCTM(cgContext, 1.0f, -1.0f);
|
|
|
|
CGContextTranslateCTM(cgContext, 0.0f, -(2.0 * destRect.origin.y + destRect.size.height));
|
2009-04-17 01:12:12 -07:00
|
|
|
if (mirrorHorizontal) {
|
|
|
|
CGContextScaleCTM(cgContext, -1.0f, 1.0f);
|
|
|
|
CGContextTranslateCTM(cgContext, -(2.0 * destRect.origin.x + destRect.size.width), 0.0f);
|
|
|
|
}
|
2008-03-14 12:29:32 -07:00
|
|
|
|
2008-11-09 14:30:46 -08:00
|
|
|
NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
|
2008-03-14 12:29:32 -07:00
|
|
|
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]];
|
|
|
|
|
2008-12-06 03:40:58 -08:00
|
|
|
// This is the second flip transform, applied to ctx.
|
|
|
|
CGContextScaleCTM(ctx, 1.0f, -1.0f);
|
|
|
|
CGContextTranslateCTM(ctx, 0.0f, -(2.0 * tmpRect.origin.y + tmpRect.size.height));
|
|
|
|
|
|
|
|
[cell drawWithFrame:tmpRect inView:view];
|
2008-03-14 12:29:32 -07:00
|
|
|
|
|
|
|
[NSGraphicsContext setCurrentContext:savedContext];
|
|
|
|
|
|
|
|
CGImageRef img = CGBitmapContextCreateImage(ctx);
|
|
|
|
|
|
|
|
// Drop the image into the original destination rectangle, scaling to fit
|
2008-10-13 09:58:40 -07:00
|
|
|
// Only scale MAX_FOCUS_RING_WIDTH by xscale/yscale when the resulting rect
|
|
|
|
// doesn't extend beyond the overflow rect
|
|
|
|
float xscale = destRect.size.width / drawRect.size.width;
|
|
|
|
float yscale = destRect.size.height / drawRect.size.height;
|
|
|
|
float scaledFocusRingX = xscale < 1.0f ? MAX_FOCUS_RING_WIDTH * xscale : MAX_FOCUS_RING_WIDTH;
|
|
|
|
float scaledFocusRingY = yscale < 1.0f ? MAX_FOCUS_RING_WIDTH * yscale : MAX_FOCUS_RING_WIDTH;
|
|
|
|
CGContextDrawImage(cgContext, CGRectMake(destRect.origin.x - scaledFocusRingX,
|
|
|
|
destRect.origin.y - scaledFocusRingY,
|
|
|
|
destRect.size.width + scaledFocusRingX * 2,
|
|
|
|
destRect.size.height + scaledFocusRingY * 2),
|
2008-03-14 12:29:32 -07:00
|
|
|
img);
|
|
|
|
|
|
|
|
CGImageRelease(img);
|
|
|
|
CGContextRelease(ctx);
|
|
|
|
}
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2008-11-09 14:30:46 -08:00
|
|
|
[NSGraphicsContext restoreGraphicsState];
|
2008-03-14 12:29:32 -07:00
|
|
|
|
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-09-22 01:57:42 -07:00
|
|
|
|
2008-10-13 09:58:40 -07:00
|
|
|
struct CellRenderSettings {
|
|
|
|
// The natural dimensions of the control.
|
|
|
|
// If a control has no natural dimensions in either/both axes, set to 0.0f.
|
|
|
|
NSSize naturalSizes[3];
|
|
|
|
|
|
|
|
// The minimum dimensions of the control.
|
|
|
|
// If a control has no minimum dimensions in either/both axes, set to 0.0f.
|
|
|
|
NSSize minimumSizes[3];
|
|
|
|
|
2011-03-30 05:41:08 -07:00
|
|
|
// A three-dimensional array,
|
2011-03-18 07:10:01 -07:00
|
|
|
// with the first dimension being the OS version (only Leopard for the moment),
|
2008-10-13 09:58:40 -07:00
|
|
|
// the second being the control size (mini, small, regular), and the third
|
|
|
|
// being the 4 margin values (left, top, right, bottom).
|
2011-03-18 07:10:01 -07:00
|
|
|
float margins[1][3][4];
|
2008-10-13 09:58:40 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Draw the given NSCell into the given cgContext with a nice control size.
|
|
|
|
*
|
|
|
|
* This function is similar to DrawCellWithScaling, but it decides what
|
|
|
|
* control size to use based on the destRect's size.
|
|
|
|
* Scaling is only applied when the difference between the destRect's size
|
2009-01-12 11:22:59 -08:00
|
|
|
* and the next smaller natural size is greater than snapTolerance. Otherwise
|
2008-10-13 09:58:40 -07:00
|
|
|
* it snaps to the next smaller control size without scaling because unscaled
|
|
|
|
* controls look nicer.
|
|
|
|
*/
|
|
|
|
static void DrawCellWithSnapping(NSCell *cell,
|
|
|
|
CGContextRef cgContext,
|
|
|
|
const HIRect& destRect,
|
|
|
|
const CellRenderSettings settings,
|
|
|
|
float verticalAlignFactor,
|
2009-01-12 11:22:59 -08:00
|
|
|
NSView* view,
|
2009-04-17 01:12:12 -07:00
|
|
|
BOOL mirrorHorizontal,
|
2009-01-12 11:22:59 -08:00
|
|
|
float snapTolerance = 2.0f)
|
2008-10-13 09:58:40 -07:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
const float rectWidth = destRect.size.width, rectHeight = destRect.size.height;
|
|
|
|
const NSSize *sizes = settings.naturalSizes;
|
|
|
|
const NSSize miniSize = sizes[EnumSizeForCocoaSize(NSMiniControlSize)];
|
|
|
|
const NSSize smallSize = sizes[EnumSizeForCocoaSize(NSSmallControlSize)];
|
|
|
|
const NSSize regularSize = sizes[EnumSizeForCocoaSize(NSRegularControlSize)];
|
|
|
|
|
|
|
|
NSControlSize controlSizeX = NSRegularControlSize, controlSizeY = NSRegularControlSize;
|
|
|
|
HIRect drawRect = destRect;
|
|
|
|
|
2009-01-12 11:22:59 -08:00
|
|
|
if (rectWidth <= miniSize.width + snapTolerance && rectWidth < smallSize.width)
|
2008-10-13 09:58:40 -07:00
|
|
|
controlSizeX = NSMiniControlSize;
|
2009-01-12 11:22:59 -08:00
|
|
|
else if(rectWidth <= smallSize.width + snapTolerance && rectWidth < regularSize.width)
|
2008-10-13 09:58:40 -07:00
|
|
|
controlSizeX = NSSmallControlSize;
|
|
|
|
|
2009-01-12 11:22:59 -08:00
|
|
|
if (rectHeight <= miniSize.height + snapTolerance && rectHeight < smallSize.height)
|
2008-10-13 09:58:40 -07:00
|
|
|
controlSizeY = NSMiniControlSize;
|
2009-01-12 11:22:59 -08:00
|
|
|
else if(rectHeight <= smallSize.height + snapTolerance && rectHeight < regularSize.height)
|
2008-10-13 09:58:40 -07:00
|
|
|
controlSizeY = NSSmallControlSize;
|
|
|
|
|
|
|
|
NSControlSize controlSize = NSRegularControlSize;
|
|
|
|
int sizeIndex = 0;
|
|
|
|
|
|
|
|
// At some sizes, don't scale but snap.
|
|
|
|
const NSControlSize smallerControlSize =
|
|
|
|
EnumSizeForCocoaSize(controlSizeX) < EnumSizeForCocoaSize(controlSizeY) ?
|
|
|
|
controlSizeX : controlSizeY;
|
|
|
|
const int smallerControlSizeIndex = EnumSizeForCocoaSize(smallerControlSize);
|
2008-12-06 03:40:58 -08:00
|
|
|
const NSSize size = sizes[smallerControlSizeIndex];
|
|
|
|
float diffWidth = size.width ? rectWidth - size.width : 0.0f;
|
|
|
|
float diffHeight = size.height ? rectHeight - size.height : 0.0f;
|
2008-10-13 09:58:40 -07:00
|
|
|
if (diffWidth >= 0.0f && diffHeight >= 0.0f &&
|
2009-01-12 11:22:59 -08:00
|
|
|
diffWidth <= snapTolerance && diffHeight <= snapTolerance) {
|
2008-10-13 09:58:40 -07:00
|
|
|
// Snap to the smaller control size.
|
|
|
|
controlSize = smallerControlSize;
|
|
|
|
sizeIndex = smallerControlSizeIndex;
|
|
|
|
// Resize and center the drawRect.
|
|
|
|
if (sizes[sizeIndex].width) {
|
|
|
|
drawRect.origin.x += ceil((destRect.size.width - sizes[sizeIndex].width) / 2);
|
|
|
|
drawRect.size.width = sizes[sizeIndex].width;
|
|
|
|
}
|
|
|
|
if (sizes[sizeIndex].height) {
|
|
|
|
drawRect.origin.y += floor((destRect.size.height - sizes[sizeIndex].height) * verticalAlignFactor);
|
|
|
|
drawRect.size.height = sizes[sizeIndex].height;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Use the larger control size.
|
|
|
|
controlSize = EnumSizeForCocoaSize(controlSizeX) > EnumSizeForCocoaSize(controlSizeY) ?
|
|
|
|
controlSizeX : controlSizeY;
|
|
|
|
sizeIndex = EnumSizeForCocoaSize(controlSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
[cell setControlSize:controlSize];
|
|
|
|
|
|
|
|
NSSize minimumSize = settings.minimumSizes ? settings.minimumSizes[sizeIndex] : NSZeroSize;
|
|
|
|
DrawCellWithScaling(cell, cgContext, drawRect, controlSize, sizes[sizeIndex],
|
2009-04-17 01:12:12 -07:00
|
|
|
minimumSize, settings.margins, view, mirrorHorizontal);
|
2008-10-13 09:58:40 -07:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static float VerticalAlignFactor(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
if (!aFrame)
|
|
|
|
return 0.5f; // default: center
|
|
|
|
|
|
|
|
const nsStyleCoord& va = aFrame->GetStyleTextReset()->mVerticalAlign;
|
|
|
|
PRUint8 intval = (va.GetUnit() == eStyleUnit_Enumerated)
|
|
|
|
? va.GetIntValue()
|
|
|
|
: NS_STYLE_VERTICAL_ALIGN_MIDDLE;
|
|
|
|
switch (intval) {
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_TOP:
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
|
|
|
|
return 0.0f;
|
|
|
|
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_SUB:
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_SUPER:
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE:
|
|
|
|
return 0.5f;
|
|
|
|
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_BASELINE:
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
|
|
|
|
case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
|
|
|
|
return 1.0f;
|
|
|
|
|
|
|
|
default:
|
|
|
|
NS_NOTREACHED("invalid vertical-align");
|
|
|
|
return 0.5f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.
|
2008-10-13 09:58:40 -07:00
|
|
|
static const CellRenderSettings radioSettings = {
|
|
|
|
{
|
|
|
|
NSMakeSize(11, 11), // mini
|
|
|
|
NSMakeSize(13, 13), // small
|
|
|
|
NSMakeSize(16, 16) // regular
|
|
|
|
},
|
|
|
|
{
|
|
|
|
NSZeroSize, NSZeroSize, NSZeroSize
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{ // Leopard
|
|
|
|
{0, 0, 0, 0}, // mini
|
|
|
|
{0, 1, 1, 1}, // small
|
|
|
|
{0, 0, 0, 0} // regular
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2008-03-14 12:29:32 -07:00
|
|
|
|
2008-10-13 09:58:40 -07:00
|
|
|
static const CellRenderSettings checkboxSettings = {
|
|
|
|
{
|
|
|
|
NSMakeSize(11, 11), // mini
|
|
|
|
NSMakeSize(13, 13), // small
|
|
|
|
NSMakeSize(16, 16) // regular
|
2008-03-14 12:29:32 -07:00
|
|
|
},
|
2008-10-13 09:58:40 -07:00
|
|
|
{
|
|
|
|
NSZeroSize, NSZeroSize, NSZeroSize
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{ // Leopard
|
|
|
|
{0, 1, 0, 0}, // mini
|
|
|
|
{0, 1, 0, 1}, // small
|
|
|
|
{0, 1, 0, 1} // regular
|
|
|
|
}
|
2008-03-14 12:29:32 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
void
|
2008-10-13 09:58:40 -07:00
|
|
|
nsNativeThemeCocoa::DrawCheckboxOrRadio(CGContextRef cgContext, PRBool inCheckbox,
|
|
|
|
const HIRect& inBoxRect, PRBool inSelected,
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates inState, nsIFrame* aFrame)
|
2008-03-04 12:51:54 -08:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-10-13 09:58:40 -07:00
|
|
|
NSButtonCell *cell = inCheckbox ? mCheckboxCell : mRadioButtonCell;
|
2009-01-29 23:19:41 -08:00
|
|
|
NSCellStateValue state = inSelected ? NSOnState : NSOffState;
|
|
|
|
|
|
|
|
// Check if we have an indeterminate checkbox
|
|
|
|
if (inCheckbox && GetIndeterminate(aFrame))
|
|
|
|
state = NSMixedState;
|
2008-03-04 12:51:54 -08:00
|
|
|
|
2010-09-27 18:25:18 -07:00
|
|
|
[cell setEnabled:!IsDisabled(aFrame, inState)];
|
2010-10-20 04:26:32 -07:00
|
|
|
[cell setShowsFirstResponder:inState.HasState(NS_EVENT_STATE_FOCUS)];
|
2009-01-29 23:19:41 -08:00
|
|
|
[cell setState:state];
|
2010-10-20 04:26:32 -07:00
|
|
|
[cell setHighlighted:inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)];
|
2008-10-13 09:58:40 -07:00
|
|
|
[cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)];
|
2008-12-11 06:48:30 -08:00
|
|
|
|
|
|
|
// Ensure that the control is square.
|
|
|
|
float length = PR_MIN(inBoxRect.size.width, inBoxRect.size.height);
|
|
|
|
HIRect drawRect = CGRectMake(inBoxRect.origin.x + (int)((inBoxRect.size.width - length) / 2.0f),
|
|
|
|
inBoxRect.origin.y + (int)((inBoxRect.size.height - length) / 2.0f),
|
|
|
|
length, length);
|
|
|
|
|
|
|
|
DrawCellWithSnapping(cell, cgContext, drawRect,
|
2008-10-13 09:58:40 -07:00
|
|
|
inCheckbox ? checkboxSettings : radioSettings,
|
2009-09-16 15:06:16 -07:00
|
|
|
VerticalAlignFactor(aFrame), mCellDrawView, NO);
|
2008-12-06 03:40:58 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const CellRenderSettings searchFieldSettings = {
|
|
|
|
{
|
|
|
|
NSMakeSize(0, 16), // mini
|
|
|
|
NSMakeSize(0, 19), // small
|
|
|
|
NSMakeSize(0, 22) // regular
|
|
|
|
},
|
|
|
|
{
|
|
|
|
NSMakeSize(32, 0), // mini
|
|
|
|
NSMakeSize(38, 0), // small
|
|
|
|
NSMakeSize(44, 0) // regular
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{ // Leopard
|
|
|
|
{0, 0, 0, 0}, // mini
|
|
|
|
{0, 0, 0, 0}, // small
|
|
|
|
{0, 0, 0, 0} // regular
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect,
|
2010-10-20 04:26:32 -07:00
|
|
|
nsIFrame* aFrame, nsEventStates inState)
|
2008-12-06 03:40:58 -08:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
NSSearchFieldCell* cell = mSearchFieldCell;
|
2010-09-27 18:25:18 -07:00
|
|
|
[cell setEnabled:!IsDisabled(aFrame, inState)];
|
2010-09-19 18:16:49 -07:00
|
|
|
// NOTE: this could probably use inState
|
2008-12-06 03:40:58 -08:00
|
|
|
[cell setShowsFirstResponder:IsFocused(aFrame)];
|
|
|
|
|
|
|
|
DrawCellWithSnapping(cell, cgContext, inBoxRect, searchFieldSettings,
|
2009-09-16 15:06:16 -07:00
|
|
|
VerticalAlignFactor(aFrame), mCellDrawView,
|
2009-04-17 01:12:12 -07:00
|
|
|
IsFrameRTL(aFrame));
|
2008-03-04 12:51:54 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
2008-01-13 20:48:33 -08:00
|
|
|
|
2009-01-12 11:22:59 -08:00
|
|
|
static const CellRenderSettings pushButtonSettings = {
|
|
|
|
{
|
|
|
|
NSMakeSize(0, 16), // mini
|
|
|
|
NSMakeSize(0, 19), // small
|
|
|
|
NSMakeSize(0, 22) // regular
|
|
|
|
},
|
|
|
|
{
|
|
|
|
NSMakeSize(18, 0), // mini
|
|
|
|
NSMakeSize(26, 0), // small
|
|
|
|
NSMakeSize(30, 0) // regular
|
2007-12-23 11:22:47 -08:00
|
|
|
},
|
2009-01-12 11:22:59 -08:00
|
|
|
{
|
|
|
|
{ // Leopard
|
|
|
|
{0, 0, 0, 0}, // mini
|
|
|
|
{4, 0, 4, 1}, // small
|
|
|
|
{5, 0, 5, 2} // regular
|
|
|
|
}
|
2007-12-23 11:22:47 -08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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
|
2009-01-18 03:05:38 -08:00
|
|
|
nsNativeThemeCocoa::DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect,
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates inState, nsIFrame* aFrame)
|
2007-12-23 11:22:47 -08:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-09-22 01:57:42 -07:00
|
|
|
BOOL isActive = FrameIsInActiveWindow(aFrame);
|
2010-09-27 18:25:18 -07:00
|
|
|
BOOL isDisabled = IsDisabled(aFrame, inState);
|
2008-09-22 01:57:42 -07:00
|
|
|
|
2010-09-19 18:16:49 -07:00
|
|
|
[mPushButtonCell setEnabled:!isDisabled];
|
2010-10-20 04:26:32 -07:00
|
|
|
[mPushButtonCell setHighlighted:isActive &&
|
|
|
|
inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)];
|
|
|
|
[mPushButtonCell setShowsFirstResponder:inState.HasState(NS_EVENT_STATE_FOCUS) && !isDisabled && isActive];
|
2008-01-08 18:52:36 -08:00
|
|
|
|
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.
|
2009-01-12 11:22:59 -08:00
|
|
|
if (inBoxRect.size.height > DO_SQUARE_BUTTON_HEIGHT) {
|
2007-12-23 11:22:47 -08:00
|
|
|
[mPushButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
|
2008-10-13 09:58:40 -07:00
|
|
|
DrawCellWithScaling(mPushButtonCell, cgContext, inBoxRect, NSRegularControlSize,
|
2009-04-17 01:12:12 -07:00
|
|
|
NSZeroSize, NSMakeSize(14, 0), NULL,
|
2009-09-16 15:06:16 -07:00
|
|
|
mCellDrawView, IsFrameRTL(aFrame));
|
2008-03-04 12:51:54 -08:00
|
|
|
} else {
|
2007-12-23 11:22:47 -08:00
|
|
|
[mPushButtonCell setBezelStyle:NSRoundedBezelStyle];
|
|
|
|
|
2009-01-12 11:22:59 -08:00
|
|
|
DrawCellWithSnapping(mPushButtonCell, cgContext, inBoxRect, pushButtonSettings,
|
2009-09-16 15:06:16 -07:00
|
|
|
0.5f, mCellDrawView, IsFrameRTL(aFrame), 1.0f);
|
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
|
|
|
}
|
|
|
|
|
2009-11-13 14:56:30 -08:00
|
|
|
typedef void (*RenderHIThemeControlFunction)(CGContextRef cgContext, const HIRect& aRenderRect, void* aData);
|
|
|
|
|
|
|
|
static void
|
|
|
|
RenderTransformedHIThemeControl(CGContextRef aCGContext, const HIRect& aRect,
|
|
|
|
RenderHIThemeControlFunction aFunc, void* aData,
|
|
|
|
BOOL mirrorHorizontally = NO)
|
|
|
|
{
|
|
|
|
CGAffineTransform savedCTM = CGContextGetCTM(aCGContext);
|
|
|
|
CGContextTranslateCTM(aCGContext, aRect.origin.x, aRect.origin.y);
|
|
|
|
|
|
|
|
PRBool drawDirect;
|
|
|
|
HIRect drawRect = aRect;
|
|
|
|
drawRect.origin = CGPointZero;
|
|
|
|
|
|
|
|
if (!mirrorHorizontally && savedCTM.a == 1.0f && savedCTM.b == 0.0f &&
|
|
|
|
savedCTM.c == 0.0f && (savedCTM.d == 1.0f || savedCTM.d == -1.0f)) {
|
|
|
|
drawDirect = TRUE;
|
|
|
|
} else {
|
|
|
|
drawDirect = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall back to no bitmap buffer if the area of our control (in pixels^2)
|
|
|
|
// is too large.
|
|
|
|
if (drawDirect || (aRect.size.width * aRect.size.height > BITMAP_MAX_AREA)) {
|
|
|
|
aFunc(aCGContext, drawRect, aData);
|
|
|
|
} else {
|
|
|
|
// Inflate the buffer to capture focus rings.
|
|
|
|
int w = ceil(drawRect.size.width) + 2 * MAX_FOCUS_RING_WIDTH;
|
|
|
|
int h = ceil(drawRect.size.height) + 2 * MAX_FOCUS_RING_WIDTH;
|
|
|
|
|
|
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
|
|
CGContextRef bitmapctx = CGBitmapContextCreate(NULL, w, h, 8, w * 4,
|
|
|
|
colorSpace,
|
|
|
|
kCGImageAlphaPremultipliedFirst);
|
|
|
|
CGColorSpaceRelease(colorSpace);
|
|
|
|
|
|
|
|
CGContextTranslateCTM(bitmapctx, MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH);
|
|
|
|
|
|
|
|
// HITheme always wants to draw into a flipped context, or things
|
|
|
|
// get confused.
|
|
|
|
CGContextTranslateCTM(bitmapctx, 0.0f, aRect.size.height);
|
|
|
|
CGContextScaleCTM(bitmapctx, 1.0f, -1.0f);
|
|
|
|
|
|
|
|
aFunc(bitmapctx, drawRect, aData);
|
|
|
|
|
|
|
|
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, aRect.size.height);
|
|
|
|
CGContextScaleCTM(aCGContext, 1.0f, -1.0f);
|
|
|
|
|
|
|
|
if (mirrorHorizontally) {
|
|
|
|
CGContextTranslateCTM(aCGContext, aRect.size.width, 0);
|
|
|
|
CGContextScaleCTM(aCGContext, -1.0f, 1.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
HIRect inflatedDrawRect = CGRectMake(-MAX_FOCUS_RING_WIDTH, -MAX_FOCUS_RING_WIDTH, w, h);
|
|
|
|
CGContextDrawImage(aCGContext, inflatedDrawRect, bitmap);
|
|
|
|
|
|
|
|
CGContextSetCTM(aCGContext, ctm);
|
|
|
|
|
|
|
|
CGImageRelease(bitmap);
|
|
|
|
CGContextRelease(bitmapctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
CGContextSetCTM(aCGContext, savedCTM);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
RenderButton(CGContextRef cgContext, const HIRect& aRenderRect, void* aData)
|
|
|
|
{
|
|
|
|
HIThemeButtonDrawInfo* bdi = (HIThemeButtonDrawInfo*)aData;
|
|
|
|
HIThemeDrawButton(&aRenderRect, bdi, cgContext, kHIThemeOrientationNormal, NULL);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
|
2010-09-19 18:16:49 -07:00
|
|
|
const HIRect& inBoxRect, PRBool inIsDefault,
|
2007-03-22 10:30:00 -07:00
|
|
|
ThemeButtonValue inValue, ThemeButtonAdornment inAdornment,
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates inState, nsIFrame* aFrame)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-09-22 01:57:42 -07:00
|
|
|
BOOL isActive = FrameIsInActiveWindow(aFrame);
|
2010-09-27 18:25:18 -07:00
|
|
|
BOOL isDisabled = IsDisabled(aFrame, inState);
|
2008-09-22 01:57:42 -07:00
|
|
|
|
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
|
|
|
|
2010-09-27 18:25:18 -07:00
|
|
|
if (isDisabled) {
|
2007-03-22 10:30:00 -07:00
|
|
|
bdi.state = kThemeStateUnavailable;
|
2008-09-22 01:57:42 -07:00
|
|
|
}
|
2010-10-20 04:26:32 -07:00
|
|
|
else if (inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
bdi.state = kThemeStatePressed;
|
2008-09-22 01:57:42 -07:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (inKind == kThemeArrowButton)
|
|
|
|
bdi.state = kThemeStateUnavailable; // these are always drawn as unavailable
|
2009-01-31 08:49:29 -08:00
|
|
|
else if (!isActive && inKind == kThemeListHeaderButton)
|
2008-09-22 01:57:42 -07:00
|
|
|
bdi.state = kThemeStateInactive;
|
|
|
|
else
|
|
|
|
bdi.state = kThemeStateActive;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-10-20 04:26:32 -07:00
|
|
|
if (inState.HasState(NS_EVENT_STATE_FOCUS) && isActive)
|
2007-03-22 10:30:00 -07:00
|
|
|
bdi.adornment |= kThemeAdornmentFocus;
|
|
|
|
|
2010-09-27 18:25:18 -07:00
|
|
|
if (inIsDefault && !isDisabled && isActive &&
|
2010-10-20 04:26:32 -07:00
|
|
|
!inState.HasState(NS_EVENT_STATE_ACTIVE)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
bdi.adornment |= kThemeAdornmentDefault;
|
2009-01-18 03:05:38 -08:00
|
|
|
bdi.animation.time.start = 0;
|
|
|
|
bdi.animation.time.current = CFAbsoluteTimeGetCurrent();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-12-23 11:22:47 -08:00
|
|
|
HIRect drawFrame = inBoxRect;
|
2008-03-19 16:01:34 -07:00
|
|
|
|
2009-01-18 03:05:38 -08:00
|
|
|
if (inKind == kThemePushButton) {
|
|
|
|
drawFrame.size.height -= 2;
|
|
|
|
if (inBoxRect.size.height < pushButtonSettings.naturalSizes[smallControlSize].height) {
|
|
|
|
bdi.kind = kThemePushButtonMini;
|
|
|
|
}
|
|
|
|
else if (inBoxRect.size.height < pushButtonSettings.naturalSizes[regularControlSize].height) {
|
|
|
|
bdi.kind = kThemePushButtonSmall;
|
|
|
|
drawFrame.origin.y -= 1;
|
|
|
|
drawFrame.origin.x += 1;
|
|
|
|
drawFrame.size.width -= 2;
|
|
|
|
}
|
|
|
|
}
|
2009-01-31 08:49:29 -08:00
|
|
|
else if (inKind == kThemeListHeaderButton) {
|
2008-11-27 14:14:54 -08:00
|
|
|
CGContextClipToRect(cgContext, inBoxRect);
|
|
|
|
// Always remove the top border.
|
|
|
|
drawFrame.origin.y -= 1;
|
|
|
|
drawFrame.size.height += 1;
|
|
|
|
// Remove the left border in LTR mode and the right border in RTL mode.
|
|
|
|
drawFrame.size.width += 1;
|
|
|
|
PRBool isLast = IsLastTreeHeaderCell(aFrame);
|
|
|
|
if (isLast)
|
|
|
|
drawFrame.size.width += 1; // Also remove the other border.
|
|
|
|
if (!IsFrameRTL(aFrame) || isLast)
|
|
|
|
drawFrame.origin.x -= 1;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-05-02 16:47:53 -07:00
|
|
|
|
2009-11-13 14:56:30 -08:00
|
|
|
RenderTransformedHIThemeControl(cgContext, drawFrame, RenderButton, &bdi,
|
|
|
|
IsFrameRTL(aFrame));
|
2008-03-19 16:01:34 -07:00
|
|
|
|
2009-01-31 08:49:29 -08:00
|
|
|
#if DRAW_IN_FRAME_DEBUG
|
|
|
|
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
|
|
|
|
CGContextFillRect(cgContext, inBoxRect);
|
|
|
|
#endif
|
2008-03-19 16:01:34 -07:00
|
|
|
|
2009-01-31 08:49:29 -08:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
2008-03-19 16:01:34 -07:00
|
|
|
|
2009-01-31 08:49:29 -08:00
|
|
|
static const CellRenderSettings dropdownSettings = {
|
|
|
|
{
|
|
|
|
NSMakeSize(0, 16), // mini
|
|
|
|
NSMakeSize(0, 19), // small
|
|
|
|
NSMakeSize(0, 22) // regular
|
|
|
|
},
|
|
|
|
{
|
|
|
|
NSMakeSize(18, 0), // mini
|
|
|
|
NSMakeSize(38, 0), // small
|
|
|
|
NSMakeSize(44, 0) // regular
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{ // Leopard
|
|
|
|
{1, 1, 2, 1}, // mini
|
|
|
|
{3, 0, 3, 1}, // small
|
|
|
|
{3, 0, 3, 0} // regular
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2008-03-19 16:01:34 -07:00
|
|
|
|
2009-02-11 07:54:10 -08:00
|
|
|
static const CellRenderSettings editableMenulistSettings = {
|
|
|
|
{
|
|
|
|
NSMakeSize(0, 15), // mini
|
|
|
|
NSMakeSize(0, 18), // small
|
|
|
|
NSMakeSize(0, 21) // regular
|
|
|
|
},
|
|
|
|
{
|
|
|
|
NSMakeSize(18, 0), // mini
|
|
|
|
NSMakeSize(38, 0), // small
|
|
|
|
NSMakeSize(44, 0) // regular
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{ // Leopard
|
|
|
|
{0, 0, 2, 2}, // mini
|
|
|
|
{0, 0, 3, 2}, // small
|
|
|
|
{0, 1, 3, 3} // regular
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-01-31 08:49:29 -08:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawDropdown(CGContextRef cgContext, const HIRect& inBoxRect,
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates inState, PRUint8 aWidgetType,
|
|
|
|
nsIFrame* aFrame)
|
2009-01-31 08:49:29 -08:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
2008-03-19 16:01:34 -07:00
|
|
|
|
2009-08-10 14:23:50 -07:00
|
|
|
[mDropdownCell setPullsDown:(aWidgetType == NS_THEME_BUTTON)];
|
|
|
|
|
|
|
|
BOOL isEditable = (aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD);
|
|
|
|
NSCell* cell = isEditable ? (NSCell*)mComboBoxCell : (NSCell*)mDropdownCell;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-09-27 18:25:18 -07:00
|
|
|
[cell setEnabled:!IsDisabled(aFrame, inState)];
|
2010-10-20 04:26:32 -07:00
|
|
|
[cell setShowsFirstResponder:(IsFocused(aFrame) || inState.HasState(NS_EVENT_STATE_FOCUS))];
|
2009-12-11 14:01:38 -08:00
|
|
|
[cell setHighlighted:IsOpenButton(aFrame)];
|
2009-02-11 07:54:10 -08:00
|
|
|
[cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)];
|
|
|
|
|
2009-08-10 14:23:50 -07:00
|
|
|
const CellRenderSettings& settings = isEditable ? editableMenulistSettings : dropdownSettings;
|
2009-02-11 07:54:10 -08:00
|
|
|
DrawCellWithSnapping(cell, cgContext, inBoxRect, settings,
|
2009-09-16 15:06:16 -07:00
|
|
|
0.5f, mCellDrawView, IsFrameRTL(aFrame));
|
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,
|
2010-09-19 18:16:49 -07:00
|
|
|
const HIRect& inBoxRect, ThemeDrawState inDrawState,
|
2007-08-27 21:05:12 -07:00
|
|
|
ThemeButtonAdornment inAdornment,
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates inState, nsIFrame* aFrame)
|
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.value = kThemeButtonOff;
|
|
|
|
bdi.adornment = inAdornment;
|
|
|
|
|
2010-09-27 18:25:18 -07:00
|
|
|
if (IsDisabled(aFrame, inState))
|
2007-03-22 10:30:00 -07:00
|
|
|
bdi.state = kThemeStateUnavailable;
|
2008-09-22 01:57:42 -07:00
|
|
|
else
|
|
|
|
bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind,
|
2010-10-20 04:26:32 -07:00
|
|
|
const HIRect& inBoxRect, PRBool inDisabled,
|
|
|
|
nsEventStates 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;
|
2008-09-22 01:57:42 -07:00
|
|
|
|
|
|
|
// We don't ever set an inactive state for this because it doesn't
|
|
|
|
// look right (see other apps).
|
2010-09-27 18:25:18 -07:00
|
|
|
fdi.state = inDisabled ? kThemeStateUnavailable : kThemeStateActive;
|
2008-09-22 01:57:42 -07:00
|
|
|
|
2008-02-07 03:39:04 -08:00
|
|
|
// for some reason focus rings on listboxes draw incorrectly
|
|
|
|
if (inKind == kHIThemeFrameListBox)
|
|
|
|
fdi.isFocused = 0;
|
|
|
|
else
|
2010-10-20 04:26:32 -07:00
|
|
|
fdi.isFocused = inState.HasState(NS_EVENT_STATE_FOCUS);
|
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
|
|
|
}
|
|
|
|
|
Back out bug 514437, bug 567872, bug 568825, bug 633209, bug 633913, bug 634086, bug 634088, bug 634549, bug 634551, bug 638176, bug 641517, bug 641905, bug 641942, bug 642127, and bug 642667 to undo the performance regression tracked by bug 655860.
2011-05-09 15:48:39 -07:00
|
|
|
static void
|
|
|
|
RenderProgress(CGContextRef cgContext, const HIRect& aRenderRect, void* aData)
|
|
|
|
{
|
|
|
|
HIThemeTrackDrawInfo* tdi = (HIThemeTrackDrawInfo*)aData;
|
|
|
|
tdi->bounds = aRenderRect;
|
|
|
|
HIThemeDrawTrack(tdi, NULL, cgContext, kHIThemeOrientationNormal);
|
|
|
|
}
|
2010-05-31 16:53:47 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
2008-09-22 01:57:42 -07:00
|
|
|
nsNativeThemeCocoa::DrawProgress(CGContextRef cgContext, const HIRect& inBoxRect,
|
|
|
|
PRBool inIsIndeterminate, PRBool inIsHorizontal,
|
Back out bug 514437, bug 567872, bug 568825, bug 633209, bug 633913, bug 634086, bug 634088, bug 634549, bug 634551, bug 638176, bug 641517, bug 641905, bug 641942, bug 642127, and bug 642667 to undo the performance regression tracked by bug 655860.
2011-05-09 15:48:39 -07:00
|
|
|
PRInt32 inValue, PRInt32 inMaxValue,
|
2008-10-30 02:34:23 -07:00
|
|
|
nsIFrame* aFrame)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-02-20 17:01:27 -08:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
Back out bug 514437, bug 567872, bug 568825, bug 633209, bug 633913, bug 634086, bug 634088, bug 634549, bug 634551, bug 638176, bug 641517, bug 641905, bug 641942, bug 642127, and bug 642667 to undo the performance regression tracked by bug 655860.
2011-05-09 15:48:39 -07:00
|
|
|
HIThemeTrackDrawInfo tdi;
|
2008-04-07 15:56:43 -07:00
|
|
|
|
Back out bug 514437, bug 567872, bug 568825, bug 633209, bug 633913, bug 634086, bug 634088, bug 634549, bug 634551, bug 638176, bug 641517, bug 641905, bug 641942, bug 642127, and bug 642667 to undo the performance regression tracked by bug 655860.
2011-05-09 15:48:39 -07:00
|
|
|
PRInt32 stepsPerSecond = inIsIndeterminate ? 60 : 30;
|
|
|
|
PRInt32 milliSecondsPerStep = 1000 / stepsPerSecond;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Back out bug 514437, bug 567872, bug 568825, bug 633209, bug 633913, bug 634086, bug 634088, bug 634549, bug 634551, bug 638176, bug 641517, bug 641905, bug 641942, bug 642127, and bug 642667 to undo the performance regression tracked by bug 655860.
2011-05-09 15:48:39 -07:00
|
|
|
tdi.version = 0;
|
|
|
|
tdi.kind = inIsIndeterminate ? kThemeMediumIndeterminateBar: kThemeMediumProgressBar;
|
|
|
|
tdi.bounds = inBoxRect;
|
|
|
|
tdi.min = 0;
|
|
|
|
tdi.max = inMaxValue;
|
|
|
|
tdi.value = inValue;
|
|
|
|
tdi.attributes = inIsHorizontal ? kThemeTrackHorizontal : 0;
|
|
|
|
tdi.enableState = FrameIsInActiveWindow(aFrame) ? kThemeTrackActive : kThemeTrackInactive;
|
|
|
|
tdi.trackInfo.progress.phase = PR_IntervalToMilliseconds(PR_IntervalNow()) /
|
|
|
|
milliSecondsPerStep % 16;
|
|
|
|
|
|
|
|
RenderTransformedHIThemeControl(cgContext, inBoxRect, RenderProgress, &tdi,
|
|
|
|
IsFrameRTL(aFrame));
|
2008-02-20 17:01:27 -08:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-22 01:57:42 -07:00
|
|
|
nsNativeThemeCocoa::DrawTabPanel(CGContextRef cgContext, const HIRect& inBoxRect,
|
|
|
|
nsIFrame* aFrame)
|
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;
|
|
|
|
|
2008-11-27 14:16:13 -08:00
|
|
|
tpdi.version = 1;
|
2008-09-22 01:57:42 -07:00
|
|
|
tpdi.state = FrameIsInActiveWindow(aFrame) ? kThemeStateActive : kThemeStateInactive;
|
2007-03-22 10:30:00 -07:00
|
|
|
tpdi.direction = kThemeTabNorth;
|
|
|
|
tpdi.size = kHIThemeTabSizeNormal;
|
2008-11-27 14:16:13 -08:00
|
|
|
tpdi.kind = kHIThemeTabKindNormal;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
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,
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates inState, PRBool inIsVertical,
|
2010-09-19 18:16:49 -07:00
|
|
|
PRBool inIsReverse, PRInt32 inCurrentValue,
|
|
|
|
PRInt32 inMinValue, PRInt32 inMaxValue,
|
|
|
|
nsIFrame* aFrame)
|
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;
|
2010-10-20 04:26:32 -07:00
|
|
|
if (inState.HasState(NS_EVENT_STATE_FOCUS))
|
2007-03-22 10:30:00 -07:00
|
|
|
tdi.attributes |= kThemeTrackHasFocus;
|
2010-09-27 18:25:18 -07:00
|
|
|
if (IsDisabled(aFrame, inState))
|
2008-09-22 01:57:42 -07:00
|
|
|
tdi.enableState = kThemeTrackDisabled;
|
|
|
|
else
|
|
|
|
tdi.enableState = FrameIsInActiveWindow(aFrame) ? kThemeTrackActive : kThemeTrackInactive;
|
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
|
|
|
}
|
|
|
|
|
2008-11-27 14:16:13 -08:00
|
|
|
#define NATURAL_MINI_TAB_BUTTON_HEIGHT 17
|
|
|
|
#define NATURAL_SMALL_TAB_BUTTON_HEIGHT 20
|
|
|
|
#define NATURAL_REGULAR_TAB_BUTTON_HEIGHT 23
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
2008-11-27 14:16:13 -08:00
|
|
|
nsNativeThemeCocoa::DrawTab(CGContextRef cgContext, HIRect inBoxRect,
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates inState, nsIFrame* aFrame)
|
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;
|
2008-11-27 14:16:13 -08:00
|
|
|
tdi.version = 1;
|
2009-03-02 06:52:17 -08:00
|
|
|
tdi.kind = kHIThemeTabKindNormal;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-11-27 14:16:13 -08:00
|
|
|
PRBool isSelected = IsSelectedTab(aFrame);
|
2010-09-27 18:25:18 -07:00
|
|
|
PRBool isDisabled = IsDisabled(aFrame, inState);
|
|
|
|
|
2008-11-27 14:16:13 -08:00
|
|
|
if (isSelected) {
|
2010-09-27 18:25:18 -07:00
|
|
|
if (isDisabled)
|
2007-03-22 10:30:00 -07:00
|
|
|
tdi.style = kThemeTabFrontUnavailable;
|
|
|
|
else
|
2008-09-22 01:57:42 -07:00
|
|
|
tdi.style = FrameIsInActiveWindow(aFrame) ? kThemeTabFront : kThemeTabFrontInactive;
|
2007-03-22 10:30:00 -07:00
|
|
|
} else {
|
2010-09-27 18:25:18 -07:00
|
|
|
if (isDisabled)
|
2007-03-22 10:30:00 -07:00
|
|
|
tdi.style = kThemeTabNonFrontUnavailable;
|
2010-10-20 04:26:32 -07:00
|
|
|
else if (inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER))
|
2007-03-22 10:30:00 -07:00
|
|
|
tdi.style = kThemeTabNonFrontPressed;
|
|
|
|
else
|
2008-09-22 01:57:42 -07:00
|
|
|
tdi.style = FrameIsInActiveWindow(aFrame) ? kThemeTabNonFront : kThemeTabNonFrontInactive;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-11-27 14:16:13 -08:00
|
|
|
tdi.direction = kThemeTabNorth;
|
2007-03-22 10:30:00 -07:00
|
|
|
tdi.size = kHIThemeTabSizeNormal;
|
2008-11-27 14:16:13 -08:00
|
|
|
if (inBoxRect.size.height < NATURAL_REGULAR_TAB_BUTTON_HEIGHT)
|
|
|
|
tdi.size = kHIThemeTabSizeSmall;
|
|
|
|
if (inBoxRect.size.height < NATURAL_SMALL_TAB_BUTTON_HEIGHT)
|
|
|
|
tdi.size = kHIThemeTabSizeMini;
|
|
|
|
|
|
|
|
PRBool isRTL = IsFrameRTL(aFrame);
|
|
|
|
PRBool isFirst = isRTL ? IsLastTab(aFrame) : IsFirstTab(aFrame);
|
|
|
|
PRBool isLast = isRTL ? IsFirstTab(aFrame) : IsLastTab(aFrame);
|
|
|
|
|
|
|
|
if (isFirst && isLast)
|
|
|
|
tdi.position = kHIThemeTabPositionOnly;
|
|
|
|
else if (isFirst)
|
|
|
|
tdi.position = kHIThemeTabPositionFirst;
|
|
|
|
else if (isLast)
|
|
|
|
tdi.position = kHIThemeTabPositionLast;
|
|
|
|
else
|
|
|
|
tdi.position = kHIThemeTabPositionMiddle;
|
|
|
|
|
|
|
|
// Tab separator management:
|
|
|
|
// Normal tabs only draw their left separator, in the leftmost pixel row of
|
|
|
|
// their frame. Selected tabs additionally draw their right separator, outside
|
|
|
|
// of their frame. To prevent overlapping, the tab to the right of the
|
|
|
|
// selected tab shouldn't draw its left separator.
|
|
|
|
tdi.adornment = kHIThemeTabAdornmentNone;
|
|
|
|
if (isRTL ? IsBeforeSelectedTab(aFrame) : IsAfterSelectedTab(aFrame)) {
|
2010-02-23 15:30:39 -08:00
|
|
|
// On Leopard, the tab's left edge must be shifted 1px to the right.
|
|
|
|
// On Tiger, this happens automatically when no leading separator is drawn.
|
|
|
|
inBoxRect.origin.x += 1;
|
|
|
|
inBoxRect.size.width -= 1;
|
2008-11-27 14:16:13 -08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
tdi.adornment = kHIThemeTabAdornmentLeadingSeparator;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isSelected && !isLast) {
|
|
|
|
tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
|
2010-02-23 15:30:39 -08:00
|
|
|
// On Tiger, the right separator is drawn outside of the frame.
|
|
|
|
// On Leopard, the right edge must be shifted 1px to the right.
|
|
|
|
inBoxRect.size.width += 1;
|
2008-11-27 14:16:13 -08:00
|
|
|
}
|
|
|
|
|
2010-10-20 04:26:32 -07:00
|
|
|
if (inState.HasState(NS_EVENT_STATE_FOCUS))
|
2008-11-27 14:16:13 -08:00
|
|
|
tdi.adornment |= kThemeAdornmentFocus;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-03-04 12:51:54 -08:00
|
|
|
static inline UInt8
|
2010-10-20 04:26:32 -07:00
|
|
|
ConvertToPressState(nsEventStates aButtonState, UInt8 aPressState)
|
2007-04-10 17:25:11 -07:00
|
|
|
{
|
|
|
|
// If the button is pressed, return the press state passed in. Otherwise, return 0.
|
2010-10-20 04:26:32 -07:00
|
|
|
return aButtonState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER) ? aPressState : 0;
|
2007-04-10 17:25:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-10-20 04:26:32 -07:00
|
|
|
nsNativeThemeCocoa::GetScrollbarPressStates(nsIFrame *aFrame, nsEventStates aButtonStates[])
|
2007-04-10 17:25:11 -07:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2010-10-20 04:26:32 -07:00
|
|
|
aButtonStates[attrIndex] = GetContentState(childFrame, NS_THEME_BUTTON);
|
2007-04-10 17:25:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
2009-09-27 14:58:15 -07:00
|
|
|
const CGSize& aSize, PRBool aShouldGetButtonStates)
|
2007-04-10 17:25:11 -07:00
|
|
|
{
|
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;
|
2009-09-27 14:58:15 -07:00
|
|
|
aTdi.bounds.origin = CGPointZero;
|
|
|
|
aTdi.bounds.size = aSize;
|
2007-04-10 17:25:11 -07:00
|
|
|
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-09-22 01:57:42 -07:00
|
|
|
// This should be done early on so things like "kThemeTrackNothingToScroll" can
|
|
|
|
// override the active enable state.
|
|
|
|
aTdi.enableState = FrameIsInActiveWindow(aFrame) ? kThemeTrackActive : kThemeTrackInactive;
|
|
|
|
|
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).
|
|
|
|
*/
|
2009-09-27 14:58:15 -07:00
|
|
|
PRInt32 longSideLength = (PRInt32)(isHorizontal ? (aSize.width) : (aSize.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;
|
|
|
|
}
|
|
|
|
|
2009-03-09 15:03:16 -07:00
|
|
|
aTdi.trackInfo.scrollbar.pressState = 0;
|
|
|
|
|
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) {
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates buttonStates[4];
|
2007-04-10 17:25:11 -07:00
|
|
|
GetScrollbarPressStates(aFrame, buttonStates);
|
2009-09-22 01:01:35 -07:00
|
|
|
NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
|
|
|
|
// It seems that unless all four buttons are showing, kThemeTopOutsideArrowPressed is the correct constant for
|
|
|
|
// the up scrollbar button.
|
|
|
|
if ([buttonPlacement isEqualToString:@"DoubleBoth"]) {
|
2007-04-10 17:25:11 -07:00
|
|
|
aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) |
|
|
|
|
ConvertToPressState(buttonStates[1], kThemeTopInsideArrowPressed) |
|
|
|
|
ConvertToPressState(buttonStates[2], kThemeBottomInsideArrowPressed) |
|
|
|
|
ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed);
|
|
|
|
} else {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-09-27 14:58:15 -07:00
|
|
|
static void
|
2009-11-13 14:56:30 -08:00
|
|
|
RenderScrollbar(CGContextRef cgContext, const HIRect& aRenderRect, void* aData)
|
2009-09-27 14:58:15 -07:00
|
|
|
{
|
|
|
|
HIThemeTrackDrawInfo* tdi = (HIThemeTrackDrawInfo*)aData;
|
|
|
|
HIThemeDrawTrack(tdi, NULL, cgContext, HITHEME_ORIENTATION);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawScrollbar(CGContextRef aCGContext, const HIRect& aBoxRect, nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
HIThemeTrackDrawInfo tdi;
|
|
|
|
GetScrollbarDrawInfo(tdi, aFrame, aBoxRect.size, PR_TRUE); // True means we want the press states
|
|
|
|
RenderTransformedHIThemeControl(aCGContext, aBoxRect, RenderScrollbar, &tdi);
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-07-24 02:35:29 -07:00
|
|
|
static PRBool
|
2009-12-30 07:23:51 -08:00
|
|
|
ToolbarCanBeUnified(CGContextRef cgContext, const HIRect& inBoxRect, NSWindow* aWindow)
|
|
|
|
{
|
2010-07-24 02:35:29 -07:00
|
|
|
if (![aWindow isKindOfClass:[ToolbarWindow class]] ||
|
|
|
|
[(ToolbarWindow*)aWindow drawsContentsIntoWindowFrame])
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
float unifiedToolbarHeight = [(ToolbarWindow*)aWindow unifiedToolbarHeight];
|
|
|
|
return inBoxRect.origin.x == 0 &&
|
|
|
|
inBoxRect.size.width == [aWindow frame].size.width &&
|
|
|
|
inBoxRect.origin.y <= 0.0 &&
|
|
|
|
inBoxRect.origin.y + inBoxRect.size.height <= unifiedToolbarHeight;
|
2009-12-30 07:23:51 -08:00
|
|
|
}
|
|
|
|
|
2008-09-16 01:21:06 -07:00
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect,
|
2009-12-30 07:23:51 -08:00
|
|
|
NSWindow* aWindow)
|
2008-09-16 01:21:06 -07:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2010-07-24 02:35:29 -07:00
|
|
|
float titlebarHeight = [(ToolbarWindow*)aWindow titlebarHeight];
|
2008-09-16 01:21:06 -07:00
|
|
|
|
2009-12-30 07:23:51 -08:00
|
|
|
BOOL isMain = [aWindow isMainWindow] || ![NSView focusView];
|
2008-09-16 01:21:06 -07:00
|
|
|
|
|
|
|
// Draw the gradient
|
|
|
|
UnifiedGradientInfo info = { titlebarHeight, inBoxRect.size.height, isMain, NO };
|
2008-10-15 06:01:10 -07:00
|
|
|
struct CGFunctionCallbacks callbacks = { 0, nsCocoaWindow::UnifiedShading, NULL };
|
2008-09-16 01:21:06 -07:00
|
|
|
CGFunctionRef function = CGFunctionCreate(&info, 1, NULL, 4, NULL, &callbacks);
|
|
|
|
float srcY = inBoxRect.origin.y;
|
|
|
|
float dstY = srcY + inBoxRect.size.height - 1;
|
|
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
|
|
CGShadingRef shading = CGShadingCreateAxial(colorSpace,
|
|
|
|
CGPointMake(0, srcY),
|
|
|
|
CGPointMake(0, dstY), function,
|
|
|
|
NO, NO);
|
|
|
|
CGColorSpaceRelease(colorSpace);
|
|
|
|
CGFunctionRelease(function);
|
|
|
|
CGContextClipToRect(cgContext, inBoxRect);
|
|
|
|
CGContextDrawShading(cgContext, shading);
|
|
|
|
CGShadingRelease(shading);
|
|
|
|
|
|
|
|
// Draw the border at the bottom of the toolbar.
|
2009-08-03 15:27:31 -07:00
|
|
|
CGRect borderRect = CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y +
|
|
|
|
inBoxRect.size.height - 1.0f,
|
|
|
|
inBoxRect.size.width, 1.0f);
|
|
|
|
DrawNativeGreyColorInRect(cgContext, headerBorderGrey, borderRect, isMain);
|
2008-09-16 01:21:06 -07:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2009-01-06 07:46:59 -08:00
|
|
|
struct GreyGradientInfo {
|
|
|
|
float startGrey;
|
|
|
|
float endGrey;
|
|
|
|
};
|
|
|
|
|
2009-09-22 01:01:35 -07:00
|
|
|
static void GreyGradientCallback(void* aInfo, const CGFloat* aIn, CGFloat* aOut)
|
2009-01-06 07:46:59 -08:00
|
|
|
{
|
|
|
|
GreyGradientInfo* info = static_cast<GreyGradientInfo*>(aInfo);
|
2009-09-22 01:01:35 -07:00
|
|
|
CGFloat result = (1.0f - *aIn) * info->startGrey + *aIn * info->endGrey;
|
2009-01-06 07:46:59 -08:00
|
|
|
aOut[0] = result;
|
|
|
|
aOut[1] = result;
|
|
|
|
aOut[2] = result;
|
|
|
|
aOut[3] = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DrawGreyGradient(CGContextRef cgContext, const HIRect& rect,
|
|
|
|
float startGrey, float endGrey)
|
|
|
|
{
|
|
|
|
if (rect.size.height <= 0.0f)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GreyGradientInfo info = { startGrey, endGrey };
|
|
|
|
struct CGFunctionCallbacks callbacks = { 0, GreyGradientCallback, NULL };
|
|
|
|
CGFunctionRef function = CGFunctionCreate(&info, 1, NULL, 4, NULL, &callbacks);
|
|
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
|
|
CGShadingRef shading = CGShadingCreateAxial(colorSpace,
|
|
|
|
CGPointMake(0, CGRectGetMinY(rect)),
|
|
|
|
CGPointMake(0, CGRectGetMaxY(rect)),
|
|
|
|
function, false, false);
|
|
|
|
CGColorSpaceRelease(colorSpace);
|
|
|
|
CGFunctionRelease(function);
|
|
|
|
CGContextSaveGState(cgContext);
|
|
|
|
CGContextClipToRect(cgContext, rect);
|
|
|
|
CGContextDrawShading(cgContext, shading);
|
|
|
|
CGContextRestoreGState(cgContext);
|
|
|
|
CGShadingRelease(shading);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect,
|
|
|
|
nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (inBoxRect.size.height < 2.0f)
|
|
|
|
return;
|
|
|
|
|
2009-08-03 15:27:31 -07:00
|
|
|
BOOL isMain = [NativeWindowForFrame(aFrame) isMainWindow] || ![NSView focusView];
|
2009-01-06 07:46:59 -08:00
|
|
|
|
|
|
|
// Draw the borders at the top of the statusbar.
|
2009-08-03 15:27:31 -07:00
|
|
|
CGRect rect = CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y,
|
|
|
|
inBoxRect.size.width, 1.0f);
|
|
|
|
DrawNativeGreyColorInRect(cgContext, statusbarFirstTopBorderGrey, rect, isMain);
|
|
|
|
rect.origin.y += 1.0f;
|
|
|
|
DrawNativeGreyColorInRect(cgContext, statusbarSecondTopBorderGrey, rect, isMain);
|
2009-01-06 07:46:59 -08:00
|
|
|
|
|
|
|
// Draw the gradient.
|
|
|
|
DrawGreyGradient(cgContext, CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y + 2.0f,
|
|
|
|
inBoxRect.size.width, inBoxRect.size.height - 2.0f),
|
|
|
|
NativeGreyColorAsFloat(statusbarGradientStartGrey, isMain),
|
|
|
|
NativeGreyColorAsFloat(statusbarGradientEndGrey, isMain));
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2009-09-27 14:58:58 -07:00
|
|
|
static void
|
2009-11-13 14:56:30 -08:00
|
|
|
RenderResizer(CGContextRef cgContext, const HIRect& aRenderRect, void* aData)
|
2009-09-27 14:58:58 -07:00
|
|
|
{
|
|
|
|
HIThemeGrowBoxDrawInfo* drawInfo = (HIThemeGrowBoxDrawInfo*)aData;
|
|
|
|
HIThemeDrawGrowBox(&CGPointZero, drawInfo, cgContext, kHIThemeOrientationNormal);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsNativeThemeCocoa::DrawResizer(CGContextRef cgContext, const HIRect& aRect,
|
|
|
|
nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
HIThemeGrowBoxDrawInfo drawInfo;
|
|
|
|
drawInfo.version = 0;
|
|
|
|
drawInfo.state = kThemeStateActive;
|
|
|
|
drawInfo.kind = kHIThemeGrowBoxKindNormal;
|
|
|
|
drawInfo.direction = kThemeGrowRight | kThemeGrowDown;
|
|
|
|
drawInfo.size = kHIThemeGrowBoxSizeNormal;
|
|
|
|
|
|
|
|
RenderTransformedHIThemeControl(cgContext, aRect, RenderResizer, &drawInfo,
|
|
|
|
IsFrameRTL(aFrame));
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
2011-04-07 18:04:40 -07:00
|
|
|
nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
|
|
|
const nsRect& aRect,
|
2008-07-24 16:01:59 -07:00
|
|
|
const nsRect& aDirtyRect)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
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
|
2011-04-07 18:04:40 -07:00
|
|
|
PRInt32 p2a = aContext->AppUnitsPerDevPixel();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-04-07 18:04:40 -07:00
|
|
|
gfxRect nativeDirtyRect(aDirtyRect.x, aDirtyRect.y,
|
|
|
|
aDirtyRect.width, aDirtyRect.height);
|
2008-02-20 03:33:27 -08:00
|
|
|
gfxRect nativeWidgetRect(aRect.x, aRect.y, aRect.width, aRect.height);
|
|
|
|
nativeWidgetRect.ScaleInverse(gfxFloat(p2a));
|
2008-07-24 16:01:59 -07:00
|
|
|
nativeDirtyRect.ScaleInverse(gfxFloat(p2a));
|
2008-07-27 09:08:51 -07:00
|
|
|
nativeWidgetRect.Round();
|
2008-10-22 09:39:08 -07:00
|
|
|
if (nativeWidgetRect.IsEmpty())
|
|
|
|
return NS_OK; // Don't attempt to draw invisible widgets.
|
2008-02-20 03:33:27 -08:00
|
|
|
|
2011-04-07 18:04:40 -07:00
|
|
|
gfxContext* thebesCtx = aContext->ThebesContext();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!thebesCtx)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2008-07-24 16:01:59 -07:00
|
|
|
gfxQuartzNativeDrawing nativeDrawing(thebesCtx, nativeDirtyRect);
|
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
|
|
|
|
|
2008-07-27 09:08:51 -07:00
|
|
|
CGRect macRect = CGRectMake(nativeWidgetRect.X(), nativeWidgetRect.Y(),
|
|
|
|
nativeWidgetRect.Width(), nativeWidgetRect.Height());
|
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
|
|
|
|
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates eventState = GetContentState(aFrame, aWidgetType);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
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,
|
2010-09-27 18:25:18 -07:00
|
|
|
menuType: IsDisabled(aFrame, eventState) ? kThemeMenuTypeInactive
|
|
|
|
: kThemeMenuTypePopUp
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
2009-01-12 11:23:51 -08:00
|
|
|
|
|
|
|
PRBool isLeftOfParent = PR_FALSE;
|
|
|
|
if (IsSubmenu(aFrame, &isLeftOfParent) && !isLeftOfParent) {
|
|
|
|
mdi.menuType = kThemeMenuTypeHierarchical;
|
|
|
|
}
|
|
|
|
|
2008-12-11 06:37:38 -08:00
|
|
|
// The rounded corners draw outside the frame.
|
|
|
|
CGRect deflatedRect = CGRectMake(macRect.origin.x, macRect.origin.y + 4,
|
|
|
|
macRect.size.width, macRect.size.height - 8);
|
|
|
|
HIThemeDrawMenuBackground(&deflatedRect, &mdi, cgContext, HITHEME_ORIENTATION);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_MENUITEM: {
|
2008-12-15 12:27:30 -08:00
|
|
|
// Clear the background to get correct transparency.
|
|
|
|
CGContextClearRect(cgContext, macRect);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// maybe use kThemeMenuItemHierBackground or PopUpBackground instead of just Plain?
|
|
|
|
HIThemeMenuItemDrawInfo drawInfo = {
|
|
|
|
version: 0,
|
|
|
|
itemType: kThemeMenuItemPlain,
|
2010-09-27 18:25:18 -07:00
|
|
|
state: (IsDisabled(aFrame, eventState) ? kThemeMenuDisabled :
|
2010-09-19 18:16:49 -07:00
|
|
|
CheckBooleanAttr(aFrame, nsWidgetAtoms::mozmenuactive) ? kThemeMenuSelected :
|
|
|
|
kThemeMenuActive)
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
// 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;
|
2010-09-27 18:25:18 -07:00
|
|
|
if (IsDisabled(aFrame, eventState)) {
|
2008-02-24 05:41:22 -08:00
|
|
|
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:
|
2009-11-13 14:58:59 -08:00
|
|
|
CGContextSetRGBFillColor(cgContext, 0.996, 1.000, 0.792, 0.950);
|
2007-03-22 10:30:00 -07:00
|
|
|
CGContextFillRect(cgContext, macRect);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_CHECKBOX:
|
2008-11-03 05:12:59 -08:00
|
|
|
case NS_THEME_RADIO: {
|
|
|
|
PRBool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX);
|
2008-10-13 09:58:40 -07:00
|
|
|
DrawCheckboxOrRadio(cgContext, isCheckbox, macRect, GetCheckedOrSelected(aFrame, !isCheckbox),
|
2010-09-19 18:16:49 -07:00
|
|
|
eventState, aFrame);
|
2008-10-13 09:58:40 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_BUTTON:
|
2009-01-18 03:05:38 -08:00
|
|
|
if (IsDefaultButton(aFrame)) {
|
2010-11-13 00:19:38 -08:00
|
|
|
if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 10)) {
|
|
|
|
NS_WARNING("Unable to animate button!");
|
|
|
|
}
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawButton(cgContext, kThemePushButton, macRect, true,
|
2009-01-18 03:05:38 -08:00
|
|
|
kThemeButtonOff, kThemeAdornmentNone, eventState, aFrame);
|
2009-08-10 14:23:50 -07:00
|
|
|
} else if (IsButtonTypeMenu(aFrame)) {
|
|
|
|
DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame);
|
2009-01-18 03:05:38 -08:00
|
|
|
} else {
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawPushButton(cgContext, macRect, eventState, aFrame);
|
2009-01-18 03:05:38 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_BUTTON_BEVEL:
|
|
|
|
DrawButton(cgContext, kThemeMediumBevelButton, macRect,
|
2010-09-19 18:16:49 -07:00
|
|
|
IsDefaultButton(aFrame), kThemeButtonOff, kThemeAdornmentNone,
|
|
|
|
eventState, aFrame);
|
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;
|
|
|
|
}
|
|
|
|
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawSpinButtons(cgContext, kThemeIncDecButton, macRect, state,
|
|
|
|
kThemeAdornmentNone, eventState, aFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TOOLBAR_BUTTON:
|
|
|
|
DrawButton(cgContext, kThemePushButton, macRect,
|
2010-09-19 18:16:49 -07:00
|
|
|
IsDefaultButton(aFrame), kThemeButtonOn, kThemeAdornmentNone,
|
|
|
|
eventState, aFrame);
|
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;
|
|
|
|
|
2008-09-16 01:21:06 -07:00
|
|
|
case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
|
2008-12-11 06:48:13 -08:00
|
|
|
case NS_THEME_TOOLBAR: {
|
2009-12-30 07:23:51 -08:00
|
|
|
NSWindow* win = NativeWindowForFrame(aFrame);
|
|
|
|
if (ToolbarCanBeUnified(cgContext, macRect, win)) {
|
|
|
|
DrawUnifiedToolbar(cgContext, macRect, win);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
BOOL isMain = [win isMainWindow] || ![NSView focusView];
|
2009-08-03 15:27:31 -07:00
|
|
|
CGRect drawRect = macRect;
|
2008-12-11 06:48:13 -08:00
|
|
|
|
|
|
|
// top border
|
2009-08-03 15:27:31 -07:00
|
|
|
drawRect.size.height = 1.0f;
|
|
|
|
DrawNativeGreyColorInRect(cgContext, toolbarTopBorderGrey, drawRect, isMain);
|
2008-12-11 06:48:13 -08:00
|
|
|
|
|
|
|
// background
|
2009-08-03 15:27:31 -07:00
|
|
|
drawRect.origin.y += drawRect.size.height;
|
|
|
|
drawRect.size.height = macRect.size.height - 2.0f;
|
|
|
|
DrawNativeGreyColorInRect(cgContext, headerEndGrey, drawRect, isMain);
|
2008-12-11 06:48:13 -08:00
|
|
|
|
|
|
|
// bottom border
|
2009-08-03 15:27:31 -07:00
|
|
|
drawRect.origin.y += drawRect.size.height;
|
|
|
|
drawRect.size.height = 1.0f;
|
|
|
|
DrawNativeGreyColorInRect(cgContext, headerBorderGrey, drawRect, isMain);
|
2008-12-11 06:48:13 -08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2009-01-06 07:46:59 -08:00
|
|
|
case NS_THEME_TOOLBOX: {
|
2007-03-22 10:30:00 -07:00
|
|
|
HIThemeHeaderDrawInfo hdi = { 0, kThemeStateActive, kHIThemeHeaderKindWindow };
|
|
|
|
HIThemeDrawHeader(&macRect, &hdi, cgContext, HITHEME_ORIENTATION);
|
|
|
|
}
|
|
|
|
break;
|
2009-01-06 07:46:59 -08:00
|
|
|
|
|
|
|
case NS_THEME_STATUSBAR:
|
|
|
|
DrawStatusBar(cgContext, macRect, aFrame);
|
|
|
|
break;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_DROPDOWN:
|
2009-02-11 07:54:10 -08:00
|
|
|
case NS_THEME_DROPDOWN_TEXTFIELD:
|
2009-08-10 14:23:50 -07:00
|
|
|
DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawButton(cgContext, kThemeArrowButton, macRect, PR_FALSE, kThemeButtonOn,
|
2008-09-22 01:57:42 -07:00
|
|
|
kThemeAdornmentArrowDownArrow, eventState, aFrame);
|
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.
|
2010-04-21 07:53:42 -07:00
|
|
|
// On Mac, focus rings are always shown for textboxes, so we do not need
|
|
|
|
// to check the window's focus ring state here
|
2009-08-24 13:02:07 -07:00
|
|
|
if (aFrame->GetContent()->IsXUL() && IsFocused(aFrame)) {
|
2008-02-07 13:54:24 -08:00
|
|
|
eventState |= NS_EVENT_STATE_FOCUS;
|
|
|
|
}
|
|
|
|
|
2010-09-27 18:25:18 -07:00
|
|
|
DrawFrame(cgContext, kHIThemeFrameTextFieldSquare, macRect,
|
|
|
|
IsDisabled(aFrame, eventState) || IsReadOnly(aFrame), eventState);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
2008-12-06 03:40:58 -08:00
|
|
|
case NS_THEME_SEARCHFIELD:
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawSearchField(cgContext, macRect, aFrame, eventState);
|
2008-12-06 03:40:58 -08:00
|
|
|
break;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_PROGRESSBAR:
|
2010-11-13 00:19:38 -08:00
|
|
|
if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) {
|
|
|
|
NS_WARNING("Unable to animate progressbar!");
|
|
|
|
}
|
Back out bug 514437, bug 567872, bug 568825, bug 633209, bug 633913, bug 634086, bug 634088, bug 634549, bug 634551, bug 638176, bug 641517, bug 641905, bug 641942, bug 642127, and bug 642667 to undo the performance regression tracked by bug 655860.
2011-05-09 15:48:39 -07:00
|
|
|
DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame),
|
2008-10-30 02:34:23 -07:00
|
|
|
PR_TRUE, GetProgressValue(aFrame),
|
|
|
|
GetProgressMaxValue(aFrame), aFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_PROGRESSBAR_VERTICAL:
|
Back out bug 514437, bug 567872, bug 568825, bug 633209, bug 633913, bug 634086, bug 634088, bug 634549, bug 634551, bug 638176, bug 641517, bug 641905, bug 641942, bug 642127, and bug 642667 to undo the performance regression tracked by bug 655860.
2011-05-09 15:48:39 -07:00
|
|
|
DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame),
|
2008-10-30 02:34:23 -07:00
|
|
|
PR_FALSE, GetProgressValue(aFrame),
|
|
|
|
GetProgressMaxValue(aFrame), 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:
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawButton(cgContext, kThemeDisclosureButton, macRect, PR_FALSE,
|
2008-09-22 01:57:42 -07:00
|
|
|
kThemeDisclosureRight, kThemeAdornmentNone, eventState, aFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_TWISTY_OPEN:
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawButton(cgContext, kThemeDisclosureButton, macRect, PR_FALSE,
|
2008-09-22 01:57:42 -07:00
|
|
|
kThemeDisclosureDown, kThemeAdornmentNone, eventState, aFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TREEVIEW_HEADER_CELL: {
|
|
|
|
TreeSortDirection sortDirection = GetTreeSortDirection(aFrame);
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawButton(cgContext, kThemeListHeaderButton, macRect, PR_FALSE,
|
2007-03-22 10:30:00 -07:00
|
|
|
sortDirection == eTreeSortDirection_Natural ? kThemeButtonOff : kThemeButtonOn,
|
2008-11-27 14:14:54 -08:00
|
|
|
sortDirection == eTreeSortDirection_Ascending ?
|
2010-09-19 18:16:49 -07:00
|
|
|
kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone, eventState, aFrame);
|
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);
|
2010-09-19 18:16:49 -07:00
|
|
|
DrawScale(cgContext, macRect, eventState,
|
2007-04-09 15:39:57 -07:00
|
|
|
(aWidgetType == NS_THEME_SCALE_VERTICAL), reverse,
|
2008-09-22 01:57:42 -07:00
|
|
|
curpos, minpos, maxpos, aFrame);
|
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
|
2010-10-20 04:26:32 -07:00
|
|
|
if (eventState.HasState(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;
|
|
|
|
|
2010-08-02 06:24:53 -07:00
|
|
|
case NS_THEME_LISTBOX: {
|
|
|
|
// We have to draw this by hand because kHIThemeFrameListBox drawing
|
|
|
|
// is buggy on 10.5, see bug 579259.
|
2007-03-22 10:30:00 -07:00
|
|
|
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
|
|
|
CGContextFillRect(cgContext, macRect);
|
2010-08-02 06:24:53 -07:00
|
|
|
|
|
|
|
// #8E8E8E for the top border, #BEBEBE for the rest.
|
|
|
|
int x = macRect.origin.x, y = macRect.origin.y;
|
|
|
|
int w = macRect.size.width, h = macRect.size.height;
|
|
|
|
CGContextSetRGBFillColor(cgContext, 0.557, 0.557, 0.557, 1.0);
|
|
|
|
CGContextFillRect(cgContext, CGRectMake(x, y, w, 1));
|
|
|
|
CGContextSetRGBFillColor(cgContext, 0.745, 0.745, 0.745, 1.0);
|
|
|
|
CGContextFillRect(cgContext, CGRectMake(x, y + 1, 1, h - 1));
|
|
|
|
CGContextFillRect(cgContext, CGRectMake(x + w - 1, y + 1, 1, h - 1));
|
|
|
|
CGContextFillRect(cgContext, CGRectMake(x + 1, y + h - 1, w - 2, 1));
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
2008-11-27 14:16:13 -08:00
|
|
|
case NS_THEME_TAB:
|
|
|
|
DrawTab(cgContext, macRect, eventState, aFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NS_THEME_TAB_PANELS:
|
2008-09-22 01:57:42 -07:00
|
|
|
DrawTabPanel(cgContext, macRect, aFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
2009-08-20 07:19:18 -07:00
|
|
|
|
|
|
|
case NS_THEME_RESIZER:
|
2009-09-27 14:58:58 -07:00
|
|
|
DrawResizer(cgContext, macRect, aFrame);
|
2009-08-20 07:19:18 -07:00
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-04-17 01:12:12 -07:00
|
|
|
nsIntMargin
|
|
|
|
nsNativeThemeCocoa::RTLAwareMargin(const nsIntMargin& aMargin, nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
if (IsFrameRTL(aFrame))
|
|
|
|
return nsIntMargin(aMargin.right, aMargin.top, aMargin.left, aMargin.bottom);
|
|
|
|
|
|
|
|
return aMargin;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const nsIntMargin kAquaDropdownBorder(5, 1, 22, 2);
|
|
|
|
static const nsIntMargin kAquaComboboxBorder(4, 3, 20, 3);
|
|
|
|
static const nsIntMargin kAquaSearchfieldBorder(19, 3, 5, 2);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-04-16 18:22:44 -07:00
|
|
|
nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntMargin* aResult)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
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
|
|
|
{
|
2009-08-10 14:23:50 -07:00
|
|
|
if (IsButtonTypeMenu(aFrame)) {
|
|
|
|
*aResult = RTLAwareMargin(kAquaDropdownBorder, aFrame);
|
|
|
|
} else {
|
|
|
|
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
|
|
|
|
2008-12-11 06:48:30 -08:00
|
|
|
case NS_THEME_CHECKBOX:
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
{
|
|
|
|
// nsFormControlFrame::GetIntrinsicWidth and nsFormControlFrame::GetIntrinsicHeight
|
|
|
|
// assume a border width of 2px.
|
|
|
|
aResult->SizeTo(2, 2, 2, 2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_DROPDOWN:
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
2009-04-17 01:12:12 -07:00
|
|
|
*aResult = RTLAwareMargin(kAquaDropdownBorder, aFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
2007-09-03 08:25:15 -07:00
|
|
|
|
2009-02-11 07:54:10 -08:00
|
|
|
case NS_THEME_DROPDOWN_TEXTFIELD:
|
2009-04-17 01:12:12 -07:00
|
|
|
*aResult = RTLAwareMargin(kAquaComboboxBorder, aFrame);
|
2009-02-11 07:54:10 -08: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
|
|
|
|
2008-12-06 03:40:58 -08:00
|
|
|
case NS_THEME_SEARCHFIELD:
|
2009-04-17 01:12:12 -07:00
|
|
|
*aResult = RTLAwareMargin(kAquaSearchfieldBorder, aFrame);
|
2008-12-06 03:40:58 -08:00
|
|
|
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
|
2009-09-22 01:01:35 -07:00
|
|
|
NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
|
|
|
|
if (!buttonPlacement || [buttonPlacement isEqualToString:@"DoubleMax"]) {
|
2007-04-10 17:25:11 -07:00
|
|
|
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
|
|
|
}
|
2008-09-16 01:21:06 -07:00
|
|
|
|
2009-01-06 07:46:59 -08:00
|
|
|
case NS_THEME_STATUSBAR:
|
|
|
|
aResult->SizeTo(0, 1, 0, 0);
|
2008-09-16 01:21:06 -07:00
|
|
|
break;
|
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-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
|
2011-04-16 18:22:44 -07:00
|
|
|
nsNativeThemeCocoa::GetWidgetPadding(nsDeviceContext* aContext,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntMargin* aResult)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
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_RADIO:
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
2011-04-16 18:22:44 -07:00
|
|
|
nsNativeThemeCocoa::GetWidgetOverflow(nsDeviceContext* 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:
|
2008-12-06 03:40:58 -08:00
|
|
|
case NS_THEME_SEARCHFIELD:
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_LISTBOX:
|
|
|
|
case NS_THEME_DROPDOWN:
|
|
|
|
case NS_THEME_DROPDOWN_BUTTON:
|
2009-02-11 07:54:10 -08:00
|
|
|
case NS_THEME_DROPDOWN_TEXTFIELD:
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_CHECKBOX:
|
|
|
|
case NS_THEME_RADIO:
|
2008-11-27 14:16:13 -08:00
|
|
|
case NS_THEME_TAB:
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2009-10-05 20:02:50 -07:00
|
|
|
static const PRInt32 kRegularScrollbarThumbMinSize = 22;
|
|
|
|
static const PRInt32 kSmallScrollbarThumbMinSize = 19;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
2011-04-07 18:04:40 -07:00
|
|
|
nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
PRUint8 aWidgetType,
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntSize* aResult,
|
2007-03-22 10:30:00 -07:00
|
|
|
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:
|
|
|
|
{
|
2009-01-12 11:22:59 -08:00
|
|
|
aResult->SizeTo(pushButtonSettings.minimumSizes[miniControlSize].width,
|
|
|
|
pushButtonSettings.naturalSizes[miniControlSize].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_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:
|
2008-12-06 03:40:58 -08:00
|
|
|
case NS_THEME_SEARCHFIELD:
|
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);
|
2008-11-27 14:14:54 -08:00
|
|
|
aResult->SizeTo(0, headerHeight - 1); // We don't need the top border.
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-11-27 14:16:13 -08:00
|
|
|
case NS_THEME_TAB:
|
|
|
|
{
|
|
|
|
aResult->SizeTo(0, NATURAL_MINI_TAB_BUTTON_HEIGHT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
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
|
|
|
|
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
|
|
|
{
|
2009-10-05 20:02:50 -07:00
|
|
|
// Find our parent scrollbar frame in order to find out whether we're in
|
|
|
|
// a small or a large scrollbar.
|
2007-04-10 17:25:11 -07:00
|
|
|
nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
|
2009-10-05 20:02:50 -07:00
|
|
|
if (!scrollbarFrame)
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-05-15 15:19:54 -07:00
|
|
|
|
2009-10-05 20:02:50 -07:00
|
|
|
PRBool isSmall = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
|
|
|
|
PRBool isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL);
|
|
|
|
PRInt32& minSize = isHorizontal ? aResult->width : aResult->height;
|
|
|
|
minSize = isSmall ? kSmallScrollbarThumbMinSize : kRegularScrollbarThumbMinSize;
|
2007-04-10 17:25:11 -07:00
|
|
|
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;
|
|
|
|
}
|
2009-08-20 07:19:18 -07:00
|
|
|
case NS_THEME_RESIZER:
|
|
|
|
{
|
|
|
|
HIThemeGrowBoxDrawInfo drawInfo;
|
|
|
|
drawInfo.version = 0;
|
|
|
|
drawInfo.state = kThemeStateActive;
|
|
|
|
drawInfo.kind = kHIThemeGrowBoxKindNormal;
|
|
|
|
drawInfo.direction = kThemeGrowRight | kThemeGrowDown;
|
|
|
|
drawInfo.size = kHIThemeGrowBoxSizeNormal;
|
|
|
|
HIPoint pnt = { 0, 0 };
|
|
|
|
HIRect bounds;
|
|
|
|
HIThemeGetGrowBoxBounds(&pnt, &drawInfo, &bounds);
|
|
|
|
aResult->SizeTo(bounds.size.width, bounds.size.height);
|
2010-06-21 05:37:35 -07:00
|
|
|
*aIsOverridable = PR_FALSE;
|
2009-08-20 07:19:18 -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
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2008-09-16 01:21:06 -07:00
|
|
|
case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
|
2007-03-22 10:30:00 -07:00
|
|
|
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:
|
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:
|
2010-11-13 00:19:38 -08:00
|
|
|
*aShouldRepaint = PR_FALSE;
|
2008-04-07 15:56:43 -07:00
|
|
|
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 ||
|
2009-01-18 03:05:38 -08:00
|
|
|
aAttribute == nsWidgetAtoms::_default ||
|
2009-12-11 14:01:38 -08:00
|
|
|
aAttribute == nsWidgetAtoms::open)
|
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)
|
|
|
|
{
|
2008-11-13 08:52:32 -08:00
|
|
|
// We don't have CSS set up to render non-native scrollbars on Mac OS X so we
|
|
|
|
// render natively even if native theme support is disabled.
|
|
|
|
if (aWidgetType != NS_THEME_SCROLLBAR &&
|
|
|
|
aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
|
2007-03-22 10:30:00 -07:00
|
|
|
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_CONTAINER:
|
|
|
|
case NS_THEME_RADIO:
|
|
|
|
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:
|
2008-09-16 01:21:06 -07:00
|
|
|
case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
|
2007-03-22 10:30:00 -07:00
|
|
|
case NS_THEME_STATUSBAR:
|
|
|
|
case NS_THEME_TEXTFIELD:
|
2007-05-06 19:06:58 -07:00
|
|
|
case NS_THEME_TEXTFIELD_MULTILINE:
|
2008-12-06 03:40:58 -08:00
|
|
|
case NS_THEME_SEARCHFIELD:
|
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_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:
|
2009-02-11 07:54:10 -08:00
|
|
|
case NS_THEME_DROPDOWN_TEXTFIELD:
|
2007-08-27 20:39:19 -07:00
|
|
|
return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
|
|
|
|
break;
|
2010-06-21 05:37:35 -07:00
|
|
|
|
|
|
|
case NS_THEME_RESIZER:
|
|
|
|
{
|
|
|
|
nsIFrame* parentFrame = aFrame->GetParent();
|
|
|
|
if (!parentFrame || parentFrame->GetType() != nsWidgetAtoms::scrollFrame)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
// Note that IsWidgetStyled is not called for resizers on Mac. This is
|
|
|
|
// because for scrollable containers, the native resizer looks better
|
|
|
|
// when scrollbars are present even when the style is overriden, and the
|
|
|
|
// custom transparent resizer looks better when scrollbars are not
|
|
|
|
// present.
|
|
|
|
nsIScrollableFrame* scrollFrame = do_QueryFrame(parentFrame);
|
|
|
|
return (scrollFrame && scrollFrame->GetScrollbarVisibility());
|
|
|
|
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:
|
|
|
|
case NS_THEME_CHECKBOX:
|
|
|
|
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 ||
|
2009-02-11 07:54:10 -08:00
|
|
|
aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD ||
|
2008-01-13 20:48:33 -08:00
|
|
|
aWidgetType == NS_THEME_BUTTON ||
|
|
|
|
aWidgetType == NS_THEME_RADIO ||
|
2008-11-03 05:12:59 -08:00
|
|
|
aWidgetType == NS_THEME_CHECKBOX)
|
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;
|
|
|
|
}
|
2008-12-11 06:37:38 -08:00
|
|
|
|
2010-06-10 15:53:57 -07:00
|
|
|
nsITheme::Transparency
|
|
|
|
nsNativeThemeCocoa::GetWidgetTransparency(nsIFrame* aFrame, PRUint8 aWidgetType)
|
2008-12-11 06:37:38 -08:00
|
|
|
{
|
2010-07-15 14:08:03 -07:00
|
|
|
switch (aWidgetType) {
|
|
|
|
case NS_THEME_MENUPOPUP:
|
|
|
|
case NS_THEME_TOOLTIP:
|
2010-06-10 15:53:57 -07:00
|
|
|
return eTransparent;
|
2008-12-11 06:37:38 -08:00
|
|
|
|
2010-07-15 14:08:03 -07:00
|
|
|
case NS_THEME_SCROLLBAR_SMALL:
|
|
|
|
case NS_THEME_SCROLLBAR:
|
2010-08-27 16:15:08 -07:00
|
|
|
case NS_THEME_STATUSBAR:
|
|
|
|
// Knowing that scrollbars and statusbars are opaque improves
|
|
|
|
// performance, because we create layers for them.
|
2010-07-15 14:08:03 -07:00
|
|
|
return eOpaque;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return eUnknownTransparency;
|
|
|
|
}
|
2008-12-11 06:37:38 -08:00
|
|
|
}
|