15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008, 2010, 2011, 2012 Apple Inc. All Rights Reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#import "config.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#import "core/platform/mac/ThemeMac.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#import <Carbon/Carbon.h>
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#import "core/platform/ScrollView.h"
3181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)#include "core/platform/graphics/GraphicsContextStateSaver.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#import "core/platform/mac/BlockExceptions.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#import "core/platform/mac/LocalCurrentGraphicsContext.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#import "core/platform/mac/WebCoreNSCellExtras.h"
357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/StdLibExtras.h"
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)NSRect focusRingClipRect;
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This is a view whose sole purpose is to tell AppKit that it's flipped.
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@interface WebCoreFlippedView : NSControl
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@end
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@implementation WebCoreFlippedView
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)- (BOOL)isFlipped
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return YES;
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)- (NSText *)currentEditor
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return nil;
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)- (BOOL)_automaticFocusRingDisabled
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return YES;
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)- (NSRect)_focusRingVisibleRect
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (NSIsEmptyRect(focusRingClipRect))
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return [self visibleRect];
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSRect rect = focusRingClipRect;
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rect.origin.y = [self bounds].size.height - NSMaxY(rect);
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return rect;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)- (NSView *)_focusRingClipAncestor
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return self;
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@end
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)@implementation NSFont (WebCoreTheme)
8153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
8253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)- (NSString*)webCoreFamilyName
8353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
8453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if ([[self familyName] hasPrefix:@"."])
8553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return [self fontName];
8653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
8753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return [self familyName];
8853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
8953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
9053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)@end
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    topMargin,
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rightMargin,
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bottomMargin,
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    leftMargin
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Theme* platformTheme()
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(ThemeMac, themeMac, ());
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return &themeMac;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Helper functions used by a bunch of different control parts.
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static NSControlSize controlSizeForFont(const Font& font)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int fontSize = font.pixelSize();
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (fontSize >= 16)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return NSRegularControlSize;
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (fontSize >= 11)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return NSSmallControlSize;
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return NSMiniControlSize;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static LengthSize sizeFromNSControlSize(NSControlSize nsControlSize, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize controlSize = sizes[nsControlSize];
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (zoomFactor != 1.0f)
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        controlSize = IntSize(controlSize.width() * zoomFactor, controlSize.height() * zoomFactor);
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LengthSize result = zoomedSize;
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (zoomedSize.width().isIntrinsicOrAuto() && controlSize.width() > 0)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.setWidth(Length(controlSize.width(), Fixed));
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (zoomedSize.height().isIntrinsicOrAuto() && controlSize.height() > 0)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.setHeight(Length(controlSize.height(), Fixed));
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return sizeFromNSControlSize(controlSizeForFont(font), zoomedSize, zoomFactor, sizes);
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static ControlSize controlSizeFromPixelSize(const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (minZoomedSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomFactor) &&
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        minZoomedSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomFactor))
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return NSRegularControlSize;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (minZoomedSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomFactor) &&
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        minZoomedSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomFactor))
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return NSSmallControlSize;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return NSMiniControlSize;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ControlSize size = controlSizeFromPixelSize(sizes, minZoomedSize, zoomFactor);
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [cell setControlSize:(NSControlSize)size];
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void updateStates(NSCell* cell, ControlStates states)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Hover state is not supported by Aqua.
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Pressed state
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool oldPressed = [cell isHighlighted];
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool pressed = states & PressedState;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (pressed != oldPressed)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [cell setHighlighted:pressed];
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Enabled state
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool oldEnabled = [cell isEnabled];
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool enabled = states & EnabledState;
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (enabled != oldEnabled)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [cell setEnabled:enabled];
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Focused state
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool oldFocused = [cell showsFirstResponder];
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool focused = states & FocusState;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (focused != oldFocused)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [cell setShowsFirstResponder:focused];
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Checked and Indeterminate
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool oldIndeterminate = [cell state] == NSMixedState;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool indeterminate = (states & IndeterminateState);
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool checked = states & CheckedState;
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool oldChecked = [cell state] == NSOnState;
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (oldIndeterminate != indeterminate || checked != oldChecked)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Window inactive state does not need to be checked explicitly, since we paint parented to
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // a view in a window whose key state can be detected.
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static ThemeDrawState convertControlStatesToThemeDrawState(ThemeButtonKind kind, ControlStates states)
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (states & ReadOnlyState)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return kThemeStateUnavailableInactive;
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!(states & EnabledState))
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return kThemeStateUnavailableInactive;
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do not process PressedState if !EnabledState or ReadOnlyState.
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (states & PressedState) {
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (kind == kThemeIncDecButton || kind == kThemeIncDecButtonSmall || kind == kThemeIncDecButtonMini)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return states & SpinUpState ? kThemeStatePressedUp : kThemeStatePressedDown;
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return kThemeStatePressed;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return kThemeStateActive;
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static IntRect inflateRect(const IntRect& zoomedRect, const IntSize& zoomedSize, const int* margins, float zoomFactor)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Only do the inflation if the available width/height are too small.  Otherwise try to
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // fit the glow/check space into the available box's width/height.
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int widthDelta = zoomedRect.width() - (zoomedSize.width() + margins[leftMargin] * zoomFactor + margins[rightMargin] * zoomFactor);
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int heightDelta = zoomedRect.height() - (zoomedSize.height() + margins[topMargin] * zoomFactor + margins[bottomMargin] * zoomFactor);
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect result(zoomedRect);
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (widthDelta < 0) {
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.setX(result.x() - margins[leftMargin] * zoomFactor);
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.setWidth(result.width() - widthDelta);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (heightDelta < 0) {
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.setY(result.y() - margins[topMargin] * zoomFactor);
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.setHeight(result.height() - heightDelta);
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Checkboxes
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const IntSize* checkboxSizes()
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) };
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return sizes;
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int* checkboxMargins(NSControlSize controlSize)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const int margins[3][4] =
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 3, 4, 4, 2 },
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 4, 3, 3, 3 },
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 4, 3, 3, 3 },
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return margins[controlSize];
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static LengthSize checkboxSize(const Font& font, const LengthSize& zoomedSize, float zoomFactor)
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the width and height are both specified, then we have nothing to do.
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!zoomedSize.width().isIntrinsicOrAuto() && !zoomedSize.height().isIntrinsicOrAuto())
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return zoomedSize;
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Use the font size to determine the intrinsic width of the control.
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return sizeFromFont(font, zoomedSize, zoomFactor, checkboxSizes());
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static NSButtonCell *checkbox(ControlStates states, const IntRect& zoomedRect, float zoomFactor)
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static NSButtonCell *checkboxCell;
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!checkboxCell) {
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        checkboxCell = [[NSButtonCell alloc] init];
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [checkboxCell setButtonType:NSSwitchButton];
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [checkboxCell setTitle:nil];
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [checkboxCell setAllowsMixedState:YES];
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [checkboxCell setFocusRingType:NSFocusRingTypeExterior];
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Set the control size based off the rectangle we're painting into.
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setControlSize(checkboxCell, checkboxSizes(), zoomedRect.size(), zoomFactor);
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Update the various states we respond to.
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateStates(checkboxCell, states);
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return checkboxCell;
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Share more code with radio buttons.
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void paintCheckbox(ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView* scrollView)
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    BEGIN_BLOCK_OBJC_EXCEPTIONS
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Determine the width and height needed for the control and prepare the cell for painting.
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSButtonCell *checkboxCell = checkbox(states, zoomedRect, zoomFactor);
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContextStateSaver stateSaver(*context);
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSControlSize controlSize = [checkboxCell controlSize];
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize zoomedSize = checkboxSizes()[controlSize];
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    zoomedSize.setWidth(zoomedSize.width() * zoomFactor);
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect inflatedRect = inflateRect(zoomedRect, zoomedSize, checkboxMargins(controlSize), zoomFactor);
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (zoomFactor != 1.0f) {
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        inflatedRect.setWidth(inflatedRect.width() / zoomFactor);
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        inflatedRect.setHeight(inflatedRect.height() / zoomFactor);
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->translate(inflatedRect.x(), inflatedRect.y());
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->scale(FloatSize(zoomFactor, zoomFactor));
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->translate(-inflatedRect.x(), -inflatedRect.y());
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LocalCurrentGraphicsContext localContext(context);
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSView *view = ThemeMac::ensuredView(scrollView);
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    [checkboxCell drawWithFrame:NSRect(inflatedRect) inView:view];
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if !BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (states & FocusState)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [checkboxCell _web_drawFocusRingWithFrame:NSRect(inflatedRect) inView:view];
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    [checkboxCell setControlView:nil];
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    END_BLOCK_OBJC_EXCEPTIONS
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Radio Buttons
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const IntSize* radioSizes()
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) };
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return sizes;
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int* radioMargins(NSControlSize controlSize)
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const int margins[3][4] =
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 2, 2, 4, 2 },
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 3, 2, 3, 2 },
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 1, 0, 2, 0 },
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return margins[controlSize];
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static LengthSize radioSize(const Font& font, const LengthSize& zoomedSize, float zoomFactor)
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the width and height are both specified, then we have nothing to do.
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!zoomedSize.width().isIntrinsicOrAuto() && !zoomedSize.height().isIntrinsicOrAuto())
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return zoomedSize;
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Use the font size to determine the intrinsic width of the control.
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return sizeFromFont(font, zoomedSize, zoomFactor, radioSizes());
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static NSButtonCell *radio(ControlStates states, const IntRect& zoomedRect, float zoomFactor)
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static NSButtonCell *radioCell;
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!radioCell) {
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        radioCell = [[NSButtonCell alloc] init];
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [radioCell setButtonType:NSRadioButton];
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [radioCell setTitle:nil];
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [radioCell setFocusRingType:NSFocusRingTypeExterior];
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Set the control size based off the rectangle we're painting into.
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setControlSize(radioCell, radioSizes(), zoomedRect.size(), zoomFactor);
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Update the various states we respond to.
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateStates(radioCell, states);
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return radioCell;
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void paintRadio(ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView* scrollView)
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Determine the width and height needed for the control and prepare the cell for painting.
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSButtonCell *radioCell = radio(states, zoomedRect, zoomFactor);
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContextStateSaver stateSaver(*context);
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSControlSize controlSize = [radioCell controlSize];
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize zoomedSize = radioSizes()[controlSize];
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    zoomedSize.setWidth(zoomedSize.width() * zoomFactor);
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect inflatedRect = inflateRect(zoomedRect, zoomedSize, radioMargins(controlSize), zoomFactor);
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (zoomFactor != 1.0f) {
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        inflatedRect.setWidth(inflatedRect.width() / zoomFactor);
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        inflatedRect.setHeight(inflatedRect.height() / zoomFactor);
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->translate(inflatedRect.x(), inflatedRect.y());
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->scale(FloatSize(zoomFactor, zoomFactor));
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->translate(-inflatedRect.x(), -inflatedRect.y());
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LocalCurrentGraphicsContext localContext(context);
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    BEGIN_BLOCK_OBJC_EXCEPTIONS
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSView *view = ThemeMac::ensuredView(scrollView);
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    [radioCell drawWithFrame:NSRect(inflatedRect) inView:view];
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if !BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (states & FocusState)
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [radioCell _web_drawFocusRingWithFrame:NSRect(inflatedRect) inView:view];
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    [radioCell setControlView:nil];
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    END_BLOCK_OBJC_EXCEPTIONS
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Buttons
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Buttons really only constrain height. They respect width.
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const IntSize* buttonSizes()
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return sizes;
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int* buttonMargins(NSControlSize controlSize)
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const int margins[3][4] =
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 4, 6, 7, 6 },
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 4, 5, 6, 5 },
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { 0, 1, 1, 1 },
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return margins[controlSize];
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void setUpButtonCell(NSButtonCell *cell, ControlPart part, ControlStates states, const IntRect& zoomedRect, float zoomFactor)
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Set the control size based off the rectangle we're painting into.
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const IntSize* sizes = buttonSizes();
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (part == SquareButtonPart || zoomedRect.height() > buttonSizes()[NSRegularControlSize].height() * zoomFactor) {
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Use the square button
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if ([cell bezelStyle] != NSShadowlessSquareBezelStyle)
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            [cell setBezelStyle:NSShadowlessSquareBezelStyle];
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if ([cell bezelStyle] != NSRoundedBezelStyle)
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [cell setBezelStyle:NSRoundedBezelStyle];
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setControlSize(cell, sizes, zoomedRect.size(), zoomFactor);
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Update the various states we respond to.
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateStates(cell, states);
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static NSButtonCell *button(ControlPart part, ControlStates states, const IntRect& zoomedRect, float zoomFactor)
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
42853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    static NSButtonCell *cell = nil;
42953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!cell) {
43053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        cell = [[NSButtonCell alloc] init];
43153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        [cell setTitle:nil];
43253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        [cell setButtonType:NSMomentaryPushInButton];
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
43453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    setUpButtonCell(cell, part, states, zoomedRect, zoomFactor);
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return cell;
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void paintButton(ControlPart part, ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView* scrollView)
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    BEGIN_BLOCK_OBJC_EXCEPTIONS
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Determine the width and height needed for the control and prepare the cell for painting.
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSButtonCell *buttonCell = button(part, states, zoomedRect, zoomFactor);
444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    GraphicsContextStateSaver stateSaver(*context);
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSControlSize controlSize = [buttonCell controlSize];
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize zoomedSize = buttonSizes()[controlSize];
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    zoomedSize.setWidth(zoomedRect.width()); // Buttons don't ever constrain width, so the zoomed width can just be honored.
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect inflatedRect = zoomedRect;
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([buttonCell bezelStyle] == NSRoundedBezelStyle) {
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Center the button within the available space.
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (inflatedRect.height() > zoomedSize.height()) {
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - zoomedSize.height()) / 2);
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            inflatedRect.setHeight(zoomedSize.height());
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Now inflate it to account for the shadow.
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        inflatedRect = inflateRect(inflatedRect, zoomedSize, buttonMargins(controlSize), zoomFactor);
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (zoomFactor != 1.0f) {
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            inflatedRect.setWidth(inflatedRect.width() / zoomFactor);
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            inflatedRect.setHeight(inflatedRect.height() / zoomFactor);
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            context->translate(inflatedRect.x(), inflatedRect.y());
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            context->scale(FloatSize(zoomFactor, zoomFactor));
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            context->translate(-inflatedRect.x(), -inflatedRect.y());
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LocalCurrentGraphicsContext localContext(context);
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSView *view = ThemeMac::ensuredView(scrollView);
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSWindow *window = [view window];
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    [buttonCell drawWithFrame:NSRect(inflatedRect) inView:view];
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if !BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (states & FocusState)
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [buttonCell _web_drawFocusRingWithFrame:NSRect(inflatedRect) inView:view];
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    [buttonCell setControlView:nil];
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    END_BLOCK_OBJC_EXCEPTIONS
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Stepper
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const IntSize* stepperSizes()
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const IntSize sizes[3] = { IntSize(19, 27), IntSize(15, 22), IntSize(13, 15) };
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return sizes;
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// We don't use controlSizeForFont() for steppers because the stepper height
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// should be equal to or less than the corresponding text field height,
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static NSControlSize stepperControlSizeForFont(const Font& font)
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int fontSize = font.pixelSize();
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (fontSize >= 18)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return NSRegularControlSize;
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (fontSize >= 13)
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return NSSmallControlSize;
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return NSMiniControlSize;
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void paintStepper(ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView*)
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We don't use NSStepperCell because there are no ways to draw an
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // NSStepperCell with the up button highlighted.
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HIThemeButtonDrawInfo drawInfo;
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    drawInfo.version = 0;
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    drawInfo.state = convertControlStatesToThemeDrawState(kThemeIncDecButton, states);
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    drawInfo.adornment = kThemeAdornmentDefault;
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ControlSize controlSize = controlSizeFromPixelSize(stepperSizes(), zoomedRect.size(), zoomFactor);
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (controlSize == NSSmallControlSize)
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        drawInfo.kind = kThemeIncDecButtonSmall;
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (controlSize == NSMiniControlSize)
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        drawInfo.kind = kThemeIncDecButtonMini;
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        drawInfo.kind = kThemeIncDecButton;
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect rect(zoomedRect);
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContextStateSaver stateSaver(*context);
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (zoomFactor != 1.0f) {
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.setWidth(rect.width() / zoomFactor);
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.setHeight(rect.height() / zoomFactor);
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->translate(rect.x(), rect.y());
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->scale(FloatSize(zoomFactor, zoomFactor));
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->translate(-rect.x(), -rect.y());
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CGRect bounds(rect);
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CGRect backgroundBounds;
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HIThemeGetButtonBackgroundBounds(&bounds, &drawInfo, &backgroundBounds);
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Center the stepper rectangle in the specified area.
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    backgroundBounds.origin.x = bounds.origin.x + (bounds.size.width - backgroundBounds.size.width) / 2;
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (backgroundBounds.size.height < bounds.size.height) {
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int heightDiff = clampToInteger(bounds.size.height - backgroundBounds.size.height);
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        backgroundBounds.origin.y = bounds.origin.y + (heightDiff / 2) + 1;
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LocalCurrentGraphicsContext localContext(context);
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HIThemeDrawButton(&backgroundBounds, &drawInfo, localContext.cgContext(), kHIThemeOrientationNormal, 0);
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This will ensure that we always return a valid NSView, even if ScrollView doesn't have an associated document NSView.
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// If the ScrollView doesn't have an NSView, we will return a fake NSView whose sole purpose is to tell AppKit that it's flipped.
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)NSView *ThemeMac::ensuredView(ScrollView* scrollView)
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
54853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Use a fake flipped view.
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static NSView *flippedView = [[WebCoreFlippedView alloc] init];
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    [flippedView setFrameSize:NSSizeFromCGSize(scrollView->contentsSize())];
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return flippedView;
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ThemeMac::setFocusRingClipRect(const FloatRect& rect)
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    focusRingClipRect = rect;
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Theme overrides
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int ThemeMac::baselinePositionAdjustment(ControlPart part) const
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (part == CheckboxPart || part == RadioPart)
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return -2;
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return Theme::baselinePositionAdjustment(part);
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FontDescription ThemeMac::controlFont(ControlPart part, const Font& font, float zoomFactor) const
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (part) {
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case PushButtonPart: {
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            FontDescription fontDescription;
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fontDescription.setIsAbsoluteSize(true);
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fontDescription.setGenericFamily(FontDescription::SerifFamily);
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            NSFont* nsFont = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSizeForFont(font)]];
57953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            fontDescription.firstFamily().setFamily([nsFont webCoreFamilyName]);
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fontDescription.setComputedSize([nsFont pointSize] * zoomFactor);
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fontDescription.setSpecifiedSize([nsFont pointSize] * zoomFactor);
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return fontDescription;
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return Theme::controlFont(part, font, zoomFactor);
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LengthSize ThemeMac::controlSize(ControlPart part, const Font& font, const LengthSize& zoomedSize, float zoomFactor) const
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (part) {
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case CheckboxPart:
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return checkboxSize(font, zoomedSize, zoomFactor);
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RadioPart:
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return radioSize(font, zoomedSize, zoomFactor);
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case PushButtonPart:
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Height is reset to auto so that specified heights can be ignored.
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return sizeFromFont(font, LengthSize(zoomedSize.width(), Length()), zoomFactor, buttonSizes());
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case InnerSpinButtonPart:
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!zoomedSize.width().isIntrinsicOrAuto() && !zoomedSize.height().isIntrinsicOrAuto())
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return zoomedSize;
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return sizeFromNSControlSize(stepperControlSizeForFont(font), zoomedSize, zoomFactor, stepperSizes());
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return zoomedSize;
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LengthSize ThemeMac::minimumControlSize(ControlPart part, const Font& font, float zoomFactor) const
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (part) {
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case SquareButtonPart:
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ButtonPart:
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return LengthSize(Length(0, Fixed), Length(static_cast<int>(15 * zoomFactor), Fixed));
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case InnerSpinButtonPart:{
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            IntSize base = stepperSizes()[NSMiniControlSize];
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return LengthSize(Length(static_cast<int>(base.width() * zoomFactor), Fixed),
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                              Length(static_cast<int>(base.height() * zoomFactor), Fixed));
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return Theme::minimumControlSize(part, font, zoomFactor);
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LengthBox ThemeMac::controlBorder(ControlPart part, const Font& font, const LengthBox& zoomedBox, float zoomFactor) const
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (part) {
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case SquareButtonPart:
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ButtonPart:
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return LengthBox(0, zoomedBox.right().value(), 0, zoomedBox.left().value());
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return Theme::controlBorder(part, font, zoomedBox, zoomFactor);
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LengthBox ThemeMac::controlPadding(ControlPart part, const Font& font, const LengthBox& zoomedBox, float zoomFactor) const
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (part) {
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case PushButtonPart: {
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Just use 8px.  AppKit wants to use 11px for mini buttons, but that padding is just too large
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // by definition constrained, since we select mini only for small cramped environments.
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // This also guarantees the HTML <button> will match our rendering by default, since we're using a consistent
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // padding.
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const int padding = 8 * zoomFactor;
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return LengthBox(0, padding, 0, padding);
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return Theme::controlPadding(part, font, zoomedBox, zoomFactor);
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ThemeMac::inflateControlPaintRect(ControlPart part, ControlStates states, IntRect& zoomedRect, float zoomFactor) const
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    BEGIN_BLOCK_OBJC_EXCEPTIONS
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (part) {
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case CheckboxPart: {
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            NSCell *cell = checkbox(states, zoomedRect, zoomFactor);
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            NSControlSize controlSize = [cell controlSize];
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            IntSize zoomedSize = checkboxSizes()[controlSize];
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedSize.setWidth(zoomedSize.width() * zoomFactor);
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedRect = inflateRect(zoomedRect, zoomedSize, checkboxMargins(controlSize), zoomFactor);
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RadioPart: {
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We inflate the rect as needed to account for padding included in the cell to accommodate the radio button
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // shadow".  We don't consider this part of the bounds of the control in WebKit.
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            NSCell *cell = radio(states, zoomedRect, zoomFactor);
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            NSControlSize controlSize = [cell controlSize];
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            IntSize zoomedSize = radioSizes()[controlSize];
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedSize.setWidth(zoomedSize.width() * zoomFactor);
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedRect = inflateRect(zoomedRect, zoomedSize, radioMargins(controlSize), zoomFactor);
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case PushButtonPart:
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ButtonPart: {
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            NSButtonCell *cell = button(part, states, zoomedRect, zoomFactor);
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            NSControlSize controlSize = [cell controlSize];
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We inflate the rect as needed to account for the Aqua button's shadow.
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if ([cell bezelStyle] == NSRoundedBezelStyle) {
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                IntSize zoomedSize = buttonSizes()[controlSize];
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                zoomedSize.setWidth(zoomedRect.width()); // Buttons don't ever constrain width, so the zoomed width can just be honored.
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                zoomedRect = inflateRect(zoomedRect, zoomedSize, buttonMargins(controlSize), zoomFactor);
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case InnerSpinButtonPart: {
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            static const int stepperMargin[4] = { 0, 0, 0, 0 };
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ControlSize controlSize = controlSizeFromPixelSize(stepperSizes(), zoomedRect.size(), zoomFactor);
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            IntSize zoomedSize = stepperSizes()[controlSize];
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedSize.setWidth(zoomedSize.width() * zoomFactor);
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            zoomedRect = inflateRect(zoomedRect, zoomedSize, stepperMargin, zoomFactor);
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    END_BLOCK_OBJC_EXCEPTIONS
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ThemeMac::paint(ControlPart part, ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView* scrollView) const
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (part) {
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case CheckboxPart:
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            paintCheckbox(states, context, zoomedRect, zoomFactor, scrollView);
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RadioPart:
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            paintRadio(states, context, zoomedRect, zoomFactor, scrollView);
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case PushButtonPart:
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ButtonPart:
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case SquareButtonPart:
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            paintButton(part, states, context, zoomedRect, zoomFactor, scrollView);
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case InnerSpinButtonPart:
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            paintStepper(states, context, zoomedRect, zoomFactor, scrollView);
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
730