Merge pull request #10 from gunyarakun/fix-invalid-return
[cocotron.git] / AppKit / NSComboBoxCell.m
blob6a9a46d9f6f8929fd6165c111920d93ec296e1b6
1 /* Copyright (c) 2006-2007 Christopher J. W. Lloyd
3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
9 #import <AppKit/NSComboBoxCell.h>
10 #import <AppKit/NSButtonCell.h>
11 #import <AppKit/NSComboBoxWindow.h>
12 #import <Foundation/NSKeyedArchiver.h>
13 #import <AppKit/NSGraphicsStyle.h>
14 #import <AppKit/NSRaise.h>
16 @implementation NSComboBoxCell
18 -(void)encodeWithCoder:(NSCoder *)coder {
19    NSUnimplementedMethod();
22 -initWithCoder:(NSCoder *)coder {
23    [super initWithCoder:coder];
25    if([coder allowsKeyedCoding]){
26     NSKeyedUnarchiver *keyed=(NSKeyedUnarchiver *)coder;
27     
28     _dataSource=[keyed decodeObjectForKey:@"NSDataSource"];
29     _objectValues=[[NSMutableArray alloc] initWithArray:[keyed decodeObjectForKey:@"NSPopUpListData"]];
30     _numberOfVisibleItems=[keyed decodeIntForKey:@"NSVisibleItemCount"];
31     _usesDataSource=[keyed decodeBoolForKey:@"NSUsesDataSource"];
32     _hasVerticalScroller=[keyed decodeBoolForKey:@"NSHasVerticalScroller"];
33     _completes=[keyed decodeBoolForKey:@"NSCompletes"];
34     _isButtonBordered=YES;
35     _buttonEnabled=YES;
36     _buttonPressed=NO;
37    }
38    else {
39     [NSException raise:NSInvalidArgumentException format:@"-[%@ %s] is not implemented for coder %@",isa,sel_getName(_cmd),coder];
40    }
42    return self;
45 -(void)dealloc {
46    [_dataSource release];
47    [_objectValues release];
48    [super dealloc];
51 -copyWithZone:(NSZone *)zone {
52     NSComboBoxCell *copy = [super copyWithZone:zone];
54     copy->_objectValues=[_objectValues copy];
56     return copy;
59 -dataSource {
60    return _dataSource;
63 -(BOOL)usesDataSource {
64    return _usesDataSource;
67 -(BOOL)isButtonBordered {
68    return _isButtonBordered;
71 -(float)itemHeight {
72    return _itemHeight;
75 -(BOOL)hasVerticalScroller {
76    return _hasVerticalScroller;
79 -(NSSize)intercellSpacing {
80    return _intercellSpacing;
83 -(BOOL)completes {
84    return _completes;
87 -(int)numberOfVisibleItems {
88    return _numberOfVisibleItems;
91 -(void)setDataSource:value {
92    _dataSource=value;
95 -(void)setUsesDataSource:(BOOL)value {
96    _usesDataSource=value;
99 -(void)setButtonBordered:(BOOL)value {
100    _isButtonBordered=value;
103 -(void)setItemHeight:(float)value {
104    _itemHeight=value;
107 -(void)setHasVerticalScroller:(BOOL)value {
108    _hasVerticalScroller=value;
111 -(void)setIntercellSpacing:(NSSize)value {
112    _intercellSpacing=value;
115 -(void)setCompletes:(BOOL)flag {
116    _completes=flag;
119 -(void)setNumberOfVisibleItems:(int)value {
120    _numberOfVisibleItems=value;
123 -(int)numberOfItems {
124    return [_objectValues count];
127 -(NSArray *)objectValues {
128    return _objectValues;
131 -itemObjectValueAtIndex:(int)index {
132    return [_objectValues objectAtIndex:index];
135 -(int)indexOfItemWithObjectValue:(id)object {
136    return [_objectValues indexOfObjectIdenticalTo:object];
139 -(void)addItemWithObjectValue:(id)object {
140    [_objectValues addObject:object];
141    _buttonEnabled=([_objectValues count]>0)?YES:NO;
144 -(void)addItemsWithObjectValues:(NSArray *)objects {
145    [_objectValues addObjectsFromArray:objects];
146    _buttonEnabled=([_objectValues count]>0)?YES:NO;
149 -(void)removeAllItems {
150    [_objectValues removeAllObjects];
151    _buttonEnabled=([_objectValues count]>0)?YES:NO;
154 -(void)removeItemAtIndex:(int)index {
155    [_objectValues removeObjectAtIndex:index];
156    _buttonEnabled=([_objectValues count]>0)?YES:NO;
159 -(void)removeItemWithObjectValue:value {
160    [_objectValues removeObject:value];
161    _buttonEnabled=([_objectValues count]>0)?YES:NO;
164 -(void)insertItemWithObjectValue:(id)object atIndex:(int)index {
165    [_objectValues insertObject:object atIndex:index];
166    _buttonEnabled=([_objectValues count]>0)?YES:NO;
169 -(int)indexOfSelectedItem {
170    int index = [_objectValues indexOfObject:[self objectValue]];
171    return (index != NSNotFound)?index:-1;
174 -objectValueOfSelectedItem {
175    if (!_usesDataSource)
176      return [self objectValue];
177    else
178    {
179      NSLog(@"*** -[%@ %s] should not be called when usesDataSource is set to YES",isa,sel_getName(_cmd));
180      return NULL;
181    }
184 -(void)selectItemAtIndex:(int)index {
185     if (index < 0 || index >= [_objectValues count])
186         return;
188     [self setObjectValue:[_objectValues objectAtIndex:index]];
191 -(void)selectItemWithObjectValue:value {
192    if (!_usesDataSource)
193    {
194       int index = [_objectValues indexOfObject:value];
195       [self selectItemAtIndex:(index != NSNotFound)?index:-1];
196    }
197    else
198       NSLog(@"*** -[%@ %s] should not be called when usesDataSource is set to YES",isa,sel_getName(_cmd));
201 -(void)deselectItemAtIndex:(int)index {
202    NSUnimplementedMethod();
205 -(void)scrollItemAtIndexToTop:(int)index {
206    NSUnimplementedMethod();
209 -(void)scrollItemAtIndexToVisible:(int)index {
210    NSUnimplementedMethod();
213 -(void)noteNumberOfItemsChanged {
214    NSUnimplementedMethod();
217 -(void)reloadData {
218    NSUnimplementedMethod();
221 - (NSString *)completedString:(NSString *)string {
222     int i, count = [_objectValues count];
223     
224     if (_usesDataSource == YES)         // not supported yet, well...
225         if ([_dataSource respondsToSelector:@selector(comboBoxCell:completedString:)] == YES)
226             return [_dataSource comboBoxCell:self completedString:string];
228     for (i = 0; i < count; ++i) {
229         NSString *stringValue;
231 //        NSLog(@"checking %@",  [_objectValues objectAtIndex:i]);
232         if ([[_objectValues objectAtIndex:i] isKindOfClass:[NSString class]])
233             stringValue = [_objectValues objectAtIndex:i];
234         else
235             stringValue = [[_objectValues objectAtIndex:i] stringValue];
236         
237         if ([stringValue hasPrefix:string])
238             return stringValue;
239     }
241     return nil;
244 -(NSSize)cellSize {
245    NSSize size=[_controlView frame].size;
246    size.width  -= 3.0;
247    size.height -= 2.0;
248    return size;
251 -(NSRect)buttonRectForBounds:(NSRect)rect {
252    rect.origin.x=(rect.origin.x+rect.size.width)-rect.size.height;
253    rect.size.width=rect.size.height;
254    return rect;
257 -(BOOL)trackMouse:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag {
258    NSComboBoxWindow *window;
259    NSPoint           origin=[controlView bounds].origin;
260    NSSize            size=[self cellSize];
261    NSPoint           check=[controlView convertPoint:[event locationInWindow] fromView:nil];
262    unsigned          selectedIndex = [_objectValues indexOfObject:[self objectValue]];
264    if([_objectValues count]==0)
265     return NO;
267    if(!NSMouseInRect(check,[self buttonRectForBounds:cellFrame],[controlView isFlipped]))
268     return NO;
270    origin.y+=size.height;
271    origin=[controlView convertPoint:origin toView:nil];
272    origin=[[controlView window] convertBaseToScreen:origin];
273    size.width+=1.0;
275    window=[[NSComboBoxWindow alloc] initWithFrame:(NSRect){origin,size}];
277    [window setObjectArray:_objectValues];
278    [window setSelectedIndex:selectedIndex];
279    if([self font] != nil)
280       [window setFont:[self font]];
282    _buttonPressed=YES;
283    [window makeKeyAndOrderFront:self];
284    selectedIndex = [window runTrackingWithEvent:event];
285    [window close]; // release when closed=YES
286    _buttonPressed=NO;
288    if (selectedIndex != NSNotFound)
289    {
290       NSTextView *editor = [controlView currentEditor];
291       NSObject   *object = [_objectValues objectAtIndex:selectedIndex];
292       if (editor && object)
293       {
294          NSString           *string = nil;
295          NSAttributedString *attstr = nil;
297          if (_formatter)
298             string = [_formatter stringForObjectValue:object];
300          if (!string)
301             if ([object isKindOfClass:[NSString class]])
302                string = object;
303             else if ([object isKindOfClass:[NSAttributedString class]])
304                if ([editor isRichText])
305                   attstr = object;
306                else
307                   string = [object string];
308             else if ([object respondsToSelector:@selector(descriptionWithLocale:)])
309                string = [object descriptionWithLocale:[NSLocale currentLocale]];
310             else if ([object respondsToSelector:@selector(description)])
311                string = [object description];
312             else
313                string = @"";
315          if (attstr)
316             [[(NSTextView *)editor textStorage] setAttributedString:attstr];
317          else
318             [editor setString:string];
320          [editor setSelectedRange:NSMakeRange(0, [[editor string] length])];
321          [self endEditing:editor];
322          if (_sendsActionOnEndEditing)
323             [(NSControl *)controlView sendAction:[(NSControl *)controlView action] to:[(NSControl *)controlView target]];
324       }
325    }
327    return YES;
330 -(NSRect)titleRectForBounds:(NSRect)rect {
331    // Keep some room for the button
332    NSRect buttonFrame = [self buttonRectForBounds:rect];
333    rect.size.width   = NSMinX(buttonFrame) - rect.origin.x;
334    rect=[super titleRectForBounds:rect];
336    return rect;
339 -(void)drawInteriorWithFrame:(NSRect)frame inView:(NSView *)controlView {
340    frame.size = [self cellSize];
341    [super drawInteriorWithFrame:frame inView:controlView];
344 -(void)drawWithFrame:(NSRect)frame inView:(NSView *)controlView {
345    frame.size = [self cellSize];
346    [super drawWithFrame:frame inView:controlView];
348    [[controlView graphicsStyle] drawComboBoxButtonInRect:[self buttonRectForBounds:frame] enabled:_buttonEnabled bordered:_isButtonBordered pressed:_buttonPressed];
351 @end