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