1
2 #include "studiox_includes.h"
3
4 #ifdef _DEBUG
5 #define new DEBUG_NEW
6 #endif
7
8 //CArray<template_info *> template_service_provider::base_info_list;
9
10 extern "C" {
11 extern GX_DISPLAY target_win_display;
12 }
13
14 ///////////////////////////////////////////////////////////////////////////////
template_service_provider()15 template_service_provider::template_service_provider()
16 {
17 }
18
19 ///////////////////////////////////////////////////////////////////////////////
~template_service_provider()20 template_service_provider::~template_service_provider()
21 {
22 Reset();
23 }
24
25 ///////////////////////////////////////////////////////////////////////////////
GetVarDeclaration()26 CString template_service_provider::GetVarDeclaration()
27 {
28 /* For derived widgets, the screen_generator installs and instance
29 of the base widget control block. Nothing to do here.
30 */
31 return CString("");
32 }
33
34
35 ///////////////////////////////////////////////////////////////////////////////
DeclarePropertiesStruct()36 CString template_service_provider::DeclarePropertiesStruct()
37 {
38 CString out(""
39 "typedef struct\n"
40 "{\n"
41 " GX_CONST GX_STUDIO_WIDGET *base_info;\n"
42 " UINT (*base_create_function) (GX_CONST struct GX_STUDIO_WIDGET_STRUCT *, GX_WIDGET *, GX_WIDGET *);\n"
43 " GX_RECTANGLE size;\n"
44 "} GX_TEMPLATE_PROPERTIES;\n\n");
45 return out;
46 }
47
48 ///////////////////////////////////////////////////////////////////////////////
WriteExtendedProperties(screen_generator * gen,CString & prefix,widget_info * info)49 CString template_service_provider::WriteExtendedProperties(screen_generator *gen, CString &prefix, widget_info *info)
50 {
51 /* derived class should write extended properties of it's base */
52 CString out;
53 widget_service_provider *bp = GetBaseProvider(info);
54 widget_info *base = GetBaseInfo(info);
55 studiox_project *project = GetOpenProject();
56
57 if (project && base && bp)
58 {
59 widget_info *parent = project->FindParentInfo(base);
60
61 CString parent_name = _T("");
62
63 if (parent)
64 {
65 parent_name = parent->app_name;
66 }
67
68 CString temp = prefix + info->app_name;
69 out.Format(_T("GX_TEMPLATE_PROPERTIES %s_properties =\n{\n"), temp);
70
71 if (parent_name.IsEmpty())
72 {
73 temp.Format(_T(" &%s%s_define, /* base info */\n"), gen->GetScreenNamePrefix(), base->app_name);
74 }
75 else
76 {
77 temp.Format(_T(" %s_%s_define, /* base info */\n"), parent_name, base->app_name);
78 }
79 out += temp;
80 temp.Format(_T(" %s, /* base create function */\n"), bp->GetCreateFromDefFunctionName());
81 out += temp;
82
83 temp.Format(_T(" {%d, %d, %d, %d} /* widget size */\n};\n"),
84 info->size.gx_rectangle_left,
85 info->size.gx_rectangle_top,
86 info->size.gx_rectangle_right,
87 info->size.gx_rectangle_bottom);
88 out += temp;
89 }
90 return out;
91 }
92
93 ///////////////////////////////////////////////////////////////////////////////
GetCreateFromDefFunctionName()94 CString template_service_provider::GetCreateFromDefFunctionName()
95 {
96 return CString("gx_studio_template_create");
97 }
98
99 ///////////////////////////////////////////////////////////////////////////////
GetCreateFromDefFunction(int version)100 CString template_service_provider::GetCreateFromDefFunction(int version)
101 {
102 studiox_project *project = GetOpenProject();
103 CString out("");
104 MakeCreatePreamble("template", version, out);
105
106 out += "{\n"
107 " UINT status = GX_SUCCESS;\n"
108 " GX_STUDIO_WIDGET derived;\n"
109 " GX_TEMPLATE_PROPERTIES *props = (GX_TEMPLATE_PROPERTIES *) info->properties;\n\n"
110 " /* create base widget and children */ \n"
111 " derived = *props->base_info;\n"
112 " derived.widget_id = info->widget_id;\n"
113 " derived.widget_name = info->widget_name;\n"
114 "\n"
115 " if (info->style & GX_STYLE_ENABLED)\n"
116 " {\n"
117 " derived.style |= GX_STYLE_ENABLED;\n"
118 " }\n"
119 " else\n"
120 " {\n"
121 " derived.style &= ~GX_STYLE_ENABLED;\n"
122 " }\n"
123 " if (info->status & GX_STATUS_ACCEPTS_FOCUS)\n"
124 " {\n"
125 " derived.status |= GX_STATUS_ACCEPTS_FOCUS;\n"
126 " }\n"
127 " else\n"
128 " {\n"
129 " derived.status &= ~GX_STATUS_ACCEPTS_FOCUS;\n"
130 " }\n\n";
131
132 if (project->mHeader.guix_version > 50206)
133 {
134
135 out += " #if defined(GX_WIDGET_USER_DATA)\n"
136 " derived.user_data = info->user_data;\n"
137 " #endif\n\n";
138 }
139
140 out += " control_block = gx_studio_widget_create((GX_BYTE *) control_block, &derived, parent);\n"
141 " if (control_block)\n"
142 " {\n"
143 " if (info->style & GX_STYLE_DYNAMICALLY_ALLOCATED)\n"
144 " {\n"
145 " control_block->gx_widget_status |= GX_STATUS_DYNAMICALLY_ALLOCATED;\n"
146 " }\n"
147 " if (derived.size.gx_rectangle_left != info->size.gx_rectangle_left ||\n"
148 " derived.size.gx_rectangle_top != info->size.gx_rectangle_top)\n"
149 " {\n"
150 " gx_widget_shift(control_block,\n"
151 " info->size.gx_rectangle_left - derived.size.gx_rectangle_left,\n"
152 " info->size.gx_rectangle_top - derived.size.gx_rectangle_top, GX_FALSE);\n"
153 " }\n"
154 " }\n"
155 " else\n"
156 " {\n"
157 " status = GX_FAILURE;\n"
158 " }\n"
159 " return status;\n"
160 "}\n";
161 return out;
162 }
163
164
165 ///////////////////////////////////////////////////////////////////////////////
CreateNewInstance(GX_WIDGET * parent)166 widget_info *template_service_provider::CreateNewInstance(GX_WIDGET *parent)
167 {
168 return NULL;
169 }
170
171 ///////////////////////////////////////////////////////////////////////////////
CreateNewInstance(GX_WIDGET * parent,widget_info * base)172 widget_info *template_service_provider::CreateNewInstance(GX_WIDGET *parent, widget_info *base)
173 {
174 GX_RECTANGLE size = base->size;
175
176 widget_info *derived_info = new widget_info;
177 *derived_info = *base;
178
179 gx_utility_rectangle_center(&size, &parent->gx_widget_size);
180 derived_info->size = size;
181
182 derived_info->app_name = CString("derived");
183 widget_factory::CreateUniqueAppNames(derived_info);
184
185 derived_info->widget = NULL;
186 derived_info->SetChildWidgetInfo(NULL);
187 derived_info->SetNextWidgetInfo(NULL);
188 derived_info->basetype = GX_TYPE_TEMPLATE;
189 derived_info->is_template = FALSE;
190 derived_info->ewi.template_display = GetProjectView()->GetActiveDisplay();
191 derived_info->base_name = base->app_name;
192
193 GX_WIDGET *derived = GenerateFromInfo(parent, derived_info);
194 derived_info->widget = derived;
195 return derived_info;
196 }
197
198 ///////////////////////////////////////////////////////////////////////////////
BuildBaseWidget(GX_WIDGET * parent,widget_info * info,GX_BOOL add_children)199 GX_WIDGET *template_service_provider::BuildBaseWidget(GX_WIDGET *parent, widget_info *info, GX_BOOL add_children)
200 {
201 GX_WIDGET *template_instance = NULL;
202
203 if (widget_factory::FindBaseName(info->base_name))
204 {
205
206 widget_service_provider *pp = widget_factory::GetServiceProvider(info->basetype);
207
208 if (pp)
209 {
210 /* generate an instance of this template base */
211 template_instance = pp->GenerateFromInfo(parent, info);
212 }
213 }
214 else
215 {
216 widget_info* base_info = GetBaseInfo(info);
217
218 if (base_info)
219 {
220 // this template is based on another, start by building the base for this
221 // template:
222 template_instance = BuildBaseWidget(parent, base_info, TRUE);
223 }
224 }
225
226 if (template_instance)
227 {
228 /* move the template instance to the correct position */
229 if (template_instance->gx_widget_size.gx_rectangle_left != info->size.gx_rectangle_left ||
230 template_instance->gx_widget_size.gx_rectangle_top != info->size.gx_rectangle_top)
231 {
232 _gx_widget_shift(template_instance,
233 info->size.gx_rectangle_left - template_instance->gx_widget_size.gx_rectangle_left,
234 info->size.gx_rectangle_top - template_instance->gx_widget_size.gx_rectangle_top, GX_TRUE);
235
236 info->size = template_instance->gx_widget_size;
237 }
238
239 if (add_children)
240 {
241 /* generate children of this template instance */
242 if (info->GetChildWidgetInfo())
243 {
244 widget_factory::GenerateWidgets(template_instance, info->GetChildWidgetInfo(), FALSE);
245 }
246 }
247
248 if (info->style & GX_STYLE_ENABLED)
249 {
250 if (!(template_instance->gx_widget_style & GX_STYLE_ENABLED))
251 {
252 _gx_widget_style_add(template_instance, GX_STYLE_ENABLED);
253 }
254 }
255 else
256 {
257 if (template_instance->gx_widget_style & GX_STYLE_ENABLED)
258 {
259 _gx_widget_style_remove(template_instance, GX_STYLE_ENABLED);
260 }
261 }
262 }
263 return template_instance;
264 }
265
266 ///////////////////////////////////////////////////////////////////////////////
GenerateFromInfo(GX_WIDGET * parent,widget_info * info)267 GX_WIDGET *template_service_provider::GenerateFromInfo(GX_WIDGET *parent, widget_info *info)
268 {
269 GX_WIDGET *instance;
270
271 instance = BuildBaseWidget(parent, info, FALSE);
272
273 if (instance)
274 {
275 instance->gx_widget_name = (CHAR*)info->app_name.GetString();
276 }
277
278 return instance;
279 }
280
281
282 ///////////////////////////////////////////////////////////////////////////////
SaveToProject(xml_writer & writer,studiox_project * project,int display,widget_info * info)283 void template_service_provider::SaveToProject(xml_writer &writer, studiox_project *project, int display, widget_info *info)
284 {
285 widget_service_provider::SaveToProject(writer, project, display, info);
286 widget_info *base_info = GetBaseInfo(info, project);
287
288 if (base_info)
289 {
290 if (base_info->app_name)
291 {
292 writer.WriteString("template_base", base_info->app_name);
293 }
294 else
295 {
296 ErrorMsg("Internal Error: Template base has no name");
297 }
298 }
299 }
300
301 ///////////////////////////////////////////////////////////////////////////////
ReadFromProject(xml_reader & reader,studiox_project * project,int display,widget_info * info,ULONG valid_styles)302 void template_service_provider::ReadFromProject(xml_reader &reader, studiox_project *project, int display, widget_info *info, ULONG valid_styles)
303 {
304 valid_styles |= 0x7fffffff;
305
306 widget_service_provider::ReadFromProject(reader, project, display, info, valid_styles);
307 reader.ReadString("template_base", info->base_name);
308 info->ewi.template_display = display;
309 }
310
311 ///////////////////////////////////////////////////////////////////////////////
AssignPixelmap(widget_info * info,int index,GX_RESOURCE_ID pixmap_id)312 void template_service_provider::AssignPixelmap(widget_info *info, int index,
313 GX_RESOURCE_ID pixmap_id)
314 {
315 }
316
317 ///////////////////////////////////////////////////////////////////////////////
Autosize(widget_info * info)318 void template_service_provider::Autosize(widget_info *info)
319 {
320 }
321
322
323 ///////////////////////////////////////////////////////////////////////////////
GetBaseInfo(widget_info * derived,studiox_project * project)324 widget_info *template_service_provider::GetBaseInfo(widget_info *derived, studiox_project *project)
325 {
326 widget_info *base = NULL;
327
328 if (!project)
329 {
330 project = GetOpenProject();
331 }
332
333 if (derived->app_name == derived->base_name)
334 {
335 if (derived->is_template)
336 {
337 ErrorMsg("Internal error: Template is based on itself");
338
339 return NULL;
340 }
341 }
342
343 if (project)
344 {
345 folder_info *folder = project->mDisplays[derived->ewi.template_display].GetFirstChildFolder();
346 base = project->FindWidgetInfo(folder, derived->base_name, FALSE);
347 }
348
349 if (base)
350 {
351 if (!base->is_template)
352 {
353 return NULL;
354 }
355 }
356
357 return base;
358 }
359
360 ///////////////////////////////////////////////////////////////////////////////
GetBaseProvider(widget_info * derived)361 widget_service_provider *template_service_provider::GetBaseProvider(widget_info *derived)
362 {
363 widget_service_provider *bp = NULL;
364 widget_info *base_info = GetBaseInfo(derived);
365
366 if (base_info)
367 {
368 bp = widget_factory::GetServiceProvider(base_info->basetype);
369 }
370 return bp;
371 }
372
373 ///////////////////////////////////////////////////////////////////////////////
374 /* This function is called only when a folder is being deleted. Check to see
375 if any widgets outside of this folder are derived from a template
376 within this folder
377 */
CheckExternalTemplateDerivations(folder_info * folder)378 BOOL template_service_provider::CheckExternalTemplateDerivations(folder_info *folder)
379 {
380 int active_display;
381 folder_info *folder_item;;
382 int derived_widgets;
383
384 widget_info *info = folder->GetFirstChildWidget();
385 active_display = GetProjectView()->GetActiveDisplay();
386
387 /* Go through the child list to see there's template or not. */
388 while (info)
389 {
390 if (info->is_template)
391 {
392 derived_widgets = 0;
393
394 /* Count total derived_widgets.*/
395 folder_item = GetOpenProject()->mDisplays[active_display].GetFirstChildFolder();
396 while (folder_item)
397 {
398 if (folder_item != folder)
399 {
400 //count derived widgets outside the current folder
401 CountDerivedWidgets(folder_item->GetFirstChildWidget(), info, derived_widgets);
402 }
403 folder_item = folder_item->GetNextFolder();
404 }
405
406 /* go to next child if total derived_widgets is 0. */
407 if (derived_widgets != 0)
408 {
409 return FALSE;
410 }
411 }
412 info = info->GetNextWidgetInfo();
413 }
414 return TRUE;
415 }
416
417 ///////////////////////////////////////////////////////////////////////////////
418 // Count widgets that are derived from a given base
CountDerivedWidgets(widget_info * base_info)419 int template_service_provider::CountDerivedWidgets(widget_info *base_info)
420 {
421 int active_display;
422 folder_info *folder;
423 int derived_widgets = 0;
424
425 active_display = GetProjectView()->GetActiveDisplay();
426 folder = GetOpenProject()->mDisplays[active_display].GetFirstChildFolder();
427
428 while (folder)
429 {
430 CountDerivedWidgets(folder->GetFirstChildWidget(), base_info, derived_widgets);
431 folder = folder->GetNextFolder();
432 }
433
434 return derived_widgets;
435 }
436
437 ///////////////////////////////////////////////////////////////////////////////
CountDerivedWidgets(widget_info * start,widget_info * base_info,int & count)438 void template_service_provider::CountDerivedWidgets(widget_info *start, widget_info *base_info, int &count)
439 {
440 widget_info *child;
441 widget_info *next;
442
443 while (start)
444 {
445 next = start->GetNextWidgetInfo();
446
447 if (start->base_name == base_info->app_name)
448 {
449 count++;
450 }
451 else
452 {
453 child = start->GetChildWidgetInfo();
454
455 if (child)
456 {
457 CountDerivedWidgets(child, base_info, count);
458 }
459 }
460
461 start = next;
462 }
463 }
464
465 ///////////////////////////////////////////////////////////////////////////////
CheckRenameTemplate(CString & old_name,CString * new_name)466 void template_service_provider::CheckRenameTemplate(CString &old_name, CString *new_name)
467 {
468 int active_display;
469 folder_info *folder;
470
471 active_display = GetProjectView()->GetActiveDisplay();
472 folder = GetOpenProject()->mDisplays[active_display].GetFirstChildFolder();
473 while (folder)
474 {
475 CheckRenameTemplate(folder->GetFirstChildWidget(), old_name, new_name);
476 folder = folder->GetNextFolder();
477 }
478
479 }
480
481 ///////////////////////////////////////////////////////////////////////////////
CheckRenameTemplate(widget_info * start,CString & old_name,CString * new_name)482 void template_service_provider::CheckRenameTemplate(widget_info *start, CString &old_name, CString *new_name)
483 {
484 widget_info *child;
485
486 while (start)
487 {
488 if (start->base_name == old_name)
489 {
490 start->base_name = *new_name;
491 }
492
493 child = start->GetChildWidgetInfo();
494
495 if (child)
496 {
497 CheckRenameTemplate(child, old_name, new_name);
498 }
499
500 start = start->GetNextWidgetInfo();
501 }
502 }
503
504 ///////////////////////////////////////////////////////////////////////////////
RebuildDerivedWidgets(widget_info * start,CString & base_name)505 void template_service_provider::RebuildDerivedWidgets(widget_info *start, CString &base_name)
506 {
507 GX_WIDGET *parent;
508
509 while (start)
510 {
511 if ((start->base_name == base_name) && start->widget)
512 {
513 parent = start->widget->gx_widget_parent;
514 _gx_widget_detach(start->widget);
515
516 widget_factory::CleanupWidgets(start, TRUE, FALSE);
517 widget_factory::GenerateWidgets(parent, start, TRUE, FALSE);
518
519 // if this widget is also a template, check for any higher level derivations:
520 if (start->is_template)
521 {
522 RebuildDerivedWidgets(start);
523 }
524 }
525 if (start->GetChildWidgetInfo())
526 {
527 RebuildDerivedWidgets(start->GetChildWidgetInfo(), base_name);
528 }
529 start = start->GetNextWidgetInfo();
530 }
531 }
532
533
534 ///////////////////////////////////////////////////////////////////////////////
RebuildDerivedWidgets(widget_info * base_info)535 void template_service_provider::RebuildDerivedWidgets(widget_info *base_info)
536 {
537 int active_display;
538 folder_info *folder;
539 widget_info *info;
540
541 active_display = GetProjectView()->GetActiveDisplay();
542
543 folder = GetOpenProject()->mDisplays[active_display].GetFirstChildFolder();
544 while (folder)
545 {
546 info = folder->GetFirstChildWidget();
547 RebuildDerivedWidgets(info, base_info->app_name);
548 folder = folder->GetNextFolder();
549 }
550 }
551