]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOBrowser.m
fixed bundle resource lookup on MacOSX, changed resource lookup in
[sope] / sope-appserver / NGObjWeb / DynamicElements / WOBrowser.m
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 "common.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 + (int)version {
54   return [super version] + 0 /* v2 */;
55 }
56
57 + (void)initialize {
58   NSAssert2([super version] == 2,
59             @"invalid superclass (%@) version %i !",
60             NSStringFromClass([self superclass]), [super version]);
61 }
62
63 - (id)initWithName:(NSString *)_name
64   associations:(NSDictionary *)_config
65   template:(WOElement *)_c {
66
67   if ((self = [super initWithName:_name associations:_config template:_c])) {
68     self->list              = OWGetProperty(_config, @"list");
69     self->item              = OWGetProperty(_config, @"item");
70     self->singleSelection   = OWGetProperty(_config, @"singleSelection");
71     self->multiple          = OWGetProperty(_config, @"multiple");
72     self->size              = OWGetProperty(_config, @"size");
73     self->noSelectionString = OWGetProperty(_config, @"noSelectionString");
74     
75     if ((self->string = OWGetProperty(_config, @"displayString")) == nil) {
76       if ((self->string = OWGetProperty(_config, @"string")) != nil) {
77         [self debugWithFormat:
78                 @"Note: using deprecated 'string' binding, "
79                 @"use 'displayString' instead."];
80       }
81     }
82     else if (OWGetProperty(_config, @"string") != nil) {
83       [self debugWithFormat:@"WARNING: 'displayString' AND 'string' bindings "
84               @"are set, use only one! ('string' is deprecated!)"];
85     }
86     
87     if ((self->selection = OWGetProperty(_config, @"selections")) == nil) {
88       if ((self->selection = OWGetProperty(_config, @"selection")) != nil) {
89         [self debugWithFormat:
90                 @"Note: using deprecated 'selection' binding, "
91                 @"use 'selections' instead."];
92       }
93     }
94     else if (OWGetProperty(_config, @"selection") != nil) {
95       [self debugWithFormat:@"WARNING: 'selections' AND 'selection' bindings "
96               @"are set, use only one! ('selection' is deprecated!)"];
97     }
98     
99     // compatiblity
100     if (self->noSelectionString == nil)
101       self->noSelectionString = OWGetProperty(_config, @"nilString");
102     
103     if (self->multiple == nil) {
104       self->multiple =
105         [WOAssociation associationWithValue:[NSNumber numberWithBool:YES]];
106       self->multiple = [self->multiple retain];
107     }
108   }
109   return self;
110 }
111
112 - (void)dealloc {
113   [self->noSelectionString release];
114   [self->singleSelection   release];
115   [self->list      release];
116   [self->item      release];
117   [self->selection release];
118   [self->string    release];
119   [self->size      release];
120   [self->multiple  release];
121   [super dealloc];
122 }
123
124 /* handling request */
125
126 - (void)_takeSingleFormValue:(id)formValue fromRequest:(WORequest *)_request
127   inContext:(WOContext *)_ctx
128 {
129   WOComponent *sComponent;
130   NSArray *objects;
131   id      object;
132       
133   sComponent = [_ctx component];
134   objects = [self->list valueInComponent:sComponent];
135       
136   if ([[formValue stringValue] isEqualToString:@"$"])
137     object = nil; // nil item selected
138   else {
139     int idx;
140       
141     object = nil;
142     if ((idx = [formValue intValue]) >= 0) {
143       if (idx < (int)[objects count])
144         object = [objects objectAtIndex:idx];
145       else {
146         [sComponent logWithFormat:
147                       @"WOBrowser got invalid index '%i' (formvalue='%@') "
148                     @"for list with count %i !",
149                     idx, formValue, [objects count]];
150       }
151     }
152     else
153       [sComponent logWithFormat:@"WOBrowser got invalid index '%i' !", idx];
154   }
155     
156   if ([self->selection isValueSettable]) {
157     NSArray *sel;
158         
159     if ([self->item isValueSettable])
160       [self->item setValue:object inComponent:sComponent];
161
162     if (object) {
163       sel = [self->singleSelection boolValueInComponent:sComponent]
164         ? [object retain]
165         : [[NSArray alloc] initWithObjects:object,nil];
166     }
167     else // nil item selected
168       sel = nil;
169           
170     [self->selection setValue:sel inComponent:sComponent];
171     [sel release]; sel = nil;
172   }
173 }
174
175 - (void)_takeMultiFormValue:(NSArray *)formValue fromRequest:(WORequest *)_rq
176   inContext:(WOContext *)_ctx
177 {
178   WOComponent *sComponent;
179   NSEnumerator   *values;
180   NSString       *v;
181   NSArray        *objects;
182   id             object;
183   
184   values     = [formValue objectEnumerator];
185   sComponent = [_ctx component];
186   objects    = [self->list valueInComponent:sComponent];
187     
188   if ([self->selection isValueSettable]) {
189     NSMutableArray *sel;
190     unsigned objCount;
191       
192     sel      = [[NSMutableArray alloc] initWithCapacity:[formValue count]];
193     objCount = [objects count];
194       
195     while ((v = [values nextObject])) {
196         int idx;
197
198         object = nil;
199         if ((idx = [v intValue]) >= 0) {
200           if (idx < (int)objCount)
201             object = [objects objectAtIndex:idx];
202           else {
203             [sComponent logWithFormat:
204                           @"WOBrowser got invalid index '%i'(formValue='%@' "
205                           @"for list with count %i !",
206                           idx, objCount, v];
207           }
208           
209           if ([self->item isValueSettable])
210             [self->item setValue:object inComponent:sComponent];
211         }
212         else {
213           [sComponent logWithFormat:@"WOBrowser got invalid index '%i' !",
214                         idx];
215         }
216         
217         if (object) [sel addObject:object];
218     }
219
220     if ([self->singleSelection boolValueInComponent:sComponent]) {
221         if ([sel count] > 1) {
222           NSLog(@"WARNING(%@): "
223                 @"using singleSelection with multiple selected values",
224                 self);
225         }
226         [self->selection setValue:[sel lastObject] inComponent:sComponent];
227     }
228     else
229       [self->selection setValue:sel inComponent:sComponent];
230     [sel release]; sel = nil;
231   }
232 }
233
234 - (void)takeValuesFromRequest:(WORequest *)_request
235   inContext:(WOContext *)_ctx
236 {
237   WOComponent *sComponent;
238   id formValue = nil;
239   
240   sComponent = [_ctx component];
241   if ([self->disabled boolValueInComponent:sComponent])
242       return;
243   
244   formValue = [_request formValuesForKey:OWFormElementName(self, _ctx)];
245 #if 0
246   [self logWithFormat:@"value=%@ ..", formValue];
247 #endif
248   
249   if ([self->value isValueSettable])
250     // TODO: is this correct?
251     [self->value setValue:formValue inComponent:sComponent];
252   
253   if ([formValue count] == 1) {
254     [self _takeSingleFormValue:[formValue lastObject] fromRequest:_request
255           inContext:_ctx];
256   }
257   else if (formValue != nil) {
258     [self _takeMultiFormValue:formValue fromRequest:_request
259           inContext:_ctx];
260   }
261   else {
262     // nothing selected
263     if ([self->item isValueSettable])
264       [self->item setValue:nil inComponent:sComponent];
265     if ([self->selection isValueSettable])
266       [self->selection setValue:nil inComponent:sComponent];
267   }
268 }
269
270 - (void)appendOptionsToResponse:(WOResponse *)_response
271   inContext:(WOContext *)_ctx
272 {
273   WOComponent *sComponent = [_ctx component];
274   BOOL     isSingle = NO;
275   NSString *nilStr  = nil;
276   NSArray  *array   = nil;
277   id       selArray = nil;
278   int      i, toGo;
279     
280
281   nilStr   = [self->noSelectionString stringValueInComponent:sComponent];
282   isSingle = [self->singleSelection boolValueInComponent:sComponent];
283   array    = [self->list            valueInComponent:sComponent];
284   selArray = [self->selection       valueInComponent:sComponent];
285   toGo     = [array count];
286
287   if (nilStr) {
288     WOResponse_AddCString(_response, "<option value=\"$\">");
289     WOResponse_AddHtmlString(_response, nilStr);
290     WOResponse_AddCString(_response, "</option>");
291   }
292     
293   for (i = 0; i < toGo; i++) {
294     NSString *v         = nil;
295     NSString *displayV  = nil;
296     id       object     = [array objectAtIndex:i];
297     BOOL     isSelected;
298
299     if ([self->item isValueSettable])
300       [self->item setValue:object inComponent:sComponent];
301
302     isSelected = NO;
303     if (selArray) {
304       isSelected = isSingle 
305         ? [selArray isEqual:object] : [selArray containsObject:object];
306     }
307     
308     v = self->value
309       ? [self->value stringValueInComponent:sComponent]
310       : [NSString stringWithFormat:@"%i", i];
311
312     displayV = self->string
313       ? [self->string stringValueInComponent:sComponent]
314       : [object stringValue];
315     
316     if (displayV == nil) displayV = @"";
317     
318     WOResponse_AddCString(_response, "<option value=\"");
319     WOResponse_AddString(_response, v);
320     WOResponse_AddString(_response,
321                          isSelected ? @"\" selected=\"selected\">" : @"\">");
322     WOResponse_AddHtmlString(_response, displayV);
323     WOResponse_AddCString(_response, "</option>");
324   }
325 }
326
327 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
328   BOOL     isMultiple;
329   unsigned s;
330   
331   if ([[_ctx request] isFromClientComponent])
332     return;
333
334   isMultiple = [self->multiple boolValueInComponent:[_ctx component]];
335   s          = [self->size unsignedIntValueInComponent:[_ctx component]];
336     
337   WOResponse_AddCString(_response, "<select name=\"");
338   [_response appendContentHTMLAttributeValue:OWFormElementName(self, _ctx)];
339   if (self->otherTagString) {
340     WOResponse_AddChar(_response, ' ');
341     WOResponse_AddString(_response,
342                          [self->otherTagString stringValueInComponent:
343                            [_ctx component]]);
344   }
345   WOResponse_AddCString(_response, "\"");
346       
347   if (s > 0) {
348     WOResponse_AddCString(_response, " size=\"");
349     WOResponse_AddUInt(_response, s);
350     [_response appendContentCharacter:'"'];
351   }
352       
353   if (isMultiple)
354     WOResponse_AddCString(_response, " multiple=\"multiple\"");
355     
356   [self appendExtraAttributesToResponse:_response inContext:_ctx];
357   WOResponse_AddCString(_response, ">\n");
358   
359   [self appendOptionsToResponse:_response inContext:_ctx];
360   
361   WOResponse_AddCString(_response, "</select>");
362 }
363
364 /* description */
365
366 - (NSString *)associationDescription {
367   NSMutableString *str;
368   
369   str = [NSMutableString stringWithCapacity:256];
370   [str appendString:[super associationDescription]];
371   
372   if (self->list)      [str appendFormat:@" list=%@",      self->list];
373   if (self->item)      [str appendFormat:@" item=%@",      self->item];
374   if (self->selection) [str appendFormat:@" selection=%@", self->selection];
375   if (self->string)    [str appendFormat:@" string=%@",    self->string];
376   if (self->noSelectionString)
377     [str appendFormat:@" noselection=%@", self->noSelectionString];
378   if (self->singleSelection)
379     [str appendFormat:@" singleSelection=%@", self->singleSelection];
380
381   if (self->size)     [str appendFormat:@" size=%@",     self->size];
382   if (self->multiple) [str appendFormat:@" multiple=%@", self->multiple];
383
384   return str;
385 }
386
387 @end /* WOBrowser */