-
Notifications
You must be signed in to change notification settings - Fork 48
/
PSMUnifiedTabStyle.m
487 lines (377 loc) · 16.7 KB
/
PSMUnifiedTabStyle.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
//
// PSMUnifiedTabStyle.m
// --------------------
//
// Created by Keith Blount on 30/04/2006.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//
#import "PSMUnifiedTabStyle.h"
#import "PSMTabBarCell.h"
#import "PSMTabBarControl.h"
#define kPSMUnifiedObjectCounterRadius 7.0
#define kPSMUnifiedCounterMinWidth 20
@interface PSMUnifiedTabStyle (Private)
- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView;
@end
@implementation PSMUnifiedTabStyle
- (NSString *)name
{
return @"Unified";
}
#pragma mark -
#pragma mark Creation/Destruction
- (id) init
{
if((self = [super init]))
{
unifiedCloseButton = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"FRATabBarClose" ofType:@"pdf" inDirectory:@"Tab Bar"]];
unifiedCloseButtonDown = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"FRATabBarClosePressed" ofType:@"pdf" inDirectory:@"Tab Bar"]];
unifiedCloseButtonOver = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"FRATabBarCloseRollover" ofType:@"pdf" inDirectory:@"Tab Bar"]];
_addTabButtonImage = nil;
_addTabButtonPressedImage = nil;
_addTabButtonRolloverImage = nil;
leftMargin = 4.0;
}
return self;
}
#pragma mark -
#pragma mark Control Specific
- (void)setLeftMarginForTabBarControl:(CGFloat)margin
{
leftMargin = margin;
}
- (CGFloat)leftMarginForTabBarControl
{
return leftMargin;
}
- (CGFloat)rightMarginForTabBarControl
{
return 24.0f;
}
#pragma mark -
#pragma mark Add Tab Button
- (NSImage *)addTabButtonImage
{
return _addTabButtonImage;
}
- (NSImage *)addTabButtonPressedImage
{
return _addTabButtonPressedImage;
}
- (NSImage *)addTabButtonRolloverImage
{
return _addTabButtonRolloverImage;
}
#pragma mark -
#pragma mark Cell Specific
- (NSRect) closeButtonRectForTabCell:(PSMTabBarCell *)cell
{
NSRect cellFrame = [cell frame];
if ([cell hasCloseButton] == NO) {
return NSZeroRect;
}
NSRect result;
result.size = [unifiedCloseButton size];
result.origin.x = cellFrame.origin.x + MARGIN_X;
result.origin.y = cellFrame.origin.y + MARGIN_Y + 1.0;
return result;
}
- (NSRect)iconRectForTabCell:(PSMTabBarCell *)cell
{
NSRect cellFrame = [cell frame];
if ([cell hasIcon] == NO) {
return NSZeroRect;
}
NSRect result;
result.size = NSMakeSize(kPSMTabBarIconWidth, kPSMTabBarIconWidth);
result.origin.x = cellFrame.origin.x + MARGIN_X;
result.origin.y = cellFrame.origin.y + MARGIN_Y + 1.0;
if([cell hasCloseButton] && ![cell isCloseButtonSuppressed])
result.origin.x += [unifiedCloseButton size].width + kPSMTabBarCellPadding;
return result;
}
- (NSRect)indicatorRectForTabCell:(PSMTabBarCell *)cell
{
NSRect cellFrame = [cell frame];
if ([[cell indicator] isHidden]) {
return NSZeroRect;
}
NSRect result;
result.size = NSMakeSize(kPSMTabBarIndicatorWidth, kPSMTabBarIndicatorWidth);
result.origin.x = cellFrame.origin.x + cellFrame.size.width - MARGIN_X - kPSMTabBarIndicatorWidth;
result.origin.y = cellFrame.origin.y + MARGIN_Y - 1.0;
return result;
}
- (NSRect)objectCounterRectForTabCell:(PSMTabBarCell *)cell
{
NSRect cellFrame = [cell frame];
if ([cell count] == 0) {
return NSZeroRect;
}
CGFloat countWidth = [[self attributedObjectCountValueForTabCell:cell] size].width;
countWidth += (2 * kPSMUnifiedObjectCounterRadius - 6.0);
if(countWidth < kPSMUnifiedCounterMinWidth)
countWidth = kPSMUnifiedCounterMinWidth;
NSRect result;
result.size = NSMakeSize(countWidth, 2 * kPSMUnifiedObjectCounterRadius); // temp
result.origin.x = cellFrame.origin.x + cellFrame.size.width - MARGIN_X - result.size.width;
result.origin.y = cellFrame.origin.y + MARGIN_Y + 1.0;
if(![[cell indicator] isHidden])
result.origin.x -= kPSMTabBarIndicatorWidth + kPSMTabBarCellPadding;
return result;
}
- (CGFloat)minimumWidthOfTabCell:(PSMTabBarCell *)cell
{
CGFloat resultWidth = 0.0;
// left margin
resultWidth = MARGIN_X;
// close button?
if([cell hasCloseButton] && ![cell isCloseButtonSuppressed])
resultWidth += [unifiedCloseButton size].width + kPSMTabBarCellPadding;
// icon?
if([cell hasIcon])
resultWidth += kPSMTabBarIconWidth + kPSMTabBarCellPadding;
// the label
resultWidth += kPSMMinimumTitleWidth;
// object counter?
if([cell count] > 0)
resultWidth += [self objectCounterRectForTabCell:cell].size.width + kPSMTabBarCellPadding;
// indicator?
if ([[cell indicator] isHidden] == NO)
resultWidth += kPSMTabBarCellPadding + kPSMTabBarIndicatorWidth;
// right margin
resultWidth += MARGIN_X;
return ceil(resultWidth);
}
- (CGFloat)desiredWidthOfTabCell:(PSMTabBarCell *)cell
{
CGFloat resultWidth = 0.0;
// left margin
resultWidth = MARGIN_X;
// close button?
if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed])
resultWidth += [unifiedCloseButton size].width + kPSMTabBarCellPadding;
// icon?
if([cell hasIcon])
resultWidth += kPSMTabBarIconWidth + kPSMTabBarCellPadding;
// the label
resultWidth += [[cell attributedStringValue] size].width;
// object counter?
if([cell count] > 0)
resultWidth += [self objectCounterRectForTabCell:cell].size.width + kPSMTabBarCellPadding;
// indicator?
if ([[cell indicator] isHidden] == NO)
resultWidth += kPSMTabBarCellPadding + kPSMTabBarIndicatorWidth;
// right margin
resultWidth += MARGIN_X;
return ceil(resultWidth);
}
#pragma mark -
#pragma mark Cell Values
- (NSAttributedString *)attributedObjectCountValueForTabCell:(PSMTabBarCell *)cell
{
NSMutableAttributedString *attrStr;
NSFontManager *fm = [NSFontManager sharedFontManager];
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setLocalizesFormat:YES];
[nf setFormat:@"0"];
[nf setHasThousandSeparators:YES];
NSString *contents = [nf stringFromNumber:[NSNumber numberWithInteger:[cell count]]];
attrStr = [[NSMutableAttributedString alloc] initWithString:contents];
NSRange range = NSMakeRange(0, [contents length]);
// Add font attribute
[attrStr addAttribute:NSFontAttributeName value:[fm convertFont:[NSFont fontWithName:@"Helvetica" size:11.0] toHaveTrait:NSBoldFontMask] range:range];
[attrStr addAttribute:NSForegroundColorAttributeName value:[[NSColor whiteColor] colorWithAlphaComponent:0.85] range:range];
return attrStr;
}
- (NSAttributedString *)attributedStringValueForTabCell:(PSMTabBarCell *)cell
{
NSMutableAttributedString *attrStr;
NSString * contents = [cell stringValue];
attrStr = [[NSMutableAttributedString alloc] initWithString:contents];
NSRange range = NSMakeRange(0, [contents length]);
[attrStr addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:11.0] range:range];
// Paragraph Style for Truncating Long Text
static NSMutableParagraphStyle *TruncatingTailParagraphStyle = nil;
if (!TruncatingTailParagraphStyle) {
TruncatingTailParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[TruncatingTailParagraphStyle setLineBreakMode:NSLineBreakByTruncatingMiddle];
}
[attrStr addAttribute:NSParagraphStyleAttributeName value:TruncatingTailParagraphStyle range:range];
return attrStr;
}
#pragma mark -
#pragma mark ---- drawing ----
- (void)drawTabCell:(PSMTabBarCell *)cell
{
NSRect cellFrame = [cell frame];
NSColor * lineColor = nil;
NSBezierPath* bezier = [NSBezierPath bezierPath];
lineColor = [NSColor colorWithCalibratedWhite:0.576 alpha:1.0];
if ([cell state] == NSOnState)
{
// selected tab
NSRect aRect = NSMakeRect(cellFrame.origin.x+0.5, cellFrame.origin.y-0.5, cellFrame.size.width-1.0, cellFrame.size.height);
aRect.size.height -= 0.5;
aRect.size.height+=0.5;
// frame
CGFloat radius = MIN(6.0, 0.5f * MIN(NSWidth(aRect), NSHeight(aRect)));
NSRect rect = NSInsetRect(aRect, radius, radius);
[bezier appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect), NSMinY(rect)) radius:radius startAngle:180.0 endAngle:270.0];
[bezier appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(rect), NSMinY(rect)) radius:radius startAngle:270.0 endAngle:360.0];
NSPoint cornerPoint = NSMakePoint(NSMaxX(aRect), NSMaxY(aRect));
[bezier appendBezierPathWithPoints:&cornerPoint count:1];
cornerPoint = NSMakePoint(NSMinX(aRect), NSMaxY(aRect));
[bezier appendBezierPathWithPoints:&cornerPoint count:1];
[bezier closePath];
NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:0.99 alpha:1.0] endingColor:[NSColor colorWithCalibratedWhite:0.941 alpha:1.0]];
[gradient drawInBezierPath:bezier angle:90];
//[bezier linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.99 alpha:1.0] endColor:[NSColor colorWithCalibratedWhite:0.941 alpha:1.0]];
[lineColor set];
[bezier stroke];
}
else
{
// unselected tab
NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height);
aRect.origin.y += 0.5;
aRect.origin.x += 1.5;
aRect.size.width -= 1;
aRect.origin.x -= 1;
aRect.size.width += 1;
// rollover
if ([cell isHighlighted])
{
[[NSColor colorWithCalibratedWhite:0.0 alpha:0.1] set];
NSRectFillUsingOperation(aRect, NSCompositeSourceAtop);
}
// frame
[lineColor set];
[bezier moveToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y-0.5)];
if(!([cell tabState] & PSMTab_RightIsSelectedMask)){
[bezier lineToPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
}
[bezier stroke];
// Create a thin lighter line next to the dividing line for a bezel effect
if(!([cell tabState] & PSMTab_RightIsSelectedMask)){
[[[NSColor whiteColor] colorWithAlphaComponent:0.5] set];
[NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX(aRect)+1.0, aRect.origin.y-0.5)
toPoint:NSMakePoint(NSMaxX(aRect)+1.0, NSMaxY(aRect)-2.5)];
}
// If this is the leftmost tab, we want to draw a line on the left, too
if ([cell tabState] & PSMTab_PositionLeftMask)
{
[lineColor set];
[NSBezierPath strokeLineFromPoint:NSMakePoint(aRect.origin.x,aRect.origin.y-0.5)
toPoint:NSMakePoint(aRect.origin.x,NSMaxY(aRect)-2.5)];
[[[NSColor whiteColor] colorWithAlphaComponent:0.5] set];
[NSBezierPath strokeLineFromPoint:NSMakePoint(aRect.origin.x+1.0,aRect.origin.y-0.5)
toPoint:NSMakePoint(aRect.origin.x+1.0,NSMaxY(aRect)-2.5)];
}
}
[self drawInteriorWithTabCell:cell inView:[cell controlView]];
}
- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView
{
NSRect cellFrame = [cell frame];
CGFloat labelPosition = cellFrame.origin.x + MARGIN_X;
// close button
if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) {
NSSize closeButtonSize = NSZeroSize;
NSRect closeButtonRect = [cell closeButtonRectForFrame:cellFrame];
NSImage * closeButton = nil;
closeButton = unifiedCloseButton;
if ([cell closeButtonOver]) closeButton = unifiedCloseButtonOver;
if ([cell closeButtonPressed]) closeButton = unifiedCloseButtonDown;
closeButtonSize = [closeButton size];
if ([controlView isFlipped]) {
closeButtonRect.origin.y += closeButtonRect.size.height;
}
[closeButton compositeToPoint:closeButtonRect.origin operation:NSCompositeSourceOver fraction:1.0];
// scoot label over
labelPosition += closeButtonSize.width + kPSMTabBarCellPadding;
}
// icon
if([cell hasIcon]){
NSRect iconRect = [self iconRectForTabCell:cell];
NSImage *icon = [[[[cell representedObject] identifier] content] icon];
if ([controlView isFlipped]) {
iconRect.origin.y = cellFrame.size.height - iconRect.origin.y;
}
[icon compositeToPoint:iconRect.origin operation:NSCompositeSourceOver fraction:1.0];
// scoot label over
labelPosition += iconRect.size.width + kPSMTabBarCellPadding;
}
// object counter
if([cell count] > 0){
[[NSColor colorWithCalibratedWhite:0.3 alpha:0.6] set];
NSBezierPath *path = [NSBezierPath bezierPath];
NSRect myRect = [self objectCounterRectForTabCell:cell];
myRect.origin.y -= 1.0;
[path moveToPoint:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y)];
[path lineToPoint:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMUnifiedObjectCounterRadius, myRect.origin.y)];
[path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMUnifiedObjectCounterRadius, myRect.origin.y + kPSMUnifiedObjectCounterRadius) radius:kPSMUnifiedObjectCounterRadius startAngle:270.0 endAngle:90.0];
[path lineToPoint:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y + myRect.size.height)];
[path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y + kPSMUnifiedObjectCounterRadius) radius:kPSMUnifiedObjectCounterRadius startAngle:90.0 endAngle:270.0];
[path fill];
// draw attributed string centered in area
NSRect counterStringRect;
NSAttributedString *counterString = [self attributedObjectCountValueForTabCell:cell];
counterStringRect.size = [counterString size];
counterStringRect.origin.x = myRect.origin.x + ((myRect.size.width - counterStringRect.size.width) / 2.0) + 0.25;
counterStringRect.origin.y = myRect.origin.y + ((myRect.size.height - counterStringRect.size.height) / 2.0) + 0.5;
[counterString drawInRect:counterStringRect];
}
// label rect
NSRect labelRect;
labelRect.origin.x = labelPosition;
labelRect.size.width = cellFrame.size.width - (labelRect.origin.x - cellFrame.origin.x) - kPSMTabBarCellPadding;
NSSize s = [[cell attributedStringValue] size];
labelRect.origin.y = cellFrame.origin.y + (cellFrame.size.height-s.height)/2.0 - 1.0;
labelRect.size.height = s.height;
if(![[cell indicator] isHidden])
labelRect.size.width -= (kPSMTabBarIndicatorWidth + kPSMTabBarCellPadding);
if([cell count] > 0)
labelRect.size.width -= ([self objectCounterRectForTabCell:cell].size.width + kPSMTabBarCellPadding);
// label
[[cell attributedStringValue] drawInRect:labelRect];
}
- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect
{
NSRect gradientRect = rect;
gradientRect.size.height -= 1.0;
NSBezierPath *path = [NSBezierPath bezierPathWithRect:gradientRect];
NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:0.918 alpha:1.0] endingColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
[gradient drawInBezierPath:path angle:90];
//[path linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.918 alpha:1.0] endColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
[[NSColor colorWithCalibratedWhite:0.576 alpha:1.0] set];
[NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x,NSMaxY(rect) - 1.0)
toPoint:NSMakePoint(NSMaxX(rect),NSMaxY(rect) - 1.0)];
// no tab view == not connected
if(![bar tabView]){
NSRect labelRect = rect;
labelRect.size.height -= 4.0;
labelRect.origin.y += 4.0;
NSMutableAttributedString *attrStr;
NSString *contents = @"PSMTabBarControl";
attrStr = [[NSMutableAttributedString alloc] initWithString:contents];
NSRange range = NSMakeRange(0, [contents length]);
[attrStr addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:11.0] range:range];
NSMutableParagraphStyle *centeredParagraphStyle = nil;
if (!centeredParagraphStyle) {
centeredParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[centeredParagraphStyle setAlignment:NSCenterTextAlignment];
}
[attrStr addAttribute:NSParagraphStyleAttributeName value:centeredParagraphStyle range:range];
[attrStr drawInRect:labelRect];
return;
}
// draw cells
NSArray *array= [NSArray arrayWithArray:[bar cells]];
for (PSMTabBarCell *cell in array) {
if(![cell isInOverflowMenu]){
[cell drawWithFrame:[cell frame] inView:bar];
}
}
}
@end