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