]> err.no Git - sope/blob - sope-appserver/WEExtensions/WEDropContainer.m
added strict OSX bundle dependencies
[sope] / sope-appserver / WEExtensions / WEDropContainer.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 #import <NGObjWeb/WODynamicElement.h>
23
24 /*
25   usage:
26
27      DropContainer: WEDropContainer {
28        elementName   = "tr";
29        isAttached    = YES;
30        tags          = ( * );
31        action        = dropAction;
32        droppedObject = droppedObject;
33        
34        swapColor     = YES;
35        activeColor   = "lightblue";
36        bgColor       = bgColor;
37      }
38      
39   renders this:
40
41     <$area BGCOLOR=white 
42         onDragEnter="fnCancelDefault()"
43         onDragOver="fnCancelDefault()"
44         onDrop="fnGetInfo()">
45        $content
46     </$area>
47 */
48
49 @interface WEDropContainer : WODynamicElement
50 {
51   NSDictionary  *dExtraAttrs;
52   WOAssociation *tags;
53   WOAssociation *elementName;
54   WOAssociation *isAttached;  /* bool */
55   WOAssociation *effect;
56   WOAssociation *swapColor; /* swap bgcolor if drag object is over container */
57   WOAssociation *action;
58   WOAssociation *droppedObject;
59   
60   WOElement     *template;
61 }
62 @end
63
64 @interface WEDropScript : WODynamicElement
65 + (void)appendDropScriptToResponse:(WOResponse *)_response
66   inContext:(WOContext *)_ctx;
67 @end
68
69 #include <NGObjWeb/WEClientCapabilities.h>
70 #include "common.h"
71
72 @implementation WEDropContainer
73
74 + (int)version {
75   return 0 + [super version];
76 }
77
78 - (id)initWithName:(NSString *)_name
79   associations:(NSDictionary *)_config
80   template:(WOElement *)_subs
81 {
82   if ((self = [super initWithName:_name associations:_config template:_subs])) {
83     self->tags            = WOExtGetProperty(_config, @"tags");
84     self->elementName     = WOExtGetProperty(_config, @"elementName");
85     self->effect          = WOExtGetProperty(_config, @"effect");
86     self->action          = WOExtGetProperty(_config, @"action");
87     self->droppedObject   = WOExtGetProperty(_config, @"droppedObject");
88     self->swapColor       = WOExtGetProperty(_config, @"swapColor");
89     self->isAttached      = WOExtGetProperty(_config, @"isAttached");
90     
91     self->template = RETAIN(_subs);
92   }
93   return self;
94 }
95
96 - (void)dealloc {
97   RELEASE(self->dExtraAttrs);
98   
99   RELEASE(self->swapColor);
100   RELEASE(self->droppedObject);
101   RELEASE(self->action);
102   RELEASE(self->template);
103   RELEASE(self->effect);
104   RELEASE(self->tags);
105   RELEASE(self->elementName);
106   RELEASE(self->isAttached);
107   
108   [super dealloc];
109 }
110
111 - (void)setExtraAttributes:(NSDictionary *)_extras {
112   ASSIGNCOPY(self->dExtraAttrs, _extras);
113 }
114
115 - (void)appendExtraAttributesToResponse:(WOResponse *)_response
116   inContext:(WOContext *)_ctx
117 {
118   if (self->dExtraAttrs) {
119     WOComponent  *sComponent;
120     NSEnumerator *keys;
121     NSString     *key;
122     
123     sComponent = [_ctx component];
124
125     keys = [self->dExtraAttrs keyEnumerator];
126     
127     while ((key = [keys nextObject])) {
128       id value;
129       
130       value = [self->dExtraAttrs objectForKey:key];
131       
132       if (value == nil)
133         continue;
134       
135       //key   = [key lowercaseString];
136       value = [value stringValueInComponent:sComponent];
137
138       [_response appendContentCharacter:' '];
139       [_response appendContentString:key];
140       [_response appendContentString:@"=\""];
141       [_response appendContentHTMLAttributeValue:value];
142       [_response appendContentCharacter:'"'];
143     }
144   }
145 }
146
147 /* responder */
148
149 - (void)takeValuesFromRequest:(WORequest *)_request
150   inContext:(WOContext *)_ctx
151 {
152   [_ctx appendElementIDComponent:@"p"];
153   [self->template takeValuesFromRequest:_request inContext:_ctx];
154   [_ctx deleteLastElementIDComponent];
155 }
156
157 - (id)invokeActionForRequest:(WORequest *)_request
158   inContext:(WOContext *)_ctx
159 {
160   NSString *op;
161   id result;
162   
163   op = [[_ctx currentElementID] stringValue];
164 #if 0
165     NSLog(@"check DROP ACTION %@ ..", op);
166 #endif
167   
168   if ([op isEqualToString:@"p"]) {
169     /* an action inside of the component */
170     [_ctx consumeElementID]; // consume id
171     [_ctx appendElementIDComponent:@"p"];
172     result = [self->template invokeActionForRequest:_request inContext:_ctx];
173     [_ctx deleteLastElementIDComponent];
174   }
175   else if ([op isEqualToString:@"drop"]) {
176     /* an action of *this* component */
177     [_ctx consumeElementID]; // consume id
178     [_ctx appendElementIDComponent:@"drop"];
179
180 #if 0
181     NSLog(@"WILL RUN DROP ACTION ..");
182 #endif
183     
184     if ([self->droppedObject isValueSettable]) {
185       [self->droppedObject setValue:
186                              [_ctx valueForKey:@"WEDragContainer_DropObject"]
187                            inComponent:[_ctx component]];
188     }
189     
190     result = [self->action valueInComponent:[_ctx component]];
191     
192     [_ctx deleteLastElementIDComponent];
193   }
194   else {
195     NSLog(@"invalid element-id: did not expect '%@' id", op);
196     result = nil;
197   }
198   return result;
199 }
200
201 - (void)appendExtraAttributesAsJavaScriptToResponse:(WOResponse *)_response
202   inContext:(WOContext *)_ctx
203 {
204   if (self->dExtraAttrs) {
205     WOComponent     *sComponent = [_ctx component];
206     NSEnumerator    *keyEnum;
207     NSString        *key;
208
209     [_response appendContentString:
210                @"\n"
211                @"<script language=\"JavaScript\">\n"
212                @"<!--\n"];
213
214     keyEnum = [self->dExtraAttrs keyEnumerator];
215     while ((key = [keyEnum nextObject])) {
216       id value;
217       
218       value = [self->dExtraAttrs objectForKey:key];
219       
220       if (value == nil)
221         continue;
222
223       if ([[key lowercaseString] isEqualToString:@"width"])
224         key = @"width";
225       else if ([[key lowercaseString] isEqualToString:@"height"])
226         key = @"height";
227       else if ([[key lowercaseString] isEqualToString:@"bgcolor"])
228         key = @"bgColor";
229       else if ([[key lowercaseString] isEqualToString:@"activecolor"])
230         key = @"activeColor";
231       else if ([[key lowercaseString] isEqualToString:@"align"])
232         key = @"align";
233       else if ([[key lowercaseString] isEqualToString:@"valign"])
234         key = @"vAlign";
235       else if ([[key lowercaseString] isEqualToString:@"colspan"])
236         key = @"colSpan";
237       else if ([[key lowercaseString] isEqualToString:@"rowspan"])
238         key = @"rowSpan";
239       else if ([[key lowercaseString] isEqualToString:@"nowrap"])
240         key = @"noWrap";
241       
242       value = [value stringValueInComponent:sComponent];
243       [_response appendContentString:
244                  [NSString stringWithFormat:@"tmp.%@ = \"%@\";\n", key, value]];
245     }
246     [_response appendContentString:
247                @"// -->\n"
248                @"</script>\n"];
249   }
250 }
251
252 - (void)appendToResponse:(WOResponse *)_response
253   inContext:(WOContext *)_ctx
254 {
255   NSString *htmlEl;
256   NSString *ttag;
257   NSString *teffect;
258   NSString *containerID = nil;
259   BOOL     doDnD, doSwap, doAttach;
260   
261   doDnD = [[[_ctx request] clientCapabilities] doesSupportDHTMLDragAndDrop];
262
263   //doDnD = YES;
264   
265   ttag = [[self->tags valueInComponent:[_ctx component]]
266                       componentsJoinedByString:@","];
267   
268   teffect = [self->effect stringValueInComponent:[_ctx component]];
269   if (teffect == nil) teffect = @"move";
270   
271   [WEDropScript appendDropScriptToResponse:_response inContext:_ctx];
272   
273   [_ctx appendElementIDComponent:@"drop"];
274   
275   htmlEl   = [self->elementName stringValueInComponent:[_ctx component]];
276   doAttach = ([self->isAttached boolValueInComponent:[_ctx component]] &&
277              (self->elementName != nil));
278   
279   if (htmlEl == nil || doAttach) htmlEl = @"span";
280   
281   if ((self->elementName != nil) || doDnD) {
282     int containerIDc;
283     
284     [_response appendContentString: @"<"];
285     [_response appendContentString:htmlEl];
286
287     if (doDnD) {
288       /* gen unique container id */
289       
290       if ((containerID = [_ctx valueForKey:@"WEDropContainerSequence"])) {
291         containerID = AUTORELEASE([containerID copy]);
292         containerIDc = [containerID intValue];
293       }
294       else {
295         containerID  = @"0";
296         containerIDc = 0;
297       }
298       
299       [_response appendContentString:@" id=\"skydrop"];
300       if (doAttach) [_response appendContentString:@"dummy"];
301       [_response appendContentString:containerID];
302       [_response appendContentString:@"\""];
303       
304       containerIDc++;
305     
306       [_ctx takeValue:[NSString stringWithFormat:@"%i", containerIDc]
307             forKey:@"WEDropContainerSequence"];
308     }
309   }
310   
311   if (doDnD) {
312     NSString *swapOnAction  = @"";
313     NSString *swapOffAction = @"";
314     NSString *cancelAction;
315     NSString *infoAction;
316       
317
318     doSwap = self->swapColor
319       ? [self->swapColor boolValueInComponent:[_ctx component]]
320       : YES;
321
322     cancelAction = [NSString stringWithFormat:@"fnCancelDefault('%@','%@');",
323                              ttag, teffect];
324     if (doSwap) {
325       swapOnAction  = [NSString stringWithFormat:
326                                 @"dropFieldSwapColor(skydrop%@,true);",
327                                 containerID];
328       swapOffAction = [NSString stringWithFormat:
329                                 @"dropFieldSwapColor(skydrop%@,false);",
330                                 containerID];
331     }
332     
333     infoAction = [NSString stringWithFormat:@"fnGetInfo(this, '%@');",
334                            [_ctx componentActionURL]];
335
336     if (doAttach) {
337       NSString *tagName = nil;
338
339       // doAttach==YES -> self->elementName != nil
340       tagName = [self->elementName stringValueInComponent:[_ctx component]];
341       tagName = [tagName uppercaseString];
342       
343       [_response appendContentCharacter:'>'];
344       
345       [_response appendContentString:[NSString stringWithFormat:
346            @"\n"
347            @"<script language=\"JavaScript\">\n"
348            @"<!--\n"
349            @"  function onDragEnterFunc%@() {\n    %@\n     %@\n}\n"
350            @"  function onDragOverFunc%@()  {\n    %@\n     %@\n}\n"
351            @"  function onDragLeaveFunc%@() {\n %@\n     }\n"
352            @"  function onDropFunc%@()      {\n %@\n     }\n"
353            @"\n"
354            @"  tmp = document.getElementById(\"%@\");\n"
355            @"  i = 5;\n"
356            @"  while ((tmp.tagName != \"%@\") && (i >= 0)) {\n"
357            @"    tmp = tmp.parentNode;\n"
358            @"    i--;\n"
359            @"  }\n"
360            @"  tmp.ondragover    = onDragOverFunc%@;\n"
361            @"  tmp.ondragleave   = onDragLeaveFunc%@;\n"
362            @"  tmp.ondrop        = onDropFunc%@;\n"
363            @"  tmp.ondragenter   = onDragEnterFunc%@;\n"
364            @"  tmp.id            = \"%@\";\n"
365            @"// -->\n"
366            @"</script>\n",
367            containerID, cancelAction, swapOnAction,
368            containerID, cancelAction, swapOnAction,
369            containerID, swapOffAction,
370            containerID, infoAction,
371            [@"skydropdummy" stringByAppendingString:containerID],
372            tagName,
373            containerID,
374            containerID,
375            containerID,
376            containerID,
377            [@"skydrop" stringByAppendingString:containerID]]];
378
379       // remove bgColors of TR's sub TD:
380       if ([tagName isEqualToString:@"TR"]) {
381         [_response appendContentString:
382            @"\n"
383            @"<script language=\"JavaScript\">\n"
384            @"<!--\n"
385            @"list = tmp.getElementsByTagName(\"TD\");\n"
386            @"cnt  = list.length;\n"
387            @"for (i=0; i<cnt; i++) {\n"
388            @"  list[i].removeAttribute(\"bgColor\");\n"
389            @"}\n"
390            @"// -->\n"
391            @"</script>\n"];
392       }
393
394       /* append extra attributes by script */
395       [self appendExtraAttributesAsJavaScriptToResponse:_response
396                                               inContext:_ctx];
397     }
398     else {
399       [_response appendContentString:@" onDragEnter=\""];
400       [_response appendContentString:cancelAction];
401       [_response appendContentString:swapOnAction];
402
403       [_response appendContentString:@"\" onDragOver=\""];
404       [_response appendContentString:cancelAction];
405       [_response appendContentString:swapOnAction];
406
407       [_response appendContentString:@"\" onDragLeave=\""];
408       [_response appendContentString:swapOffAction];
409      
410       [_response appendContentString:@"\" onDrop=\""];
411       [_response appendContentString:infoAction];
412       [_response appendContentCharacter:'"'];
413       
414       [self appendExtraAttributesToResponse:_response inContext:_ctx];
415       [_response appendContentCharacter:'>'];
416     }
417   }
418   else if (self->elementName != nil) {
419     [self appendExtraAttributesToResponse:_response inContext:_ctx];
420     [_response appendContentCharacter:'>'];
421   }
422   
423   [_ctx deleteLastElementIDComponent];
424   
425   /* add template */
426   [_ctx appendElementIDComponent:@"p"];
427   [self->template appendToResponse:_response inContext:_ctx];
428   [_ctx deleteLastElementIDComponent];
429   
430   /* close container */
431   if ((self->elementName != nil) || doDnD) {
432     [_response appendContentString:@"</"];
433     [_response appendContentString:htmlEl];
434     [_response appendContentCharacter:'>'];
435   }
436 }
437
438 /* accessors */
439
440 - (id)template {
441   return self->template;
442 }
443
444 @end /* WEDropContainer */
445
446
447 @implementation WEDropScript
448
449 + (void)appendDropScriptToResponse:(WOResponse *)_response
450   inContext:(WOContext *)_ctx
451 {
452   BOOL doDnD;
453   
454   doDnD = [[[_ctx request] clientCapabilities] doesSupportDHTMLDragAndDrop];
455   
456   if (![[_ctx valueForKey:@"WEDropContainerScriptDone"] boolValue] && doDnD) {
457     NSString *dropScript;
458     
459     dropScript =
460 #include "WEDropScript.jsm"
461       ;
462     
463     [_response appendContentString:dropScript];
464     
465     [_ctx takeValue:[NSNumber numberWithBool:YES]
466           forKey:@"WEDropContainerScriptDone"];
467   }
468 }
469
470 - (void)appendToResponse:(WOResponse *)_response
471   inContext:(WOContext *)_ctx
472 {
473   [[self class] appendDropScriptToResponse:_response inContext:_ctx];
474 }
475
476 @end /* WEDropScript */