mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-25 13:50:57 +00:00
part name, instead themes should just provide a part called NSScrollView. Add -scrollViewScrollersOverlapBorders method. * Source/GSTheme.m: Remove GSScrollViewBottomCorner part name. * Source/GSThemeDrawing.m: Add -scrollViewScrollersOverlapBorders. * Source/GSThemeDrawing.m (-drawBrowserRect:...): If -scrollViewScrollersOverlapBorders is enabled, fill the browser background with the NSScrollView tile. * Source/GSThemeDrawing.m (-drawScrollViewRect:...): If -scrollViewScrollersOverlapBorders is enabled, fill the scroll view background with the NSScrollView tile. * Source/NSScroller.m (-rectForPart:): Change the meaning of the GSScrollerKnobOvershoot default so the knob only overlaps the buttons by this much (rather than both ends of the track). Turns out this is more useful for themes. * Source/NSScrollView.m (-tile): Add support for -[GSTheme scrollViewScrollersOverlapBorders] * Source/NSBrowser.m (-tile): Add support for -[GSTheme scrollViewScrollersOverlapBorders] and -[GSTheme scrollViewUseBottomCorner] The overall point of these additions is to support NSScrollView and NSBrowser looking like: http://jesseross.com/clients/gnustep/ui/concepts/ git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@37238 72102866-910b-0410-8b05-ffd578937521
3267 lines
84 KiB
Objective-C
3267 lines
84 KiB
Objective-C
/** <title>GSThemeDrawing</title>
|
|
|
|
<abstract>The theme methods for drawing controls</abstract>
|
|
|
|
Copyright (C) 2004-2010 Free Software Foundation, Inc.
|
|
|
|
Author: Adam Fedor <fedor@gnu.org>
|
|
Date: Jan 2004
|
|
|
|
This file is part of the GNU Objective C User interface library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#import "GSThemePrivate.h"
|
|
|
|
#import "Foundation/NSUserDefaults.h"
|
|
#import "Foundation/NSIndexSet.h"
|
|
|
|
#import "AppKit/NSAttributedString.h"
|
|
#import "AppKit/NSBezierPath.h"
|
|
#import "AppKit/NSButtonCell.h"
|
|
#import "AppKit/NSBrowser.h"
|
|
#import "AppKit/NSCell.h"
|
|
#import "AppKit/NSColor.h"
|
|
#import "AppKit/NSColorList.h"
|
|
#import "AppKit/NSColorWell.h"
|
|
#import "AppKit/NSGraphics.h"
|
|
#import "AppKit/NSImage.h"
|
|
#import "AppKit/NSMenuView.h"
|
|
#import "AppKit/NSMenuItemCell.h"
|
|
#import "AppKit/NSParagraphStyle.h"
|
|
#import "AppKit/NSPopUpButtonCell.h"
|
|
#import "AppKit/NSProgressIndicator.h"
|
|
#import "AppKit/NSScroller.h"
|
|
#import "AppKit/NSScrollView.h"
|
|
#import "AppKit/NSStringDrawing.h"
|
|
#import "AppKit/NSTableView.h"
|
|
#import "AppKit/NSTableColumn.h"
|
|
#import "AppKit/NSTableHeaderCell.h"
|
|
#import "AppKit/NSTableHeaderView.h"
|
|
#import "AppKit/NSView.h"
|
|
#import "AppKit/NSTabView.h"
|
|
#import "AppKit/NSTabViewItem.h"
|
|
#import "AppKit/PSOperators.h"
|
|
#import "AppKit/NSSliderCell.h"
|
|
|
|
#import "GNUstepGUI/GSToolbarView.h"
|
|
#import "GNUstepGUI/GSTitleView.h"
|
|
|
|
/* a border width of 5 gives a reasonable compromise between Cocoa metrics and looking good */
|
|
/* 7.0 gives us the NeXT Look (which is 8 pix wide including the shadow) */
|
|
#define COLOR_WELL_BORDER_WIDTH 7.0
|
|
|
|
@interface NSTableView (Private)
|
|
- (float *)_columnOrigins;
|
|
- (void) _willDisplayCell: (NSCell*)cell
|
|
forTableColumn: (NSTableColumn *)tb
|
|
row: (int)index;
|
|
@end
|
|
|
|
@interface NSCell (Private)
|
|
- (void) _setInEditing: (BOOL)flag;
|
|
@end
|
|
|
|
@implementation GSTheme (Drawing)
|
|
- (void) setKeyEquivalent: (NSString *)key
|
|
forButtonCell: (NSButtonCell *)cell
|
|
{
|
|
if([cell image] == nil && ([key isEqualToString:@"\r"] ||
|
|
[key isEqualToString:@"\n"]))
|
|
{
|
|
[cell setImagePosition: NSImageRight];
|
|
[cell setImage: [NSImage imageNamed:@"common_ret"]];
|
|
[cell setAlternateImage: [NSImage imageNamed:@"common_retH"]];
|
|
}
|
|
else if([key isEqualToString:@"\r"] == NO &&
|
|
[key isEqualToString:@"\n"] == NO)
|
|
{
|
|
NSImage *cellImage = [cell image];
|
|
if(cellImage == [NSImage imageNamed:@"common_ret"])
|
|
{
|
|
[cell setImage: nil];
|
|
[cell setAlternateImage: nil];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) drawButton: (NSRect)frame
|
|
in: (NSCell*)cell
|
|
view: (NSView*)view
|
|
style: (int)style
|
|
state: (GSThemeControlState)state
|
|
{
|
|
GSDrawTiles *tiles = nil;
|
|
NSColor *color = nil;
|
|
NSString *name = [self nameForElement: cell];
|
|
|
|
if (name == nil)
|
|
{
|
|
name = GSStringFromBezelStyle(style);
|
|
}
|
|
|
|
color = [self colorNamed: name state: state];
|
|
if (color == nil)
|
|
{
|
|
if (state == GSThemeNormalState)
|
|
{
|
|
color = [NSColor controlBackgroundColor];
|
|
}
|
|
else if (state == GSThemeHighlightedState
|
|
|| state == GSThemeHighlightedFirstResponderState)
|
|
{
|
|
color = [NSColor selectedControlColor];
|
|
}
|
|
else if (state == GSThemeSelectedState
|
|
|| state == GSThemeSelectedFirstResponderState)
|
|
{
|
|
color = [NSColor selectedControlColor];
|
|
}
|
|
else
|
|
{
|
|
color = [NSColor controlBackgroundColor];
|
|
}
|
|
}
|
|
|
|
tiles = [self tilesNamed: name state: state];
|
|
if (tiles == nil)
|
|
{
|
|
tiles = [self tilesNamed: @"NSButton" state: state];
|
|
}
|
|
|
|
if (tiles == nil)
|
|
{
|
|
switch (style)
|
|
{
|
|
case NSRoundRectBezelStyle:
|
|
case NSTexturedRoundedBezelStyle:
|
|
case NSRoundedBezelStyle:
|
|
[self drawRoundBezel: frame withColor: color];
|
|
break;
|
|
case NSTexturedSquareBezelStyle:
|
|
frame = NSInsetRect(frame, 0, 1);
|
|
case NSSmallSquareBezelStyle:
|
|
case NSRegularSquareBezelStyle:
|
|
case NSShadowlessSquareBezelStyle:
|
|
[color set];
|
|
NSRectFill(frame);
|
|
[[NSColor controlShadowColor] set];
|
|
NSFrameRectWithWidth(frame, 1);
|
|
break;
|
|
case NSThickSquareBezelStyle:
|
|
[color set];
|
|
NSRectFill(frame);
|
|
[[NSColor controlShadowColor] set];
|
|
NSFrameRectWithWidth(frame, 1.5);
|
|
break;
|
|
case NSThickerSquareBezelStyle:
|
|
[color set];
|
|
NSRectFill(frame);
|
|
[[NSColor controlShadowColor] set];
|
|
NSFrameRectWithWidth(frame, 2);
|
|
break;
|
|
case NSCircularBezelStyle:
|
|
frame = NSInsetRect(frame, 3, 3);
|
|
[self drawCircularBezel: frame withColor: color];
|
|
break;
|
|
case NSHelpButtonBezelStyle:
|
|
[self drawCircularBezel: frame withColor: color];
|
|
{
|
|
NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSFont controlContentFontOfSize: 0]
|
|
forKey: NSFontAttributeName];
|
|
NSAttributedString *questionMark = [[[NSAttributedString alloc]
|
|
initWithString: _(@"?")
|
|
attributes: attributes] autorelease];
|
|
|
|
NSRect textRect;
|
|
textRect.size = [questionMark size];
|
|
textRect.origin.x = NSMidX(frame) - (textRect.size.width / 2);
|
|
textRect.origin.y = NSMidY(frame) - (textRect.size.height / 2);
|
|
|
|
[questionMark drawInRect: textRect];
|
|
}
|
|
break;
|
|
case NSDisclosureBezelStyle:
|
|
case NSRoundedDisclosureBezelStyle:
|
|
case NSRecessedBezelStyle:
|
|
// FIXME
|
|
break;
|
|
default:
|
|
[color set];
|
|
NSRectFill(frame);
|
|
|
|
if (state == GSThemeNormalState || state == GSThemeHighlightedState)
|
|
{
|
|
[self drawButton: frame withClip: NSZeroRect];
|
|
}
|
|
else if (state == GSThemeSelectedState || state == GSThemeSelectedFirstResponderState)
|
|
{
|
|
[self drawGrayBezel: frame withClip: NSZeroRect];
|
|
}
|
|
else
|
|
{
|
|
[self drawButton: frame withClip: NSZeroRect];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Use tiles to draw button border with central part filled with color
|
|
*/
|
|
[self fillRect: frame
|
|
withTiles: tiles
|
|
background: color];
|
|
}
|
|
}
|
|
|
|
- (GSThemeMargins) buttonMarginsForCell: (NSCell*)cell
|
|
style: (int)style
|
|
state: (GSThemeControlState)state
|
|
{
|
|
GSDrawTiles *tiles = nil;
|
|
NSString *name = [self nameForElement: cell];
|
|
GSThemeMargins margins;
|
|
|
|
if (name == nil)
|
|
{
|
|
name = GSStringFromBezelStyle(style);
|
|
}
|
|
|
|
tiles = [self tilesNamed: name state: state];
|
|
if (tiles == nil)
|
|
{
|
|
tiles = [self tilesNamed: @"NSButton" state: state];
|
|
}
|
|
|
|
if (tiles == nil)
|
|
{
|
|
switch (style)
|
|
{
|
|
case NSRoundRectBezelStyle:
|
|
case NSTexturedRoundedBezelStyle:
|
|
case NSRoundedBezelStyle:
|
|
margins.left = 5; margins.top = 5; margins.right = 5; margins.bottom = 5;
|
|
return margins;
|
|
case NSTexturedSquareBezelStyle:
|
|
margins.left = 3; margins.top = 3; margins.right = 3; margins.bottom = 3;
|
|
return margins;
|
|
case NSSmallSquareBezelStyle:
|
|
case NSRegularSquareBezelStyle:
|
|
case NSShadowlessSquareBezelStyle:
|
|
margins.left = 2; margins.top = 2; margins.right = 2; margins.bottom = 2;
|
|
return margins;
|
|
case NSThickSquareBezelStyle:
|
|
margins.left = 3; margins.top = 3; margins.right = 3; margins.bottom = 3;
|
|
return margins;
|
|
case NSThickerSquareBezelStyle:
|
|
margins.left = 4; margins.top = 4; margins.right = 4; margins.bottom = 4;
|
|
return margins;
|
|
case NSCircularBezelStyle:
|
|
margins.left = 5; margins.top = 5; margins.right = 5; margins.bottom = 5;
|
|
return margins;
|
|
case NSHelpButtonBezelStyle:
|
|
margins.left = 2; margins.top = 2; margins.right = 2; margins.bottom = 2;
|
|
return margins;
|
|
case NSDisclosureBezelStyle:
|
|
case NSRoundedDisclosureBezelStyle:
|
|
case NSRecessedBezelStyle:
|
|
// FIXME
|
|
margins.left = 0; margins.top = 0; margins.right = 0; margins.bottom = 0;
|
|
return margins;
|
|
default:
|
|
margins.left = 2; margins.top = 2; margins.right = 3; margins.bottom = 3;
|
|
return margins;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
margins = [tiles themeMargins];
|
|
return margins;
|
|
}
|
|
}
|
|
|
|
- (void) drawFocusFrame: (NSRect) frame view: (NSView*) view
|
|
{
|
|
GSDrawTiles *tiles = [self tilesNamed: @"NSFocusRing" state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
NSDottedFrameRect(frame);
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: frame
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (void) drawWindowBackground: (NSRect) frame view: (NSView*) view
|
|
{
|
|
NSColor *c;
|
|
|
|
c = [[view window] backgroundColor];
|
|
[c set];
|
|
NSRectFill (frame);
|
|
}
|
|
|
|
- (void) drawBorderType: (NSBorderType)aType
|
|
frame: (NSRect)frame
|
|
view: (NSView*)view
|
|
{
|
|
NSString *name = GSStringFromBorderType(aType);
|
|
GSDrawTiles *tiles = [self tilesNamed: name state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
switch (aType)
|
|
{
|
|
case NSLineBorder:
|
|
[[NSColor controlDarkShadowColor] set];
|
|
NSFrameRect(frame);
|
|
break;
|
|
case NSGrooveBorder:
|
|
[self drawGroove: frame withClip: NSZeroRect];
|
|
break;
|
|
case NSBezelBorder:
|
|
[self drawWhiteBezel: frame withClip: NSZeroRect];
|
|
break;
|
|
case NSNoBorder:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: frame
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (NSSize) sizeForBorderType: (NSBorderType)aType
|
|
{
|
|
NSString *name = GSStringFromBorderType(aType);
|
|
GSDrawTiles *tiles = [self tilesNamed: name state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
// Returns the size of a border
|
|
switch (aType)
|
|
{
|
|
case NSLineBorder:
|
|
return NSMakeSize(1, 1);
|
|
case NSGrooveBorder:
|
|
case NSBezelBorder:
|
|
return NSMakeSize(2, 2);
|
|
case NSNoBorder:
|
|
default:
|
|
return NSZeroSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FIXME: We assume the button's top and right padding are the same as
|
|
// its bottom and left.
|
|
|
|
GSThemeMargins margins = [tiles themeMargins];
|
|
return NSMakeSize(margins.left, margins.bottom);
|
|
}
|
|
}
|
|
|
|
- (void) drawBorderForImageFrameStyle: (NSImageFrameStyle)frameStyle
|
|
frame: (NSRect)frame
|
|
view: (NSView*)view
|
|
{
|
|
switch (frameStyle)
|
|
{
|
|
case NSImageFrameNone:
|
|
// do nothing
|
|
break;
|
|
case NSImageFramePhoto:
|
|
[self drawFramePhoto: frame withClip: NSZeroRect];
|
|
break;
|
|
case NSImageFrameGrayBezel:
|
|
[self drawGrayBezel: frame withClip: NSZeroRect];
|
|
break;
|
|
case NSImageFrameGroove:
|
|
[self drawGroove: frame withClip: NSZeroRect];
|
|
break;
|
|
case NSImageFrameButton:
|
|
[self drawButton: frame withClip: NSZeroRect];
|
|
break;
|
|
}
|
|
}
|
|
|
|
- (NSSize) sizeForImageFrameStyle: (NSImageFrameStyle)frameStyle
|
|
{
|
|
// Get border size
|
|
switch (frameStyle)
|
|
{
|
|
case NSImageFrameNone:
|
|
default:
|
|
return NSZeroSize;
|
|
case NSImageFramePhoto:
|
|
// FIXME
|
|
return NSMakeSize(2, 2);
|
|
case NSImageFrameGrayBezel:
|
|
case NSImageFrameGroove:
|
|
case NSImageFrameButton:
|
|
return NSMakeSize(2, 2);
|
|
}
|
|
}
|
|
|
|
|
|
/* NSScroller themeing.
|
|
*/
|
|
- (BOOL) scrollerArrowsSameEndForScroller: (NSScroller *)aScroller
|
|
{
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
if ([defs objectForKey: @"GSScrollerArrowsSameEnd"] != nil)
|
|
{
|
|
return [defs boolForKey: @"GSScrollerArrowsSameEnd"];
|
|
}
|
|
else
|
|
{
|
|
NSInterfaceStyle interfaceStyle =
|
|
NSInterfaceStyleForKey(@"NSScrollerInterfaceStyle", aScroller);
|
|
|
|
if ((interfaceStyle == NSNextStepInterfaceStyle
|
|
|| interfaceStyle == NSMacintoshInterfaceStyle
|
|
|| interfaceStyle == GSWindowMakerInterfaceStyle))
|
|
{
|
|
return YES;
|
|
}
|
|
else
|
|
{
|
|
return NO;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (BOOL) scrollerScrollsByPageForScroller: (NSScroller *)aScroller
|
|
{
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
if ([defs objectForKey: @"GSScrollerScrollsByPage"] != nil)
|
|
{
|
|
return [defs boolForKey: @"GSScrollerScrollsByPage"];
|
|
}
|
|
else
|
|
{
|
|
NSInterfaceStyle interfaceStyle =
|
|
NSInterfaceStyleForKey(@"NSScrollerInterfaceStyle", aScroller);
|
|
|
|
if (interfaceStyle == NSNextStepInterfaceStyle
|
|
|| interfaceStyle == NSMacintoshInterfaceStyle
|
|
|| interfaceStyle == GSWindowMakerInterfaceStyle)
|
|
{
|
|
/* NeXTstep style is to scroll to point.
|
|
*/
|
|
return NO;
|
|
}
|
|
else
|
|
{
|
|
/* Windows style is to scroll by a page.
|
|
*/
|
|
return YES;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (NSButtonCell*) cellForScrollerArrow: (NSScrollerArrow)arrow
|
|
horizontal: (BOOL)horizontal
|
|
{
|
|
NSButtonCell *cell;
|
|
NSString *name;
|
|
|
|
cell = [NSButtonCell new];
|
|
if (horizontal)
|
|
{
|
|
if (arrow == NSScrollerDecrementArrow)
|
|
{
|
|
[cell setHighlightsBy:
|
|
NSChangeBackgroundCellMask | NSContentsCellMask];
|
|
[cell setImage: [NSImage imageNamed: @"common_ArrowLeft"]];
|
|
[cell setAlternateImage: [NSImage imageNamed: @"common_ArrowLeftH"]];
|
|
[cell setImagePosition: NSImageOnly];
|
|
name = GSScrollerLeftArrow;
|
|
}
|
|
else
|
|
{
|
|
[cell setHighlightsBy:
|
|
NSChangeBackgroundCellMask | NSContentsCellMask];
|
|
[cell setImage: [NSImage imageNamed: @"common_ArrowRight"]];
|
|
[cell setAlternateImage: [NSImage imageNamed: @"common_ArrowRightH"]];
|
|
[cell setImagePosition: NSImageOnly];
|
|
name = GSScrollerRightArrow;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (arrow == NSScrollerDecrementArrow)
|
|
{
|
|
[cell setHighlightsBy:
|
|
NSChangeBackgroundCellMask | NSContentsCellMask];
|
|
[cell setImage: [NSImage imageNamed: @"common_ArrowUp"]];
|
|
[cell setAlternateImage: [NSImage imageNamed: @"common_ArrowUpH"]];
|
|
[cell setImagePosition: NSImageOnly];
|
|
name = GSScrollerUpArrow;
|
|
}
|
|
else
|
|
{
|
|
[cell setHighlightsBy:
|
|
NSChangeBackgroundCellMask | NSContentsCellMask];
|
|
[cell setImage: [NSImage imageNamed: @"common_ArrowDown"]];
|
|
[cell setAlternateImage: [NSImage imageNamed: @"common_ArrowDownH"]];
|
|
[cell setImagePosition: NSImageOnly];
|
|
name = GSScrollerDownArrow;
|
|
}
|
|
}
|
|
[self setName: name forElement: cell temporary: YES];
|
|
RELEASE(cell);
|
|
return cell;
|
|
}
|
|
|
|
- (NSCell*) cellForScrollerKnob: (BOOL)horizontal
|
|
{
|
|
NSButtonCell *cell;
|
|
|
|
cell = [NSButtonCell new];
|
|
[cell setButtonType: NSMomentaryChangeButton];
|
|
[cell setImagePosition: NSImageOnly];
|
|
if (horizontal)
|
|
{
|
|
[self setName: GSScrollerHorizontalKnob forElement: cell temporary: YES];
|
|
[cell setImage: [NSImage imageNamed: @"common_DimpleHoriz"]];
|
|
}
|
|
else
|
|
{
|
|
[self setName: GSScrollerVerticalKnob forElement: cell temporary: YES];
|
|
[cell setImage: [NSImage imageNamed: @"common_Dimple"]];
|
|
|
|
}
|
|
RELEASE(cell);
|
|
return cell;
|
|
}
|
|
|
|
- (NSCell*) cellForScrollerKnobSlot: (BOOL)horizontal
|
|
{
|
|
GSDrawTiles *tiles;
|
|
NSButtonCell *cell;
|
|
NSColor *color;
|
|
NSString *name;
|
|
|
|
if (horizontal)
|
|
{
|
|
name = GSScrollerHorizontalSlot;
|
|
}
|
|
else
|
|
{
|
|
name = GSScrollerVerticalSlot;
|
|
}
|
|
|
|
tiles = [self tilesNamed: name state: GSThemeNormalState];
|
|
color = [self colorNamed: name state: GSThemeNormalState];
|
|
|
|
cell = [NSButtonCell new];
|
|
[cell setBordered: (tiles != nil)];
|
|
[cell setTitle: nil];
|
|
|
|
[self setName: name forElement: cell temporary: YES];
|
|
|
|
if (color == nil)
|
|
{
|
|
color = [NSColor scrollBarColor];
|
|
}
|
|
[cell setBackgroundColor: color];
|
|
RELEASE(cell);
|
|
return cell;
|
|
}
|
|
|
|
- (float) defaultScrollerWidth
|
|
{
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
float defaultScrollerWidth;
|
|
|
|
if ([defs objectForKey: @"GSScrollerDefaultWidth"] != nil)
|
|
{
|
|
defaultScrollerWidth = [defs floatForKey: @"GSScrollerDefaultWidth"];
|
|
}
|
|
else
|
|
{
|
|
defaultScrollerWidth = 18.0;
|
|
}
|
|
return defaultScrollerWidth;
|
|
}
|
|
|
|
- (BOOL) scrollViewUseBottomCorner
|
|
{
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
if ([defs objectForKey: @"GSScrollViewUseBottomCorner"] != nil)
|
|
{
|
|
return [defs boolForKey: @"GSScrollViewUseBottomCorner"];
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
- (BOOL) scrollViewScrollersOverlapBorders
|
|
{
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
if ([defs objectForKey: @"GSScrollViewScrollersOverlapBorders"] != nil)
|
|
{
|
|
return [defs boolForKey: @"GSScrollViewScrollersOverlapBorders"];
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
- (NSColor *) toolbarBackgroundColor
|
|
{
|
|
NSColor *color;
|
|
|
|
color = [self colorNamed: @"toolbarBackgroundColor"
|
|
state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [NSColor clearColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (NSColor *) toolbarBorderColor
|
|
{
|
|
NSColor *color;
|
|
|
|
color = [self colorNamed: @"toolbarBorderColor"
|
|
state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [NSColor darkGrayColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (void) drawToolbarRect: (NSRect)aRect
|
|
frame: (NSRect)viewFrame
|
|
borderMask: (unsigned int)borderMask
|
|
{
|
|
// We draw the background
|
|
[[self toolbarBackgroundColor] set];
|
|
[NSBezierPath fillRect: aRect];
|
|
|
|
// We draw the border
|
|
[[self toolbarBorderColor] set];
|
|
if (borderMask & GSToolbarViewBottomBorder)
|
|
{
|
|
[NSBezierPath strokeLineFromPoint: NSMakePoint(0, 0.5)
|
|
toPoint: NSMakePoint(viewFrame.size.width, 0.5)];
|
|
}
|
|
if (borderMask & GSToolbarViewTopBorder)
|
|
{
|
|
[NSBezierPath strokeLineFromPoint: NSMakePoint(0,
|
|
viewFrame.size.height - 0.5)
|
|
toPoint: NSMakePoint(viewFrame.size.width,
|
|
viewFrame.size.height - 0.5)];
|
|
}
|
|
if (borderMask & GSToolbarViewLeftBorder)
|
|
{
|
|
[NSBezierPath strokeLineFromPoint: NSMakePoint(0.5, 0)
|
|
toPoint: NSMakePoint(0.5, viewFrame.size.height)];
|
|
}
|
|
if (borderMask & GSToolbarViewRightBorder)
|
|
{
|
|
[NSBezierPath strokeLineFromPoint: NSMakePoint(viewFrame.size.width - 0.5,0)
|
|
toPoint: NSMakePoint(viewFrame.size.width - 0.5,
|
|
viewFrame.size.height)];
|
|
}
|
|
}
|
|
|
|
- (BOOL) toolbarIsOpaque
|
|
{
|
|
if ([[self toolbarBackgroundColor] alphaComponent] < 1.0)
|
|
{
|
|
return NO;
|
|
}
|
|
else
|
|
{
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
- (NSRect) stepperUpButtonRectWithFrame: (NSRect)frame
|
|
{
|
|
NSSize size = [[NSImage imageNamed: @"common_StepperUp"] size];
|
|
NSRect upRect;
|
|
|
|
upRect.size = size;
|
|
upRect.origin.x = NSMaxX(frame) - size.width;
|
|
upRect.origin.y = NSMinY(frame) + ((int)frame.size.height / 2) + 1;
|
|
return upRect;
|
|
}
|
|
|
|
- (NSRect) stepperDownButtonRectWithFrame: (NSRect)frame
|
|
{
|
|
NSSize size = [[NSImage imageNamed: @"common_StepperDown"] size];
|
|
NSRect downRect;
|
|
|
|
downRect.size = size;
|
|
downRect.origin.x = NSMaxX(frame) - size.width;
|
|
downRect.origin.y = NSMinY(frame) + ((int)frame.size.height / 2) - size.height + 1;
|
|
return downRect;
|
|
}
|
|
|
|
- (void) drawStepperBorder: (NSRect)frame
|
|
{
|
|
}
|
|
|
|
- (NSRect) drawStepperLightButton: (NSRect)border : (NSRect)clip
|
|
{
|
|
return NSZeroRect;
|
|
}
|
|
|
|
- (void) drawStepperUpButton: (NSRect)aRect
|
|
{
|
|
NSImage *image = [NSImage imageNamed: @"common_StepperUp"];
|
|
[image drawInRect: aRect
|
|
fromRect: NSZeroRect
|
|
operation: NSCompositeSourceOver
|
|
fraction: 1
|
|
respectFlipped: YES
|
|
hints: nil];
|
|
}
|
|
|
|
- (void) drawStepperHighlightUpButton: (NSRect)aRect
|
|
{
|
|
NSImage *image = [NSImage imageNamed: @"common_StepperUpHighlighted"];
|
|
[image drawInRect: aRect
|
|
fromRect: NSZeroRect
|
|
operation: NSCompositeSourceOver
|
|
fraction: 1
|
|
respectFlipped: YES
|
|
hints: nil];
|
|
}
|
|
|
|
- (void) drawStepperDownButton: (NSRect)aRect
|
|
{
|
|
NSImage *image = [NSImage imageNamed: @"common_StepperDown"];
|
|
[image drawInRect: aRect
|
|
fromRect: NSZeroRect
|
|
operation: NSCompositeSourceOver
|
|
fraction: 1
|
|
respectFlipped: YES
|
|
hints: nil];
|
|
}
|
|
|
|
- (void) drawStepperHighlightDownButton: (NSRect)aRect
|
|
{
|
|
NSImage *image = [NSImage imageNamed: @"common_StepperDownHighlighted"];
|
|
[image drawInRect: aRect
|
|
fromRect: NSZeroRect
|
|
operation: NSCompositeSourceOver
|
|
fraction: 1
|
|
respectFlipped: YES
|
|
hints: nil];
|
|
}
|
|
|
|
- (void) drawStepperCell: (NSCell*)cell
|
|
withFrame: (NSRect)cellFrame
|
|
inView: (NSView*)controlView
|
|
highlightUp: (BOOL)highlightUp
|
|
highlightDown: (BOOL)highlightDown
|
|
{
|
|
const NSRect upRect = [self stepperUpButtonRectWithFrame: cellFrame];
|
|
const NSRect downRect = [self stepperDownButtonRectWithFrame: cellFrame];
|
|
|
|
[self drawStepperBorder: cellFrame];
|
|
|
|
if (highlightUp)
|
|
[self drawStepperHighlightUpButton: upRect];
|
|
else
|
|
[self drawStepperUpButton: upRect];
|
|
|
|
if (highlightDown)
|
|
[self drawStepperHighlightDownButton: downRect];
|
|
else
|
|
[self drawStepperDownButton: downRect];
|
|
}
|
|
|
|
// NSSegmentedControl drawing methods
|
|
|
|
- (void) drawSegmentedControlSegment: (NSCell *)cell
|
|
withFrame: (NSRect)cellFrame
|
|
inView: (NSView *)controlView
|
|
style: (NSSegmentStyle)style
|
|
state: (GSThemeControlState)state
|
|
roundedLeft: (BOOL)roundedLeft
|
|
roundedRight: (BOOL)roundedRight
|
|
{
|
|
GSDrawTiles *tiles;
|
|
NSString *name = GSStringFromSegmentStyle(style);
|
|
if (roundedLeft)
|
|
{
|
|
name = [name stringByAppendingString: @"RoundedLeft"];
|
|
}
|
|
if (roundedRight)
|
|
{
|
|
name = [name stringByAppendingString: @"RoundedRight"];
|
|
}
|
|
|
|
tiles = [self tilesNamed: name state: state];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
[self drawButton: cellFrame
|
|
in: cell
|
|
view: controlView
|
|
style: NSRegularSquareBezelStyle
|
|
state: state];
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: cellFrame
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (NSColor *) menuBackgroundColor
|
|
{
|
|
NSColor *color = [self colorNamed: @"menuBackgroundColor"
|
|
state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [NSColor windowBackgroundColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (NSColor *) menuItemBackgroundColor
|
|
{
|
|
NSColor *color = [self colorNamed: @"menuItemBackgroundColor"
|
|
state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [NSColor controlBackgroundColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (NSColor *) menuBorderColor
|
|
{
|
|
NSColor *color = [self colorNamed: @"menuBorderColor"
|
|
state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [NSColor darkGrayColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (NSColor *) menuBarBackgroundColor
|
|
{
|
|
NSColor *color = [self colorNamed: @"menuBarBackgroundColor"
|
|
state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [self menuBackgroundColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (NSColor *) menuBarBorderColor
|
|
{
|
|
NSColor *color = [self colorNamed: @"menuBarBorderColor"
|
|
state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [self menuBorderColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (NSColor *) menuBorderColorForEdge: (NSRectEdge)edge isHorizontal: (BOOL)horizontal
|
|
{
|
|
if (horizontal && edge == NSMinYEdge)
|
|
{
|
|
return [self menuBorderColor];
|
|
}
|
|
else if (edge == NSMinXEdge || edge == NSMaxYEdge)
|
|
{
|
|
// Draw the dark gray upper left lines.
|
|
return [self menuBorderColor];
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (void) drawBackgroundForMenuView: (NSMenuView*)menuView
|
|
withFrame: (NSRect)bounds
|
|
dirtyRect: (NSRect)dirtyRect
|
|
horizontal: (BOOL)horizontal
|
|
{
|
|
NSString *name = horizontal ? GSMenuHorizontalBackground :
|
|
GSMenuVerticalBackground;
|
|
GSDrawTiles *tiles = [self tilesNamed: name state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
NSRectEdge sides[4] = { NSMinXEdge, NSMaxYEdge, NSMaxXEdge, NSMinYEdge };
|
|
NSColor *colors[] = {[self menuBorderColorForEdge: NSMinXEdge isHorizontal: horizontal],
|
|
[self menuBorderColorForEdge: NSMaxYEdge isHorizontal: horizontal],
|
|
[self menuBorderColorForEdge: NSMaxXEdge isHorizontal: horizontal],
|
|
[self menuBorderColorForEdge: NSMinYEdge isHorizontal: horizontal]};
|
|
|
|
[[self menuBackgroundColor] set];
|
|
NSRectFill(NSIntersectionRect(bounds, dirtyRect));
|
|
NSDrawColorTiledRects(bounds, dirtyRect, sides, colors, 4);
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: bounds
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (BOOL) drawsBorderForMenuItemCell: (NSMenuItemCell *)cell
|
|
state: (GSThemeControlState)state
|
|
isHorizontal: (BOOL)horizontal
|
|
{
|
|
return [cell isBordered];
|
|
}
|
|
|
|
- (void) drawBorderAndBackgroundForMenuItemCell: (NSMenuItemCell *)cell
|
|
withFrame: (NSRect)cellFrame
|
|
inView: (NSView *)controlView
|
|
state: (GSThemeControlState)state
|
|
isHorizontal: (BOOL)isHorizontal
|
|
{
|
|
NSString *name = isHorizontal ? GSMenuHorizontalItem :
|
|
GSMenuVerticalItem;
|
|
GSDrawTiles *tiles = [self tilesNamed: name state: state];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
NSColor *backgroundColor = [cell backgroundColor];
|
|
|
|
if (isHorizontal)
|
|
{
|
|
cellFrame = [cell drawingRectForBounds: cellFrame];
|
|
[backgroundColor set];
|
|
NSRectFill(cellFrame);
|
|
return;
|
|
}
|
|
|
|
// Set cell's background color
|
|
[backgroundColor set];
|
|
NSRectFill(cellFrame);
|
|
|
|
if (![self drawsBorderForMenuItemCell: cell
|
|
state: state
|
|
isHorizontal: isHorizontal])
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (state == GSThemeSelectedState)
|
|
{
|
|
[self drawGrayBezel: cellFrame withClip: NSZeroRect];
|
|
}
|
|
else
|
|
{
|
|
[self drawButton: cellFrame withClip: NSZeroRect];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: cellFrame
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (NSColor *) menuSeparatorColor
|
|
{
|
|
NSColor *color = [self colorNamed: @"menuSeparatorColor"
|
|
state: GSThemeNormalState];
|
|
NSInterfaceStyle style = NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil);
|
|
|
|
// TODO: Remove the style check... Windows theming should be in a subclass
|
|
// probably
|
|
if (color == nil && style == NSWindows95InterfaceStyle)
|
|
{
|
|
color = [NSColor blackColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (CGFloat) menuSeparatorInset
|
|
{
|
|
return 3.0;
|
|
}
|
|
|
|
- (void) drawSeparatorItemForMenuItemCell: (NSMenuItemCell *)cell
|
|
withFrame: (NSRect)cellFrame
|
|
inView: (NSView *)controlView
|
|
isHorizontal: (BOOL)isHorizontal
|
|
{
|
|
GSDrawTiles *tiles = [self tilesNamed: GSMenuSeparatorItem state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
NSBezierPath *path = [NSBezierPath bezierPath];
|
|
CGFloat inset = [self menuSeparatorInset];
|
|
NSPoint start = NSMakePoint(inset, cellFrame.size.height / 2 +
|
|
cellFrame.origin.y + 0.5);
|
|
NSPoint end = NSMakePoint(cellFrame.size.width - inset,
|
|
cellFrame.size.height / 2 + cellFrame.origin.y + 0.5);
|
|
|
|
[[self menuSeparatorColor] set];
|
|
|
|
[path setLineWidth: 0.0];
|
|
[path moveToPoint: start];
|
|
[path lineToPoint: end];
|
|
|
|
[path stroke];
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: cellFrame
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (void) drawTitleForMenuItemCell: (NSMenuItemCell *)cell
|
|
withFrame: (NSRect)cellFrame
|
|
inView: (NSView *)controlView
|
|
state: (GSThemeControlState)state
|
|
isHorizontal: (BOOL)isHorizontal
|
|
{
|
|
[cell _drawText: [[cell menuItem] title]
|
|
inFrame: [cell titleRectForBounds: cellFrame]];
|
|
}
|
|
|
|
- (Class) titleViewClassForMenuView: (NSMenuView *)aMenuView
|
|
{
|
|
return [GSTitleView class];
|
|
}
|
|
|
|
- (NSRect) drawMenuTitleBackground: (GSTitleView *)aTitleView
|
|
withBounds: (NSRect)bounds
|
|
withClip: (NSRect)clipRect
|
|
{
|
|
GSDrawTiles *tiles = [self tilesNamed: GSMenuTitleBackground state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
NSRect workRect = bounds;
|
|
NSRectEdge top_left[] = {NSMinXEdge, NSMaxYEdge};
|
|
CGFloat darkGrays[] = {NSDarkGray, NSDarkGray};
|
|
NSColor *titleColor;
|
|
|
|
titleColor = [self colorNamed: @"GSMenuBar" state: GSThemeNormalState];
|
|
if (titleColor == nil)
|
|
{
|
|
titleColor = [NSColor blackColor];
|
|
}
|
|
|
|
// Draw the dark gray upper left lines for menu and black for others.
|
|
// Rectangle 1
|
|
workRect = NSDrawTiledRects(workRect, workRect, top_left, darkGrays, 2);
|
|
|
|
// Rectangle 2
|
|
// Draw the title box's button.
|
|
[self drawButton: workRect withClip: workRect];
|
|
|
|
// Overdraw white top and left lines with light gray lines for window title
|
|
workRect.origin.y += 1;
|
|
workRect.size.height -= 1;
|
|
workRect.size.width -= 1;
|
|
|
|
// Rectangle 3
|
|
// Paint background
|
|
workRect.origin.x += 1;
|
|
workRect.origin.y += 1;
|
|
workRect.size.height -= 2;
|
|
workRect.size.width -= 2;
|
|
|
|
[titleColor set];
|
|
NSRectFill(workRect);
|
|
|
|
return workRect;
|
|
}
|
|
else
|
|
{
|
|
return [self fillRect: bounds
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (CGFloat) menuBarHeight
|
|
{
|
|
CGFloat height = [[NSUserDefaults standardUserDefaults]
|
|
floatForKey: @"GSMenuBarHeight"];
|
|
if (height <= 0)
|
|
{
|
|
return 22;
|
|
}
|
|
return height;
|
|
}
|
|
|
|
- (CGFloat) menuItemHeight
|
|
{
|
|
CGFloat height = [[NSUserDefaults standardUserDefaults]
|
|
floatForKey: @"GSMenuItemHeight"];
|
|
if (height <= 0)
|
|
{
|
|
return 20;
|
|
}
|
|
return height;
|
|
}
|
|
|
|
- (CGFloat) menuSeparatorHeight
|
|
{
|
|
CGFloat height = [[NSUserDefaults standardUserDefaults]
|
|
floatForKey: @"GSMenuSeparatorHeight"];
|
|
if (height <= 0)
|
|
{
|
|
return 20;
|
|
}
|
|
return height;
|
|
}
|
|
|
|
// NSColorWell drawing method
|
|
- (NSRect) drawColorWellBorder: (NSColorWell*)well
|
|
withBounds: (NSRect)bounds
|
|
withClip: (NSRect)clipRect
|
|
{
|
|
NSRect aRect = bounds;
|
|
|
|
if ([well isBordered])
|
|
{
|
|
GSThemeControlState state;
|
|
GSDrawTiles *tiles;
|
|
|
|
if ([[well cell] isHighlighted] || [well isActive])
|
|
{
|
|
state = GSThemeHighlightedState;
|
|
}
|
|
else
|
|
{
|
|
state = GSThemeNormalState;
|
|
}
|
|
|
|
tiles = [self tilesNamed: GSColorWell state: state];
|
|
if (tiles == nil)
|
|
{
|
|
/*
|
|
* Draw border.
|
|
*/
|
|
[self drawButton: aRect withClip: clipRect];
|
|
|
|
/*
|
|
* Fill in control color.
|
|
*/
|
|
if (state == GSThemeHighlightedState)
|
|
{
|
|
[[NSColor selectedControlColor] set];
|
|
}
|
|
else
|
|
{
|
|
[[NSColor controlColor] set];
|
|
}
|
|
aRect = NSInsetRect(aRect, 2.0, 2.0);
|
|
NSRectFill(NSIntersectionRect(aRect, clipRect));
|
|
}
|
|
else
|
|
{
|
|
aRect = [self fillRect: aRect
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
|
|
/*
|
|
* Set an inset rect for the color area
|
|
*/
|
|
aRect = NSInsetRect(bounds, COLOR_WELL_BORDER_WIDTH, COLOR_WELL_BORDER_WIDTH);
|
|
}
|
|
|
|
/*
|
|
* OpenStep 4.2 behavior is to omit the inner border for
|
|
* non-enabled NSColorWell objects.
|
|
*/
|
|
if ([well isEnabled])
|
|
{
|
|
/*
|
|
* Draw inner frame.
|
|
*/
|
|
[self drawGrayBezel: aRect withClip: clipRect];
|
|
aRect = NSInsetRect(aRect, 2.0, 2.0);
|
|
}
|
|
|
|
return aRect;
|
|
}
|
|
|
|
// progress indicator drawing methods
|
|
static NSColor *fillColour = nil;
|
|
#define MaxCount 10
|
|
static int indeterminateMaxCount = MaxCount;
|
|
static int spinningMaxCount = MaxCount;
|
|
static NSColor *indeterminateColors[MaxCount];
|
|
static NSImage *spinningImages[MaxCount];
|
|
|
|
- (void) initProgressIndicatorDrawing
|
|
{
|
|
int i;
|
|
|
|
// FIXME: Should come from defaults and should be reset when defaults change
|
|
// FIXME: Should probably get the color from the color extension list (see NSToolbar)
|
|
fillColour = RETAIN([NSColor controlShadowColor]);
|
|
|
|
// Load images for indeterminate style
|
|
for (i = 0; i < MaxCount; i++)
|
|
{
|
|
NSString *imgName = [NSString stringWithFormat: @"common_ProgressIndeterminate_%d", i + 1];
|
|
NSImage *image = [NSImage imageNamed: imgName];
|
|
|
|
if (image == nil)
|
|
{
|
|
indeterminateMaxCount = i;
|
|
break;
|
|
}
|
|
indeterminateColors[i] = RETAIN([NSColor colorWithPatternImage: image]);
|
|
}
|
|
|
|
// Load images for spinning style
|
|
for (i = 0; i < MaxCount; i++)
|
|
{
|
|
NSString *imgName = [NSString stringWithFormat: @"common_ProgressSpinning_%d", i + 1];
|
|
NSImage *image = [NSImage imageNamed: imgName];
|
|
|
|
if (image == nil)
|
|
{
|
|
spinningMaxCount = i;
|
|
break;
|
|
}
|
|
spinningImages[i] = RETAIN(image);
|
|
}
|
|
}
|
|
|
|
- (void) drawProgressIndicator: (NSProgressIndicator*)progress
|
|
withBounds: (NSRect)bounds
|
|
withClip: (NSRect)rect
|
|
atCount: (int)count
|
|
forValue: (double)val
|
|
{
|
|
NSRect r;
|
|
|
|
if (fillColour == nil)
|
|
{
|
|
[self initProgressIndicatorDrawing];
|
|
}
|
|
|
|
// Draw the Bezel
|
|
if ([progress isBezeled])
|
|
{
|
|
// Calc the inside rect to be drawn
|
|
r = [self drawProgressIndicatorBezel: bounds withClip: rect];
|
|
}
|
|
else
|
|
{
|
|
r = bounds;
|
|
}
|
|
|
|
if ([progress style] == NSProgressIndicatorSpinningStyle)
|
|
{
|
|
NSRect imgBox = {{0,0}, {0,0}};
|
|
|
|
if (spinningMaxCount != 0)
|
|
{
|
|
count = count % spinningMaxCount;
|
|
imgBox.size = [spinningImages[count] size];
|
|
[spinningImages[count] drawInRect: r
|
|
fromRect: imgBox
|
|
operation: NSCompositeSourceOver
|
|
fraction: 1.0];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ([progress isIndeterminate])
|
|
{
|
|
if (indeterminateMaxCount != 0)
|
|
{
|
|
count = count % indeterminateMaxCount;
|
|
[indeterminateColors[count] set];
|
|
NSRectFill(r);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Draw determinate
|
|
if ([progress isVertical])
|
|
{
|
|
float height = NSHeight(r) * val;
|
|
|
|
if ([progress isFlipped])
|
|
{
|
|
// Compensate for the flip
|
|
r.origin.y += NSHeight(r) - height;
|
|
}
|
|
r.size.height = height;
|
|
}
|
|
else
|
|
{
|
|
r.size.width = NSWidth(r) * val;
|
|
}
|
|
r = NSIntersectionRect(r, rect);
|
|
if (!NSIsEmptyRect(r))
|
|
{
|
|
[self drawProgressIndicatorBarDeterminate: (NSRect)r];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (NSRect) drawProgressIndicatorBezel: (NSRect)bounds withClip: (NSRect) rect
|
|
{
|
|
GSDrawTiles *tiles = [self tilesNamed: GSProgressIndicatorBezel
|
|
state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
return [self drawGrayBezel: bounds withClip: rect];
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: bounds
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
|
|
return [tiles contentRectForRect: bounds];
|
|
}
|
|
}
|
|
|
|
- (void) drawProgressIndicatorBarDeterminate: (NSRect)bounds
|
|
{
|
|
GSDrawTiles *tiles = [self tilesNamed: GSProgressIndicatorBarDeterminate
|
|
state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
[fillColour set];
|
|
NSRectFill(bounds);
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: bounds
|
|
withTiles: tiles
|
|
background: fillColour];
|
|
}
|
|
}
|
|
|
|
// Table drawing methods
|
|
|
|
- (NSColor *) tableHeaderTextColorForState: (GSThemeControlState)state
|
|
{
|
|
NSColor *color;
|
|
|
|
color = [self colorNamed: @"tableHeaderTextColor"
|
|
state: state];
|
|
if (color == nil)
|
|
{
|
|
if (state == GSThemeHighlightedState)
|
|
color = [NSColor controlTextColor];
|
|
else
|
|
color = [NSColor windowFrameTextColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (void) drawTableCornerView: (NSView*)cornerView
|
|
withClip: (NSRect)aRect
|
|
{
|
|
NSRect divide;
|
|
NSRect rect;
|
|
GSDrawTiles *tiles = [self tilesNamed: GSTableCorner state: GSThemeNormalState];
|
|
|
|
if ([cornerView isFlipped])
|
|
{
|
|
NSDivideRect(aRect, ÷, &rect, 1.0, NSMaxYEdge);
|
|
}
|
|
else
|
|
{
|
|
NSDivideRect(aRect, ÷, &rect, 1.0, NSMinYEdge);
|
|
}
|
|
|
|
if (tiles == nil)
|
|
{
|
|
[[NSColor blackColor] set];
|
|
NSRectFill(divide);
|
|
rect = [self drawDarkButton: rect withClip: aRect];
|
|
[[NSColor controlShadowColor] set];
|
|
NSRectFill(rect);
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: aRect
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (void) drawTableHeaderCell: (NSTableHeaderCell *)cell
|
|
withFrame: (NSRect)cellFrame
|
|
inView: (NSView *)controlView
|
|
state: (GSThemeControlState)state
|
|
{
|
|
GSDrawTiles *tiles = [self tilesNamed: GSTableHeader state: state];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
NSRect rect;
|
|
|
|
// Leave a 1pt thick horizontal line underneath the header
|
|
if (![controlView isFlipped])
|
|
{
|
|
cellFrame.origin.y++;
|
|
}
|
|
cellFrame.size.height--;
|
|
|
|
if (state == GSThemeHighlightedState)
|
|
{
|
|
rect = [self drawButton: cellFrame withClip: cellFrame];
|
|
[[NSColor controlColor] set];
|
|
NSRectFill(rect);
|
|
}
|
|
else
|
|
{
|
|
rect = [self drawDarkButton: cellFrame withClip: cellFrame];
|
|
[[NSColor controlShadowColor] set];
|
|
NSRectFill(rect);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: cellFrame
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
|
|
// Window decoration drawing methods
|
|
/* These include the black border. */
|
|
#define TITLE_HEIGHT 23.0
|
|
#define RESIZE_HEIGHT 9.0
|
|
|
|
- (float) titlebarHeight
|
|
{
|
|
return TITLE_HEIGHT;
|
|
}
|
|
|
|
- (float) resizebarHeight
|
|
{
|
|
return RESIZE_HEIGHT;
|
|
}
|
|
|
|
static NSDictionary *titleTextAttributes[3] = {nil, nil, nil};
|
|
|
|
- (void) drawTitleBarRect: (NSRect)titleBarRect
|
|
forStyleMask: (unsigned int)styleMask
|
|
state: (int)inputState
|
|
andTitle: (NSString*)title
|
|
{
|
|
static const NSRectEdge edges[4] = {NSMinXEdge, NSMaxYEdge,
|
|
NSMaxXEdge, NSMinYEdge};
|
|
CGFloat grays[3][4] =
|
|
{{NSLightGray, NSLightGray, NSDarkGray, NSDarkGray},
|
|
{NSWhite, NSWhite, NSDarkGray, NSDarkGray},
|
|
{NSLightGray, NSLightGray, NSBlack, NSBlack}};
|
|
NSRect workRect;
|
|
GSDrawTiles *tiles = nil;
|
|
|
|
if (!titleTextAttributes[0])
|
|
{
|
|
NSMutableParagraphStyle *p;
|
|
NSColor *keyColor, *normalColor, *mainColor;
|
|
|
|
p = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
|
[p setLineBreakMode: NSLineBreakByClipping];
|
|
|
|
// FIXME: refine color names based on style mask
|
|
// (HUD or textured or regular window)
|
|
|
|
keyColor = [self colorNamed: @"keyWindowFrameTextColor"
|
|
state: GSThemeNormalState];
|
|
if (nil == keyColor)
|
|
{
|
|
keyColor = [NSColor windowFrameTextColor];
|
|
}
|
|
|
|
normalColor = [self colorNamed: @"normalWindowFrameTextColor"
|
|
state: GSThemeNormalState];
|
|
if (nil == normalColor)
|
|
{
|
|
normalColor = [NSColor blackColor];
|
|
}
|
|
|
|
mainColor = [self colorNamed: @"mainWindowFrameTextColor"
|
|
state: GSThemeNormalState];
|
|
if (nil == mainColor)
|
|
{
|
|
mainColor = [NSColor windowFrameTextColor];
|
|
}
|
|
|
|
titleTextAttributes[0] = [[NSMutableDictionary alloc]
|
|
initWithObjectsAndKeys:
|
|
[NSFont titleBarFontOfSize: 0], NSFontAttributeName,
|
|
keyColor, NSForegroundColorAttributeName,
|
|
p, NSParagraphStyleAttributeName,
|
|
nil];
|
|
|
|
titleTextAttributes[1] = [[NSMutableDictionary alloc]
|
|
initWithObjectsAndKeys:
|
|
[NSFont titleBarFontOfSize: 0], NSFontAttributeName,
|
|
normalColor, NSForegroundColorAttributeName,
|
|
p, NSParagraphStyleAttributeName,
|
|
nil];
|
|
|
|
titleTextAttributes[2] = [[NSMutableDictionary alloc]
|
|
initWithObjectsAndKeys:
|
|
[NSFont titleBarFontOfSize: 0], NSFontAttributeName,
|
|
mainColor, NSForegroundColorAttributeName,
|
|
p, NSParagraphStyleAttributeName,
|
|
nil];
|
|
|
|
RELEASE(p);
|
|
}
|
|
|
|
tiles = [self tilesNamed: @"GSWindowTitleBar" state: GSThemeNormalState];
|
|
if (tiles == nil)
|
|
{
|
|
/*
|
|
Draw the black border towards the rest of the window. (The outer black
|
|
border is drawn in -drawRect: since it might be drawn even if we don't have
|
|
a title bar.
|
|
*/
|
|
NSColor *borderColor = [self colorNamed: @"windowBorderColor"
|
|
state: GSThemeNormalState];
|
|
if (nil == borderColor)
|
|
{
|
|
borderColor = [NSColor blackColor];
|
|
}
|
|
[borderColor set];
|
|
|
|
PSmoveto(0, NSMinY(titleBarRect) + 0.5);
|
|
PSrlineto(titleBarRect.size.width, 0);
|
|
PSstroke();
|
|
|
|
/*
|
|
Draw the button-like border.
|
|
*/
|
|
workRect = titleBarRect;
|
|
workRect.origin.x += 1;
|
|
workRect.origin.y += 1;
|
|
workRect.size.width -= 2;
|
|
workRect.size.height -= 2;
|
|
|
|
workRect = NSDrawTiledRects(workRect, workRect, edges, grays[inputState], 4);
|
|
|
|
/*
|
|
Draw the background.
|
|
*/
|
|
switch (inputState)
|
|
{
|
|
default:
|
|
case 0:
|
|
[[NSColor windowFrameColor] set];
|
|
break;
|
|
case 1:
|
|
[[NSColor lightGrayColor] set];
|
|
break;
|
|
case 2:
|
|
[[NSColor darkGrayColor] set];
|
|
break;
|
|
}
|
|
NSRectFill(workRect);
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: titleBarRect
|
|
withTiles: tiles
|
|
background: [NSColor windowFrameColor]];
|
|
workRect = titleBarRect;
|
|
}
|
|
/* Draw the title. */
|
|
if (styleMask & NSTitledWindowMask)
|
|
{
|
|
NSSize titleSize;
|
|
|
|
if (styleMask & NSMiniaturizableWindowMask)
|
|
{
|
|
workRect.origin.x += 17;
|
|
workRect.size.width -= 17;
|
|
}
|
|
if (styleMask & NSClosableWindowMask)
|
|
{
|
|
workRect.size.width -= 17;
|
|
}
|
|
|
|
titleSize = [title sizeWithAttributes: titleTextAttributes[inputState]];
|
|
if (titleSize.width <= workRect.size.width)
|
|
workRect.origin.x = NSMidX(workRect) - titleSize.width / 2;
|
|
workRect.origin.y = NSMidY(workRect) - titleSize.height / 2;
|
|
workRect.size.height = titleSize.height;
|
|
[title drawInRect: workRect
|
|
withAttributes: titleTextAttributes[inputState]];
|
|
}
|
|
}
|
|
|
|
// FIXME: Would be good if this took the window as a param
|
|
- (void) drawResizeBarRect: (NSRect)resizeBarRect
|
|
{
|
|
GSDrawTiles *tiles;
|
|
tiles = [self tilesNamed: @"GSWindowResizeBar" state: GSThemeNormalState];
|
|
if (tiles == nil)
|
|
{
|
|
[[NSColor lightGrayColor] set];
|
|
PSrectfill(1.0, 1.0, resizeBarRect.size.width - 2.0, RESIZE_HEIGHT - 3.0);
|
|
|
|
PSsetlinewidth(1.0);
|
|
|
|
[[NSColor blackColor] set];
|
|
PSmoveto(0.0, 0.5);
|
|
PSlineto(resizeBarRect.size.width, 0.5);
|
|
PSstroke();
|
|
|
|
[[NSColor darkGrayColor] set];
|
|
PSmoveto(1.0, RESIZE_HEIGHT - 0.5);
|
|
PSlineto(resizeBarRect.size.width - 1.0, RESIZE_HEIGHT - 0.5);
|
|
PSstroke();
|
|
|
|
[[NSColor whiteColor] set];
|
|
PSmoveto(1.0, RESIZE_HEIGHT - 1.5);
|
|
PSlineto(resizeBarRect.size.width - 1.0, RESIZE_HEIGHT - 1.5);
|
|
PSstroke();
|
|
|
|
|
|
/* Only draw the notches if there's enough space. */
|
|
if (resizeBarRect.size.width < 30 * 2)
|
|
return;
|
|
|
|
[[NSColor darkGrayColor] set];
|
|
PSmoveto(27.5, 1.0);
|
|
PSlineto(27.5, RESIZE_HEIGHT - 2.0);
|
|
PSmoveto(resizeBarRect.size.width - 28.5, 1.0);
|
|
PSlineto(resizeBarRect.size.width - 28.5, RESIZE_HEIGHT - 2.0);
|
|
PSstroke();
|
|
|
|
[[NSColor whiteColor] set];
|
|
PSmoveto(28.5, 1.0);
|
|
PSlineto(28.5, RESIZE_HEIGHT - 2.0);
|
|
PSmoveto(resizeBarRect.size.width - 27.5, 1.0);
|
|
PSlineto(resizeBarRect.size.width - 27.5, RESIZE_HEIGHT - 2.0);
|
|
PSstroke();
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: resizeBarRect
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (void) drawWindowBorder: (NSRect)rect
|
|
withFrame: (NSRect)frame
|
|
forStyleMask: (unsigned int)styleMask
|
|
state: (int)inputState
|
|
andTitle: (NSString*)title
|
|
{
|
|
if (styleMask & (NSTitledWindowMask | NSClosableWindowMask
|
|
| NSMiniaturizableWindowMask))
|
|
{
|
|
NSRect titleBarRect;
|
|
|
|
titleBarRect = NSMakeRect(0.0, frame.size.height - TITLE_HEIGHT,
|
|
frame.size.width, TITLE_HEIGHT);
|
|
if (NSIntersectsRect(rect, titleBarRect))
|
|
[self drawTitleBarRect: titleBarRect
|
|
forStyleMask: styleMask
|
|
state: inputState
|
|
andTitle: title];
|
|
}
|
|
|
|
if (styleMask & NSResizableWindowMask)
|
|
{
|
|
NSRect resizeBarRect;
|
|
|
|
resizeBarRect = NSMakeRect(0.0, 0.0, frame.size.width, RESIZE_HEIGHT);
|
|
if (NSIntersectsRect(rect, resizeBarRect))
|
|
[self drawResizeBarRect: resizeBarRect];
|
|
}
|
|
|
|
if (styleMask & (NSTitledWindowMask | NSClosableWindowMask
|
|
| NSMiniaturizableWindowMask | NSResizableWindowMask))
|
|
{
|
|
NSColor *borderColor = [self colorNamed: @"windowBorderColor"
|
|
state: GSThemeNormalState];
|
|
if (nil == borderColor)
|
|
{
|
|
borderColor = [NSColor blackColor];
|
|
}
|
|
[borderColor set];
|
|
PSsetlinewidth(1.0);
|
|
if (NSMinX(rect) < 1.0)
|
|
{
|
|
PSmoveto(0.5, 0.0);
|
|
PSlineto(0.5, frame.size.height);
|
|
PSstroke();
|
|
}
|
|
if (NSMaxX(rect) > frame.size.width - 1.0)
|
|
{
|
|
PSmoveto(frame.size.width - 0.5, 0.0);
|
|
PSlineto(frame.size.width - 0.5, frame.size.height);
|
|
PSstroke();
|
|
}
|
|
if (NSMaxY(rect) > frame.size.height - 1.0)
|
|
{
|
|
PSmoveto(0.0, frame.size.height - 0.5);
|
|
PSlineto(frame.size.width, frame.size.height - 0.5);
|
|
PSstroke();
|
|
}
|
|
if (NSMinY(rect) < 1.0)
|
|
{
|
|
PSmoveto(0.0, 0.5);
|
|
PSlineto(frame.size.width, 0.5);
|
|
PSstroke();
|
|
}
|
|
}
|
|
}
|
|
|
|
- (NSColor *) browserHeaderTextColor
|
|
{
|
|
NSColor *color;
|
|
|
|
color = [self colorNamed: @"browserHeaderTextColor"
|
|
state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [NSColor windowFrameTextColor];
|
|
}
|
|
return color;
|
|
}
|
|
|
|
- (void) drawBrowserHeaderCell: (NSTableHeaderCell*)cell
|
|
withFrame: (NSRect)rect
|
|
inView: (NSView*)view;
|
|
{
|
|
GSDrawTiles *tiles;
|
|
tiles = [self tilesNamed: GSBrowserHeader state: GSThemeNormalState];
|
|
if (tiles == nil)
|
|
{
|
|
[self drawGrayBezel: rect withClip: NSZeroRect];
|
|
[cell _drawBackgroundWithFrame: rect inView: view];
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: rect
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (NSRect) browserHeaderDrawingRectForCell: (NSTableHeaderCell*)cell
|
|
withFrame: (NSRect)rect
|
|
{
|
|
GSDrawTiles *tiles;
|
|
tiles = [self tilesNamed: GSBrowserHeader state: GSThemeNormalState];
|
|
if (tiles == nil)
|
|
{
|
|
return NSInsetRect(rect, 2, 2);
|
|
}
|
|
else
|
|
{
|
|
NSRect result = [tiles contentRectForRect: rect];
|
|
return result;
|
|
}
|
|
}
|
|
|
|
typedef enum {
|
|
GSTabSelectedLeft,
|
|
GSTabSelectedRight,
|
|
GSTabSelectedToUnSelectedJunction,
|
|
GSTabSelectedFill,
|
|
GSTabUnSelectedLeft,
|
|
GSTabUnSelectedRight,
|
|
GSTabUnSelectedToSelectedJunction,
|
|
GSTabUnSelectedJunction,
|
|
GSTabUnSelectedFill,
|
|
GSTabBackgroundFill
|
|
} GSTabPart;
|
|
|
|
- (NSImage *)imageForTabPart: (GSTabPart)part type: (NSTabViewType)type
|
|
{
|
|
NSMutableString *imageName = [NSMutableString stringWithCapacity: 32];
|
|
NSString *typeString = nil;
|
|
NSString *partString = nil;
|
|
|
|
switch (type)
|
|
{
|
|
case NSTopTabsBezelBorder:
|
|
typeString = @"";
|
|
break;
|
|
case NSBottomTabsBezelBorder:
|
|
typeString = @"Down";
|
|
break;
|
|
case NSLeftTabsBezelBorder:
|
|
typeString = @"Left";
|
|
break;
|
|
case NSRightTabsBezelBorder:
|
|
typeString = @"Right";
|
|
break;
|
|
default:
|
|
return nil;
|
|
}
|
|
|
|
switch (part)
|
|
{
|
|
case GSTabSelectedLeft:
|
|
partString = @"SelectedLeft";
|
|
break;
|
|
case GSTabSelectedRight:
|
|
partString = @"SelectedRight";
|
|
break;
|
|
case GSTabSelectedToUnSelectedJunction:
|
|
partString = @"SelectedToUnSelectedJunction";
|
|
break;
|
|
case GSTabSelectedFill:
|
|
return nil;
|
|
case GSTabUnSelectedLeft:
|
|
partString = @"UnSelectedLeft";
|
|
break;
|
|
case GSTabUnSelectedRight:
|
|
partString = @"UnSelectedRight";
|
|
break;
|
|
case GSTabUnSelectedToSelectedJunction:
|
|
partString = @"UnSelectedToSelectedJunction";
|
|
break;
|
|
case GSTabUnSelectedJunction:
|
|
partString = @"UnSelectedJunction";
|
|
break;
|
|
case GSTabUnSelectedFill:
|
|
case GSTabBackgroundFill:
|
|
return nil;
|
|
}
|
|
|
|
[imageName appendString: @"common_Tab"];
|
|
[imageName appendString: typeString];
|
|
[imageName appendString: partString];
|
|
|
|
return [NSImage imageNamed: imageName];
|
|
}
|
|
|
|
- (GSDrawTiles *)tilesForTabPart: (GSTabPart)part type: (NSTabViewType)type
|
|
{
|
|
NSString *name = nil;
|
|
|
|
if (type == NSTopTabsBezelBorder)
|
|
{
|
|
if (part == GSTabSelectedFill)
|
|
name = GSTabViewSelectedTabFill;
|
|
else if (part == GSTabUnSelectedFill)
|
|
name = GSTabViewUnSelectedTabFill;
|
|
else if (part == GSTabBackgroundFill)
|
|
name = GSTabViewBackgroundTabFill;
|
|
}
|
|
else if (type == NSBottomTabsBezelBorder)
|
|
{
|
|
if (part == GSTabSelectedFill)
|
|
name = GSTabViewBottomSelectedTabFill;
|
|
else if (part == GSTabUnSelectedFill)
|
|
name = GSTabViewBottomUnSelectedTabFill;
|
|
else if (part == GSTabBackgroundFill)
|
|
name = GSTabViewBottomBackgroundTabFill;
|
|
}
|
|
else if (type == NSLeftTabsBezelBorder)
|
|
{
|
|
if (part == GSTabSelectedFill)
|
|
name = GSTabViewLeftSelectedTabFill;
|
|
else if (part == GSTabUnSelectedFill)
|
|
name = GSTabViewLeftUnSelectedTabFill;
|
|
else if (part == GSTabBackgroundFill)
|
|
name = GSTabViewLeftBackgroundTabFill;
|
|
}
|
|
else if (type == NSRightTabsBezelBorder)
|
|
{
|
|
if (part == GSTabSelectedFill)
|
|
name = GSTabViewRightSelectedTabFill;
|
|
else if (part == GSTabUnSelectedFill)
|
|
name = GSTabViewRightUnSelectedTabFill;
|
|
else if (part == GSTabBackgroundFill)
|
|
name = GSTabViewRightBackgroundTabFill;
|
|
}
|
|
|
|
return [self tilesNamed: name state: GSThemeNormalState];
|
|
}
|
|
|
|
- (void) frameTabRectTopAndBottom: (NSRect)aRect
|
|
topColor: (NSColor *)topColor
|
|
bottomColor: (NSColor *)bottomColor
|
|
{
|
|
NSRect bottom = aRect;
|
|
NSRect top = aRect;
|
|
|
|
top.size.height = 1;
|
|
bottom.origin.y = NSMaxY(aRect) - 1;
|
|
bottom.size.height = 1;
|
|
|
|
[topColor set];
|
|
NSRectFill(top);
|
|
|
|
[bottomColor set];
|
|
NSRectFill(bottom);
|
|
}
|
|
|
|
- (void) drawTabFillInRect: (NSRect)aRect forPart: (GSTabPart)part type: (NSTabViewType)type
|
|
{
|
|
GSDrawTiles *tiles = [self tilesForTabPart: part type: type];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
if (type == NSBottomTabsBezelBorder)
|
|
{
|
|
switch (part)
|
|
{
|
|
case GSTabSelectedFill:
|
|
[self frameTabRectTopAndBottom: aRect
|
|
topColor: [NSColor clearColor]
|
|
bottomColor: [NSColor whiteColor]];
|
|
break;
|
|
case GSTabUnSelectedFill:
|
|
[self frameTabRectTopAndBottom: aRect
|
|
topColor: [NSColor darkGrayColor]
|
|
bottomColor: [NSColor whiteColor]];
|
|
break;
|
|
case GSTabBackgroundFill:
|
|
{
|
|
const NSRect clip = aRect;
|
|
aRect.origin.x -= 2;
|
|
aRect.origin.y = NSMinY(aRect) - 2;
|
|
aRect.size.width += 2;
|
|
aRect.size.height = 4;
|
|
[self drawButton: aRect withClip: clip];
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (type == NSTopTabsBezelBorder)
|
|
{
|
|
switch (part)
|
|
{
|
|
case GSTabSelectedFill:
|
|
[self frameTabRectTopAndBottom: aRect
|
|
topColor: [NSColor whiteColor]
|
|
bottomColor: [NSColor clearColor]];
|
|
break;
|
|
case GSTabUnSelectedFill:
|
|
[self frameTabRectTopAndBottom: aRect
|
|
topColor: [NSColor whiteColor]
|
|
bottomColor: [NSColor whiteColor]];
|
|
break;
|
|
case GSTabBackgroundFill:
|
|
{
|
|
const NSRect clip = aRect;
|
|
aRect.origin.x -= 2;
|
|
aRect.origin.y = NSMaxY(aRect) - 1;
|
|
aRect.size.width += 2;
|
|
aRect.size.height = 4;
|
|
[self drawButton: aRect withClip: clip];
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: aRect
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (CGFloat) tabHeightForType: (NSTabViewType)type
|
|
{
|
|
NSImage *img = [self imageForTabPart: GSTabUnSelectedLeft type: type];
|
|
if (img == nil)
|
|
{
|
|
return 0;
|
|
}
|
|
return [img size].height;
|
|
}
|
|
|
|
- (NSRect) tabViewBackgroundRectForBounds: (NSRect)aRect
|
|
tabViewType: (NSTabViewType)type
|
|
{
|
|
const CGFloat tabHeight = [self tabHeightForType: type];
|
|
|
|
switch (type)
|
|
{
|
|
default:
|
|
case NSTopTabsBezelBorder:
|
|
aRect.size.height -= tabHeight;
|
|
aRect.origin.y += tabHeight;
|
|
break;
|
|
|
|
case NSBottomTabsBezelBorder:
|
|
aRect.size.height -= tabHeight;
|
|
break;
|
|
|
|
case NSLeftTabsBezelBorder:
|
|
aRect.size.width -= tabHeight;
|
|
aRect.origin.x += tabHeight;
|
|
break;
|
|
|
|
case NSRightTabsBezelBorder:
|
|
aRect.size.width -= tabHeight;
|
|
break;
|
|
|
|
case NSNoTabsBezelBorder:
|
|
case NSNoTabsLineBorder:
|
|
case NSNoTabsNoBorder:
|
|
break;
|
|
}
|
|
|
|
return aRect;
|
|
}
|
|
|
|
|
|
- (NSRect) tabViewContentRectForBounds: (NSRect)aRect
|
|
tabViewType: (NSTabViewType)type
|
|
tabView: (NSTabView *)view
|
|
{
|
|
NSRect cRect = [self tabViewBackgroundRectForBounds: aRect
|
|
tabViewType: type];
|
|
NSString *name = GSStringFromTabViewType(type);
|
|
GSDrawTiles *tiles = [self tilesNamed: name state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
switch (type)
|
|
{
|
|
case NSBottomTabsBezelBorder:
|
|
cRect.origin.x += 1;
|
|
cRect.origin.y += 1;
|
|
cRect.size.width -= 3;
|
|
cRect.size.height -= 2;
|
|
break;
|
|
case NSNoTabsBezelBorder:
|
|
cRect.origin.x += 1;
|
|
cRect.origin.y += 1;
|
|
cRect.size.width -= 3;
|
|
cRect.size.height -= 2;
|
|
break;
|
|
case NSNoTabsLineBorder:
|
|
cRect.origin.y += 1;
|
|
cRect.origin.x += 1;
|
|
cRect.size.width -= 2;
|
|
cRect.size.height -= 2;
|
|
break;
|
|
case NSTopTabsBezelBorder:
|
|
cRect.origin.x += 1;
|
|
cRect.origin.y += 1;
|
|
cRect.size.width -= 3;
|
|
cRect.size.height -= 2;
|
|
break;
|
|
case NSLeftTabsBezelBorder:
|
|
cRect.origin.x += 1;
|
|
cRect.origin.y += 1;
|
|
cRect.size.width -= 3;
|
|
cRect.size.height -= 2;
|
|
break;
|
|
case NSRightTabsBezelBorder:
|
|
cRect.origin.x += 1;
|
|
cRect.origin.y += 1;
|
|
cRect.size.width -= 3;
|
|
cRect.size.height -= 2;
|
|
break;
|
|
case NSNoTabsNoBorder:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cRect = [tiles contentRectForRect: cRect];
|
|
}
|
|
return cRect;
|
|
}
|
|
|
|
|
|
- (void) drawTabViewBezelRect: (NSRect)aRect
|
|
tabViewType: (NSTabViewType)type
|
|
inView: (NSView *)view
|
|
{
|
|
NSString *name = GSStringFromTabViewType(type);
|
|
GSDrawTiles *tiles = [self tilesNamed: name state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
switch (type)
|
|
{
|
|
default:
|
|
case NSTopTabsBezelBorder:
|
|
{
|
|
const NSRect clip = aRect;
|
|
aRect.size.height += 1;
|
|
aRect.origin.y -= 1;
|
|
[self drawButton: aRect withClip: clip];
|
|
break;
|
|
}
|
|
case NSBottomTabsBezelBorder:
|
|
{
|
|
const NSRect clip = aRect;
|
|
aRect.size.height += 2;
|
|
[self drawButton: aRect withClip: clip];
|
|
break;
|
|
}
|
|
case NSLeftTabsBezelBorder:
|
|
case NSRightTabsBezelBorder:
|
|
[self drawButton: aRect withClip: NSZeroRect];
|
|
break;
|
|
case NSNoTabsBezelBorder:
|
|
break;
|
|
case NSNoTabsLineBorder:
|
|
[[NSColor controlDarkShadowColor] set];
|
|
NSFrameRect(aRect);
|
|
break;
|
|
case NSNoTabsNoBorder:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: aRect
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (void) drawTabViewRect: (NSRect)rect
|
|
inView: (NSView *)view
|
|
withItems: (NSArray *)items
|
|
selectedItem: (NSTabViewItem *)selected
|
|
{
|
|
NSGraphicsContext *ctxt = GSCurrentContext();
|
|
const NSUInteger howMany = [items count];
|
|
int i;
|
|
int previousState = 0;
|
|
const NSTabViewType type = [(NSTabView *)view tabViewType];
|
|
const NSRect bounds = [view bounds];
|
|
NSRect aRect = [self tabViewBackgroundRectForBounds: bounds tabViewType: type];
|
|
|
|
const BOOL truncate = [(NSTabView *)view allowsTruncatedLabels];
|
|
const CGFloat tabHeight = [self tabHeightForType: type];
|
|
|
|
DPSgsave(ctxt);
|
|
|
|
[self drawTabViewBezelRect: aRect
|
|
tabViewType: type
|
|
inView: view];
|
|
|
|
if (type == NSBottomTabsBezelBorder
|
|
|| type == NSTopTabsBezelBorder)
|
|
{
|
|
NSPoint iP;
|
|
if (type == NSTopTabsBezelBorder)
|
|
iP = bounds.origin;
|
|
else
|
|
iP = NSMakePoint(aRect.origin.x, NSMaxY(aRect));
|
|
|
|
for (i = 0; i < howMany; i++)
|
|
{
|
|
NSRect r;
|
|
NSTabViewItem *anItem = [items objectAtIndex: i];
|
|
const NSTabState itemState = [anItem tabState];
|
|
const NSSize s = [anItem sizeOfLabel: truncate];
|
|
|
|
// Draw the left image
|
|
|
|
if (i == 0)
|
|
{
|
|
NSImage *part = nil;
|
|
if (itemState == NSSelectedTab)
|
|
{
|
|
part = [self imageForTabPart: GSTabSelectedLeft type: type];
|
|
}
|
|
else if (itemState == NSBackgroundTab)
|
|
{
|
|
part = [self imageForTabPart: GSTabUnSelectedLeft type: type];
|
|
}
|
|
else
|
|
NSLog(@"Not finished yet. Luff ya.\n");
|
|
|
|
[part drawInRect: NSMakeRect(iP.x, iP.y, [part size].width, [part size].height)
|
|
fromRect: NSZeroRect
|
|
operation: NSCompositeSourceOver
|
|
fraction: 1.0
|
|
respectFlipped: YES
|
|
hints: nil];
|
|
|
|
iP.x += [part size].width;
|
|
}
|
|
else
|
|
{
|
|
NSImage *part = nil;
|
|
if (itemState == NSSelectedTab)
|
|
{
|
|
part = [self imageForTabPart: GSTabUnSelectedToSelectedJunction type: type];
|
|
}
|
|
else if (itemState == NSBackgroundTab)
|
|
{
|
|
if (previousState == NSSelectedTab)
|
|
{
|
|
part = [self imageForTabPart: GSTabSelectedToUnSelectedJunction type: type];
|
|
}
|
|
else
|
|
{
|
|
part = [self imageForTabPart: GSTabUnSelectedJunction type: type];
|
|
}
|
|
}
|
|
else
|
|
NSLog(@"Not finished yet. Luff ya.\n");
|
|
|
|
[part drawInRect: NSMakeRect(iP.x, iP.y, [part size].width, [part size].height)
|
|
fromRect: NSZeroRect
|
|
operation: NSCompositeSourceOver
|
|
fraction: 1.0
|
|
respectFlipped: YES
|
|
hints: nil];
|
|
|
|
iP.x += [part size].width;
|
|
}
|
|
|
|
// Draw the middle fill part of the tab
|
|
|
|
r.origin = iP;
|
|
r.size.width = s.width;
|
|
r.size.height = tabHeight;
|
|
|
|
if (itemState == NSSelectedTab)
|
|
{
|
|
[self drawTabFillInRect: r forPart: GSTabSelectedFill type: type];
|
|
}
|
|
else if (itemState == NSBackgroundTab)
|
|
{
|
|
[self drawTabFillInRect: r forPart: GSTabUnSelectedFill type: type];
|
|
}
|
|
else
|
|
NSLog(@"Not finished yet. Luff ya.\n");
|
|
|
|
// Label
|
|
[anItem drawLabel: truncate inRect: r];
|
|
|
|
iP.x += s.width;
|
|
previousState = itemState;
|
|
|
|
// For the rightmost tab, draw the right side
|
|
|
|
if (i == howMany - 1)
|
|
{
|
|
NSImage *part = nil;
|
|
if ([anItem tabState] == NSSelectedTab)
|
|
{
|
|
part = [self imageForTabPart: GSTabSelectedRight type: type];
|
|
}
|
|
else if ([anItem tabState] == NSBackgroundTab)
|
|
{
|
|
part = [self imageForTabPart: GSTabUnSelectedRight type: type];
|
|
}
|
|
else
|
|
NSLog(@"Not finished yet. Luff ya.\n");
|
|
|
|
[part drawInRect: NSMakeRect(iP.x, iP.y, [part size].width, [part size].height)
|
|
fromRect: NSZeroRect
|
|
operation: NSCompositeSourceOver
|
|
fraction: 1.0
|
|
respectFlipped: YES
|
|
hints: nil];
|
|
|
|
iP.x += [part size].width;
|
|
|
|
// Draw the background fill
|
|
if (iP.x < NSMaxX(bounds))
|
|
{
|
|
r.origin = iP;
|
|
r.size.width = NSMaxX(bounds) - iP.x;
|
|
r.size.height = tabHeight;
|
|
|
|
[self drawTabFillInRect: r forPart: GSTabBackgroundFill type: type];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// FIXME: Missing drawing code for other cases
|
|
|
|
DPSgrestore(ctxt);
|
|
}
|
|
|
|
- (void) drawScrollerRect: (NSRect)rect
|
|
inView: (NSView *)view
|
|
hitPart: (NSScrollerPart)hitPart
|
|
isHorizontal: (BOOL)isHorizontal
|
|
{
|
|
NSRect rectForPartIncrementLine;
|
|
NSRect rectForPartDecrementLine;
|
|
NSRect rectForPartKnobSlot;
|
|
NSScroller *scroller = (NSScroller *)view;
|
|
|
|
rectForPartIncrementLine = [scroller rectForPart: NSScrollerIncrementLine];
|
|
rectForPartDecrementLine = [scroller rectForPart: NSScrollerDecrementLine];
|
|
rectForPartKnobSlot = [scroller rectForPart: NSScrollerKnobSlot];
|
|
|
|
[[[view window] backgroundColor] set];
|
|
NSRectFill (rect);
|
|
|
|
if (NSIntersectsRect (rect, rectForPartKnobSlot) == YES)
|
|
{
|
|
[scroller drawKnobSlot];
|
|
[scroller drawKnob];
|
|
}
|
|
|
|
if (NSIntersectsRect (rect, rectForPartDecrementLine) == YES)
|
|
{
|
|
[scroller drawArrow: NSScrollerDecrementArrow
|
|
highlight: hitPart == NSScrollerDecrementLine];
|
|
}
|
|
if (NSIntersectsRect (rect, rectForPartIncrementLine) == YES)
|
|
{
|
|
[scroller drawArrow: NSScrollerIncrementArrow
|
|
highlight: hitPart == NSScrollerIncrementLine];
|
|
}
|
|
}
|
|
|
|
- (void) drawBrowserRect: (NSRect)rect
|
|
inView: (NSView *)view
|
|
withScrollerRect: (NSRect)scrollerRect
|
|
columnSize: (NSSize)columnSize
|
|
{
|
|
NSBrowser *browser = (NSBrowser *)view;
|
|
NSRect bounds = [view bounds];
|
|
|
|
// Load the first column if not already done
|
|
if (![browser isLoaded])
|
|
{
|
|
[browser loadColumnZero];
|
|
}
|
|
|
|
// Draws titles
|
|
if ([browser isTitled])
|
|
{
|
|
int i;
|
|
|
|
for (i = [browser firstVisibleColumn];
|
|
i <= [browser lastVisibleColumn];
|
|
++i)
|
|
{
|
|
NSRect titleRect = [browser titleFrameOfColumn: i];
|
|
if (NSIntersectsRect (titleRect, rect) == YES)
|
|
{
|
|
[browser drawTitleOfColumn: i
|
|
inRect: titleRect];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draws scroller border
|
|
|
|
if ([self browserUseBezels])
|
|
{
|
|
if ([browser hasHorizontalScroller] &&
|
|
[browser separatesColumns])
|
|
{
|
|
NSRect scrollerBorderRect = scrollerRect;
|
|
NSSize bs = [self sizeForBorderType: NSBezelBorder];
|
|
|
|
scrollerBorderRect.origin.x = 0;
|
|
scrollerBorderRect.origin.y = 0;
|
|
scrollerBorderRect.size.width += 2 * bs.width;
|
|
scrollerBorderRect.size.height += (2 * bs.height) - 1;
|
|
|
|
if ((NSIntersectsRect (scrollerBorderRect, rect) == YES) && [view window])
|
|
{
|
|
[self drawGrayBezel: scrollerBorderRect withClip: rect];
|
|
}
|
|
}
|
|
|
|
if (![browser separatesColumns])
|
|
{
|
|
NSPoint p1,p2;
|
|
int i, visibleColumns;
|
|
float hScrollerWidth = [browser hasHorizontalScroller] ?
|
|
[NSScroller scrollerWidth] : 0;
|
|
|
|
// Columns borders
|
|
[self drawGrayBezel: bounds withClip: rect];
|
|
|
|
[[NSColor blackColor] set];
|
|
visibleColumns = [browser numberOfVisibleColumns];
|
|
for (i = 1; i < visibleColumns; i++)
|
|
{
|
|
p1 = NSMakePoint((columnSize.width * i) + 2 + (i-1),
|
|
columnSize.height + hScrollerWidth + 2);
|
|
p2 = NSMakePoint((columnSize.width * i) + 2 + (i-1),
|
|
hScrollerWidth + 2);
|
|
[NSBezierPath strokeLineFromPoint: p1 toPoint: p2];
|
|
}
|
|
|
|
// Horizontal scroller border
|
|
if ([browser hasHorizontalScroller])
|
|
{
|
|
p1 = NSMakePoint(2, hScrollerWidth + 2);
|
|
p2 = NSMakePoint(rect.size.width - 2, hScrollerWidth + 2);
|
|
[NSBezierPath strokeLineFromPoint: p1 toPoint: p2];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (![self browserUseBezels]
|
|
&& [self scrollViewScrollersOverlapBorders])
|
|
{
|
|
NSRect baseRect = NSMakeRect(0, 0, bounds.size.width, 1);
|
|
NSRect colFrame = [browser frameOfColumn: [browser firstVisibleColumn]];
|
|
NSRect scrollViewRect = NSUnionRect(baseRect, colFrame);
|
|
|
|
GSDrawTiles *tiles = [self tilesNamed: @"NSScrollView"
|
|
state: GSThemeNormalState];
|
|
|
|
[self fillRect: scrollViewRect
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
|
|
- (CGFloat) browserColumnSeparation
|
|
{
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
if ([defs objectForKey: @"GSBrowserColumnSeparation"] != nil)
|
|
{
|
|
return [defs floatForKey: @"GSBrowserColumnSeparation"];
|
|
}
|
|
else
|
|
{
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
- (CGFloat) browserVerticalPadding
|
|
{
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
if ([defs objectForKey: @"GSBrowserVerticalPadding"] != nil)
|
|
{
|
|
return [defs floatForKey: @"GSBrowserVerticalPadding"];
|
|
}
|
|
else
|
|
{
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
- (BOOL) browserUseBezels
|
|
{
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
if ([defs objectForKey: @"GSBrowserUseBezels"] != nil)
|
|
{
|
|
return [defs boolForKey: @"GSBrowserUseBezels"];
|
|
}
|
|
else
|
|
{
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
- (void) drawMenuRect: (NSRect)rect
|
|
inView: (NSView *)view
|
|
isHorizontal: (BOOL)horizontal
|
|
itemCells: (NSArray *)itemCells
|
|
{
|
|
int i = 0;
|
|
int howMany = [itemCells count];
|
|
NSMenuView *menuView = (NSMenuView *)view;
|
|
NSRect bounds = [view bounds];
|
|
|
|
[self drawBackgroundForMenuView: menuView
|
|
withFrame: bounds
|
|
dirtyRect: rect
|
|
horizontal: horizontal];
|
|
|
|
// Draw the menu cells.
|
|
for (i = 0; i < howMany; i++)
|
|
{
|
|
NSRect aRect;
|
|
NSMenuItemCell *aCell;
|
|
|
|
aRect = [menuView rectOfItemAtIndex: i];
|
|
if (NSIntersectsRect(rect, aRect) == YES)
|
|
{
|
|
aCell = [menuView menuItemCellForItemAtIndex: i];
|
|
[aCell drawWithFrame: aRect inView: menuView];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) drawScrollViewRect: (NSRect)rect
|
|
inView: (NSView *)view
|
|
{
|
|
NSScrollView *scrollView = (NSScrollView *)view;
|
|
NSGraphicsContext *ctxt = GSCurrentContext();
|
|
GSTheme *theme = [GSTheme theme];
|
|
NSColor *color;
|
|
NSString *name;
|
|
NSBorderType borderType = [scrollView borderType];
|
|
NSRect bounds = [view bounds];
|
|
BOOL hasInnerBorder = ![[NSUserDefaults standardUserDefaults]
|
|
boolForKey: @"GSScrollViewNoInnerBorder"];
|
|
GSDrawTiles *tiles = nil;
|
|
|
|
name = [theme nameForElement: self];
|
|
if (name == nil)
|
|
{
|
|
name = @"NSScrollView";
|
|
}
|
|
color = [theme colorNamed: name state: GSThemeNormalState];
|
|
tiles = [theme tilesNamed: name state: GSThemeNormalState];
|
|
if (color == nil)
|
|
{
|
|
color = [NSColor controlDarkShadowColor];
|
|
}
|
|
|
|
if (tiles == nil)
|
|
{
|
|
switch (borderType)
|
|
{
|
|
case NSNoBorder:
|
|
break;
|
|
|
|
case NSLineBorder:
|
|
[color set];
|
|
NSFrameRect(bounds);
|
|
break;
|
|
|
|
case NSBezelBorder:
|
|
[theme drawGrayBezel: bounds withClip: rect];
|
|
break;
|
|
|
|
case NSGrooveBorder:
|
|
[theme drawGroove: bounds withClip: rect];
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[self fillRect: bounds
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
|
|
if (hasInnerBorder)
|
|
{
|
|
NSScroller *vertScroller = [scrollView verticalScroller];
|
|
NSScroller *horizScroller = [scrollView horizontalScroller];
|
|
CGFloat scrollerWidth = [NSScroller scrollerWidth];
|
|
|
|
[color set];
|
|
DPSsetlinewidth(ctxt, 1);
|
|
|
|
if ([scrollView hasVerticalScroller])
|
|
{
|
|
NSInterfaceStyle style;
|
|
|
|
style = NSInterfaceStyleForKey(@"NSScrollViewInterfaceStyle", nil);
|
|
if (style == NSMacintoshInterfaceStyle
|
|
|| style == NSWindows95InterfaceStyle)
|
|
{
|
|
DPSmoveto(ctxt, [vertScroller frame].origin.x - 1,
|
|
[vertScroller frame].origin.y - 1);
|
|
}
|
|
else
|
|
{
|
|
DPSmoveto(ctxt, [vertScroller frame].origin.x + scrollerWidth,
|
|
[vertScroller frame].origin.y - 1);
|
|
}
|
|
DPSrlineto(ctxt, 0, [vertScroller frame].size.height + 1);
|
|
DPSstroke(ctxt);
|
|
}
|
|
|
|
if ([scrollView hasHorizontalScroller])
|
|
{
|
|
float ypos;
|
|
float scrollerY = [horizScroller frame].origin.y;
|
|
|
|
if ([scrollView isFlipped])
|
|
{
|
|
ypos = scrollerY - 1;
|
|
}
|
|
else
|
|
{
|
|
ypos = scrollerY + scrollerWidth + 1;
|
|
}
|
|
|
|
DPSmoveto(ctxt, [horizScroller frame].origin.x - 1, ypos);
|
|
DPSrlineto(ctxt, [horizScroller frame].size.width + 1, 0);
|
|
DPSstroke(ctxt);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) drawSliderBorderAndBackground: (NSBorderType)aType
|
|
frame: (NSRect)cellFrame
|
|
inCell: (NSCell *)cell
|
|
isHorizontal: (BOOL)horizontal
|
|
{
|
|
NSSliderType type = [(NSSliderCell *)cell sliderType];
|
|
if (type == NSLinearSlider)
|
|
{
|
|
NSString *partName = (horizontal ? GSSliderHorizontalTrack : GSSliderVerticalTrack);
|
|
GSDrawTiles *tiles = [self tilesNamed: partName
|
|
state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
[[GSTheme theme] drawBorderType: aType
|
|
frame: cellFrame
|
|
view: [cell controlView]];
|
|
}
|
|
else
|
|
{
|
|
// FIXME: This code could be factored out
|
|
NSSize tilesNaturalSize = [tiles size];
|
|
NSRect tilesRect;
|
|
|
|
// Only stretch the tiles in one direction
|
|
if (horizontal)
|
|
{
|
|
tilesRect.size = NSMakeSize(cellFrame.size.width, tilesNaturalSize.height);
|
|
}
|
|
else
|
|
{
|
|
tilesRect.size = NSMakeSize(tilesNaturalSize.width, cellFrame.size.height);
|
|
}
|
|
tilesRect.origin = NSMakePoint((cellFrame.size.width - tilesRect.size.width) / 2.0,
|
|
(cellFrame.size.height - tilesRect.size.height) / 2.0);
|
|
|
|
if ([cell controlView] != nil)
|
|
{
|
|
tilesRect = [[cell controlView] centerScanRect: tilesRect];
|
|
}
|
|
|
|
[self fillRect: tilesRect
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) drawBarInside: (NSRect)rect
|
|
inCell: (NSCell *)cell
|
|
flipped: (BOOL)flipped
|
|
{
|
|
NSSliderType type = [(NSSliderCell *)cell sliderType];
|
|
if (type == NSLinearSlider)
|
|
{
|
|
BOOL horizontal = (rect.size.width > rect.size.height);
|
|
NSString *partName = (horizontal ? GSSliderHorizontalTrack : GSSliderVerticalTrack);
|
|
GSDrawTiles *tiles = [self tilesNamed: partName
|
|
state: GSThemeNormalState];
|
|
|
|
if (tiles == nil)
|
|
{
|
|
[[NSColor scrollBarColor] set];
|
|
NSRectFill(rect);
|
|
}
|
|
// Don't draw anything if we have tiles, they are drawn
|
|
// in -drawSliderBorderAndBackground:...
|
|
}
|
|
}
|
|
|
|
- (void) drawKnobInCell: (NSCell *)cell
|
|
{
|
|
NSView *controlView = [cell controlView];
|
|
NSSliderCell *sliderCell = (NSSliderCell *)cell;
|
|
|
|
[sliderCell drawKnob:
|
|
[sliderCell knobRectFlipped:
|
|
[controlView isFlipped]]];
|
|
}
|
|
|
|
- (NSRect) tableHeaderCellDrawingRectForBounds: (NSRect)theRect
|
|
{
|
|
NSSize borderSize;
|
|
|
|
// This adjustment must match the drawn border
|
|
borderSize = NSMakeSize(1, 1);
|
|
|
|
return NSInsetRect(theRect, borderSize.width, borderSize.height);
|
|
}
|
|
|
|
- (void)drawTableHeaderRect: (NSRect)aRect
|
|
inView: (NSView *)view
|
|
{
|
|
NSTableHeaderView *tableHeaderView = (NSTableHeaderView *)view;
|
|
NSTableView *tableView = [tableHeaderView tableView];
|
|
NSArray *columns;
|
|
int firstColumnToDraw;
|
|
int lastColumnToDraw;
|
|
NSRect drawingRect;
|
|
NSTableColumn *column;
|
|
NSTableColumn *highlightedTableColumn;
|
|
float width;
|
|
int i;
|
|
NSCell *cell;
|
|
|
|
if (tableView == nil)
|
|
return;
|
|
|
|
firstColumnToDraw = [tableHeaderView columnAtPoint: NSMakePoint (aRect.origin.x,
|
|
aRect.origin.y)];
|
|
if (firstColumnToDraw == -1)
|
|
firstColumnToDraw = 0;
|
|
|
|
lastColumnToDraw = [tableHeaderView columnAtPoint: NSMakePoint (NSMaxX (aRect),
|
|
aRect.origin.y)];
|
|
if (lastColumnToDraw == -1)
|
|
lastColumnToDraw = [tableView numberOfColumns] - 1;
|
|
|
|
drawingRect = [tableHeaderView headerRectOfColumn: firstColumnToDraw];
|
|
|
|
columns = [tableView tableColumns];
|
|
highlightedTableColumn = [tableView highlightedTableColumn];
|
|
|
|
for (i = firstColumnToDraw; i <= lastColumnToDraw; i++)
|
|
{
|
|
column = [columns objectAtIndex: i];
|
|
width = [column width];
|
|
drawingRect.size.width = width;
|
|
cell = [column headerCell];
|
|
if ((column == highlightedTableColumn)
|
|
|| [tableView isColumnSelected: i])
|
|
{
|
|
[cell setHighlighted: YES];
|
|
}
|
|
else
|
|
{
|
|
[cell setHighlighted: NO];
|
|
}
|
|
[cell drawWithFrame: drawingRect
|
|
inView: tableHeaderView];
|
|
drawingRect.origin.x += width;
|
|
}
|
|
}
|
|
|
|
- (void) drawPopUpButtonCellInteriorWithFrame: (NSRect)cellFrame
|
|
withCell: (NSCell *)cell
|
|
inView: (NSView *)controlView
|
|
{
|
|
// Default implementation of this method does nothing.
|
|
}
|
|
|
|
- (void) drawTableViewBackgroundInClipRect: (NSRect)aRect
|
|
inView: (NSView *)view
|
|
withBackgroundColor: (NSColor *)backgroundColor
|
|
{
|
|
NSTableView *tableView = (NSTableView *)view;
|
|
|
|
[backgroundColor set];
|
|
NSRectFill (aRect);
|
|
|
|
if ([tableView usesAlternatingRowBackgroundColors])
|
|
{
|
|
const CGFloat rowHeight = [tableView rowHeight];
|
|
NSInteger startingRow = [tableView rowAtPoint: NSMakePoint(0, NSMinY(aRect))];
|
|
NSInteger endingRow;
|
|
NSInteger i;
|
|
|
|
NSArray *rowColors = [NSColor controlAlternatingRowBackgroundColors];
|
|
const NSUInteger rowColorCount = [rowColors count];
|
|
|
|
NSRect rowRect;
|
|
|
|
if (rowHeight <= 0
|
|
|| rowColorCount == 0
|
|
|| aRect.size.height <= 0)
|
|
return;
|
|
|
|
if (startingRow <= 0)
|
|
startingRow = 0;
|
|
|
|
rowRect = [tableView rectOfRow: startingRow];
|
|
rowRect.origin.x = aRect.origin.x;
|
|
rowRect.size.width = aRect.size.width;
|
|
|
|
endingRow = startingRow + ceil(aRect.size.height / rowHeight);
|
|
|
|
for (i = startingRow; i <= endingRow; i++)
|
|
{
|
|
NSColor *color = [rowColors objectAtIndex: (i % rowColorCount)];
|
|
|
|
[color set];
|
|
NSRectFill(rowRect);
|
|
|
|
rowRect.origin.y += rowHeight;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) drawTableViewGridInClipRect: (NSRect)aRect
|
|
inView: (NSView *)view
|
|
{
|
|
NSTableView *tableView = (NSTableView *)view;
|
|
|
|
// Cache some constants
|
|
const CGFloat minX = NSMinX(aRect);
|
|
const CGFloat maxX = NSMaxX(aRect);
|
|
const CGFloat minY = NSMinY(aRect);
|
|
const CGFloat maxY = NSMaxY(aRect);
|
|
const NSInteger numberOfColumns = [tableView numberOfColumns];
|
|
const NSInteger numberOfRows = [tableView numberOfRows];
|
|
|
|
NSInteger startingRow = [tableView rowAtPoint: NSMakePoint(minX, minY)];
|
|
NSInteger endingRow = [tableView rowAtPoint: NSMakePoint(minX, maxY)];
|
|
NSInteger startingColumn = [tableView columnAtPoint: NSMakePoint(minX, minY)];
|
|
NSInteger endingColumn = [tableView columnAtPoint: NSMakePoint(maxX, minY)];
|
|
|
|
NSGraphicsContext *ctxt = GSCurrentContext();
|
|
NSColor *gridColor = [tableView gridColor];
|
|
|
|
|
|
if (startingRow == -1)
|
|
startingRow = 0;
|
|
if (endingRow == -1)
|
|
endingRow = numberOfRows - 1;
|
|
|
|
if (startingColumn == -1)
|
|
startingColumn = 0;
|
|
if (endingColumn == -1)
|
|
endingColumn = numberOfColumns - 1;
|
|
|
|
|
|
DPSgsave(ctxt);
|
|
[gridColor set];
|
|
|
|
// Draw horizontal lines
|
|
if (numberOfRows > 0)
|
|
{
|
|
NSInteger i;
|
|
for (i = startingRow; i <= endingRow; i++)
|
|
{
|
|
NSRect rowRect = [tableView rectOfRow: i];
|
|
rowRect.origin.y += rowRect.size.height - 1;
|
|
rowRect.size.height = 1;
|
|
NSRectFill(rowRect);
|
|
}
|
|
}
|
|
|
|
// Draw vertical lines
|
|
if (numberOfColumns > 0)
|
|
{
|
|
NSInteger i;
|
|
for (i = startingColumn; i <= endingColumn; i++)
|
|
{
|
|
NSRect colRect = [tableView rectOfColumn: i];
|
|
colRect.origin.x += colRect.size.width - 1;
|
|
colRect.size.width = 1;
|
|
NSRectFill(colRect);
|
|
}
|
|
}
|
|
|
|
DPSgrestore (ctxt);
|
|
}
|
|
|
|
- (void) drawTableViewRect: (NSRect)aRect
|
|
inView: (NSView *)view
|
|
{
|
|
int startingRow;
|
|
int endingRow;
|
|
int i;
|
|
NSTableView *tableView = (NSTableView *)view;
|
|
int numberOfRows = [tableView numberOfRows];
|
|
int numberOfColumns = [tableView numberOfColumns];
|
|
BOOL drawsGrid = [tableView drawsGrid];
|
|
|
|
/* Draw background */
|
|
[tableView drawBackgroundInClipRect: aRect];
|
|
|
|
if ((numberOfRows == 0) || (numberOfColumns == 0))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Draw selection */
|
|
[tableView highlightSelectionInClipRect: aRect];
|
|
|
|
/* Draw grid */
|
|
if (drawsGrid)
|
|
{
|
|
[tableView drawGridInClipRect: aRect];
|
|
}
|
|
|
|
/* Draw visible cells */
|
|
/* Using rowAtPoint: here calls them only twice per drawn rect */
|
|
startingRow = [tableView rowAtPoint: NSMakePoint (0, NSMinY (aRect))];
|
|
endingRow = [tableView rowAtPoint: NSMakePoint (0, NSMaxY (aRect))];
|
|
|
|
if (startingRow == -1)
|
|
{
|
|
startingRow = 0;
|
|
}
|
|
if (endingRow == -1)
|
|
{
|
|
endingRow = numberOfRows - 1;
|
|
}
|
|
// NSLog(@"drawRect : %d-%d", startingRow, endingRow);
|
|
{
|
|
SEL sel = @selector(drawRow:clipRect:);
|
|
IMP imp = [tableView methodForSelector: sel];
|
|
|
|
for (i = startingRow; i <= endingRow; i++)
|
|
{
|
|
(*imp)(tableView, sel, i, aRect);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) highlightTableViewSelectionInClipRect: (NSRect)clipRect
|
|
inView: (NSView *)view
|
|
selectingColumns: (BOOL)selectingColumns
|
|
{
|
|
NSTableView *tableView = (NSTableView *)view;
|
|
int numberOfRows = [tableView numberOfRows];
|
|
int numberOfColumns = [tableView numberOfColumns];
|
|
NSIndexSet *selectedRows = [tableView selectedRowIndexes];
|
|
NSIndexSet *selectedColumns = [tableView selectedColumnIndexes];
|
|
NSColor *backgroundColor = [tableView backgroundColor];
|
|
|
|
if (selectingColumns == NO)
|
|
{
|
|
NSInteger selectedRowsCount;
|
|
NSUInteger row;
|
|
NSInteger startingRow, endingRow;
|
|
|
|
selectedRowsCount = [selectedRows count];
|
|
if (selectedRowsCount == 0)
|
|
return;
|
|
|
|
/* highlight selected rows */
|
|
startingRow = [tableView rowAtPoint: NSMakePoint(0, NSMinY(clipRect))];
|
|
endingRow = [tableView rowAtPoint: NSMakePoint(0, NSMaxY(clipRect))];
|
|
|
|
if (startingRow == -1)
|
|
startingRow = 0;
|
|
if (endingRow == -1)
|
|
endingRow = numberOfRows - 1;
|
|
|
|
row = [selectedRows indexGreaterThanOrEqualToIndex: startingRow];
|
|
while ((row != NSNotFound) && (row <= endingRow))
|
|
{
|
|
NSColor *selectionColor = nil;
|
|
|
|
// Switch to the alternate color of the backgroundColor is white.
|
|
if([backgroundColor isEqual: [NSColor whiteColor]])
|
|
{
|
|
selectionColor = [NSColor colorWithCalibratedRed: 0.86
|
|
green: 0.92
|
|
blue: 0.99
|
|
alpha: 1.0];
|
|
}
|
|
else
|
|
{
|
|
selectionColor = [NSColor whiteColor];
|
|
}
|
|
|
|
//NSHighlightRect(NSIntersectionRect([tableView rectOfRow: row],
|
|
// clipRect));
|
|
[selectionColor set];
|
|
NSRectFill(NSIntersectionRect([tableView rectOfRow: row], clipRect));
|
|
row = [selectedRows indexGreaterThanIndex: row];
|
|
}
|
|
}
|
|
else // Selecting columns
|
|
{
|
|
NSUInteger selectedColumnsCount;
|
|
NSUInteger column;
|
|
NSInteger startingColumn, endingColumn;
|
|
|
|
selectedColumnsCount = [selectedColumns count];
|
|
|
|
if (selectedColumnsCount == 0)
|
|
return;
|
|
|
|
/* highlight selected columns */
|
|
startingColumn = [tableView columnAtPoint: NSMakePoint(NSMinX(clipRect), 0)];
|
|
endingColumn = [tableView columnAtPoint: NSMakePoint(NSMaxX(clipRect), 0)];
|
|
|
|
if (startingColumn == -1)
|
|
startingColumn = 0;
|
|
if (endingColumn == -1)
|
|
endingColumn = numberOfColumns - 1;
|
|
|
|
column = [selectedColumns indexGreaterThanOrEqualToIndex: startingColumn];
|
|
while ((column != NSNotFound) && (column <= endingColumn))
|
|
{
|
|
NSHighlightRect(NSIntersectionRect([tableView rectOfColumn: column],
|
|
clipRect));
|
|
column = [selectedColumns indexGreaterThanIndex: column];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) drawTableViewRow: (int)rowIndex
|
|
clipRect: (NSRect)clipRect
|
|
inView: (NSView *)view
|
|
{
|
|
NSTableView *tableView = (NSTableView *)view;
|
|
// int numberOfRows = [tableView numberOfRows];
|
|
int numberOfColumns = [tableView numberOfColumns];
|
|
// NSIndexSet *selectedRows = [tableView selectedRowIndexes];
|
|
// NSColor *backgroundColor = [tableView backgroundColor];
|
|
id dataSource = [tableView dataSource];
|
|
float *columnOrigins = [tableView _columnOrigins];
|
|
int editedRow = [tableView editedRow];
|
|
int editedColumn = [tableView editedColumn];
|
|
NSArray *tableColumns = [tableView tableColumns];
|
|
int startingColumn;
|
|
int endingColumn;
|
|
NSTableColumn *tb;
|
|
NSRect drawingRect;
|
|
NSCell *cell;
|
|
int i;
|
|
float x_pos;
|
|
|
|
if (dataSource == nil)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Using columnAtPoint: here would make it called twice per row per drawn
|
|
rect - so we avoid it and do it natively */
|
|
|
|
/* Determine starting column as fast as possible */
|
|
x_pos = NSMinX (clipRect);
|
|
i = 0;
|
|
while ((i < numberOfColumns) && (x_pos > columnOrigins[i]))
|
|
{
|
|
i++;
|
|
}
|
|
startingColumn = (i - 1);
|
|
|
|
if (startingColumn == -1)
|
|
startingColumn = 0;
|
|
|
|
/* Determine ending column as fast as possible */
|
|
x_pos = NSMaxX (clipRect);
|
|
// Nota Bene: we do *not* reset i
|
|
while ((i < numberOfColumns) && (x_pos > columnOrigins[i]))
|
|
{
|
|
i++;
|
|
}
|
|
endingColumn = (i - 1);
|
|
|
|
if (endingColumn == -1)
|
|
endingColumn = numberOfColumns - 1;
|
|
|
|
/* Draw the row between startingColumn and endingColumn */
|
|
for (i = startingColumn; i <= endingColumn; i++)
|
|
{
|
|
tb = [tableColumns objectAtIndex: i];
|
|
cell = [tb dataCellForRow: rowIndex];
|
|
if (i == editedColumn && rowIndex == editedRow)
|
|
[cell _setInEditing: YES];
|
|
[tableView _willDisplayCell: cell
|
|
forTableColumn: tb
|
|
row: rowIndex];
|
|
[cell setObjectValue: [dataSource tableView: tableView
|
|
objectValueForTableColumn: tb
|
|
row: rowIndex]];
|
|
drawingRect = [tableView frameOfCellAtColumn: i
|
|
row: rowIndex];
|
|
[cell drawWithFrame: drawingRect inView: tableView];
|
|
if (i == editedColumn && rowIndex == editedRow)
|
|
[cell _setInEditing: NO];
|
|
}
|
|
}
|
|
|
|
- (void) drawBoxInClipRect: (NSRect)clipRect
|
|
boxType: (NSBoxType)boxType
|
|
borderType: (NSBorderType)borderType
|
|
inView: (NSBox *)box
|
|
{
|
|
NSColor *color;
|
|
BOOL drawTitleBackground = YES;
|
|
|
|
if (boxType == NSBoxCustom)
|
|
{
|
|
if (![box isOpaque])
|
|
{
|
|
color = [NSColor clearColor];
|
|
}
|
|
else
|
|
{
|
|
color = [box fillColor];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
color = [[box window] backgroundColor];
|
|
}
|
|
|
|
// Draw separator boxes
|
|
|
|
if (boxType == NSBoxSeparator)
|
|
{
|
|
[[box borderColor] set];
|
|
NSRectFill([box borderRect]);
|
|
return;
|
|
}
|
|
|
|
// Draw border
|
|
|
|
GSDrawTiles *tiles = [[GSTheme theme] tilesNamed: GSBoxBorder state: GSThemeNormalState];
|
|
if (tiles == nil
|
|
|| borderType == NSNoBorder
|
|
|| boxType == NSBoxOldStyle
|
|
|| boxType == NSBoxCustom)
|
|
{
|
|
// Fill inside
|
|
[color set];
|
|
NSRectFill(clipRect);
|
|
|
|
switch (borderType)
|
|
{
|
|
case NSNoBorder:
|
|
break;
|
|
case NSLineBorder:
|
|
if (boxType == NSBoxCustom)
|
|
{
|
|
[[box borderColor] set];
|
|
NSFrameRectWithWidth([box borderRect], [box borderWidth]);
|
|
}
|
|
else
|
|
{
|
|
[[NSColor controlDarkShadowColor] set];
|
|
NSFrameRect([box borderRect]);
|
|
}
|
|
break;
|
|
case NSBezelBorder:
|
|
[[GSTheme theme] drawDarkBezel: [box borderRect] withClip: clipRect];
|
|
break;
|
|
case NSGrooveBorder:
|
|
[[GSTheme theme] drawGroove: [box borderRect] withClip: clipRect];
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
drawTitleBackground = NO;
|
|
|
|
// If the title is on the border, clip a hole in the later
|
|
|
|
[NSGraphicsContext saveGraphicsState];
|
|
|
|
if ((borderType != NSNoBorder)
|
|
&& (([box titlePosition] == NSAtTop) || ([box titlePosition] == NSAtBottom)))
|
|
{
|
|
const NSRect borderRect = [box borderRect];
|
|
const NSRect titleRect = [box titleRect];
|
|
NSBezierPath *path = [NSBezierPath bezierPath];
|
|
|
|
// Left
|
|
if (NSMinX(titleRect) > NSMinX(borderRect))
|
|
{
|
|
NSRect left = borderRect;
|
|
left.size.width = NSMinX(titleRect) - NSMinX(borderRect);
|
|
[path appendBezierPathWithRect: left];
|
|
}
|
|
|
|
// Right
|
|
if (NSMaxX(borderRect) > NSMaxX(titleRect))
|
|
{
|
|
NSRect right = borderRect;
|
|
right.size.width = NSMaxX(borderRect) - NSMaxX(titleRect);
|
|
right.origin.x = NSMaxX(titleRect);
|
|
[path appendBezierPathWithRect: right];
|
|
}
|
|
|
|
// MinY
|
|
if (NSMinY(titleRect) > NSMinY(borderRect))
|
|
{
|
|
NSRect minY = borderRect;
|
|
minY.size.height = NSMinY(titleRect) - NSMinY(borderRect);
|
|
[path appendBezierPathWithRect: minY];
|
|
}
|
|
|
|
// MaxY
|
|
if (NSMaxY(borderRect) > NSMaxY(titleRect))
|
|
{
|
|
NSRect maxY = borderRect;
|
|
maxY.size.height = NSMaxY(borderRect) - NSMaxY(titleRect);
|
|
maxY.origin.y = NSMaxY(titleRect);
|
|
[path appendBezierPathWithRect: maxY];
|
|
}
|
|
|
|
if (![path isEmpty])
|
|
{
|
|
[path addClip];
|
|
}
|
|
}
|
|
|
|
|
|
[[GSTheme theme] fillRect: [box borderRect]
|
|
withTiles: tiles
|
|
background: [NSColor clearColor]];
|
|
|
|
// Restore clipping path
|
|
[NSGraphicsContext restoreGraphicsState];
|
|
}
|
|
|
|
|
|
// Draw title
|
|
if ([box titlePosition] != NSNoTitle)
|
|
{
|
|
// If the title is on the border, clip a hole in the later
|
|
if (drawTitleBackground
|
|
&& (borderType != NSNoBorder)
|
|
&& (([box titlePosition] == NSAtTop) || ([box titlePosition] == NSAtBottom)))
|
|
{
|
|
[color set];
|
|
NSRectFill([box titleRect]);
|
|
}
|
|
|
|
[[box titleCell] drawWithFrame: [box titleRect] inView: box];
|
|
}
|
|
}
|
|
|
|
@end
|