]> err.no Git - sope/blob - sope-appserver/WEExtensions/WETabItem.m
fix for SoProductResourceManager.m
[sope] / sope-appserver / WEExtensions / WETabItem.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo 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   OGo 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 OGo; 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 // $Id$
22
23 #include "WETabView.h"
24 #include "common.h"
25
26 #if DEBUG
27 #  define DEBUG_JS 1
28 #endif
29
30 /* context keys */
31 extern NSString *WETabView_HEAD;
32 extern NSString *WETabView_BODY;
33 extern NSString *WETabView_KEYS;
34 extern NSString *WETabView_SCRIPT;
35 extern NSString *WETabView_ACTIVEKEY;
36 extern NSString *WETabView_COLLECT;
37
38 @implementation WETabItem
39
40 static Class StrClass = Nil;
41
42 + (int)version {
43   return [super version] + 0;
44 }
45 + (void)initialize {
46   StrClass = [NSString class];
47 }
48
49 static NSString *retStrForInt(int i) {
50   switch(i) {
51   case 0:  return @"0";
52   case 1:  return @"1";
53   case 2:  return @"2";
54   case 3:  return @"3";
55   case 4:  return @"4";
56   case 5:  return @"5";
57   case 6:  return @"6";
58   case 7:  return @"7";
59   case 8:  return @"8";
60   case 9:  return @"9";
61   case 10: return @"10";
62     // TODO: find useful count!
63   default:
64     return [[StrClass alloc] initWithFormat:@"%i", i];
65   }
66 }
67
68 - (id)initWithName:(NSString *)_name
69   associations:(NSDictionary *)_config
70   template:(WOElement *)_subs
71 {
72   if ((self = [super initWithName:_name associations:_config template:_subs])) {
73     self->key      = WOExtGetProperty(_config, @"key");
74     self->icon     = WOExtGetProperty(_config, @"icon");
75     self->label    = WOExtGetProperty(_config, @"label");
76     self->action   = WOExtGetProperty(_config, @"action");
77     self->isScript = WOExtGetProperty(_config, @"isScript");
78
79     self->tabIcon         = WOExtGetProperty(_config, @"tabIcon");
80     self->leftTabIcon     = WOExtGetProperty(_config, @"leftTabIcon");
81     self->selectedTabIcon = WOExtGetProperty(_config, @"selectedTabIcon");
82     
83     self->asBackground    = WOExtGetProperty(_config, @"asBackground");
84     self->width           = WOExtGetProperty(_config, @"width");
85     self->height          = WOExtGetProperty(_config, @"height");
86     self->activeBgColor   = WOExtGetProperty(_config, @"activeBgColor");
87     self->inactiveBgColor = WOExtGetProperty(_config, @"inactiveBgColor");
88     
89     self->template = [_subs retain];
90   }
91   return self;
92 }
93
94 - (void)dealloc {
95   [self->action   release];
96   [self->label    release];
97   [self->icon     release];
98   [self->key      release];
99   [self->isScript release];
100   [self->template release];
101
102   [self->leftTabIcon     release];
103   [self->selectedTabIcon release];
104   [self->tabIcon         release];
105
106   [self->asBackground release];
107   [self->width        release];
108   [self->height       release];
109
110   [self->activeBgColor   release];
111   [self->inactiveBgColor release];
112   
113   [super dealloc];
114 }
115
116 /* responder */
117
118 - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
119   NSString *activeTabKey;
120   NSString *myTabKey;
121   BOOL     doCheck;
122   
123   if ([_ctx objectForKey:WETabView_HEAD]) {
124     /* head clicks */
125     [[_ctx component] debugWithFormat:
126                         @"WETabItem: head takes (no) values, eid='%@'",
127                         [_ctx elementID]];
128     return;
129   }
130
131   if ((activeTabKey = [_ctx objectForKey:WETabView_BODY]) == nil) {
132     [[_ctx component] debugWithFormat:@"WETabItem: invalid state"];
133     [self->template takeValuesFromRequest:_rq inContext:_ctx];
134     return;
135   }
136   
137   myTabKey = [self->key      stringValueInComponent:[_ctx component]];
138   doCheck  = [self->isScript boolValueInComponent:[_ctx component]];
139     
140   if ([activeTabKey isEqualToString:myTabKey] || doCheck) {
141 #if ADD_OWN_ELEMENTIDS
142     [_ctx appendElementIDComponent:activeTabKey];
143 #endif
144       
145 #if DEBUG_TAKEVALUES
146     [[_ctx component] debugWithFormat:
147                           @"WETabItem: body takes values, eid='%@'",
148                           [_ctx elementID]];
149 #endif
150       
151     [self->template takeValuesFromRequest:_rq inContext:_ctx];
152 #if ADD_OWN_ELEMENTIDS
153     [_ctx deleteLastElementIDComponent];
154 #endif
155   }
156 #if DEBUG_TAKEVALUES
157   else {
158       [[_ctx component] debugWithFormat:
159                           @"WETabItem: body takes no values, eid='%@'",
160                           [_ctx elementID]];
161   }
162 #endif
163 }
164
165 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
166   id            result;
167   WOAssociation *tmp;
168   NSString      *activeTabKey;
169   
170   if ((tmp = [_ctx objectForKey:WETabView_HEAD])) {
171     /* click on tab icon */
172     NSString      *tabkey;
173     
174     tabkey = [_ctx currentElementID];
175     [_ctx consumeElementID];
176     [_ctx appendElementIDComponent:tabkey];
177     
178     if ([tmp isValueSettable])
179       [tmp setValue:tabkey inComponent:[_ctx component]];
180     
181     result = [self->action valueInComponent:[_ctx component]];
182
183     [_ctx deleteLastElementIDComponent];
184   }
185   else if ((activeTabKey = [_ctx objectForKey:WETabView_BODY])) {
186     /* clicked somewhere in the (active) body */
187     result = [self->template invokeActionForRequest:_req inContext:_ctx];
188   }
189   else {
190     [[_ctx component] logWithFormat:@"WETabItem: invalid invoke state"];
191     result = [self->template invokeActionForRequest:_req inContext:_ctx];
192   }
193   
194   return result;
195 }
196
197 /* info collection */
198
199 - (void)_collectInContext:(WOContext *)_ctx key:(NSString *)k {
200   BOOL  isLeft = NO;
201   NSMutableArray *keys;
202   WETabItemInfo  *info;
203   WOComponent    *cmp;
204       
205   cmp  = [_ctx component];
206   keys = [_ctx objectForKey:WETabView_KEYS];
207   if (keys == nil) {
208     keys = [[[NSMutableArray alloc] init] autorelease];
209     [_ctx setObject:keys forKey:WETabView_KEYS];
210     isLeft = YES;
211   }
212       
213   if (k == nil) {
214     /* auto-assign a key */
215     k = retStrForInt([keys count]);
216   }
217   else
218     k = [k retain];
219   [_ctx appendElementIDComponent:k];
220   
221   info = [[WETabItemInfo alloc] init];
222   info->key      = [k copy];
223   info->label    = [[self->label stringValueInComponent:cmp] copy];
224   info->icon     = [[self->icon  stringValueInComponent:cmp] copy];
225   info->uri      = [[_ctx componentActionURL] copy];
226   info->isScript = [self->isScript boolValueInComponent:cmp];
227   info->tabIcon  = [[self->tabIcon stringValueInComponent:cmp] copy];
228   info->leftIcon = [[self->leftTabIcon stringValueInComponent:cmp] copy];
229   info->selIcon  = [[self->selectedTabIcon stringValueInComponent:cmp]
230                                            copy];
231   if (self->asBackground == nil)
232     info->asBackground = 0;
233   else {
234     info->asBackground
235       = ([self->asBackground boolValueInComponent:cmp]) ? 1 : -1;
236   }
237   info->width        = [[self->width  stringValueInComponent:cmp] copy];
238   info->height       = [[self->height stringValueInComponent:cmp] copy];
239   info->activeBg     = [[self->activeBgColor stringValueInComponent:cmp]
240                                              copy];
241   info->inactiveBg   = [[self->inactiveBgColor stringValueInComponent:cmp]
242                                                copy];
243       
244   if (info->leftIcon == nil) info->leftIcon = [info->tabIcon copy];
245       
246   [keys addObject:info];
247   [info release];
248   [k release];
249       
250   [_ctx deleteLastElementIDComponent];
251 }
252
253 /* header generation */
254
255 - (void)_appendHeadToResponse:(WOResponse *)_response
256   inContext:(WOContext *)_ctx
257   activeKey:(NSString *)activeKey
258   key:(NSString *)k
259 {
260   /* head is currently generated in WETabView */
261 #if 0
262   // note: some associations can be inherited by WETabView !
263   BOOL        doImages;
264   WOComponent *comp;
265   BOOL        doBgIcon;
266   NSString    *label;
267   NSString    *w, *h;
268   
269   doImages = ![[[_ctx request] clientCapabilities] isTextModeBrowser];
270   comp     = [_ctx component];
271   
272   doBgIcon = self->asBackground && doImages
273     ? [self->asBackground boolValueInComponent:comp] ? YES : NO
274     : NO;
275   
276   if ((label = [self->label stringValueInComponent:comp]) == nil)
277     label = k;
278
279   if (doImages) {
280     /* lookup image */
281     NSString *imgName = nil;
282     // ...
283     
284     imgUri = WEUriOfResource(imgName, _ctx);
285     if ([imgUri length] < 1)
286       doImages = NO;
287   }
288   
289   // .... _isActive
290 #endif
291 }
292
293 /* body generation */
294
295 - (void)_appendBodyToResponse:(WOResponse *)_response
296   inContext:(WOContext *)_ctx
297   activeKey:(NSString *)tmp
298   key:(NSString *)k
299 {
300   BOOL doScript;
301   BOOL isScript_;
302   BOOL isActive;
303
304   doScript  = [[_ctx objectForKey:WETabView_SCRIPT] boolValue];
305   isScript_ = [self->isScript boolValueInComponent:[_ctx component]];
306   isActive  = [tmp isEqualToString:k];
307     
308   if (doScript && (isActive || isScript_)) {
309     [_response appendContentString:@"<div id=\""];
310     [_response appendContentString:k];
311     [_response appendContentString:@"TabLayer\" style=\"display: none;\">\n"];
312   }
313   
314   if (isActive || (doScript && isScript_)) {
315     /* content is active or used as layer*/
316 #if ADD_OWN_ELEMENTIDS
317     [_ctx appendElementIDComponent:k];
318 #endif
319 #if DEBUG && 0
320     NSLog(@"TAB: %@", k);
321 #endif
322     
323     [self->template appendToResponse:_response inContext:_ctx];
324     
325 #if ADD_OWN_ELEMENTIDS
326     [_ctx deleteLastElementIDComponent];
327 #endif
328   }
329     
330   if (doScript && (isActive || isScript_)) {
331     NSString *jsout;
332     [_response appendContentString:@"</div>"];
333
334     jsout = [NSString alloc];
335     jsout = [jsout initWithFormat:
336                    @"<script language=\"JavaScript\">\n<!--\n"
337                    @"%@Tab[\"Div\"] = %@TabLayer;\n",
338                    k, k];
339     
340     [_response appendContentString:jsout];
341     [jsout release];
342     
343 #if DEBUG_JS
344     jsout = [NSString alloc];
345     jsout = [jsout initWithFormat:
346                      @"if (%@Tab[\"Div\"].style==null) {"
347                      @"alert('missing style in div for tab %@');}",
348                      k, k];
349     
350     [_response appendContentString:jsout];
351     [jsout release];
352 #endif
353     
354     if (isActive) {
355       [_response appendContentString:@"showTab("];
356       [_response appendContentString:k];
357       [_response appendContentString:@"Tab);\n"];
358     }
359     [_response appendContentString:@"//-->\n</script>"];
360   }
361 }
362
363 /* master generation method */
364
365 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
366   NSString *k;
367   BOOL     doForm;
368   id       tmp;
369   
370   doForm = [_ctx isInForm];
371   k = [self->key stringValueInComponent:[_ctx component]];
372   
373   if ((tmp = [_ctx objectForKey:WETabView_HEAD])) {
374     if ([tmp isEqual:WETabView_COLLECT]) {
375       [self _collectInContext:_ctx key:k];
376     }
377     else {
378       [self _appendHeadToResponse:_response inContext:_ctx
379             activeKey:tmp key:k];
380     }
381   }
382   else if ((tmp = [_ctx objectForKey:WETabView_BODY])) {
383     [self _appendBodyToResponse:_response inContext:_ctx
384           activeKey:tmp key:k];
385   }
386   else {
387     NSLog(@"WARNING(%s): invalid WETabItem state !!!", __PRETTY_FUNCTION__);
388     [_response appendContentString:@"[invalid state]"];
389   }
390 }
391
392 @end /* WETabItem */
393
394 @implementation WETabItemInfo
395
396 - (void)dealloc {
397   [self->uri        release];
398   [self->icon       release];
399   [self->label      release];
400   [self->key        release];
401   [self->tabIcon    release];
402   [self->selIcon    release];
403   [self->leftIcon   release];
404   [self->width      release];
405   [self->height     release];
406   [self->activeBg   release];
407   [self->inactiveBg release];
408   
409   [super dealloc];
410 }
411
412 /* accessors */
413
414 - (NSString *)key {
415   return self->key;
416 }
417 - (NSString *)label {
418   return self->label;
419 }
420 - (NSString *)icon {
421   return self->icon;
422 }
423 - (NSString *)uri {
424   return self->uri;
425 }
426 - (BOOL)isScript {
427   return self->isScript;
428 }
429
430 - (int)asBackground {
431   return self->asBackground;
432 }
433
434 - (NSString *)width {
435   return self->width;
436 }
437
438 - (NSString *)height {
439   return self->height;
440 }
441
442 - (NSString *)activeBg {
443   return self->activeBg;
444 }
445
446 - (NSString *)inactiveBg {
447   return self->inactiveBg;
448 }
449
450 @end /* WETabItemInfo */