mirror of
https://github.com/azure-rtos/guix.git
synced 2025-02-04 07:13:17 +08:00
551 lines
17 KiB
C++
551 lines
17 KiB
C++
|
|
#include "studiox_includes.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
//CArray<template_info *> template_service_provider::base_info_list;
|
|
|
|
extern "C" {
|
|
extern GX_DISPLAY target_win_display;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template_service_provider::template_service_provider()
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template_service_provider::~template_service_provider()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CString template_service_provider::GetVarDeclaration()
|
|
{
|
|
/* For derived widgets, the screen_generator installs and instance
|
|
of the base widget control block. Nothing to do here.
|
|
*/
|
|
return CString("");
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CString template_service_provider::DeclarePropertiesStruct()
|
|
{
|
|
CString out(""
|
|
"typedef struct\n"
|
|
"{\n"
|
|
" GX_CONST GX_STUDIO_WIDGET *base_info;\n"
|
|
" UINT (*base_create_function) (GX_CONST struct GX_STUDIO_WIDGET_STRUCT *, GX_WIDGET *, GX_WIDGET *);\n"
|
|
" GX_RECTANGLE size;\n"
|
|
"} GX_TEMPLATE_PROPERTIES;\n\n");
|
|
return out;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CString template_service_provider::WriteExtendedProperties(screen_generator *gen, CString &prefix, widget_info *info)
|
|
{
|
|
/* derived class should write extended properties of it's base */
|
|
CString out;
|
|
widget_service_provider *bp = GetBaseProvider(info);
|
|
widget_info *base = GetBaseInfo(info);
|
|
studiox_project *project = GetOpenProject();
|
|
|
|
if (project && base && bp)
|
|
{
|
|
widget_info *parent = project->FindParentInfo(base);
|
|
|
|
CString parent_name = _T("");
|
|
|
|
if (parent)
|
|
{
|
|
parent_name = parent->app_name;
|
|
}
|
|
|
|
CString temp = prefix + info->app_name;
|
|
out.Format(_T("GX_TEMPLATE_PROPERTIES %s_properties =\n{\n"), temp);
|
|
|
|
if (parent_name.IsEmpty())
|
|
{
|
|
temp.Format(_T(" &%s%s_define, /* base info */\n"), gen->GetScreenNamePrefix(), base->app_name);
|
|
}
|
|
else
|
|
{
|
|
temp.Format(_T(" %s_%s_define, /* base info */\n"), parent_name, base->app_name);
|
|
}
|
|
out += temp;
|
|
temp.Format(_T(" %s, /* base create function */\n"), bp->GetCreateFromDefFunctionName());
|
|
out += temp;
|
|
|
|
temp.Format(_T(" {%d, %d, %d, %d} /* widget size */\n};\n"),
|
|
info->size.gx_rectangle_left,
|
|
info->size.gx_rectangle_top,
|
|
info->size.gx_rectangle_right,
|
|
info->size.gx_rectangle_bottom);
|
|
out += temp;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CString template_service_provider::GetCreateFromDefFunctionName()
|
|
{
|
|
return CString("gx_studio_template_create");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
CString template_service_provider::GetCreateFromDefFunction(int version)
|
|
{
|
|
studiox_project *project = GetOpenProject();
|
|
CString out("");
|
|
MakeCreatePreamble("template", version, out);
|
|
|
|
out += "{\n"
|
|
" UINT status = GX_SUCCESS;\n"
|
|
" GX_STUDIO_WIDGET derived;\n"
|
|
" GX_TEMPLATE_PROPERTIES *props = (GX_TEMPLATE_PROPERTIES *) info->properties;\n\n"
|
|
" /* create base widget and children */ \n"
|
|
" derived = *props->base_info;\n"
|
|
" derived.widget_id = info->widget_id;\n"
|
|
" derived.widget_name = info->widget_name;\n"
|
|
"\n"
|
|
" if (info->style & GX_STYLE_ENABLED)\n"
|
|
" {\n"
|
|
" derived.style |= GX_STYLE_ENABLED;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" derived.style &= ~GX_STYLE_ENABLED;\n"
|
|
" }\n"
|
|
" if (info->status & GX_STATUS_ACCEPTS_FOCUS)\n"
|
|
" {\n"
|
|
" derived.status |= GX_STATUS_ACCEPTS_FOCUS;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" derived.status &= ~GX_STATUS_ACCEPTS_FOCUS;\n"
|
|
" }\n\n";
|
|
|
|
if (project->mHeader.guix_version > 50206)
|
|
{
|
|
|
|
out += " #if defined(GX_WIDGET_USER_DATA)\n"
|
|
" derived.user_data = info->user_data;\n"
|
|
" #endif\n\n";
|
|
}
|
|
|
|
out += " control_block = gx_studio_widget_create((GX_BYTE *) control_block, &derived, parent);\n"
|
|
" if (control_block)\n"
|
|
" {\n"
|
|
" if (info->style & GX_STYLE_DYNAMICALLY_ALLOCATED)\n"
|
|
" {\n"
|
|
" control_block->gx_widget_status |= GX_STATUS_DYNAMICALLY_ALLOCATED;\n"
|
|
" }\n"
|
|
" if (derived.size.gx_rectangle_left != info->size.gx_rectangle_left ||\n"
|
|
" derived.size.gx_rectangle_top != info->size.gx_rectangle_top)\n"
|
|
" {\n"
|
|
" gx_widget_shift(control_block,\n"
|
|
" info->size.gx_rectangle_left - derived.size.gx_rectangle_left,\n"
|
|
" info->size.gx_rectangle_top - derived.size.gx_rectangle_top, GX_FALSE);\n"
|
|
" }\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" status = GX_FAILURE;\n"
|
|
" }\n"
|
|
" return status;\n"
|
|
"}\n";
|
|
return out;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
widget_info *template_service_provider::CreateNewInstance(GX_WIDGET *parent)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
widget_info *template_service_provider::CreateNewInstance(GX_WIDGET *parent, widget_info *base)
|
|
{
|
|
GX_RECTANGLE size = base->size;
|
|
|
|
widget_info *derived_info = new widget_info;
|
|
*derived_info = *base;
|
|
|
|
gx_utility_rectangle_center(&size, &parent->gx_widget_size);
|
|
derived_info->size = size;
|
|
|
|
derived_info->app_name = CString("derived");
|
|
widget_factory::CreateUniqueAppNames(derived_info);
|
|
|
|
derived_info->widget = NULL;
|
|
derived_info->SetChildWidgetInfo(NULL);
|
|
derived_info->SetNextWidgetInfo(NULL);
|
|
derived_info->basetype = GX_TYPE_TEMPLATE;
|
|
derived_info->is_template = FALSE;
|
|
derived_info->ewi.template_display = GetProjectView()->GetActiveDisplay();
|
|
derived_info->base_name = base->app_name;
|
|
|
|
GX_WIDGET *derived = GenerateFromInfo(parent, derived_info);
|
|
derived_info->widget = derived;
|
|
return derived_info;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
GX_WIDGET *template_service_provider::BuildBaseWidget(GX_WIDGET *parent, widget_info *info, GX_BOOL add_children)
|
|
{
|
|
GX_WIDGET *template_instance = NULL;
|
|
|
|
if (widget_factory::FindBaseName(info->base_name))
|
|
{
|
|
|
|
widget_service_provider *pp = widget_factory::GetServiceProvider(info->basetype);
|
|
|
|
if (pp)
|
|
{
|
|
/* generate an instance of this template base */
|
|
template_instance = pp->GenerateFromInfo(parent, info);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
widget_info* base_info = GetBaseInfo(info);
|
|
|
|
if (base_info)
|
|
{
|
|
// this template is based on another, start by building the base for this
|
|
// template:
|
|
template_instance = BuildBaseWidget(parent, base_info, TRUE);
|
|
}
|
|
}
|
|
|
|
if (template_instance)
|
|
{
|
|
/* move the template instance to the correct position */
|
|
if (template_instance->gx_widget_size.gx_rectangle_left != info->size.gx_rectangle_left ||
|
|
template_instance->gx_widget_size.gx_rectangle_top != info->size.gx_rectangle_top)
|
|
{
|
|
_gx_widget_shift(template_instance,
|
|
info->size.gx_rectangle_left - template_instance->gx_widget_size.gx_rectangle_left,
|
|
info->size.gx_rectangle_top - template_instance->gx_widget_size.gx_rectangle_top, GX_TRUE);
|
|
|
|
info->size = template_instance->gx_widget_size;
|
|
}
|
|
|
|
if (add_children)
|
|
{
|
|
/* generate children of this template instance */
|
|
if (info->GetChildWidgetInfo())
|
|
{
|
|
widget_factory::GenerateWidgets(template_instance, info->GetChildWidgetInfo(), FALSE);
|
|
}
|
|
}
|
|
|
|
if (info->style & GX_STYLE_ENABLED)
|
|
{
|
|
if (!(template_instance->gx_widget_style & GX_STYLE_ENABLED))
|
|
{
|
|
_gx_widget_style_add(template_instance, GX_STYLE_ENABLED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (template_instance->gx_widget_style & GX_STYLE_ENABLED)
|
|
{
|
|
_gx_widget_style_remove(template_instance, GX_STYLE_ENABLED);
|
|
}
|
|
}
|
|
}
|
|
return template_instance;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
GX_WIDGET *template_service_provider::GenerateFromInfo(GX_WIDGET *parent, widget_info *info)
|
|
{
|
|
GX_WIDGET *instance;
|
|
|
|
instance = BuildBaseWidget(parent, info, FALSE);
|
|
|
|
if (instance)
|
|
{
|
|
instance->gx_widget_name = (CHAR*)info->app_name.GetString();
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::SaveToProject(xml_writer &writer, studiox_project *project, int display, widget_info *info)
|
|
{
|
|
widget_service_provider::SaveToProject(writer, project, display, info);
|
|
widget_info *base_info = GetBaseInfo(info, project);
|
|
|
|
if (base_info)
|
|
{
|
|
if (base_info->app_name)
|
|
{
|
|
writer.WriteString("template_base", base_info->app_name);
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg("Internal Error: Template base has no name");
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::ReadFromProject(xml_reader &reader, studiox_project *project, int display, widget_info *info, ULONG valid_styles)
|
|
{
|
|
valid_styles |= 0x7fffffff;
|
|
|
|
widget_service_provider::ReadFromProject(reader, project, display, info, valid_styles);
|
|
reader.ReadString("template_base", info->base_name);
|
|
info->ewi.template_display = display;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::AssignPixelmap(widget_info *info, int index,
|
|
GX_RESOURCE_ID pixmap_id)
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::Autosize(widget_info *info)
|
|
{
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
widget_info *template_service_provider::GetBaseInfo(widget_info *derived, studiox_project *project)
|
|
{
|
|
widget_info *base = NULL;
|
|
|
|
if (!project)
|
|
{
|
|
project = GetOpenProject();
|
|
}
|
|
|
|
if (derived->app_name == derived->base_name)
|
|
{
|
|
if (derived->is_template)
|
|
{
|
|
ErrorMsg("Internal error: Template is based on itself");
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (project)
|
|
{
|
|
folder_info *folder = project->mDisplays[derived->ewi.template_display].GetFirstChildFolder();
|
|
base = project->FindWidgetInfo(folder, derived->base_name, FALSE);
|
|
}
|
|
|
|
if (base)
|
|
{
|
|
if (!base->is_template)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return base;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
widget_service_provider *template_service_provider::GetBaseProvider(widget_info *derived)
|
|
{
|
|
widget_service_provider *bp = NULL;
|
|
widget_info *base_info = GetBaseInfo(derived);
|
|
|
|
if (base_info)
|
|
{
|
|
bp = widget_factory::GetServiceProvider(base_info->basetype);
|
|
}
|
|
return bp;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* This function is called only when a folder is being deleted. Check to see
|
|
if any widgets outside of this folder are derived from a template
|
|
within this folder
|
|
*/
|
|
BOOL template_service_provider::CheckExternalTemplateDerivations(folder_info *folder)
|
|
{
|
|
int active_display;
|
|
folder_info *folder_item;;
|
|
int derived_widgets;
|
|
|
|
widget_info *info = folder->GetFirstChildWidget();
|
|
active_display = GetProjectView()->GetActiveDisplay();
|
|
|
|
/* Go through the child list to see there's template or not. */
|
|
while (info)
|
|
{
|
|
if (info->is_template)
|
|
{
|
|
derived_widgets = 0;
|
|
|
|
/* Count total derived_widgets.*/
|
|
folder_item = GetOpenProject()->mDisplays[active_display].GetFirstChildFolder();
|
|
while (folder_item)
|
|
{
|
|
if (folder_item != folder)
|
|
{
|
|
//count derived widgets outside the current folder
|
|
CountDerivedWidgets(folder_item->GetFirstChildWidget(), info, derived_widgets);
|
|
}
|
|
folder_item = folder_item->GetNextFolder();
|
|
}
|
|
|
|
/* go to next child if total derived_widgets is 0. */
|
|
if (derived_widgets != 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
info = info->GetNextWidgetInfo();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Count widgets that are derived from a given base
|
|
int template_service_provider::CountDerivedWidgets(widget_info *base_info)
|
|
{
|
|
int active_display;
|
|
folder_info *folder;
|
|
int derived_widgets = 0;
|
|
|
|
active_display = GetProjectView()->GetActiveDisplay();
|
|
folder = GetOpenProject()->mDisplays[active_display].GetFirstChildFolder();
|
|
|
|
while (folder)
|
|
{
|
|
CountDerivedWidgets(folder->GetFirstChildWidget(), base_info, derived_widgets);
|
|
folder = folder->GetNextFolder();
|
|
}
|
|
|
|
return derived_widgets;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::CountDerivedWidgets(widget_info *start, widget_info *base_info, int &count)
|
|
{
|
|
widget_info *child;
|
|
widget_info *next;
|
|
|
|
while (start)
|
|
{
|
|
next = start->GetNextWidgetInfo();
|
|
|
|
if (start->base_name == base_info->app_name)
|
|
{
|
|
count++;
|
|
}
|
|
else
|
|
{
|
|
child = start->GetChildWidgetInfo();
|
|
|
|
if (child)
|
|
{
|
|
CountDerivedWidgets(child, base_info, count);
|
|
}
|
|
}
|
|
|
|
start = next;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::CheckRenameTemplate(CString &old_name, CString *new_name)
|
|
{
|
|
int active_display;
|
|
folder_info *folder;
|
|
|
|
active_display = GetProjectView()->GetActiveDisplay();
|
|
folder = GetOpenProject()->mDisplays[active_display].GetFirstChildFolder();
|
|
while (folder)
|
|
{
|
|
CheckRenameTemplate(folder->GetFirstChildWidget(), old_name, new_name);
|
|
folder = folder->GetNextFolder();
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::CheckRenameTemplate(widget_info *start, CString &old_name, CString *new_name)
|
|
{
|
|
widget_info *child;
|
|
|
|
while (start)
|
|
{
|
|
if (start->base_name == old_name)
|
|
{
|
|
start->base_name = *new_name;
|
|
}
|
|
|
|
child = start->GetChildWidgetInfo();
|
|
|
|
if (child)
|
|
{
|
|
CheckRenameTemplate(child, old_name, new_name);
|
|
}
|
|
|
|
start = start->GetNextWidgetInfo();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::RebuildDerivedWidgets(widget_info *start, CString &base_name)
|
|
{
|
|
GX_WIDGET *parent;
|
|
|
|
while (start)
|
|
{
|
|
if ((start->base_name == base_name) && start->widget)
|
|
{
|
|
parent = start->widget->gx_widget_parent;
|
|
_gx_widget_detach(start->widget);
|
|
|
|
widget_factory::CleanupWidgets(start, TRUE, FALSE);
|
|
widget_factory::GenerateWidgets(parent, start, TRUE, FALSE);
|
|
|
|
// if this widget is also a template, check for any higher level derivations:
|
|
if (start->is_template)
|
|
{
|
|
RebuildDerivedWidgets(start);
|
|
}
|
|
}
|
|
if (start->GetChildWidgetInfo())
|
|
{
|
|
RebuildDerivedWidgets(start->GetChildWidgetInfo(), base_name);
|
|
}
|
|
start = start->GetNextWidgetInfo();
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void template_service_provider::RebuildDerivedWidgets(widget_info *base_info)
|
|
{
|
|
int active_display;
|
|
folder_info *folder;
|
|
widget_info *info;
|
|
|
|
active_display = GetProjectView()->GetActiveDisplay();
|
|
|
|
folder = GetOpenProject()->mDisplays[active_display].GetFirstChildFolder();
|
|
while (folder)
|
|
{
|
|
info = folder->GetFirstChildWidget();
|
|
RebuildDerivedWidgets(info, base_info->app_name);
|
|
folder = folder->GetNextFolder();
|
|
}
|
|
}
|