]> err.no Git - sope/blob - sope-appserver/WOExtensions/WOCheckBoxMatrix.m
b3a7dbb67e7511bad04d61bea87db48181c244cc
[sope] / sope-appserver / WOExtensions / WOCheckBoxMatrix.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 <NGObjWeb/WODynamicElement.h>
23
24 @interface WOCheckBoxMatrix : WODynamicElement
25 {
26   // WODynamicElement: extraAttributes (are appended at the main table)
27   // WODynamicElement: otherTagString
28 @protected
29   WOAssociation *list;       // array of objects to iterate through
30   WOAssociation *item;       // current item in the array
31   WOAssociation *selections; // selected objects
32   WOAssociation *maxColumns; // number of columns
33   
34   /* non WO attribute */
35   WOAssociation *index;      // current index
36   WOAssociation *col;        // current column (is updated with each iteration)
37   WOAssociation *row;        // current row    (is updated with each iteration)
38
39   WOAssociation *cellAlign;  // current cell align
40   WOAssociation *cellVAlign; // current cell valign
41   WOAssociation *rowBackgroundColor;  // current row background color;
42   WOAssociation *cellBackgroundColor; // current cell background color;
43   WOAssociation *horizontal;   // order items horizontal (default = NO)
44
45   WOElement     *template;
46 }
47 @end
48
49 #include "common.h"
50
51 @implementation WOCheckBoxMatrix
52
53 static NSString *retStrForInt(int i) {
54   switch(i) {
55   case 0:  return @"0";
56   case 1:  return @"1";
57   case 2:  return @"2";
58   case 3:  return @"3";
59   case 4:  return @"4";
60   case 5:  return @"5";
61   case 6:  return @"6";
62   case 7:  return @"7";
63   case 8:  return @"8";
64   case 9:  return @"9";
65   case 10: return @"10";
66     // TODO: find useful count!
67   default:
68     return [[NSString alloc] initWithFormat:@"%i", i];
69   }
70 }
71
72 - (id)initWithName:(NSString *)_name
73   associations:(NSDictionary *)_config
74   template:(WOElement *)_c
75 {
76   if ((self = [super initWithName:_name associations:_config template:_c])) {
77     self->list       = WOExtGetProperty(_config, @"list");
78     self->item       = WOExtGetProperty(_config, @"item");
79     self->selections = WOExtGetProperty(_config, @"selections");
80     self->maxColumns = WOExtGetProperty(_config, @"maxColumns");
81     
82     self->index      = WOExtGetProperty(_config, @"index");
83     self->col        = WOExtGetProperty(_config, @"col");
84     self->row        = WOExtGetProperty(_config, @"row");
85     self->horizontal = WOExtGetProperty(_config, @"horizontal");
86
87     self->cellAlign  = WOExtGetProperty(_config, @"cellAlign");
88     self->cellVAlign = WOExtGetProperty(_config, @"cellVAlign");
89     self->rowBackgroundColor  = 
90       WOExtGetProperty(_config, @"rowBackgroundColor");
91     self->cellBackgroundColor = 
92       WOExtGetProperty(_config, @"cellBackgroundColor");
93
94     self->template = RETAIN(_c);
95   }
96   return self;
97 }
98
99 - (void)dealloc {
100   RELEASE(self->template);
101   
102   RELEASE(self->list);
103   RELEASE(self->item);
104   RELEASE(self->maxColumns);
105   RELEASE(self->selections);
106   
107   RELEASE(self->index);
108   RELEASE(self->col);
109   RELEASE(self->row);
110   RELEASE(self->horizontal);
111
112   RELEASE(self->cellAlign);
113   RELEASE(self->cellVAlign);
114   RELEASE(self->rowBackgroundColor);
115   RELEASE(self->cellBackgroundColor);
116   [super dealloc];
117 }
118
119 /* request handling */
120
121 static inline
122 void _applyIndex(WOCheckBoxMatrix *self, WOComponent *cmp, unsigned _idx)
123 {
124   NSArray  *array;
125   BOOL     isHor;
126   unsigned r, c, cnt, cols;
127
128   isHor = [self->horizontal boolValueInComponent:cmp];
129   cols  = [self->maxColumns unsignedIntValueInComponent:cmp];
130   array = [self->list valueInComponent:cmp];
131   cnt   = [array count];
132   cols  = (cols) ? cols : 1;
133   r     = (isHor) ? (_idx / cols) + 1 : _idx % ((cnt / cols)+1) + 1;
134   c     = (isHor) ? (_idx % cols) + 1 : _idx / ((cnt / cols)+1) + 1;
135     
136   if ([self->index isValueSettable])
137     [self->index setUnsignedIntValue:_idx inComponent:cmp];
138
139   if ([self->row isValueSettable])
140     [self->row setUnsignedIntValue:r inComponent:cmp];
141
142   if ([self->col isValueSettable])
143     [self->col setUnsignedIntValue:c inComponent:cmp];
144
145   if ([self->item isValueSettable]) {
146     if (_idx < cnt)
147       [self->item setValue:[array objectAtIndex:_idx] inComponent:cmp];
148     else {
149       [cmp logWithFormat:
150            @"WOCheckBoxMatrix: array did change, index is invalid."];
151       [self->item setValue:nil inComponent:cmp];
152     }
153   }
154 }
155
156 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
157   WOComponent *cmp;
158   NSArray     *array;
159   NSArray     *selArray = nil;
160   unsigned    cnt, i;
161
162   cmp   = [_ctx component];
163   array = [self->list valueInComponent:cmp];
164   cnt   = [array count];
165
166   if (cnt) {
167     NSMutableArray *newSelection = nil;
168
169     if (self->selections)
170         newSelection = [[NSMutableArray alloc] initWithCapacity:cnt];
171   
172     [_ctx appendZeroElementIDComponent];
173     for (i = 0; i < cnt; i++) {
174       id formValue = nil;
175       id obj       = nil;
176       
177       _applyIndex(self, cmp, i);
178       [self->template takeValuesFromRequest:_req inContext:_ctx];
179
180       if ((formValue = [_req formValueForKey:[_ctx elementID]])) {
181         NSString *s;
182
183         s = retStrForInt(i);
184         if ([formValue isEqualToString:s]) {
185           if ((obj = [self->item valueInComponent:cmp]) && (newSelection))
186             [newSelection addObject:obj];
187         }
188         [s release];
189       }
190       [_ctx incrementLastElementIDComponent];
191     }
192     [_ctx deleteLastElementIDComponent];
193
194     if (self->selections) {
195       selArray = [newSelection copy];
196       [newSelection release];
197     }
198   }
199   else
200     selArray = [[NSArray alloc] init];
201
202   if ([self->selections isValueSettable])
203     [self->selections setValue:selArray inComponent:cmp];
204
205   [selArray release];
206 }
207
208 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
209   WOComponent *cmp;
210   id          result = nil;
211   unsigned    idx;
212   NSString    *s;
213
214   cmp = [_ctx component];
215   if ([self->list valueInComponent:cmp] == nil)
216     return nil;
217   
218   idx = [[_ctx currentElementID] intValue];
219   [_ctx consumeElementID]; // consume index
220   s = retStrForInt(idx);
221   [_ctx appendElementIDComponent:s];
222   [s release];
223   _applyIndex(self, cmp, idx);
224   result = [self->template invokeActionForRequest:_req inContext:_ctx];
225   [_ctx deleteLastElementIDComponent];
226   return result;
227 }
228
229 /* generating response */
230
231 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
232   WOComponent *cmp;
233   NSArray     *array;
234   NSArray     *selArray;
235   BOOL        isHor;       // is horizontal
236   unsigned    c, colCount; // column index
237   unsigned    r, rowCount; // row    index
238   unsigned    cnt;
239
240   cmp      = [_ctx component];
241   colCount = [self->maxColumns unsignedIntValueInComponent:cmp];
242   array    = [self->list valueInComponent:cmp];
243   cnt      = [array count];
244   isHor    = [self->horizontal boolValueInComponent:cmp];
245   selArray = [self->selections valueInComponent:cmp];
246
247   colCount = (colCount) ? colCount : 1;
248   rowCount = ((cnt % colCount) > 0) ? (cnt / colCount) + 1 : (cnt / colCount);
249
250   [_response appendContentString:@"<table "];
251   [self appendExtraAttributesToResponse:_response inContext:_ctx];
252   [_response appendContentCharacter:'>'];
253
254   for (r = 0; r < rowCount; r++) {
255     NSString *rowColor;
256     
257     rowColor = [self->rowBackgroundColor stringValueInComponent:cmp];
258     [_response appendContentString:@"<tr"];
259     if (rowColor) {
260       [_response appendContentString:@" bgcolor=\""];
261       [_response appendContentString:rowColor];
262       [_response appendContentCharacter:'"'];
263     }
264     [_response appendContentCharacter:'>'];
265     
266     for (c = 0; c < colCount; c++) {
267       NSString *cColor, *align, *valign;
268       unsigned i;
269       
270       cColor = [self->cellBackgroundColor stringValueInComponent:cmp];
271       align  = [self->cellAlign  stringValueInComponent:cmp];
272       valign = [self->cellVAlign stringValueInComponent:cmp];
273       i = (isHor) ? (r * colCount + c) : (c * rowCount + r);
274       
275       [_response appendContentString:@"<td"];
276       if (cColor) {
277         [_response appendContentString:@" bgcolor=\""];
278         [_response appendContentString:cColor];
279         [_response appendContentCharacter:'"'];
280       }
281       if (align) {
282         [_response appendContentString:@" align=\""];
283         [_response appendContentString:align];
284         [_response appendContentCharacter:'"'];
285       }
286       if (valign) {
287         [_response appendContentString:@" valign=\""];
288         [_response appendContentString:valign];
289         [_response appendContentCharacter:'"'];
290       }
291       [_response appendContentCharacter:'>'];
292       
293       if (i < cnt) {
294         NSString *s;
295         id obj;
296         
297         s = retStrForInt(i);
298         [_ctx appendElementIDComponent:s];
299         [s release];
300         _applyIndex(self, cmp, i);
301         obj = [self->item valueInComponent:cmp];
302
303         // append check box
304         [_response appendContentString:@"<input type=\"checkbox\" name=\""];
305         [_response appendContentHTMLAttributeValue:[_ctx elementID]];
306         [_response appendContentString:@"\" value=\""];
307         s = retStrForInt(i);
308         [_response appendContentString:s];
309         [s release];
310         [_response appendContentCharacter:'"'];
311         
312         // TODO: need a ctx flag for empty attributes
313         if ([selArray containsObject:obj])
314          [_response appendContentString:@" checked=\"checked\""];
315         
316         [_response appendContentString:
317                      (_ctx->wcFlags.xmlStyleEmptyElements ? @" />" : @">")];
318         
319         /* append template */
320         [self->template appendToResponse:_response inContext:_ctx];
321         [_ctx deleteLastElementIDComponent];
322       }
323       else
324         [_response appendContentString:@"&nbsp;"]; // TODO: XML/XHTML?
325       [_response appendContentString:@"</td>"];
326     }
327     [_response appendContentString:@"</tr>"];
328   }
329   [_response appendContentString:@"</table>"];
330 }
331
332 /* description */
333
334 - (NSString *)associationDescription {
335   NSMutableString *str;
336
337   str = [NSMutableString stringWithCapacity:128];
338   if (self->list)       [str appendFormat:@" list=%@",       self->list];
339   if (self->item)       [str appendFormat:@" item=%@",       self->item];
340   if (self->maxColumns) [str appendFormat:@" maxColumns=%@", self->maxColumns];
341   if (self->selections) [str appendFormat:@" selections=%@", self->selections];
342   if (self->index)      [str appendFormat:@" index=%@",      self->index];
343   if (self->col)        [str appendFormat:@" col=%@",        self->col];
344   if (self->row)        [str appendFormat:@" row=%@",        self->row];
345   if (self->horizontal) [str appendFormat:@" horizontal=%@", self->horizontal];
346   if (self->template)   [str appendFormat:@" template=%@",   self->template];
347
348   return str;
349 }
350
351 @end /* WOCheckBoxMatrix */