diff --git a/Import/GacUI.cpp b/Import/GacUI.cpp index c857e22b..7864f7ce 100644 --- a/Import/GacUI.cpp +++ b/Import/GacUI.cpp @@ -804,6 +804,24 @@ GuiControl void GuiControl::OnParentLineChanged() { + { + GuiControlSignalEventArgs arguments(boundsComposition); + arguments.controlSignal = ControlSignal::ParentLineChanged; + ControlSignalTrigerred.Execute(arguments); + } + for(vint i=0;iOnParentLineChanged(); + } + } + + void GuiControl::OnServiceAdded() + { + { + GuiControlSignalEventArgs arguments(boundsComposition); + arguments.controlSignal = ControlSignal::ServiceAdded; + ControlSignalTrigerred.Execute(arguments); + } for(vint i=0;iOnParentLineChanged(); @@ -812,7 +830,9 @@ GuiControl void GuiControl::OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget) { - RenderTargetChanged.Execute(GetNotifyEventArguments()); + GuiControlSignalEventArgs arguments(boundsComposition); + arguments.controlSignal = ControlSignal::RenderTargetChanged; + ControlSignalTrigerred.Execute(arguments); } void GuiControl::OnBeforeReleaseGraphicsHost() @@ -919,7 +939,7 @@ GuiControl { ControlThemeNameChanged.SetAssociatedComposition(boundsComposition); ControlTemplateChanged.SetAssociatedComposition(boundsComposition); - RenderTargetChanged.SetAssociatedComposition(boundsComposition); + ControlSignalTrigerred.SetAssociatedComposition(boundsComposition); VisibleChanged.SetAssociatedComposition(boundsComposition); EnabledChanged.SetAssociatedComposition(boundsComposition); VisuallyEnabledChanged.SetAssociatedComposition(boundsComposition); @@ -1261,16 +1281,34 @@ GuiControl } else if (identifier == IGuiAltActionContainer::Identifier) { - return 0; - } - else if(parent) - { - return parent->QueryService(identifier); + return nullptr; } else { - return 0; + vint index = controlServices.Keys().IndexOf(identifier); + if (index != -1) + { + return controlServices.Values()[index].Obj(); + } + + if (parent) + { + return parent->QueryService(identifier); + } } + return nullptr; + } + + bool GuiControl::AddService(const WString& identifier, Ptr value) + { + if (controlServices.Keys().Contains(identifier)) + { + return false; + } + + controlServices.Add(identifier, value); + OnServiceAdded(); + return true; } /*********************************************************************** @@ -22199,7 +22237,7 @@ GuiToolstripCommand { if (auto control = dynamic_cast(attachedRootObject)) { - control->RenderTargetChanged.Detach(renderTargetChangedHandler); + control->ControlSignalTrigerred.Detach(renderTargetChangedHandler); } else if (auto composition = dynamic_cast(attachedRootObject)) { @@ -22213,7 +22251,11 @@ GuiToolstripCommand { if (auto control = dynamic_cast(attachedRootObject)) { - renderTargetChangedHandler = control->RenderTargetChanged.AttachMethod(this, &GuiToolstripCommand::OnRenderTargetChanged); + renderTargetChangedHandler = control->ControlSignalTrigerred.AttachLambda( + [=](GuiGraphicsComposition* sender, GuiControlSignalEventArgs& arguments) + { + OnRenderTargetChanged(sender, arguments); + }); } else if (auto composition = dynamic_cast(attachedRootObject)) { @@ -32239,35 +32281,41 @@ namespace vl tempResource->AddItem(L"Document", tempResourceItem); auto tempResolver = MakePtr(tempResource, L""); + internal::ContextFreeReader reader(stream); { - vint32_t count = 0; - if (stream.Read(&count, sizeof(count)) != sizeof(count)) return nullptr; - for (vint i = 0; i < count; i++) + WString title; + vint32_t version = 0; + reader << title << version; + + if (title != L"WCF_Document" || version < 1) { - vint32_t size = 0; - if (stream.Read(&size, sizeof(size)) != sizeof(size)) return nullptr; - if (size > 0) - { - Array buffer(size); - if (stream.Read(&buffer[0], size) != size) return nullptr; - if (auto image = GetCurrentController()->ImageService()->CreateImageFromMemory(&buffer[0], buffer.Count())) - { - auto imageItem = MakePtr(); - imageItem->SetContent(L"Image", MakePtr(image, 0)); - tempResource->AddItem(L"Image_" + itow(i), imageItem); - } - } + return nullptr; } } - StreamReader streamReader(stream); - auto text = streamReader.ReadToEnd(); + WString xmlText; + reader << xmlText; List errors; - auto parser = GetParserManager()->GetParser(L"XML"); - auto xml = parser->Parse({}, text, errors); + auto xml = parser->Parse({}, xmlText, errors); if (errors.Count() > 0) return nullptr; + { + vint32_t count = 0; + reader << count; + for (vint i = 0; i < count; i++) + { + MemoryStream memoryStream; + reader << (IStream&)memoryStream; + if (auto image = GetCurrentController()->ImageService()->CreateImageFromStream(memoryStream)) + { + auto imageItem = MakePtr(); + imageItem->SetContent(L"Image", MakePtr(image, 0)); + tempResource->AddItem(L"Image_" + itow(i), imageItem); + } + } + } + auto document = DocumentModel::LoadFromXml(tempResourceItem, xml, tempResolver, errors); return document; } @@ -32279,29 +32327,42 @@ namespace vl { paragraph->Accept(&visitor); } + + internal::ContextFreeWriter writer(stream); + { + WString title = L"WCF_Document"; + vint32_t version = 1; + writer << title << version; + } + { + auto xmlText = GenerateToStream([&](StreamWriter& streamWriter) + { + auto xml = model->SaveToXml(); + XmlPrint(xml, streamWriter); + }); + writer << xmlText; + } { vint32_t count = (vint32_t)visitor.imageRuns.Count(); - stream.Write(&count, sizeof(count)); + writer << count; + FOREACH(Ptr, imageRun, visitor.imageRuns) { - stream::MemoryStream memoryStream; + MemoryStream memoryStream; if (imageRun->image) { - imageRun->image->SaveToStream(memoryStream); + auto format = imageRun->image->GetFormat(); + if (format == INativeImage::Gif) + { + format = INativeImage::Png; + } + + imageRun->image->SaveToStream(memoryStream, format); } - count = (vint32_t)memoryStream.Size(); - stream.Write(&count, sizeof(count)); - if (count > 0) - { - stream.Write(memoryStream.GetInternalBuffer(), count); - } + writer << (IStream&)memoryStream; } } - - StreamWriter streamWriter(stream); - auto xml = model->SaveToXml(); - XmlPrint(xml, streamWriter); } } } @@ -32440,7 +32501,13 @@ namespace vl if (run->image) { writer.WriteString(L"size.x) + L"\" height=\"" + itow(run->size.y) + L"\" src=\"data:image/"); - switch (run->image->GetFormat()) + auto format = run->image->GetFormat(); + if (format == INativeImage::Gif) + { + format = INativeImage::Png; + } + + switch (format) { case INativeImage::Bmp: writer.WriteString(L"bmp;base64,"); break; case INativeImage::Gif: writer.WriteString(L"gif;base64,"); break; @@ -32453,7 +32520,7 @@ namespace vl } MemoryStream memoryStream; - run->image->SaveToStream(memoryStream); + run->image->SaveToStream(memoryStream, format); memoryStream.SeekFromBegin(0); while (true) { diff --git a/Import/GacUI.h b/Import/GacUI.h index 15386d60..6e98c8ec 100644 --- a/Import/GacUI.h +++ b/Import/GacUI.h @@ -3277,11 +3277,42 @@ Predefined Events } }; + /// Control signal. + enum class ControlSignal + { + /// Render target changed. + RenderTargetChanged, + /// Render target changed. + ParentLineChanged, + /// Service added changed. + ServiceAdded, + }; + + /// Control signal event arguments. + struct GuiControlSignalEventArgs : public GuiEventArgs, public Description + { + /// The event raiser composition. + ControlSignal controlSignal = ControlSignal::ParentLineChanged; + + /// Create an event arguments with and set to null. + GuiControlSignalEventArgs() + { + } + + /// Create an event arguments with and set to a specified value. + /// The speciied value to set and . + GuiControlSignalEventArgs(GuiGraphicsComposition* composition) + :GuiEventArgs(composition) + { + } + }; + typedef GuiGraphicsEvent GuiNotifyEvent; typedef GuiGraphicsEvent GuiRequestEvent; typedef GuiGraphicsEvent GuiKeyEvent; typedef GuiGraphicsEvent GuiCharEvent; typedef GuiGraphicsEvent GuiMouseEvent; + typedef GuiGraphicsEvent GuiControlSignalEvent; /*********************************************************************** Predefined Item Events @@ -9516,6 +9547,26 @@ namespace vl namespace controls { + template + struct QueryServiceHelper; + + template + struct QueryServiceHelper::YesNoType> + { + static WString GetIdentifier() + { + return WString(T::Identifier, false); + } + }; + + template + struct QueryServiceHelper::YesNoType> + { + static WString GetIdentifier() + { + return MoveValue(T::GetIdentifier()); + } + }; /*********************************************************************** Basic Construction @@ -9533,6 +9584,7 @@ Basic Construction protected: using ControlList = collections::List; + using ControlServiceMap = collections::Dictionary>; using ControlTemplatePropertyType = TemplateProperty; private: @@ -9554,6 +9606,7 @@ Basic Construction FontProperties font; description::Value context; compositions::IGuiAltActionHost* activatingAltHost = nullptr; + ControlServiceMap controlServices; GuiControl* parent = nullptr; ControlList children; @@ -9572,6 +9625,7 @@ Basic Construction virtual void OnChildRemoved(GuiControl* control); virtual void OnParentChanged(GuiControl* oldParent, GuiControl* newParent); virtual void OnParentLineChanged(); + virtual void OnServiceAdded(); virtual void OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget); virtual void OnBeforeReleaseGraphicsHost(); virtual void UpdateVisuallyEnabled(); @@ -9597,8 +9651,8 @@ Basic Construction compositions::GuiNotifyEvent ControlThemeNameChanged; /// Control template changed event. This event will be raised when the control template is changed. compositions::GuiNotifyEvent ControlTemplateChanged; - /// Render target changed event. This event will be raised when the render target of the control is changed. - compositions::GuiNotifyEvent RenderTargetChanged; + /// Control signal trigerred. This event will be raised because of multiple reason specified in the argument. + compositions::GuiControlSignalEvent ControlSignalTrigerred; /// Visible event. This event will be raised when the visibility state of the control is changed. compositions::GuiNotifyEvent VisibleChanged; /// Enabled event. This event will be raised when the enabling state of the control is changed. @@ -9749,10 +9803,16 @@ Basic Construction /// The identifier. virtual IDescriptable* QueryService(const WString& identifier); + /// Add a service to this control dynamically. The added service cannot override existing services. + /// Returns true if this operation succeeded. + /// The identifier. You are suggested to fill this parameter using the value from the interface's GetIdentifier function, or will not work on this service. + /// The service. + bool AddService(const WString& identifier, Ptr value); + template T* QueryTypedService() { - return dynamic_cast(QueryService(T::Identifier)); + return dynamic_cast(QueryService(QueryServiceHelper::GetIdentifier())); } }; @@ -18225,12 +18285,6 @@ External Functions extern void GuiTableComposition_SetRows(presentation::compositions::GuiTableComposition* thisObject, vint value); extern void GuiTableComposition_SetColumns(presentation::compositions::GuiTableComposition* thisObject, vint value); extern void IGuiAltActionHost_CollectAltActions(presentation::compositions::IGuiAltActionHost* host, collections::List& actions); - - template - WString Interface_GetIdentifier() - { - return T::Identifier; - } } } } diff --git a/Import/GacUIReflection.cpp b/Import/GacUIReflection.cpp index e88e4f93..7e3d4cf1 100644 --- a/Import/GacUIReflection.cpp +++ b/Import/GacUIReflection.cpp @@ -836,7 +836,7 @@ namespace vl #define _ , #define INTERFACE_IDENTIFIER(INTERFACE)\ - CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetIdentifier, NO_PARAMETER, WString(*)(), vl::reflection::description::Interface_GetIdentifier<::INTERFACE>) + CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetIdentifier, NO_PARAMETER, WString(*)(), vl::presentation::controls::QueryServiceHelper<::INTERFACE>::GetIdentifier) /*********************************************************************** Type Declaration (Extra) @@ -1367,7 +1367,7 @@ namespace vl CLASS_MEMBER_PROPERTY_READONLY_FAST(ControlTemplateObject)\ #define INTERFACE_IDENTIFIER(INTERFACE)\ - CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetIdentifier, NO_PARAMETER, WString(*)(), vl::reflection::description::Interface_GetIdentifier<::INTERFACE>) + CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetIdentifier, NO_PARAMETER, WString(*)(), vl::presentation::controls::QueryServiceHelper<::INTERFACE>::GetIdentifier) /*********************************************************************** Type Declaration (Extra) @@ -2030,7 +2030,7 @@ Type Declaration (Class) CLASS_MEMBER_EXTERNALMETHOD(SafeDelete, NO_PARAMETER, void(GuiControl::*)(), vl::presentation::compositions::SafeDeleteControl) - CLASS_MEMBER_GUIEVENT(RenderTargetChanged) + CLASS_MEMBER_GUIEVENT(ControlSignalTrigerred) CLASS_MEMBER_PROPERTY_GUIEVENT_FAST(ControlThemeName) CLASS_MEMBER_PROPERTY_GUIEVENT_FAST(ControlTemplate) CLASS_MEMBER_PROPERTY_READONLY_FAST(BoundsComposition) @@ -2058,7 +2058,8 @@ Type Declaration (Class) CLASS_MEMBER_METHOD(SetFocus, NO_PARAMETER) CLASS_MEMBER_METHOD(DisplayTooltip, {L"location"}) CLASS_MEMBER_METHOD(CloseTooltip, NO_PARAMETER) - CLASS_MEMBER_METHOD_OVERLOAD(QueryService, {L"identifier"}, IDescriptable*(GuiControl::*)(const WString&)) + CLASS_MEMBER_METHOD(QueryService, {L"identifier"}) + CLASS_MEMBER_METHOD(AddService, { L"identifier" _ L"value" }) END_CLASS_MEMBER(GuiControl) BEGIN_CLASS_MEMBER(GuiCustomControl) @@ -2318,7 +2319,6 @@ Type Declaration (Class) CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE_2(GuiMenu, GuiControl*, owner) CLASS_MEMBER_METHOD(UpdateMenuService, NO_PARAMETER) - CLASS_MEMBER_METHOD(QueryService, {L"identifier"}) END_CLASS_MEMBER(GuiMenu) BEGIN_CLASS_MEMBER(GuiMenuBar) @@ -3164,6 +3164,18 @@ Type Declaration CLASS_MEMBER_FIELD(nonClient) END_CLASS_MEMBER(GuiMouseEventArgs) + BEGIN_ENUM_ITEM(ControlSignal) + ENUM_CLASS_ITEM(RenderTargetChanged) + ENUM_CLASS_ITEM(ParentLineChanged) + ENUM_CLASS_ITEM(ServiceAdded) + END_ENUM_ITEM(ControlSignal) + + BEGIN_CLASS_MEMBER(GuiControlSignalEventArgs) + CLASS_MEMBER_BASE(GuiEventArgs) + + CLASS_MEMBER_FIELD(controlSignal) + END_CLASS_MEMBER(GuiControlSignalEventArgs) + BEGIN_CLASS_MEMBER(GuiItemEventArgs) CLASS_MEMBER_BASE(GuiEventArgs) EVENTARGS_CONSTRUCTOR(GuiItemEventArgs) diff --git a/Import/GacUIReflection.h b/Import/GacUIReflection.h index 0a11a99d..f20f9126 100644 --- a/Import/GacUIReflection.h +++ b/Import/GacUIReflection.h @@ -266,6 +266,8 @@ Type List (Events) F(presentation::compositions::GuiKeyEventArgs)\ F(presentation::compositions::GuiCharEventArgs)\ F(presentation::compositions::GuiMouseEventArgs)\ + F(presentation::compositions::ControlSignal)\ + F(presentation::compositions::GuiControlSignalEventArgs)\ F(presentation::compositions::GuiItemEventArgs)\ F(presentation::compositions::GuiItemMouseEventArgs)\ F(presentation::compositions::GuiNodeEventArgs)\ diff --git a/Import/GacUIWindows.cpp b/Import/GacUIWindows.cpp index 7a3a5698..6ea532ed 100644 --- a/Import/GacUIWindows.cpp +++ b/Import/GacUIWindows.cpp @@ -13306,6 +13306,48 @@ WindowsImage } } + void CopyMetadataBody(IWICMetadataQueryReader* reader, IWICMetadataQueryWriter* writer, const WString& prefix) + { + IEnumString* enumString = nullptr; + HRESULT hr = reader->GetEnumerator(&enumString); + if (enumString) + { + while (true) + { + LPOLESTR metadataName = nullptr; + ULONG fetched = 0; + hr = enumString->Next(1, &metadataName, &fetched); + if (hr != S_OK) break; + if (fetched == 0) break; + + PROPVARIANT metadataValue; + PropVariantInit(&metadataValue); + hr = reader->GetMetadataByName(metadataName, &metadataValue); + if (hr == S_OK) + { + if (metadataValue.vt == VT_UNKNOWN && metadataValue.punkVal) + { + IWICMetadataQueryReader* embeddedReader = nullptr; + hr = metadataValue.punkVal->QueryInterface(&embeddedReader); + if (embeddedReader) + { + CopyMetadataBody(embeddedReader, writer, prefix + metadataName); + embeddedReader->Release(); + } + } + else + { + hr = writer->SetMetadataByName((prefix + metadataName).Buffer(), &metadataValue); + } + hr = PropVariantClear(&metadataValue); + } + + CoTaskMemFree(metadataName); + } + enumString->Release(); + } + } + template void CopyMetadata(TDecoder* decoder, TEncoder* encoder) { @@ -13315,30 +13357,7 @@ WindowsImage hr = encoder->GetMetadataQueryWriter(&writer); if (reader && writer) { - IEnumString* enumString = nullptr; - hr = reader->GetEnumerator(&enumString); - if (enumString) - { - while (true) - { - LPOLESTR metadataName = nullptr; - ULONG fetched = 0; - hr = enumString->Next(0, &metadataName, &fetched); - if (hr != S_OK) break; - if (fetched == 0) break; - - PROPVARIANT metadataValue; - hr = reader->GetMetadataByName(metadataName, &metadataValue); - if (hr == S_OK) - { - hr = writer->SetMetadataByName(metadataName, &metadataValue); - hr = PropVariantClear(&metadataValue); - } - - CoTaskMemFree(metadataName); - } - enumString->Release(); - } + CopyMetadataBody(reader, writer, WString::Empty); } if (reader) reader->Release(); if (writer) writer->Release(); @@ -13386,6 +13405,8 @@ WindowsImage auto factory = GetWICImagingFactory(); GUID formatGUID; HRESULT hr; + + bool sameFormat = formatType == INativeImage::Unknown || formatType == GetFormat(); if (formatType == INativeImage::Unknown) { hr = bitmapDecoder->GetContainerFormat(&formatGUID); @@ -13467,7 +13488,11 @@ WindowsImage source->Release(); } } - CopyMetadata(bitmapDecoder.Obj(), bitmapEncoder); + + if (sameFormat) + { + CopyMetadata(bitmapDecoder.Obj(), bitmapEncoder); + } UINT frameCount = 0; bitmapDecoder->GetFrameCount(&frameCount); @@ -13480,7 +13505,10 @@ WindowsImage if (frameDecode && frameEncode) { hr = frameEncode->Initialize(NULL); - CopyMetadata(frameDecode, frameEncode); + if (sameFormat) + { + CopyMetadata(frameDecode, frameEncode); + } hr = frameEncode->WriteSource(frameDecode, NULL); hr = frameEncode->Commit(); } diff --git a/Import/VlppWorkflowRuntime.cpp b/Import/VlppWorkflowRuntime.cpp index 282fdff8..53c74384 100644 --- a/Import/VlppWorkflowRuntime.cpp +++ b/Import/VlppWorkflowRuntime.cpp @@ -5418,10 +5418,18 @@ WfTypeImpl { FOREACH(Ptr, td, classes) { + if (td->GetBaseTypeDescriptorCount() == 0) + { + td->AddBaseType(description::GetTypeDescriptor()); + } manager->SetTypeDescriptor(td->GetTypeName(), td); } FOREACH(Ptr, td, interfaces) { + if (td->GetBaseTypeDescriptorCount() == 0) + { + td->AddBaseType(description::GetTypeDescriptor()); + } manager->SetTypeDescriptor(td->GetTypeName(), td); } FOREACH(Ptr, td, structs) diff --git a/Import/VlppWorkflowRuntime.h b/Import/VlppWorkflowRuntime.h index a41ccf1d..33cdfcad 100644 --- a/Import/VlppWorkflowRuntime.h +++ b/Import/VlppWorkflowRuntime.h @@ -730,7 +730,7 @@ Instance void InstallBaseObject(ITypeDescriptor* td, Value& value); }; - class WfInterfaceInstance : public Object, public reflection::Description + class WfInterfaceInstance : public Object, public reflection::IDescriptable, public reflection::Description { typedef reflection::description::ITypeDescriptor ITypeDescriptor; typedef reflection::description::IMethodInfo IMethodInfo; diff --git a/Tools/CppMerge.exe b/Tools/CppMerge.exe index d5e2773c..06544f99 100644 Binary files a/Tools/CppMerge.exe and b/Tools/CppMerge.exe differ diff --git a/Tools/GacGen32.exe b/Tools/GacGen32.exe index 6bbb8746..0b2505a0 100644 Binary files a/Tools/GacGen32.exe and b/Tools/GacGen32.exe differ diff --git a/Tools/GacGen64.exe b/Tools/GacGen64.exe index e5915e7d..30754748 100644 Binary files a/Tools/GacGen64.exe and b/Tools/GacGen64.exe differ diff --git a/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x64 b/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x64 index 00b4c828..f8883182 100644 Binary files a/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x64 and b/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x64 differ diff --git a/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x86 b/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x86 index 7b4a71e9..29039236 100644 Binary files a/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x86 and b/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x86 differ