Now, groups can retrieve a list of the contacts in that group. I probably should...
[adiumx.git] / Source / KNShelfSplitView.m
blob8b6c36dad87c48411a05fce177afc473dc920f91
1 /*
3 BSD License
5 Copyright (c) 2006, Keith Anderson
6 All rights reserved.
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
11 *       Redistributions of source code must retain the above copyright notice,
12         this list of conditions and the following disclaimer.
13 *       Redistributions in binary form must reproduce the above copyright notice,
14         this list of conditions and the following disclaimer in the documentation
15         and/or other materials provided with the distribution.
16 *       Neither the name of keeto.net or Keith Anderson nor the names of its
17         contributors may be used to endorse or promote products derived
18         from this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  * Modified to have a glass-style background; this requires the sourceListBackground image.
36  */
38 #import "KNShelfSplitView.h"
40 #import <AIUtilities/AIAttributedStringAdditions.h>
41 #import <AIUtilities/AIParagraphStyleAdditions.h>
42 #import <AIUtilities/AIImageAdditions.h>
43 #import <AIUtilities/AIToolbarUtilities.h>
44 #import <AIAdium.h>
46 #define DEFAULT_SHELF_WIDTH 200
47 #define CONTROL_HEIGHT 22
48 #define BUTTON_WIDTH 30
49 #define THUMB_WIDTH 15
50 #define THUMB_LINE_SPACING 2.0
51 #define RESIZE_BAR_EFFECTIVE_WIDTH 1.0
53 #define CONTROL_PART_NONE 0
54 #define CONTROL_PART_ACTION_BUTTON 1
55 #define CONTROL_PART_CONTEXT_BUTTON 2
56 #define CONTROL_PART_RESIZE_THUMB 3
57 #define CONTROL_PART_RESIZE_BAR 4
59 #define TOOLBAR_TOGGLESHELF_IDENTIFIER @"Toggle Shelf"
60 #define TOGGLESHELF @"Toggle Shelf"
61 @implementation KNShelfSplitView
63 + (void)initialize
65         if ((self == [KNShelfSplitView class])) {
66                 [self exposeBinding:@"contextButtonMenu"];
67         }
71 -(IBAction)toggleShelf:(id)sender
73         #pragma unused(sender)
74         [self setShelfIsVisible: ![self isShelfVisible]];
75         [self setNeedsDisplay: YES];
78 - (id)initWithFrame:(NSRect)aFrame {
79         return [self initWithFrame: aFrame shelfView: nil contentView: nil];
82 -(id)initWithFrame:(NSRect)aFrame shelfView:(NSView *)aShelfView contentView:(NSView *)aContentView{
83         self = [super initWithFrame: aFrame];
84         if( self ){
85                 
86                 currentShelfWidth = DEFAULT_SHELF_WIDTH; //change this
87                 isShelfVisible = YES;
88                 shouldHilite = NO;
89                 activeControlPart = CONTROL_PART_NONE;
90                 contextButtonMenu = nil;
91                 [self recalculateSizes];
92                 
93                 autosaveName = nil;
94                 shelfBackgroundColor = nil;
95                 actionButtonImage = nil;
96                 contextButtonImage = nil;
97                 
98                 background = [[NSImage imageNamed:@"sourceListBackground" forClass:[self class]] retain];
99                 backgroundSize = [background size];
101                 [self setDelegate: nil];
102                 target = nil;
103                 action = nil;
104         
105                 [self setShelfView: aShelfView];
106                 [self setContentView: aContentView];
107         }
108         return self;
112 -(void)dealloc{
113         if( autosaveName ){ [autosaveName release]; }
114         if( contextButtonImage ){ [contextButtonImage release]; }
115         if( actionButtonImage ){ [actionButtonImage release]; }
116         if( shelfBackgroundColor ){ [shelfBackgroundColor release]; }
117         if( contextButtonMenu ){ [contextButtonMenu release]; }
118         if( background ){ [background release]; }
119         
120         [self unbind:@"contextButtonMenu"];
122         [super dealloc];
125 -(void)setDelegate:(id)aDelegate{
126         delegate = aDelegate;
127         
128         delegateHasValidateWidth = NO;
129         
130         if( delegate ){
131                 if( [delegate respondsToSelector:@selector(shelfSplitView:validateWidth:)] ){
132                         delegateHasValidateWidth = YES;
133                 }
134         }
137 -(id)delegate{
138         return delegate;
141 -(void)setTarget:(id)aTarget{
142         target = aTarget;
143         [self recalculateSizes];
146 -(id)target{
147         return target;
150 -(void)setAction:(SEL)aSelector{
151         action = aSelector;
152         [self recalculateSizes];
155 -(SEL)action{
156         return action;
159 -(void)setContextButtonMenu:(NSMenu *)aMenu{
160         if( contextButtonMenu ){
161                 [contextButtonMenu autorelease];
162                 [[NSNotificationCenter defaultCenter] removeObserver: self];
163         }
164         
165         contextButtonMenu = [aMenu retain];
166         
167         if( contextButtonMenu ){
168                 [contextButtonMenu setDelegate: self];
169                 [[NSNotificationCenter defaultCenter] addObserver: self
170                         selector: @selector(didEndContextMenuTracking)
171                         name: NSMenuDidEndTrackingNotification
172                         object: contextButtonMenu
173                 ];
174         }
176         [self recalculateSizes];
179 -(void)didEndContextMenuTracking{
180         shouldHilite = NO;
181         [self setNeedsDisplayInRect: controlRect];
184 -(NSMenu *)contextButtonMenu{
185         return contextButtonMenu;
188 -(void)setShelfView:(NSView *)aView{
189         if( shelfView ){
190                 [shelfView removeFromSuperview];
191         }
192         
193         shelfView = aView;
194         
195         if( shelfView ){
196                 [self addSubview: shelfView];
197         }
198         [self recalculateSizes];
201 -(NSView *)shelfView{
202         return shelfView;
205 -(void)setContentView:(NSView *)aView{
206         if( contentView ){
207                 [contentView removeFromSuperview];
208         }
209         
210         contentView = aView;
211         
212         if( contentView ){
213                 [self addSubview: contentView];
214         }
215         
216         [self recalculateSizes];
219 -(NSView *)contentView{
220         return contentView;
223 -(void)setShelfWidth:(float)aWidth{
224         float                           newWidth = aWidth;
225         
226         
227         // The shelf can never be completely closed. We always have at least enough to show our resize thumb, otherwise
228         // if the delegate responds to shelfSplitView:validateWidth:, we use that width as our minimum shelf size
229         float                           minShelf = THUMB_WIDTH;
230         if( delegateHasValidateWidth ){
231                 float                           requestedWidth = [delegate shelfSplitView:self validateWidth: aWidth];
232                 if( requestedWidth > minShelf ){
233                         minShelf = requestedWidth;
234                 }
235         }
236         if( minShelf > newWidth ){
237                 newWidth = minShelf;
238         }
239         
240         // The shelf can never be wider than half the entire view
241         float maxShelf = [self frame].size.width / 2;
242         
243         if( newWidth > maxShelf ){
244                 newWidth = maxShelf;
245         }
246         
247         currentShelfWidth = newWidth;
248         
249         [self recalculateSizes];
252 -(float)shelfWidth{
253         return currentShelfWidth;
256 -(void)setAutosaveName:(NSString *)aName{
257         if( autosaveName ){
258                 [autosaveName autorelease];
259         }
260         autosaveName = [aName retain];
263 -(NSString *)autosaveName{
264         return autosaveName;
267 -(void)recalculateSizes{        
268         if( isShelfVisible ){
269                 controlRect = NSMakeRect( 0, 0, currentShelfWidth, CONTROL_HEIGHT );
270                 
271                 resizeThumbRect = NSMakeRect( (controlRect.size.width - THUMB_WIDTH), 0, THUMB_WIDTH, CONTROL_HEIGHT );
272                 resizeBarRect = NSMakeRect( currentShelfWidth - (RESIZE_BAR_EFFECTIVE_WIDTH / 2), 0, RESIZE_BAR_EFFECTIVE_WIDTH, [self frame].size.height );
273                 
274                 float availableSpace = controlRect.size.width - THUMB_WIDTH;
275                 
276                 if( target && action && (availableSpace > BUTTON_WIDTH) ){
277                         shouldDrawActionButton = YES;
278                         actionButtonRect = NSMakeRect( 0, 0, BUTTON_WIDTH, CONTROL_HEIGHT );
279                         availableSpace -= BUTTON_WIDTH;
280                 }
281                 
282                 if( contextButtonMenu && [contextButtonMenu numberOfItems] && (availableSpace > BUTTON_WIDTH) ){
283                         shouldDrawContextButton = YES;
284                         contextButtonRect = NSMakeRect(controlRect.size.width - (THUMB_WIDTH + availableSpace), 0, BUTTON_WIDTH, CONTROL_HEIGHT);
285                 }
286         }
287         
288         if( shelfView ){
289                 [shelfView setFrame: NSMakeRect( 0, CONTROL_HEIGHT + 1, currentShelfWidth, [self bounds].size.height - (CONTROL_HEIGHT + 1) )];
290         }
291         
292         if( contentView ){
293                 float contentViewX = (isShelfVisible ? (currentShelfWidth + 1) : 0);
294                 NSRect newRect = NSMakeRect(contentViewX, 0, NSWidth([self bounds]) - contentViewX, NSHeight([self bounds]));
295                 if (!NSEqualRects(newRect, [contentView frame])){
296                         [contentView setFrame:newRect];
297                 }
298         }
299         
300         [self setNeedsDisplay: YES];
301         [[self window] invalidateCursorRectsForView: self];
302         
305 -(BOOL)isShelfVisible{
306         return isShelfVisible;
309 -(void)setShelfIsVisible:(BOOL)visible{
310         if( shelfView ){
311                 if( isShelfVisible && !visible ){
312                         [shelfView retain];
313                         [shelfView removeFromSuperview];
314                 } else if( !isShelfVisible && visible ){
315                         [self addSubview: shelfView];
316                         [shelfView release];
317                 }
318         }
320         isShelfVisible = visible;
321         [self recalculateSizes];
324 -(void)setActionButtonImage:(NSImage *)anImage{
325         if( actionButtonImage ){
326                 [actionButtonImage autorelease];
327         }
328         
329         actionButtonImage = [anImage retain];
330         
331         [self setNeedsDisplayInRect: controlRect];
334 -(NSImage *)actionButtonImage{
335                 return actionButtonImage;
338 -(void)setContextButtonImage:(NSImage *)anImage{
339         if( contextButtonImage ){
340                 [contextButtonImage autorelease];
341         }
342         
343         contextButtonImage = [anImage retain];
344         
345         [self setNeedsDisplayInRect: controlRect];
348 -(NSImage *)contextButtonImage{
349         return contextButtonImage;
352 -(void)setShelfBackgroundColor:(NSColor *)aColor{
353         if( shelfBackgroundColor ){
354                 [shelfBackgroundColor autorelease];
355         }
356         
357         shelfBackgroundColor = [aColor retain];
358         [self setNeedsDisplay: YES];
361 -(NSColor *)shelfBackgroundColor{
362         return shelfBackgroundColor;
365 -(void)resetCursorRects{
366         [super resetCursorRects];
367         if( isShelfVisible ){
368                 [self addCursorRect: resizeThumbRect cursor: [NSCursor resizeLeftRightCursor]];
369                 [self addCursorRect: resizeBarRect cursor: [NSCursor resizeLeftRightCursor]];
370         }
373 -(void)mouseDown:(NSEvent *)anEvent{
374         BOOL                                    stillMouseDown = YES;
375         NSPoint                                 currentLocation;
377         // determine if we're in a control part we care about
378         currentLocation = [self convertPoint: [anEvent locationInWindow] fromView: nil];
379         
380         if( shouldDrawActionButton && NSPointInRect( currentLocation, actionButtonRect ) ){
381                 activeControlPart = CONTROL_PART_ACTION_BUTTON;
382                 shouldHilite = YES;
383         }else if( shouldDrawContextButton && NSPointInRect( currentLocation, contextButtonRect ) ){
384                 activeControlPart = CONTROL_PART_CONTEXT_BUTTON;
385                 shouldHilite = YES;
386                 
387                 NSEvent *                       contextEvent = [NSEvent mouseEventWithType: [anEvent type]
388                                                                                                 location: NSMakePoint( contextButtonRect.origin.x + (contextButtonRect.size.width / 2) , contextButtonRect.origin.y + (contextButtonRect.size.height / 2) )
389                                                                                                 modifierFlags: [anEvent modifierFlags]
390                                                                                                 timestamp: [anEvent timestamp]
391                                                                                                 windowNumber: [anEvent windowNumber]
392                                                                                                 context: [anEvent context]
393                                                                                                 eventNumber: [anEvent eventNumber]
394                                                                                                 clickCount: [anEvent clickCount]
395                                                                                                 pressure: [anEvent pressure]
396                                                                                         ];
397                 [self setNeedsDisplayInRect: controlRect];
398                 [NSMenu popUpContextMenu: contextButtonMenu withEvent: contextEvent forView: self];
399                 [super mouseDown: contextEvent];
400                 return;
401                 
402         }else if( NSPointInRect( currentLocation, resizeThumbRect ) ){
403                 activeControlPart = CONTROL_PART_RESIZE_THUMB;
404         }else if( NSPointInRect( currentLocation, resizeBarRect ) ){
405                 activeControlPart = CONTROL_PART_RESIZE_BAR;
406         }else{
407                 activeControlPart = CONTROL_PART_NONE;
408         }
409         
410         [self setNeedsDisplayInRect: controlRect];
412         if( activeControlPart != CONTROL_PART_NONE ){
413                 if([anEvent clickCount] == 2){
414                         [self setShelfIsVisible: NO];
415                 } else {
416                 while( stillMouseDown ){
417                         anEvent = [[self window] nextEventMatchingMask: NSLeftMouseUpMask | NSLeftMouseDraggedMask];
418                         currentLocation = [self convertPoint: [anEvent locationInWindow] fromView: nil];
419                         shouldHilite = NO;
420                         
421                         if( (activeControlPart == CONTROL_PART_ACTION_BUTTON) && NSPointInRect( currentLocation, actionButtonRect ) ){
422                                 shouldHilite = YES;
423                         }else if( (activeControlPart == CONTROL_PART_CONTEXT_BUTTON) && NSPointInRect( currentLocation, contextButtonRect ) ){
424                                 shouldHilite = YES;
425                         }
426                         
427                         switch( [anEvent type] ){
428                                 case NSLeftMouseDragged:
429                                         if( (activeControlPart == CONTROL_PART_RESIZE_THUMB) || (activeControlPart == CONTROL_PART_RESIZE_BAR) ){
430                                                 [self setShelfWidth: currentLocation.x];
431                                         }else{
432                                                 [self setNeedsDisplayInRect: controlRect];
433                                         }
434                                         break;
435                                         
436                                 case NSLeftMouseUp:
437                                         shouldHilite = NO;
438                                         [self setNeedsDisplayInRect: controlRect];
439                                         
440                                         if( (activeControlPart == CONTROL_PART_ACTION_BUTTON) && NSPointInRect( currentLocation, actionButtonRect ) ){
441                                                 // trigger an action
442                                                 if( target && action && [target respondsToSelector:action]){
443                                                         [target performSelector: action withObject: self];
444                                                 }
445                                         }                                       
446                                         stillMouseDown = NO;
447                                         
448                                         break;
449                                         
450                                 default:
451                                         break;
452                         }
453                 }
454         }
455         }else{
456                 [super mouseDown:anEvent];
457         }
460 - (void)drawRect:(NSRect)rect {
461 #pragma unused( rect )
462         
463                 if( isShelfVisible ){
464                 //NSLog(@"Drawing Control( %f, %f) (%f, %f)", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
465                 
466                 float remainderStart = 0.0;
467                 
468                 // action button
469                 if( shouldDrawActionButton  == YES){
470                         [self drawControlBackgroundInRect: actionButtonRect
471                                 active: (activeControlPart == CONTROL_PART_ACTION_BUTTON) && shouldHilite
472                         ];
473                         [[NSColor windowFrameColor] set];
474                 //      NSRectFill( NSMakeRect( (actionButtonRect.origin.x + actionButtonRect.size.width) - 1, 0, 1, controlRect.size.height ) );
475                         remainderStart += actionButtonRect.size.width;
476                         
477                         if( actionButtonImage ){
478                                 
479                                 NSRect                  targetRect = NSMakeRect(actionButtonRect.origin.x,
480                                                                                                                 actionButtonRect.origin.y,
481                                                                                                                 [actionButtonImage size].width, 
482                                                                                                                 [actionButtonImage size].height
483                                                                                         );
484                                 
485                                 if( targetRect.size.width > actionButtonRect.size.width ){
486                                         targetRect.size.width = actionButtonRect.size.width;
487                                 }
488                                 if( targetRect.size.width < actionButtonRect.size.width ){
489                                         targetRect.origin.x += (actionButtonRect.size.width - targetRect.size.width) / 2.0;
490                                 }
491                                 if( targetRect.size.height > actionButtonRect.size.height ){
492                                         targetRect.size.height = actionButtonRect.size.height;
493                                 }
494                                 if( targetRect.size.height < actionButtonRect.size.height ){
495                                         targetRect.origin.y += (actionButtonRect.size.height - targetRect.size.height) / 2.0;
496                                 }
497                                 
498                                 [actionButtonImage compositeToPoint:NSMakePoint(actionButtonRect.origin.x,
499                                                                                                                 actionButtonRect.origin.y) operation:NSCompositeDestinationAtop];
501         
502                         }
503                 }
504                 
505                 // context button
506                 
507                 if( shouldDrawContextButton ){
508                         [self drawControlBackgroundInRect: contextButtonRect
509                                 active: (activeControlPart == CONTROL_PART_CONTEXT_BUTTON ) && shouldHilite
510                         ];
511                         [[NSColor windowFrameColor] set];
512                         NSRectFill( NSMakeRect( (contextButtonRect.origin.x + contextButtonRect.size.width) - 1, 0, 1, controlRect.size.height ) );
513                         remainderStart += contextButtonRect.size.width;
514                         
515                         if( contextButtonImage ){
516                 
517                                 NSRect                  targetRect = NSMakeRect(contextButtonRect.origin.x,
518                                                                                                                 contextButtonRect.origin.y,
519                                                                                                                 [contextButtonImage size].width, 
520                                                                                                                 [contextButtonImage size].height
521                                                                                         );
522                                 
523                                 if( targetRect.size.width > contextButtonRect.size.width ){
524                                         targetRect.size.width = contextButtonRect.size.width;
525                                 }
526                                 if( targetRect.size.width < contextButtonRect.size.width ){
527                                         targetRect.origin.x += (contextButtonRect.size.width - targetRect.size.width) / 2.0;
528                                 }
529                                 if( targetRect.size.height > contextButtonRect.size.height ){
530                                         targetRect.size.height = contextButtonRect.size.height;
531                                 }
532                                 if( targetRect.size.height < contextButtonRect.size.height ){
533                                         targetRect.origin.y += (contextButtonRect.size.height - targetRect.size.height) / 2.0;
534                                 }
535                                 [contextButtonImage drawInRect: targetRect
536                                         fromRect: NSMakeRect( 0, 0, [contextButtonImage size].width, [contextButtonImage size].height )
537                                         operation: NSCompositeSourceOver
538                                         fraction: 1.0f
539                                 ]; 
540                         }
541                 }
542                 
543                 //remainder and thumb
544                 [self drawControlBackgroundInRect:NSMakeRect( remainderStart, 0, (controlRect.size.width - remainderStart), controlRect.size.height )
545                                                                    active:NO];
547                 [[NSColor windowFrameColor] set];
548                 NSRectFill( NSMakeRect( 0, CONTROL_HEIGHT, currentShelfWidth, 1 ) );
549                 
550                 // Draw our split line
551                 [[NSColor windowFrameColor] set];
552                 NSRectFill( NSMakeRect( currentShelfWidth, 0, 1, [self frame].size.height ) );
553                 
554                 // Draw our thumb lines
555                 [[NSColor disabledControlTextColor] set];
556                 NSRect                  thumbLineRect = NSMakeRect( 
557                                                                                         resizeThumbRect.origin.x + (resizeThumbRect.size.width - ((2*THUMB_LINE_SPACING) + 3.0)) / 2.0, 
558                                                                                         resizeThumbRect.size.height / 4.0, 
559                                                                                         1.0, 
560                                                                                         resizeThumbRect.size.height / 2.0
561                                                                                 );
562                 int i;
563                 for( i=0; i<3; i++ ){
564                         NSRectFill( thumbLineRect );
565                         thumbLineRect.origin.x += (1+THUMB_LINE_SPACING);
566                 }
567                 
568                 if( shelfBackgroundColor ){
569                         [shelfBackgroundColor set];
570                         NSRectFill( NSMakeRect( 0, CONTROL_HEIGHT+1, currentShelfWidth, [self frame].size.height ) );
571                 }
572                 
573                 //Draw the string
574                 if (attributedStringValue && !shouldDrawContextButton && !shouldDrawActionButton) {
575                         NSRect  textRect = NSMakeRect(6, (NSHeight(controlRect) - stringHeight)/2, NSMinX(resizeThumbRect) - 8, stringHeight);
576                         
577                         [attributedStringValue drawInRect:textRect];
578                 } 
579         }
582 -(void)drawControlBackgroundInRect:(NSRect)aRect active:(BOOL)isActive{ 
583         //Draw the background, tiling across
584     NSRect sourceRect = NSMakeRect(0, 0, backgroundSize.width, backgroundSize.height);
585     NSRect destRect = NSMakeRect(aRect.origin.x, aRect.origin.y, sourceRect.size.width, aRect.size.height);
586         
587     while ((destRect.origin.x < NSMaxX(aRect)) && destRect.size.width > 0) {
588         //Crop
589         if (NSMaxX(destRect) > NSMaxX(aRect)) {
590                         destRect.size.width = NSMaxX(aRect) - NSMinX(destRect);
591             sourceRect.size.width = NSWidth(destRect);
592         }
593                 
594         [background drawInRect:destRect
595                                           fromRect:sourceRect
596                                          operation:NSCompositeSourceOver
597                                           fraction:1.0];
598         destRect.origin.x += destRect.size.width;
599     }
602 -(void)setFrame:(NSRect)aRect{
603         [super setFrame: aRect];
604         [self recalculateSizes];
607 #pragma mark Status string
608 - (void)setResizeThumbStringValue:(NSString *)inString
610         if (![inString isEqualToString:stringValue]) {
611                 [stringValue release];
612                 stringValue = [inString copy];
613                 
614                 [attributedStringValue release];
615                 if (stringValue) {
616                         NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
617                                 [NSParagraphStyle styleWithAlignment:NSLeftTextAlignment
618                                                                            lineBreakMode:NSLineBreakByTruncatingTail], NSParagraphStyleAttributeName,
619                                 [NSFont systemFontOfSize:[NSFont smallSystemFontSize]], NSFontAttributeName, 
620                                 nil];
621                         
622                         stringHeight = [NSAttributedString stringHeightForAttributes:attributes];
623                         attributedStringValue = [[NSAttributedString alloc] initWithString:stringValue
624                                                                                                                                         attributes:attributes];
625                 } else {
626                         attributedStringValue = nil;
627                 }
628                 [self setNeedsDisplay:YES];
629         }
632 @end