1/* 2 Copyright (C) 2000-2005 SKYRIX Software AG 3 4 This file is part of SOPE. 5 6 SOPE is free software; you can redistribute it and/or modify it under 7 the terms of the GNU Lesser General Public License as published by the 8 Free Software Foundation; either version 2, or (at your option) any 9 later version. 10 11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 14 License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with SOPE; see the file COPYING. If not, write to the 18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19 02111-1307, USA. 20*/ 21 22#include "WOInput.h" 23#include "decommon.h" 24 25@interface WOBrowser : WOInput 26{ 27 // WODynamicElement: extraAttributes 28 // WODynamicElement: otherTagString 29 // inherited: name 30 // inherited: value 31 // inherited: disabled 32@protected 33 WOAssociation *list; 34 WOAssociation *item; 35 WOAssociation *selection; // => use 'selections'! 36 WOAssociation *string; // WO4 => use 'displayString'! 37 WOAssociation *noSelectionString; // WO4 38 39 // non-WO: 40 WOAssociation *singleSelection; // selection contains an item, not an array 41 42 // WO 4.5 43 WOAssociation *multiple; // multiple selections allowed 44 WOAssociation *size; 45 46 // TODO: WO 4.5: selectedValues, escapeHTML 47} 48 49@end /* WOBrowser */ 50 51@implementation WOBrowser 52 53- (id)initWithName:(NSString *)_name 54 associations:(NSDictionary *)_config 55 template:(WOElement *)_c 56{ 57 if ((self = [super initWithName:_name associations:_config template:_c])) { 58 self->list = OWGetProperty(_config, @"list"); 59 self->item = OWGetProperty(_config, @"item"); 60 self->singleSelection = OWGetProperty(_config, @"singleSelection"); 61 self->multiple = OWGetProperty(_config, @"multiple"); 62 self->size = OWGetProperty(_config, @"size"); 63 self->noSelectionString = OWGetProperty(_config, @"noSelectionString"); 64 65 if ((self->string = OWGetProperty(_config, @"displayString")) == nil) { 66 if ((self->string = OWGetProperty(_config, @"string")) != nil) { 67 [self debugWithFormat: 68 @"Note: using deprecated 'string' binding, " 69 @"use 'displayString' instead."]; 70 } 71 } 72 else if (OWGetProperty(_config, @"string") != nil) { 73 [self debugWithFormat:@"WARNING: 'displayString' AND 'string' bindings " 74 @"are set, use only one! ('string' is deprecated!)"]; 75 } 76 77 if ((self->selection = OWGetProperty(_config, @"selections")) == nil) { 78 if ((self->selection = OWGetProperty(_config, @"selection")) != nil) { 79 [self debugWithFormat: 80 @"Note: using deprecated 'selection' binding, " 81 @"use 'selections' instead."]; 82 } 83 } 84 else if (OWGetProperty(_config, @"selection") != nil) { 85 [self debugWithFormat:@"WARNING: 'selections' AND 'selection' bindings " 86 @"are set, use only one! ('selection' is deprecated!)"]; 87 } 88 89 // compatiblity 90 if (self->noSelectionString == nil) 91 self->noSelectionString = OWGetProperty(_config, @"nilString"); 92 93 if (self->multiple == nil) { 94 self->multiple = 95 [WOAssociation associationWithValue:[NSNumber numberWithBool:YES]]; 96 self->multiple = [self->multiple retain]; 97 } 98 } 99 return self; 100} 101 102- (void)dealloc { 103 [self->noSelectionString release]; 104 [self->singleSelection release]; 105 [self->list release]; 106 [self->item release]; 107 [self->selection release]; 108 [self->string release]; 109 [self->size release]; 110 [self->multiple release]; 111 [super dealloc]; 112} 113 114/* handling request */ 115 116- (void)_takeSingleFormValue:(id)formValue fromRequest:(WORequest *)_request 117 inContext:(WOContext *)_ctx 118{ 119 WOComponent *sComponent; 120 NSArray *objects; 121 id object; 122 123 sComponent = [_ctx component]; 124 objects = [self->list valueInComponent:sComponent]; 125 126 if ([[formValue stringValue] isEqualToString:@"$"]) 127 object = nil; // nil item selected 128 else { 129 int idx; 130 131 object = nil; 132 if ((idx = [formValue intValue]) >= 0) { 133 if (idx < (int)[objects count]) 134 object = [objects objectAtIndex:idx]; 135 else { 136 [sComponent logWithFormat: 137 @"WOBrowser got invalid index '%i' (formvalue='%@') " 138 @"for list with count %i !", 139 idx, formValue, [objects count]]; 140 } 141 } 142 else 143 [sComponent logWithFormat:@"WOBrowser got invalid index '%i' !", idx]; 144 } 145 146 if ([self->selection isValueSettable]) { 147 NSArray *sel; 148 149 if ([self->item isValueSettable]) 150 [self->item setValue:object inComponent:sComponent]; 151 152 if (object) { 153 sel = [self->singleSelection boolValueInComponent:sComponent] 154 ? [object retain] 155 : [[NSArray alloc] initWithObjects:object,nil]; 156 } 157 else // nil item selected 158 sel = nil; 159 160 [self->selection setValue:sel inComponent:sComponent]; 161 [sel release]; sel = nil; 162 } 163} 164 165- (void)_takeMultiFormValue:(NSArray *)formValue fromRequest:(WORequest *)_rq 166 inContext:(WOContext *)_ctx 167{ 168 WOComponent *sComponent; 169 NSEnumerator *values; 170 NSString *v; 171 NSArray *objects; 172 id object; 173 174 values = [formValue objectEnumerator]; 175 sComponent = [_ctx component]; 176 objects = [self->list valueInComponent:sComponent]; 177 178 if ([self->selection isValueSettable]) { 179 NSMutableArray *sel; 180 unsigned objCount; 181 182 sel = [[NSMutableArray alloc] initWithCapacity:[formValue count]]; 183 objCount = [objects count]; 184 185 while ((v = [values nextObject])) { 186 int idx; 187 188 object = nil; 189 if ((idx = [v intValue]) >= 0) { 190 if (idx < (int)objCount) 191 object = [objects objectAtIndex:idx]; 192 else { 193 [sComponent logWithFormat: 194 @"WOBrowser got invalid index '%i'(formValue='%@' " 195 @"for list with count %i !", 196 idx, objCount, v]; 197 } 198 199 if ([self->item isValueSettable]) 200 [self->item setValue:object inComponent:sComponent]; 201 } 202 else { 203 [sComponent logWithFormat:@"WOBrowser got invalid index '%i' !", 204 idx]; 205 } 206 207 if (object) [sel addObject:object]; 208 } 209 210 if ([self->singleSelection boolValueInComponent:sComponent]) { 211#if 0 212 if ([sel count] > 1) { 213 NSLog(@"WARNING(%@): " 214 @"using singleSelection with multiple selected values", 215 self); 216 } 217#endif 218 [self->selection setValue:[sel lastObject] inComponent:sComponent]; 219 } 220 else 221 [self->selection setValue:sel inComponent:sComponent]; 222 [sel release]; sel = nil; 223 } 224} 225 226- (void)takeValuesFromRequest:(WORequest *)_request 227 inContext:(WOContext *)_ctx 228{ 229 WOComponent *sComponent; 230 id formValue = nil; 231 232 sComponent = [_ctx component]; 233 if ([self->disabled boolValueInComponent:sComponent]) 234 return; 235 236 formValue = [_request formValuesForKey:OWFormElementName(self, _ctx)]; 237#if 0 238 [self logWithFormat:@"value=%@ ..", formValue]; 239#endif 240 241 if ([self->value isValueSettable]) 242 // TODO: is this correct? 243 [self->value setValue:formValue inComponent:sComponent]; 244 245 if ([formValue count] == 1) { 246 [self _takeSingleFormValue:[formValue lastObject] fromRequest:_request 247 inContext:_ctx]; 248 } 249 else if (formValue != nil) { 250 [self _takeMultiFormValue:formValue fromRequest:_request 251 inContext:_ctx]; 252 } 253 else { 254 // nothing selected 255 if ([self->item isValueSettable]) 256 [self->item setValue:nil inComponent:sComponent]; 257 if ([self->selection isValueSettable]) 258 [self->selection setValue:nil inComponent:sComponent]; 259 } 260} 261 262/* generate response */ 263 264- (void)appendOptionsToResponse:(WOResponse *)_response 265 inContext:(WOContext *)_ctx 266{ 267 WOComponent *sComponent; 268 BOOL isSingle; 269 NSString *nilStr; 270 NSArray *array; 271 id selArray; 272 int i, toGo; 273 274 sComponent = [_ctx component]; 275 276 nilStr = [self->noSelectionString stringValueInComponent:sComponent]; 277 isSingle = [self->singleSelection boolValueInComponent:sComponent]; 278 array = [self->list valueInComponent:sComponent]; 279 selArray = [self->selection valueInComponent:sComponent]; 280 toGo = [array count]; 281 282 if (nilStr != nil) { 283 WOResponse_AddCString(_response, "<option value=\"$\">"); 284 WOResponse_AddHtmlString(_response, nilStr); 285 WOResponse_AddCString(_response, "</option>"); 286 } 287 288 for (i = 0; i < toGo; i++) { 289 NSString *v, *displayV; 290 id object; 291 BOOL isSelected; 292 293 object = [array objectAtIndex:i]; 294 295 if ([self->item isValueSettable]) 296 [self->item setValue:object inComponent:sComponent]; 297 298 isSelected = NO; 299 if (selArray != nil) { 300 isSelected = isSingle 301 ? [selArray isEqual:object] : [selArray containsObject:object]; 302 } 303 304 v = (self->value != nil) 305 ? [self->value stringValueInComponent:sComponent] 306 : (NSString *)[NSString stringWithFormat:@"%i", i]; // TODO: slow 307 308 displayV = self->string 309 ? [self->string stringValueInComponent:sComponent] 310 : [object stringValue]; 311 312 if (displayV == nil) displayV = @""; 313 314 WOResponse_AddCString(_response, "<option value=\""); 315 WOResponse_AddString(_response, v); 316 if (isSelected) { 317 WOResponse_AddString(_response, _ctx->wcFlags.allowEmptyAttributes 318 ? @"\" selected>" : @"\" selected=\"selected\">"); 319 } 320 else { 321 WOResponse_AddString(_response, @"\">"); 322 } 323 WOResponse_AddHtmlString(_response, displayV); 324 WOResponse_AddCString(_response, "</option>"); 325 } 326} 327 328- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { 329 BOOL isMultiple; 330 unsigned s; 331 332 if ([[_ctx request] isFromClientComponent]) 333 return; 334 335 isMultiple = [self->multiple boolValueInComponent:[_ctx component]]; 336 s = [self->size unsignedIntValueInComponent:[_ctx component]]; 337 338 WOResponse_AddCString(_response, "<select name=\""); 339 [_response appendContentHTMLAttributeValue:OWFormElementName(self, _ctx)]; 340 if (self->otherTagString) { 341 WOResponse_AddChar(_response, ' '); 342 WOResponse_AddString(_response, 343 [self->otherTagString stringValueInComponent: 344 [_ctx component]]); 345 } 346 WOResponse_AddCString(_response, "\""); 347 348 if (s > 0) { 349 WOResponse_AddCString(_response, " size=\""); 350 WOResponse_AddUInt(_response, s); 351 [_response appendContentCharacter:'"']; 352 } 353 354 if ([self->disabled boolValueInComponent:[_ctx component]]) 355 WOResponse_AddCString(_response, " disabled=\"disabled\""); 356 357 if (isMultiple) 358 WOResponse_AddCString(_response, " multiple=\"multiple\""); 359 360 [self appendExtraAttributesToResponse:_response inContext:_ctx]; 361 WOResponse_AddCString(_response, ">\n"); 362 363 [self appendOptionsToResponse:_response inContext:_ctx]; 364 365 WOResponse_AddCString(_response, "</select>"); 366} 367 368/* description */ 369 370- (NSString *)associationDescription { 371 NSMutableString *str; 372 373 str = [NSMutableString stringWithCapacity:256]; 374 [str appendString:[super associationDescription]]; 375 376 if (self->list) [str appendFormat:@" list=%@", self->list]; 377 if (self->item) [str appendFormat:@" item=%@", self->item]; 378 if (self->selection) [str appendFormat:@" selection=%@", self->selection]; 379 if (self->string) [str appendFormat:@" string=%@", self->string]; 380 if (self->noSelectionString) 381 [str appendFormat:@" noselection=%@", self->noSelectionString]; 382 if (self->singleSelection) 383 [str appendFormat:@" singleSelection=%@", self->singleSelection]; 384 385 if (self->size) [str appendFormat:@" size=%@", self->size]; 386 if (self->multiple) [str appendFormat:@" multiple=%@", self->multiple]; 387 388 return str; 389} 390 391@end /* WOBrowser */ 392