/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "WOInput.h" #include "decommon.h" @interface WOBrowser : WOInput { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString // inherited: name // inherited: value // inherited: disabled @protected WOAssociation *list; WOAssociation *item; WOAssociation *selection; // => use 'selections'! WOAssociation *string; // WO4 => use 'displayString'! WOAssociation *noSelectionString; // WO4 // non-WO: WOAssociation *singleSelection; // selection contains an item, not an array // WO 4.5 WOAssociation *multiple; // multiple selections allowed WOAssociation *size; // TODO: WO 4.5: selectedValues, escapeHTML } @end /* WOBrowser */ @implementation WOBrowser + (int)version { return [super version] + 0 /* v2 */; } + (void)initialize { NSAssert2([super version] == 2, @"invalid superclass (%@) version %i !", NSStringFromClass([self superclass]), [super version]); } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_c { if ((self = [super initWithName:_name associations:_config template:_c])) { self->list = OWGetProperty(_config, @"list"); self->item = OWGetProperty(_config, @"item"); self->singleSelection = OWGetProperty(_config, @"singleSelection"); self->multiple = OWGetProperty(_config, @"multiple"); self->size = OWGetProperty(_config, @"size"); self->noSelectionString = OWGetProperty(_config, @"noSelectionString"); if ((self->string = OWGetProperty(_config, @"displayString")) == nil) { if ((self->string = OWGetProperty(_config, @"string")) != nil) { [self debugWithFormat: @"Note: using deprecated 'string' binding, " @"use 'displayString' instead."]; } } else if (OWGetProperty(_config, @"string") != nil) { [self debugWithFormat:@"WARNING: 'displayString' AND 'string' bindings " @"are set, use only one! ('string' is deprecated!)"]; } if ((self->selection = OWGetProperty(_config, @"selections")) == nil) { if ((self->selection = OWGetProperty(_config, @"selection")) != nil) { [self debugWithFormat: @"Note: using deprecated 'selection' binding, " @"use 'selections' instead."]; } } else if (OWGetProperty(_config, @"selection") != nil) { [self debugWithFormat:@"WARNING: 'selections' AND 'selection' bindings " @"are set, use only one! ('selection' is deprecated!)"]; } // compatiblity if (self->noSelectionString == nil) self->noSelectionString = OWGetProperty(_config, @"nilString"); if (self->multiple == nil) { self->multiple = [WOAssociation associationWithValue:[NSNumber numberWithBool:YES]]; self->multiple = [self->multiple retain]; } } return self; } - (void)dealloc { [self->noSelectionString release]; [self->singleSelection release]; [self->list release]; [self->item release]; [self->selection release]; [self->string release]; [self->size release]; [self->multiple release]; [super dealloc]; } /* handling request */ - (void)_takeSingleFormValue:(id)formValue fromRequest:(WORequest *)_request inContext:(WOContext *)_ctx { WOComponent *sComponent; NSArray *objects; id object; sComponent = [_ctx component]; objects = [self->list valueInComponent:sComponent]; if ([[formValue stringValue] isEqualToString:@"$"]) object = nil; // nil item selected else { int idx; object = nil; if ((idx = [formValue intValue]) >= 0) { if (idx < (int)[objects count]) object = [objects objectAtIndex:idx]; else { [sComponent logWithFormat: @"WOBrowser got invalid index '%i' (formvalue='%@') " @"for list with count %i !", idx, formValue, [objects count]]; } } else [sComponent logWithFormat:@"WOBrowser got invalid index '%i' !", idx]; } if ([self->selection isValueSettable]) { NSArray *sel; if ([self->item isValueSettable]) [self->item setValue:object inComponent:sComponent]; if (object) { sel = [self->singleSelection boolValueInComponent:sComponent] ? [object retain] : [[NSArray alloc] initWithObjects:object,nil]; } else // nil item selected sel = nil; [self->selection setValue:sel inComponent:sComponent]; [sel release]; sel = nil; } } - (void)_takeMultiFormValue:(NSArray *)formValue fromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { WOComponent *sComponent; NSEnumerator *values; NSString *v; NSArray *objects; id object; values = [formValue objectEnumerator]; sComponent = [_ctx component]; objects = [self->list valueInComponent:sComponent]; if ([self->selection isValueSettable]) { NSMutableArray *sel; unsigned objCount; sel = [[NSMutableArray alloc] initWithCapacity:[formValue count]]; objCount = [objects count]; while ((v = [values nextObject])) { int idx; object = nil; if ((idx = [v intValue]) >= 0) { if (idx < (int)objCount) object = [objects objectAtIndex:idx]; else { [sComponent logWithFormat: @"WOBrowser got invalid index '%i'(formValue='%@' " @"for list with count %i !", idx, objCount, v]; } if ([self->item isValueSettable]) [self->item setValue:object inComponent:sComponent]; } else { [sComponent logWithFormat:@"WOBrowser got invalid index '%i' !", idx]; } if (object) [sel addObject:object]; } if ([self->singleSelection boolValueInComponent:sComponent]) { if ([sel count] > 1) { NSLog(@"WARNING(%@): " @"using singleSelection with multiple selected values", self); } [self->selection setValue:[sel lastObject] inComponent:sComponent]; } else [self->selection setValue:sel inComponent:sComponent]; [sel release]; sel = nil; } } - (void)takeValuesFromRequest:(WORequest *)_request inContext:(WOContext *)_ctx { WOComponent *sComponent; id formValue = nil; sComponent = [_ctx component]; if ([self->disabled boolValueInComponent:sComponent]) return; formValue = [_request formValuesForKey:OWFormElementName(self, _ctx)]; #if 0 [self logWithFormat:@"value=%@ ..", formValue]; #endif if ([self->value isValueSettable]) // TODO: is this correct? [self->value setValue:formValue inComponent:sComponent]; if ([formValue count] == 1) { [self _takeSingleFormValue:[formValue lastObject] fromRequest:_request inContext:_ctx]; } else if (formValue != nil) { [self _takeMultiFormValue:formValue fromRequest:_request inContext:_ctx]; } else { // nothing selected if ([self->item isValueSettable]) [self->item setValue:nil inComponent:sComponent]; if ([self->selection isValueSettable]) [self->selection setValue:nil inComponent:sComponent]; } } /* generate response */ - (void)appendOptionsToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *sComponent; BOOL isSingle; NSString *nilStr; NSArray *array; id selArray; int i, toGo; sComponent = [_ctx component]; nilStr = [self->noSelectionString stringValueInComponent:sComponent]; isSingle = [self->singleSelection boolValueInComponent:sComponent]; array = [self->list valueInComponent:sComponent]; selArray = [self->selection valueInComponent:sComponent]; toGo = [array count]; if (nilStr != nil) { WOResponse_AddCString(_response, ""); } for (i = 0; i < toGo; i++) { NSString *v, *displayV; id object; BOOL isSelected; object = [array objectAtIndex:i]; if ([self->item isValueSettable]) [self->item setValue:object inComponent:sComponent]; isSelected = NO; if (selArray != nil) { isSelected = isSingle ? [selArray isEqual:object] : [selArray containsObject:object]; } v = (self->value != nil) ? [self->value stringValueInComponent:sComponent] : (NSString *)[NSString stringWithFormat:@"%i", i]; // TODO: slow displayV = self->string ? [self->string stringValueInComponent:sComponent] : [object stringValue]; if (displayV == nil) displayV = @""; WOResponse_AddCString(_response, ""); } } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { BOOL isMultiple; unsigned s; if ([[_ctx request] isFromClientComponent]) return; isMultiple = [self->multiple boolValueInComponent:[_ctx component]]; s = [self->size unsignedIntValueInComponent:[_ctx component]]; WOResponse_AddCString(_response, ""); } /* description */ - (NSString *)associationDescription { NSMutableString *str; str = [NSMutableString stringWithCapacity:256]; [str appendString:[super associationDescription]]; if (self->list) [str appendFormat:@" list=%@", self->list]; if (self->item) [str appendFormat:@" item=%@", self->item]; if (self->selection) [str appendFormat:@" selection=%@", self->selection]; if (self->string) [str appendFormat:@" string=%@", self->string]; if (self->noSelectionString) [str appendFormat:@" noselection=%@", self->noSelectionString]; if (self->singleSelection) [str appendFormat:@" singleSelection=%@", self->singleSelection]; if (self->size) [str appendFormat:@" size=%@", self->size]; if (self->multiple) [str appendFormat:@" multiple=%@", self->multiple]; return str; } @end /* WOBrowser */