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/*
25  renders this:
26
27  <...small script...>
28  <SPAN onDragStart="fnSetInfo($tag,$effectsAllowed)">
29  $content
30  </SPAN>
31
32*/
33
34@interface WEDragContainer : WODynamicElement
35{
36  WOElement     *template;
37  WOAssociation *tag;
38  WOAssociation *effectsAllowed;
39  WOAssociation *elementName;
40  WOAssociation *isDraggable;
41
42  WOAssociation *object;
43  WOAssociation *droppedObject;
44}
45@end
46
47@interface WEDragScript : WODynamicElement
48+ (void)appendDragScriptToResponse:(WOResponse *)_response
49  inContext:(WOContext *)_ctx;
50@end
51
52#include <NGObjWeb/WEClientCapabilities.h>
53#include "common.h"
54
55//#define DEBUG_TAKEVALUES 1
56
57@implementation WEDragContainer
58
59static BOOL debugTakeValues = NO;
60
61- (id)initWithName:(NSString *)_name
62  associations:(NSDictionary *)_config
63  template:(WOElement *)_t
64{
65  if ((self = [super initWithName:_name associations:_config template:_t])) {
66    self->tag            = WOExtGetProperty(_config, @"tag");
67    self->effectsAllowed = WOExtGetProperty(_config, @"effectsAllowed");
68    self->elementName    = WOExtGetProperty(_config, @"elementName");
69    self->isDraggable    = WOExtGetProperty(_config, @"isDraggable");
70
71    self->object         = WOExtGetProperty(_config, @"object");
72    self->droppedObject  = WOExtGetProperty(_config, @"droppedObject");
73
74    self->template = [_t retain];
75  }
76  return self;
77}
78
79- (void)dealloc {
80  [self->isDraggable    release];
81  [self->object         release];
82  [self->droppedObject  release];
83  [self->tag            release];
84  [self->elementName    release];
85  [self->effectsAllowed release];
86  [self->template       release];
87  [super dealloc];
88}
89
90/* processing request values */
91
92- (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
93  id formValue;
94
95  if ((formValue = [_rq formValueForKey:[_ctx elementID]]) != nil) {
96    id obj;
97
98    if (debugTakeValues) {
99      [[_ctx component]
100	     debugWithFormat:@"WEDragContainer: got value '%@' for id '%@'",
101               formValue, [_ctx elementID]];
102    }
103
104    obj = [self->object valueInComponent:[_ctx component]];
105
106    if (debugTakeValues)
107      NSLog(@"DRAG MATCH => ok, obj is %@",obj);
108
109    if ([self->droppedObject isValueSettable])
110      [self->droppedObject setValue:obj inComponent:[_ctx component]];
111
112    if (obj) {
113      [_ctx takeValue:obj forKey:@"WEDragContainer_DropObject"];
114    }
115  }
116  else if (debugTakeValues) {
117    [[_ctx component]
118           debugWithFormat:@"WEDragContainer: got no value for id '%@'",
119             [_ctx elementID]];
120  }
121
122  [self->template takeValuesFromRequest:_rq inContext:_ctx];
123}
124
125- (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
126  return [self->template invokeActionForRequest:_rq inContext:_ctx];
127}
128
129/* generating response */
130
131- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
132  NSString *tmp = nil;
133  NSString *ttag;
134  BOOL     doDnD;
135
136  if ([_ctx isRenderingDisabled]) {
137    [self->template appendToResponse:_response inContext:_ctx];
138    return;
139  }
140
141  doDnD = [[[_ctx request] clientCapabilities] doesSupportDHTMLDragAndDrop];
142
143  if (doDnD) {
144    if (self->isDraggable)
145      doDnD = [self->isDraggable boolValueInComponent:[_ctx component]];
146  }
147
148  [WEDragScript appendDragScriptToResponse:_response inContext:_ctx];
149
150  ttag = [self->tag stringValueInComponent:[_ctx component]];
151
152  if (doDnD) {
153    NSString *teffect, *tdragContent;
154
155    teffect = self->effectsAllowed
156      ? [self->effectsAllowed stringValueInComponent:[_ctx component]]
157      : (NSString *)@"all";
158
159    tdragContent = @"this.innerHTML";
160
161    tmp = @"fnSetInfo('%@?%@','%@', %@)";
162    tmp = [NSString stringWithFormat:tmp,
163                      [_ctx elementID], ttag,
164                      teffect,
165                      tdragContent];
166  }
167
168  if (self->elementName || doDnD) {
169    /* Note: not using lowercase names since this might break JS? */
170    [_response appendContentString:@"<SPAN "];
171    [_response appendContentString:@"ID=\"span_"];
172    [_response appendContentString:[_ctx elementID]];
173    [_response appendContentString:@"\" "];
174  }
175
176  if (doDnD) {
177    [_response appendContentString:@" onDragStart=\""];
178    [_response appendContentString:tmp];
179    [_response appendContentString: @"\""];
180    [_response appendContentString:@" onDrag=\"fnDrag()\""];
181    [_response appendContentString:@" onDragEnd=\"fnDragEnd()\""];
182  }
183
184  if (self->elementName || doDnD) {
185    [self appendExtraAttributesToResponse:_response inContext:_ctx];
186    [_response appendContentString:@">"];
187  }
188
189  /* add template */
190  [self->template appendToResponse:_response inContext:_ctx];
191
192  /* close container */
193  if (self->elementName || doDnD)
194    [_response appendContentString:@"</SPAN>"];
195}
196
197/* accessors */
198
199- (id)template {
200  return self->template;
201}
202
203@end /* WEDragContainer */
204
205
206@implementation WEDragScript
207
208+ (void)appendDragScriptToResponse:(WOResponse *)_response
209  inContext:(WOContext *)_ctx
210{
211  NSString *dragScript;
212  BOOL     doDnD;
213
214  doDnD = [[[_ctx request] clientCapabilities] doesSupportDHTMLDragAndDrop];
215
216  if (![[_ctx objectForKey: @"WEDragContainerScriptDone"] boolValue] && doDnD) {
217    dragScript =
218      @"<DIV ID=\"DragDIV\" STYLE=\"position: absolute; visibility: hidden; width: 150;\"></DIV>"
219      @"<SCRIPT LANGUAGE=\"JScript\">\n"
220      @"<!--\n"
221      @"function fnSetInfo(objData, effects, dragContent) {\n"
222      @"  event.dataTransfer.clearData(\"Text\");\n"
223      @"  event.dataTransfer.setData(\"Text\", objData);\n"
224      @"  event.dataTransfer.effectAllowed = effects;\n "
225      @"  DragDIV.innerHTML = dragContent;\n"
226      @"  DragDIV.style.visibility = \"visible\";\n "
227      @"  DragDIV.style.top  =window.event.clientY+document.body.scrollTop;\n"
228      @"  DragDIV.style.left =window.event.clientX+document.body.scrollLeft;\n"
229      @"  DragDIV.style.zIndex += 20; \n"
230      @"}\n"
231      @"function fnDrag() {\n"
232      @"  DragDIV.style.top  =window.event.clientY+document.body.scrollTop;\n"
233      @"  DragDIV.style.left =window.event.clientX+document.body.scrollLeft;\n"
234      @"}\n"
235      @"function fnDragEnd() {\n"
236      @"  DragDIV.innerHTML = \"\";\n"
237      @"  DragDIV.style.visibility = \"hidden\";\n"
238      @"}\n"
239      @"// -->\n"
240      @"</SCRIPT>";
241
242    [_response appendContentString: dragScript];
243
244    [_ctx takeValue: [NSNumber numberWithBool: YES] forKey:
245          @"WEDragContainerScriptDone"];
246  }
247}
248
249- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
250  [[self class] appendDragScriptToResponse:_response inContext:_ctx];
251}
252
253@end /* WEDragScript */
254