Update release

This commit is contained in:
vczh
2025-08-31 22:44:06 -07:00
parent 9c91710e2d
commit 3f0e43b724
19 changed files with 1447 additions and 865 deletions
+32 -32
View File
@@ -896,15 +896,15 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
::vl::__vwsn::This(this->self)->SetClientSize([&](){ ::vl::presentation::Size __vwsn_temp__; __vwsn_temp__.x = static_cast<::vl::vint>(1920); __vwsn_temp__.y = static_cast<::vl::vint>(1080); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->self)->SetClientSize([&](){ ::vl::presentation::Size __vwsn_temp__; __vwsn_temp__.x = static_cast<::vl::vint>(1920); __vwsn_temp__.y = static_cast<::vl::vint>(1080); return __vwsn_temp__; }());
} }
(this->__vwsn_precompile_0 = new ::vl::presentation::compositions::GuiTableComposition()); (this->__vwsn_precompile_0 = new ::vl::presentation::compositions::GuiTableComposition());
{
::vl::__vwsn::This(this->__vwsn_precompile_0)->SetMinSizeLimitation(::vl::presentation::compositions::GuiGraphicsComposition::MinSizeLimitation::LimitToElementAndChildren);
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_0)->SetCellPadding(static_cast<::vl::vint>(5)); ::vl::__vwsn::This(this->__vwsn_precompile_0)->SetCellPadding(static_cast<::vl::vint>(5));
} }
{ {
::vl::__vwsn::This(this->__vwsn_precompile_0)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->__vwsn_precompile_0)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }());
} }
{
::vl::__vwsn::This(this->__vwsn_precompile_0)->SetMinSizeLimitation(::vl::presentation::compositions::GuiGraphicsComposition::MinSizeLimitation::LimitToElementAndChildren);
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_0)->SetRowsAndColumns(static_cast<::vl::vint>(1), static_cast<::vl::vint>(4)); ::vl::__vwsn::This(this->__vwsn_precompile_0)->SetRowsAndColumns(static_cast<::vl::vint>(1), static_cast<::vl::vint>(4));
::vl::__vwsn::This(this->__vwsn_precompile_0)->SetRowOption(static_cast<::vl::vint>(0), [&](){ ::vl::presentation::compositions::GuiCellOption __vwsn_temp__; __vwsn_temp__.composeType = ::vl::presentation::compositions::GuiCellOption::ComposeType::Percentage; __vwsn_temp__.percentage = static_cast<double>(1.0); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->__vwsn_precompile_0)->SetRowOption(static_cast<::vl::vint>(0), [&](){ ::vl::presentation::compositions::GuiCellOption __vwsn_temp__; __vwsn_temp__.composeType = ::vl::presentation::compositions::GuiCellOption::ComposeType::Percentage; __vwsn_temp__.percentage = static_cast<double>(1.0); return __vwsn_temp__; }());
@@ -938,6 +938,12 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
{ {
::vl::__vwsn::This(this->treeViewFileNodes)->SetChildrenProperty(vl::Func(::vl_workflow_global::__vwsnf1_GuiUnitTestSnapshotViewer_gaclib_controls_UnitTestSnapshotViewerWindowConstructor___vwsn_gaclib_controls_UnitTestSnapshotViewerWindow_Initialize_(this))); ::vl::__vwsn::This(this->treeViewFileNodes)->SetChildrenProperty(vl::Func(::vl_workflow_global::__vwsnf1_GuiUnitTestSnapshotViewer_gaclib_controls_UnitTestSnapshotViewerWindowConstructor___vwsn_gaclib_controls_UnitTestSnapshotViewerWindow_Initialize_(this)));
} }
{
::vl::__vwsn::This(this->treeViewFileNodes)->SetHorizontalAlwaysVisible(false);
}
{
::vl::__vwsn::This(this->treeViewFileNodes)->SetVerticalAlwaysVisible(false);
}
{ {
::vl::__vwsn::This(this->treeViewFileNodes)->SetTextProperty(vl::Func(::vl_workflow_global::__vwsnf2_GuiUnitTestSnapshotViewer_gaclib_controls_UnitTestSnapshotViewerWindowConstructor___vwsn_gaclib_controls_UnitTestSnapshotViewerWindow_Initialize_(this))); ::vl::__vwsn::This(this->treeViewFileNodes)->SetTextProperty(vl::Func(::vl_workflow_global::__vwsnf2_GuiUnitTestSnapshotViewer_gaclib_controls_UnitTestSnapshotViewerWindowConstructor___vwsn_gaclib_controls_UnitTestSnapshotViewerWindow_Initialize_(this)));
} }
@@ -945,12 +951,6 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
{ {
::vl::__vwsn::This(this->__vwsn_precompile_4)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->__vwsn_precompile_4)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }());
} }
{
::vl::__vwsn::This(this->treeViewFileNodes)->SetHorizontalAlwaysVisible(false);
}
{
::vl::__vwsn::This(this->treeViewFileNodes)->SetVerticalAlwaysVisible(false);
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_3)->AddChild(static_cast<::vl::presentation::compositions::GuiGraphicsComposition*>(::vl::__vwsn::This(this->treeViewFileNodes)->GetBoundsComposition())); ::vl::__vwsn::This(this->__vwsn_precompile_3)->AddChild(static_cast<::vl::presentation::compositions::GuiGraphicsComposition*>(::vl::__vwsn::This(this->treeViewFileNodes)->GetBoundsComposition()));
} }
@@ -974,6 +974,12 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
(this->textListFrames = new ::vl::presentation::controls::GuiBindableTextList(::vl::presentation::theme::ThemeName::TextList)); (this->textListFrames = new ::vl::presentation::controls::GuiBindableTextList(::vl::presentation::theme::ThemeName::TextList));
::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"textListFrames"), ::vl::__vwsn::Box(this->textListFrames)); ::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"textListFrames"), ::vl::__vwsn::Box(this->textListFrames));
} }
{
::vl::__vwsn::This(this->textListFrames)->SetHorizontalAlwaysVisible(false);
}
{
::vl::__vwsn::This(this->textListFrames)->SetVerticalAlwaysVisible(false);
}
{ {
::vl::__vwsn::This(this->textListFrames)->SetTextProperty(vl::Func(::vl_workflow_global::__vwsnf3_GuiUnitTestSnapshotViewer_gaclib_controls_UnitTestSnapshotViewerWindowConstructor___vwsn_gaclib_controls_UnitTestSnapshotViewerWindow_Initialize_(this))); ::vl::__vwsn::This(this->textListFrames)->SetTextProperty(vl::Func(::vl_workflow_global::__vwsnf3_GuiUnitTestSnapshotViewer_gaclib_controls_UnitTestSnapshotViewerWindowConstructor___vwsn_gaclib_controls_UnitTestSnapshotViewerWindow_Initialize_(this)));
} }
@@ -981,12 +987,6 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
{ {
::vl::__vwsn::This(this->__vwsn_precompile_9)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->__vwsn_precompile_9)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }());
} }
{
::vl::__vwsn::This(this->textListFrames)->SetHorizontalAlwaysVisible(false);
}
{
::vl::__vwsn::This(this->textListFrames)->SetVerticalAlwaysVisible(false);
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_8)->AddChild(static_cast<::vl::presentation::controls::GuiControl*>(this->textListFrames)); ::vl::__vwsn::This(this->__vwsn_precompile_8)->AddChild(static_cast<::vl::presentation::controls::GuiControl*>(this->textListFrames));
} }
@@ -1021,16 +1021,16 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
(this->scRendering = new ::vl::presentation::controls::GuiScrollContainer(::vl::presentation::theme::ThemeName::ScrollView)); (this->scRendering = new ::vl::presentation::controls::GuiScrollContainer(::vl::presentation::theme::ThemeName::ScrollView));
::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"scRendering"), ::vl::__vwsn::Box(this->scRendering)); ::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"scRendering"), ::vl::__vwsn::Box(this->scRendering));
} }
(this->__vwsn_precompile_14 = ::vl::__vwsn::This(this->scRendering)->GetBoundsComposition());
{
::vl::__vwsn::This(this->__vwsn_precompile_14)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(5); __vwsn_temp__.top = static_cast<::vl::vint>(5); __vwsn_temp__.right = static_cast<::vl::vint>(5); __vwsn_temp__.bottom = static_cast<::vl::vint>(5); return __vwsn_temp__; }());
}
{ {
::vl::__vwsn::This(this->scRendering)->SetHorizontalAlwaysVisible(false); ::vl::__vwsn::This(this->scRendering)->SetHorizontalAlwaysVisible(false);
} }
{ {
::vl::__vwsn::This(this->scRendering)->SetVerticalAlwaysVisible(false); ::vl::__vwsn::This(this->scRendering)->SetVerticalAlwaysVisible(false);
} }
(this->__vwsn_precompile_14 = ::vl::__vwsn::This(this->scRendering)->GetBoundsComposition());
{
::vl::__vwsn::This(this->__vwsn_precompile_14)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(5); __vwsn_temp__.top = static_cast<::vl::vint>(5); __vwsn_temp__.right = static_cast<::vl::vint>(5); __vwsn_temp__.bottom = static_cast<::vl::vint>(5); return __vwsn_temp__; }());
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_13)->AddChild(static_cast<::vl::presentation::controls::GuiControl*>(this->scRendering)); ::vl::__vwsn::This(this->__vwsn_precompile_13)->AddChild(static_cast<::vl::presentation::controls::GuiControl*>(this->scRendering));
} }
@@ -1047,16 +1047,16 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
{ {
(this->__vwsn_precompile_16 = new ::vl::presentation::controls::GuiMultilineTextBox(::vl::presentation::theme::ThemeName::MultilineTextBox)); (this->__vwsn_precompile_16 = new ::vl::presentation::controls::GuiMultilineTextBox(::vl::presentation::theme::ThemeName::MultilineTextBox));
} }
(this->__vwsn_precompile_17 = ::vl::__vwsn::This(this->__vwsn_precompile_16)->GetBoundsComposition());
{
::vl::__vwsn::This(this->__vwsn_precompile_17)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(5); __vwsn_temp__.top = static_cast<::vl::vint>(5); __vwsn_temp__.right = static_cast<::vl::vint>(5); __vwsn_temp__.bottom = static_cast<::vl::vint>(5); return __vwsn_temp__; }());
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_16)->SetHorizontalAlwaysVisible(false); ::vl::__vwsn::This(this->__vwsn_precompile_16)->SetHorizontalAlwaysVisible(false);
} }
{ {
::vl::__vwsn::This(this->__vwsn_precompile_16)->SetVerticalAlwaysVisible(false); ::vl::__vwsn::This(this->__vwsn_precompile_16)->SetVerticalAlwaysVisible(false);
} }
(this->__vwsn_precompile_17 = ::vl::__vwsn::This(this->__vwsn_precompile_16)->GetBoundsComposition());
{
::vl::__vwsn::This(this->__vwsn_precompile_17)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(5); __vwsn_temp__.top = static_cast<::vl::vint>(5); __vwsn_temp__.right = static_cast<::vl::vint>(5); __vwsn_temp__.bottom = static_cast<::vl::vint>(5); return __vwsn_temp__; }());
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_15)->AddChild(static_cast<::vl::presentation::controls::GuiControl*>(this->__vwsn_precompile_16)); ::vl::__vwsn::This(this->__vwsn_precompile_15)->AddChild(static_cast<::vl::presentation::controls::GuiControl*>(this->__vwsn_precompile_16));
} }
@@ -1073,16 +1073,16 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
{ {
(this->__vwsn_precompile_19 = new ::vl::presentation::controls::GuiMultilineTextBox(::vl::presentation::theme::ThemeName::MultilineTextBox)); (this->__vwsn_precompile_19 = new ::vl::presentation::controls::GuiMultilineTextBox(::vl::presentation::theme::ThemeName::MultilineTextBox));
} }
(this->__vwsn_precompile_20 = ::vl::__vwsn::This(this->__vwsn_precompile_19)->GetBoundsComposition());
{
::vl::__vwsn::This(this->__vwsn_precompile_20)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(5); __vwsn_temp__.top = static_cast<::vl::vint>(5); __vwsn_temp__.right = static_cast<::vl::vint>(5); __vwsn_temp__.bottom = static_cast<::vl::vint>(5); return __vwsn_temp__; }());
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_19)->SetHorizontalAlwaysVisible(false); ::vl::__vwsn::This(this->__vwsn_precompile_19)->SetHorizontalAlwaysVisible(false);
} }
{ {
::vl::__vwsn::This(this->__vwsn_precompile_19)->SetVerticalAlwaysVisible(false); ::vl::__vwsn::This(this->__vwsn_precompile_19)->SetVerticalAlwaysVisible(false);
} }
(this->__vwsn_precompile_20 = ::vl::__vwsn::This(this->__vwsn_precompile_19)->GetBoundsComposition());
{
::vl::__vwsn::This(this->__vwsn_precompile_20)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(5); __vwsn_temp__.top = static_cast<::vl::vint>(5); __vwsn_temp__.right = static_cast<::vl::vint>(5); __vwsn_temp__.bottom = static_cast<::vl::vint>(5); return __vwsn_temp__; }());
}
{ {
::vl::__vwsn::This(this->__vwsn_precompile_18)->AddChild(static_cast<::vl::presentation::controls::GuiControl*>(this->__vwsn_precompile_19)); ::vl::__vwsn::This(this->__vwsn_precompile_18)->AddChild(static_cast<::vl::presentation::controls::GuiControl*>(this->__vwsn_precompile_19));
} }
@@ -1137,11 +1137,8 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
} }
UnitTestSnapshotViewerWindowConstructor::UnitTestSnapshotViewerWindowConstructor() UnitTestSnapshotViewerWindowConstructor::UnitTestSnapshotViewerWindowConstructor()
: ViewModel(::vl::Ptr<::gaclib_controls::IUnitTestSnapshotViewerViewModel>()) : self(static_cast<::gaclib_controls::UnitTestSnapshotViewerWindow*>(nullptr))
, self(static_cast<::gaclib_controls::UnitTestSnapshotViewerWindow*>(nullptr)) , ViewModel(::vl::Ptr<::gaclib_controls::IUnitTestSnapshotViewerViewModel>())
, treeViewFileNodes(static_cast<::vl::presentation::controls::GuiBindableTreeView*>(nullptr))
, textListFrames(static_cast<::vl::presentation::controls::GuiBindableTextList*>(nullptr))
, scRendering(static_cast<::vl::presentation::controls::GuiScrollContainer*>(nullptr))
, __vwsn_precompile_0(static_cast<::vl::presentation::compositions::GuiTableComposition*>(nullptr)) , __vwsn_precompile_0(static_cast<::vl::presentation::compositions::GuiTableComposition*>(nullptr))
, __vwsn_precompile_1(static_cast<::vl::presentation::compositions::GuiColumnSplitterComposition*>(nullptr)) , __vwsn_precompile_1(static_cast<::vl::presentation::compositions::GuiColumnSplitterComposition*>(nullptr))
, __vwsn_precompile_2(static_cast<::vl::presentation::compositions::GuiColumnSplitterComposition*>(nullptr)) , __vwsn_precompile_2(static_cast<::vl::presentation::compositions::GuiColumnSplitterComposition*>(nullptr))
@@ -1163,6 +1160,9 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor)
, __vwsn_precompile_18(static_cast<::vl::presentation::controls::GuiTabPage*>(nullptr)) , __vwsn_precompile_18(static_cast<::vl::presentation::controls::GuiTabPage*>(nullptr))
, __vwsn_precompile_19(static_cast<::vl::presentation::controls::GuiMultilineTextBox*>(nullptr)) , __vwsn_precompile_19(static_cast<::vl::presentation::controls::GuiMultilineTextBox*>(nullptr))
, __vwsn_precompile_20(static_cast<::vl::presentation::compositions::GuiBoundsComposition*>(nullptr)) , __vwsn_precompile_20(static_cast<::vl::presentation::compositions::GuiBoundsComposition*>(nullptr))
, treeViewFileNodes(static_cast<::vl::presentation::controls::GuiBindableTreeView*>(nullptr))
, textListFrames(static_cast<::vl::presentation::controls::GuiBindableTextList*>(nullptr))
, scRendering(static_cast<::vl::presentation::controls::GuiScrollContainer*>(nullptr))
{ {
} }
+4 -4
View File
@@ -153,11 +153,8 @@ namespace gaclib_controls
friend struct ::vl::reflection::description::CustomTypeDescriptorSelector<UnitTestSnapshotViewerWindowConstructor>; friend struct ::vl::reflection::description::CustomTypeDescriptorSelector<UnitTestSnapshotViewerWindowConstructor>;
#endif #endif
protected: protected:
::vl::Ptr<::gaclib_controls::IUnitTestSnapshotViewerViewModel> ViewModel;
::gaclib_controls::UnitTestSnapshotViewerWindow* self; ::gaclib_controls::UnitTestSnapshotViewerWindow* self;
::vl::presentation::controls::GuiBindableTreeView* treeViewFileNodes; ::vl::Ptr<::gaclib_controls::IUnitTestSnapshotViewerViewModel> ViewModel;
::vl::presentation::controls::GuiBindableTextList* textListFrames;
::vl::presentation::controls::GuiScrollContainer* scRendering;
::vl::presentation::compositions::GuiTableComposition* __vwsn_precompile_0; ::vl::presentation::compositions::GuiTableComposition* __vwsn_precompile_0;
::vl::presentation::compositions::GuiColumnSplitterComposition* __vwsn_precompile_1; ::vl::presentation::compositions::GuiColumnSplitterComposition* __vwsn_precompile_1;
::vl::presentation::compositions::GuiColumnSplitterComposition* __vwsn_precompile_2; ::vl::presentation::compositions::GuiColumnSplitterComposition* __vwsn_precompile_2;
@@ -179,6 +176,9 @@ namespace gaclib_controls
::vl::presentation::controls::GuiTabPage* __vwsn_precompile_18; ::vl::presentation::controls::GuiTabPage* __vwsn_precompile_18;
::vl::presentation::controls::GuiMultilineTextBox* __vwsn_precompile_19; ::vl::presentation::controls::GuiMultilineTextBox* __vwsn_precompile_19;
::vl::presentation::compositions::GuiBoundsComposition* __vwsn_precompile_20; ::vl::presentation::compositions::GuiBoundsComposition* __vwsn_precompile_20;
::vl::presentation::controls::GuiBindableTreeView* treeViewFileNodes;
::vl::presentation::controls::GuiBindableTextList* textListFrames;
::vl::presentation::controls::GuiScrollContainer* scRendering;
void __vwsn_gaclib_controls_UnitTestSnapshotViewerWindow_Initialize(::gaclib_controls::UnitTestSnapshotViewerWindow* __vwsn_this_); void __vwsn_gaclib_controls_UnitTestSnapshotViewerWindow_Initialize(::gaclib_controls::UnitTestSnapshotViewerWindow* __vwsn_this_);
public: public:
UnitTestSnapshotViewerWindowConstructor(); UnitTestSnapshotViewerWindowConstructor();
+34 -3
View File
@@ -54,6 +54,11 @@ namespace vl::presentation::unittest
} }
} }
namespace vl::presentation::GuiHostedController_UnitTestHelper
{
extern bool ExceptionOccuredUnderUnitTestReleaseMode();
}
using namespace vl; using namespace vl;
using namespace vl::collections; using namespace vl::collections;
using namespace vl::filesystem; using namespace vl::filesystem;
@@ -63,6 +68,7 @@ using namespace vl::presentation;
using namespace vl::presentation::remoteprotocol; using namespace vl::presentation::remoteprotocol;
using namespace vl::presentation::controls; using namespace vl::presentation::controls;
using namespace vl::presentation::unittest; using namespace vl::presentation::unittest;
using namespace vl::presentation::GuiHostedController_UnitTestHelper;
class UnitTestContextImpl : public Object, public virtual IUnitTestContext class UnitTestContextImpl : public Object, public virtual IUnitTestContext
{ {
@@ -362,6 +368,7 @@ void GacUIUnitTest_Start(const WString& appName, Nullable<UnitTestScreenConfig>
: &filteredProtocol : &filteredProtocol
); );
GacUIUnitTest_SetGuiMainProxy({}); GacUIUnitTest_SetGuiMainProxy({});
TEST_ASSERT(!ExceptionOccuredUnderUnitTestReleaseMode());
GacUIUnitTest_LogUI(appName, unitTestProtocol); GacUIUnitTest_LogUI(appName, unitTestProtocol);
if (!globalConfig.useDomDiff) if (!globalConfig.useDomDiff)
@@ -445,6 +452,8 @@ void GacUIUnitTest_StartAsync(const WString& appName, Nullable<UnitTestScreenCon
}); });
asyncChannelSender.WaitForStopped(); asyncChannelSender.WaitForStopped();
TEST_ASSERT(!ExceptionOccuredUnderUnitTestReleaseMode());
GacUIUnitTest_LogUI(appName, unitTestProtocol); GacUIUnitTest_LogUI(appName, unitTestProtocol);
if (!config.Value().useDomDiff) if (!config.Value().useDomDiff)
{ {
@@ -500,6 +509,16 @@ void GacUIUnitTest_Start_WithResourceAsText(const WString& appName, Nullable<Uni
#undef ERROR_MESSAGE_PREFIX #undef ERROR_MESSAGE_PREFIX
} }
void GacUIUnitTest_PrintErrors(GuiResourceError::List& errors)
{
for (auto&& error : errors)
{
TEST_PRINT(L"Error in resource: " + error.location.resourcePath);
TEST_PRINT(L" ROW: " + itow(error.position.row) + L", COLUMN: " + itow(error.position.column));
TEST_PRINT(L" REASON: " + error.message);
}
}
Ptr<GuiResource> GacUIUnitTest_CompileAndLoad(const WString& xmlResource) Ptr<GuiResource> GacUIUnitTest_CompileAndLoad(const WString& xmlResource)
{ {
#define ERROR_MESSAGE_PREFIX L"GacUIUnitTest_CompileAndLoad(const WString&)#" #define ERROR_MESSAGE_PREFIX L"GacUIUnitTest_CompileAndLoad(const WString&)#"
@@ -509,10 +528,18 @@ Ptr<GuiResource> GacUIUnitTest_CompileAndLoad(const WString& xmlResource)
auto resourcePath = (GetUnitTestFrameworkConfig().resourceFolder / L"Resource.xml").GetFullPath(); auto resourcePath = (GetUnitTestFrameworkConfig().resourceFolder / L"Resource.xml").GetFullPath();
auto parser = GetParserManager()->GetParser<glr::xml::XmlDocument>(L"XML"); auto parser = GetParserManager()->GetParser<glr::xml::XmlDocument>(L"XML");
auto xml = parser->Parse({ WString::Empty,resourcePath }, xmlResource, errors); auto xml = parser->Parse({ WString::Empty,resourcePath }, xmlResource, errors);
CHECK_ERROR(xml && errors.Count() == 0, ERROR_MESSAGE_PREFIX L"Failed to parse XML resource."); if(!xml || errors.Count()> 0)
{
GacUIUnitTest_PrintErrors(errors);
CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Failed to parse XML resource.");
}
resource = GuiResource::LoadFromXml(xml, resourcePath, GetFolderPath(resourcePath), errors); resource = GuiResource::LoadFromXml(xml, resourcePath, GetFolderPath(resourcePath), errors);
CHECK_ERROR(resource && errors.Count() == 0, ERROR_MESSAGE_PREFIX L"Failed to load XML resource."); if (!resource || errors.Count() > 0)
{
GacUIUnitTest_PrintErrors(errors);
CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Failed to load XML resource.");
}
} }
auto precompiledFolder = resource->Precompile( auto precompiledFolder = resource->Precompile(
@@ -524,7 +551,11 @@ Ptr<GuiResource> GacUIUnitTest_CompileAndLoad(const WString& xmlResource)
nullptr, nullptr,
errors errors
); );
CHECK_ERROR(precompiledFolder && errors.Count() == 0, ERROR_MESSAGE_PREFIX L"Failed to precompile XML resource."); if (!precompiledFolder || errors.Count() > 0)
{
GacUIUnitTest_PrintErrors(errors);
CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Failed to precompile XML resource.");
}
auto compiledWorkflow = precompiledFolder->GetValueByPath(WString::Unmanaged(L"Workflow/InstanceClass")).Cast<GuiInstanceCompiledWorkflow>(); auto compiledWorkflow = precompiledFolder->GetValueByPath(WString::Unmanaged(L"Workflow/InstanceClass")).Cast<GuiInstanceCompiledWorkflow>();
CHECK_ERROR(compiledWorkflow, ERROR_MESSAGE_PREFIX L"Failed to compile generated Workflow script."); CHECK_ERROR(compiledWorkflow, ERROR_MESSAGE_PREFIX L"Failed to compile generated Workflow script.");
+20
View File
@@ -1388,9 +1388,11 @@ UnitTestRemoteProtocol
protected: protected:
bool everRendered = false; bool everRendered = false;
Ptr<UnitTestLoggedFrame> candidateFrame; Ptr<UnitTestLoggedFrame> candidateFrame;
vint idlingCounter = 0;
bool LogRenderingResult() bool LogRenderingResult()
{ {
#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Logging<TProtocol>::ProcessRemoteEvents()#"
if (auto lastFrame = this->TryGetLastRenderingFrameAndReset()) if (auto lastFrame = this->TryGetLastRenderingFrameAndReset())
{ {
candidateFrame = lastFrame; candidateFrame = lastFrame;
@@ -1400,6 +1402,7 @@ UnitTestRemoteProtocol
{ {
if (candidateFrame) if (candidateFrame)
{ {
idlingCounter = 0;
auto descs = Ptr(new collections::Dictionary<vint, ElementDescVariant>); auto descs = Ptr(new collections::Dictionary<vint, ElementDescVariant>);
CopyFrom(*descs.Obj(), this->lastElementDescs); CopyFrom(*descs.Obj(), this->lastElementDescs);
this->loggedTrace.frames->Add({ this->loggedTrace.frames->Add({
@@ -1412,8 +1415,20 @@ UnitTestRemoteProtocol
candidateFrame = {}; candidateFrame = {};
return true; return true;
} }
else
{
idlingCounter++;
if (idlingCounter == 100)
{
CHECK_ERROR(
idlingCounter < 100,
ERROR_MESSAGE_PREFIX L"The last frame didn't trigger UI updating. The action registered by OnNextIdleFrame should always make any element or layout to change."
);
}
}
} }
return false; return false;
#undef ERROR_MESSAGE_PREFIX
} }
public: public:
@@ -1555,6 +1570,8 @@ IGuiRemoteProtocol
protected: protected:
bool frameExecuting = false;
void ProcessRemoteEvents() override void ProcessRemoteEvents() override
{ {
#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol::ProcessRemoteEvents()#" #define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol::ProcessRemoteEvents()#"
@@ -1563,6 +1580,7 @@ IGuiRemoteProtocol
if (LogRenderingResult()) if (LogRenderingResult())
{ {
auto [name, func] = processRemoteEvents[nextEventIndex]; auto [name, func] = processRemoteEvents[nextEventIndex];
CHECK_ERROR(!frameExecuting, ERROR_MESSAGE_PREFIX L"The action registered by OnNextIdleFrame should not call any blocking function, consider using InvokeInMainThread.");
vl::unittest::UnitTest::PrintMessage(L"Execute idle frame[" + (name ? name.Value() : itow(nextEventIndex)) + L"]", vl::unittest::UnitTest::MessageKind::Info); vl::unittest::UnitTest::PrintMessage(L"Execute idle frame[" + (name ? name.Value() : itow(nextEventIndex)) + L"]", vl::unittest::UnitTest::MessageKind::Info);
CHECK_ERROR(lastFrameIndex != loggedTrace.frames->Count() - 1, ERROR_MESSAGE_PREFIX L"No rendering occured after the last idle frame."); CHECK_ERROR(lastFrameIndex != loggedTrace.frames->Count() - 1, ERROR_MESSAGE_PREFIX L"No rendering occured after the last idle frame.");
lastFrameIndex = loggedTrace.frames->Count() - 1; lastFrameIndex = loggedTrace.frames->Count() - 1;
@@ -1572,7 +1590,9 @@ IGuiRemoteProtocol
auto&& lastFrame = (*loggedTrace.frames.Obj())[loggedTrace.frames->Count() - 1]; auto&& lastFrame = (*loggedTrace.frames.Obj())[loggedTrace.frames->Count() - 1];
lastFrame.frameName = name; lastFrame.frameName = name;
} }
frameExecuting = true;
func(); func();
frameExecuting = false;
nextEventIndex++; nextEventIndex++;
} }
} }
+232 -78
View File
File diff suppressed because one or more lines are too long
+19 -4
View File
@@ -14184,8 +14184,12 @@ Buttons
GuiButton(theme::ThemeName themeName); GuiButton(theme::ThemeName themeName);
~GuiButton(); ~GuiButton();
/// <summary>Mouse click event.</summary> /// <summary>Mouse click event, but raised before Clicked. This event is for pre-UI effects.</summary>
compositions::GuiNotifyEvent BeforeClicked;
/// <summary>Mouse click event. This event is for executing the actual task assigned with the button.</summary>
compositions::GuiNotifyEvent Clicked; compositions::GuiNotifyEvent Clicked;
/// <summary>Mouse click event, but raised after Clicked. This event is for post-UI effects.</summary>
compositions::GuiNotifyEvent AfterClicked;
/// <summary>Test is the <see cref="Clicked"/> event raised when left mouse button up.</summary> /// <summary>Test is the <see cref="Clicked"/> event raised when left mouse button up.</summary>
/// <returns>Returns true if this event is raised when left mouse button up</returns> /// <returns>Returns true if this event is raised when left mouse button up</returns>
@@ -14255,7 +14259,7 @@ Buttons
bool autoSelection = true; bool autoSelection = true;
bool isSelected = false; bool isSelected = false;
void OnClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); void OnAfterClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
public: public:
/// <summary>Create a control with a specified default theme.</summary> /// <summary>Create a control with a specified default theme.</summary>
/// <param name="themeName">The theme name for retriving a default control template.</param> /// <param name="themeName">The theme name for retriving a default control template.</param>
@@ -15506,6 +15510,7 @@ GuiVirtualTextList
void OnStyleInstalled(vint itemIndex, ItemStyle* style, bool refreshPropertiesOnly)override; void OnStyleInstalled(vint itemIndex, ItemStyle* style, bool refreshPropertiesOnly)override;
void OnItemTemplateChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); void OnItemTemplateChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
void OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments);
public: public:
/// <summary>Create a Text list control in virtual mode.</summary> /// <summary>Create a Text list control in virtual mode.</summary>
/// <param name="themeName">The theme name for retriving a default control template.</param> /// <param name="themeName">The theme name for retriving a default control template.</param>
@@ -18197,7 +18202,7 @@ MenuButton
void OnSubMenuWindowOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); void OnSubMenuWindowOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
void OnSubMenuWindowClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); void OnSubMenuWindowClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
void OnMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); void OnMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
void OnClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); void OnBeforeClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
virtual IGuiMenuService::Direction GetSubMenuDirection(); virtual IGuiMenuService::Direction GetSubMenuDirection();
@@ -18328,13 +18333,23 @@ ComboBox Base
GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(ComboBoxTemplate, GuiMenuButton) GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(ComboBoxTemplate, GuiMenuButton)
protected: protected:
compositions::IGuiAltActionHost* GetActivatingAltHost()override;
IGuiMenuService::Direction GetSubMenuDirection()override; IGuiMenuService::Direction GetSubMenuDirection()override;
void OnCachedBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); void OnCachedBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
void OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments);
void OnAfterSubMenuOpening(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
private:
bool autoFocusDropdown;
public: public:
/// <summary>Create a control with a specified default theme.</summary> /// <summary>Create a control with a specified default theme.</summary>
/// <param name="themeName">The theme name for retriving a default control template.</param> /// <param name="themeName">The theme name for retriving a default control template.</param>
GuiComboBoxBase(theme::ThemeName themeName); /// <param name="_autoFocusDropdown">Whether to automatically focus the dropdown when it opens.</param>
GuiComboBoxBase(theme::ThemeName themeName, bool _autoFocusDropdown);
~GuiComboBoxBase(); ~GuiComboBoxBase();
IDescriptable* QueryService(const WString& identifier) override;
}; };
/*********************************************************************** /***********************************************************************
+3 -1
View File
@@ -2454,7 +2454,9 @@ Type Declaration (Class)
CLASS_MEMBER_BASE(GuiControl) CLASS_MEMBER_BASE(GuiControl)
CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE(GuiButton) CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE(GuiButton)
CLASS_MEMBER_GUIEVENT(BeforeClicked)
CLASS_MEMBER_GUIEVENT(Clicked) CLASS_MEMBER_GUIEVENT(Clicked)
CLASS_MEMBER_GUIEVENT(AfterClicked)
CLASS_MEMBER_PROPERTY_FAST(ClickOnMouseUp) CLASS_MEMBER_PROPERTY_FAST(ClickOnMouseUp)
CLASS_MEMBER_PROPERTY_FAST(AutoFocus) CLASS_MEMBER_PROPERTY_FAST(AutoFocus)
@@ -2771,7 +2773,7 @@ Type Declaration (Class)
BEGIN_CLASS_MEMBER(GuiComboBoxBase) BEGIN_CLASS_MEMBER(GuiComboBoxBase)
CLASS_MEMBER_BASE(GuiMenuButton) CLASS_MEMBER_BASE(GuiMenuButton)
CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE(GuiComboBoxBase) CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE_2(GuiComboBoxBase, bool, _autoFocusDropdown)
END_CLASS_MEMBER(GuiComboBoxBase) END_CLASS_MEMBER(GuiComboBoxBase)
BEGIN_CLASS_MEMBER(GuiComboButton) BEGIN_CLASS_MEMBER(GuiComboButton)
+12
View File
@@ -27299,6 +27299,9 @@ Class (::darkskin::ListViewColumnHeaderTemplateConstructor)
(this->buttonArrow = new ::vl::presentation::controls::GuiSelectableButton(::vl::presentation::theme::ThemeName::CheckBox)); (this->buttonArrow = new ::vl::presentation::controls::GuiSelectableButton(::vl::presentation::theme::ThemeName::CheckBox));
::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"buttonArrow"), ::vl::__vwsn::Box(this->buttonArrow)); ::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"buttonArrow"), ::vl::__vwsn::Box(this->buttonArrow));
} }
{
::vl::__vwsn::This(this->buttonArrow)->SetAutoSelection(false);
}
(this->__vwsn_precompile_14 = ::vl::__vwsn::This(this->buttonArrow)->GetBoundsComposition()); (this->__vwsn_precompile_14 = ::vl::__vwsn::This(this->buttonArrow)->GetBoundsComposition());
{ {
::vl::__vwsn::This(this->__vwsn_precompile_14)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->__vwsn_precompile_14)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }());
@@ -29687,6 +29690,9 @@ Class (::darkskin::RibbonLargeSplitButtonTemplateConstructor)
(this->buttonArrow = new ::vl::presentation::controls::GuiSelectableButton(::vl::presentation::theme::ThemeName::CheckBox)); (this->buttonArrow = new ::vl::presentation::controls::GuiSelectableButton(::vl::presentation::theme::ThemeName::CheckBox));
::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"buttonArrow"), ::vl::__vwsn::Box(this->buttonArrow)); ::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"buttonArrow"), ::vl::__vwsn::Box(this->buttonArrow));
} }
{
::vl::__vwsn::This(this->buttonArrow)->SetAutoSelection(false);
}
(this->__vwsn_precompile_9 = ::vl::__vwsn::This(this->buttonArrow)->GetBoundsComposition()); (this->__vwsn_precompile_9 = ::vl::__vwsn::This(this->buttonArrow)->GetBoundsComposition());
{ {
::vl::__vwsn::This(this->__vwsn_precompile_9)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->__vwsn_precompile_9)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }());
@@ -30449,6 +30455,9 @@ Class (::darkskin::RibbonSmallSplitButtonTemplateConstructor)
(this->buttonArrow = new ::vl::presentation::controls::GuiSelectableButton(::vl::presentation::theme::ThemeName::CheckBox)); (this->buttonArrow = new ::vl::presentation::controls::GuiSelectableButton(::vl::presentation::theme::ThemeName::CheckBox));
::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"buttonArrow"), ::vl::__vwsn::Box(this->buttonArrow)); ::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"buttonArrow"), ::vl::__vwsn::Box(this->buttonArrow));
} }
{
::vl::__vwsn::This(this->buttonArrow)->SetAutoSelection(false);
}
(this->__vwsn_precompile_11 = ::vl::__vwsn::This(this->buttonArrow)->GetBoundsComposition()); (this->__vwsn_precompile_11 = ::vl::__vwsn::This(this->buttonArrow)->GetBoundsComposition());
{ {
::vl::__vwsn::This(this->__vwsn_precompile_11)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->__vwsn_precompile_11)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }());
@@ -32770,6 +32779,9 @@ Class (::darkskin::ToolstripSplitButtonTemplateConstructor)
(this->buttonArrow = new ::vl::presentation::controls::GuiSelectableButton(::vl::presentation::theme::ThemeName::CheckBox)); (this->buttonArrow = new ::vl::presentation::controls::GuiSelectableButton(::vl::presentation::theme::ThemeName::CheckBox));
::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"buttonArrow"), ::vl::__vwsn::Box(this->buttonArrow)); ::vl::__vwsn::This(__vwsn_this_)->SetNamedObject(::vl::WString::Unmanaged(L"buttonArrow"), ::vl::__vwsn::Box(this->buttonArrow));
} }
{
::vl::__vwsn::This(this->buttonArrow)->SetAutoSelection(false);
}
(this->__vwsn_precompile_8 = ::vl::__vwsn::This(this->buttonArrow)->GetBoundsComposition()); (this->__vwsn_precompile_8 = ::vl::__vwsn::This(this->buttonArrow)->GetBoundsComposition());
{ {
::vl::__vwsn::This(this->__vwsn_precompile_8)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); ::vl::__vwsn::This(this->__vwsn_precompile_8)->SetAlignmentToParent([&](){ ::vl::presentation::Margin __vwsn_temp__; __vwsn_temp__.left = static_cast<::vl::vint>(0); __vwsn_temp__.top = static_cast<::vl::vint>(0); __vwsn_temp__.right = static_cast<::vl::vint>(0); __vwsn_temp__.bottom = static_cast<::vl::vint>(0); return __vwsn_temp__; }());
+64 -15
View File
@@ -1399,7 +1399,7 @@ UnitTest
vint passedFiles = 0; vint passedFiles = 0;
vint totalCases = 0; vint totalCases = 0;
vint passedCases = 0; vint passedCases = 0;
bool suppressFailure = false; UnitTest::FailureMode failureMode = UnitTest::FailureMode::NotRunning;
template<typename TMessage> template<typename TMessage>
void RecordFailure(TMessage errorMessage) void RecordFailure(TMessage errorMessage)
@@ -1423,22 +1423,46 @@ UnitTest
catch (const UnitTestAssertError& e) catch (const UnitTestAssertError& e)
{ {
RecordFailure(e.message); RecordFailure(e.message);
if (failureMode == UnitTest::FailureMode::Copilot)
{
throw UnitTestJustCrashError{};
}
} }
catch (const UnitTestConfigError& e) catch (const UnitTestConfigError& e)
{ {
RecordFailure(e.message); RecordFailure(e.message);
if (failureMode == UnitTest::FailureMode::Copilot)
{
throw UnitTestJustCrashError{};
}
} }
catch (const Error& e) catch (const Error& e)
{ {
RecordFailure(e.Description()); RecordFailure(e.Description());
if (failureMode == UnitTest::FailureMode::Copilot)
{
throw UnitTestJustCrashError{};
}
} }
catch (const Exception& e) catch (const Exception& e)
{ {
RecordFailure(e.Message()); RecordFailure(e.Message());
if (failureMode == UnitTest::FailureMode::Copilot)
{
throw UnitTestJustCrashError{};
}
}
catch (const UnitTestJustCrashError&)
{
throw;
} }
catch (...) catch (...)
{ {
RecordFailure(L"Unknown exception occurred!"); RecordFailure(L"Unknown exception occurred!");
if (failureMode == UnitTest::FailureMode::Copilot)
{
throw UnitTestJustCrashError{};
}
} }
} }
@@ -1462,18 +1486,26 @@ UnitTest
template<typename TCallback> template<typename TCallback>
void ExecuteAndSuppressFailure(TCallback&& callback) void ExecuteAndSuppressFailure(TCallback&& callback)
{ {
if (suppressFailure) switch (failureMode)
{ {
case UnitTest::FailureMode::Release:
SuppressCFailure(std::forward<TCallback&&>(callback)); SuppressCFailure(std::forward<TCallback&&>(callback));
} break;
else case UnitTest::FailureMode::Copilot:
{ SuppressCppFailure(std::forward<TCallback&&>(callback));
break;
default:
callback(); callback();
} }
} }
} }
using namespace execution_impl; using namespace execution_impl;
UnitTest::FailureMode UnitTest::GetFailureMode()
{
return execution_impl::failureMode;
}
void UnitTest::PrintMessage(const WString& string, MessageKind kind) void UnitTest::PrintMessage(const WString& string, MessageKind kind)
{ {
if (kind != MessageKind::Error && !testContext) if (kind != MessageKind::Error && !testContext)
@@ -1505,7 +1537,7 @@ UnitTest
int UnitTest::PrintUsages() int UnitTest::PrintUsages()
{ {
PrintMessage(L"Usage: [/D | /R] {/F:TestFile}", MessageKind::Error); PrintMessage(L"Usage: [/D | /R | /C] {/F:TestFile}", MessageKind::Error);
return 1; return 1;
} }
@@ -1517,6 +1549,7 @@ UnitTest
bool unrecognized = false; bool unrecognized = false;
bool _D = false; bool _D = false;
bool _R = false; bool _R = false;
bool _C = false;
List<AString> _Fs; List<AString> _Fs;
for (auto&& option : From(options)) for (auto&& option : From(options))
@@ -1529,6 +1562,10 @@ UnitTest
{ {
_R = true; _R = true;
} }
else if (option == L"/C")
{
_C = true;
}
else if (option.Length() > 3 && option.Left(3) == L"/F:") else if (option.Length() > 3 && option.Left(3) == L"/F:")
{ {
_Fs.Add(wtoa(option.Sub(3, option.Length() - 3))); _Fs.Add(wtoa(option.Sub(3, option.Length() - 3)));
@@ -1539,22 +1576,30 @@ UnitTest
} }
} }
if (unrecognized || (_D && _R)) vint modeCount = 0;
if (_D) modeCount++;
if (_R) modeCount++;
if (_C) modeCount++;
if (unrecognized || modeCount > 1)
{ {
return PrintUsages(); return PrintUsages();
} }
if (_D) if (_D)
{ {
suppressFailure = false; failureMode = FailureMode::Debug;
} }
else if (_R) else if (_R)
{ {
suppressFailure = true; failureMode = FailureMode::Release;
}
else if (_C)
{
failureMode = FailureMode::Copilot;
} }
else else
{ {
suppressFailure = !IsDebuggerAttached(); failureMode = IsDebuggerAttached() ? FailureMode::Debug : FailureMode::Release;
} }
{ {
@@ -1565,13 +1610,17 @@ UnitTest
totalCases = 0; totalCases = 0;
passedCases = 0; passedCases = 0;
if (suppressFailure) switch (failureMode)
{
PrintMessage(L"Failures are suppressed.", MessageKind::Info);
}
else
{ {
case FailureMode::Debug:
PrintMessage(L"Failures are not suppressed.", MessageKind::Info); PrintMessage(L"Failures are not suppressed.", MessageKind::Info);
break;
case FailureMode::Release:
PrintMessage(L"Failures are suppressed.", MessageKind::Info);
break;
case FailureMode::Copilot:
PrintMessage(L"Failures cause immediate exit.", MessageKind::Info);
break;
} }
auto current = testHead; auto current = testHead;
+25 -6
View File
@@ -9404,6 +9404,12 @@ namespace vl
/// A <b>TEST_ASSERT</b> failure will report an error and skip rest of the current <b>TEST_CASE</b>, the execution will continue. /// A <b>TEST_ASSERT</b> failure will report an error and skip rest of the current <b>TEST_CASE</b>, the execution will continue.
/// </p> /// </p>
/// <p> /// <p>
/// When the test program is started with command line option "/C" (Copilot mode),
/// A <b>TEST_ASSERT</b> failure will report an error and cause immediate program termination.
/// This mode is designed for automated testing where you want to stop at the first failure.
/// The "/D", "/R", and "/C" options are mutually exclusive.
/// </p>
/// <p>
/// <b>TEST_ERROR</b> execute one statement, it fails when no [T:vl.Error] is thrown. /// <b>TEST_ERROR</b> execute one statement, it fails when no [T:vl.Error] is thrown.
/// </p> /// </p>
/// <p> /// <p>
@@ -9473,23 +9479,32 @@ namespace vl
Case, Case,
}; };
static void PrintMessage(const WString& string, MessageKind kind); enum class FailureMode
{
NotRunning, // UnitTest is not running
Debug, // corresponds to /D - no exception suppression
Release, // corresponds to /R - suppress and continue
Copilot // corresponds to /C - suppress, record, and rethrow
};
static FailureMode GetFailureMode();
static void PrintMessage(const WString& string, MessageKind kind);
/// <summary>Run all test cases.</summary> /// <summary>Run all test cases.</summary>
/// <returns>The return value for the main function. If any assertion fails, it is non-zero.</returns> /// <returns>The return value for the main function. If any assertion fails, it is non-zero.</returns>
/// <param name="argc">Accept the first argument of the main function.</param> /// <param name="argc">Accept the first argument of the main function.</param>
/// <param name="argv">Accept the second argument of the main function.</param> /// <param name="argv">Accept the second argument of the main function.</param>
static int RunAndDisposeTests(int argc, wchar_t* argv[]); static int RunAndDisposeTests(int argc, wchar_t* argv[]);
/// <summary>Run all test cases.</summary> /// <summary>Run all test cases.</summary>
/// <returns>The return value for the main function. If any assertion fails, it is non-zero.</returns> /// <returns>The return value for the main function. If any assertion fails, it is non-zero.</returns>
/// <param name="argc">Accept the first argument of the main function.</param> /// <param name="argc">Accept the first argument of the main function.</param>
/// <param name="argv">Accept the second argument of the main function.</param> /// <param name="argv">Accept the second argument of the main function.</param>
static int RunAndDisposeTests(int argc, char* argv[]); static int RunAndDisposeTests(int argc, char* argv[]);
static void RegisterTestFile(UnitTestLink* link); static void RegisterTestFile(UnitTestLink* link);
static void RunCategoryOrCase(const WString& description, bool isCategory, Func<void()>&& callback); static void RunCategoryOrCase(const WString& description, bool isCategory, Func<void()>&& callback);
static void EnsureLegalToAssert(); static void EnsureLegalToAssert();
}; };
class UnitTestFile class UnitTestFile
@@ -9520,6 +9535,10 @@ namespace vl
UnitTestConfigError(const wchar_t* _message) :message(_message) {} UnitTestConfigError(const wchar_t* _message) :message(_message) {}
}; };
struct UnitTestJustCrashError
{
};
#define TEST_FILE\ #define TEST_FILE\
static void VLPPTEST_TESTFILE();\ static void VLPPTEST_TESTFILE();\
static ::vl::unittest::UnitTestFile VLPPTEST_TESTFILE_INSTANCE(__FILE__, &VLPPTEST_TESTFILE);\ static ::vl::unittest::UnitTestFile VLPPTEST_TESTFILE_INSTANCE(__FILE__, &VLPPTEST_TESTFILE);\
+198 -184
View File
@@ -23,225 +23,239 @@ static_assert(false, "Do not build this file for Windows applications.");
namespace vl namespace vl
{ {
namespace stream
{
extern Ptr<IFileStreamImpl> CreateOSFileStreamImpl(const WString& fileName, FileStream::AccessRight accessRight);
}
namespace filesystem namespace filesystem
{ {
using namespace collections; using namespace collections;
using namespace stream; using namespace stream;
/*********************************************************************** /***********************************************************************
FilePath LinuxFileSystemImpl
***********************************************************************/ ***********************************************************************/
const wchar_t FilePath::Delimiter; class LinuxFileSystemImpl : public Object, public virtual IFileSystemImpl
void FilePath::Initialize()
{ {
public:
// FilePath operations implementation
void Initialize(WString& fullPath) const override
{ {
Array<wchar_t> buffer(fullPath.Length() + 1);
wcscpy(&buffer[0], fullPath.Buffer());
NormalizeDelimiters(buffer);
fullPath = &buffer[0];
}
if (fullPath.Length() == 0)
fullPath = WString::Unmanaged(L"/");
if (fullPath[0] != Delimiter)
{
char buffer[PATH_MAX] = { 0 };
getcwd(buffer, PATH_MAX);
fullPath = atow(AString(buffer)) + WString::FromChar(Delimiter) + fullPath;
}
{
collections::List<WString> components;
GetPathComponents(fullPath, components);
for (int i = 0; i < components.Count(); i++)
{ {
if (components[i] == L".") Array<wchar_t> buffer(fullPath.Length() + 1);
wcscpy(&buffer[0], fullPath.Buffer());
FilePath::NormalizeDelimiters(buffer);
fullPath = &buffer[0];
}
if (fullPath.Length() == 0)
fullPath = WString::Unmanaged(L"/");
if (fullPath[0] != FilePath::Delimiter)
{
char buffer[PATH_MAX] = { 0 };
getcwd(buffer, PATH_MAX);
fullPath = atow(AString(buffer)) + WString::FromChar(FilePath::Delimiter) + fullPath;
}
{
collections::List<WString> components;
FilePath::GetPathComponents(fullPath, components);
for (int i = 0; i < components.Count(); i++)
{ {
components.RemoveAt(i); if (components[i] == L".")
i--;
}
else if (components[i] == L"..")
{
if (i > 0)
{ {
components.RemoveAt(i); components.RemoveAt(i);
components.RemoveAt(i - 1); i--;
i -= 2;
} }
else else if (components[i] == L"..")
{ {
throw ArgumentException(L"Illegal path."); if (i > 0)
{
components.RemoveAt(i);
components.RemoveAt(i - 1);
i -= 2;
}
else
{
throw ArgumentException(L"Illegal path.");
}
} }
} }
fullPath = FilePath::ComponentsToPath(components);
}
FilePath::TrimLastDelimiter(fullPath);
}
bool IsFile(const WString& fullPath) const override
{
struct stat info;
AString path = wtoa(fullPath);
int result = stat(path.Buffer(), &info);
if(result != 0) return false;
else return S_ISREG(info.st_mode);
}
bool IsFolder(const WString& fullPath) const override
{
struct stat info;
AString path = wtoa(fullPath);
int result = stat(path.Buffer(), &info);
if(result != 0) return false;
else return S_ISDIR(info.st_mode);
}
bool IsRoot(const WString& fullPath) const override
{
return fullPath == L"/";
}
WString GetRelativePathFor(const WString& fromPath, const WString& toPath) const override
{
if (fromPath.Length() == 0 || toPath.Length() == 0 || fromPath[0] != toPath[0])
{
return toPath;
}
collections::List<WString> srcComponents, tgtComponents, resultComponents;
FilePath::GetPathComponents(IsFolder(fromPath) ? fromPath : FilePath(fromPath).GetFolder().GetFullPath(), srcComponents);
FilePath::GetPathComponents(toPath, tgtComponents);
int minLength = srcComponents.Count() <= tgtComponents.Count() ? srcComponents.Count() : tgtComponents.Count();
int lastCommonComponent = 0;
for (int i = 0; i < minLength; i++)
{
if (srcComponents[i] == tgtComponents[i])
{
lastCommonComponent = i;
}
else
break;
}
for (int i = lastCommonComponent + 1; i < srcComponents.Count(); i++)
{
resultComponents.Add(L"..");
}
for (int i = lastCommonComponent + 1; i < tgtComponents.Count(); i++)
{
resultComponents.Add(tgtComponents[i]);
}
return FilePath::ComponentsToPath(resultComponents);
}
// File operations implementation
bool FileDelete(const FilePath& filePath) const override
{
AString path = wtoa(filePath.GetFullPath());
return unlink(path.Buffer()) == 0;
}
bool FileRename(const FilePath& filePath, const WString& newName) const override
{
AString oldFileName = wtoa(filePath.GetFullPath());
AString newFileName = wtoa((filePath.GetFolder() / newName).GetFullPath());
return rename(oldFileName.Buffer(), newFileName.Buffer()) == 0;
}
// Folder operations implementation
bool GetFolders(const FilePath& folderPath, collections::List<Folder>& folders) const override
{
DIR *dir;
AString searchPath = wtoa(folderPath.GetFullPath());
if ((dir = opendir(searchPath.Buffer())) == NULL)
{
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
WString childName = atow(AString(entry->d_name));
FilePath childFullPath = folderPath / childName;
if (childName != L"." && childName != L".." && childFullPath.IsFolder())
{
folders.Add(Folder(childFullPath));
}
} }
fullPath = ComponentsToPath(components); if (closedir(dir) != 0)
}
TrimLastDelimiter(fullPath);
}
bool FilePath::IsFile()const
{
struct stat info;
AString path = wtoa(fullPath);
int result = stat(path.Buffer(), &info);
if(result != 0) return false;
else return S_ISREG(info.st_mode);
}
bool FilePath::IsFolder()const
{
struct stat info;
AString path = wtoa(fullPath);
int result = stat(path.Buffer(), &info);
if(result != 0) return false;
else return S_ISDIR(info.st_mode);
}
bool FilePath::IsRoot()const
{
return fullPath == L"/";
}
WString FilePath::GetRelativePathFor(const FilePath& _filePath) const
{
if (fullPath.Length() == 0 || _filePath.fullPath.Length() == 0 || fullPath[0] != _filePath.fullPath[0])
{
return _filePath.fullPath;
}
collections::List<WString> srcComponents, tgtComponents, resultComponents;
GetPathComponents(IsFolder() ? fullPath : GetFolder().GetFullPath(), srcComponents);
GetPathComponents(_filePath.fullPath, tgtComponents);
int minLength = srcComponents.Count() <= tgtComponents.Count() ? srcComponents.Count() : tgtComponents.Count();
int lastCommonComponent = 0;
for (int i = 0; i < minLength; i++)
{
if (srcComponents[i] == tgtComponents[i])
{ {
lastCommonComponent = i; return false;
} }
else
break; return true;
} }
for (int i = lastCommonComponent + 1; i < srcComponents.Count(); i++) bool GetFiles(const FilePath& folderPath, collections::List<File>& files) const override
{ {
resultComponents.Add(L".."); DIR* dir;
AString searchPath = wtoa(folderPath.GetFullPath());
if ((dir = opendir(searchPath.Buffer())) == NULL)
{
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
FilePath childFullPath = folderPath / (atow(AString(entry->d_name)));
if (childFullPath.IsFile())
{
files.Add(File(childFullPath));
}
}
if (closedir(dir) != 0)
{
return false;
}
return true;
} }
for (int i = lastCommonComponent + 1; i < tgtComponents.Count(); i++) bool CreateFolder(const FilePath& folderPath) const override
{ {
resultComponents.Add(tgtComponents[i]); AString path = wtoa(folderPath.GetFullPath());
return mkdir(path.Buffer(), 0777) == 0;
} }
return ComponentsToPath(resultComponents); bool DeleteFolder(const FilePath& folderPath) const override
} {
AString path = wtoa(folderPath.GetFullPath());
return rmdir(path.Buffer()) == 0;
}
bool FolderRename(const FilePath& folderPath, const WString& newName) const override
{
AString oldFileName = wtoa(folderPath.GetFullPath());
AString newFileName = wtoa((folderPath.GetFolder() / newName).GetFullPath());
return rename(oldFileName.Buffer(), newFileName.Buffer()) == 0;
}
Ptr<stream::IFileStreamImpl> GetFileStreamImpl(const WString& fileName, stream::FileStream::AccessRight accessRight) const override
{
return stream::CreateOSFileStreamImpl(fileName, accessRight);
}
};
/*********************************************************************** /***********************************************************************
File Global FileSystem Implementation
***********************************************************************/ ***********************************************************************/
bool File::Delete()const LinuxFileSystemImpl osFileSystemImpl;
IFileSystemImpl* GetOSFileSystemImpl()
{ {
AString path = wtoa(filePath.GetFullPath()); return &osFileSystemImpl;
return unlink(path.Buffer()) == 0;
}
bool File::Rename(const WString& newName)const
{
AString oldFileName = wtoa(filePath.GetFullPath());
AString newFileName = wtoa((filePath.GetFolder() / newName).GetFullPath());
return rename(oldFileName.Buffer(), newFileName.Buffer()) == 0;
}
/***********************************************************************
Folder
***********************************************************************/
bool Folder::GetFolders(collections::List<Folder>& folders)const
{
if (!Exists()) return false;
DIR *dir;
AString searchPath = wtoa(filePath.GetFullPath());
if ((dir = opendir(searchPath.Buffer())) == NULL)
{
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
WString childName = atow(AString(entry->d_name));
FilePath childFullPath = filePath / childName;
if (childName != L"." && childName != L".." && childFullPath.IsFolder())
{
folders.Add(Folder(childFullPath));
}
}
if (closedir(dir) != 0)
{
return false;
}
return true;
}
bool Folder::GetFiles(collections::List<File>& files)const
{
if (!Exists()) return false;
DIR* dir;
AString searchPath = wtoa(filePath.GetFullPath());
if ((dir = opendir(searchPath.Buffer())) == NULL)
{
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
FilePath childFullPath = filePath / (atow(AString(entry->d_name)));
if (childFullPath.IsFile())
{
files.Add(File(childFullPath));
}
}
if (closedir(dir) != 0)
{
return false;
}
return true;
}
bool Folder::CreateNonRecursively()const
{
AString path = wtoa(filePath.GetFullPath());
return mkdir(path.Buffer(), 0777) == 0;
}
bool Folder::DeleteNonRecursively()const
{
AString path = wtoa(filePath.GetFullPath());
return rmdir(path.Buffer()) == 0;
}
bool Folder::Rename(const WString& newName)const
{
AString oldFileName = wtoa(filePath.GetFullPath());
AString newFileName = wtoa((filePath.GetFolder() / newName).GetFullPath());
return rename(oldFileName.Buffer(), newFileName.Buffer()) == 0;
} }
} }
} }
+184 -171
View File
@@ -24,151 +24,194 @@ static_assert(false, "Do not build this file for non-Windows applications.");
namespace vl namespace vl
{ {
namespace stream
{
extern Ptr<IFileStreamImpl> CreateOSFileStreamImpl(const WString& fileName, FileStream::AccessRight accessRight);
}
namespace filesystem namespace filesystem
{ {
using namespace collections; using namespace collections;
using namespace stream; using namespace stream;
/*********************************************************************** /***********************************************************************
FilePath WindowsFileSystemImpl
***********************************************************************/ ***********************************************************************/
void FilePath::Initialize() class WindowsFileSystemImpl : public Object, public virtual IFileSystemImpl
{ {
public:
void Initialize(WString& fullPath) const override
{ {
Array<wchar_t> buffer(fullPath.Length() + 1); {
wcscpy_s(&buffer[0], fullPath.Length() + 1, fullPath.Buffer()); Array<wchar_t> buffer(fullPath.Length() + 1);
NormalizeDelimiters(buffer); wcscpy_s(&buffer[0], fullPath.Length() + 1, fullPath.Buffer());
fullPath = &buffer[0]; FilePath::NormalizeDelimiters(buffer);
fullPath = &buffer[0];
}
if (fullPath != L"")
{
if (fullPath.Length() < 2 || fullPath[1] != L':')
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
auto result = GetCurrentDirectory(sizeof(buffer) / sizeof(*buffer), buffer);
if (result > MAX_PATH + 1 || result == 0)
{
throw ArgumentException(L"Failed to call GetCurrentDirectory.", L"vl::filesystem::FilePath::Initialize", L"");
}
fullPath = WString(buffer) + L"\\" + fullPath;
}
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
if (fullPath.Length() == 2 && fullPath[1] == L':')
{
fullPath += L"\\";
}
auto result = GetFullPathName(fullPath.Buffer(), sizeof(buffer) / sizeof(*buffer), buffer, NULL);
if (result > MAX_PATH + 1 || result == 0)
{
throw ArgumentException(L"The path is illegal.", L"vl::filesystem::FilePath::FilePath", L"_filePath");
}
{
wchar_t shortPath[MAX_PATH + 1];
wchar_t longPath[MAX_PATH + 1];
if (GetShortPathName(buffer, shortPath, MAX_PATH) > 0)
{
if (GetLongPathName(shortPath, longPath, MAX_PATH) > 0)
{
memcpy(buffer, longPath, sizeof(buffer));
}
}
}
fullPath = buffer;
}
}
FilePath::TrimLastDelimiter(fullPath);
} }
if (fullPath != L"") bool IsFile(const WString& fullPath) const override
{ {
if (fullPath.Length() < 2 || fullPath[1] != L':') WIN32_FILE_ATTRIBUTE_DATA info;
{ BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
wchar_t buffer[MAX_PATH + 1] = { 0 }; if (!result) return false;
auto result = GetCurrentDirectory(sizeof(buffer) / sizeof(*buffer), buffer); return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
if (result > MAX_PATH + 1 || result == 0) }
{
throw ArgumentException(L"Failed to call GetCurrentDirectory.", L"vl::filesystem::FilePath::Initialize", L"");
}
fullPath = WString(buffer) + L"\\" + fullPath;
}
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
if (fullPath.Length() == 2 && fullPath[1] == L':')
{
fullPath += L"\\";
}
auto result = GetFullPathName(fullPath.Buffer(), sizeof(buffer) / sizeof(*buffer), buffer, NULL);
if (result > MAX_PATH + 1 || result == 0)
{
throw ArgumentException(L"The path is illegal.", L"vl::filesystem::FilePath::FilePath", L"_filePath");
}
bool IsFolder(const WString& fullPath) const override
{
WIN32_FILE_ATTRIBUTE_DATA info;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if (!result) return false;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
bool IsRoot(const WString& fullPath) const override
{
return fullPath == L"";
}
WString GetRelativePathFor(const WString& fromPath, const WString& toPath) const override
{
if (fromPath.Length() == 0 || toPath.Length() == 0 || fromPath[0] != toPath[0])
{
return toPath;
}
wchar_t buffer[MAX_PATH + 1] = { 0 };
PathRelativePathTo(
buffer,
fromPath.Buffer(),
(IsFolder(fromPath) ? FILE_ATTRIBUTE_DIRECTORY : 0),
toPath.Buffer(),
(IsFolder(toPath) ? FILE_ATTRIBUTE_DIRECTORY : 0)
);
return buffer;
}
bool FileDelete(const FilePath& filePath) const override
{
return DeleteFile(filePath.GetFullPath().Buffer()) != 0;
}
bool FileRename(const FilePath& filePath, const WString& newName) const override
{
WString oldFileName = filePath.GetFullPath();
WString newFileName = (filePath.GetFolder() / newName).GetFullPath();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
}
bool GetFolders(const FilePath& folderPath, collections::List<Folder>& folders) const override
{
if (folderPath.IsRoot())
{
auto bufferSize = GetLogicalDriveStrings(0, nullptr);
if (bufferSize > 0)
{ {
wchar_t shortPath[MAX_PATH + 1]; Array<wchar_t> buffer(bufferSize);
wchar_t longPath[MAX_PATH + 1]; if (GetLogicalDriveStrings((DWORD)buffer.Count(), &buffer[0]) > 0)
if (GetShortPathName(buffer, shortPath, MAX_PATH) > 0)
{ {
if (GetLongPathName(shortPath, longPath, MAX_PATH) > 0) auto begin = &buffer[0];
auto end = begin + buffer.Count();
while (begin < end && *begin)
{ {
memcpy(buffer, longPath, sizeof(buffer)); WString driveString = begin;
begin += driveString.Length() + 1;
folders.Add(Folder(FilePath(driveString)));
}
return true;
}
}
return false;
}
else
{
if (!IsFolder(folderPath.GetFullPath())) return false;
WIN32_FIND_DATA findData;
HANDLE findHandle = INVALID_HANDLE_VALUE;
while (true)
{
if (findHandle == INVALID_HANDLE_VALUE)
{
WString searchPath = (folderPath / L"*").GetFullPath();
findHandle = FindFirstFile(searchPath.Buffer(), &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
break;
}
}
else
{
BOOL result = FindNextFile(findHandle, &findData);
if (result == 0)
{
FindClose(findHandle);
break;
}
}
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (wcscmp(findData.cFileName, L".") != 0 && wcscmp(findData.cFileName, L"..") != 0)
{
folders.Add(Folder(folderPath / findData.cFileName));
} }
} }
} }
fullPath = buffer; return true;
} }
} }
TrimLastDelimiter(fullPath); bool GetFiles(const FilePath& folderPath, collections::List<File>& files) const override
}
bool FilePath::IsFile()const
{
WIN32_FILE_ATTRIBUTE_DATA info;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if (!result) return false;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
bool FilePath::IsFolder()const
{
WIN32_FILE_ATTRIBUTE_DATA info;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if (!result) return false;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
bool FilePath::IsRoot()const
{
return fullPath == L"";
}
WString FilePath::GetRelativePathFor(const FilePath& _filePath) const
{
if (fullPath.Length() == 0 || _filePath.fullPath.Length() == 0 || fullPath[0] != _filePath.fullPath[0])
{ {
return _filePath.fullPath; if (IsRoot(folderPath.GetFullPath()))
}
wchar_t buffer[MAX_PATH + 1] = { 0 };
PathRelativePathTo(
buffer,
fullPath.Buffer(),
(IsFolder() ? FILE_ATTRIBUTE_DIRECTORY : 0),
_filePath.fullPath.Buffer(),
(_filePath.IsFolder() ? FILE_ATTRIBUTE_DIRECTORY : 0)
);
return buffer;
}
/***********************************************************************
File
***********************************************************************/
bool File::Delete()const
{
return DeleteFile(filePath.GetFullPath().Buffer()) != 0;
}
bool File::Rename(const WString& newName)const
{
WString oldFileName = filePath.GetFullPath();
WString newFileName = (filePath.GetFolder() / newName).GetFullPath();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
}
/***********************************************************************
Folder
***********************************************************************/
bool Folder::GetFolders(collections::List<Folder>& folders)const
{
if (filePath.IsRoot())
{
auto bufferSize = GetLogicalDriveStrings(0, nullptr);
if (bufferSize > 0)
{ {
Array<wchar_t> buffer(bufferSize); return true;
if (GetLogicalDriveStrings((DWORD)buffer.Count(), &buffer[0]) > 0)
{
auto begin = &buffer[0];
auto end = begin + buffer.Count();
while (begin < end && *begin)
{
WString driveString = begin;
begin += driveString.Length() + 1;
folders.Add(Folder(FilePath(driveString)));
}
return true;
}
} }
return false; if (!IsFolder(folderPath.GetFullPath())) return false;
}
else
{
if (!Exists()) return false;
WIN32_FIND_DATA findData; WIN32_FIND_DATA findData;
HANDLE findHandle = INVALID_HANDLE_VALUE; HANDLE findHandle = INVALID_HANDLE_VALUE;
@@ -176,7 +219,7 @@ Folder
{ {
if (findHandle == INVALID_HANDLE_VALUE) if (findHandle == INVALID_HANDLE_VALUE)
{ {
WString searchPath = (filePath / L"*").GetFullPath(); WString searchPath = (folderPath / L"*").GetFullPath();
findHandle = FindFirstFile(searchPath.Buffer(), &findData); findHandle = FindFirstFile(searchPath.Buffer(), &findData);
if (findHandle == INVALID_HANDLE_VALUE) if (findHandle == INVALID_HANDLE_VALUE)
{ {
@@ -193,72 +236,42 @@ Folder
} }
} }
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{ {
if (wcscmp(findData.cFileName, L".") != 0 && wcscmp(findData.cFileName, L"..") != 0) files.Add(File(folderPath / findData.cFileName));
{
folders.Add(Folder(filePath / findData.cFileName));
}
} }
} }
return true; return true;
} }
}
bool Folder::GetFiles(collections::List<File>& files)const bool CreateFolder(const FilePath& folderPath) const override
{
if (filePath.IsRoot())
{ {
return true; return CreateDirectory(folderPath.GetFullPath().Buffer(), NULL) != 0;
} }
if (!Exists()) return false;
WIN32_FIND_DATA findData;
HANDLE findHandle = INVALID_HANDLE_VALUE;
while (true) bool DeleteFolder(const FilePath& folderPath) const override
{ {
if (findHandle == INVALID_HANDLE_VALUE) return RemoveDirectory(folderPath.GetFullPath().Buffer()) != 0;
{
WString searchPath = (filePath / L"*").GetFullPath();
findHandle = FindFirstFile(searchPath.Buffer(), &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
break;
}
}
else
{
BOOL result = FindNextFile(findHandle, &findData);
if (result == 0)
{
FindClose(findHandle);
break;
}
}
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
files.Add(File(filePath / findData.cFileName));
}
} }
return true;
}
bool Folder::CreateNonRecursively()const bool FolderRename(const FilePath& folderPath, const WString& newName) const override
{ {
return CreateDirectory(filePath.GetFullPath().Buffer(), NULL) != 0; WString oldFileName = folderPath.GetFullPath();
} WString newFileName = (folderPath.GetFolder() / newName).GetFullPath();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
}
bool Folder::DeleteNonRecursively()const Ptr<stream::IFileStreamImpl> GetFileStreamImpl(const WString& fileName, stream::FileStream::AccessRight accessRight) const override
{ {
return RemoveDirectory(filePath.GetFullPath().Buffer()) != 0; return stream::CreateOSFileStreamImpl(fileName, accessRight);
} }
};
bool Folder::Rename(const WString& newName)const WindowsFileSystemImpl osFileSystemImpl;
IFileSystemImpl* GetOSFileSystemImpl()
{ {
WString oldFileName = filePath.GetFullPath(); return &osFileSystemImpl;
WString newFileName = (filePath.GetFolder() / newName).GetFullPath();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
} }
} }
} }
+346 -139
View File
File diff suppressed because it is too large Load Diff
+263 -217
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -653,8 +653,8 @@ Tokenizer
/// } /// }
/// }; /// };
/// ///
/// RegexLexer lexer(tokenDefs, proc); /// RegexLexer lexer(tokenDefs);
/// RegexLexerColorizer colorizer = lexer.Colorize(); /// RegexLexerColorizer colorizer = lexer.Colorize(proc);
/// ///
/// void* lastInterTokenState = nullptr; /// void* lastInterTokenState = nullptr;
/// for (auto [line, index] : indexed(From(lines))) /// for (auto [line, index] : indexed(From(lines)))
@@ -712,7 +712,7 @@ Tokenizer
/// tokenDefs.Add(L"/w+"); /// tokenDefs.Add(L"/w+");
/// tokenDefs.Add(L"/s+"); /// tokenDefs.Add(L"/s+");
/// ///
/// RegexLexer lexer(tokenDefs, {}); /// RegexLexer lexer(tokenDefs);
/// WString input = L"I have 2 books."; /// WString input = L"I have 2 books.";
/// auto tokenResult = lexer.Parse(input); /// auto tokenResult = lexer.Parse(input);
/// ///
@@ -753,7 +753,7 @@ Tokenizer
/// tokenDefs.Add(L"/w+"); /// tokenDefs.Add(L"/w+");
/// tokenDefs.Add(L"/s+"); /// tokenDefs.Add(L"/s+");
/// ///
/// RegexLexer lexer(tokenDefs, {}); /// RegexLexer lexer(tokenDefs);
/// WString input = L"I have 2 books."; /// WString input = L"I have 2 books.";
/// auto tokenResult = lexer.Parse(input); /// auto tokenResult = lexer.Parse(input);
/// ///
@@ -786,7 +786,7 @@ RegexLexerWalker
/// tokenDefs.Add(L"/w+"); /// tokenDefs.Add(L"/w+");
/// tokenDefs.Add(L"/s+"); /// tokenDefs.Add(L"/s+");
/// ///
/// RegexLexer lexer(tokenDefs, {}); /// RegexLexer lexer(tokenDefs);
/// RegexLexerWalker walker = lexer.Walk(); /// RegexLexerWalker walker = lexer.Walk();
/// ///
/// WString input = L"This book costs 2.5. That book costs 2."; /// WString input = L"This book costs 2.5. That book costs 2.";
@@ -919,7 +919,7 @@ RegexLexerWalker
/// tokenDefs.Add(L"/d+./d+"); /// tokenDefs.Add(L"/d+./d+");
/// tokenDefs.Add(L"/d+"); /// tokenDefs.Add(L"/d+");
/// ///
/// RegexLexer lexer(tokenDefs, {}); /// RegexLexer lexer(tokenDefs);
/// RegexLexerWalker walker = lexer.Walk(); /// RegexLexerWalker walker = lexer.Walk();
/// ///
/// WString tests[] = { L".", L"2", L"2.", L"2.5", L"2.5." }; /// WString tests[] = { L".", L"2", L"2.", L"2.5", L"2.5." };
@@ -969,7 +969,7 @@ RegexLexerWalker
/// tokenDefs.Add(L"/d+./d+"); /// tokenDefs.Add(L"/d+./d+");
/// tokenDefs.Add(L"/d+"); /// tokenDefs.Add(L"/d+");
/// ///
/// RegexLexer lexer(tokenDefs, {}); /// RegexLexer lexer(tokenDefs);
/// RegexLexerWalker walker = lexer.Walk(); /// RegexLexerWalker walker = lexer.Walk();
/// ///
/// WString tests[] = { L".", L"2", L"2.", L"2.5", L"2.5." }; /// WString tests[] = { L".", L"2", L"2.", L"2.5", L"2.5." };
@@ -1034,8 +1034,8 @@ RegexLexerColorizer
/// Console::WriteLine(itow(token) + L": <" + WString(text + start, length) + L">"); /// Console::WriteLine(itow(token) + L": <" + WString(text + start, length) + L">");
/// }; /// };
/// ///
/// RegexLexer lexer(tokenDefs, proc); /// RegexLexer lexer(tokenDefs);
/// RegexLexerColorizer colorizer = lexer.Colorize(); /// RegexLexerColorizer colorizer = lexer.Colorize(proc);
/// ///
/// for (auto [line, index] : indexed(From(lines))) /// for (auto [line, index] : indexed(From(lines)))
/// { /// {
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.