2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
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
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.
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
23 #include <NGObjDOM/WORenderDOM.h>
24 #include "ODNodeRenderer.h"
29 #if NeXT_RUNTIME || APPLE_RUNTIME
30 # define sel_get_name sel_getName
33 @interface WOContext(Privates)
34 - (unsigned)componentStackCount;
35 - (id)activeFormElement;
38 @implementation WORenderDOM
40 static int profileComponents = -1;
41 static Class NSDateClass = Nil;
44 if (NSDateClass == Nil)
45 NSDateClass = [NSDate class];
46 if (profileComponents == -1) {
47 profileComponents = [[[NSUserDefaults standardUserDefaults]
48 objectForKey:@"WOProfileComponents"]
53 - (id)initWithName:(NSString *)_name
54 associations:(NSDictionary *)_assocs
55 template:(WOElement *)_templ
57 if ((self = [super initWithName:_name associations:nil template:nil])){
59 NSLog(@"WARNING(%s): contains template !", __PRETTY_FUNCTION__);
61 self->domDocument = [[_assocs objectForKey:@"domDocument"] copy];
62 self->node = [[_assocs objectForKey:@"node"] copy];
63 self->renderer = [[_assocs objectForKey:@"renderer"] copy];
64 self->factory = [[_assocs objectForKey:@"factory"] copy];
70 RELEASE(self->factory);
72 RELEASE(self->renderer);
73 RELEASE(self->domDocument);
77 /* discovering renders */
79 - (ODNodeRenderer *)rendererForNode:(id)_domNode inContext:(WOContext *)_ctx {
80 ODNodeRenderer *lrenderer;
82 if ([self->node isValueSettable])
83 [self->node setValue:_domNode inComponent:[_ctx component]];
86 id<ODNodeRendererFactory> lfactory;
88 if ((lfactory = [self->factory valueInComponent:[_ctx component]])) {
90 NSLog(@"factory: %@", lfactory);
92 lrenderer = [lfactory rendererForNode:_domNode inContext:_ctx];
97 else if (self->renderer)
98 lrenderer = [self->renderer valueInComponent:[_ctx component]];
103 NSLog(@"lrenderer: %@", lrenderer);
109 /* root level methods */
111 - (id)pushToCtx:(WOContext *)_ctx {
114 old = [_ctx objectForKey:@"domRenderFactory"];
115 [_ctx setObject:self forKey:@"domRenderFactory"];
118 - (void)popFromCtx:(WOContext *)_ctx old:(id)_old {
120 [_ctx setObject:_old forKey:@"domRenderFactory"];
122 [_ctx removeObjectForKey:@"domRenderFactory"];
125 - (BOOL)_requiresFormInContext:(WOContext *)_ctx
127 renderer:(id)_renderer
132 return [_renderer requiresFormForNode:_domNode inContext:_ctx];
135 - (id)domInContext:(WOContext *)_ctx {
136 return [self->domDocument valueInComponent:[_ctx component]];
139 - (void)takeValuesFromRequest:(WORequest *)_request inContext:(WOContext *)_ctx {
140 ODNodeRenderer *lrenderer;
144 NSTimeInterval st = 0.0;
146 if (profileComponents)
147 st = [[NSDateClass date] timeIntervalSince1970];
150 if ([_ctx isInForm]) {
151 NSLog(@"WARNING(%s): this element shouldn't be used in forms, it generates "
152 @"it's own one.", __PRETTY_FUNCTION__);
156 if ((edom = [self domInContext:_ctx]) == nil)
159 old = [self pushToCtx:_ctx];
161 lrenderer = [self rendererForNode:edom inContext:_ctx];
162 doForm = [self _requiresFormInContext:_ctx node:edom renderer:lrenderer];
165 [_ctx setInForm:YES];
168 [lrenderer takeValuesForNode:edom
176 [self popFromCtx:_ctx old:old];
178 if (profileComponents) {
181 diff = [[NSDateClass date] timeIntervalSince1970] - st;
182 for (i = [_ctx componentStackCount]; i >= 0; i--)
184 printf("[%s %s]: %0.3fs\n",
185 "WORenderDOM", sel_get_name(_cmd), diff);
189 - (id)invokeActionForRequest:(WORequest *)_request inContext:(WOContext *)_ctx {
190 ODNodeRenderer *lrenderer;
195 NSTimeInterval st = 0.0;
197 if (profileComponents)
198 st = [[NSDateClass date] timeIntervalSince1970];
201 if ([_ctx isInForm]) {
202 NSLog(@"WARNING(%s): this element shouldn't be used in forms, it generates "
203 @"it's own one.", __PRETTY_FUNCTION__);
207 if ((edom = [self domInContext:_ctx]) == nil)
208 /* no DOM tree available */
211 old = [self pushToCtx:_ctx];
213 lrenderer = [self rendererForNode:edom inContext:_ctx];
214 doForm = [self _requiresFormInContext:_ctx node:edom renderer:lrenderer];
217 [_ctx setInForm:YES];
219 if ([_ctx currentElementID] == nil) {
222 activeNode = [_ctx activeFormElement];
224 lrenderer = [self rendererForNode:activeNode inContext:_ctx];
226 result = [lrenderer invokeActionForNode:activeNode
231 result = [lrenderer invokeActionForNode:edom
239 result = [lrenderer invokeActionForNode:edom
244 [self popFromCtx:_ctx old:old];
246 if (profileComponents) {
249 diff = [[NSDateClass date] timeIntervalSince1970] - st;
250 for (i = [_ctx componentStackCount]; i >= 0; i--)
252 printf("[%s %s]: %0.3fs\n",
253 "WORenderDOM", sel_get_name(_cmd), diff);
259 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
260 ODNodeRenderer *lrenderer;
265 NSTimeInterval st = 0.0;
267 if (profileComponents)
268 st = [[NSDateClass date] timeIntervalSince1970];
271 if ([_ctx isInForm]) {
272 NSLog(@"WARNING(%s): this element shouldn't be used in forms, it generates "
273 @"it's own one.", __PRETTY_FUNCTION__);
277 cmp = [_ctx component];
280 NSAssert(_ctx, @"missing context ..");
281 NSAssert(_response, @"missing response ..");
282 NSAssert(cmp, @"missing component ..");
283 [_response appendContentString:@"<!-- renderdom-begin -->"];
286 if ((edom = [self domInContext:_ctx]) == nil) {
288 [cmp logWithFormat:@"no DOM to render .."];
289 [_response appendContentString:@"<!-- missing dom -->"];
294 old = [self pushToCtx:_ctx];
296 if ((lrenderer = [self rendererForNode:edom inContext:_ctx]) == nil) {
298 [cmp logWithFormat:@"did not find renderer for node %@", edom];
299 [_response appendContentString:@"<!-- missing dom renderer -->"];
304 doForm = [self _requiresFormInContext:_ctx node:edom renderer:lrenderer];
307 [_response appendContentString:@"<form method=\"post\" action=\""];
308 [_response appendContentString:[_ctx componentActionURL]];
309 [_response appendContentString:@"\">"];
310 [_ctx setInForm:YES];
314 [cmp logWithFormat:@"render dom %@ using %@", edom, lrenderer];
315 NSAssert(lrenderer, @"lost renderer ..");
318 [lrenderer appendNode:edom
324 [_response appendContentString:@"</form>"];
328 NSAssert(_response, @"lost response ..");
329 [_response appendContentString:@"<!-- renderdom-end -->"];
332 [self popFromCtx:_ctx old:old];
334 if (profileComponents) {
337 diff = [[NSDateClass date] timeIntervalSince1970] - st;
338 for (i = [_ctx componentStackCount]; i >= 0; i--)
340 printf("[%s %s]: %0.3fs (component=%s)\n",
341 "WORenderDOM", sel_get_name(_cmd), diff,
342 [[(WOComponent *)[_ctx component] name] cString]);
346 @end /* WORenderDOM */