NSWindow的风格一直只有两种,很难看。Panel倒是有种HUD风格的,但window没有,毕竟window和panel的titile大小还是不一样的,网上有关于HUDWindow的代码,不过那是把window的titlebar给隐藏掉,自己画上三个button和右下角可以resize的东东,如果用这个window来弹出sheet的话会很诡异的出现……     就是sheet从window的最上面弹出来了,底层window看不到titlebar了~ @@AL@.*  
NSWindow在设置成Texture模式之后可以设置背景色,不过这是单色,渐进色设置不了。最简单的方法就是先给window设置背景色,再覆盖上一层NSView来填充content的颜色,不过这样不是浑然一体的,每个window都要这样搞的话还是很麻烦的。 krUtOVI  
所以只能从被apple隐藏起来的方法里找办法了~所以class-dump出来看看~ ij ?7MP  
你会发现在NSWindow.h中绘制界面的函数几乎没有,不想那些继承与NSView的控件一样,那么多私有的绘制方法。那window是怎样绘制的呢。 w\)K0RN  
仔细观察,你会发现NSWindow有很多扩展类,而且window功能性的东西是非常多的,所以它的重绘肯定是委托给别人来做了(这一点通过获取NSWindow的closebutton可以知道,那三个button都不是标准的NSButton,而是 NSThemeButton?记不太清楚了)。经过查找可以发现函数

?
1
+(Class)frameViewClassForStyleMask:(unsigned int )styleMask

非常可疑,而且dump出来的类有一个叫做NSThemeFrame的,查看它的类方法,哈哈,发现了吧,全是跟window有关的绘制方法。 suY47DCX)  
jr=9.=jI8k  
所以接下来的事情就很简单了,写一个类继承 NSThemeFrame *'>_X X

?
1
2
3
4
5
6
#import <COCOA Cocoa.h>
#import "NSThemeFrame.h"
@interface KAThemeFrame : NSThemeFrame
{
}
@end

P_(8+)ud-  
PVIOe}N  
那么需要重写哪些函数呢~我们的目标是重画TitleBar,具体窗体的内容不需要重画,因为反正有一个NSView要覆盖在上面的,所以一个方法就足够了,废话少说,上代码 )9hqd

?
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
#import "KAThemeFrame.h"
  
@implementation KAThemeFrame
  
- ( id )contentFill
{
     // This color is used only when dragging.
     // Please don't try to modify the value.
     return [ NSColor colorWithCalibratedWhite:.13 alpha:1];
}
  
- ( id )frameColor
{
     return [ NSColor redColor];
}
  
- ( void )_drawTitleBar:( NSRect )rect
{
     NSRect titleRect = [ self titlebarRect];
      
     // Panel style
     if ([ self _isUtility])
     {
         KAGradient *titleGradient = [KAGradient gradientWithStartingColor: [ NSColor colorWithCalibratedRed:0.423f green:0.423f blue:0.423f alpha:1.0] 
                                                               endingColor: [ NSColor colorWithCalibratedRed:0.365f green:0.365f blue:0.365f alpha:1.0]];
         [titleGradient drawInRect:titleRect angle:-90];
     }
     // Window style
     else
     {
         float radius = 4;
         NSBezierPath *borderPath = [ NSBezierPath bezierPathWithRoundedRect:titleRect cornerRadius:radius inCorners:(OSTopLeftCorner | OSTopRightCorner)];
         NSBezierPath *titlebarPath = [ NSBezierPath bezierPathWithRoundedRect: NSInsetRect (titleRect, 1, 1) cornerRadius:radius-1 inCorners:(OSTopLeftCorner | OSTopRightCorner)];
          
         KAGradient *titleGradient  = [KAGradient gradientWithStartingColor: [ NSColor colorWithCalibratedRed:0.423f green:0.423f blue:0.423f alpha:1.0] 
                                                                endingColor: [ NSColor colorWithCalibratedRed:0.365f green:0.365f blue:0.365f alpha:1.0]];
         KAGradient *borderGradient = [KAGradient gradientWithStartingColor: [ NSColor colorWithCalibratedRed:0.423f green:0.423f blue:0.423f alpha:1.0] 
                                                                endingColor: [ NSColor colorWithCalibratedRed:0.365f green:0.365f blue:0.365f alpha:1.0]];
          
          
         [[ NSColor clearColor] set];
         NSRectFill (titleRect);
          
         [borderGradient drawInBezierPath:borderPath angle:-90];
         [titleGradient drawInBezierPath:titlebarPath angle:-90];
          
     }
     [ self _drawTitleStringIn:[ self _titlebarTitleRect] withColor:[ NSColor colorWithDeviceWhite:.75 alpha:1]];
}
@end

Lc{AB!Br  
r fqwxr45h  
这样你就有一个属于自己自定义的TitileBar的window了~ KN}#8.'>3  
当然你自己实现的画还可以区分HUD啊,Texture啊啥的风格来重画~ ;z'&$#pA  
当然你也可以通过重写

?
1
- ( void )_drawFrameRects:( NSRect )fp8;

来画背景。 h.edb6  
到这里可以说重绘NSWindow已经完成了,但是怎样通过styleMask来控制它的重绘呢,怎样创建一个IBPlugin来在IB里拖出你自己的window呢,怎样为这个window设置一个你自己的contentview呢? |'h (S|  
且听下(下下?)回分解~先讲完重绘,再讲创建IBPlugin。 CD&a_-'z$K  
8 0tA5AP  
这里给出KAGradient的代码(支持10.4/10.5/10.6)很简单的一个工厂模式,为了使用接口一致,所以堆NSGradient做了封装~_KAGradient在10.5/10.6有performance问题~ 7m2iL#5[

?
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
@protocol KAGradientProtocol
  
+ ( id ) gradientWithStartingColor: ( NSColor *) startingColor
                 endingColor: ( NSColor *) endingColor;
  
- ( id ) initWithStartingColor: ( NSColor *) startingColor
                  endingColor: ( NSColor *) endingColor;
- ( void ) addColorStop: ( NSColor *) stopColor
            atPosition: (CGFloat) position;
  
- ( void ) drawFromPoint: ( NSPoint ) startingPoint
                toPoint: ( NSPoint ) endingPoint;
- ( void ) drawFromCenter: ( NSPoint ) startingCenter
                  radius: (CGFloat) startRadius
                toCenter: ( NSPoint ) endCenter
                  radius: (CGFloat) endRadius;
  
- ( void ) drawInRect: ( NSRect ) rect 
               angle: (CGFloat) angle;
- ( void ) drawInBezierPath: ( NSBezierPath *) path 
                     angle: (CGFloat) angle;
  
- ( void ) drawRadialInRect: ( NSRect ) rect;
- ( void ) drawRadialInBezierPath: ( NSBezierPath *) path;
  
@end

#Zdh<.  
NNt n

?
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
#import <COCOA Cocoa.h>
#import "KAGradientProtocol.h"
  
typedef struct _KAGradientElement 
     {
         CGFloat red, green, blue, alpha;
         CGFloat position;
          
         struct _KAGradientElement *nextElement;
     } KAGradientElement;
  
typedef enum  _KABlendingMode
     {
         KALinearBlendingMode,
         KAChromaticBlendingMode,
         KAInverseChromaticBlendingMode,
     } KAGradientBlendingMode;
  
/*!
      @class
      @abstract    Private Gradient class which will be used on 10.4.
      @discussion  The is a class which uses Quartz to draw gradient graphics on 
                   10.4. You can add color stop after initialization.
  */
@interface _KAGradient : NSObject <KAGRADIENTPROTOCOL>
{
     KAGradientElement* elementList;
     KAGradientBlendingMode blendingMode;
      
     CGFunctionRef gradientFunction;    
}
@end

T8S&9BM7  
[+\He/M6

?
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
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
#import "_KAGradient.h"
  
@interface  _KAGradient (PrivateMethods)
  
- ( void )_commonInit;
  
- ( void )setBlendingMode:(KAGradientBlendingMode)mode;
- (KAGradientBlendingMode)blendingMode;
  
- ( void )addElement:(KAGradientElement*)newElement;
- (KAGradientElement *)elementAtIndex:(unsigned)index;
- (KAGradientElement)removeElementAtIndex:(unsigned)index;
- (KAGradientElement)removeElementAtPosition:( float )position;
  
@end
  
//C Fucti***** for color blending
static void linearEvaluation   ( void *info, c*****t float *in, float *out);
static void chromaticEvaluation( void *info, c*****t float *in, float *out);
static void inverseChromaticEvaluation( void *info, c*****t float *in, float *out);
static void transformRGB_HSV( float *components);
static void transformHSV_RGB( float *components);
static void resolveHSV( float *color1, float *color2);
  
@implementation _KAGradient
  
+ gradientWithStartingColor: ( NSColor *) startingColor
                 endingColor: ( NSColor *) endingColor
{
     _KAGradient* instance = [[[ self class ] alloc] init];
      
     KAGradientElement color1;
     KAGradientElement color2;
      
     [[startingColor colorUsingColorSpaceName: NSCalibratedRGBColorSpace ] getRed: &color1.red 
                                                                           green: &color1.green
                                                                            blue: &color1.blue 
                                                                           alpha: &color1.alpha];
     [[endingColor colorUsingColorSpaceName: NSCalibratedRGBColorSpace ] getRed: &color2.red
                                                                         green: &color2.green
                                                                          blue: &color2.blue
                                                                         alpha: &color2.alpha];
     color1.position = 0;
     color2.position = 1;
      
     [instance addElement: &color1];
     [instance addElement: &color2];
      
     return [instance autorelease];
}
  
- ( id ) init
{
     if ( self = [ super init])
     {
         [ self _commonInit];
         [ self setBlendingMode: KALinearBlendingMode];
     }
     return self ;
}
  
- ( id ) initWithStartingColor: ( NSColor *) startingColor
                  endingColor: ( NSColor *) endingColor
{
     self = [ super init];
      
     if ( self )
     {
         [ self _commonInit];
         [ self setBlendingMode: KALinearBlendingMode];
          
         KAGradientElement color1;
         KAGradientElement color2;
          
         [[startingColor colorUsingColorSpaceName: NSCalibratedRGBColorSpace ] getRed: &color1.red 
                                                                               green: &color1.green
                                                                                blue: &color1.blue 
                                                                               alpha: &color1.alpha];
         [[endingColor colorUsingColorSpaceName: NSCalibratedRGBColorSpace ] getRed: &color2.red
                                                                             green: &color2.green
                                                                              blue: &color2.blue
                                                                             alpha: &color2.alpha];
         color1.position = 0;
         color2.position = 1;
          
         [ self addElement: &color1];
         [ self addElement: &color2];
     }
      
      
     return self ;
}
  
- ( void ) dealloc
{
     CGFunctionRelease(gradientFunction);
      
     KAGradientElement* elementToRemove = elementList;
     while (elementList != nil )
     {
         elementToRemove = elementList;
         elementList = elementList->nextElement;
         free(elementToRemove);
     }
      
     [ super dealloc];
}
  
- ( id ) copyWithZone: ( NSZone *) zone
{
     _KAGradient * copy = [[[ self class ] allocWithZone: zone] init];
      
     // now just copy my elementList
     KAGradientElement* currentElement = elementList;
     while (currentElement)
     {
         [ copy addElement: currentElement];
         currentElement = currentElement->nextElement;
     }
      
     [ copy setBlendingMode: blendingMode];
      
     return copy ;
}
  
- ( void )encodeWithCoder:( NSCoder *)coder
{
     if ([coder allowsKeyedCoding])
     {
         unsigned count = 0;
         KAGradientElement *currentElement = elementList;
         while(currentElement != nil )
         {
             [coder encodeValueOfObjCType: @encode ( float ) at:&(currentElement->red)];
             [coder encodeValueOfObjCType: @encode ( float ) at:&(currentElement->green)];
             [coder encodeValueOfObjCType: @encode ( float ) at:&(currentElement->blue)];
             [coder encodeValueOfObjCType: @encode ( float ) at:&(currentElement->alpha)];
             [coder encodeValueOfObjCType: @encode ( float ) at:&(currentElement->position)];
              
             count++;
             currentElement = currentElement->nextElement;
         }
         [coder encodeInt:count forKey:@ "KAGradientElementCount" ];
         [coder encodeInt:blendingMode forKey:@ "KAGradientBlendingMode" ];
     }
     else
         [ NSException raise: NSInvalidArchiveOperationException format:@ "Only supports NSKeyedArchiver coders" ];
}
  
- ( id )initWithCoder:( NSCoder *)coder
{
     [ self _commonInit];
      
     [ self setBlendingMode:[coder decodeIntForKey:@ "KAGradientBlendingMode" ]];
     unsigned count = [coder decodeIntForKey:@ "KAGradientElementCount" ];
      
     while(count != 0)
     {
         KAGradientElement newElement;
          
         [coder decodeValueOfObjCType: @encode ( float ) at:&(newElement.red)];
         [coder decodeValueOfObjCType: @encode ( float ) at:&(newElement.green)];
         [coder decodeValueOfObjCType: @encode ( float ) at:&(newElement.blue)];
         [coder decodeValueOfObjCType: @encode ( float ) at:&(newElement.alpha)];
         [coder decodeValueOfObjCType: @encode ( float ) at:&(newElement.position)];
          
         count--;
         [ self addElement:&newElement];
     }
     return self ;
}
#pragma mark -
  
#pragma mark [PrivateMethods]
- ( void )_commonInit
{
     elementList = nil ;
}
  
- ( void )setBlendingMode:(KAGradientBlendingMode)mode
{
     blendingMode = mode;
      
     //Choose what blending function to use
     void *evaluationFunction;
     switch (blendingMode)
     {
         case KALinearBlendingMode:
             evaluationFunction = &linearEvaluation;            break ;
         case KAChromaticBlendingMode:
             evaluationFunction = &chromaticEvaluation;            break ;
         case KAInverseChromaticBlendingMode:
             evaluationFunction = &inverseChromaticEvaluation;    break ;
     }
      
     //replace the current CoreGraphics Function with new one
     if (gradientFunction != NULL )
         CGFunctionRelease(gradientFunction);
      
     CGFunctionCallbacks evaluationCallbackInfo = {0 , evaluationFunction, NULL };    //Version, evaluator function, cleanup function
      
     static c*****t float input_value_range   [2] = { 0, 1 };                        //range  for the evaluator input
     static c*****t float output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };        //ranges for the evaluator output (4 returned values)
      
     gradientFunction = CGFunctionCreate(&elementList,                    //the two transition colors
                                         1, input_value_range  ,        //number of inputs (just fraction of progression)
                                         4, output_value_ranges,        //number of outputs (4 - RGBa)
                                         &evaluationCallbackInfo);        //info for using the evaluator function
      
}
- (KAGradientBlendingMode)blendingMode
{
     return blendingMode;
}
  
- ( void )addElement:(KAGradientElement*)newElement
{
     if (elementList == nil || newElement->position < elementList->position)
     {
         // insert at the beginning
         KAGradientElement* tmpNext = elementList;
         elementList = malloc( sizeof (KAGradientElement));
         *elementList = *newElement;
         elementList->nextElement = tmpNext;
     }
     else
     {
         KAGradientElement* currentElement = elementList;
         while (currentElement->nextElement != nil 
                && !((currentElement->position <= newElement->position) 
                     && (newElement->position < currentElement->nextElement->position)))
         {
             currentElement = currentElement->nextElement;
         }
          
         KAGradientElement* tmpNext = currentElement->nextElement;
         currentElement->nextElement = malloc( sizeof (KAGradientElement));
         *(currentElement->nextElement) = *newElement;
         currentElement->nextElement->nextElement = tmpNext;
     }
}
- (KAGradientElement *)elementAtIndex:(unsigned)index
{
     unsigned count = 0;
     KAGradientElement *currentElement = elementList;
      
     while (currentElement != nil )
     {
         if (count == index)
             return currentElement;
          
         count++;
         currentElement = currentElement->nextElement;
     }
      
     return nil ;
}
- (KAGradientElement)removeElementAtIndex:(unsigned)index
{
     KAGradientElement removedElement;
      
     if (elementList != nil )
     {
         if (index == 0)
         {
             KAGradientElement *tmpNext = elementList;
             elementList = elementList->nextElement;
              
             removedElement = *tmpNext;
             free(tmpNext);
              
             return removedElement;
         }
          
         unsigned count = 1;        //we want to start one ahead
         KAGradientElement *currentElement = elementList;
         while(currentElement->nextElement != nil )
         {
             if (count == index)
             {
                 KAGradientElement *tmpNext  = currentElement->nextElement;
                 currentElement->nextElement = currentElement->nextElement->nextElement;
                  
                 removedElement = *tmpNext;
                 free(tmpNext);
                  
                 return removedElement;
             }
              
             count++;
             currentElement = currentElement->nextElement;
         }
     }
      
     //element is not found, return empty element
     removedElement.red   = 0.0;
     removedElement.green = 0.0;
     removedElement.blue  = 0.0;
     removedElement.alpha = 0.0;
     removedElement.position = NAN;
     removedElement.nextElement = nil ;
      
     return removedElement;
}
- (KAGradientElement)removeElementAtPosition:( float )position
{
     KAGradientElement removedElement;
      
     if (elementList != nil )
     {
         if (elementList->position == position)
         {
             KAGradientElement *tmpNext = elementList;
             elementList = elementList->nextElement;
              
             removedElement = *tmpNext;
             free(tmpNext);
              
             return removedElement;
         }
         else
         {
             KAGradientElement *curElement = elementList;
             while(curElement->nextElement != nil )
             {
                 if (curElement->nextElement->position == position)
                 {
                     KAGradientElement *tmpNext = curElement->nextElement;
                     curElement->nextElement = curElement->nextElement->nextElement;
                      
                     removedElement = *tmpNext;
                     free(tmpNext);
                      
                     return removedElement;
                 }
             }
         }
     }
      
     //element is not found, return empty element
     removedElement.red   = 0.0;
     removedElement.green = 0.0;
     removedElement.blue  = 0.0;
     removedElement.alpha = 0.0;
     removedElement.position = NAN;
     removedElement.nextElement = nil ;
      
     return removedElement;
}
  
#pragma mark [color stop]
- ( void ) addColorStop: ( NSColor *) stopColor
            atPosition: (CGFloat) position
{
     if ( nil == stopColor)
         [ NSException raise: NSInvalidArgumentException format:@ "The incoming color can't be nil" ];
     if (position < 0.0f || position > 1.0f)
         [ NSException raise: NSInvalidArgumentException format:@ "Location value should > 0.0f and < 1.0f. It can't be %f" , position];
      
     KAGradientElement newElement;
      
     // put the components of color into the newElement 
     //- must make sure it is a RGB color (not gray or CMYK)
     [[stopColor colorUsingColorSpaceName: NSCalibratedRGBColorSpace ] getRed: &newElement.red
                                                                       green: &newElement.green
                                                                        blue: &newElement.blue 
                                                                       alpha: &newElement.alpha];
     newElement.position = position;
     [ self addElement: &newElement];
}
  
#pragma mark [Draw functi*****]
// draw
- ( void ) drawFromPoint: ( NSPoint ) startingPoint
                toPoint: ( NSPoint ) endingPoint
{
      
}
- ( void ) drawFromCenter: ( NSPoint ) startingCenter
                  radius: (CGFloat) startRadius
                toCenter: ( NSPoint ) endCenter
                  radius: (CGFloat) endRadius
{
      
}
  
- ( void ) drawInRect: ( NSRect ) rect 
               angle: (CGFloat) angle
{
     //First Calculate where the beginning and ending points should be
     CGPoint startPoint;
     CGPoint endPoint;
      
     if (angle == 0)        //screw the calculati***** - we know the answer
       {
         startPoint = CGPointMake( NSMinX (rect), NSMinY (rect));    //right of rect
         endPoint   = CGPointMake( NSMaxX (rect), NSMinY (rect));    //left  of rect
       }
     else if (angle == 90)    //same as above
       {
         startPoint = CGPointMake( NSMinX (rect), NSMinY (rect));    //bottom of rect
         endPoint   = CGPointMake( NSMinX (rect), NSMaxY (rect));    //top    of rect
       }
     else                        //ok, we'll do the calculati***** now 
       {
         float x,y;
         float sina, cosa, tana;
          
         float length;
         float deltax,
         deltay;
          
         float rangle = angle * pi/180;    //convert the angle to radians
          
         if (fabsf(tan(rangle))<=1)    //for range [-45,45], [135,225]
         {
             x = NSWidth (rect);
             y = NSHeight (rect);
              
             sina = sin(rangle);
             cosa = cos(rangle);
             tana = tan(rangle);
              
             length = x/fabsf(cosa)+(y-x*fabsf(tana))*fabsf(sina);
              
             deltax = length*cosa/2;
             deltay = length*sina/2;
         }
         else                        //for range [45,135], [225,315]
         {
             x = NSHeight (rect);
             y = NSWidth (rect);
              
             sina = sin(rangle - 90*pi/180);
             cosa = cos(rangle - 90*pi/180);
             tana = tan(rangle - 90*pi/180);
              
             length = x/fabsf(cosa)+(y-x*fabsf(tana))*fabsf(sina);
              
             deltax =-length*sina/2;
             deltay = length*cosa/2;
         }
          
         startPoint = CGPointMake( NSMidX (rect)-deltax, NSMidY (rect)-deltay);
         endPoint   = CGPointMake( NSMidX (rect)+deltax, NSMidY (rect)+deltay);
     }
      
     //Calls to CoreGraphics
     CGContextRef currentContext = (CGContextRef)[[ NSGraphicsContext currentContext] graphicsPort];
     CGContextSaveGState(currentContext);
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
     CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
#else
     CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
#endif
     CGShadingRef myCGShading = CGShadingCreateAxial(colorspace, startPoint, endPoint, gradientFunction, false , false );
      
     CGContextClipToRect (currentContext, *(CGRect *)&rect);    //This is where the action happens
     CGContextDrawShading(currentContext, myCGShading);
      
     CGShadingRelease(myCGShading);
     CGColorSpaceRelease(colorspace );
     CGContextRestoreGState(currentContext);
}
- ( void ) drawInBezierPath: ( NSBezierPath *) path 
                     angle: (CGFloat) angle
{
     NSGraphicsContext *currentContext = [ NSGraphicsContext currentContext];
     [currentContext saveGraphicsState];
     NSAffineTransform *transform = [[ NSAffineTransform alloc] init];
      
     [transform rotateByDegrees:-angle];
     [path transformUsingAffineTransform:transform];
     [transform invert];
     [transform concat];
      
     [path addClip];
     [ self drawInRect:[path bounds] angle:0];
     [path transformUsingAffineTransform:transform];
     [transform release];
     [currentContext restoreGraphicsState];
}
  
- ( void ) drawRadialInRect: ( NSRect ) rect
{
     CGPoint startPoint, endPoint;
     float startRadius, endRadius;
     float scalex, scaley, transx, transy;
      
     startPoint = endPoint = CGPointMake( NSMidX (rect), NSMidY (rect));
      
     startRadius = -1;
     if ( NSHeight (rect)> NSWidth (rect))
     {
         scalex = NSWidth (rect)/ NSHeight (rect);
         transx = rect.origin.x + ( NSHeight (rect)- NSWidth (rect))/2;
         scaley = 1;
         transy = 1;
         endRadius = NSHeight (rect)/2;
     }
     else
     {
         scalex = 1;
         transx = 1;
         scaley = NSHeight (rect)/ NSWidth (rect);
         transy = rect.origin.y + ( NSWidth (rect)- NSHeight (rect))/2;
         endRadius = NSWidth (rect)/2;
     }
      
     //Calls to CoreGraphics
     CGContextRef currentContext = (CGContextRef)[[ NSGraphicsContext currentContext] graphicsPort];
     CGContextSaveGState(currentContext);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
     CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
#else
     CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
#endif
     CGShadingRef myCGShading = CGShadingCreateRadial(colorspace, startPoint, startRadius, endPoint, endRadius, gradientFunction, true , true );
      
     CGContextClipToRect  (currentContext, *(CGRect *)&rect);
     CGContextScaleCTM    (currentContext, scalex, scaley);
     CGContextTranslateCTM(currentContext, transx, transy);
     CGContextDrawShading (currentContext, myCGShading);        //This is where the action happens
      
     CGShadingRelease(myCGShading);
     CGColorSpaceRelease(colorspace);
     CGContextRestoreGState(currentContext);
}
- ( void ) drawRadialInBezierPath: ( NSBezierPath *) path
{
     NSGraphicsContext *currentContext = [ NSGraphicsContext currentContext];
     [currentContext saveGraphicsState];
     [path addClip];
     [ self drawRadialInRect:[path bounds]];
     [currentContext restoreGraphicsState];
}
#pragma mark -
  
#pragma mark Core Graphics
//Blending Functi*****/
void linearEvaluation ( void *info, c*****t float *in, float *out)
{
     float position = *in;
      
     if (*(KAGradientElement **)info == nil )    //if elementList is empty return clear color
     {
         out[0] = out[1] = out[2] = out[3] = 1;
         return ;
     }
      
     //This grabs the first two colors in the sequence
     KAGradientElement *color1 = *(KAGradientElement **)info;
     KAGradientElement *color2 = color1->nextElement;
      
     //make sure first color and second color are on other sides of position
     while(color2 != nil && color2->position < position)
       {
         color1 = color2;
         color2 = color1->nextElement;
       }
     //if we don't have another color then make next color the same color
     if (color2 == nil )
     {
         color2 = color1;
     }
      
     //----------FailSafe settings----------
     //color1->red   = 1; color2->red   = 0;
     //color1->green = 1; color2->green = 0;
     //color1->blue  = 1; color2->blue  = 0;
     //color1->alpha = 1; color2->alpha = 1;
     //color1->position = .5;
     //color2->position = .5;
     //-------------------------------------
      
     if (position <= color1->position)            //Make all below color color1's position equal to color1
       {
         out[0] = color1->red; 
         out[1] = color1->green;
         out[2] = color1->blue;
         out[3] = color1->alpha;
       }
     else if (position >= color2->position)    //Make all above color color2's position equal to color2
       {
         out[0] = color2->red; 
         out[1] = color2->green;
         out[2] = color2->blue;
         out[3] = color2->alpha;
       }
     else                                        //Interpolate color at posti***** between color1 and color1
       {
         //adjust position so that it goes from 0 to 1 in the range from color 1 & 2's position 
         position = (position-color1->position)/(color2->position - color1->position);
          
         out[0] = (color2->red   - color1->red  )*position + color1->red; 
         out[1] = (color2->green - color1->green)*position + color1->green;
         out[2] = (color2->blue  - color1->blue )*position + color1->blue;
         out[3] = (color2->alpha - color1->alpha)*position + color1->alpha;
     }
      
     //Premultiply the color by the alpha.
     out[0] *= out[3];
     out[1] *= out[3];
     out[2] *= out[3];
}
  
//Chromatic Evaluation - 
//    This blends colors by their Hue, Saturation, and Value(Brightness) right now I just 
//    transform the RGB values stored in the KAGradientElements to HSB, in the future I may
//    streamline it to avoid transforming in and out of HSB colorspace *for later*
//
//    For the chromatic blend we shift the hue of color1 to meet the hue of color2. To do
//    this we will add to the hue's angle (if we subtract we'll be doing the inverse
//    chromatic...scroll down more for that). All we need to do is keep adding to the hue
//  until we wrap around the colorwheel and get to color2.
void chromaticEvaluation( void *info, c*****t float *in, float *out)
{
     float position = *in;
      
     if (*(KAGradientElement **)info == nil )    //if elementList is empty return clear color
     {
         out[0] = out[1] = out[2] = out[3] = 1;
         return ;
     }
      
     //This grabs the first two colors in the sequence
     KAGradientElement *color1 = *(KAGradientElement **)info;
     KAGradientElement *color2 = color1->nextElement;
      
     float c1[4];
     float c2[4];
      
     //make sure first color and second color are on other sides of position
     while(color2 != nil && color2->position < position)
       {
         color1 = color2;
         color2 = color1->nextElement;
       }
     //if we don't have another color then make next color the same color
     if (color2 == nil )
     {
         color2 = color1;
     }
      
      
     c1[0] = color1->red; 
     c1[1] = color1->green;
     c1[2] = color1->blue;
     c1[3] = color1->alpha;
      
     c2[0] = color2->red; 
     c2[1] = color2->green;
     c2[2] = color2->blue;
     c2[3] = color2->alpha;
      
     transformRGB_HSV(c1);
     transformRGB_HSV(c2);
     resolveHSV(c1,c2);
      
     if (c1[0] > c2[0]) //if color1's hue is higher than color2's hue then 
         c2[0] += 360;    //    we need to move c2 one revolution around the wheel
      
      
     if (position <= color1->position)            //Make all below color color1's position equal to color1
       {
         out[0] = c1[0]; 
         out[1] = c1[1];
         out[2] = c1[2];
         out[3] = c1[3];
       }
     else if (position >= color2->position)    //Make all above color color2's position equal to color2
       {
         out[0] = c2[0]; 
         out[1] = c2[1];
         out[2] = c2[2];
         out[3] = c2[3];
       }
     else                                        //Interpolate color at posti***** between color1 and color1
       {
         //adjust position so that it goes from 0 to 1 in the range from color 1 & 2's position 
         position = (position-color1->position)/(color2->position - color1->position);
          
         out[0] = (c2[0] - c1[0])*position + c1[0]; 
         out[1] = (c2[1] - c1[1])*position + c1[1];
         out[2] = (c2[2] - c1[2])*position + c1[2];
         out[3] = (c2[3] - c1[3])*position + c1[3];
       }
      
     transformHSV_RGB(out);
      
     //Premultiply the color by the alpha.
     out[0] *= out[3];
     out[1] *= out[3];
     out[2] *= out[3];
}
  
//Inverse Chromatic Evaluation - 
//    Inverse Chromatic is about the same story as Chromatic Blend, but here the Hue
//    is strictly decreasing, that is we need to get from color1 to color2 by decreasing
//    the 'angle' (i.e. 90o -> 180o would be done by subtracting 270o and getting -180o...
//    which is equivalent to 180o mod 360o
void inverseChromaticEvaluation( void *info, c*****t float *in, float *out)
{
     float position = *in;
      
     if (*(KAGradientElement **)info == nil )    //if elementList is empty return clear color
     {
         out[0] = out[1] = out[2] = out[3] = 1;
         return ;
     }
      
     //This grabs the first two colors in the sequence
     KAGradientElement *color1 = *(KAGradientElement **)info;
     KAGradientElement *color2 = color1->nextElement;
      
     float c1[4];
     float c2[4];
      
     //make sure first color and second color are on other sides of position
     while(color2 != nil && color2->position < position)
       {
         color1 = color2;
         color2 = color1->nextElement;
       }
     //if we don't have another color then make next color the same color
     if (color2 == nil )
     {
         color2 = color1;
     }
      
     c1[0] = color1->red; 
     c1[1] = color1->green;
     c1[2] = color1->blue;
     c1[3] = color1->alpha;
      
     c2[0] = color2->red; 
     c2[1] = color2->green;
     c2[2] = color2->blue;
     c2[3] = color2->alpha;
      
     transformRGB_HSV(c1);
     transformRGB_HSV(c2);
     resolveHSV(c1,c2);
      
     if (c1[0] < c2[0]) //if color1's hue is higher than color2's hue then 
         c1[0] += 360;    //    we need to move c2 one revolution back on the wheel
      
      
     if (position <= color1->position)            //Make all below color color1's position equal to color1
       {
         out[0] = c1[0]; 
         out[1] = c1[1];
         out[2] = c1[2];
         out[3] = c1[3];
       }
     else if (position >= color2->position)    //Make all above color color2's position equal to color2
       {
         out[0] = c2[0]; 
         out[1] = c2[1];
         out[2] = c2[2];
         out[3] = c2[3];
       }
     else                                        //Interpolate color at posti***** between color1 and color1
       {
         //adjust position so that it goes from 0 to 1 in the range from color 1 & 2's position 
         position = (position-color1->position)/(color2->position - color1->position);
          
         out[0] = (c2[0] - c1[0])*position + c1[0]; 
         out[1] = (c2[1] - c1[1])*position + c1[1];
         out[2] = (c2[2] - c1[2])*position + c1[2];
         out[3] = (c2[3] - c1[3])*position + c1[3];
       }
      
     transformHSV_RGB(out);
      
     //Premultiply the color by the alpha.
     out[0] *= out[3];
     out[1] *= out[3];
     out[2] *= out[3];
}
  
  
void transformRGB_HSV( float *components) //H,S,B -> R,G,B
{
     float H, S, V;
     float R = components[0],
     G = components[1],
     B = components[2];
      
     float MAX = R > G ? (R > B ? R : B) : (G > B ? G : B),
     MIN = R < G ? (R < B ? R : B) : (G < B ? G : B);
      
     if (MAX == MIN)
         H = NAN;
     else if (MAX == R)
         if (G >= B)
             H = 60*(G-B)/(MAX-MIN)+0;
         else
             H = 60*(G-B)/(MAX-MIN)+360;
         else if (MAX == G)
             H = 60*(B-R)/(MAX-MIN)+120;
         else if (MAX == B)
             H = 60*(R-G)/(MAX-MIN)+240;
      
     S = MAX == 0 ? 0 : 1 - MIN/MAX;
     V = MAX;
      
     components[0] = H;
     components[1] = S;
     components[2] = V;
}
  
void transformHSV_RGB( float *components) //H,S,B -> R,G,B
{
     float R, G, B;
     float H = fmodf(components[0],359),    //map to [0,360)
     S = components[1],
     V = components[2];
      
     int   Hi = ( int )floorf(H/60.) % 6;
     float f  = H/60-Hi,
     p  = V*(1-S),
     q  = V*(1-f*S),
     t  = V*(1-(1-f)*S);
      
     switch (Hi)
     {
         case 0:    R=V;G=t;B=p;    break ;
         case 1:    R=q;G=V;B=p;    break ;
         case 2:    R=p;G=V;B=t;    break ;
         case 3:    R=p;G=q;B=V;    break ;
         case 4:    R=t;G=p;B=V;    break ;
         case 5:    R=V;G=p;B=q;    break ;
     }
      
     components[0] = R;
     components[1] = G;
     components[2] = B;
}
  
void resolveHSV( float *color1, float *color2)    //H value may be undefined (i.e. graycale color)
{                                            //    we want to fill it with a sensible value
     if (isnan(color1[0]) && isnan(color2[0]))
         color1[0] = color2[0] = 0;
     else if (isnan(color1[0]))
         color1[0] = color2[0];
     else if (isnan(color2[0]))
         color2[0] = color1[0];
}

nt2b}u>*  
*y4DK6OFe

?
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
#import <COCOA Cocoa.h>
#import "KAGradientProtocol.h"
  
/*!
     @class
     @abstract    Private Gradient class which will be used on OS X which version
                  is more than 10.5
     @discussion  The is a class which uses NSGradient to draw graphics on 
                  10.5/10.6. And it has the different draw methods than NSGradient.
                  You can add color stop after initialization.
*/
@interface _NSGradient : NSObject <KAGRADIENTPROTOCOL>
{
@private
     NSGradient        *m_Gradient;
     NSMutableArray    *m_Colors;
     NSMutableArray    *m_Locati*****;
      
     int                __colorsCount;
}
  
/*!
     @function
     @abstract   Add color stop
     @discussion You can add a color stop after initialization.
     @param      color The color you want to add.
     @param        location The color location. The value should between 0.0f and 1.0f.
     @result     Void.
     @exception    NSInvalidArgumentException If the colro is nil or value of 
                 location is invalid, it will rasie the exception.
*/
- ( void ) addColor:( NSColor *) color andLocation:(CGFloat) location;
  
#pragma mark Accessors
- ( NSGradient *) m_Gradient;
- ( void ) setM_Gradient: ( NSGradient *) newValue;
- ( NSMutableArray *) m_Colors;
- ( void ) setM_Colors: ( NSMutableArray *) newValue;
- ( NSMutableArray *) m_Locati*****;
- ( void ) setM_Locati*****: ( NSMutableArray *) newValue;
@end

Ic'D# m  
T\gs

?
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
#import "_NSGradient.h"
  
  
@implementation _NSGradient
  
- ( void ) dealloc
{
     [ self setM_Colors: nil ];
     [ self setM_Gradient: nil ];
     [ self setM_Locati*****: nil ];
      
     [ super dealloc];
}
  
#pragma mark Protocol Methods
+ ( id ) gradientWithStartingColor: ( NSColor *) startingColor
                      endingColor: ( NSColor *) endingColor
{
     return [[[ self alloc] initWithStartingColor:startingColor endingColor:endingColor] autorelease];
}
  
- ( id ) initWithStartingColor: ( NSColor *) startingColor
                  endingColor: ( NSColor *) endingColor
{
     if ( self = [ super init])
     {
         [ self setM_Colors:[ NSMutableArray array]];
         [ self setM_Locati*****:[ NSMutableArray array]];
          
         [ self addColor:startingColor andLocation:0.0f];
         [ self addColor:endingColor andLocation:1.0f];
     }
     return self ;
}
  
- ( void ) addColorStop: ( NSColor *) stopColor
            atPosition: (CGFloat) position
{
     [ self addColor:stopColor andLocation:position];
}
  
- ( void ) drawFromPoint: ( NSPoint ) startingPoint
                toPoint: ( NSPoint ) endingPoint
{
     [ self _initGradientInstance];
     [m_Gradient drawFromPoint:startingPoint 
                       toPoint:endingPoint 
                       opti*****: NSGradientDrawsAfterEndingLocation ];
}
  
- ( void ) drawFromCenter: ( NSPoint ) startingCenter
                  radius: (CGFloat) startRadius
                toCenter: ( NSPoint ) endCenter
                  radius: (CGFloat) endRadius
{
     [ self _initGradientInstance];
     [m_Gradient drawFromCenter:startingCenter 
                         radius:startRadius 
                       toCenter:endCenter 
                         radius:endRadius 
                        opti*****: NSGradientDrawsAfterEndingLocation ];
}
  
- ( void ) drawInRect: ( NSRect ) rect 
               angle: (CGFloat) angle
{
     [ self _initGradientInstance];
     [m_Gradient drawInRect:rect angle:angle];
}
  
- ( void ) drawInBezierPath: ( NSBezierPath *) path 
                     angle: (CGFloat) angle
{
     [ self _initGradientInstance];
     [m_Gradient drawInBezierPath:path angle:angle];
}
  
- ( void ) drawRadialInRect: ( NSRect ) rect
{
     [ self _initGradientInstance];
     [m_Gradient drawInRect:rect relativeCenterPosition: NSZeroPoint ];
}
  
- ( void ) drawRadialInBezierPath: ( NSBezierPath *) path
{
     [ self _initGradientInstance];
     [m_Gradient drawInBezierPath:path relativeCenterPosition: NSZeroPoint ];
}
  
  
#pragma mark Private Methods
/*!
     @function
     @abstract   The private method to init the gradient instance.
     @discussion Beacuse we need to add color after initialization, we can't init
                 the gradient instance before starting drawing. The method should
                 only be invoked when drawing.
     @param      nil
     @result     void
     @exception    NSInvalidArgumentException If the graident have less than 2 color
                 stops, it will raise this exception.
*/
- ( void ) _initGradientInstance
{
     // Gradients must have at least two color stops: one defining the location of the start color and one defining the location of the end color.
     // Gradients may have additional color stops located at different transition points in between the start and end stops.
     if (__colorsCount < 2)
         [ NSException raise: NSInvalidArgumentException format:@ "Color stop of Gradient must be more than 2. We only have %i now." , __colorsCount];
      
     if ( nil == [ self m_Gradient])
     {
         CGFloat *locati***** = malloc( sizeof (CGFloat)*__colorsCount);
         for ( int i = 0; i < __colorsCount; i++)
         {
             locati*****[i] = [[m_Locati***** objectAtIndex:i] floatValue];
         }
         NSGradient *tempGradient = [[ NSGradient alloc] initWithColors:m_Colors
                                                           atLocati*****:locati***** 
                                                            colorSpace:[ NSColorSpace deviceRGBColorSpace]];
         [ self setM_Gradient:tempGradient];
         [tempGradient release];
         free(locati*****);
     }
}
  
  
- ( void ) addColor:( NSColor *) color andLocation:(CGFloat) location
{
     if ( nil == color)
         [ NSException raise: NSInvalidArgumentException format:@ "The incoming color can't be nil" ];
     if (location < 0.0f || location > 1.0f)
         [ NSException raise: NSInvalidArgumentException format:@ "Location value should > 0.0f and < 1.0f. It can't be %f" , location];
      
     [m_Colors insertObject:color atIndex:__colorsCount];
     [m_Locati***** insertObject:[ NSNumber numberWithFloat:location] atIndex:__colorsCount];
      
     __colorsCount ++;
}
  
#pragma mark Accessors
  
- ( NSGradient *) m_Gradient {
     return m_Gradient;
}
  
- ( void ) setM_Gradient: ( NSGradient *) newValue {
     [m_Gradient autorelease];
     m_Gradient = [newValue retain];
}
  
  
- ( NSMutableArray *) m_Colors {
     return m_Colors;
}
  
- ( void ) setM_Colors: ( NSMutableArray *) newValue {
     [m_Colors autorelease];
     m_Colors = [newValue retain];
}
  
  
- ( NSMutableArray *) m_Locati***** {
     return m_Locati*****;
}
  
- ( void ) setM_Locati*****: ( NSMutableArray *) newValue {
     [m_Locati***** autorelease];
     m_Locati***** = [newValue retain];
}
  
@end

sVh)Ofn  
2hHRitt36

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#import <COCOA Cocoa.h>
#import "KAGradientProtocol.h"
  
/*!
     @class
     @abstract    Factory class for gradient.
     @discussion  This is a factory class which uses to create different gradient
                  instance according os's version.
*/
@interface KAGradient : NSObject <KAGRADIENTPROTOCOL>
{
     id <KAGRADIENTPROTOCOL> m_TheGradient;
}
  
- ( id <KAGRADIENTPROTOCOL>) theGradient;
- ( void ) SetGradient:( id <KAGRADIENTPROTOCOL>)newGradient;
  
@end

|>ztx}\  
Mi.#x_

?
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
#import "KAGradient.h"
#import "_KAGradient.h"
#import "_NSGradient.h"
  
@implementation KAGradient
  
#pragma mark Protocol Methods
+ ( id ) gradientWithStartingColor: ( NSColor *) startingColor
                      endingColor: ( NSColor *) endingColor
{
     return [[[ self alloc] initWithStartingColor:startingColor endingColor:endingColor] autorelease];
}
  
- ( id ) initWithStartingColor: ( NSColor *) startingColor
                  endingColor: ( NSColor *) endingColor
{
     if ( self = [ super init])
     {
         SInt32 minorVer, majorVer;
         Gestalt(gestaltSystemVersionMajor, &majorVer);
         Gestalt(gestaltSystemVersionMinor, &minorVer);
          
         // Leopard && Snow Leopard
         if ((majorVer >= 10)&&(minorVer >= 5))
         {
             [ self SetGradient:[_NSGradient gradientWithStartingColor:startingColor endingColor:endingColor]];
         }
         // 10.4
         else if ((majorVer == 10)&&(minorVer == 4) )
         {
             [ self SetGradient:[_KAGradient gradientWithStartingColor:startingColor endingColor:endingColor]];
         }
         // Error OS Version
         else
         {
             [ NSException raise: NSInvalidArgumentException format:@ "You can't use gradient on this OS version. We only support 10.4 and later. You Max OS version is %i.%i"
              majorVer, minorVer];
         }
     }
     return self ;
}
- ( void ) addColorStop: ( NSColor *) stopColor
            atPosition: (CGFloat) position
{
     [m_TheGradient addColorStop:stopColor atPosition:position];
}
  
- ( void ) drawFromPoint: ( NSPoint ) startingPoint
                toPoint: ( NSPoint ) endingPoint
{
     [m_TheGradient drawFromPoint:startingPoint toPoint:endingPoint];
}
  
- ( void ) drawFromCenter: ( NSPoint ) startingCenter
                  radius: (CGFloat) startRadius
                toCenter: ( NSPoint ) endCenter
                  radius: (CGFloat) endRadius
{
     [m_TheGradient drawFromCenter:startingCenter radius:startRadius toCenter:endCenter radius:endRadius];
}
  
- ( void ) drawInRect: ( NSRect ) rect 
               angle: (CGFloat) angle
{
     [m_TheGradient drawInRect:rect angle:angle];
}
  
- ( void ) drawInBezierPath: ( NSBezierPath *) path 
                     angle: (CGFloat) angle
{
     [m_TheGradient drawInBezierPath:path angle:angle];
}
  
- ( void ) drawRadialInRect: ( NSRect ) rect
{
     [m_TheGradient drawRadialInRect:rect];
}
  
- ( void ) drawRadialInBezierPath: ( NSBezierPath *) path
{
     [m_TheGradient drawRadialInBezierPath:path];
}
  
- ( void ) dealloc
{
     [ self SetGradient: nil ];
      
     [ super dealloc];
}
  
- ( id <KAGRADIENTPROTOCOL>) theGradient
{
     return m_TheGradient;
}
- ( void ) SetGradient:( id <KAGRADIENTPROTOCOL>)newGradient
{
     if (m_TheGradient != newGradient)
     {
         if (newGradient != nil && ![newGradient conformsToProtocol: @protocol (KAGradientProtocol)])
         {
             [ NSException raise: NSInvalidArgumentException format:@ "The %@ doesn't implement all methods in KAGradientProtocol." , newGradient];
         }
         [m_TheGradient release];
         m_TheGradient = [newGradient retain];
     }
}
  
@end

[系统控件重绘教程(一)]重绘NSWindow相关推荐

  1. C# ListBox控件中item换行 C#重绘ListBox项

    C# ListBox控件中item换行 C#重绘ListBox项 WindowsForm项目开发中,Listbox控件item数据项,只能一条数据显示在一行,有的时候内容很长,体验就非常之差.简直要歇 ...

  2. Android UI 统一修改Button控件的样式,以及其它系统控件的默认样式

    先介绍下修改原理:首先打开位于android.widget包下面的Button.java文件,这里有一句关键的代码如下: public Button(Context context, Attribut ...

  3. 修改安卓默认的系统button样式,以及其它系统控件的默认样式

    先介绍下修改原理:首先打开位于android.widget包下面的Button.java文件,这里有一句关键的代码如下: public Button(Context context, Attribut ...

  4. Android游戏开发系统控件-CheckBox

    Android游戏开发系统控件-CheckBox 2012/5/11 星期五 CheckBox是Android系统最普通的UI控件,继承了Button按钮 下面通过一个实例来学习 作者:wwj 功能: ...

  5. Android游戏开发系统控件-Dialog

    Android游戏开发系统控件-Dialog Dialog(对话框)在Android应用开发中经常用到,下面是学习<Android游戏编程从零开始>一书,关于Dialog的初步学习. 创建 ...

  6. android layout 替换,LayoutInflater 后记--替换系统控件

    之前记录了自己走通 LayoutInflater 的源码整体流程,一直想搞个好玩的东西,想起之前看到过的换肤方案,决定写个换系统控件的库. 项目地址,项目的具体使用,可以看README 首先需要确定, ...

  7. Android系统控件获取自定义属性

    我们如果想在ImageView,Button,TextView等系统控件中在XML中配置自定义属性该如何实现呢?例如我们有一个scrollView,在ScrollView里面有上述的一些控件的自定义属 ...

  8. 文件批量重命名教程-批量重命名软件推荐

    小伙伴们注意:公众号的推送机制不再按照时间前后推送了,微信公众号信息流乱序.君哥建议大家把科技毒瘤君公众号置顶(设为星标⭐),以便第一时间看到推送,非常感谢~,方法如下图: 上次发了一个BAYC猿壁纸 ...

  9. Android银联手机控件支付使用教程

    Android银联手机控件支付使用教程 最近刚接入银联手机支付,也是第一次搞这个,就写一写Demo的使用.这里就不贴全部代码了,具体可以下载Demo查看.这个教程提供一个url获取tn号和测试账号,可 ...

最新文章

  1. 单语言表征如何迁移到多语言去?
  2. 【JVM调优系列】----NewRatio与SurvivorRatio
  3. canvas动画特效 之 星空
  4. mysqldump 定时备份数据(全量)
  5. http协议中content-length 以及chunked编码分析
  6. jdk版本修改不生效
  7. 解决Windows下Redis出现“MISCONF Redis is configured to save RDB snapshots”的错误
  8. 数电笔记之无关项化简逻辑函数
  9. 论文笔记:NeuS: Learning Neural Implicit Surfaces by Volume Rendering for Multi-view Reconstruction
  10. Verifying an Alien Dictionary
  11. iOS牛顿摆 小球撞击 物理学仿真模拟
  12. Linux下搭建SVN
  13. SAP 中文小写金额转大写金额 amount in word(支持负数)
  14. vue打包时页面布局出现混乱
  15. 3.1 项目经理的角色习题集
  16. matlab算百人同生日概率
  17. ipad一直显示连接app服务器出错,iPad显示无法连接到App Store怎么办 打开不了解决方法...
  18. 刷了一个半月算法题,我薪资终于Double了
  19. 计算机高配置表格,数据大的excel表格对显卡有要求-求excel大量数据处理的电脑配置...
  20. 三菱FX3U-485ADP-MB与英威腾GD变频器通讯程序

热门文章

  1. MultiTech MT9234ZBA 调制解调器Modem的测试方法
  2. Postgresql逻辑复制报错could not start WAL streaming: ERROR: replication slot “x“is active for PID xxx
  3. 微信小程序--优购商城项目(6)
  4. CI第一篇 Jenkins+github fir im 蒲公英pgyer com
  5. 用 Java 实现拦截器 Interceptor 的拦截功能
  6. 工业企业产值产量电子台账操作指南(第一版)
  7. 五维图matlab,五维立体图,怎么画五维图(即以五边形反映各项水平)
  8. ubuntu16.04安装onlyoffice
  9. hangfire mysql_Hangfire 在.NET Core环境的使用
  10. 基于Lumerical的光子晶体谐振腔滤波器仿真模拟