diff --git a/Import/GacUI.cpp b/Import/GacUI.cpp index a2224d5e..4075511a 100644 --- a/Import/GacUI.cpp +++ b/Import/GacUI.cpp @@ -165,7 +165,7 @@ External Functions (Compositions) } /*********************************************************************** -.\CONTROLS\GUIAPPLICATION.CPP +.\APPLICATION\CONTROLS\GUIAPPLICATION.CPP ***********************************************************************/ extern void GuiMain(); @@ -439,150 +439,17 @@ GuiApplication } } -/*********************************************************************** -GuiPluginManager -***********************************************************************/ - - class GuiPluginManager : public Object, public IGuiPluginManager - { - protected: - List> plugins; - bool loaded; - public: - GuiPluginManager() - :loaded(false) - { - } - - ~GuiPluginManager() - { - Unload(); - } - - void AddPlugin(Ptr plugin)override - { - CHECK_ERROR(!loaded, L"GuiPluginManager::AddPlugin(Ptr)#Load function has already been executed."); - auto name = plugin->GetName(); - if (name != L"") - { - for (auto plugin : plugins) - { - CHECK_ERROR(plugin->GetName() != name, L"GuiPluginManager::AddPlugin(Ptr)#Duplicated plugin name."); - } - } - plugins.Add(plugin); - } - - void Load()override - { - CHECK_ERROR(!loaded, L"GuiPluginManager::AddPlugin(Ptr)#Load function has already been executed."); - loaded=true; - - SortedList loaded; - Group loading; - Dictionary> pluginsToLoad; - for (auto plugin : plugins) - { - auto name = plugin->GetName(); - pluginsToLoad.Add(name, plugin); - List dependencies; - plugin->GetDependencies(dependencies); - for (auto dependency : dependencies) - { - loading.Add(name, dependency); - } - } - - while (pluginsToLoad.Count() > 0) - { - vint count = pluginsToLoad.Count(); - { - for (auto [name, index] : indexed(pluginsToLoad.Keys())) - { - if (!loading.Keys().Contains(name)) - { - for (vint i = loading.Count() - 1; i >= 0; i--) - { - loading.Remove(loading.Keys()[i], name); - } - loaded.Add(name); - - auto plugin = pluginsToLoad.Values()[index]; - pluginsToLoad.Remove(name); - plugin->Load(); - break; - } - } - } - if (count == pluginsToLoad.Count()) - { - WString message; - for (auto plugin : pluginsToLoad.Values()) - { - message += L"Cannot load plugin \"" + plugin->GetName() + L"\" because part of its dependencies are not ready:"; - List dependencies; - plugin->GetDependencies(dependencies); - bool first = true; - for (auto dependency : dependencies) - { - if (!loaded.Contains(dependency)) - { - message += L" \"" + dependency + L"\";"; - } - } - message += L"\r\n"; - } - throw Exception(message); - } - } - } - - void Unload()override - { - CHECK_ERROR(loaded, L"GuiPluginManager::AddPlugin(Ptr)#Load function has not been executed."); - loaded=false; - for (auto plugin : plugins) - { - plugin->Unload(); - } - } - - bool IsLoaded()override - { - return loaded; - } - }; - /*********************************************************************** Helpers ***********************************************************************/ GuiApplication* application=0; - IGuiPluginManager* pluginManager=0; GuiApplication* GetApplication() { return application; } - IGuiPluginManager* GetPluginManager() - { - if(!pluginManager) - { - pluginManager=new GuiPluginManager; - } - return pluginManager; - } - - void DestroyPluginManager() - { - if(pluginManager) - { - delete pluginManager; - pluginManager=0; - } - } - /*********************************************************************** GuiApplicationMain ***********************************************************************/ @@ -664,7 +531,7 @@ void GuiApplicationMain() } /*********************************************************************** -.\CONTROLS\GUIBASICCONTROLS.CPP +.\APPLICATION\CONTROLS\GUIBASICCONTROLS.CPP ***********************************************************************/ namespace vl @@ -1075,10 +942,9 @@ GuiControl } } - void GuiControl::InvokeOrDelayIfRendering(Func proc) + void GuiControl::TryDelayExecuteIfNotDeleted(Func proc) { - auto controlHost = GetRelatedControlHost(); - if (controlHost && boundsComposition->IsRendering()) + if (auto controlHost = GetRelatedControlHost()) { auto flag = GetDisposedFlag(); GetApplication()->InvokeInMainThread(controlHost, [=]() @@ -1470,7 +1336,7 @@ GuiCustomControl } /*********************************************************************** -.\CONTROLS\GUIBUTTONCONTROLS.CPP +.\APPLICATION\CONTROLS\GUIINSTANCEROOTOBJECT.CPP ***********************************************************************/ namespace vl @@ -1479,1767 +1345,293 @@ namespace vl { namespace controls { - using namespace elements; + using namespace reflection::description; using namespace compositions; - using namespace collections; - using namespace reflection::description; /*********************************************************************** -GuiButton +GuiComponent ***********************************************************************/ - - void GuiButton::BeforeControlTemplateUninstalled_() - { - } - - void GuiButton::AfterControlTemplateInstalled_(bool initialize) - { - TypedControlTemplateObject(true)->SetState(controlState); - } - - void GuiButton::OnParentLineChanged() - { - GuiControl::OnParentLineChanged(); - if(GetRelatedControlHost()==0) - { - mousePressing=false; - mouseHoving=false; - UpdateControlState(); - } - } - - void GuiButton::OnActiveAlt() - { - if (autoFocus) - { - GuiControl::OnActiveAlt(); - } - Clicked.Execute(GetNotifyEventArguments()); - } - - bool GuiButton::IsTabAvailable() - { - return autoFocus && GuiControl::IsTabAvailable(); - } - - void GuiButton::UpdateControlState() - { - auto newControlState = ButtonState::Normal; - if (keyPressing) - { - newControlState = ButtonState::Pressed; - } - else if (mousePressing) - { - if (mouseHoving) - { - newControlState = ButtonState::Pressed; - } - else - { - newControlState = ButtonState::Active; - } - } - else - { - if (mouseHoving) - { - newControlState = ButtonState::Active; - } - else - { - newControlState = ButtonState::Normal; - } - } - if (controlState != newControlState) - { - controlState = newControlState; - TypedControlTemplateObject(true)->SetState(controlState); - } - } - - void GuiButton::CheckAndClick(compositions::GuiEventArgs& arguments) - { - auto eventSource = arguments.eventSource->GetAssociatedControl(); - while (eventSource && eventSource != this) - { - if (eventSource->GetFocusableComposition()) - { - return; - } - eventSource = eventSource->GetParent(); - } - Clicked.Execute(GetNotifyEventArguments()); - } - - void GuiButton::OnLeftButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if (arguments.eventSource == boundsComposition || !ignoreChildControlMouseEvents) - { - mousePressing = true; - if (autoFocus) - { - SetFocus(); - } - UpdateControlState(); - if (!clickOnMouseUp) - { - CheckAndClick(arguments); - } - } - } - - void GuiButton::OnLeftButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if (arguments.eventSource == boundsComposition || !ignoreChildControlMouseEvents) - { - mousePressing = false; - UpdateControlState(); - } - if (GetVisuallyEnabled()) - { - if (mouseHoving && clickOnMouseUp) - { - CheckAndClick(arguments); - } - } - } - - void GuiButton::OnMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - if (arguments.eventSource == boundsComposition || !ignoreChildControlMouseEvents) - { - mouseHoving = true; - UpdateControlState(); - } - } - - void GuiButton::OnMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - if (arguments.eventSource == boundsComposition || !ignoreChildControlMouseEvents) - { - mouseHoving = false; - UpdateControlState(); - } - } - void GuiButton::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) + GuiComponent::GuiComponent() { - if (arguments.eventSource == focusableComposition && !arguments.ctrl && !arguments.shift && !arguments.alt) + } + + GuiComponent::~GuiComponent() + { + } + + void GuiComponent::Attach(GuiInstanceRootObject* rootObject) + { + } + + void GuiComponent::Detach(GuiInstanceRootObject* rootObject) + { + } + +/*********************************************************************** +GuiInstanceRootObject +***********************************************************************/ + + class RootObjectTimerCallback : public Object, public IGuiGraphicsTimerCallback + { + public: + GuiControlHost* controlHost; + GuiInstanceRootObject* rootObject; + bool alive = true; + + RootObjectTimerCallback(GuiInstanceRootObject* _rootObject, GuiControlHost* _controlHost) + :rootObject(_rootObject) + , controlHost(_controlHost) { - switch (arguments.code) + } + + bool Play()override + { + if (alive) { - case VKEY::KEY_RETURN: - CheckAndClick(arguments); - arguments.handled = true; - break; - case VKEY::KEY_SPACE: - if (!arguments.autoRepeatKeyDown) + for (vint i = rootObject->runningAnimations.Count() - 1; i >= 0; i--) { - keyPressing = true; - UpdateControlState(); + auto animation = rootObject->runningAnimations[i]; + animation->Run(); + if (animation->GetStopped()) + { + rootObject->runningAnimations.RemoveAt(i); + } } - arguments.handled = true; - break; - default:; - } - } - } - void GuiButton::OnKeyUp(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) - { - if (arguments.eventSource == focusableComposition && !arguments.ctrl && !arguments.shift && !arguments.alt) - { - switch (arguments.code) - { - case VKEY::KEY_SPACE: - if (keyPressing) + if (rootObject->runningAnimations.Count() == 0) { - keyPressing = false; - UpdateControlState(); - CheckAndClick(arguments); + rootObject->UninstallTimerCallback(nullptr); + return false; } - arguments.handled = true; - break; - default:; } + return alive; } - } - - void GuiButton::OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - if (keyPressing) - { - keyPressing = false; - UpdateControlState(); - } - } - - GuiButton::GuiButton(theme::ThemeName themeName) - :GuiControl(themeName) - { - Clicked.SetAssociatedComposition(boundsComposition); - SetFocusableComposition(boundsComposition); - - boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiButton::OnLeftButtonDown); - boundsComposition->GetEventReceiver()->leftButtonUp.AttachMethod(this, &GuiButton::OnLeftButtonUp); - boundsComposition->GetEventReceiver()->mouseEnter.AttachMethod(this, &GuiButton::OnMouseEnter); - boundsComposition->GetEventReceiver()->mouseLeave.AttachMethod(this, &GuiButton::OnMouseLeave); - boundsComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiButton::OnKeyDown); - boundsComposition->GetEventReceiver()->keyUp.AttachMethod(this, &GuiButton::OnKeyUp); - boundsComposition->GetEventReceiver()->lostFocus.AttachMethod(this, &GuiButton::OnLostFocus); - } - - GuiButton::~GuiButton() - { - } - - bool GuiButton::GetClickOnMouseUp() - { - return clickOnMouseUp; - } - - void GuiButton::SetClickOnMouseUp(bool value) - { - clickOnMouseUp=value; - } - - bool GuiButton::GetAutoFocus() - { - return autoFocus; - } - - void GuiButton::SetAutoFocus(bool value) - { - autoFocus = value; - } - - bool GuiButton::GetIgnoreChildControlMouseEvents() - { - return ignoreChildControlMouseEvents; - } - - void GuiButton::SetIgnoreChildControlMouseEvents(bool value) - { - ignoreChildControlMouseEvents = value; - } - -/*********************************************************************** -GuiSelectableButton::GroupController -***********************************************************************/ - - GuiSelectableButton::GroupController::GroupController() - { - } - - GuiSelectableButton::GroupController::~GroupController() - { - for(vint i=buttons.Count()-1;i>=0;i--) - { - buttons[i]->SetGroupController(0); - } - } - - void GuiSelectableButton::GroupController::Attach(GuiSelectableButton* button) - { - if(!buttons.Contains(button)) - { - buttons.Add(button); - } - } - - void GuiSelectableButton::GroupController::Detach(GuiSelectableButton* button) - { - buttons.Remove(button); - } - -/*********************************************************************** -GuiSelectableButton::MutexGroupController -***********************************************************************/ - - GuiSelectableButton::MutexGroupController::MutexGroupController() - :suppress(false) - { - } - - GuiSelectableButton::MutexGroupController::~MutexGroupController() - { - } - - void GuiSelectableButton::MutexGroupController::OnSelectedChanged(GuiSelectableButton* button) - { - if(!suppress) - { - suppress=true; - for(vint i=0;iSetSelected(buttons[i]==button); - } - suppress=false; - } - } - -/*********************************************************************** -GuiSelectableButton -***********************************************************************/ - - void GuiSelectableButton::BeforeControlTemplateUninstalled_() - { - } - - void GuiSelectableButton::AfterControlTemplateInstalled_(bool initialize) - { - TypedControlTemplateObject(true)->SetSelected(isSelected); - } - - void GuiSelectableButton::OnClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - if(autoSelection) - { - SetSelected(!GetSelected()); - } - } - - GuiSelectableButton::GuiSelectableButton(theme::ThemeName themeName) - :GuiButton(themeName) - { - GroupControllerChanged.SetAssociatedComposition(boundsComposition); - AutoSelectionChanged.SetAssociatedComposition(boundsComposition); - SelectedChanged.SetAssociatedComposition(boundsComposition); - - Clicked.AttachMethod(this, &GuiSelectableButton::OnClicked); - } + }; - GuiSelectableButton::~GuiSelectableButton() + void GuiInstanceRootObject::InstallTimerCallback(controls::GuiControlHost* controlHost) { - if(groupController) + if (!timerCallback) { - groupController->Detach(this); + timerCallback = Ptr(new RootObjectTimerCallback(this, controlHost)); + controlHost->GetTimerManager()->AddCallback(timerCallback); } } - GuiSelectableButton::GroupController* GuiSelectableButton::GetGroupController() + bool GuiInstanceRootObject::UninstallTimerCallback(controls::GuiControlHost* controlHost) { - return groupController; - } - - void GuiSelectableButton::SetGroupController(GroupController* value) - { - if(groupController) + if (timerCallback && timerCallback->controlHost != controlHost) { - groupController->Detach(this); + timerCallback->alive = false; + timerCallback = nullptr; + return true; } - groupController=value; - if(groupController) - { - groupController->Attach(this); - } - GroupControllerChanged.Execute(GetNotifyEventArguments()); - } - - bool GuiSelectableButton::GetAutoSelection() - { - return autoSelection; - } - - void GuiSelectableButton::SetAutoSelection(bool value) - { - if(autoSelection!=value) - { - autoSelection=value; - AutoSelectionChanged.Execute(GetNotifyEventArguments()); - } - } - - bool GuiSelectableButton::GetSelected() - { - return isSelected; - } - - void GuiSelectableButton::SetSelected(bool value) - { - if (isSelected != value) - { - isSelected = value; - TypedControlTemplateObject(true)->SetSelected(isSelected); - if (groupController) - { - groupController->OnSelectedChanged(this); - } - SelectedChanged.Execute(GetNotifyEventArguments()); - } - } - } - } -} - -/*********************************************************************** -.\CONTROLS\GUICONTAINERCONTROLS.CPP -***********************************************************************/ - - -namespace vl -{ - namespace presentation - { - using namespace compositions; - - namespace controls - { - using namespace reflection::description; - -/*********************************************************************** -GuiTabPage -***********************************************************************/ - - bool GuiTabPage::IsAltAvailable() - { return false; } - GuiTabPage::GuiTabPage(theme::ThemeName themeName) - :GuiCustomControl(themeName) + void GuiInstanceRootObject::OnControlHostForInstanceChanged() { - } - - GuiTabPage::~GuiTabPage() - { - FinalizeAggregation(); - } - - GuiTab* GuiTabPage::GetOwnerTab() - { - return tab; - } - -/*********************************************************************** -GuiTabPageList -***********************************************************************/ - - bool GuiTabPageList::QueryInsert(vint index, GuiTabPage* const& value) - { - return !items.Contains(value) && value->tab == nullptr; - } - - void GuiTabPageList::AfterInsert(vint index, GuiTabPage* const& value) - { - value->tab = tab; - value->SetVisible(false); - value->boundsComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); - tab->containerComposition->AddChild(value->boundsComposition); - - if (!tab->selectedPage) + auto controlHost = GetControlHostForInstance(); + if (UninstallTimerCallback(controlHost)) { - tab->SetSelectedPage(value); - } - } - - void GuiTabPageList::BeforeRemove(vint index, GuiTabPage* const& value) - { - tab->containerComposition->RemoveChild(value->boundsComposition); - value->tab = nullptr; - - if (items.Count() <= 1) - { - tab->SetSelectedPage(nullptr); - } - else if (items.Count() > index + 1) - { - tab->SetSelectedPage(items[index + 1]); - } - else if (items.Count() == index + 1) - { - tab->SetSelectedPage(items[index - 1]); - } - } - - GuiTabPageList::GuiTabPageList(GuiTab* _tab) - :tab(_tab) - { - } - - GuiTabPageList::~GuiTabPageList() - { - } - -/*********************************************************************** -GuiTab::CommandExecutor -***********************************************************************/ - - GuiTab::CommandExecutor::CommandExecutor(GuiTab* _tab) - :tab(_tab) - { - } - - GuiTab::CommandExecutor::~CommandExecutor() - { - } - - void GuiTab::CommandExecutor::ShowTab(vint index, bool setFocus) - { - tab->SetSelectedPage(tab->GetPages().Get(index)); - if (setFocus) - { - tab->SetFocus(); - } - } - -/*********************************************************************** -GuiTab -***********************************************************************/ - - void GuiTab::BeforeControlTemplateUninstalled_() - { - auto ct = TypedControlTemplateObject(false); - if (!ct) return; - - ct->SetCommands(nullptr); - ct->SetTabPages(nullptr); - ct->SetSelectedTabPage(nullptr); - } - - void GuiTab::AfterControlTemplateInstalled_(bool initialize) - { - auto ct = TypedControlTemplateObject(true); - ct->SetCommands(commandExecutor.Obj()); - ct->SetTabPages(UnboxValue>(BoxParameter(tabPages))); - ct->SetSelectedTabPage(selectedPage); - } - - void GuiTab::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) - { - if (arguments.eventSource == focusableComposition) - { - if (auto ct = TypedControlTemplateObject(false)) + for (auto animation : runningAnimations) { - vint index = tabPages.IndexOf(selectedPage); - if (index != -1) - { - auto hint = ct->GetTabOrder(); - vint tabOffset = 0; - switch (hint) - { - case TabPageOrder::LeftToRight: - if (arguments.code == VKEY::KEY_LEFT) tabOffset = -1; - else if (arguments.code == VKEY::KEY_RIGHT) tabOffset = 1; - break; - case TabPageOrder::RightToLeft: - if (arguments.code == VKEY::KEY_LEFT) tabOffset = 1; - else if (arguments.code == VKEY::KEY_RIGHT) tabOffset = -1; - break; - case TabPageOrder::TopToBottom: - if (arguments.code == VKEY::KEY_UP) tabOffset = -1; - else if (arguments.code == VKEY::KEY_DOWN) tabOffset = 1; - break; - case TabPageOrder::BottomToTop: - if (arguments.code == VKEY::KEY_UP) tabOffset = 1; - else if (arguments.code == VKEY::KEY_DOWN) tabOffset = -1; - break; - default:; - } - - if (tabOffset != 0) - { - arguments.handled = true; - index += tabOffset; - if (index < 0) index = 0; - else if (index >= tabPages.Count()) index = tabPages.Count() - 1; - - SetSelectedPage(tabPages[index]); - } - } - } - } - } - - GuiTab::GuiTab(theme::ThemeName themeName) - :GuiControl(themeName) - , tabPages(this) - { - commandExecutor = Ptr(new CommandExecutor(this)); - SetFocusableComposition(boundsComposition); - - boundsComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiTab::OnKeyDown); - } - - GuiTab::~GuiTab() - { - } - - collections::ObservableList& GuiTab::GetPages() - { - return tabPages; - } - - GuiTabPage* GuiTab::GetSelectedPage() - { - return selectedPage; - } - - bool GuiTab::SetSelectedPage(GuiTabPage* value) - { - if (!value) - { - if (tabPages.Count() == 0) - { - selectedPage = nullptr; - } - } - else if (value->GetOwnerTab() == this) - { - if (selectedPage == value) - { - return true; - } - - selectedPage = value; - for (auto tabPage : tabPages) - { - tabPage->SetVisible(tabPage == selectedPage); - } - } - if (auto ct = TypedControlTemplateObject(false)) - { - ct->SetSelectedTabPage(selectedPage); - } - SelectedPageChanged.Execute(GetNotifyEventArguments()); - return selectedPage == value; - } - -/*********************************************************************** -GuiScrollView -***********************************************************************/ - - void GuiScrollView::BeforeControlTemplateUninstalled_() - { - auto ct = TypedControlTemplateObject(false); - if (!ct) return; - - if (auto scroll = ct->GetHorizontalScroll()) - { - scroll->PositionChanged.Detach(hScrollHandler); - } - if (auto scroll = ct->GetVerticalScroll()) - { - scroll->PositionChanged.Detach(vScrollHandler); - } - ct->GetEventReceiver()->horizontalWheel.Detach(hWheelHandler); - ct->GetEventReceiver()->verticalWheel.Detach(vWheelHandler); - ct->BoundsChanged.Detach(containerBoundsChangedHandler); - - hScrollHandler = nullptr; - vScrollHandler = nullptr; - hWheelHandler = nullptr; - vWheelHandler = nullptr; - containerBoundsChangedHandler = nullptr; - supressScrolling = false; - } - - void GuiScrollView::AfterControlTemplateInstalled_(bool initialize) - { - auto ct = TypedControlTemplateObject(true); - if (auto scroll = ct->GetHorizontalScroll()) - { - hScrollHandler = scroll->PositionChanged.AttachMethod(this, &GuiScrollView::OnHorizontalScroll); - } - if (auto scroll = ct->GetVerticalScroll()) - { - vScrollHandler = scroll->PositionChanged.AttachMethod(this, &GuiScrollView::OnVerticalScroll); - } - hWheelHandler = ct->GetEventReceiver()->horizontalWheel.AttachMethod(this, &GuiScrollView::OnHorizontalWheel); - vWheelHandler = ct->GetEventReceiver()->verticalWheel.AttachMethod(this, &GuiScrollView::OnVerticalWheel); - containerBoundsChangedHandler = ct->BoundsChanged.AttachMethod(this, &GuiScrollView::OnContainerBoundsChanged); - CalculateView(); - } - - void GuiScrollView::UpdateDisplayFont() - { - GuiControl::UpdateDisplayFont(); - CalculateView(); - } - - void GuiScrollView::OnContainerBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - InvokeOrDelayIfRendering([=]() - { - CalculateView(); - }); - } - - void GuiScrollView::OnHorizontalScroll(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - if(!supressScrolling) - { - CallUpdateView(); - } - } - - void GuiScrollView::OnVerticalScroll(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - if(!supressScrolling) - { - CallUpdateView(); - } - } - - void GuiScrollView::OnHorizontalWheel(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if(!supressScrolling) - { - if (auto scroll = TypedControlTemplateObject(true)->GetHorizontalScroll()) - { - if (scroll->GetEnabled()) - { - vint position = scroll->GetPosition(); - vint move = scroll->GetSmallMove(); - position -= move * arguments.wheel / 60; - scroll->SetPosition(position); - } - } - } - } - - void GuiScrollView::OnVerticalWheel(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if(!supressScrolling && GetVisuallyEnabled()) - { - if (auto scroll = TypedControlTemplateObject(true)->GetVerticalScroll()) - { - if (scroll->GetEnabled()) - { - vint position = scroll->GetPosition(); - vint move = scroll->GetSmallMove(); - position -= move * arguments.wheel / 60; - scroll->SetPosition(position); - } - } - } - } - - void GuiScrollView::CallUpdateView() - { - Rect viewBounds=GetViewBounds(); - UpdateView(viewBounds); - } - - bool GuiScrollView::AdjustView(Size fullSize) - { - auto ct = TypedControlTemplateObject(true); - auto hScroll = ct->GetHorizontalScroll(); - auto vScroll = ct->GetVerticalScroll(); - Size viewSize = ct->GetContainerComposition()->GetBounds().GetSize(); - - auto hVisible = hScroll ? hScroll->GetVisible() : false; - auto vVisible = vScroll ? vScroll->GetVisible() : false; - - if (hScroll) - { - if (fullSize.x <= viewSize.x) - { - hScroll->SetVisible(horizontalAlwaysVisible); - hScroll->SetEnabled(false); - hScroll->SetPosition(0); - } - else - { - hScroll->SetVisible(true); - hScroll->SetEnabled(true); - hScroll->SetTotalSize(fullSize.x); - hScroll->SetPageSize(viewSize.x); + animation->Pause(); } } - if (vScroll) + if (controlHost) { - if (fullSize.y <= viewSize.y) + InstallTimerCallback(controlHost); + for (auto animation : runningAnimations) { - vScroll->SetVisible(verticalAlwaysVisible); - vScroll->SetEnabled(false); - vScroll->SetPosition(0); + animation->Resume(); } - else + StartPendingAnimations(); + } + } + + void GuiInstanceRootObject::StartPendingAnimations() + { + for (auto animation : pendingAnimations) + { + animation->Start(); + } + + CopyFrom(runningAnimations, pendingAnimations, true); + pendingAnimations.Clear(); + } + + GuiInstanceRootObject::GuiInstanceRootObject() + { + } + + GuiInstanceRootObject::~GuiInstanceRootObject() + { + UninstallTimerCallback(nullptr); + } + + void GuiInstanceRootObject::FinalizeInstance() + { + if (!finalized) + { + finalized = true; + + for (auto subscription : subscriptions) { - vScroll->SetVisible(true); - vScroll->SetEnabled(true); - vScroll->SetTotalSize(fullSize.y); - vScroll->SetPageSize(viewSize.y); + subscription->Close(); } - } - - auto hVisible2 = hScroll ? hScroll->GetVisible() : false; - auto vVisible2 = vScroll ? vScroll->GetVisible() : false; - return hVisible != hVisible2 || vVisible != vVisible2; - } - - GuiScrollView::GuiScrollView(theme::ThemeName themeName) - :GuiControl(themeName) - { - containerComposition->BoundsChanged.AttachMethod(this, &GuiScrollView::OnContainerBoundsChanged); - } - - vint GuiScrollView::GetSmallMove() - { - return GetDisplayFont().size * 2; - } - - Size GuiScrollView::GetBigMove() - { - return GetViewSize(); - } - - GuiScrollView::~GuiScrollView() - { - } - - void GuiScrollView::CalculateView() - { - auto ct = TypedControlTemplateObject(true); - auto hScroll = ct->GetHorizontalScroll(); - auto vScroll = ct->GetVerticalScroll(); - - if (!supressScrolling) - { - Size fullSize = QueryFullSize(); - while (true) + for (auto component : components) { - bool flagA = false; - bool flagB = false; - - flagA = AdjustView(fullSize); - bool bothInvisible = (hScroll ? !hScroll->GetVisible() : true) && (vScroll ? !vScroll->GetVisible() : true); - - if (!bothInvisible) - { - flagB = AdjustView(fullSize); - bothInvisible = (hScroll ? !hScroll->GetVisible() : true) && (vScroll ? !vScroll->GetVisible() : true); - } - - supressScrolling = true; - CallUpdateView(); - supressScrolling = false; - - Size newSize = QueryFullSize(); - if (fullSize == newSize) - { - vint smallMove = GetSmallMove(); - Size bigMove = GetBigMove(); - if (hScroll) - { - hScroll->SetSmallMove(smallMove); - hScroll->SetBigMove(bigMove.x); - } - if (vScroll) - { - vScroll->SetSmallMove(smallMove); - vScroll->SetBigMove(bigMove.y); - } - - if (bothInvisible || !flagA && !flagB) - { - break; - } - } - else - { - fullSize = newSize; - } + component->Detach(this); } - } - } - Size GuiScrollView::GetViewSize() - { - Size viewSize = TypedControlTemplateObject(true)->GetContainerComposition()->GetBounds().GetSize(); - return viewSize; - } - - Rect GuiScrollView::GetViewBounds() - { - return Rect(GetViewPosition(), GetViewSize()); - } - - Point GuiScrollView::GetViewPosition() - { - auto ct = TypedControlTemplateObject(true); - auto hScroll = ct->GetHorizontalScroll(); - auto vScroll = ct->GetVerticalScroll(); - return Point(hScroll ? hScroll->GetPosition() : 0, vScroll ? vScroll->GetPosition() : 0); - } - - void GuiScrollView::SetViewPosition(Point value) - { - auto ct = TypedControlTemplateObject(true); - if (auto hScroll = ct->GetHorizontalScroll()) - { - hScroll->SetPosition(value.x); - } - if (auto vScroll = ct->GetVerticalScroll()) - { - vScroll->SetPosition(value.y); - } - } - - GuiScroll* GuiScrollView::GetHorizontalScroll() - { - return TypedControlTemplateObject(true)->GetHorizontalScroll(); - } - - GuiScroll* GuiScrollView::GetVerticalScroll() - { - return TypedControlTemplateObject(true)->GetVerticalScroll(); - } - - bool GuiScrollView::GetHorizontalAlwaysVisible() - { - return horizontalAlwaysVisible; - } - - void GuiScrollView::SetHorizontalAlwaysVisible(bool value) - { - if (horizontalAlwaysVisible != value) - { - horizontalAlwaysVisible = value; - CalculateView(); - } - } - - bool GuiScrollView::GetVerticalAlwaysVisible() - { - return verticalAlwaysVisible; - } - - void GuiScrollView::SetVerticalAlwaysVisible(bool value) - { - if (verticalAlwaysVisible != value) - { - verticalAlwaysVisible = value; - CalculateView(); - } - } - -/*********************************************************************** -GuiScrollContainer -***********************************************************************/ - - Size GuiScrollContainer::QueryFullSize() - { - return containerComposition->GetBounds().GetSize(); - } - - void GuiScrollContainer::UpdateView(Rect viewBounds) - { - auto leftTop = Point(-viewBounds.x1, -viewBounds.y1); - containerComposition->SetBounds(Rect(leftTop, Size(0, 0))); - } - - GuiScrollContainer::GuiScrollContainer(theme::ThemeName themeName) - :GuiScrollView(themeName) - { - containerComposition->SetAlignmentToParent(Margin(-1, -1, -1, -1)); - UpdateView(Rect(0, 0, 0, 0)); - } - - GuiScrollContainer::~GuiScrollContainer() - { - } - - bool GuiScrollContainer::GetExtendToFullWidth() - { - return extendToFullWidth; - } - - void GuiScrollContainer::SetExtendToFullWidth(bool value) - { - if (extendToFullWidth != value) - { - extendToFullWidth = value; - auto margin = containerComposition->GetAlignmentToParent(); - if (value) + subscriptions.Clear(); + for (vint i = 0; iSetAlignmentToParent(Margin(0, margin.top, 0, margin.bottom)); - } - else - { - containerComposition->SetAlignmentToParent(Margin(-1, margin.top, -1, margin.bottom)); + delete components[i]; } + components.Clear(); } } - bool GuiScrollContainer::GetExtendToFullHeight() + bool GuiInstanceRootObject::IsFinalized() { - return extendToFullHeight; + return finalized; } - void GuiScrollContainer::SetExtendToFullHeight(bool value) + void GuiInstanceRootObject::FinalizeInstanceRecursively(templates::GuiTemplate* thisObject) { - if (extendToFullHeight != value) + if (!finalized) { - extendToFullHeight = value; - auto margin = containerComposition->GetAlignmentToParent(); - if (value) - { - containerComposition->SetAlignmentToParent(Margin(margin.left, 0, margin.right, 0)); - } - else - { - containerComposition->SetAlignmentToParent(Margin(margin.left, -1, margin.right, -1)); - } + NotifyFinalizeInstance(thisObject); } } - } - } -} -/*********************************************************************** -.\CONTROLS\GUIDATETIMECONTROLS.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace collections; - using namespace compositions; - using namespace elements; - -/*********************************************************************** -GuiDatePicker::CommandExecutor -***********************************************************************/ - - GuiDatePicker::CommandExecutor::CommandExecutor(GuiDatePicker* _datePicker) - :datePicker(_datePicker) + void GuiInstanceRootObject::FinalizeInstanceRecursively(GuiCustomControl* thisObject) { - } - - GuiDatePicker::CommandExecutor::~CommandExecutor() - { - } - - void GuiDatePicker::CommandExecutor::NotifyDateChanged() - { - datePicker->date = datePicker->TypedControlTemplateObject(true)->GetDate(); - datePicker->UpdateText(); - datePicker->DateChanged.Execute(datePicker->GetNotifyEventArguments()); - } - - void GuiDatePicker::CommandExecutor::NotifyDateNavigated() - { - datePicker->DateNavigated.Execute(datePicker->GetNotifyEventArguments()); - } - - void GuiDatePicker::CommandExecutor::NotifyDateSelected() - { - datePicker->DateSelected.Execute(datePicker->GetNotifyEventArguments()); - } - -/*********************************************************************** -GuiDatePicker -***********************************************************************/ - - void GuiDatePicker::BeforeControlTemplateUninstalled_() - { - auto ct = TypedControlTemplateObject(false); - if (!ct) return; - - ct->SetCommands(nullptr); - } - - void GuiDatePicker::AfterControlTemplateInstalled_(bool initialize) - { - auto ct = TypedControlTemplateObject(true); - ct->SetCommands(commandExecutor.Obj()); - ct->SetDate(date); - ct->SetDateLocale(dateLocale); - UpdateText(); - } - - void GuiDatePicker::UpdateText() - { - GuiControl::SetText(dateLocale.FormatDate(dateFormat, date)); - } - - bool GuiDatePicker::IsAltAvailable() - { - if (nestedAlt) + if (!finalized) { - return alt != L""; + NotifyFinalizeInstance(thisObject); + } + } + + void GuiInstanceRootObject::FinalizeInstanceRecursively(GuiControlHost* thisObject) + { + if (!finalized) + { + NotifyFinalizeInstance(thisObject); + } + } + + void GuiInstanceRootObject::FinalizeGeneralInstance(GuiInstanceRootObject* thisObject) + { + } + + void GuiInstanceRootObject::SetResourceResolver(Ptr resolver) + { + resourceResolver = resolver; + } + + Ptr GuiInstanceRootObject::ResolveResource(const WString& protocol, const WString& path, bool ensureExist) + { + Ptr object; + if (resourceResolver) + { + object = resourceResolver->ResolveResource(protocol, path); + } + if (ensureExist && !object) + { + throw ArgumentException(L"Resource \"" + protocol + L"://" + path + L"\" does not exist."); + } + return object; + } + + Ptr GuiInstanceRootObject::AddSubscription(Ptr subscription) + { + CHECK_ERROR(finalized == false, L"GuiInstanceRootObject::AddSubscription(Ptr)#Cannot add subscription after finalizing."); + if (subscriptions.Contains(subscription.Obj())) + { + return nullptr; } else { - return GuiControl::IsAltAvailable(); + subscriptions.Add(subscription); + subscription->Open(); + subscription->Update(); + return subscription; } } - compositions::IGuiAltActionHost* GuiDatePicker::GetActivatingAltHost() + void GuiInstanceRootObject::UpdateSubscriptions() { - if (nestedAlt) + for (auto subscription : subscriptions) { - return this; + subscription->Update(); + } + } + + bool GuiInstanceRootObject::AddComponent(GuiComponent* component) + { + CHECK_ERROR(finalized == false, L"GuiInstanceRootObject::AddComponent(GuiComponent*)#Cannot add component after finalizing."); + if(components.Contains(component)) + { + return false; } else { - return GuiControl::GetActivatingAltHost(); + components.Add(component); + component->Attach(this); + return true; } } - GuiDatePicker::GuiDatePicker(theme::ThemeName themeName, bool _nestedAlt) - :GuiControl(themeName) - , nestedAlt(_nestedAlt) + bool GuiInstanceRootObject::AddControlHostComponent(GuiControlHost* controlHost) { - commandExecutor = Ptr(new CommandExecutor(this)); - SetDate(DateTime::LocalTime()); - SetDateLocale(Locale::UserDefault()); - SetAltComposition(boundsComposition); - SetAltControl(this, false); - - DateChanged.SetAssociatedComposition(boundsComposition); - DateNavigated.SetAssociatedComposition(boundsComposition); - DateSelected.SetAssociatedComposition(boundsComposition); - DateFormatChanged.SetAssociatedComposition(boundsComposition); - DateLocaleChanged.SetAssociatedComposition(boundsComposition); - - commandExecutor->NotifyDateChanged(); + return AddComponent(new GuiObjectComponent(Ptr(controlHost))); } - GuiDatePicker::~GuiDatePicker() + bool GuiInstanceRootObject::AddAnimation(Ptr animation) { - } - - const DateTime& GuiDatePicker::GetDate() - { - return date; - } - - void GuiDatePicker::SetDate(const DateTime& value) - { - if (date != value) + CHECK_ERROR(finalized == false, L"GuiInstanceRootObject::AddAnimation(Ptr)#Cannot add animation after finalizing."); + if (runningAnimations.Contains(animation.Obj()) || pendingAnimations.Contains(animation.Obj())) { - date = value; - TypedControlTemplateObject(true)->SetDate(value); + return false; } - } - - const WString& GuiDatePicker::GetDateFormat() - { - return dateFormat; - } - - void GuiDatePicker::SetDateFormat(const WString& value) - { - dateFormat=value; - UpdateText(); - DateFormatChanged.Execute(GetNotifyEventArguments()); - } - - const Locale& GuiDatePicker::GetDateLocale() - { - return dateLocale; - } - - void GuiDatePicker::SetDateLocale(const Locale& value) - { - dateLocale=value; - List formats; - dateLocale.GetLongDateFormats(formats); - if(formats.Count()>0) + else { - dateFormat=formats[0]; + pendingAnimations.Add(animation); + + if (auto controlHost = GetControlHostForInstance()) + { + InstallTimerCallback(controlHost); + StartPendingAnimations(); + } + return true; } - TypedControlTemplateObject(true)->SetDateLocale(dateLocale); - - UpdateText(); - DateFormatChanged.Execute(GetNotifyEventArguments()); - DateLocaleChanged.Execute(GetNotifyEventArguments()); } - void GuiDatePicker::SetText(const WString& value) + bool GuiInstanceRootObject::KillAnimation(Ptr animation) { - } - -/*********************************************************************** -GuiDateComboBox -***********************************************************************/ - - void GuiDateComboBox::BeforeControlTemplateUninstalled_() - { - } - - void GuiDateComboBox::AfterControlTemplateInstalled_(bool initialize) - { - auto ct = TypedControlTemplateObject(true); - datePicker->SetControlTemplate(ct->GetDatePickerTemplate()); - } - - void GuiDateComboBox::UpdateText() - { - SetText(datePicker->GetDateLocale().FormatDate(datePicker->GetDateFormat(), selectedDate)); - } - - void GuiDateComboBox::NotifyUpdateSelectedDate() - { - UpdateText(); - SelectedDateChanged.Execute(GetNotifyEventArguments()); - } - - void GuiDateComboBox::OnSubMenuOpeningChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - datePicker->SetDate(selectedDate); - } - - void GuiDateComboBox::datePicker_DateLocaleChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - UpdateText(); - } - - void GuiDateComboBox::datePicker_DateFormatChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - UpdateText(); - } - - void GuiDateComboBox::datePicker_DateSelected(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - selectedDate=datePicker->GetDate(); - GetSubMenu()->Hide(); - NotifyUpdateSelectedDate(); - } - - GuiDateComboBox::GuiDateComboBox(theme::ThemeName themeName) - :GuiComboBoxBase(themeName) - { - SelectedDateChanged.SetAssociatedComposition(GetBoundsComposition()); - - datePicker = new GuiDatePicker(theme::ThemeName::DatePicker, false); - datePicker->DateSelected.AttachMethod(this, &GuiDateComboBox::datePicker_DateSelected); - datePicker->DateLocaleChanged.AttachMethod(this, &GuiDateComboBox::datePicker_DateLocaleChanged); - datePicker->DateFormatChanged.AttachMethod(this, &GuiDateComboBox::datePicker_DateFormatChanged); - datePicker->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); - - GetSubMenu()->GetContainerComposition()->AddChild(datePicker->GetBoundsComposition()); - GetSubMenu()->SetHideOnDeactivateAltHost(false); - - selectedDate=datePicker->GetDate(); - SubMenuOpeningChanged.AttachMethod(this, &GuiDateComboBox::OnSubMenuOpeningChanged); - SetFont(GetFont()); - SetText(datePicker->GetText()); - } - - GuiDateComboBox::~GuiDateComboBox() - { - } - - void GuiDateComboBox::SetFont(const Nullable& value) - { - GuiComboBoxBase::SetFont(value); - datePicker->SetFont(value); - } - - const DateTime& GuiDateComboBox::GetSelectedDate() - { - return selectedDate; - } - - void GuiDateComboBox::SetSelectedDate(const DateTime& value) - { - selectedDate=value; - NotifyUpdateSelectedDate(); - } - - GuiDatePicker* GuiDateComboBox::GetDatePicker() - { - return datePicker; + if (!animation) return false; + if (runningAnimations.Contains(animation.Obj())) + { + runningAnimations.Remove(animation.Obj()); + return true; + } + if (pendingAnimations.Contains(animation.Obj())) + { + pendingAnimations.Remove(animation.Obj()); + return true; + } + return false; } } } } /*********************************************************************** -.\CONTROLS\GUIDIALOGS.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace elements; - using namespace compositions; - using namespace collections; - using namespace reflection::description; - -/*********************************************************************** -GuiDialogBase -***********************************************************************/ - - GuiWindow* GuiDialogBase::GetHostWindow() - { - if (rootObject) - { - if (auto control = dynamic_cast(rootObject)) - { - if (auto host = control->GetRelatedControlHost()) - { - return dynamic_cast(host); - } - } - else if (auto composition = dynamic_cast(rootObject)) - { - if (auto host = composition->GetRelatedControlHost()) - { - return dynamic_cast(host); - } - } - } - return nullptr; - } - - GuiDialogBase::GuiDialogBase() - { - } - - GuiDialogBase::~GuiDialogBase() - { - } - - void GuiDialogBase::Attach(GuiInstanceRootObject* _rootObject) - { - rootObject = _rootObject; - } - - void GuiDialogBase::Detach(GuiInstanceRootObject* _rootObject) - { - rootObject = nullptr; - } - -/*********************************************************************** -GuiMessageDialog -***********************************************************************/ - - GuiMessageDialog::GuiMessageDialog() - { - } - - GuiMessageDialog::~GuiMessageDialog() - { - } - - INativeDialogService::MessageBoxButtonsInput GuiMessageDialog::GetInput() - { - return input; - } - - void GuiMessageDialog::SetInput(INativeDialogService::MessageBoxButtonsInput value) - { - input = value; - } - - INativeDialogService::MessageBoxDefaultButton GuiMessageDialog::GetDefaultButton() - { - return defaultButton; - } - - void GuiMessageDialog::SetDefaultButton(INativeDialogService::MessageBoxDefaultButton value) - { - defaultButton = value; - } - - INativeDialogService::MessageBoxIcons GuiMessageDialog::GetIcon() - { - return icon; - } - - void GuiMessageDialog::SetIcon(INativeDialogService::MessageBoxIcons value) - { - icon = value; - } - - INativeDialogService::MessageBoxModalOptions GuiMessageDialog::GetModalOption() - { - return modalOption; - } - - void GuiMessageDialog::SetModalOption(INativeDialogService::MessageBoxModalOptions value) - { - modalOption = value; - } - - const WString& GuiMessageDialog::GetText() - { - return text; - } - - void GuiMessageDialog::SetText(const WString& value) - { - text = value; - } - - const WString& GuiMessageDialog::GetTitle() - { - return title; - } - - void GuiMessageDialog::SetTitle(const WString& value) - { - title = value; - } - - INativeDialogService::MessageBoxButtonsOutput GuiMessageDialog::ShowDialog() - { - auto service = GetCurrentController()->DialogService(); - return service->ShowMessageBox(GetHostWindow()->GetNativeWindow(), text, title, input, defaultButton, icon, modalOption); - } - -/*********************************************************************** -GuiColorDialog -***********************************************************************/ - - GuiColorDialog::GuiColorDialog() - { - for (vint i = 0; i < 16; i++) - { - customColors.Add(Color()); - } - } - - GuiColorDialog::~GuiColorDialog() - { - } - - bool GuiColorDialog::GetEnabledCustomColor() - { - return enabledCustomColor; - } - - void GuiColorDialog::SetEnabledCustomColor(bool value) - { - enabledCustomColor = value; - } - - bool GuiColorDialog::GetOpenedCustomColor() - { - return openedCustomColor; - } - - void GuiColorDialog::SetOpenedCustomColor(bool value) - { - openedCustomColor = value; - } - - Color GuiColorDialog::GetSelectedColor() - { - return selectedColor; - } - - void GuiColorDialog::SetSelectedColor(Color value) - { - if (selectedColor != value) - { - selectedColor = value; - SelectedColorChanged.Execute(GuiEventArgs()); - } - } - - collections::List& GuiColorDialog::GetCustomColors() - { - return customColors; - } - - bool GuiColorDialog::ShowDialog() - { - Array colors; - CopyFrom(colors, customColors); - colors.Resize(16); - - INativeDialogService::ColorDialogCustomColorOptions options = - !enabledCustomColor ? INativeDialogService::CustomColorDisabled : - !openedCustomColor ? INativeDialogService::CustomColorEnabled : - INativeDialogService::CustomColorOpened; - - auto service = GetCurrentController()->DialogService(); - if (!service->ShowColorDialog(GetHostWindow()->GetNativeWindow(), selectedColor, showSelection, options, &colors[0])) - { - return false; - } - - CopyFrom(customColors, colors); - SelectedColorChanged.Execute(GuiEventArgs()); - return true; - } - -/*********************************************************************** -GuiFontDialog -***********************************************************************/ - - GuiFontDialog::GuiFontDialog() - { - } - - GuiFontDialog::~GuiFontDialog() - { - } - - const FontProperties& GuiFontDialog::GetSelectedFont() - { - return selectedFont; - } - - void GuiFontDialog::SetSelectedFont(const FontProperties& value) - { - if (selectedFont != value) - { - selectedFont = value; - SelectedFontChanged.Execute(GuiEventArgs()); - } - } - - Color GuiFontDialog::GetSelectedColor() - { - return selectedColor; - } - - void GuiFontDialog::SetSelectedColor(Color value) - { - if (selectedColor != value) - { - selectedColor = value; - SelectedColorChanged.Execute(GuiEventArgs()); - } - } - - bool GuiFontDialog::GetShowSelection() - { - return showSelection; - } - - void GuiFontDialog::SetShowSelection(bool value) - { - showSelection = value; - } - - bool GuiFontDialog::GetShowEffect() - { - return showEffect; - } - - void GuiFontDialog::SetShowEffect(bool value) - { - showEffect = value; - } - - bool GuiFontDialog::GetForceFontExist() - { - return forceFontExist; - } - - void GuiFontDialog::SetForceFontExist(bool value) - { - forceFontExist = value; - } - - bool GuiFontDialog::ShowDialog() - { - auto service = GetCurrentController()->DialogService(); - if (!service->ShowFontDialog(GetHostWindow()->GetNativeWindow(), selectedFont, selectedColor, showSelection, showEffect, forceFontExist)) - { - return false; - } - - SelectedColorChanged.Execute(GuiEventArgs()); - SelectedFontChanged.Execute(GuiEventArgs()); - return true; - } - -/*********************************************************************** -GuiFileDialogBase -***********************************************************************/ - - GuiFileDialogBase::GuiFileDialogBase() - { - } - - GuiFileDialogBase::~GuiFileDialogBase() - { - } - - const WString& GuiFileDialogBase::GetFilter() - { - return filter; - } - - void GuiFileDialogBase::SetFilter(const WString& value) - { - filter = value; - } - - vint GuiFileDialogBase::GetFilterIndex() - { - return filterIndex; - } - - void GuiFileDialogBase::SetFilterIndex(vint value) - { - if (filterIndex != value) - { - filterIndex = value; - FilterIndexChanged.Execute(GuiEventArgs()); - } - } - - bool GuiFileDialogBase::GetEnabledPreview() - { - return enabledPreview; - } - - void GuiFileDialogBase::SetEnabledPreview(bool value) - { - enabledPreview = value; - } - - WString GuiFileDialogBase::GetTitle() - { - return title; - } - - void GuiFileDialogBase::SetTitle(const WString& value) - { - title = value; - } - - WString GuiFileDialogBase::GetFileName() - { - return fileName; - } - - void GuiFileDialogBase::SetFileName(const WString& value) - { - if (fileName != value) - { - FileNameChanged.Execute(GuiEventArgs()); - } - } - - WString GuiFileDialogBase::GetDirectory() - { - return directory; - } - - void GuiFileDialogBase::SetDirectory(const WString& value) - { - directory = value; - } - - WString GuiFileDialogBase::GetDefaultExtension() - { - return defaultExtension; - } - - void GuiFileDialogBase::SetDefaultExtension(const WString& value) - { - defaultExtension = value; - } - - INativeDialogService::FileDialogOptions GuiFileDialogBase::GetOptions() - { - return options; - } - - void GuiFileDialogBase::SetOptions(INativeDialogService::FileDialogOptions value) - { - options = value; - } - -/*********************************************************************** -GuiOpenFileDialog -***********************************************************************/ - - GuiOpenFileDialog::GuiOpenFileDialog() - { - } - - GuiOpenFileDialog::~GuiOpenFileDialog() - { - } - - collections::List& GuiOpenFileDialog::GetFileNames() - { - return fileNames; - } - - bool GuiOpenFileDialog::ShowDialog() - { - fileNames.Clear(); - auto service = GetCurrentController()->DialogService(); - if (!service->ShowFileDialog( - GetHostWindow()->GetNativeWindow(), - fileNames, - filterIndex, - (enabledPreview ? INativeDialogService::FileDialogOpenPreview : INativeDialogService::FileDialogOpen), - title, - fileName, - directory, - defaultExtension, - filter, - options)) - { - return false; - } - - if (fileNames.Count() > 0) - { - fileName = fileNames[0]; - FileNameChanged.Execute(GuiEventArgs()); - FilterIndexChanged.Execute(GuiEventArgs()); - } - return true; - } - -/*********************************************************************** -GuiSaveFileDialog -***********************************************************************/ - - GuiSaveFileDialog::GuiSaveFileDialog() - { - } - - GuiSaveFileDialog::~GuiSaveFileDialog() - { - } - - bool GuiSaveFileDialog::ShowDialog() - { - List fileNames; - auto service = GetCurrentController()->DialogService(); - if (!service->ShowFileDialog( - GetHostWindow()->GetNativeWindow(), - fileNames, - filterIndex, - (enabledPreview ? INativeDialogService::FileDialogSavePreview : INativeDialogService::FileDialogSave), - title, - fileName, - directory, - defaultExtension, - filter, - options)) - { - return false; - } - - if (fileNames.Count() > 0) - { - fileName = fileNames[0]; - FileNameChanged.Execute(GuiEventArgs()); - FilterIndexChanged.Execute(GuiEventArgs()); - } - return true; - } - } - } -} - -/*********************************************************************** -.\CONTROLS\GUILABELCONTROLS.CPP +.\APPLICATION\CONTROLS\GUILABELCONTROLS.CPP ***********************************************************************/ namespace vl @@ -3305,284 +1697,54 @@ GuiLabel } /*********************************************************************** -.\CONTROLS\GUISCROLLCONTROLS.CPP +.\APPLICATION\CONTROLS\GUITHEMEMANAGER.CPP ***********************************************************************/ namespace vl { namespace presentation { - namespace controls + namespace templates { - using namespace elements; - using namespace compositions; - using namespace collections; - using namespace reflection::description; /*********************************************************************** -GuiScroll::CommandExecutor +GuiTemplate ***********************************************************************/ - GuiScroll::CommandExecutor::CommandExecutor(GuiScroll* _scroll) - :scroll(_scroll) + GuiTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) + + controls::GuiControlHost* GuiTemplate::GetControlHostForInstance() { + return GetRelatedControlHost(); } - GuiScroll::CommandExecutor::~CommandExecutor() + void GuiTemplate::OnParentLineChanged() { + GuiBoundsComposition::OnParentLineChanged(); + OnControlHostForInstanceChanged(); } - void GuiScroll::CommandExecutor::SmallDecrease() + GuiTemplate::GuiTemplate() { - scroll->SetPosition(scroll->GetPosition()-scroll->GetSmallMove()); + GuiTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } - void GuiScroll::CommandExecutor::SmallIncrease() + GuiTemplate::~GuiTemplate() { - scroll->SetPosition(scroll->GetPosition()+scroll->GetSmallMove()); - } - - void GuiScroll::CommandExecutor::BigDecrease() - { - scroll->SetPosition(scroll->GetPosition()-scroll->GetBigMove()); - } - - void GuiScroll::CommandExecutor::BigIncrease() - { - scroll->SetPosition(scroll->GetPosition()+scroll->GetBigMove()); - } - - void GuiScroll::CommandExecutor::SetTotalSize(vint value) - { - scroll->SetTotalSize(value); - } - - void GuiScroll::CommandExecutor::SetPageSize(vint value) - { - scroll->SetPageSize(value); - } - - void GuiScroll::CommandExecutor::SetPosition(vint value) - { - scroll->SetPosition(value); + FinalizeInstanceRecursively(this); } /*********************************************************************** -GuiScroll +Template Declarations ***********************************************************************/ - void GuiScroll::OnActiveAlt() - { - if (autoFocus) - { - GuiControl::OnActiveAlt(); - } - } - - bool GuiScroll::IsTabAvailable() - { - return autoFocus && GuiControl::IsTabAvailable(); - } - - void GuiScroll::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) - { - if (arguments.eventSource == focusableComposition) - { - switch (arguments.code) - { - case VKEY::KEY_HOME: - SetPosition(GetMinPosition()); - arguments.handled = true; - break; - case VKEY::KEY_END: - SetPosition(GetMaxPosition()); - arguments.handled = true; - break; - case VKEY::KEY_PRIOR: - commandExecutor->BigDecrease(); - arguments.handled = true; - break; - case VKEY::KEY_NEXT: - commandExecutor->BigIncrease(); - arguments.handled = true; - break; - case VKEY::KEY_LEFT: - case VKEY::KEY_UP: - commandExecutor->SmallDecrease(); - arguments.handled = true; - break; - case VKEY::KEY_RIGHT: - case VKEY::KEY_DOWN: - commandExecutor->SmallIncrease(); - arguments.handled = true; - break; - default:; - } - } - } - - void GuiScroll::OnMouseDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if (autoFocus) - { - SetFocus(); - } - } - - void GuiScroll::BeforeControlTemplateUninstalled_() - { - auto ct = TypedControlTemplateObject(false); - if (!ct) return; - - ct->SetCommands(nullptr); - } - - void GuiScroll::AfterControlTemplateInstalled_(bool initialize) - { - auto ct = TypedControlTemplateObject(true); - ct->SetCommands(commandExecutor.Obj()); - ct->SetPageSize(pageSize); - ct->SetTotalSize(totalSize); - ct->SetPosition(position); - } - - GuiScroll::GuiScroll(theme::ThemeName themeName) - :GuiControl(themeName) - { - SetFocusableComposition(boundsComposition); - - TotalSizeChanged.SetAssociatedComposition(boundsComposition); - PageSizeChanged.SetAssociatedComposition(boundsComposition); - PositionChanged.SetAssociatedComposition(boundsComposition); - SmallMoveChanged.SetAssociatedComposition(boundsComposition); - BigMoveChanged.SetAssociatedComposition(boundsComposition); - - commandExecutor = Ptr(new CommandExecutor(this)); - boundsComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiScroll::OnKeyDown); - boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiScroll::OnMouseDown); - boundsComposition->GetEventReceiver()->rightButtonDown.AttachMethod(this, &GuiScroll::OnMouseDown); - } - - GuiScroll::~GuiScroll() - { - } - - vint GuiScroll::GetTotalSize() - { - return totalSize; - } - - void GuiScroll::SetTotalSize(vint value) - { - if(totalSize!=value && 0totalSize) - { - SetPageSize(totalSize); - } - if(position>GetMaxPosition()) - { - SetPosition(GetMaxPosition()); - } - TypedControlTemplateObject(true)->SetTotalSize(totalSize); - TotalSizeChanged.Execute(GetNotifyEventArguments()); - } - } - - vint GuiScroll::GetPageSize() - { - return pageSize; - } - - void GuiScroll::SetPageSize(vint value) - { - if(pageSize!=value && 0<=value && value<=totalSize) - { - pageSize=value; - if(position>GetMaxPosition()) - { - SetPosition(GetMaxPosition()); - } - TypedControlTemplateObject(true)->SetPageSize(pageSize); - PageSizeChanged.Execute(GetNotifyEventArguments()); - } - } - - vint GuiScroll::GetPosition() - { - return position; - } - - void GuiScroll::SetPosition(vint value) - { - vint min=GetMinPosition(); - vint max=GetMaxPosition(); - vint newPosition= - valuemax?max: - value; - if(position!=newPosition) - { - position=newPosition; - TypedControlTemplateObject(true)->SetPosition(position); - PositionChanged.Execute(GetNotifyEventArguments()); - } - } - - vint GuiScroll::GetSmallMove() - { - return smallMove; - } - - void GuiScroll::SetSmallMove(vint value) - { - if(value>0 && smallMove!=value) - { - smallMove=value; - SmallMoveChanged.Execute(GetNotifyEventArguments()); - } - } - - vint GuiScroll::GetBigMove() - { - return bigMove; - } - - void GuiScroll::SetBigMove(vint value) - { - if(value>0 && bigMove!=value) - { - bigMove=value; - BigMoveChanged.Execute(GetNotifyEventArguments()); - } - } - - vint GuiScroll::GetMinPosition() - { - return 0; - } - - vint GuiScroll::GetMaxPosition() - { - return totalSize-pageSize; - } - - bool GuiScroll::GetAutoFocus() - { - return autoFocus; - } - - void GuiScroll::SetAutoFocus(bool value) - { - autoFocus = value; - } + GUI_CORE_CONTROL_TEMPLATE_DECL(GUI_TEMPLATE_CLASS_IMPL) } } } /*********************************************************************** -.\CONTROLS\GUIWINDOWCONTROLS.CPP +.\APPLICATION\CONTROLS\GUIWINDOWCONTROLS.CPP ***********************************************************************/ namespace vl @@ -4822,6 +2984,4518 @@ GuiPopup } +/*********************************************************************** +.\APPLICATION\GRAPHICSCOMPOSITIONS\GUIGRAPHICSBASICCOMPOSITION.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace compositions + { + using namespace collections; + using namespace elements; + +/*********************************************************************** +GuiBoundsComposition +***********************************************************************/ + + GuiBoundsComposition::GuiBoundsComposition() + { + } + + GuiBoundsComposition::~GuiBoundsComposition() + { + } + + bool GuiBoundsComposition::GetSizeAffectParent() + { + return sizeAffectParent; + } + + void GuiBoundsComposition::SetSizeAffectParent(bool value) + { + sizeAffectParent = value; + } + + bool GuiBoundsComposition::IsSizeAffectParent() + { + return sizeAffectParent; + } + + Rect GuiBoundsComposition::GetPreferredBounds() + { + Rect result = GetBoundsInternal(compositionBounds); + if (GetParent() && IsAlignedToParent()) + { + if (alignmentToParent.left >= 0) + { + vint offset = alignmentToParent.left - result.x1; + result.x1 += offset; + result.x2 += offset; + } + if (alignmentToParent.top >= 0) + { + vint offset = alignmentToParent.top - result.y1; + result.y1 += offset; + result.y2 += offset; + } + if (alignmentToParent.right >= 0) + { + result.x2 += alignmentToParent.right; + } + if (alignmentToParent.bottom >= 0) + { + result.y2 += alignmentToParent.bottom; + } + } + return result; + } + + Rect GuiBoundsComposition::GetBounds() + { + Rect result = GetPreferredBounds(); + if (GetParent() && IsAlignedToParent()) + { + Size clientSize = GetParent()->GetClientArea().GetSize(); + if (alignmentToParent.left >= 0 && alignmentToParent.right >= 0) + { + result.x1 = alignmentToParent.left; + result.x2 = clientSize.x - alignmentToParent.right; + } + else if (alignmentToParent.left >= 0) + { + vint width = result.Width(); + result.x1 = alignmentToParent.left; + result.x2 = result.x1 + width; + } + else if (alignmentToParent.right >= 0) + { + vint width = result.Width(); + result.x2 = clientSize.x - alignmentToParent.right; + result.x1 = result.x2 - width; + } + + if (alignmentToParent.top >= 0 && alignmentToParent.bottom >= 0) + { + result.y1 = alignmentToParent.top; + result.y2 = clientSize.y - alignmentToParent.bottom; + } + else if (alignmentToParent.top >= 0) + { + vint height = result.Height(); + result.y1 = alignmentToParent.top; + result.y2 = result.y1 + height; + } + else if (alignmentToParent.bottom >= 0) + { + vint height = result.Height(); + result.y2 = clientSize.y - alignmentToParent.bottom; + result.y1 = result.y2 - height; + } + } + UpdatePreviousBounds(result); + return result; + } + + void GuiBoundsComposition::SetBounds(Rect value) + { + compositionBounds = value; + InvokeOnCompositionStateChanged(); + } + + Margin GuiBoundsComposition::GetAlignmentToParent() + { + return alignmentToParent; + } + + void GuiBoundsComposition::SetAlignmentToParent(Margin value) + { + alignmentToParent = value; + InvokeOnCompositionStateChanged(); + } + + bool GuiBoundsComposition::IsAlignedToParent() + { + return alignmentToParent != Margin(-1, -1, -1, -1); + } + } + } +} + +/*********************************************************************** +.\APPLICATION\GRAPHICSCOMPOSITIONS\GUIGRAPHICSCOMPOSITIONBASE.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace compositions + { + using namespace collections; + using namespace controls; + using namespace elements; + + void InvokeOnCompositionStateChanged(compositions::GuiGraphicsComposition* composition) + { + composition->InvokeOnCompositionStateChanged(); + } + +/*********************************************************************** +GuiWindowComposition +***********************************************************************/ + + GuiWindowComposition::GuiWindowComposition() + { + } + + GuiWindowComposition::~GuiWindowComposition() + { + } + + Rect GuiWindowComposition::GetBounds() + { + Rect bounds; + if (relatedHostRecord) + { + if (auto window = relatedHostRecord->host->GetNativeWindow()) + { + bounds = Rect(Point(0, 0), window->Convert(window->GetClientSize())); + } + } + UpdatePreviousBounds(bounds); + return bounds; + } + + void GuiWindowComposition::SetMargin(Margin value) + { + } + +/*********************************************************************** +GuiGraphicsComposition +***********************************************************************/ + + void GuiGraphicsComposition::OnControlParentChanged(controls::GuiControl* control) + { + if(associatedControl && associatedControl!=control) + { + if(associatedControl->GetParent()) + { + associatedControl->GetParent()->OnChildRemoved(associatedControl); + } + if(control) + { + control->OnChildInserted(associatedControl); + } + } + else + { + for(vint i=0;iOnControlParentChanged(control); + } + } + } + + void GuiGraphicsComposition::OnChildInserted(GuiGraphicsComposition* child) + { + child->OnControlParentChanged(GetRelatedControl()); + } + + void GuiGraphicsComposition::OnChildRemoved(GuiGraphicsComposition* child) + { + child->OnControlParentChanged(0); + } + + void GuiGraphicsComposition::OnParentChanged(GuiGraphicsComposition* oldParent, GuiGraphicsComposition* newParent) + { + OnParentLineChanged(); + } + + void GuiGraphicsComposition::OnParentLineChanged() + { + for (vint i = 0; i < children.Count(); i++) + { + children[i]->OnParentLineChanged(); + } + } + + void GuiGraphicsComposition::OnRenderContextChanged() + { + } + + void GuiGraphicsComposition::UpdateRelatedHostRecord(GraphicsHostRecord* record) + { + relatedHostRecord = record; + auto renderTarget = GetRenderTarget(); + + if (ownedElement) + { + if (auto renderer = ownedElement->GetRenderer()) + { + renderer->SetRenderTarget(renderTarget); + } + } + + for (vint i = 0; i < children.Count(); i++) + { + children[i]->UpdateRelatedHostRecord(record); + } + + if (HasEventReceiver()) + { + GetEventReceiver()->renderTargetChanged.Execute(GuiEventArgs(this)); + } + if (associatedControl) + { + associatedControl->OnRenderTargetChanged(renderTarget); + } + + OnRenderContextChanged(); + } + + void GuiGraphicsComposition::SetAssociatedControl(controls::GuiControl* control) + { + if (associatedControl) + { + for (vint i = 0; i < children.Count(); i++) + { + children[i]->OnControlParentChanged(0); + } + } + associatedControl = control; + if (associatedControl) + { + for (vint i = 0; i < children.Count(); i++) + { + children[i]->OnControlParentChanged(associatedControl); + } + } + } + + void GuiGraphicsComposition::InvokeOnCompositionStateChanged() + { + if (relatedHostRecord) + { + relatedHostRecord->host->RequestRender(); + } + } + + bool GuiGraphicsComposition::SharedPtrDestructorProc(DescriptableObject* obj, bool forceDisposing) + { + GuiGraphicsComposition* value=dynamic_cast(obj); + if(value->parent) + { + if (!forceDisposing) return false; + } + SafeDeleteComposition(value); + return true; + } + + GuiGraphicsComposition::GuiGraphicsComposition() + { + sharedPtrDestructorProc = &GuiGraphicsComposition::SharedPtrDestructorProc; + } + + GuiGraphicsComposition::~GuiGraphicsComposition() + { + for(vint i=0;iGetParent()) return false; + children.Insert(index, child); + + // composition parent changed -> control parent changed -> related host changed + child->parent = this; + child->OnParentChanged(nullptr, this); + OnChildInserted(child); + child->UpdateRelatedHostRecord(relatedHostRecord); + + InvokeOnCompositionStateChanged(); + return true; + } + + bool GuiGraphicsComposition::RemoveChild(GuiGraphicsComposition* child) + { + CHECK_ERROR(!isRendering, L"GuiGraphicsComposition::InsertChild(vint, GuiGraphicsComposition*)#Cannot modify composition tree during rendering."); + if (!child) return false; + vint index = children.IndexOf(child); + if (index == -1) return false; + + // composition parent changed -> control parent changed -> related host changed + child->parent = nullptr; + child->OnParentChanged(this, nullptr); + OnChildRemoved(child); + child->UpdateRelatedHostRecord(nullptr); + + GuiGraphicsHost* host = GetRelatedGraphicsHost(); + if (host) + { + host->DisconnectComposition(child); + } + children.RemoveAt(index); + InvokeOnCompositionStateChanged(); + return true; + } + + bool GuiGraphicsComposition::MoveChild(GuiGraphicsComposition* child, vint newIndex) + { + if(!child) return false; + vint index=children.IndexOf(child); + if(index==-1) return false; + children.RemoveAt(index); + children.Insert(newIndex, child); + InvokeOnCompositionStateChanged(); + return true; + } + + Ptr GuiGraphicsComposition::GetOwnedElement() + { + return ownedElement; + } + + void GuiGraphicsComposition::SetOwnedElement(Ptr element) + { + if (ownedElement != element) + { + if (ownedElement) + { + if (auto renderer = ownedElement->GetRenderer()) + { + renderer->SetRenderTarget(nullptr); + } + ownedElement->SetOwnerComposition(nullptr); + } + ownedElement = element; + if (ownedElement) + { + if (auto renderer = ownedElement->GetRenderer()) + { + renderer->SetRenderTarget(GetRenderTarget()); + } + ownedElement->SetOwnerComposition(this); + } + InvokeOnCompositionStateChanged(); + } + } + + bool GuiGraphicsComposition::GetVisible() + { + return visible; + } + + void GuiGraphicsComposition::SetVisible(bool value) + { + visible = value; + InvokeOnCompositionStateChanged(); + } + + GuiGraphicsComposition::MinSizeLimitation GuiGraphicsComposition::GetMinSizeLimitation() + { + return minSizeLimitation; + } + + void GuiGraphicsComposition::SetMinSizeLimitation(MinSizeLimitation value) + { + minSizeLimitation = value; + InvokeOnCompositionStateChanged(); + } + + elements::IGuiGraphicsRenderTarget* GuiGraphicsComposition::GetRenderTarget() + { + return relatedHostRecord ? relatedHostRecord->renderTarget : nullptr; + } + + void GuiGraphicsComposition::Render(Size offset) + { + auto renderTarget = GetRenderTarget(); + if (visible && renderTarget && !renderTarget->IsClipperCoverWholeTarget()) + { + Rect bounds = GetBounds(); + bounds.x1 += margin.left; + bounds.y1 += margin.top; + bounds.x2 -= margin.right; + bounds.y2 -= margin.bottom; + + if (bounds.x1 <= bounds.x2 && bounds.y1 <= bounds.y2) + { + bounds.x1 += offset.x; + bounds.x2 += offset.x; + bounds.y1 += offset.y; + bounds.y2 += offset.y; + + isRendering = true; + if (ownedElement) + { + IGuiGraphicsRenderer* renderer = ownedElement->GetRenderer(); + if (renderer) + { + renderer->Render(bounds); + } + } + if (children.Count() > 0) + { + bounds.x1 += internalMargin.left; + bounds.y1 += internalMargin.top; + bounds.x2 -= internalMargin.right; + bounds.y2 -= internalMargin.bottom; + if (bounds.x1 <= bounds.x2 && bounds.y1 <= bounds.y2) + { + offset = bounds.GetSize(); + renderTarget->PushClipper(bounds); + if (!renderTarget->IsClipperCoverWholeTarget()) + { + for (vint i = 0; i < children.Count(); i++) + { + children[i]->Render(Size(bounds.x1, bounds.y1)); + } + } + renderTarget->PopClipper(); + } + } + isRendering = false; + } + } + } + + GuiGraphicsEventReceiver* GuiGraphicsComposition::GetEventReceiver() + { + if(!eventReceiver) + { + eventReceiver=Ptr(new GuiGraphicsEventReceiver(this)); + } + return eventReceiver.Obj(); + } + + bool GuiGraphicsComposition::HasEventReceiver() + { + return eventReceiver; + } + + GuiGraphicsComposition* GuiGraphicsComposition::FindComposition(Point location, bool forMouseEvent) + { + if (!visible) return 0; + Rect bounds = GetBounds(); + Rect relativeBounds = Rect(Point(0, 0), bounds.GetSize()); + if (relativeBounds.Contains(location)) + { + Rect clientArea = GetClientArea(); + for (vint i = children.Count() - 1; i >= 0; i--) + { + GuiGraphicsComposition* child = children[i]; + Rect childBounds = child->GetBounds(); + vint offsetX = childBounds.x1 + (clientArea.x1 - bounds.x1); + vint offsetY = childBounds.y1 + (clientArea.y1 - bounds.y1); + Point newLocation = location - Size(offsetX, offsetY); + GuiGraphicsComposition* childResult = child->FindComposition(newLocation, forMouseEvent); + if (childResult) + { + return childResult; + } + } + + if (!forMouseEvent || !transparentToMouse) + { + return this; + } + } + return nullptr; + } + + bool GuiGraphicsComposition::GetTransparentToMouse() + { + return transparentToMouse; + } + + void GuiGraphicsComposition::SetTransparentToMouse(bool value) + { + transparentToMouse = value; + } + + Rect GuiGraphicsComposition::GetGlobalBounds() + { + Rect bounds = GetBounds(); + GuiGraphicsComposition* composition = parent; + while (composition) + { + Rect clientArea = composition->GetClientArea(); + Rect parentBounds = composition->GetBounds(); + bounds.x1 += clientArea.x1; + bounds.x2 += clientArea.x1; + bounds.y1 += clientArea.y1; + bounds.y2 += clientArea.y1; + composition = composition->parent; + } + return bounds; + } + + controls::GuiControl* GuiGraphicsComposition::GetAssociatedControl() + { + return associatedControl; + } + + GuiGraphicsHost* GuiGraphicsComposition::GetAssociatedHost() + { + if (relatedHostRecord && relatedHostRecord->host->GetMainComposition() == this) + { + return relatedHostRecord->host; + } + else + { + return nullptr; + } + } + + INativeCursor* GuiGraphicsComposition::GetAssociatedCursor() + { + return associatedCursor; + } + + void GuiGraphicsComposition::SetAssociatedCursor(INativeCursor* cursor) + { + associatedCursor = cursor; + } + + INativeWindowListener::HitTestResult GuiGraphicsComposition::GetAssociatedHitTestResult() + { + return associatedHitTestResult; + } + + void GuiGraphicsComposition::SetAssociatedHitTestResult(INativeWindowListener::HitTestResult value) + { + associatedHitTestResult = value; + } + + controls::GuiControl* GuiGraphicsComposition::GetRelatedControl() + { + GuiGraphicsComposition* composition = this; + while (composition) + { + if (composition->GetAssociatedControl()) + { + return composition->GetAssociatedControl(); + } + else + { + composition = composition->GetParent(); + } + } + return nullptr; + } + + GuiGraphicsHost* GuiGraphicsComposition::GetRelatedGraphicsHost() + { + return relatedHostRecord ? relatedHostRecord->host : nullptr; + } + + controls::GuiControlHost* GuiGraphicsComposition::GetRelatedControlHost() + { + if (auto control = GetRelatedControl()) + { + return control->GetRelatedControlHost(); + } + return nullptr; + } + + INativeCursor* GuiGraphicsComposition::GetRelatedCursor() + { + GuiGraphicsComposition* composition = this; + while (composition) + { + if (composition->GetAssociatedCursor()) + { + return composition->GetAssociatedCursor(); + } + else + { + composition = composition->GetParent(); + } + } + return nullptr; + } + + Margin GuiGraphicsComposition::GetMargin() + { + return margin; + } + + void GuiGraphicsComposition::SetMargin(Margin value) + { + margin = value; + InvokeOnCompositionStateChanged(); + } + + Margin GuiGraphicsComposition::GetInternalMargin() + { + return internalMargin; + } + + void GuiGraphicsComposition::SetInternalMargin(Margin value) + { + internalMargin = value; + InvokeOnCompositionStateChanged(); + } + + Size GuiGraphicsComposition::GetPreferredMinSize() + { + return preferredMinSize; + } + + void GuiGraphicsComposition::SetPreferredMinSize(Size value) + { + preferredMinSize = value; + InvokeOnCompositionStateChanged(); + } + + Rect GuiGraphicsComposition::GetClientArea() + { + Rect bounds=GetBounds(); + bounds.x1+=margin.left+internalMargin.left; + bounds.y1+=margin.top+internalMargin.top; + bounds.x2-=margin.right+internalMargin.right; + bounds.y2-=margin.bottom+internalMargin.bottom; + return bounds; + } + + void GuiGraphicsComposition::ForceCalculateSizeImmediately() + { + isRendering = true; + for (vint i = 0; i < children.Count(); i++) + { + children[i]->ForceCalculateSizeImmediately(); + } + isRendering = false; + InvokeOnCompositionStateChanged(); + } + +/*********************************************************************** +GuiGraphicsSite +***********************************************************************/ + + Rect GuiGraphicsSite::GetBoundsInternal(Rect expectedBounds) + { + Size minSize = GetMinPreferredClientSize(); + if (minSize.x < preferredMinSize.x) minSize.x = preferredMinSize.x; + if (minSize.y < preferredMinSize.y) minSize.y = preferredMinSize.y; + + minSize.x += margin.left + margin.right + internalMargin.left + internalMargin.right; + minSize.y += margin.top + margin.bottom + internalMargin.top + internalMargin.bottom; + vint w = expectedBounds.Width(); + vint h = expectedBounds.Height(); + if (minSize.x < w) minSize.x = w; + if (minSize.y < h) minSize.y = h; + return Rect(expectedBounds.LeftTop(), minSize); + } + + void GuiGraphicsSite::UpdatePreviousBounds(Rect bounds) + { + if (previousBounds != bounds) + { + previousBounds = bounds; + BoundsChanged.Execute(GuiEventArgs(this)); + InvokeOnCompositionStateChanged(); + } + } + + GuiGraphicsSite::GuiGraphicsSite() + { + BoundsChanged.SetAssociatedComposition(this); + } + + GuiGraphicsSite::~GuiGraphicsSite() + { + } + + bool GuiGraphicsSite::IsSizeAffectParent() + { + return true; + } + + Size GuiGraphicsSite::GetMinPreferredClientSize() + { + Size minSize; + if (minSizeLimitation != GuiGraphicsComposition::NoLimit) + { + if (ownedElement) + { + IGuiGraphicsRenderer* renderer = ownedElement->GetRenderer(); + if (renderer) + { + minSize = renderer->GetMinSize(); + } + } + } + if (minSizeLimitation == GuiGraphicsComposition::LimitToElementAndChildren) + { + vint childCount = Children().Count(); + for (vint i = 0; i < childCount; i++) + { + GuiGraphicsComposition* child = children[i]; + if (child->IsSizeAffectParent()) + { + Rect childBounds = child->GetPreferredBounds(); + if (minSize.x < childBounds.x2) minSize.x = childBounds.x2; + if (minSize.y < childBounds.y2) minSize.y = childBounds.y2; + } + } + } + return minSize; + } + + Rect GuiGraphicsSite::GetPreferredBounds() + { + return GetBoundsInternal(Rect(Point(0, 0), GetMinPreferredClientSize())); + } + +/*********************************************************************** +Helper Functions +***********************************************************************/ + + void NotifyFinalizeInstance(controls::GuiControl* value) + { + if (value) + { + NotifyFinalizeInstance(value->GetBoundsComposition()); + } + } + + void NotifyFinalizeInstance(GuiGraphicsComposition* value) + { + if (value) + { + bool finalized = false; + if (auto root = dynamic_cast(value)) + { + if (root->IsFinalized()) + { + finalized = true; + } + else + { + root->FinalizeInstance(); + } + } + + if (auto control = value->GetAssociatedControl()) + { + if (auto root = dynamic_cast(control)) + { + if (root->IsFinalized()) + { + finalized = true; + } + else + { + root->FinalizeInstance(); + } + } + } + + if (!finalized) + { + vint count = value->Children().Count(); + for (vint i = 0; i < count; i++) + { + NotifyFinalizeInstance(value->Children()[i]); + } + } + } + } + + void SafeDeleteControlInternal(controls::GuiControl* value) + { + if(value) + { + if (value->GetRelatedControlHost() != value) + { + GuiGraphicsComposition* bounds = value->GetBoundsComposition(); + if (bounds->GetParent()) + { + bounds->GetParent()->RemoveChild(bounds); + } + } + delete value; + } + } + + void SafeDeleteCompositionInternal(GuiGraphicsComposition* value) + { + if (value) + { + if (value->GetParent()) + { + value->GetParent()->RemoveChild(value); + } + + if (value->GetAssociatedControl()) + { + SafeDeleteControlInternal(value->GetAssociatedControl()); + } + else + { + for (vint i = value->Children().Count() - 1; i >= 0; i--) + { + SafeDeleteCompositionInternal(value->Children().Get(i)); + } + delete value; + } + } + } + + void SafeDeleteControl(controls::GuiControl* value) + { + if (auto controlHost = dynamic_cast(value)) + { + controlHost->DeleteAfterProcessingAllEvents(); + } + else + { + NotifyFinalizeInstance(value); + SafeDeleteControlInternal(value); + } + } + + void SafeDeleteComposition(GuiGraphicsComposition* value) + { + NotifyFinalizeInstance(value); + SafeDeleteCompositionInternal(value); + } + } + } +} + +/*********************************************************************** +.\APPLICATION\GRAPHICSCOMPOSITIONS\GUIGRAPHICSEVENTRECEIVER.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace compositions + { + +/*********************************************************************** +Event Receiver +***********************************************************************/ + + GuiGraphicsEventReceiver::GuiGraphicsEventReceiver(GuiGraphicsComposition* _sender) + :sender(_sender) + ,leftButtonDown(_sender) + ,leftButtonUp(_sender) + ,leftButtonDoubleClick(_sender) + ,middleButtonDown(_sender) + ,middleButtonUp(_sender) + ,middleButtonDoubleClick(_sender) + ,rightButtonDown(_sender) + ,rightButtonUp(_sender) + ,rightButtonDoubleClick(_sender) + ,horizontalWheel(_sender) + ,verticalWheel(_sender) + ,mouseMove(_sender) + ,mouseEnter(_sender) + ,mouseLeave(_sender) + ,previewKey(_sender) + ,keyDown(_sender) + ,keyUp(_sender) + ,systemKeyDown(_sender) + ,systemKeyUp(_sender) + ,previewCharInput(_sender) + ,charInput(_sender) + ,gotFocus(_sender) + ,lostFocus(_sender) + ,caretNotify(_sender) + ,clipboardNotify(_sender) + { + } + + GuiGraphicsEventReceiver::~GuiGraphicsEventReceiver() + { + } + + GuiGraphicsComposition* GuiGraphicsEventReceiver::GetAssociatedComposition() + { + return sender; + } + } + } +} + +/*********************************************************************** +.\APPLICATION\GRAPHICSHOST\GUIGRAPHICSHOST.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace compositions + { + using namespace collections; + using namespace controls; + using namespace elements; + +/*********************************************************************** +GuiGraphicsTimerManager +***********************************************************************/ + + GuiGraphicsTimerManager::GuiGraphicsTimerManager() + { + } + + GuiGraphicsTimerManager::~GuiGraphicsTimerManager() + { + } + + void GuiGraphicsTimerManager::AddCallback(Ptr callback) + { + callbacks.Add(callback); + } + + void GuiGraphicsTimerManager::Play() + { + for (vint i = callbacks.Count() - 1; i >= 0; i--) + { + auto callback = callbacks[i]; + if (!callback->Play()) + { + callbacks.RemoveAt(i); + } + } + } + +/*********************************************************************** +GuiGraphicsHost +***********************************************************************/ + + void GuiGraphicsHost::RefreshRelatedHostRecord(INativeWindow* nativeWindow) + { + hostRecord.nativeWindow = nativeWindow; + hostRecord.renderTarget = nativeWindow ? GetGuiGraphicsResourceManager()->GetRenderTarget(nativeWindow) : nullptr; + windowComposition->UpdateRelatedHostRecord(&hostRecord); + } + + void GuiGraphicsHost::DisconnectCompositionInternal(GuiGraphicsComposition* composition) + { + for(vint i=0;iChildren().Count();i++) + { + DisconnectCompositionInternal(composition->Children().Get(i)); + } + if(mouseCaptureComposition==composition) + { + if(hostRecord.nativeWindow) + { + hostRecord.nativeWindow->ReleaseCapture(); + } + mouseCaptureComposition=0; + } + if(focusedComposition==composition) + { + focusedComposition=0; + } + mouseEnterCompositions.Remove(composition); + } + + void GuiGraphicsHost::MouseCapture(const NativeWindowMouseInfo& info) + { + if (hostRecord.nativeWindow && (info.left || info.middle || info.right)) + { + if (!hostRecord.nativeWindow->IsCapturing() && !info.nonClient) + { + hostRecord.nativeWindow->RequireCapture(); + auto point = hostRecord.nativeWindow->Convert(NativePoint(info.x, info.y)); + mouseCaptureComposition = windowComposition->FindComposition(point, true); + } + } + } + + void GuiGraphicsHost::MouseUncapture(const NativeWindowMouseInfo& info) + { + if(hostRecord.nativeWindow && !(info.left || info.middle || info.right)) + { + hostRecord.nativeWindow->ReleaseCapture(); + mouseCaptureComposition=0; + } + } + + void GuiGraphicsHost::OnCharInput(const NativeWindowCharInfo& info, GuiGraphicsComposition* composition, GuiCharEvent GuiGraphicsEventReceiver::* eventReceiverEvent) + { + List compositions; + while(composition) + { + if(composition->HasEventReceiver()) + { + compositions.Add(composition); + } + composition=composition->GetParent(); + } + + GuiCharEventArgs arguments(composition); + (NativeWindowCharInfo&)arguments=info; + + for(vint i=compositions.Count()-1;i>=0;i--) + { + compositions[i]->GetEventReceiver()->previewCharInput.Execute(arguments); + if(arguments.handled) + { + return; + } + } + + for(vint i=0;iGetEventReceiver()->*eventReceiverEvent).Execute(arguments); + if(arguments.handled) + { + return; + } + } + } + + void GuiGraphicsHost::OnKeyInput(const NativeWindowKeyInfo& info, GuiGraphicsComposition* composition, GuiKeyEvent GuiGraphicsEventReceiver::* eventReceiverEvent) + { + List compositions; + { + auto current = composition; + while (current) + { + if (current->HasEventReceiver()) + { + compositions.Add(current); + } + current = current->GetParent(); + } + } + + GuiKeyEventArgs arguments(composition); + (NativeWindowKeyInfo&)arguments = info; + + for (vint i = compositions.Count() - 1; i >= 0; i--) + { + compositions[i]->GetEventReceiver()->previewKey.Execute(arguments); + if (arguments.handled) + { + return; + } + } + + for (vint i = 0; i < compositions.Count(); i++) + { + (compositions[i]->GetEventReceiver()->*eventReceiverEvent).Execute(arguments); + if (arguments.handled) + { + return; + } + } + } + + void GuiGraphicsHost::RaiseMouseEvent(GuiMouseEventArgs& arguments, GuiGraphicsComposition* composition, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent) + { + arguments.compositionSource=composition; + arguments.eventSource=0; + vint x=arguments.x; + vint y=arguments.y; + + while(composition) + { + if(composition->HasEventReceiver()) + { + if(!arguments.eventSource) + { + arguments.eventSource=composition; + } + GuiGraphicsEventReceiver* eventReceiver=composition->GetEventReceiver(); + (eventReceiver->*eventReceiverEvent).Execute(arguments); + if(arguments.handled) + { + break; + } + } + + GuiGraphicsComposition* parent=composition->GetParent(); + if(parent) + { + Rect parentBounds=parent->GetBounds(); + Rect clientArea=parent->GetClientArea(); + Rect childBounds=composition->GetBounds(); + + x+=childBounds.x1+(clientArea.x1-parentBounds.x1); + y+=childBounds.y1+(clientArea.y1-parentBounds.y1); + arguments.x=x; + arguments.y=y; + } + composition=parent; + } + } + + void GuiGraphicsHost::OnMouseInput(const NativeWindowMouseInfo& info, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent) + { + GuiGraphicsComposition* composition = 0; + if (mouseCaptureComposition) + { + composition = mouseCaptureComposition; + } + else + { + auto point = hostRecord.nativeWindow->Convert(NativePoint(info.x, info.y)); + composition = windowComposition->FindComposition(point, true); + } + if (composition) + { + Rect bounds = composition->GetGlobalBounds(); + Point point = hostRecord.nativeWindow->Convert(NativePoint(info.x, info.y)); + GuiMouseEventArgs arguments; + arguments.ctrl = info.ctrl; + arguments.shift = info.shift; + arguments.left = info.left; + arguments.middle = info.middle; + arguments.right = info.right; + arguments.wheel = info.wheel; + arguments.nonClient = info.nonClient; + arguments.x = point.x - bounds.x1; + arguments.y = point.y - bounds.y1; + RaiseMouseEvent(arguments, composition, eventReceiverEvent); + } + } + + void GuiGraphicsHost::RecreateRenderTarget() + { + windowComposition->UpdateRelatedHostRecord(nullptr); + GetGuiGraphicsResourceManager()->RecreateRenderTarget(hostRecord.nativeWindow); + RefreshRelatedHostRecord(hostRecord.nativeWindow); + } + + INativeWindowListener::HitTestResult GuiGraphicsHost::HitTest(NativePoint location) + { + NativeRect bounds = hostRecord.nativeWindow->GetBounds(); + NativeRect clientBounds = hostRecord.nativeWindow->GetClientBoundsInScreen(); + NativePoint clientLocation(location.x + bounds.x1 - clientBounds.x1, location.y + bounds.y1 - clientBounds.y1); + auto point = hostRecord.nativeWindow->Convert(clientLocation); + GuiGraphicsComposition* hitComposition = windowComposition->FindComposition(point, true); + while (hitComposition) + { + INativeWindowListener::HitTestResult result = hitComposition->GetAssociatedHitTestResult(); + if (result == INativeWindowListener::NoDecision) + { + hitComposition = hitComposition->GetParent(); + } + else + { + return result; + } + } + return INativeWindowListener::NoDecision; + } + + void GuiGraphicsHost::Moving(NativeRect& bounds, bool fixSizeOnly, bool draggingBorder) + { + NativeRect oldBounds = hostRecord.nativeWindow->GetBounds(); + minSize = windowComposition->GetPreferredBounds().GetSize(); + NativeSize minWindowSize = hostRecord.nativeWindow->Convert(minSize) + (oldBounds.GetSize() - hostRecord.nativeWindow->GetClientSize()); + if (bounds.Width() < minWindowSize.x) + { + if (fixSizeOnly) + { + if (bounds.Width() < minWindowSize.x) + { + bounds.x2 = bounds.x1 + minWindowSize.x; + } + } + else if (oldBounds.x1 != bounds.x1) + { + bounds.x1 = oldBounds.x2 - minWindowSize.x; + } + else if (oldBounds.x2 != bounds.x2) + { + bounds.x2 = oldBounds.x1 + minWindowSize.x; + } + } + if (bounds.Height() < minWindowSize.y) + { + if (fixSizeOnly) + { + if (bounds.Height() < minWindowSize.y) + { + bounds.y2 = bounds.y1 + minWindowSize.y; + } + } + else if (oldBounds.y1 != bounds.y1) + { + bounds.y1 = oldBounds.y2 - minWindowSize.y; + } + else if (oldBounds.y2 != bounds.y2) + { + bounds.y2 = oldBounds.y1 + minWindowSize.y; + } + } + } + + void GuiGraphicsHost::Moved() + { + NativeSize size = hostRecord.nativeWindow->GetClientSize(); + if (previousClientSize != size) + { + previousClientSize = size; + minSize = windowComposition->GetPreferredBounds().GetSize(); + needRender = true; + } + } + + void GuiGraphicsHost::DpiChanged() + { + RecreateRenderTarget(); + needRender = true; + } + + void GuiGraphicsHost::Paint() + { + if (!supressPaint) + { + needRender = true; + } + } + + void GuiGraphicsHost::LeftButtonDown(const NativeWindowMouseInfo& info) + { + altActionManager->CloseAltHost(); + MouseCapture(info); + OnMouseInput(info, &GuiGraphicsEventReceiver::leftButtonDown); + } + + void GuiGraphicsHost::LeftButtonUp(const NativeWindowMouseInfo& info) + { + OnMouseInput(info, &GuiGraphicsEventReceiver::leftButtonUp); + MouseUncapture(info); + } + + void GuiGraphicsHost::LeftButtonDoubleClick(const NativeWindowMouseInfo& info) + { + LeftButtonDown(info); + OnMouseInput(info, &GuiGraphicsEventReceiver::leftButtonDoubleClick); + } + + void GuiGraphicsHost::RightButtonDown(const NativeWindowMouseInfo& info) + { + altActionManager->CloseAltHost(); + MouseCapture(info); + OnMouseInput(info, &GuiGraphicsEventReceiver::rightButtonDown); + } + + void GuiGraphicsHost::RightButtonUp(const NativeWindowMouseInfo& info) + { + OnMouseInput(info, &GuiGraphicsEventReceiver::rightButtonUp); + MouseUncapture(info); + } + + void GuiGraphicsHost::RightButtonDoubleClick(const NativeWindowMouseInfo& info) + { + RightButtonDown(info); + OnMouseInput(info, &GuiGraphicsEventReceiver::rightButtonDoubleClick); + } + + void GuiGraphicsHost::MiddleButtonDown(const NativeWindowMouseInfo& info) + { + altActionManager->CloseAltHost(); + MouseCapture(info); + OnMouseInput(info, &GuiGraphicsEventReceiver::middleButtonDown); + } + + void GuiGraphicsHost::MiddleButtonUp(const NativeWindowMouseInfo& info) + { + OnMouseInput(info, &GuiGraphicsEventReceiver::middleButtonUp); + MouseUncapture(info); + } + + void GuiGraphicsHost::MiddleButtonDoubleClick(const NativeWindowMouseInfo& info) + { + MiddleButtonDown(info); + OnMouseInput(info, &GuiGraphicsEventReceiver::middleButtonDoubleClick); + } + + void GuiGraphicsHost::HorizontalWheel(const NativeWindowMouseInfo& info) + { + OnMouseInput(info, &GuiGraphicsEventReceiver::horizontalWheel); + } + + void GuiGraphicsHost::VerticalWheel(const NativeWindowMouseInfo& info) + { + OnMouseInput(info, &GuiGraphicsEventReceiver::verticalWheel); + } + + void GuiGraphicsHost::MouseMoving(const NativeWindowMouseInfo& info) + { + CompositionList newCompositions; + { + auto point = hostRecord.nativeWindow->Convert(NativePoint(info.x, info.y)); + GuiGraphicsComposition* composition = windowComposition->FindComposition(point, true); + while (composition) + { + newCompositions.Insert(0, composition); + composition = composition->GetParent(); + } + } + + vint firstDifferentIndex = mouseEnterCompositions.Count(); + for (vint i = 0; i < mouseEnterCompositions.Count(); i++) + { + if (i == newCompositions.Count()) + { + firstDifferentIndex = newCompositions.Count(); + break; + } + if (mouseEnterCompositions[i] != newCompositions[i]) + { + firstDifferentIndex = i; + break; + } + } + + for (vint i = mouseEnterCompositions.Count() - 1; i >= firstDifferentIndex; i--) + { + GuiGraphicsComposition* composition = mouseEnterCompositions[i]; + if (composition->HasEventReceiver()) + { + composition->GetEventReceiver()->mouseLeave.Execute(GuiEventArgs(composition)); + } + } + + CopyFrom(mouseEnterCompositions, newCompositions); + for (vint i = firstDifferentIndex; i < mouseEnterCompositions.Count(); i++) + { + GuiGraphicsComposition* composition = mouseEnterCompositions[i]; + if (composition->HasEventReceiver()) + { + composition->GetEventReceiver()->mouseEnter.Execute(GuiEventArgs(composition)); + } + } + + INativeCursor* cursor = 0; + if (newCompositions.Count() > 0) + { + cursor = newCompositions[newCompositions.Count() - 1]->GetRelatedCursor(); + } + if (cursor) + { + hostRecord.nativeWindow->SetWindowCursor(cursor); + } + else + { + hostRecord.nativeWindow->SetWindowCursor(GetCurrentController()->ResourceService()->GetDefaultSystemCursor()); + } + + OnMouseInput(info, &GuiGraphicsEventReceiver::mouseMove); + } + + void GuiGraphicsHost::MouseEntered() + { + } + + void GuiGraphicsHost::MouseLeaved() + { + for(vint i=mouseEnterCompositions.Count()-1;i>=0;i--) + { + GuiGraphicsComposition* composition=mouseEnterCompositions[i]; + if(composition->HasEventReceiver()) + { + composition->GetEventReceiver()->mouseLeave.Execute(GuiEventArgs(composition)); + } + } + mouseEnterCompositions.Clear(); + } + + void GuiGraphicsHost::KeyDown(const NativeWindowKeyInfo& info) + { + if (altActionManager->KeyDown(info)) { return; } + if (tabActionManager->KeyDown(info, focusedComposition)) { return; } + if(shortcutKeyManager && shortcutKeyManager->Execute(info)) { return; } + + if (focusedComposition && focusedComposition->HasEventReceiver()) + { + OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::keyDown); + } + } + + void GuiGraphicsHost::KeyUp(const NativeWindowKeyInfo& info) + { + if (altActionManager->KeyUp(info)) { return; } + + if(focusedComposition && focusedComposition->HasEventReceiver()) + { + OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::keyUp); + } + } + + void GuiGraphicsHost::SysKeyDown(const NativeWindowKeyInfo& info) + { + if (altActionManager->SysKeyDown(info)) { return; } + + if(focusedComposition && focusedComposition->HasEventReceiver()) + { + OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::systemKeyDown); + } + } + + void GuiGraphicsHost::SysKeyUp(const NativeWindowKeyInfo& info) + { + if (altActionManager->SysKeyUp(info)) { return; } + + if (!info.ctrl && !info.shift && info.code == VKEY::KEY_MENU && hostRecord.nativeWindow) + { + if (hostRecord.nativeWindow) + { + hostRecord.nativeWindow->SupressAlt(); + } + } + + if (focusedComposition && focusedComposition->HasEventReceiver()) + { + OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::systemKeyUp); + } + } + + void GuiGraphicsHost::Char(const NativeWindowCharInfo& info) + { + if (altActionManager->Char(info)) { return; } + if (tabActionManager->Char(info)) { return; } + + if(focusedComposition && focusedComposition->HasEventReceiver()) + { + OnCharInput(info, focusedComposition, &GuiGraphicsEventReceiver::charInput); + } + } + + void GuiGraphicsHost::GlobalTimer() + { + timerManager.Play(); + + DateTime now=DateTime::UtcTime(); + if(now.totalMilliseconds-lastCaretTime>=CaretInterval) + { + lastCaretTime=now.totalMilliseconds; + if(focusedComposition && focusedComposition->HasEventReceiver()) + { + focusedComposition->GetEventReceiver()->caretNotify.Execute(GuiEventArgs(focusedComposition)); + } + } + + Render(false); + } + + GuiGraphicsHost::GuiGraphicsHost(controls::GuiControlHost* _controlHost, GuiGraphicsComposition* boundsComposition) + :controlHost(_controlHost) + { + altActionManager = new GuiAltActionManager(controlHost); + tabActionManager = new GuiTabActionManager(controlHost); + hostRecord.host = this; + windowComposition=new GuiWindowComposition; + windowComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); + windowComposition->AddChild(boundsComposition); + RefreshRelatedHostRecord(nullptr); + } + + GuiGraphicsHost::~GuiGraphicsHost() + { + windowComposition->RemoveChild(windowComposition->Children()[0]); + NotifyFinalizeInstance(windowComposition); + + delete altActionManager; + delete tabActionManager; + if (shortcutKeyManager) + { + delete shortcutKeyManager; + shortcutKeyManager = nullptr; + } + + delete windowComposition; + } + + INativeWindow* GuiGraphicsHost::GetNativeWindow() + { + return hostRecord.nativeWindow; + } + + void GuiGraphicsHost::SetNativeWindow(INativeWindow* _nativeWindow) + { + if (hostRecord.nativeWindow != _nativeWindow) + { + if (hostRecord.nativeWindow) + { + GetCurrentController()->CallbackService()->UninstallListener(this); + hostRecord.nativeWindow->UninstallListener(this); + } + + if (_nativeWindow) + { + _nativeWindow->InstallListener(this); + GetCurrentController()->CallbackService()->InstallListener(this); + previousClientSize = _nativeWindow->GetClientSize(); + minSize = windowComposition->GetPreferredBounds().GetSize(); + _nativeWindow->SetCaretPoint(_nativeWindow->Convert(caretPoint)); + needRender = true; + } + + RefreshRelatedHostRecord(_nativeWindow); + } + } + + GuiGraphicsComposition* GuiGraphicsHost::GetMainComposition() + { + return windowComposition; + } + + void GuiGraphicsHost::Render(bool forceUpdate) + { + if (!forceUpdate && !needRender) + { + return; + } + needRender = false; + + if(hostRecord.nativeWindow && hostRecord.nativeWindow->IsVisible()) + { + supressPaint = true; + hostRecord.renderTarget->StartRendering(); + windowComposition->Render(Size()); + auto result = hostRecord.renderTarget->StopRendering(); + hostRecord.nativeWindow->RedrawContent(); + supressPaint = false; + + switch (result) + { + case RenderTargetFailure::ResizeWhileRendering: + { + GetGuiGraphicsResourceManager()->ResizeRenderTarget(hostRecord.nativeWindow); + needRender = true; + } + break; + case RenderTargetFailure::LostDevice: + { + RecreateRenderTarget(); + needRender = true; + } + break; + default: + { + supressPaint = true; + auto bounds = windowComposition->GetBounds(); + auto preferred = windowComposition->GetPreferredBounds(); + auto width = bounds.Width() > preferred.Width() ? bounds.Width() : preferred.Width(); + auto height = bounds.Height() > preferred.Height() ? bounds.Height() : preferred.Height(); + controlHost->UpdateClientSizeAfterRendering(preferred.GetSize(), Size(width, height)); + supressPaint = false; + } + } + } + + if (!needRender) + { + { + ProcList procs; + CopyFrom(procs, afterRenderProcs); + afterRenderProcs.Clear(); + for (vint i = 0; i < procs.Count(); i++) + { + procs[i](); + } + } + { + ProcMap procs; + CopyFrom(procs, afterRenderKeyedProcs); + afterRenderKeyedProcs.Clear(); + for (vint i = 0; i < procs.Count(); i++) + { + procs.Values()[i](); + } + } + } + } + + void GuiGraphicsHost::RequestRender() + { + needRender = true; + } + + void GuiGraphicsHost::InvokeAfterRendering(const Func& proc, ProcKey key) + { + if (key.key == nullptr) + { + afterRenderProcs.Add(proc); + } + else + { + afterRenderKeyedProcs.Set(key, proc); + } + } + + void GuiGraphicsHost::InvalidateTabOrderCache() + { + tabActionManager->InvalidateTabOrderCache(); + } + + IGuiShortcutKeyManager* GuiGraphicsHost::GetShortcutKeyManager() + { + return shortcutKeyManager; + } + + void GuiGraphicsHost::SetShortcutKeyManager(IGuiShortcutKeyManager* value) + { + shortcutKeyManager=value; + } + + bool GuiGraphicsHost::SetFocus(GuiGraphicsComposition* composition) + { + if(!composition || composition->GetRelatedGraphicsHost()!=this) + { + return false; + } + if(focusedComposition && focusedComposition->HasEventReceiver()) + { + GuiEventArgs arguments; + arguments.compositionSource=focusedComposition; + arguments.eventSource=focusedComposition; + focusedComposition->GetEventReceiver()->lostFocus.Execute(arguments); + } + focusedComposition=composition; + SetCaretPoint(Point(0, 0)); + if(focusedComposition && focusedComposition->HasEventReceiver()) + { + GuiEventArgs arguments; + arguments.compositionSource=focusedComposition; + arguments.eventSource=focusedComposition; + focusedComposition->GetEventReceiver()->gotFocus.Execute(arguments); + } + return true; + } + + GuiGraphicsComposition* GuiGraphicsHost::GetFocusedComposition() + { + return focusedComposition; + } + + Point GuiGraphicsHost::GetCaretPoint() + { + return caretPoint; + } + + void GuiGraphicsHost::SetCaretPoint(Point value, GuiGraphicsComposition* referenceComposition) + { + if (referenceComposition) + { + Rect bounds = referenceComposition->GetGlobalBounds(); + value.x += bounds.x1; + value.y += bounds.y1; + } + caretPoint = value; + if (hostRecord.nativeWindow) + { + hostRecord.nativeWindow->SetCaretPoint(hostRecord.nativeWindow->Convert(caretPoint)); + } + } + + GuiGraphicsTimerManager* GuiGraphicsHost::GetTimerManager() + { + return &timerManager; + } + + void GuiGraphicsHost::DisconnectComposition(GuiGraphicsComposition* composition) + { + DisconnectCompositionInternal(composition); + } + } + } +} + +/*********************************************************************** +.\APPLICATION\GRAPHICSHOST\GUIGRAPHICSHOST_ALT.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace compositions + { + using namespace collections; + using namespace controls; + using namespace theme; + + const wchar_t* const IGuiAltAction::Identifier = L"vl::presentation::compositions::IGuiAltAction"; + const wchar_t* const IGuiAltActionContainer::Identifier = L"vl::presentation::compositions::IGuiAltActionContainer"; + const wchar_t* const IGuiAltActionHost::Identifier = L"vl::presentation::compositions::IGuiAltActionHost"; + +/*********************************************************************** +IGuiAltAction +***********************************************************************/ + + bool IGuiAltAction::IsLegalAlt(const WString& alt) + { + for (vint i = 0; i < alt.Length(); i++) + { + auto c = alt[i]; + if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')) + { + continue; + } + return false; + } + return true; + } + +/*********************************************************************** +IGuiAltActionHost +***********************************************************************/ + + void IGuiAltActionHost::CollectAltActionsFromControl(controls::GuiControl* control, bool includeThisControl, collections::Group& actions) + { + List controls; + controls.Add(control); + vint index = 0; + + while (index < controls.Count()) + { + auto current = controls[index++]; + + if (current != control || includeThisControl) + { + if (auto container = current->QueryTypedService()) + { + vint count = container->GetAltActionCount(); + for (vint i = 0; i < count; i++) + { + auto action = container->GetAltAction(i); + actions.Add(action->GetAlt(), action); + } + continue; + } + else if (auto action = current->QueryTypedService()) + { + if (action->IsAltAvailable()) + { + if (action->IsAltEnabled()) + { + actions.Add(action->GetAlt(), action); + continue; + } + } + } + } + + vint count = current->GetChildrenCount(); + for (vint i = 0; i < count; i++) + { + controls.Add(current->GetChild(i)); + } + } + } + +/*********************************************************************** +GuiAltActionHostBase +***********************************************************************/ + + void GuiAltActionHostBase::SetAltComposition(GuiGraphicsComposition* _composition) + { + composition = _composition; + } + + void GuiAltActionHostBase::SetAltControl(controls::GuiControl* _control, bool _includeControl) + { + control = _control; + includeControl = _includeControl; + } + + GuiGraphicsComposition* GuiAltActionHostBase::GetAltComposition() + { + CHECK_ERROR(composition, L"GuiAltActionHostBase::GetAltComposition()#Need to call SetAltComposition."); + return composition; + } + + IGuiAltActionHost* GuiAltActionHostBase::GetPreviousAltHost() + { + return previousHost; + } + + void GuiAltActionHostBase::OnActivatedAltHost(IGuiAltActionHost* _previousHost) + { + previousHost = _previousHost; + } + + void GuiAltActionHostBase::OnDeactivatedAltHost() + { + previousHost = nullptr; + } + + void GuiAltActionHostBase::CollectAltActions(collections::Group& actions) + { + CHECK_ERROR(control, L"GuiAltActionHostBase::CollectAltActions(Group&)#Need to call SetAltControl."); + CollectAltActionsFromControl(control, includeControl, actions); + } + +/*********************************************************************** +GuiAltActionManager +***********************************************************************/ + + void GuiAltActionManager::EnterAltHost(IGuiAltActionHost* host) + { + ClearAltHost(); + + Group actions; + host->CollectAltActions(actions); + if (actions.Count() == 0) + { + CloseAltHost(); + return; + } + + host->OnActivatedAltHost(currentAltHost); + currentAltHost = host; + CreateAltTitles(actions); + } + + void GuiAltActionManager::LeaveAltHost() + { + if (currentAltHost) + { + ClearAltHost(); + auto previousHost = currentAltHost->GetPreviousAltHost(); + currentAltHost->OnDeactivatedAltHost(); + currentAltHost = previousHost; + + if (currentAltHost) + { + Group actions; + currentAltHost->CollectAltActions(actions); + CreateAltTitles(actions); + } + } + } + + bool GuiAltActionManager::EnterAltKey(wchar_t key) + { + currentAltPrefix += WString::FromChar(key); + vint index = currentActiveAltActions.Keys().IndexOf(currentAltPrefix); + if (index == -1) + { + if (FilterTitles() == 0) + { + currentAltPrefix = currentAltPrefix.Left(currentAltPrefix.Length() - 1); + FilterTitles(); + } + } + else + { + auto action = currentActiveAltActions.Values()[index]; + if (action->GetActivatingAltHost()) + { + EnterAltHost(action->GetActivatingAltHost()); + } + else + { + CloseAltHost(); + } + action->OnActiveAlt(); + return true; + } + return false; + } + + void GuiAltActionManager::LeaveAltKey() + { + if (currentAltPrefix.Length() >= 1) + { + currentAltPrefix = currentAltPrefix.Left(currentAltPrefix.Length() - 1); + } + FilterTitles(); + } + + void GuiAltActionManager::CreateAltTitles(const collections::Group& actions) + { + if (currentAltHost) + { + vint count = actions.Count(); + for (vint i = 0; i < count; i++) + { + WString key = actions.Keys()[i]; + const auto& values = actions.GetByIndex(i); + vint numberLength = 0; + if (values.Count() == 1 && key.Length() > 0) + { + numberLength = 0; + } + else if (values.Count() <= 10) + { + numberLength = 1; + } + else if (values.Count() <= 100) + { + numberLength = 2; + } + else if (values.Count() <= 1000) + { + numberLength = 3; + } + else + { + continue; + } + + for (auto [action, index] : indexed(values)) + { + WString key = actions.Keys()[i]; + if (numberLength > 0) + { + WString number = itow(index); + while (number.Length() < numberLength) + { + number = L"0" + number; + } + key += number; + } + currentActiveAltActions.Add(key, action); + } + } + + count = currentActiveAltActions.Count(); + auto window = dynamic_cast(currentAltHost->GetAltComposition()->GetRelatedControlHost()); + for (vint i = 0; i < count; i++) + { + auto key = currentActiveAltActions.Keys()[i]; + auto composition = currentActiveAltActions.Values()[i]->GetAltComposition(); + + auto label = new GuiLabel(theme::ThemeName::ShortcutKey); + if (auto labelStyle = window->TypedControlTemplateObject(true)->GetShortcutKeyTemplate()) + { + label->SetControlTemplate(labelStyle); + } + label->SetText(key); + composition->AddChild(label->GetBoundsComposition()); + currentActiveAltTitles.Add(key, label); + } + + FilterTitles(); + } + } + + vint GuiAltActionManager::FilterTitles() + { + vint count = currentActiveAltTitles.Count(); + vint visibles = 0; + for (vint i = 0; i < count; i++) + { + auto key = currentActiveAltTitles.Keys()[i]; + auto value = currentActiveAltTitles.Values()[i]; + if (key.Length() >= currentAltPrefix.Length() && key.Left(currentAltPrefix.Length()) == currentAltPrefix) + { + value->SetVisible(true); + if (currentAltPrefix.Length() <= key.Length()) + { + value->SetText( + key + .Insert(currentAltPrefix.Length(), L"[") + .Insert(currentAltPrefix.Length() + 2, L"]") + ); + } + else + { + value->SetText(key); + } + visibles++; + } + else + { + value->SetVisible(false); + } + } + return visibles; + } + + void GuiAltActionManager::ClearAltHost() + { + for (auto title : currentActiveAltTitles.Values()) + { + SafeDeleteControl(title); + } + currentActiveAltActions.Clear(); + currentActiveAltTitles.Clear(); + currentAltPrefix = L""; + } + + void GuiAltActionManager::CloseAltHost() + { + ClearAltHost(); + while (currentAltHost) + { + currentAltHost->OnDeactivatedAltHost(); + currentAltHost = currentAltHost->GetPreviousAltHost(); + } + } + + GuiAltActionManager::GuiAltActionManager(controls::GuiControlHost* _controlHost) + :controlHost(_controlHost) + { + } + + GuiAltActionManager::~GuiAltActionManager() + { + } + + bool GuiAltActionManager::KeyDown(const NativeWindowKeyInfo& info) + { + if (!info.ctrl && !info.shift && currentAltHost) + { + if (info.code == VKEY::KEY_ESCAPE) + { + LeaveAltHost(); + return true; + } + else if (info.code == VKEY::KEY_BACK) + { + LeaveAltKey(); + } + else if (VKEY::KEY_NUMPAD0 <= info.code && info.code <= VKEY::KEY_NUMPAD9) + { + if (EnterAltKey((wchar_t)(L'0' + ((vint)info.code - (vint)VKEY::KEY_NUMPAD0)))) + { + supressAltKey = info.code; + return true; + } + } + else if ((VKEY::KEY_0 <= info.code && info.code <= VKEY::KEY_9) || (VKEY::KEY_A <= info.code && info.code <= VKEY::KEY_Z)) + { + if (EnterAltKey((wchar_t)info.code)) + { + supressAltKey = info.code; + return true; + } + } + } + + if (currentAltHost) + { + return true; + } + return false; + } + + bool GuiAltActionManager::KeyUp(const NativeWindowKeyInfo& info) + { + if (!info.ctrl && !info.shift && info.code == supressAltKey) + { + supressAltKey = VKEY::KEY_UNKNOWN; + return true; + } + return false; + } + + bool GuiAltActionManager::SysKeyDown(const NativeWindowKeyInfo& info) + { + if (!info.ctrl && !info.shift && info.code == VKEY::KEY_MENU && !currentAltHost) + { + if (auto altHost = controlHost->QueryTypedService()) + { + if (!altHost->GetPreviousAltHost()) + { + EnterAltHost(altHost); + } + } + } + + if (currentAltHost) + { + return true; + } + return false; + } + + bool GuiAltActionManager::SysKeyUp(const NativeWindowKeyInfo& info) + { + return false; + } + + bool GuiAltActionManager::Char(const NativeWindowCharInfo& info) + { + if (currentAltHost || supressAltKey != VKEY::KEY_UNKNOWN) + { + return true; + } + return false; + } + } + } +} + +/*********************************************************************** +.\APPLICATION\GRAPHICSHOST\GUIGRAPHICSHOST_SHORTCUTKEY.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace compositions + { + +/*********************************************************************** +GuiShortcutKeyItem +***********************************************************************/ + + GuiShortcutKeyItem::GuiShortcutKeyItem(GuiShortcutKeyManager* _shortcutKeyManager, bool _ctrl, bool _shift, bool _alt, VKEY _key) + :shortcutKeyManager(_shortcutKeyManager) + ,ctrl(_ctrl) + ,shift(_shift) + ,alt(_alt) + ,key(_key) + { + } + + GuiShortcutKeyItem::~GuiShortcutKeyItem() + { + } + + IGuiShortcutKeyManager* GuiShortcutKeyItem::GetManager() + { + return shortcutKeyManager; + } + + WString GuiShortcutKeyItem::GetName() + { + WString name; + if(ctrl) name+=L"Ctrl+"; + if(shift) name+=L"Shift+"; + if(alt) name+=L"Alt+"; + name+=GetCurrentController()->InputService()->GetKeyName(key); + return name; + } + + bool GuiShortcutKeyItem::CanActivate(const NativeWindowKeyInfo& info) + { + return + info.ctrl==ctrl && + info.shift==shift && + info.alt==alt && + info.code==key; + } + + bool GuiShortcutKeyItem::CanActivate(bool _ctrl, bool _shift, bool _alt, VKEY _key) + { + return + _ctrl==ctrl && + _shift==shift && + _alt==alt && + _key==key; + } + +/*********************************************************************** +GuiShortcutKeyManager +***********************************************************************/ + + GuiShortcutKeyManager::GuiShortcutKeyManager() + { + } + + GuiShortcutKeyManager::~GuiShortcutKeyManager() + { + } + + vint GuiShortcutKeyManager::GetItemCount() + { + return shortcutKeyItems.Count(); + } + + IGuiShortcutKeyItem* GuiShortcutKeyManager::GetItem(vint index) + { + return shortcutKeyItems[index].Obj(); + } + + bool GuiShortcutKeyManager::Execute(const NativeWindowKeyInfo& info) + { + bool executed=false; + for (auto item : shortcutKeyItems) + { + if(item->CanActivate(info)) + { + GuiEventArgs arguments; + item->Executed.Execute(arguments); + executed=true; + } + } + return executed; + } + + IGuiShortcutKeyItem* GuiShortcutKeyManager::CreateShortcut(bool ctrl, bool shift, bool alt, VKEY key) + { + for (auto item : shortcutKeyItems) + { + if(item->CanActivate(ctrl, shift, alt, key)) + { + return item.Obj(); + } + } + auto item=Ptr(new GuiShortcutKeyItem(this, ctrl, shift, alt, key)); + shortcutKeyItems.Add(item); + return item.Obj(); + } + + bool GuiShortcutKeyManager::DestroyShortcut(bool ctrl, bool shift, bool alt, VKEY key) + { + for (auto item : shortcutKeyItems) + { + if(item->CanActivate(ctrl, shift, alt, key)) + { + shortcutKeyItems.Remove(item.Obj()); + return true; + } + } + return false; + } + + IGuiShortcutKeyItem* GuiShortcutKeyManager::TryGetShortcut(bool ctrl, bool shift, bool alt, VKEY key) + { + for (auto item : shortcutKeyItems) + { + if(item->CanActivate(ctrl, shift, alt, key)) + { + return item.Obj(); + } + } + return 0; + } + } + } +} + +/*********************************************************************** +.\APPLICATION\GRAPHICSHOST\GUIGRAPHICSHOST_TAB.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace compositions + { + using namespace collections; + using namespace controls; + + const wchar_t* const IGuiTabAction::Identifier = L"vl::presentation::compositions::IGuiTabAction"; + +/*********************************************************************** +GuiTabActionManager +***********************************************************************/ + + namespace tab_focus + { + void CollectControls(GuiControl* current, bool includeCurrent, Group& prioritized) + { + if (includeCurrent) + { + auto tabAction = current->QueryTypedService(); + if (tabAction && (tabAction->IsTabAvailable() || tabAction->GetTabPriority() != -1)) + { + vint priority = tabAction->GetTabPriority(); + vuint64_t normalized = priority < 0 ? ~(vuint64_t)0 : (vuint64_t)priority; + prioritized.Add(normalized, current); + return; + } + } + + vint count = current->GetChildrenCount(); + for (vint i = 0; i < count; i++) + { + CollectControls(current->GetChild(i), true, prioritized); + } + } + + void InsertPrioritized(List& controls, vint index, Group& prioritized) + { + vint count = prioritized.Count(); + for (vint i = 0; i < count; i++) + { + auto& values = prioritized.GetByIndex(i); + for (vint j = 0; j < values.Count(); j++) + { + controls.Insert(index++, values[j]); + } + } + } + } + using namespace tab_focus; + + void GuiTabActionManager::BuildControlList() + { + controlsInOrder.Clear(); + { + Group prioritized; + CollectControls(controlHost, false, prioritized); + InsertPrioritized(controlsInOrder, 0, prioritized); + } + + for (vint i = 0; i < controlsInOrder.Count(); i++) + { + Group prioritized; + CollectControls(controlsInOrder[i], false, prioritized); + InsertPrioritized(controlsInOrder, i + 1, prioritized); + } + } + + controls::GuiControl* GuiTabActionManager::GetNextFocusControl(controls::GuiControl* focusedControl, vint offset) + { + if (!available) + { + BuildControlList(); + available = true; + } +#define STEP_AND_NORMALIZE(INDEX) (((INDEX) + offset + controlsInOrder.Count()) % controlsInOrder.Count()) + + if (controlsInOrder.Count() == 0) return nullptr; + vint startIndex = controlsInOrder.IndexOf(focusedControl); + startIndex = + startIndex == -1 ? 0 : + STEP_AND_NORMALIZE(startIndex); + + vint index = startIndex; + do + { + auto control = controlsInOrder[index]; + if (auto tabAction = control->QueryTypedService()) + { + if (tabAction->IsTabAvailable() && tabAction->IsTabEnabled()) + { + return control; + } + } + + index = STEP_AND_NORMALIZE(index); + } while (index != startIndex); + +#undef STEP_AND_NORMALIZE + + return nullptr; + } + + GuiTabActionManager::GuiTabActionManager(controls::GuiControlHost* _controlHost) + :controlHost(_controlHost) + { + } + + GuiTabActionManager::~GuiTabActionManager() + { + } + + void GuiTabActionManager::InvalidateTabOrderCache() + { + available = false; + controlsInOrder.Clear(); + } + + bool GuiTabActionManager::KeyDown(const NativeWindowKeyInfo& info, GuiGraphicsComposition* focusedComposition) + { + if (!info.ctrl && !info.alt && info.code == VKEY::KEY_TAB) + { + GuiControl* focusedControl = nullptr; + if (focusedComposition) + { + focusedControl = focusedComposition->GetRelatedControl(); + if (focusedControl && focusedControl->GetAcceptTabInput()) + { + return false; + } + } + + if (auto next = GetNextFocusControl(focusedControl, (info.shift ? -1 : 1))) + { + next->SetFocus(); + supressTabOnce = true; + return true; + } + } + return false; + } + + bool GuiTabActionManager::Char(const NativeWindowCharInfo& info) + { + bool supress = supressTabOnce; + supressTabOnce = false; + return supress && info.code == L'\t'; + } + } + } +} + +/*********************************************************************** +.\CONTROLS\GUIBUTTONCONTROLS.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace controls + { + using namespace elements; + using namespace compositions; + using namespace collections; + using namespace reflection::description; + +/*********************************************************************** +GuiButton +***********************************************************************/ + + void GuiButton::BeforeControlTemplateUninstalled_() + { + } + + void GuiButton::AfterControlTemplateInstalled_(bool initialize) + { + TypedControlTemplateObject(true)->SetState(controlState); + } + + void GuiButton::OnParentLineChanged() + { + GuiControl::OnParentLineChanged(); + if(GetRelatedControlHost()==0) + { + mousePressing=false; + mouseHoving=false; + UpdateControlState(); + } + } + + void GuiButton::OnActiveAlt() + { + if (autoFocus) + { + GuiControl::OnActiveAlt(); + } + Clicked.Execute(GetNotifyEventArguments()); + } + + bool GuiButton::IsTabAvailable() + { + return autoFocus && GuiControl::IsTabAvailable(); + } + + void GuiButton::UpdateControlState() + { + auto newControlState = ButtonState::Normal; + if (keyPressing) + { + newControlState = ButtonState::Pressed; + } + else if (mousePressing) + { + if (mouseHoving) + { + newControlState = ButtonState::Pressed; + } + else + { + newControlState = ButtonState::Active; + } + } + else + { + if (mouseHoving) + { + newControlState = ButtonState::Active; + } + else + { + newControlState = ButtonState::Normal; + } + } + if (controlState != newControlState) + { + controlState = newControlState; + TypedControlTemplateObject(true)->SetState(controlState); + } + } + + void GuiButton::CheckAndClick(compositions::GuiEventArgs& arguments) + { + auto eventSource = arguments.eventSource->GetAssociatedControl(); + while (eventSource && eventSource != this) + { + if (eventSource->GetFocusableComposition()) + { + return; + } + eventSource = eventSource->GetParent(); + } + Clicked.Execute(GetNotifyEventArguments()); + } + + void GuiButton::OnLeftButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) + { + if (arguments.eventSource == boundsComposition || !ignoreChildControlMouseEvents) + { + mousePressing = true; + if (autoFocus) + { + SetFocus(); + } + UpdateControlState(); + if (!clickOnMouseUp) + { + CheckAndClick(arguments); + } + } + } + + void GuiButton::OnLeftButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) + { + if (arguments.eventSource == boundsComposition || !ignoreChildControlMouseEvents) + { + mousePressing = false; + UpdateControlState(); + } + if (GetVisuallyEnabled()) + { + if (mouseHoving && clickOnMouseUp) + { + CheckAndClick(arguments); + } + } + } + + void GuiButton::OnMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + if (arguments.eventSource == boundsComposition || !ignoreChildControlMouseEvents) + { + mouseHoving = true; + UpdateControlState(); + } + } + + void GuiButton::OnMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + if (arguments.eventSource == boundsComposition || !ignoreChildControlMouseEvents) + { + mouseHoving = false; + UpdateControlState(); + } + } + + void GuiButton::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) + { + if (arguments.eventSource == focusableComposition && !arguments.ctrl && !arguments.shift && !arguments.alt) + { + switch (arguments.code) + { + case VKEY::KEY_RETURN: + CheckAndClick(arguments); + arguments.handled = true; + break; + case VKEY::KEY_SPACE: + if (!arguments.autoRepeatKeyDown) + { + keyPressing = true; + UpdateControlState(); + } + arguments.handled = true; + break; + default:; + } + } + } + + void GuiButton::OnKeyUp(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) + { + if (arguments.eventSource == focusableComposition && !arguments.ctrl && !arguments.shift && !arguments.alt) + { + switch (arguments.code) + { + case VKEY::KEY_SPACE: + if (keyPressing) + { + keyPressing = false; + UpdateControlState(); + CheckAndClick(arguments); + } + arguments.handled = true; + break; + default:; + } + } + } + + void GuiButton::OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + if (keyPressing) + { + keyPressing = false; + UpdateControlState(); + } + } + + GuiButton::GuiButton(theme::ThemeName themeName) + :GuiControl(themeName) + { + Clicked.SetAssociatedComposition(boundsComposition); + SetFocusableComposition(boundsComposition); + + boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiButton::OnLeftButtonDown); + boundsComposition->GetEventReceiver()->leftButtonUp.AttachMethod(this, &GuiButton::OnLeftButtonUp); + boundsComposition->GetEventReceiver()->mouseEnter.AttachMethod(this, &GuiButton::OnMouseEnter); + boundsComposition->GetEventReceiver()->mouseLeave.AttachMethod(this, &GuiButton::OnMouseLeave); + boundsComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiButton::OnKeyDown); + boundsComposition->GetEventReceiver()->keyUp.AttachMethod(this, &GuiButton::OnKeyUp); + boundsComposition->GetEventReceiver()->lostFocus.AttachMethod(this, &GuiButton::OnLostFocus); + } + + GuiButton::~GuiButton() + { + } + + bool GuiButton::GetClickOnMouseUp() + { + return clickOnMouseUp; + } + + void GuiButton::SetClickOnMouseUp(bool value) + { + clickOnMouseUp=value; + } + + bool GuiButton::GetAutoFocus() + { + return autoFocus; + } + + void GuiButton::SetAutoFocus(bool value) + { + autoFocus = value; + } + + bool GuiButton::GetIgnoreChildControlMouseEvents() + { + return ignoreChildControlMouseEvents; + } + + void GuiButton::SetIgnoreChildControlMouseEvents(bool value) + { + ignoreChildControlMouseEvents = value; + } + +/*********************************************************************** +GuiSelectableButton::GroupController +***********************************************************************/ + + GuiSelectableButton::GroupController::GroupController() + { + } + + GuiSelectableButton::GroupController::~GroupController() + { + for(vint i=buttons.Count()-1;i>=0;i--) + { + buttons[i]->SetGroupController(0); + } + } + + void GuiSelectableButton::GroupController::Attach(GuiSelectableButton* button) + { + if(!buttons.Contains(button)) + { + buttons.Add(button); + } + } + + void GuiSelectableButton::GroupController::Detach(GuiSelectableButton* button) + { + buttons.Remove(button); + } + +/*********************************************************************** +GuiSelectableButton::MutexGroupController +***********************************************************************/ + + GuiSelectableButton::MutexGroupController::MutexGroupController() + :suppress(false) + { + } + + GuiSelectableButton::MutexGroupController::~MutexGroupController() + { + } + + void GuiSelectableButton::MutexGroupController::OnSelectedChanged(GuiSelectableButton* button) + { + if(!suppress) + { + suppress=true; + for(vint i=0;iSetSelected(buttons[i]==button); + } + suppress=false; + } + } + +/*********************************************************************** +GuiSelectableButton +***********************************************************************/ + + void GuiSelectableButton::BeforeControlTemplateUninstalled_() + { + } + + void GuiSelectableButton::AfterControlTemplateInstalled_(bool initialize) + { + TypedControlTemplateObject(true)->SetSelected(isSelected); + } + + void GuiSelectableButton::OnClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + if(autoSelection) + { + SetSelected(!GetSelected()); + } + } + + GuiSelectableButton::GuiSelectableButton(theme::ThemeName themeName) + :GuiButton(themeName) + { + GroupControllerChanged.SetAssociatedComposition(boundsComposition); + AutoSelectionChanged.SetAssociatedComposition(boundsComposition); + SelectedChanged.SetAssociatedComposition(boundsComposition); + + Clicked.AttachMethod(this, &GuiSelectableButton::OnClicked); + } + + GuiSelectableButton::~GuiSelectableButton() + { + if(groupController) + { + groupController->Detach(this); + } + } + + GuiSelectableButton::GroupController* GuiSelectableButton::GetGroupController() + { + return groupController; + } + + void GuiSelectableButton::SetGroupController(GroupController* value) + { + if(groupController) + { + groupController->Detach(this); + } + groupController=value; + if(groupController) + { + groupController->Attach(this); + } + GroupControllerChanged.Execute(GetNotifyEventArguments()); + } + + bool GuiSelectableButton::GetAutoSelection() + { + return autoSelection; + } + + void GuiSelectableButton::SetAutoSelection(bool value) + { + if(autoSelection!=value) + { + autoSelection=value; + AutoSelectionChanged.Execute(GetNotifyEventArguments()); + } + } + + bool GuiSelectableButton::GetSelected() + { + return isSelected; + } + + void GuiSelectableButton::SetSelected(bool value) + { + if (isSelected != value) + { + isSelected = value; + TypedControlTemplateObject(true)->SetSelected(isSelected); + if (groupController) + { + groupController->OnSelectedChanged(this); + } + SelectedChanged.Execute(GetNotifyEventArguments()); + } + } + } + } +} + +/*********************************************************************** +.\CONTROLS\GUICONTAINERCONTROLS.CPP +***********************************************************************/ + + +namespace vl +{ + namespace presentation + { + using namespace compositions; + + namespace controls + { + using namespace reflection::description; + +/*********************************************************************** +GuiTabPage +***********************************************************************/ + + bool GuiTabPage::IsAltAvailable() + { + return false; + } + + GuiTabPage::GuiTabPage(theme::ThemeName themeName) + :GuiCustomControl(themeName) + { + } + + GuiTabPage::~GuiTabPage() + { + FinalizeAggregation(); + } + + GuiTab* GuiTabPage::GetOwnerTab() + { + return tab; + } + +/*********************************************************************** +GuiTabPageList +***********************************************************************/ + + bool GuiTabPageList::QueryInsert(vint index, GuiTabPage* const& value) + { + return !items.Contains(value) && value->tab == nullptr; + } + + void GuiTabPageList::AfterInsert(vint index, GuiTabPage* const& value) + { + value->tab = tab; + value->SetVisible(false); + value->boundsComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); + tab->containerComposition->AddChild(value->boundsComposition); + + if (!tab->selectedPage) + { + tab->SetSelectedPage(value); + } + } + + void GuiTabPageList::BeforeRemove(vint index, GuiTabPage* const& value) + { + tab->containerComposition->RemoveChild(value->boundsComposition); + value->tab = nullptr; + + if (items.Count() <= 1) + { + tab->SetSelectedPage(nullptr); + } + else if (items.Count() > index + 1) + { + tab->SetSelectedPage(items[index + 1]); + } + else if (items.Count() == index + 1) + { + tab->SetSelectedPage(items[index - 1]); + } + } + + GuiTabPageList::GuiTabPageList(GuiTab* _tab) + :tab(_tab) + { + } + + GuiTabPageList::~GuiTabPageList() + { + } + +/*********************************************************************** +GuiTab::CommandExecutor +***********************************************************************/ + + GuiTab::CommandExecutor::CommandExecutor(GuiTab* _tab) + :tab(_tab) + { + } + + GuiTab::CommandExecutor::~CommandExecutor() + { + } + + void GuiTab::CommandExecutor::ShowTab(vint index, bool setFocus) + { + tab->SetSelectedPage(tab->GetPages().Get(index)); + if (setFocus) + { + tab->SetFocus(); + } + } + +/*********************************************************************** +GuiTab +***********************************************************************/ + + void GuiTab::BeforeControlTemplateUninstalled_() + { + auto ct = TypedControlTemplateObject(false); + if (!ct) return; + + ct->SetCommands(nullptr); + ct->SetTabPages(nullptr); + ct->SetSelectedTabPage(nullptr); + } + + void GuiTab::AfterControlTemplateInstalled_(bool initialize) + { + auto ct = TypedControlTemplateObject(true); + ct->SetCommands(commandExecutor.Obj()); + ct->SetTabPages(UnboxValue>(BoxParameter(tabPages))); + ct->SetSelectedTabPage(selectedPage); + } + + void GuiTab::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) + { + if (arguments.eventSource == focusableComposition) + { + if (auto ct = TypedControlTemplateObject(false)) + { + vint index = tabPages.IndexOf(selectedPage); + if (index != -1) + { + auto hint = ct->GetTabOrder(); + vint tabOffset = 0; + switch (hint) + { + case TabPageOrder::LeftToRight: + if (arguments.code == VKEY::KEY_LEFT) tabOffset = -1; + else if (arguments.code == VKEY::KEY_RIGHT) tabOffset = 1; + break; + case TabPageOrder::RightToLeft: + if (arguments.code == VKEY::KEY_LEFT) tabOffset = 1; + else if (arguments.code == VKEY::KEY_RIGHT) tabOffset = -1; + break; + case TabPageOrder::TopToBottom: + if (arguments.code == VKEY::KEY_UP) tabOffset = -1; + else if (arguments.code == VKEY::KEY_DOWN) tabOffset = 1; + break; + case TabPageOrder::BottomToTop: + if (arguments.code == VKEY::KEY_UP) tabOffset = 1; + else if (arguments.code == VKEY::KEY_DOWN) tabOffset = -1; + break; + default:; + } + + if (tabOffset != 0) + { + arguments.handled = true; + index += tabOffset; + if (index < 0) index = 0; + else if (index >= tabPages.Count()) index = tabPages.Count() - 1; + + SetSelectedPage(tabPages[index]); + } + } + } + } + } + + GuiTab::GuiTab(theme::ThemeName themeName) + :GuiControl(themeName) + , tabPages(this) + { + commandExecutor = Ptr(new CommandExecutor(this)); + SetFocusableComposition(boundsComposition); + + boundsComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiTab::OnKeyDown); + } + + GuiTab::~GuiTab() + { + } + + collections::ObservableList& GuiTab::GetPages() + { + return tabPages; + } + + GuiTabPage* GuiTab::GetSelectedPage() + { + return selectedPage; + } + + bool GuiTab::SetSelectedPage(GuiTabPage* value) + { + if (!value) + { + if (tabPages.Count() == 0) + { + selectedPage = nullptr; + } + } + else if (value->GetOwnerTab() == this) + { + if (selectedPage == value) + { + return true; + } + + selectedPage = value; + for (auto tabPage : tabPages) + { + tabPage->SetVisible(tabPage == selectedPage); + } + } + if (auto ct = TypedControlTemplateObject(false)) + { + ct->SetSelectedTabPage(selectedPage); + } + SelectedPageChanged.Execute(GetNotifyEventArguments()); + return selectedPage == value; + } + +/*********************************************************************** +GuiScrollView +***********************************************************************/ + + void GuiScrollView::BeforeControlTemplateUninstalled_() + { + auto ct = TypedControlTemplateObject(false); + if (!ct) return; + + if (auto scroll = ct->GetHorizontalScroll()) + { + scroll->PositionChanged.Detach(hScrollHandler); + } + if (auto scroll = ct->GetVerticalScroll()) + { + scroll->PositionChanged.Detach(vScrollHandler); + } + ct->GetEventReceiver()->horizontalWheel.Detach(hWheelHandler); + ct->GetEventReceiver()->verticalWheel.Detach(vWheelHandler); + ct->BoundsChanged.Detach(containerBoundsChangedHandler); + + hScrollHandler = nullptr; + vScrollHandler = nullptr; + hWheelHandler = nullptr; + vWheelHandler = nullptr; + containerBoundsChangedHandler = nullptr; + supressScrolling = false; + } + + void GuiScrollView::AfterControlTemplateInstalled_(bool initialize) + { + auto ct = TypedControlTemplateObject(true); + if (auto scroll = ct->GetHorizontalScroll()) + { + hScrollHandler = scroll->PositionChanged.AttachMethod(this, &GuiScrollView::OnHorizontalScroll); + } + if (auto scroll = ct->GetVerticalScroll()) + { + vScrollHandler = scroll->PositionChanged.AttachMethod(this, &GuiScrollView::OnVerticalScroll); + } + hWheelHandler = ct->GetEventReceiver()->horizontalWheel.AttachMethod(this, &GuiScrollView::OnHorizontalWheel); + vWheelHandler = ct->GetEventReceiver()->verticalWheel.AttachMethod(this, &GuiScrollView::OnVerticalWheel); + containerBoundsChangedHandler = ct->BoundsChanged.AttachMethod(this, &GuiScrollView::OnContainerBoundsChanged); + CalculateView(); + } + + void GuiScrollView::UpdateDisplayFont() + { + GuiControl::UpdateDisplayFont(); + CalculateView(); + } + + void GuiScrollView::OnContainerBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + CalculateView(); + } + + void GuiScrollView::OnHorizontalScroll(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + if(!supressScrolling) + { + CallUpdateView(); + } + } + + void GuiScrollView::OnVerticalScroll(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + if(!supressScrolling) + { + CallUpdateView(); + } + } + + void GuiScrollView::OnHorizontalWheel(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) + { + if(!supressScrolling) + { + if (auto scroll = TypedControlTemplateObject(true)->GetHorizontalScroll()) + { + if (scroll->GetEnabled()) + { + vint position = scroll->GetPosition(); + vint move = scroll->GetSmallMove(); + position -= move * arguments.wheel / 60; + scroll->SetPosition(position); + } + } + } + } + + void GuiScrollView::OnVerticalWheel(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) + { + if(!supressScrolling && GetVisuallyEnabled()) + { + if (auto scroll = TypedControlTemplateObject(true)->GetVerticalScroll()) + { + if (scroll->GetEnabled()) + { + vint position = scroll->GetPosition(); + vint move = scroll->GetSmallMove(); + position -= move * arguments.wheel / 60; + scroll->SetPosition(position); + } + } + } + } + + void GuiScrollView::CallUpdateView() + { + Rect viewBounds=GetViewBounds(); + UpdateView(viewBounds); + } + + bool GuiScrollView::AdjustView(Size fullSize) + { + auto ct = TypedControlTemplateObject(true); + auto hScroll = ct->GetHorizontalScroll(); + auto vScroll = ct->GetVerticalScroll(); + Size viewSize = ct->GetContainerComposition()->GetBounds().GetSize(); + + auto hVisible = hScroll ? hScroll->GetVisible() : false; + auto vVisible = vScroll ? vScroll->GetVisible() : false; + + if (hScroll) + { + if (fullSize.x <= viewSize.x) + { + hScroll->SetVisible(horizontalAlwaysVisible); + hScroll->SetEnabled(false); + hScroll->SetPosition(0); + } + else + { + hScroll->SetVisible(true); + hScroll->SetEnabled(true); + hScroll->SetTotalSize(fullSize.x); + hScroll->SetPageSize(viewSize.x); + } + } + + if (vScroll) + { + if (fullSize.y <= viewSize.y) + { + vScroll->SetVisible(verticalAlwaysVisible); + vScroll->SetEnabled(false); + vScroll->SetPosition(0); + } + else + { + vScroll->SetVisible(true); + vScroll->SetEnabled(true); + vScroll->SetTotalSize(fullSize.y); + vScroll->SetPageSize(viewSize.y); + } + } + + auto hVisible2 = hScroll ? hScroll->GetVisible() : false; + auto vVisible2 = vScroll ? vScroll->GetVisible() : false; + return hVisible != hVisible2 || vVisible != vVisible2; + } + + GuiScrollView::GuiScrollView(theme::ThemeName themeName) + :GuiControl(themeName) + { + containerComposition->BoundsChanged.AttachMethod(this, &GuiScrollView::OnContainerBoundsChanged); + } + + vint GuiScrollView::GetSmallMove() + { + return GetDisplayFont().size * 2; + } + + Size GuiScrollView::GetBigMove() + { + return GetViewSize(); + } + + GuiScrollView::~GuiScrollView() + { + } + + void GuiScrollView::CalculateView() + { + TryDelayExecuteIfNotDeleted([=]() + { + auto ct = TypedControlTemplateObject(true); + auto hScroll = ct->GetHorizontalScroll(); + auto vScroll = ct->GetVerticalScroll(); + + if (!supressScrolling) + { + Size fullSize = QueryFullSize(); + while (true) + { + bool flagA = false; + bool flagB = false; + + flagA = AdjustView(fullSize); + bool bothInvisible = (hScroll ? !hScroll->GetVisible() : true) && (vScroll ? !vScroll->GetVisible() : true); + + if (!bothInvisible) + { + flagB = AdjustView(fullSize); + bothInvisible = (hScroll ? !hScroll->GetVisible() : true) && (vScroll ? !vScroll->GetVisible() : true); + } + + supressScrolling = true; + CallUpdateView(); + supressScrolling = false; + + Size newSize = QueryFullSize(); + if (fullSize == newSize) + { + vint smallMove = GetSmallMove(); + Size bigMove = GetBigMove(); + if (hScroll) + { + hScroll->SetSmallMove(smallMove); + hScroll->SetBigMove(bigMove.x); + } + if (vScroll) + { + vScroll->SetSmallMove(smallMove); + vScroll->SetBigMove(bigMove.y); + } + + if (bothInvisible || !flagA && !flagB) + { + break; + } + } + else + { + fullSize = newSize; + } + } + } + }); + } + + Size GuiScrollView::GetViewSize() + { + Size viewSize = TypedControlTemplateObject(true)->GetContainerComposition()->GetBounds().GetSize(); + return viewSize; + } + + Rect GuiScrollView::GetViewBounds() + { + return Rect(GetViewPosition(), GetViewSize()); + } + + Point GuiScrollView::GetViewPosition() + { + auto ct = TypedControlTemplateObject(true); + auto hScroll = ct->GetHorizontalScroll(); + auto vScroll = ct->GetVerticalScroll(); + return Point(hScroll ? hScroll->GetPosition() : 0, vScroll ? vScroll->GetPosition() : 0); + } + + void GuiScrollView::SetViewPosition(Point value) + { + auto ct = TypedControlTemplateObject(true); + if (auto hScroll = ct->GetHorizontalScroll()) + { + hScroll->SetPosition(value.x); + } + if (auto vScroll = ct->GetVerticalScroll()) + { + vScroll->SetPosition(value.y); + } + } + + GuiScroll* GuiScrollView::GetHorizontalScroll() + { + return TypedControlTemplateObject(true)->GetHorizontalScroll(); + } + + GuiScroll* GuiScrollView::GetVerticalScroll() + { + return TypedControlTemplateObject(true)->GetVerticalScroll(); + } + + bool GuiScrollView::GetHorizontalAlwaysVisible() + { + return horizontalAlwaysVisible; + } + + void GuiScrollView::SetHorizontalAlwaysVisible(bool value) + { + if (horizontalAlwaysVisible != value) + { + horizontalAlwaysVisible = value; + CalculateView(); + } + } + + bool GuiScrollView::GetVerticalAlwaysVisible() + { + return verticalAlwaysVisible; + } + + void GuiScrollView::SetVerticalAlwaysVisible(bool value) + { + if (verticalAlwaysVisible != value) + { + verticalAlwaysVisible = value; + CalculateView(); + } + } + +/*********************************************************************** +GuiScrollContainer +***********************************************************************/ + + Size GuiScrollContainer::QueryFullSize() + { + return containerComposition->GetBounds().GetSize(); + } + + void GuiScrollContainer::UpdateView(Rect viewBounds) + { + auto leftTop = Point(-viewBounds.x1, -viewBounds.y1); + containerComposition->SetBounds(Rect(leftTop, Size(0, 0))); + } + + GuiScrollContainer::GuiScrollContainer(theme::ThemeName themeName) + :GuiScrollView(themeName) + { + containerComposition->SetAlignmentToParent(Margin(-1, -1, -1, -1)); + UpdateView(Rect(0, 0, 0, 0)); + } + + GuiScrollContainer::~GuiScrollContainer() + { + } + + bool GuiScrollContainer::GetExtendToFullWidth() + { + return extendToFullWidth; + } + + void GuiScrollContainer::SetExtendToFullWidth(bool value) + { + if (extendToFullWidth != value) + { + extendToFullWidth = value; + auto margin = containerComposition->GetAlignmentToParent(); + if (value) + { + containerComposition->SetAlignmentToParent(Margin(0, margin.top, 0, margin.bottom)); + } + else + { + containerComposition->SetAlignmentToParent(Margin(-1, margin.top, -1, margin.bottom)); + } + } + } + + bool GuiScrollContainer::GetExtendToFullHeight() + { + return extendToFullHeight; + } + + void GuiScrollContainer::SetExtendToFullHeight(bool value) + { + if (extendToFullHeight != value) + { + extendToFullHeight = value; + auto margin = containerComposition->GetAlignmentToParent(); + if (value) + { + containerComposition->SetAlignmentToParent(Margin(margin.left, 0, margin.right, 0)); + } + else + { + containerComposition->SetAlignmentToParent(Margin(margin.left, -1, margin.right, -1)); + } + } + } + } + } +} + +/*********************************************************************** +.\CONTROLS\GUIDATETIMECONTROLS.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace controls + { + using namespace collections; + using namespace compositions; + using namespace elements; + +/*********************************************************************** +GuiDatePicker::CommandExecutor +***********************************************************************/ + + GuiDatePicker::CommandExecutor::CommandExecutor(GuiDatePicker* _datePicker) + :datePicker(_datePicker) + { + } + + GuiDatePicker::CommandExecutor::~CommandExecutor() + { + } + + void GuiDatePicker::CommandExecutor::NotifyDateChanged() + { + datePicker->date = datePicker->TypedControlTemplateObject(true)->GetDate(); + datePicker->UpdateText(); + datePicker->DateChanged.Execute(datePicker->GetNotifyEventArguments()); + } + + void GuiDatePicker::CommandExecutor::NotifyDateNavigated() + { + datePicker->DateNavigated.Execute(datePicker->GetNotifyEventArguments()); + } + + void GuiDatePicker::CommandExecutor::NotifyDateSelected() + { + datePicker->DateSelected.Execute(datePicker->GetNotifyEventArguments()); + } + +/*********************************************************************** +GuiDatePicker +***********************************************************************/ + + void GuiDatePicker::BeforeControlTemplateUninstalled_() + { + auto ct = TypedControlTemplateObject(false); + if (!ct) return; + + ct->SetCommands(nullptr); + } + + void GuiDatePicker::AfterControlTemplateInstalled_(bool initialize) + { + auto ct = TypedControlTemplateObject(true); + ct->SetCommands(commandExecutor.Obj()); + ct->SetDate(date); + ct->SetDateLocale(dateLocale); + UpdateText(); + } + + void GuiDatePicker::UpdateText() + { + GuiControl::SetText(dateLocale.FormatDate(dateFormat, date)); + } + + bool GuiDatePicker::IsAltAvailable() + { + if (nestedAlt) + { + return alt != L""; + } + else + { + return GuiControl::IsAltAvailable(); + } + } + + compositions::IGuiAltActionHost* GuiDatePicker::GetActivatingAltHost() + { + if (nestedAlt) + { + return this; + } + else + { + return GuiControl::GetActivatingAltHost(); + } + } + + GuiDatePicker::GuiDatePicker(theme::ThemeName themeName, bool _nestedAlt) + :GuiControl(themeName) + , nestedAlt(_nestedAlt) + { + commandExecutor = Ptr(new CommandExecutor(this)); + SetDate(DateTime::LocalTime()); + SetDateLocale(Locale::UserDefault()); + SetAltComposition(boundsComposition); + SetAltControl(this, false); + + DateChanged.SetAssociatedComposition(boundsComposition); + DateNavigated.SetAssociatedComposition(boundsComposition); + DateSelected.SetAssociatedComposition(boundsComposition); + DateFormatChanged.SetAssociatedComposition(boundsComposition); + DateLocaleChanged.SetAssociatedComposition(boundsComposition); + + commandExecutor->NotifyDateChanged(); + } + + GuiDatePicker::~GuiDatePicker() + { + } + + const DateTime& GuiDatePicker::GetDate() + { + return date; + } + + void GuiDatePicker::SetDate(const DateTime& value) + { + if (date != value) + { + date = value; + TypedControlTemplateObject(true)->SetDate(value); + } + } + + const WString& GuiDatePicker::GetDateFormat() + { + return dateFormat; + } + + void GuiDatePicker::SetDateFormat(const WString& value) + { + dateFormat=value; + UpdateText(); + DateFormatChanged.Execute(GetNotifyEventArguments()); + } + + const Locale& GuiDatePicker::GetDateLocale() + { + return dateLocale; + } + + void GuiDatePicker::SetDateLocale(const Locale& value) + { + dateLocale=value; + List formats; + dateLocale.GetLongDateFormats(formats); + if(formats.Count()>0) + { + dateFormat=formats[0]; + } + TypedControlTemplateObject(true)->SetDateLocale(dateLocale); + + UpdateText(); + DateFormatChanged.Execute(GetNotifyEventArguments()); + DateLocaleChanged.Execute(GetNotifyEventArguments()); + } + + void GuiDatePicker::SetText(const WString& value) + { + } + +/*********************************************************************** +GuiDateComboBox +***********************************************************************/ + + void GuiDateComboBox::BeforeControlTemplateUninstalled_() + { + } + + void GuiDateComboBox::AfterControlTemplateInstalled_(bool initialize) + { + auto ct = TypedControlTemplateObject(true); + datePicker->SetControlTemplate(ct->GetDatePickerTemplate()); + } + + void GuiDateComboBox::UpdateText() + { + SetText(datePicker->GetDateLocale().FormatDate(datePicker->GetDateFormat(), selectedDate)); + } + + void GuiDateComboBox::NotifyUpdateSelectedDate() + { + UpdateText(); + SelectedDateChanged.Execute(GetNotifyEventArguments()); + } + + void GuiDateComboBox::OnSubMenuOpeningChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + datePicker->SetDate(selectedDate); + } + + void GuiDateComboBox::datePicker_DateLocaleChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + UpdateText(); + } + + void GuiDateComboBox::datePicker_DateFormatChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + UpdateText(); + } + + void GuiDateComboBox::datePicker_DateSelected(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) + { + selectedDate=datePicker->GetDate(); + GetSubMenu()->Hide(); + NotifyUpdateSelectedDate(); + } + + GuiDateComboBox::GuiDateComboBox(theme::ThemeName themeName) + :GuiComboBoxBase(themeName) + { + SelectedDateChanged.SetAssociatedComposition(GetBoundsComposition()); + + datePicker = new GuiDatePicker(theme::ThemeName::DatePicker, false); + datePicker->DateSelected.AttachMethod(this, &GuiDateComboBox::datePicker_DateSelected); + datePicker->DateLocaleChanged.AttachMethod(this, &GuiDateComboBox::datePicker_DateLocaleChanged); + datePicker->DateFormatChanged.AttachMethod(this, &GuiDateComboBox::datePicker_DateFormatChanged); + datePicker->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); + + GetSubMenu()->GetContainerComposition()->AddChild(datePicker->GetBoundsComposition()); + GetSubMenu()->SetHideOnDeactivateAltHost(false); + + selectedDate=datePicker->GetDate(); + SubMenuOpeningChanged.AttachMethod(this, &GuiDateComboBox::OnSubMenuOpeningChanged); + SetFont(GetFont()); + SetText(datePicker->GetText()); + } + + GuiDateComboBox::~GuiDateComboBox() + { + } + + void GuiDateComboBox::SetFont(const Nullable& value) + { + GuiComboBoxBase::SetFont(value); + datePicker->SetFont(value); + } + + const DateTime& GuiDateComboBox::GetSelectedDate() + { + return selectedDate; + } + + void GuiDateComboBox::SetSelectedDate(const DateTime& value) + { + selectedDate=value; + NotifyUpdateSelectedDate(); + } + + GuiDatePicker* GuiDateComboBox::GetDatePicker() + { + return datePicker; + } + } + } +} + +/*********************************************************************** +.\CONTROLS\GUIDIALOGS.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace controls + { + using namespace elements; + using namespace compositions; + using namespace collections; + using namespace reflection::description; + +/*********************************************************************** +GuiDialogBase +***********************************************************************/ + + GuiWindow* GuiDialogBase::GetHostWindow() + { + if (rootObject) + { + if (auto control = dynamic_cast(rootObject)) + { + if (auto host = control->GetRelatedControlHost()) + { + return dynamic_cast(host); + } + } + else if (auto composition = dynamic_cast(rootObject)) + { + if (auto host = composition->GetRelatedControlHost()) + { + return dynamic_cast(host); + } + } + } + return nullptr; + } + + GuiDialogBase::GuiDialogBase() + { + } + + GuiDialogBase::~GuiDialogBase() + { + } + + void GuiDialogBase::Attach(GuiInstanceRootObject* _rootObject) + { + rootObject = _rootObject; + } + + void GuiDialogBase::Detach(GuiInstanceRootObject* _rootObject) + { + rootObject = nullptr; + } + +/*********************************************************************** +GuiMessageDialog +***********************************************************************/ + + GuiMessageDialog::GuiMessageDialog() + { + } + + GuiMessageDialog::~GuiMessageDialog() + { + } + + INativeDialogService::MessageBoxButtonsInput GuiMessageDialog::GetInput() + { + return input; + } + + void GuiMessageDialog::SetInput(INativeDialogService::MessageBoxButtonsInput value) + { + input = value; + } + + INativeDialogService::MessageBoxDefaultButton GuiMessageDialog::GetDefaultButton() + { + return defaultButton; + } + + void GuiMessageDialog::SetDefaultButton(INativeDialogService::MessageBoxDefaultButton value) + { + defaultButton = value; + } + + INativeDialogService::MessageBoxIcons GuiMessageDialog::GetIcon() + { + return icon; + } + + void GuiMessageDialog::SetIcon(INativeDialogService::MessageBoxIcons value) + { + icon = value; + } + + INativeDialogService::MessageBoxModalOptions GuiMessageDialog::GetModalOption() + { + return modalOption; + } + + void GuiMessageDialog::SetModalOption(INativeDialogService::MessageBoxModalOptions value) + { + modalOption = value; + } + + const WString& GuiMessageDialog::GetText() + { + return text; + } + + void GuiMessageDialog::SetText(const WString& value) + { + text = value; + } + + const WString& GuiMessageDialog::GetTitle() + { + return title; + } + + void GuiMessageDialog::SetTitle(const WString& value) + { + title = value; + } + + INativeDialogService::MessageBoxButtonsOutput GuiMessageDialog::ShowDialog() + { + auto service = GetCurrentController()->DialogService(); + return service->ShowMessageBox(GetHostWindow()->GetNativeWindow(), text, title, input, defaultButton, icon, modalOption); + } + +/*********************************************************************** +GuiColorDialog +***********************************************************************/ + + GuiColorDialog::GuiColorDialog() + { + for (vint i = 0; i < 16; i++) + { + customColors.Add(Color()); + } + } + + GuiColorDialog::~GuiColorDialog() + { + } + + bool GuiColorDialog::GetEnabledCustomColor() + { + return enabledCustomColor; + } + + void GuiColorDialog::SetEnabledCustomColor(bool value) + { + enabledCustomColor = value; + } + + bool GuiColorDialog::GetOpenedCustomColor() + { + return openedCustomColor; + } + + void GuiColorDialog::SetOpenedCustomColor(bool value) + { + openedCustomColor = value; + } + + Color GuiColorDialog::GetSelectedColor() + { + return selectedColor; + } + + void GuiColorDialog::SetSelectedColor(Color value) + { + if (selectedColor != value) + { + selectedColor = value; + SelectedColorChanged.Execute(GuiEventArgs()); + } + } + + collections::List& GuiColorDialog::GetCustomColors() + { + return customColors; + } + + bool GuiColorDialog::ShowDialog() + { + Array colors; + CopyFrom(colors, customColors); + colors.Resize(16); + + INativeDialogService::ColorDialogCustomColorOptions options = + !enabledCustomColor ? INativeDialogService::CustomColorDisabled : + !openedCustomColor ? INativeDialogService::CustomColorEnabled : + INativeDialogService::CustomColorOpened; + + auto service = GetCurrentController()->DialogService(); + if (!service->ShowColorDialog(GetHostWindow()->GetNativeWindow(), selectedColor, showSelection, options, &colors[0])) + { + return false; + } + + CopyFrom(customColors, colors); + SelectedColorChanged.Execute(GuiEventArgs()); + return true; + } + +/*********************************************************************** +GuiFontDialog +***********************************************************************/ + + GuiFontDialog::GuiFontDialog() + { + } + + GuiFontDialog::~GuiFontDialog() + { + } + + const FontProperties& GuiFontDialog::GetSelectedFont() + { + return selectedFont; + } + + void GuiFontDialog::SetSelectedFont(const FontProperties& value) + { + if (selectedFont != value) + { + selectedFont = value; + SelectedFontChanged.Execute(GuiEventArgs()); + } + } + + Color GuiFontDialog::GetSelectedColor() + { + return selectedColor; + } + + void GuiFontDialog::SetSelectedColor(Color value) + { + if (selectedColor != value) + { + selectedColor = value; + SelectedColorChanged.Execute(GuiEventArgs()); + } + } + + bool GuiFontDialog::GetShowSelection() + { + return showSelection; + } + + void GuiFontDialog::SetShowSelection(bool value) + { + showSelection = value; + } + + bool GuiFontDialog::GetShowEffect() + { + return showEffect; + } + + void GuiFontDialog::SetShowEffect(bool value) + { + showEffect = value; + } + + bool GuiFontDialog::GetForceFontExist() + { + return forceFontExist; + } + + void GuiFontDialog::SetForceFontExist(bool value) + { + forceFontExist = value; + } + + bool GuiFontDialog::ShowDialog() + { + auto service = GetCurrentController()->DialogService(); + if (!service->ShowFontDialog(GetHostWindow()->GetNativeWindow(), selectedFont, selectedColor, showSelection, showEffect, forceFontExist)) + { + return false; + } + + SelectedColorChanged.Execute(GuiEventArgs()); + SelectedFontChanged.Execute(GuiEventArgs()); + return true; + } + +/*********************************************************************** +GuiFileDialogBase +***********************************************************************/ + + GuiFileDialogBase::GuiFileDialogBase() + { + } + + GuiFileDialogBase::~GuiFileDialogBase() + { + } + + const WString& GuiFileDialogBase::GetFilter() + { + return filter; + } + + void GuiFileDialogBase::SetFilter(const WString& value) + { + filter = value; + } + + vint GuiFileDialogBase::GetFilterIndex() + { + return filterIndex; + } + + void GuiFileDialogBase::SetFilterIndex(vint value) + { + if (filterIndex != value) + { + filterIndex = value; + FilterIndexChanged.Execute(GuiEventArgs()); + } + } + + bool GuiFileDialogBase::GetEnabledPreview() + { + return enabledPreview; + } + + void GuiFileDialogBase::SetEnabledPreview(bool value) + { + enabledPreview = value; + } + + WString GuiFileDialogBase::GetTitle() + { + return title; + } + + void GuiFileDialogBase::SetTitle(const WString& value) + { + title = value; + } + + WString GuiFileDialogBase::GetFileName() + { + return fileName; + } + + void GuiFileDialogBase::SetFileName(const WString& value) + { + if (fileName != value) + { + FileNameChanged.Execute(GuiEventArgs()); + } + } + + WString GuiFileDialogBase::GetDirectory() + { + return directory; + } + + void GuiFileDialogBase::SetDirectory(const WString& value) + { + directory = value; + } + + WString GuiFileDialogBase::GetDefaultExtension() + { + return defaultExtension; + } + + void GuiFileDialogBase::SetDefaultExtension(const WString& value) + { + defaultExtension = value; + } + + INativeDialogService::FileDialogOptions GuiFileDialogBase::GetOptions() + { + return options; + } + + void GuiFileDialogBase::SetOptions(INativeDialogService::FileDialogOptions value) + { + options = value; + } + +/*********************************************************************** +GuiOpenFileDialog +***********************************************************************/ + + GuiOpenFileDialog::GuiOpenFileDialog() + { + } + + GuiOpenFileDialog::~GuiOpenFileDialog() + { + } + + collections::List& GuiOpenFileDialog::GetFileNames() + { + return fileNames; + } + + bool GuiOpenFileDialog::ShowDialog() + { + fileNames.Clear(); + auto service = GetCurrentController()->DialogService(); + if (!service->ShowFileDialog( + GetHostWindow()->GetNativeWindow(), + fileNames, + filterIndex, + (enabledPreview ? INativeDialogService::FileDialogOpenPreview : INativeDialogService::FileDialogOpen), + title, + fileName, + directory, + defaultExtension, + filter, + options)) + { + return false; + } + + if (fileNames.Count() > 0) + { + fileName = fileNames[0]; + FileNameChanged.Execute(GuiEventArgs()); + FilterIndexChanged.Execute(GuiEventArgs()); + } + return true; + } + +/*********************************************************************** +GuiSaveFileDialog +***********************************************************************/ + + GuiSaveFileDialog::GuiSaveFileDialog() + { + } + + GuiSaveFileDialog::~GuiSaveFileDialog() + { + } + + bool GuiSaveFileDialog::ShowDialog() + { + List fileNames; + auto service = GetCurrentController()->DialogService(); + if (!service->ShowFileDialog( + GetHostWindow()->GetNativeWindow(), + fileNames, + filterIndex, + (enabledPreview ? INativeDialogService::FileDialogSavePreview : INativeDialogService::FileDialogSave), + title, + fileName, + directory, + defaultExtension, + filter, + options)) + { + return false; + } + + if (fileNames.Count() > 0) + { + fileName = fileNames[0]; + FileNameChanged.Execute(GuiEventArgs()); + FilterIndexChanged.Execute(GuiEventArgs()); + } + return true; + } + } + } +} + +/*********************************************************************** +.\CONTROLS\GUISCROLLCONTROLS.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace controls + { + using namespace elements; + using namespace compositions; + using namespace collections; + using namespace reflection::description; + +/*********************************************************************** +GuiScroll::CommandExecutor +***********************************************************************/ + + GuiScroll::CommandExecutor::CommandExecutor(GuiScroll* _scroll) + :scroll(_scroll) + { + } + + GuiScroll::CommandExecutor::~CommandExecutor() + { + } + + void GuiScroll::CommandExecutor::SmallDecrease() + { + scroll->SetPosition(scroll->GetPosition()-scroll->GetSmallMove()); + } + + void GuiScroll::CommandExecutor::SmallIncrease() + { + scroll->SetPosition(scroll->GetPosition()+scroll->GetSmallMove()); + } + + void GuiScroll::CommandExecutor::BigDecrease() + { + scroll->SetPosition(scroll->GetPosition()-scroll->GetBigMove()); + } + + void GuiScroll::CommandExecutor::BigIncrease() + { + scroll->SetPosition(scroll->GetPosition()+scroll->GetBigMove()); + } + + void GuiScroll::CommandExecutor::SetTotalSize(vint value) + { + scroll->SetTotalSize(value); + } + + void GuiScroll::CommandExecutor::SetPageSize(vint value) + { + scroll->SetPageSize(value); + } + + void GuiScroll::CommandExecutor::SetPosition(vint value) + { + scroll->SetPosition(value); + } + +/*********************************************************************** +GuiScroll +***********************************************************************/ + + void GuiScroll::OnActiveAlt() + { + if (autoFocus) + { + GuiControl::OnActiveAlt(); + } + } + + bool GuiScroll::IsTabAvailable() + { + return autoFocus && GuiControl::IsTabAvailable(); + } + + void GuiScroll::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) + { + if (arguments.eventSource == focusableComposition) + { + switch (arguments.code) + { + case VKEY::KEY_HOME: + SetPosition(GetMinPosition()); + arguments.handled = true; + break; + case VKEY::KEY_END: + SetPosition(GetMaxPosition()); + arguments.handled = true; + break; + case VKEY::KEY_PRIOR: + commandExecutor->BigDecrease(); + arguments.handled = true; + break; + case VKEY::KEY_NEXT: + commandExecutor->BigIncrease(); + arguments.handled = true; + break; + case VKEY::KEY_LEFT: + case VKEY::KEY_UP: + commandExecutor->SmallDecrease(); + arguments.handled = true; + break; + case VKEY::KEY_RIGHT: + case VKEY::KEY_DOWN: + commandExecutor->SmallIncrease(); + arguments.handled = true; + break; + default:; + } + } + } + + void GuiScroll::OnMouseDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) + { + if (autoFocus) + { + SetFocus(); + } + } + + void GuiScroll::BeforeControlTemplateUninstalled_() + { + auto ct = TypedControlTemplateObject(false); + if (!ct) return; + + ct->SetCommands(nullptr); + } + + void GuiScroll::AfterControlTemplateInstalled_(bool initialize) + { + auto ct = TypedControlTemplateObject(true); + ct->SetCommands(commandExecutor.Obj()); + ct->SetPageSize(pageSize); + ct->SetTotalSize(totalSize); + ct->SetPosition(position); + } + + GuiScroll::GuiScroll(theme::ThemeName themeName) + :GuiControl(themeName) + { + SetFocusableComposition(boundsComposition); + + TotalSizeChanged.SetAssociatedComposition(boundsComposition); + PageSizeChanged.SetAssociatedComposition(boundsComposition); + PositionChanged.SetAssociatedComposition(boundsComposition); + SmallMoveChanged.SetAssociatedComposition(boundsComposition); + BigMoveChanged.SetAssociatedComposition(boundsComposition); + + commandExecutor = Ptr(new CommandExecutor(this)); + boundsComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiScroll::OnKeyDown); + boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiScroll::OnMouseDown); + boundsComposition->GetEventReceiver()->rightButtonDown.AttachMethod(this, &GuiScroll::OnMouseDown); + } + + GuiScroll::~GuiScroll() + { + } + + vint GuiScroll::GetTotalSize() + { + return totalSize; + } + + void GuiScroll::SetTotalSize(vint value) + { + if(totalSize!=value && 0totalSize) + { + SetPageSize(totalSize); + } + if(position>GetMaxPosition()) + { + SetPosition(GetMaxPosition()); + } + TypedControlTemplateObject(true)->SetTotalSize(totalSize); + TotalSizeChanged.Execute(GetNotifyEventArguments()); + } + } + + vint GuiScroll::GetPageSize() + { + return pageSize; + } + + void GuiScroll::SetPageSize(vint value) + { + if(pageSize!=value && 0<=value && value<=totalSize) + { + pageSize=value; + if(position>GetMaxPosition()) + { + SetPosition(GetMaxPosition()); + } + TypedControlTemplateObject(true)->SetPageSize(pageSize); + PageSizeChanged.Execute(GetNotifyEventArguments()); + } + } + + vint GuiScroll::GetPosition() + { + return position; + } + + void GuiScroll::SetPosition(vint value) + { + vint min=GetMinPosition(); + vint max=GetMaxPosition(); + vint newPosition= + valuemax?max: + value; + if(position!=newPosition) + { + position=newPosition; + TypedControlTemplateObject(true)->SetPosition(position); + PositionChanged.Execute(GetNotifyEventArguments()); + } + } + + vint GuiScroll::GetSmallMove() + { + return smallMove; + } + + void GuiScroll::SetSmallMove(vint value) + { + if(value>0 && smallMove!=value) + { + smallMove=value; + SmallMoveChanged.Execute(GetNotifyEventArguments()); + } + } + + vint GuiScroll::GetBigMove() + { + return bigMove; + } + + void GuiScroll::SetBigMove(vint value) + { + if(value>0 && bigMove!=value) + { + bigMove=value; + BigMoveChanged.Execute(GetNotifyEventArguments()); + } + } + + vint GuiScroll::GetMinPosition() + { + return 0; + } + + vint GuiScroll::GetMaxPosition() + { + return totalSize-pageSize; + } + + bool GuiScroll::GetAutoFocus() + { + return autoFocus; + } + + void GuiScroll::SetAutoFocus(bool value) + { + autoFocus = value; + } + } + } +} + /*********************************************************************** .\CONTROLS\LISTCONTROLPACKAGE\GUIBINDABLEDATAGRID.CPP ***********************************************************************/ @@ -9526,10 +12200,7 @@ GuiListControl::ItemCallback void GuiListControl::ItemCallback::OnStyleBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { - listControl->InvokeOrDelayIfRendering([=]() - { - listControl->CalculateView(); - }); + listControl->CalculateView(); } GuiListControl::ItemCallback::ItemCallback(GuiListControl* _listControl) @@ -14548,301 +17219,6 @@ GuiCommonScrollBehavior } } -/*********************************************************************** -.\CONTROLS\TEMPLATES\GUICONTROLSHARED.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace reflection::description; - using namespace compositions; - -/*********************************************************************** -GuiComponent -***********************************************************************/ - - GuiComponent::GuiComponent() - { - } - - GuiComponent::~GuiComponent() - { - } - - void GuiComponent::Attach(GuiInstanceRootObject* rootObject) - { - } - - void GuiComponent::Detach(GuiInstanceRootObject* rootObject) - { - } - -/*********************************************************************** -GuiInstanceRootObject -***********************************************************************/ - - class RootObjectTimerCallback : public Object, public IGuiGraphicsTimerCallback - { - public: - GuiControlHost* controlHost; - GuiInstanceRootObject* rootObject; - bool alive = true; - - RootObjectTimerCallback(GuiInstanceRootObject* _rootObject, GuiControlHost* _controlHost) - :rootObject(_rootObject) - , controlHost(_controlHost) - { - } - - bool Play()override - { - if (alive) - { - for (vint i = rootObject->runningAnimations.Count() - 1; i >= 0; i--) - { - auto animation = rootObject->runningAnimations[i]; - animation->Run(); - if (animation->GetStopped()) - { - rootObject->runningAnimations.RemoveAt(i); - } - } - - if (rootObject->runningAnimations.Count() == 0) - { - rootObject->UninstallTimerCallback(nullptr); - return false; - } - } - return alive; - } - }; - - void GuiInstanceRootObject::InstallTimerCallback(controls::GuiControlHost* controlHost) - { - if (!timerCallback) - { - timerCallback = Ptr(new RootObjectTimerCallback(this, controlHost)); - controlHost->GetTimerManager()->AddCallback(timerCallback); - } - } - - bool GuiInstanceRootObject::UninstallTimerCallback(controls::GuiControlHost* controlHost) - { - if (timerCallback && timerCallback->controlHost != controlHost) - { - timerCallback->alive = false; - timerCallback = nullptr; - return true; - } - return false; - } - - void GuiInstanceRootObject::OnControlHostForInstanceChanged() - { - auto controlHost = GetControlHostForInstance(); - if (UninstallTimerCallback(controlHost)) - { - for (auto animation : runningAnimations) - { - animation->Pause(); - } - } - - if (controlHost) - { - InstallTimerCallback(controlHost); - for (auto animation : runningAnimations) - { - animation->Resume(); - } - StartPendingAnimations(); - } - } - - void GuiInstanceRootObject::StartPendingAnimations() - { - for (auto animation : pendingAnimations) - { - animation->Start(); - } - - CopyFrom(runningAnimations, pendingAnimations, true); - pendingAnimations.Clear(); - } - - GuiInstanceRootObject::GuiInstanceRootObject() - { - } - - GuiInstanceRootObject::~GuiInstanceRootObject() - { - UninstallTimerCallback(nullptr); - } - - void GuiInstanceRootObject::FinalizeInstance() - { - if (!finalized) - { - finalized = true; - - for (auto subscription : subscriptions) - { - subscription->Close(); - } - for (auto component : components) - { - component->Detach(this); - } - - subscriptions.Clear(); - for (vint i = 0; i resolver) - { - resourceResolver = resolver; - } - - Ptr GuiInstanceRootObject::ResolveResource(const WString& protocol, const WString& path, bool ensureExist) - { - Ptr object; - if (resourceResolver) - { - object = resourceResolver->ResolveResource(protocol, path); - } - if (ensureExist && !object) - { - throw ArgumentException(L"Resource \"" + protocol + L"://" + path + L"\" does not exist."); - } - return object; - } - - Ptr GuiInstanceRootObject::AddSubscription(Ptr subscription) - { - CHECK_ERROR(finalized == false, L"GuiInstanceRootObject::AddSubscription(Ptr)#Cannot add subscription after finalizing."); - if (subscriptions.Contains(subscription.Obj())) - { - return nullptr; - } - else - { - subscriptions.Add(subscription); - subscription->Open(); - subscription->Update(); - return subscription; - } - } - - void GuiInstanceRootObject::UpdateSubscriptions() - { - for (auto subscription : subscriptions) - { - subscription->Update(); - } - } - - bool GuiInstanceRootObject::AddComponent(GuiComponent* component) - { - CHECK_ERROR(finalized == false, L"GuiInstanceRootObject::AddComponent(GuiComponent*)#Cannot add component after finalizing."); - if(components.Contains(component)) - { - return false; - } - else - { - components.Add(component); - component->Attach(this); - return true; - } - } - - bool GuiInstanceRootObject::AddControlHostComponent(GuiControlHost* controlHost) - { - return AddComponent(new GuiObjectComponent(Ptr(controlHost))); - } - - bool GuiInstanceRootObject::AddAnimation(Ptr animation) - { - CHECK_ERROR(finalized == false, L"GuiInstanceRootObject::AddAnimation(Ptr)#Cannot add animation after finalizing."); - if (runningAnimations.Contains(animation.Obj()) || pendingAnimations.Contains(animation.Obj())) - { - return false; - } - else - { - pendingAnimations.Add(animation); - - if (auto controlHost = GetControlHostForInstance()) - { - InstallTimerCallback(controlHost); - StartPendingAnimations(); - } - return true; - } - } - - bool GuiInstanceRootObject::KillAnimation(Ptr animation) - { - if (!animation) return false; - if (runningAnimations.Contains(animation.Obj())) - { - runningAnimations.Remove(animation.Obj()); - return true; - } - if (pendingAnimations.Contains(animation.Obj())) - { - pendingAnimations.Remove(animation.Obj()); - return true; - } - return false; - } - } - } -} - /*********************************************************************** .\CONTROLS\TEMPLATES\GUICONTROLTEMPLATES.CPP ***********************************************************************/ @@ -14858,33 +17234,6 @@ namespace vl using namespace compositions; using namespace elements; -/*********************************************************************** -GuiTemplate -***********************************************************************/ - - GuiTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) - - controls::GuiControlHost* GuiTemplate::GetControlHostForInstance() - { - return GetRelatedControlHost(); - } - - void GuiTemplate::OnParentLineChanged() - { - GuiBoundsComposition::OnParentLineChanged(); - OnControlHostForInstanceChanged(); - } - - GuiTemplate::GuiTemplate() - { - GuiTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) - } - - GuiTemplate::~GuiTemplate() - { - FinalizeInstanceRecursively(this); - } - /*********************************************************************** Item GuiListItemTemplate ***********************************************************************/ @@ -24646,973 +26995,6 @@ GuiAxis } } -/*********************************************************************** -.\GRAPHICSCOMPOSITION\GUIGRAPHICSBASICCOMPOSITION.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace compositions - { - using namespace collections; - using namespace controls; - using namespace elements; - -/*********************************************************************** -GuiWindowComposition -***********************************************************************/ - - GuiWindowComposition::GuiWindowComposition() - { - } - - GuiWindowComposition::~GuiWindowComposition() - { - } - - Rect GuiWindowComposition::GetBounds() - { - Rect bounds; - if (relatedHostRecord) - { - if (auto window = relatedHostRecord->host->GetNativeWindow()) - { - bounds = Rect(Point(0, 0), window->Convert(window->GetClientSize())); - } - } - UpdatePreviousBounds(bounds); - return bounds; - } - - void GuiWindowComposition::SetMargin(Margin value) - { - } - -/*********************************************************************** -GuiBoundsComposition -***********************************************************************/ - - GuiBoundsComposition::GuiBoundsComposition() - { - } - - GuiBoundsComposition::~GuiBoundsComposition() - { - } - - bool GuiBoundsComposition::GetSizeAffectParent() - { - return sizeAffectParent; - } - - void GuiBoundsComposition::SetSizeAffectParent(bool value) - { - sizeAffectParent = value; - } - - bool GuiBoundsComposition::IsSizeAffectParent() - { - return sizeAffectParent; - } - - Rect GuiBoundsComposition::GetPreferredBounds() - { - Rect result = GetBoundsInternal(compositionBounds); - if (GetParent() && IsAlignedToParent()) - { - if (alignmentToParent.left >= 0) - { - vint offset = alignmentToParent.left - result.x1; - result.x1 += offset; - result.x2 += offset; - } - if (alignmentToParent.top >= 0) - { - vint offset = alignmentToParent.top - result.y1; - result.y1 += offset; - result.y2 += offset; - } - if (alignmentToParent.right >= 0) - { - result.x2 += alignmentToParent.right; - } - if (alignmentToParent.bottom >= 0) - { - result.y2 += alignmentToParent.bottom; - } - } - return result; - } - - Rect GuiBoundsComposition::GetBounds() - { - Rect result = GetPreferredBounds(); - if (GetParent() && IsAlignedToParent()) - { - Size clientSize = GetParent()->GetClientArea().GetSize(); - if (alignmentToParent.left >= 0 && alignmentToParent.right >= 0) - { - result.x1 = alignmentToParent.left; - result.x2 = clientSize.x - alignmentToParent.right; - } - else if (alignmentToParent.left >= 0) - { - vint width = result.Width(); - result.x1 = alignmentToParent.left; - result.x2 = result.x1 + width; - } - else if (alignmentToParent.right >= 0) - { - vint width = result.Width(); - result.x2 = clientSize.x - alignmentToParent.right; - result.x1 = result.x2 - width; - } - - if (alignmentToParent.top >= 0 && alignmentToParent.bottom >= 0) - { - result.y1 = alignmentToParent.top; - result.y2 = clientSize.y - alignmentToParent.bottom; - } - else if (alignmentToParent.top >= 0) - { - vint height = result.Height(); - result.y1 = alignmentToParent.top; - result.y2 = result.y1 + height; - } - else if (alignmentToParent.bottom >= 0) - { - vint height = result.Height(); - result.y2 = clientSize.y - alignmentToParent.bottom; - result.y1 = result.y2 - height; - } - } - UpdatePreviousBounds(result); - return result; - } - - void GuiBoundsComposition::SetBounds(Rect value) - { - compositionBounds = value; - InvokeOnCompositionStateChanged(); - } - - Margin GuiBoundsComposition::GetAlignmentToParent() - { - return alignmentToParent; - } - - void GuiBoundsComposition::SetAlignmentToParent(Margin value) - { - alignmentToParent = value; - InvokeOnCompositionStateChanged(); - } - - bool GuiBoundsComposition::IsAlignedToParent() - { - return alignmentToParent != Margin(-1, -1, -1, -1); - } - } - } -} - -/*********************************************************************** -.\GRAPHICSCOMPOSITION\GUIGRAPHICSCOMPOSITIONBASE.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace compositions - { - using namespace collections; - using namespace controls; - using namespace elements; - - void InvokeOnCompositionStateChanged(compositions::GuiGraphicsComposition* composition) - { - composition->InvokeOnCompositionStateChanged(); - } - -/*********************************************************************** -GuiGraphicsComposition -***********************************************************************/ - - void GuiGraphicsComposition::OnControlParentChanged(controls::GuiControl* control) - { - if(associatedControl && associatedControl!=control) - { - if(associatedControl->GetParent()) - { - associatedControl->GetParent()->OnChildRemoved(associatedControl); - } - if(control) - { - control->OnChildInserted(associatedControl); - } - } - else - { - for(vint i=0;iOnControlParentChanged(control); - } - } - } - - void GuiGraphicsComposition::OnChildInserted(GuiGraphicsComposition* child) - { - child->OnControlParentChanged(GetRelatedControl()); - } - - void GuiGraphicsComposition::OnChildRemoved(GuiGraphicsComposition* child) - { - child->OnControlParentChanged(0); - } - - void GuiGraphicsComposition::OnParentChanged(GuiGraphicsComposition* oldParent, GuiGraphicsComposition* newParent) - { - OnParentLineChanged(); - } - - void GuiGraphicsComposition::OnParentLineChanged() - { - for (vint i = 0; i < children.Count(); i++) - { - children[i]->OnParentLineChanged(); - } - } - - void GuiGraphicsComposition::OnRenderContextChanged() - { - } - - void GuiGraphicsComposition::UpdateRelatedHostRecord(GraphicsHostRecord* record) - { - relatedHostRecord = record; - auto renderTarget = GetRenderTarget(); - - if (ownedElement) - { - if (auto renderer = ownedElement->GetRenderer()) - { - renderer->SetRenderTarget(renderTarget); - } - } - - for (vint i = 0; i < children.Count(); i++) - { - children[i]->UpdateRelatedHostRecord(record); - } - - if (HasEventReceiver()) - { - GetEventReceiver()->renderTargetChanged.Execute(GuiEventArgs(this)); - } - if (associatedControl) - { - associatedControl->OnRenderTargetChanged(renderTarget); - } - - OnRenderContextChanged(); - } - - void GuiGraphicsComposition::SetAssociatedControl(controls::GuiControl* control) - { - if (associatedControl) - { - for (vint i = 0; i < children.Count(); i++) - { - children[i]->OnControlParentChanged(0); - } - } - associatedControl = control; - if (associatedControl) - { - for (vint i = 0; i < children.Count(); i++) - { - children[i]->OnControlParentChanged(associatedControl); - } - } - } - - void GuiGraphicsComposition::InvokeOnCompositionStateChanged() - { - if (relatedHostRecord) - { - relatedHostRecord->host->RequestRender(); - } - } - - bool GuiGraphicsComposition::SharedPtrDestructorProc(DescriptableObject* obj, bool forceDisposing) - { - GuiGraphicsComposition* value=dynamic_cast(obj); - if(value->parent) - { - if (!forceDisposing) return false; - } - SafeDeleteComposition(value); - return true; - } - - GuiGraphicsComposition::GuiGraphicsComposition() - { - sharedPtrDestructorProc = &GuiGraphicsComposition::SharedPtrDestructorProc; - } - - GuiGraphicsComposition::~GuiGraphicsComposition() - { - for(vint i=0;iGetParent()) return false; - children.Insert(index, child); - - // composition parent changed -> control parent changed -> related host changed - child->parent = this; - child->OnParentChanged(nullptr, this); - OnChildInserted(child); - child->UpdateRelatedHostRecord(relatedHostRecord); - - InvokeOnCompositionStateChanged(); - return true; - } - - bool GuiGraphicsComposition::RemoveChild(GuiGraphicsComposition* child) - { - CHECK_ERROR(!isRendering, L"GuiGraphicsComposition::InsertChild(vint, GuiGraphicsComposition*)#Cannot modify composition tree during rendering."); - if (!child) return false; - vint index = children.IndexOf(child); - if (index == -1) return false; - - // composition parent changed -> control parent changed -> related host changed - child->parent = nullptr; - child->OnParentChanged(this, nullptr); - OnChildRemoved(child); - child->UpdateRelatedHostRecord(nullptr); - - GuiGraphicsHost* host = GetRelatedGraphicsHost(); - if (host) - { - host->DisconnectComposition(child); - } - children.RemoveAt(index); - InvokeOnCompositionStateChanged(); - return true; - } - - bool GuiGraphicsComposition::MoveChild(GuiGraphicsComposition* child, vint newIndex) - { - if(!child) return false; - vint index=children.IndexOf(child); - if(index==-1) return false; - children.RemoveAt(index); - children.Insert(newIndex, child); - InvokeOnCompositionStateChanged(); - return true; - } - - Ptr GuiGraphicsComposition::GetOwnedElement() - { - return ownedElement; - } - - void GuiGraphicsComposition::SetOwnedElement(Ptr element) - { - if (ownedElement != element) - { - if (ownedElement) - { - if (auto renderer = ownedElement->GetRenderer()) - { - renderer->SetRenderTarget(nullptr); - } - ownedElement->SetOwnerComposition(nullptr); - } - ownedElement = element; - if (ownedElement) - { - if (auto renderer = ownedElement->GetRenderer()) - { - renderer->SetRenderTarget(GetRenderTarget()); - } - ownedElement->SetOwnerComposition(this); - } - InvokeOnCompositionStateChanged(); - } - } - - bool GuiGraphicsComposition::GetVisible() - { - return visible; - } - - void GuiGraphicsComposition::SetVisible(bool value) - { - visible = value; - InvokeOnCompositionStateChanged(); - } - - GuiGraphicsComposition::MinSizeLimitation GuiGraphicsComposition::GetMinSizeLimitation() - { - return minSizeLimitation; - } - - void GuiGraphicsComposition::SetMinSizeLimitation(MinSizeLimitation value) - { - minSizeLimitation = value; - InvokeOnCompositionStateChanged(); - } - - elements::IGuiGraphicsRenderTarget* GuiGraphicsComposition::GetRenderTarget() - { - return relatedHostRecord ? relatedHostRecord->renderTarget : nullptr; - } - - void GuiGraphicsComposition::Render(Size offset) - { - auto renderTarget = GetRenderTarget(); - if (visible && renderTarget && !renderTarget->IsClipperCoverWholeTarget()) - { - Rect bounds = GetBounds(); - bounds.x1 += margin.left; - bounds.y1 += margin.top; - bounds.x2 -= margin.right; - bounds.y2 -= margin.bottom; - - if (bounds.x1 <= bounds.x2 && bounds.y1 <= bounds.y2) - { - bounds.x1 += offset.x; - bounds.x2 += offset.x; - bounds.y1 += offset.y; - bounds.y2 += offset.y; - - isRendering = true; - if (ownedElement) - { - IGuiGraphicsRenderer* renderer = ownedElement->GetRenderer(); - if (renderer) - { - renderer->Render(bounds); - } - } - if (children.Count() > 0) - { - bounds.x1 += internalMargin.left; - bounds.y1 += internalMargin.top; - bounds.x2 -= internalMargin.right; - bounds.y2 -= internalMargin.bottom; - if (bounds.x1 <= bounds.x2 && bounds.y1 <= bounds.y2) - { - offset = bounds.GetSize(); - renderTarget->PushClipper(bounds); - if (!renderTarget->IsClipperCoverWholeTarget()) - { - for (vint i = 0; i < children.Count(); i++) - { - children[i]->Render(Size(bounds.x1, bounds.y1)); - } - } - renderTarget->PopClipper(); - } - } - isRendering = false; - } - } - } - - GuiGraphicsEventReceiver* GuiGraphicsComposition::GetEventReceiver() - { - if(!eventReceiver) - { - eventReceiver=Ptr(new GuiGraphicsEventReceiver(this)); - } - return eventReceiver.Obj(); - } - - bool GuiGraphicsComposition::HasEventReceiver() - { - return eventReceiver; - } - - GuiGraphicsComposition* GuiGraphicsComposition::FindComposition(Point location, bool forMouseEvent) - { - if (!visible) return 0; - Rect bounds = GetBounds(); - Rect relativeBounds = Rect(Point(0, 0), bounds.GetSize()); - if (relativeBounds.Contains(location)) - { - Rect clientArea = GetClientArea(); - for (vint i = children.Count() - 1; i >= 0; i--) - { - GuiGraphicsComposition* child = children[i]; - Rect childBounds = child->GetBounds(); - vint offsetX = childBounds.x1 + (clientArea.x1 - bounds.x1); - vint offsetY = childBounds.y1 + (clientArea.y1 - bounds.y1); - Point newLocation = location - Size(offsetX, offsetY); - GuiGraphicsComposition* childResult = child->FindComposition(newLocation, forMouseEvent); - if (childResult) - { - return childResult; - } - } - - if (!forMouseEvent || !transparentToMouse) - { - return this; - } - } - return nullptr; - } - - bool GuiGraphicsComposition::GetTransparentToMouse() - { - return transparentToMouse; - } - - void GuiGraphicsComposition::SetTransparentToMouse(bool value) - { - transparentToMouse = value; - } - - Rect GuiGraphicsComposition::GetGlobalBounds() - { - Rect bounds = GetBounds(); - GuiGraphicsComposition* composition = parent; - while (composition) - { - Rect clientArea = composition->GetClientArea(); - Rect parentBounds = composition->GetBounds(); - bounds.x1 += clientArea.x1; - bounds.x2 += clientArea.x1; - bounds.y1 += clientArea.y1; - bounds.y2 += clientArea.y1; - composition = composition->parent; - } - return bounds; - } - - controls::GuiControl* GuiGraphicsComposition::GetAssociatedControl() - { - return associatedControl; - } - - GuiGraphicsHost* GuiGraphicsComposition::GetAssociatedHost() - { - if (relatedHostRecord && relatedHostRecord->host->GetMainComposition() == this) - { - return relatedHostRecord->host; - } - else - { - return nullptr; - } - } - - INativeCursor* GuiGraphicsComposition::GetAssociatedCursor() - { - return associatedCursor; - } - - void GuiGraphicsComposition::SetAssociatedCursor(INativeCursor* cursor) - { - associatedCursor = cursor; - } - - INativeWindowListener::HitTestResult GuiGraphicsComposition::GetAssociatedHitTestResult() - { - return associatedHitTestResult; - } - - void GuiGraphicsComposition::SetAssociatedHitTestResult(INativeWindowListener::HitTestResult value) - { - associatedHitTestResult = value; - } - - controls::GuiControl* GuiGraphicsComposition::GetRelatedControl() - { - GuiGraphicsComposition* composition = this; - while (composition) - { - if (composition->GetAssociatedControl()) - { - return composition->GetAssociatedControl(); - } - else - { - composition = composition->GetParent(); - } - } - return nullptr; - } - - GuiGraphicsHost* GuiGraphicsComposition::GetRelatedGraphicsHost() - { - return relatedHostRecord ? relatedHostRecord->host : nullptr; - } - - controls::GuiControlHost* GuiGraphicsComposition::GetRelatedControlHost() - { - if (auto control = GetRelatedControl()) - { - return control->GetRelatedControlHost(); - } - return nullptr; - } - - INativeCursor* GuiGraphicsComposition::GetRelatedCursor() - { - GuiGraphicsComposition* composition = this; - while (composition) - { - if (composition->GetAssociatedCursor()) - { - return composition->GetAssociatedCursor(); - } - else - { - composition = composition->GetParent(); - } - } - return nullptr; - } - - Margin GuiGraphicsComposition::GetMargin() - { - return margin; - } - - void GuiGraphicsComposition::SetMargin(Margin value) - { - margin = value; - InvokeOnCompositionStateChanged(); - } - - Margin GuiGraphicsComposition::GetInternalMargin() - { - return internalMargin; - } - - void GuiGraphicsComposition::SetInternalMargin(Margin value) - { - internalMargin = value; - InvokeOnCompositionStateChanged(); - } - - Size GuiGraphicsComposition::GetPreferredMinSize() - { - return preferredMinSize; - } - - void GuiGraphicsComposition::SetPreferredMinSize(Size value) - { - preferredMinSize = value; - InvokeOnCompositionStateChanged(); - } - - Rect GuiGraphicsComposition::GetClientArea() - { - Rect bounds=GetBounds(); - bounds.x1+=margin.left+internalMargin.left; - bounds.y1+=margin.top+internalMargin.top; - bounds.x2-=margin.right+internalMargin.right; - bounds.y2-=margin.bottom+internalMargin.bottom; - return bounds; - } - - void GuiGraphicsComposition::ForceCalculateSizeImmediately() - { - isRendering = true; - for (vint i = 0; i < children.Count(); i++) - { - children[i]->ForceCalculateSizeImmediately(); - } - isRendering = false; - InvokeOnCompositionStateChanged(); - } - -/*********************************************************************** -GuiGraphicsSite -***********************************************************************/ - - Rect GuiGraphicsSite::GetBoundsInternal(Rect expectedBounds) - { - Size minSize = GetMinPreferredClientSize(); - if (minSize.x < preferredMinSize.x) minSize.x = preferredMinSize.x; - if (minSize.y < preferredMinSize.y) minSize.y = preferredMinSize.y; - - minSize.x += margin.left + margin.right + internalMargin.left + internalMargin.right; - minSize.y += margin.top + margin.bottom + internalMargin.top + internalMargin.bottom; - vint w = expectedBounds.Width(); - vint h = expectedBounds.Height(); - if (minSize.x < w) minSize.x = w; - if (minSize.y < h) minSize.y = h; - return Rect(expectedBounds.LeftTop(), minSize); - } - - void GuiGraphicsSite::UpdatePreviousBounds(Rect bounds) - { - if (previousBounds != bounds) - { - previousBounds = bounds; - BoundsChanged.Execute(GuiEventArgs(this)); - InvokeOnCompositionStateChanged(); - } - } - - GuiGraphicsSite::GuiGraphicsSite() - { - BoundsChanged.SetAssociatedComposition(this); - } - - GuiGraphicsSite::~GuiGraphicsSite() - { - } - - bool GuiGraphicsSite::IsSizeAffectParent() - { - return true; - } - - Size GuiGraphicsSite::GetMinPreferredClientSize() - { - Size minSize; - if (minSizeLimitation != GuiGraphicsComposition::NoLimit) - { - if (ownedElement) - { - IGuiGraphicsRenderer* renderer = ownedElement->GetRenderer(); - if (renderer) - { - minSize = renderer->GetMinSize(); - } - } - } - if (minSizeLimitation == GuiGraphicsComposition::LimitToElementAndChildren) - { - vint childCount = Children().Count(); - for (vint i = 0; i < childCount; i++) - { - GuiGraphicsComposition* child = children[i]; - if (child->IsSizeAffectParent()) - { - Rect childBounds = child->GetPreferredBounds(); - if (minSize.x < childBounds.x2) minSize.x = childBounds.x2; - if (minSize.y < childBounds.y2) minSize.y = childBounds.y2; - } - } - } - return minSize; - } - - Rect GuiGraphicsSite::GetPreferredBounds() - { - return GetBoundsInternal(Rect(Point(0, 0), GetMinPreferredClientSize())); - } - -/*********************************************************************** -Helper Functions -***********************************************************************/ - - void NotifyFinalizeInstance(controls::GuiControl* value) - { - if (value) - { - NotifyFinalizeInstance(value->GetBoundsComposition()); - } - } - - void NotifyFinalizeInstance(GuiGraphicsComposition* value) - { - if (value) - { - bool finalized = false; - if (auto root = dynamic_cast(value)) - { - if (root->IsFinalized()) - { - finalized = true; - } - else - { - root->FinalizeInstance(); - } - } - - if (auto control = value->GetAssociatedControl()) - { - if (auto root = dynamic_cast(control)) - { - if (root->IsFinalized()) - { - finalized = true; - } - else - { - root->FinalizeInstance(); - } - } - } - - if (!finalized) - { - vint count = value->Children().Count(); - for (vint i = 0; i < count; i++) - { - NotifyFinalizeInstance(value->Children()[i]); - } - } - } - } - - void SafeDeleteControlInternal(controls::GuiControl* value) - { - if(value) - { - if (value->GetRelatedControlHost() != value) - { - GuiGraphicsComposition* bounds = value->GetBoundsComposition(); - if (bounds->GetParent()) - { - bounds->GetParent()->RemoveChild(bounds); - } - } - delete value; - } - } - - void SafeDeleteCompositionInternal(GuiGraphicsComposition* value) - { - if (value) - { - if (value->GetParent()) - { - value->GetParent()->RemoveChild(value); - } - - if (value->GetAssociatedControl()) - { - SafeDeleteControlInternal(value->GetAssociatedControl()); - } - else - { - for (vint i = value->Children().Count() - 1; i >= 0; i--) - { - SafeDeleteCompositionInternal(value->Children().Get(i)); - } - delete value; - } - } - } - - void SafeDeleteControl(controls::GuiControl* value) - { - if (auto controlHost = dynamic_cast(value)) - { - controlHost->DeleteAfterProcessingAllEvents(); - } - else - { - NotifyFinalizeInstance(value); - SafeDeleteControlInternal(value); - } - } - - void SafeDeleteComposition(GuiGraphicsComposition* value) - { - NotifyFinalizeInstance(value); - SafeDeleteCompositionInternal(value); - } - } - } -} - -/*********************************************************************** -.\GRAPHICSCOMPOSITION\GUIGRAPHICSEVENTRECEIVER.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace compositions - { - -/*********************************************************************** -Event Receiver -***********************************************************************/ - - GuiGraphicsEventReceiver::GuiGraphicsEventReceiver(GuiGraphicsComposition* _sender) - :sender(_sender) - ,leftButtonDown(_sender) - ,leftButtonUp(_sender) - ,leftButtonDoubleClick(_sender) - ,middleButtonDown(_sender) - ,middleButtonUp(_sender) - ,middleButtonDoubleClick(_sender) - ,rightButtonDown(_sender) - ,rightButtonUp(_sender) - ,rightButtonDoubleClick(_sender) - ,horizontalWheel(_sender) - ,verticalWheel(_sender) - ,mouseMove(_sender) - ,mouseEnter(_sender) - ,mouseLeave(_sender) - ,previewKey(_sender) - ,keyDown(_sender) - ,keyUp(_sender) - ,systemKeyDown(_sender) - ,systemKeyUp(_sender) - ,previewCharInput(_sender) - ,charInput(_sender) - ,gotFocus(_sender) - ,lostFocus(_sender) - ,caretNotify(_sender) - ,clipboardNotify(_sender) - { - } - - GuiGraphicsEventReceiver::~GuiGraphicsEventReceiver() - { - } - - GuiGraphicsComposition* GuiGraphicsEventReceiver::GetAssociatedComposition() - { - return sender; - } - } - } -} - /*********************************************************************** .\GRAPHICSCOMPOSITION\GUIGRAPHICSFLOWCOMPOSITION.CPP ***********************************************************************/ @@ -27060,10 +28442,9 @@ GuiResponsiveContainerComposition void GuiResponsiveContainerComposition::OnBoundsChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) { - auto control = GetRelatedControl(); - if (control) + if (auto control = GetRelatedControl()) { - control->InvokeOrDelayIfRendering([=]() + control->TryDelayExecuteIfNotDeleted([=]() { AdjustLevel(); }); @@ -31690,1507 +33071,6 @@ GuiColorizedTextElement } -/*********************************************************************** -.\GRAPHICSHOST\GUIGRAPHICSHOST.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace compositions - { - using namespace collections; - using namespace controls; - using namespace elements; - using namespace theme; - -/*********************************************************************** -GuiGraphicsTimerManager -***********************************************************************/ - - GuiGraphicsTimerManager::GuiGraphicsTimerManager() - { - } - - GuiGraphicsTimerManager::~GuiGraphicsTimerManager() - { - } - - void GuiGraphicsTimerManager::AddCallback(Ptr callback) - { - callbacks.Add(callback); - } - - void GuiGraphicsTimerManager::Play() - { - for (vint i = callbacks.Count() - 1; i >= 0; i--) - { - auto callback = callbacks[i]; - if (!callback->Play()) - { - callbacks.RemoveAt(i); - } - } - } - -/*********************************************************************** -GuiGraphicsHost -***********************************************************************/ - - void GuiGraphicsHost::RefreshRelatedHostRecord(INativeWindow* nativeWindow) - { - hostRecord.nativeWindow = nativeWindow; - hostRecord.renderTarget = nativeWindow ? GetGuiGraphicsResourceManager()->GetRenderTarget(nativeWindow) : nullptr; - windowComposition->UpdateRelatedHostRecord(&hostRecord); - } - - void GuiGraphicsHost::DisconnectCompositionInternal(GuiGraphicsComposition* composition) - { - for(vint i=0;iChildren().Count();i++) - { - DisconnectCompositionInternal(composition->Children().Get(i)); - } - if(mouseCaptureComposition==composition) - { - if(hostRecord.nativeWindow) - { - hostRecord.nativeWindow->ReleaseCapture(); - } - mouseCaptureComposition=0; - } - if(focusedComposition==composition) - { - focusedComposition=0; - } - mouseEnterCompositions.Remove(composition); - } - - void GuiGraphicsHost::MouseCapture(const NativeWindowMouseInfo& info) - { - if (hostRecord.nativeWindow && (info.left || info.middle || info.right)) - { - if (!hostRecord.nativeWindow->IsCapturing() && !info.nonClient) - { - hostRecord.nativeWindow->RequireCapture(); - auto point = hostRecord.nativeWindow->Convert(NativePoint(info.x, info.y)); - mouseCaptureComposition = windowComposition->FindComposition(point, true); - } - } - } - - void GuiGraphicsHost::MouseUncapture(const NativeWindowMouseInfo& info) - { - if(hostRecord.nativeWindow && !(info.left || info.middle || info.right)) - { - hostRecord.nativeWindow->ReleaseCapture(); - mouseCaptureComposition=0; - } - } - - void GuiGraphicsHost::OnCharInput(const NativeWindowCharInfo& info, GuiGraphicsComposition* composition, GuiCharEvent GuiGraphicsEventReceiver::* eventReceiverEvent) - { - List compositions; - while(composition) - { - if(composition->HasEventReceiver()) - { - compositions.Add(composition); - } - composition=composition->GetParent(); - } - - GuiCharEventArgs arguments(composition); - (NativeWindowCharInfo&)arguments=info; - - for(vint i=compositions.Count()-1;i>=0;i--) - { - compositions[i]->GetEventReceiver()->previewCharInput.Execute(arguments); - if(arguments.handled) - { - return; - } - } - - for(vint i=0;iGetEventReceiver()->*eventReceiverEvent).Execute(arguments); - if(arguments.handled) - { - return; - } - } - } - - void GuiGraphicsHost::OnKeyInput(const NativeWindowKeyInfo& info, GuiGraphicsComposition* composition, GuiKeyEvent GuiGraphicsEventReceiver::* eventReceiverEvent) - { - List compositions; - { - auto current = composition; - while (current) - { - if (current->HasEventReceiver()) - { - compositions.Add(current); - } - current = current->GetParent(); - } - } - - GuiKeyEventArgs arguments(composition); - (NativeWindowKeyInfo&)arguments = info; - - for (vint i = compositions.Count() - 1; i >= 0; i--) - { - compositions[i]->GetEventReceiver()->previewKey.Execute(arguments); - if (arguments.handled) - { - return; - } - } - - for (vint i = 0; i < compositions.Count(); i++) - { - (compositions[i]->GetEventReceiver()->*eventReceiverEvent).Execute(arguments); - if (arguments.handled) - { - return; - } - } - } - - void GuiGraphicsHost::RaiseMouseEvent(GuiMouseEventArgs& arguments, GuiGraphicsComposition* composition, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent) - { - arguments.compositionSource=composition; - arguments.eventSource=0; - vint x=arguments.x; - vint y=arguments.y; - - while(composition) - { - if(composition->HasEventReceiver()) - { - if(!arguments.eventSource) - { - arguments.eventSource=composition; - } - GuiGraphicsEventReceiver* eventReceiver=composition->GetEventReceiver(); - (eventReceiver->*eventReceiverEvent).Execute(arguments); - if(arguments.handled) - { - break; - } - } - - GuiGraphicsComposition* parent=composition->GetParent(); - if(parent) - { - Rect parentBounds=parent->GetBounds(); - Rect clientArea=parent->GetClientArea(); - Rect childBounds=composition->GetBounds(); - - x+=childBounds.x1+(clientArea.x1-parentBounds.x1); - y+=childBounds.y1+(clientArea.y1-parentBounds.y1); - arguments.x=x; - arguments.y=y; - } - composition=parent; - } - } - - void GuiGraphicsHost::OnMouseInput(const NativeWindowMouseInfo& info, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent) - { - GuiGraphicsComposition* composition = 0; - if (mouseCaptureComposition) - { - composition = mouseCaptureComposition; - } - else - { - auto point = hostRecord.nativeWindow->Convert(NativePoint(info.x, info.y)); - composition = windowComposition->FindComposition(point, true); - } - if (composition) - { - Rect bounds = composition->GetGlobalBounds(); - Point point = hostRecord.nativeWindow->Convert(NativePoint(info.x, info.y)); - GuiMouseEventArgs arguments; - arguments.ctrl = info.ctrl; - arguments.shift = info.shift; - arguments.left = info.left; - arguments.middle = info.middle; - arguments.right = info.right; - arguments.wheel = info.wheel; - arguments.nonClient = info.nonClient; - arguments.x = point.x - bounds.x1; - arguments.y = point.y - bounds.y1; - RaiseMouseEvent(arguments, composition, eventReceiverEvent); - } - } - - void GuiGraphicsHost::RecreateRenderTarget() - { - windowComposition->UpdateRelatedHostRecord(nullptr); - GetGuiGraphicsResourceManager()->RecreateRenderTarget(hostRecord.nativeWindow); - RefreshRelatedHostRecord(hostRecord.nativeWindow); - } - - INativeWindowListener::HitTestResult GuiGraphicsHost::HitTest(NativePoint location) - { - NativeRect bounds = hostRecord.nativeWindow->GetBounds(); - NativeRect clientBounds = hostRecord.nativeWindow->GetClientBoundsInScreen(); - NativePoint clientLocation(location.x + bounds.x1 - clientBounds.x1, location.y + bounds.y1 - clientBounds.y1); - auto point = hostRecord.nativeWindow->Convert(clientLocation); - GuiGraphicsComposition* hitComposition = windowComposition->FindComposition(point, true); - while (hitComposition) - { - INativeWindowListener::HitTestResult result = hitComposition->GetAssociatedHitTestResult(); - if (result == INativeWindowListener::NoDecision) - { - hitComposition = hitComposition->GetParent(); - } - else - { - return result; - } - } - return INativeWindowListener::NoDecision; - } - - void GuiGraphicsHost::Moving(NativeRect& bounds, bool fixSizeOnly, bool draggingBorder) - { - NativeRect oldBounds = hostRecord.nativeWindow->GetBounds(); - minSize = windowComposition->GetPreferredBounds().GetSize(); - NativeSize minWindowSize = hostRecord.nativeWindow->Convert(minSize) + (oldBounds.GetSize() - hostRecord.nativeWindow->GetClientSize()); - if (bounds.Width() < minWindowSize.x) - { - if (fixSizeOnly) - { - if (bounds.Width() < minWindowSize.x) - { - bounds.x2 = bounds.x1 + minWindowSize.x; - } - } - else if (oldBounds.x1 != bounds.x1) - { - bounds.x1 = oldBounds.x2 - minWindowSize.x; - } - else if (oldBounds.x2 != bounds.x2) - { - bounds.x2 = oldBounds.x1 + minWindowSize.x; - } - } - if (bounds.Height() < minWindowSize.y) - { - if (fixSizeOnly) - { - if (bounds.Height() < minWindowSize.y) - { - bounds.y2 = bounds.y1 + minWindowSize.y; - } - } - else if (oldBounds.y1 != bounds.y1) - { - bounds.y1 = oldBounds.y2 - minWindowSize.y; - } - else if (oldBounds.y2 != bounds.y2) - { - bounds.y2 = oldBounds.y1 + minWindowSize.y; - } - } - } - - void GuiGraphicsHost::Moved() - { - NativeSize size = hostRecord.nativeWindow->GetClientSize(); - if (previousClientSize != size) - { - previousClientSize = size; - minSize = windowComposition->GetPreferredBounds().GetSize(); - needRender = true; - } - } - - void GuiGraphicsHost::DpiChanged() - { - RecreateRenderTarget(); - needRender = true; - } - - void GuiGraphicsHost::Paint() - { - if (!supressPaint) - { - needRender = true; - } - } - - void GuiGraphicsHost::LeftButtonDown(const NativeWindowMouseInfo& info) - { - altActionManager->CloseAltHost(); - MouseCapture(info); - OnMouseInput(info, &GuiGraphicsEventReceiver::leftButtonDown); - } - - void GuiGraphicsHost::LeftButtonUp(const NativeWindowMouseInfo& info) - { - OnMouseInput(info, &GuiGraphicsEventReceiver::leftButtonUp); - MouseUncapture(info); - } - - void GuiGraphicsHost::LeftButtonDoubleClick(const NativeWindowMouseInfo& info) - { - LeftButtonDown(info); - OnMouseInput(info, &GuiGraphicsEventReceiver::leftButtonDoubleClick); - } - - void GuiGraphicsHost::RightButtonDown(const NativeWindowMouseInfo& info) - { - altActionManager->CloseAltHost(); - MouseCapture(info); - OnMouseInput(info, &GuiGraphicsEventReceiver::rightButtonDown); - } - - void GuiGraphicsHost::RightButtonUp(const NativeWindowMouseInfo& info) - { - OnMouseInput(info, &GuiGraphicsEventReceiver::rightButtonUp); - MouseUncapture(info); - } - - void GuiGraphicsHost::RightButtonDoubleClick(const NativeWindowMouseInfo& info) - { - RightButtonDown(info); - OnMouseInput(info, &GuiGraphicsEventReceiver::rightButtonDoubleClick); - } - - void GuiGraphicsHost::MiddleButtonDown(const NativeWindowMouseInfo& info) - { - altActionManager->CloseAltHost(); - MouseCapture(info); - OnMouseInput(info, &GuiGraphicsEventReceiver::middleButtonDown); - } - - void GuiGraphicsHost::MiddleButtonUp(const NativeWindowMouseInfo& info) - { - OnMouseInput(info, &GuiGraphicsEventReceiver::middleButtonUp); - MouseUncapture(info); - } - - void GuiGraphicsHost::MiddleButtonDoubleClick(const NativeWindowMouseInfo& info) - { - MiddleButtonDown(info); - OnMouseInput(info, &GuiGraphicsEventReceiver::middleButtonDoubleClick); - } - - void GuiGraphicsHost::HorizontalWheel(const NativeWindowMouseInfo& info) - { - OnMouseInput(info, &GuiGraphicsEventReceiver::horizontalWheel); - } - - void GuiGraphicsHost::VerticalWheel(const NativeWindowMouseInfo& info) - { - OnMouseInput(info, &GuiGraphicsEventReceiver::verticalWheel); - } - - void GuiGraphicsHost::MouseMoving(const NativeWindowMouseInfo& info) - { - CompositionList newCompositions; - { - auto point = hostRecord.nativeWindow->Convert(NativePoint(info.x, info.y)); - GuiGraphicsComposition* composition = windowComposition->FindComposition(point, true); - while (composition) - { - newCompositions.Insert(0, composition); - composition = composition->GetParent(); - } - } - - vint firstDifferentIndex = mouseEnterCompositions.Count(); - for (vint i = 0; i < mouseEnterCompositions.Count(); i++) - { - if (i == newCompositions.Count()) - { - firstDifferentIndex = newCompositions.Count(); - break; - } - if (mouseEnterCompositions[i] != newCompositions[i]) - { - firstDifferentIndex = i; - break; - } - } - - for (vint i = mouseEnterCompositions.Count() - 1; i >= firstDifferentIndex; i--) - { - GuiGraphicsComposition* composition = mouseEnterCompositions[i]; - if (composition->HasEventReceiver()) - { - composition->GetEventReceiver()->mouseLeave.Execute(GuiEventArgs(composition)); - } - } - - CopyFrom(mouseEnterCompositions, newCompositions); - for (vint i = firstDifferentIndex; i < mouseEnterCompositions.Count(); i++) - { - GuiGraphicsComposition* composition = mouseEnterCompositions[i]; - if (composition->HasEventReceiver()) - { - composition->GetEventReceiver()->mouseEnter.Execute(GuiEventArgs(composition)); - } - } - - INativeCursor* cursor = 0; - if (newCompositions.Count() > 0) - { - cursor = newCompositions[newCompositions.Count() - 1]->GetRelatedCursor(); - } - if (cursor) - { - hostRecord.nativeWindow->SetWindowCursor(cursor); - } - else - { - hostRecord.nativeWindow->SetWindowCursor(GetCurrentController()->ResourceService()->GetDefaultSystemCursor()); - } - - OnMouseInput(info, &GuiGraphicsEventReceiver::mouseMove); - } - - void GuiGraphicsHost::MouseEntered() - { - } - - void GuiGraphicsHost::MouseLeaved() - { - for(vint i=mouseEnterCompositions.Count()-1;i>=0;i--) - { - GuiGraphicsComposition* composition=mouseEnterCompositions[i]; - if(composition->HasEventReceiver()) - { - composition->GetEventReceiver()->mouseLeave.Execute(GuiEventArgs(composition)); - } - } - mouseEnterCompositions.Clear(); - } - - void GuiGraphicsHost::KeyDown(const NativeWindowKeyInfo& info) - { - if (altActionManager->KeyDown(info)) { return; } - if (tabActionManager->KeyDown(info, focusedComposition)) { return; } - if(shortcutKeyManager && shortcutKeyManager->Execute(info)) { return; } - - if (focusedComposition && focusedComposition->HasEventReceiver()) - { - OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::keyDown); - } - } - - void GuiGraphicsHost::KeyUp(const NativeWindowKeyInfo& info) - { - if (altActionManager->KeyUp(info)) { return; } - - if(focusedComposition && focusedComposition->HasEventReceiver()) - { - OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::keyUp); - } - } - - void GuiGraphicsHost::SysKeyDown(const NativeWindowKeyInfo& info) - { - if (altActionManager->SysKeyDown(info)) { return; } - - if(focusedComposition && focusedComposition->HasEventReceiver()) - { - OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::systemKeyDown); - } - } - - void GuiGraphicsHost::SysKeyUp(const NativeWindowKeyInfo& info) - { - if (altActionManager->SysKeyUp(info)) { return; } - - if (!info.ctrl && !info.shift && info.code == VKEY::KEY_MENU && hostRecord.nativeWindow) - { - if (hostRecord.nativeWindow) - { - hostRecord.nativeWindow->SupressAlt(); - } - } - - if (focusedComposition && focusedComposition->HasEventReceiver()) - { - OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::systemKeyUp); - } - } - - void GuiGraphicsHost::Char(const NativeWindowCharInfo& info) - { - if (altActionManager->Char(info)) { return; } - if (tabActionManager->Char(info)) { return; } - - if(focusedComposition && focusedComposition->HasEventReceiver()) - { - OnCharInput(info, focusedComposition, &GuiGraphicsEventReceiver::charInput); - } - } - - void GuiGraphicsHost::GlobalTimer() - { - timerManager.Play(); - - DateTime now=DateTime::UtcTime(); - if(now.totalMilliseconds-lastCaretTime>=CaretInterval) - { - lastCaretTime=now.totalMilliseconds; - if(focusedComposition && focusedComposition->HasEventReceiver()) - { - focusedComposition->GetEventReceiver()->caretNotify.Execute(GuiEventArgs(focusedComposition)); - } - } - - Render(false); - } - - GuiGraphicsHost::GuiGraphicsHost(controls::GuiControlHost* _controlHost, GuiGraphicsComposition* boundsComposition) - :controlHost(_controlHost) - { - altActionManager = new GuiAltActionManager(controlHost); - tabActionManager = new GuiTabActionManager(controlHost); - hostRecord.host = this; - windowComposition=new GuiWindowComposition; - windowComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); - windowComposition->AddChild(boundsComposition); - RefreshRelatedHostRecord(nullptr); - } - - GuiGraphicsHost::~GuiGraphicsHost() - { - windowComposition->RemoveChild(windowComposition->Children()[0]); - NotifyFinalizeInstance(windowComposition); - - delete altActionManager; - delete tabActionManager; - if (shortcutKeyManager) - { - delete shortcutKeyManager; - shortcutKeyManager = nullptr; - } - - delete windowComposition; - } - - INativeWindow* GuiGraphicsHost::GetNativeWindow() - { - return hostRecord.nativeWindow; - } - - void GuiGraphicsHost::SetNativeWindow(INativeWindow* _nativeWindow) - { - if (hostRecord.nativeWindow != _nativeWindow) - { - if (hostRecord.nativeWindow) - { - GetCurrentController()->CallbackService()->UninstallListener(this); - hostRecord.nativeWindow->UninstallListener(this); - } - - if (_nativeWindow) - { - _nativeWindow->InstallListener(this); - GetCurrentController()->CallbackService()->InstallListener(this); - previousClientSize = _nativeWindow->GetClientSize(); - minSize = windowComposition->GetPreferredBounds().GetSize(); - _nativeWindow->SetCaretPoint(_nativeWindow->Convert(caretPoint)); - needRender = true; - } - - RefreshRelatedHostRecord(_nativeWindow); - } - } - - GuiGraphicsComposition* GuiGraphicsHost::GetMainComposition() - { - return windowComposition; - } - - void GuiGraphicsHost::Render(bool forceUpdate) - { - if (!forceUpdate && !needRender) - { - return; - } - needRender = false; - - if(hostRecord.nativeWindow && hostRecord.nativeWindow->IsVisible()) - { - supressPaint = true; - hostRecord.renderTarget->StartRendering(); - windowComposition->Render(Size()); - auto result = hostRecord.renderTarget->StopRendering(); - hostRecord.nativeWindow->RedrawContent(); - supressPaint = false; - - switch (result) - { - case RenderTargetFailure::ResizeWhileRendering: - { - GetGuiGraphicsResourceManager()->ResizeRenderTarget(hostRecord.nativeWindow); - needRender = true; - } - break; - case RenderTargetFailure::LostDevice: - { - RecreateRenderTarget(); - needRender = true; - } - break; - default: - { - supressPaint = true; - auto bounds = windowComposition->GetBounds(); - auto preferred = windowComposition->GetPreferredBounds(); - auto width = bounds.Width() > preferred.Width() ? bounds.Width() : preferred.Width(); - auto height = bounds.Height() > preferred.Height() ? bounds.Height() : preferred.Height(); - controlHost->UpdateClientSizeAfterRendering(preferred.GetSize(), Size(width, height)); - supressPaint = false; - } - } - } - - if (!needRender) - { - { - ProcList procs; - CopyFrom(procs, afterRenderProcs); - afterRenderProcs.Clear(); - for (vint i = 0; i < procs.Count(); i++) - { - procs[i](); - } - } - { - ProcMap procs; - CopyFrom(procs, afterRenderKeyedProcs); - afterRenderKeyedProcs.Clear(); - for (vint i = 0; i < procs.Count(); i++) - { - procs.Values()[i](); - } - } - } - } - - void GuiGraphicsHost::RequestRender() - { - needRender = true; - } - - void GuiGraphicsHost::InvokeAfterRendering(const Func& proc, ProcKey key) - { - if (key.key == nullptr) - { - afterRenderProcs.Add(proc); - } - else - { - afterRenderKeyedProcs.Set(key, proc); - } - } - - void GuiGraphicsHost::InvalidateTabOrderCache() - { - tabActionManager->InvalidateTabOrderCache(); - } - - IGuiShortcutKeyManager* GuiGraphicsHost::GetShortcutKeyManager() - { - return shortcutKeyManager; - } - - void GuiGraphicsHost::SetShortcutKeyManager(IGuiShortcutKeyManager* value) - { - shortcutKeyManager=value; - } - - bool GuiGraphicsHost::SetFocus(GuiGraphicsComposition* composition) - { - if(!composition || composition->GetRelatedGraphicsHost()!=this) - { - return false; - } - if(focusedComposition && focusedComposition->HasEventReceiver()) - { - GuiEventArgs arguments; - arguments.compositionSource=focusedComposition; - arguments.eventSource=focusedComposition; - focusedComposition->GetEventReceiver()->lostFocus.Execute(arguments); - } - focusedComposition=composition; - SetCaretPoint(Point(0, 0)); - if(focusedComposition && focusedComposition->HasEventReceiver()) - { - GuiEventArgs arguments; - arguments.compositionSource=focusedComposition; - arguments.eventSource=focusedComposition; - focusedComposition->GetEventReceiver()->gotFocus.Execute(arguments); - } - return true; - } - - GuiGraphicsComposition* GuiGraphicsHost::GetFocusedComposition() - { - return focusedComposition; - } - - Point GuiGraphicsHost::GetCaretPoint() - { - return caretPoint; - } - - void GuiGraphicsHost::SetCaretPoint(Point value, GuiGraphicsComposition* referenceComposition) - { - if (referenceComposition) - { - Rect bounds = referenceComposition->GetGlobalBounds(); - value.x += bounds.x1; - value.y += bounds.y1; - } - caretPoint = value; - if (hostRecord.nativeWindow) - { - hostRecord.nativeWindow->SetCaretPoint(hostRecord.nativeWindow->Convert(caretPoint)); - } - } - - GuiGraphicsTimerManager* GuiGraphicsHost::GetTimerManager() - { - return &timerManager; - } - - void GuiGraphicsHost::DisconnectComposition(GuiGraphicsComposition* composition) - { - DisconnectCompositionInternal(composition); - } - } - } -} - -/*********************************************************************** -.\GRAPHICSHOST\GUIGRAPHICSHOST_ALT.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace compositions - { - using namespace collections; - using namespace controls; - using namespace theme; - - const wchar_t* const IGuiAltAction::Identifier = L"vl::presentation::compositions::IGuiAltAction"; - const wchar_t* const IGuiAltActionContainer::Identifier = L"vl::presentation::compositions::IGuiAltActionContainer"; - const wchar_t* const IGuiAltActionHost::Identifier = L"vl::presentation::compositions::IGuiAltActionHost"; - -/*********************************************************************** -IGuiAltAction -***********************************************************************/ - - bool IGuiAltAction::IsLegalAlt(const WString& alt) - { - for (vint i = 0; i < alt.Length(); i++) - { - auto c = alt[i]; - if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')) - { - continue; - } - return false; - } - return true; - } - -/*********************************************************************** -IGuiAltActionHost -***********************************************************************/ - - void IGuiAltActionHost::CollectAltActionsFromControl(controls::GuiControl* control, bool includeThisControl, collections::Group& actions) - { - List controls; - controls.Add(control); - vint index = 0; - - while (index < controls.Count()) - { - auto current = controls[index++]; - - if (current != control || includeThisControl) - { - if (auto container = current->QueryTypedService()) - { - vint count = container->GetAltActionCount(); - for (vint i = 0; i < count; i++) - { - auto action = container->GetAltAction(i); - actions.Add(action->GetAlt(), action); - } - continue; - } - else if (auto action = current->QueryTypedService()) - { - if (action->IsAltAvailable()) - { - if (action->IsAltEnabled()) - { - actions.Add(action->GetAlt(), action); - continue; - } - } - } - } - - vint count = current->GetChildrenCount(); - for (vint i = 0; i < count; i++) - { - controls.Add(current->GetChild(i)); - } - } - } - -/*********************************************************************** -GuiAltActionHostBase -***********************************************************************/ - - void GuiAltActionHostBase::SetAltComposition(GuiGraphicsComposition* _composition) - { - composition = _composition; - } - - void GuiAltActionHostBase::SetAltControl(controls::GuiControl* _control, bool _includeControl) - { - control = _control; - includeControl = _includeControl; - } - - GuiGraphicsComposition* GuiAltActionHostBase::GetAltComposition() - { - CHECK_ERROR(composition, L"GuiAltActionHostBase::GetAltComposition()#Need to call SetAltComposition."); - return composition; - } - - IGuiAltActionHost* GuiAltActionHostBase::GetPreviousAltHost() - { - return previousHost; - } - - void GuiAltActionHostBase::OnActivatedAltHost(IGuiAltActionHost* _previousHost) - { - previousHost = _previousHost; - } - - void GuiAltActionHostBase::OnDeactivatedAltHost() - { - previousHost = nullptr; - } - - void GuiAltActionHostBase::CollectAltActions(collections::Group& actions) - { - CHECK_ERROR(control, L"GuiAltActionHostBase::CollectAltActions(Group&)#Need to call SetAltControl."); - CollectAltActionsFromControl(control, includeControl, actions); - } - -/*********************************************************************** -GuiAltActionManager -***********************************************************************/ - - void GuiAltActionManager::EnterAltHost(IGuiAltActionHost* host) - { - ClearAltHost(); - - Group actions; - host->CollectAltActions(actions); - if (actions.Count() == 0) - { - CloseAltHost(); - return; - } - - host->OnActivatedAltHost(currentAltHost); - currentAltHost = host; - CreateAltTitles(actions); - } - - void GuiAltActionManager::LeaveAltHost() - { - if (currentAltHost) - { - ClearAltHost(); - auto previousHost = currentAltHost->GetPreviousAltHost(); - currentAltHost->OnDeactivatedAltHost(); - currentAltHost = previousHost; - - if (currentAltHost) - { - Group actions; - currentAltHost->CollectAltActions(actions); - CreateAltTitles(actions); - } - } - } - - bool GuiAltActionManager::EnterAltKey(wchar_t key) - { - currentAltPrefix += WString::FromChar(key); - vint index = currentActiveAltActions.Keys().IndexOf(currentAltPrefix); - if (index == -1) - { - if (FilterTitles() == 0) - { - currentAltPrefix = currentAltPrefix.Left(currentAltPrefix.Length() - 1); - FilterTitles(); - } - } - else - { - auto action = currentActiveAltActions.Values()[index]; - if (action->GetActivatingAltHost()) - { - EnterAltHost(action->GetActivatingAltHost()); - } - else - { - CloseAltHost(); - } - action->OnActiveAlt(); - return true; - } - return false; - } - - void GuiAltActionManager::LeaveAltKey() - { - if (currentAltPrefix.Length() >= 1) - { - currentAltPrefix = currentAltPrefix.Left(currentAltPrefix.Length() - 1); - } - FilterTitles(); - } - - void GuiAltActionManager::CreateAltTitles(const collections::Group& actions) - { - if (currentAltHost) - { - vint count = actions.Count(); - for (vint i = 0; i < count; i++) - { - WString key = actions.Keys()[i]; - const auto& values = actions.GetByIndex(i); - vint numberLength = 0; - if (values.Count() == 1 && key.Length() > 0) - { - numberLength = 0; - } - else if (values.Count() <= 10) - { - numberLength = 1; - } - else if (values.Count() <= 100) - { - numberLength = 2; - } - else if (values.Count() <= 1000) - { - numberLength = 3; - } - else - { - continue; - } - - for (auto [action, index] : indexed(values)) - { - WString key = actions.Keys()[i]; - if (numberLength > 0) - { - WString number = itow(index); - while (number.Length() < numberLength) - { - number = L"0" + number; - } - key += number; - } - currentActiveAltActions.Add(key, action); - } - } - - count = currentActiveAltActions.Count(); - auto window = dynamic_cast(currentAltHost->GetAltComposition()->GetRelatedControlHost()); - for (vint i = 0; i < count; i++) - { - auto key = currentActiveAltActions.Keys()[i]; - auto composition = currentActiveAltActions.Values()[i]->GetAltComposition(); - - auto label = new GuiLabel(theme::ThemeName::ShortcutKey); - if (auto labelStyle = window->TypedControlTemplateObject(true)->GetShortcutKeyTemplate()) - { - label->SetControlTemplate(labelStyle); - } - label->SetText(key); - composition->AddChild(label->GetBoundsComposition()); - currentActiveAltTitles.Add(key, label); - } - - FilterTitles(); - } - } - - vint GuiAltActionManager::FilterTitles() - { - vint count = currentActiveAltTitles.Count(); - vint visibles = 0; - for (vint i = 0; i < count; i++) - { - auto key = currentActiveAltTitles.Keys()[i]; - auto value = currentActiveAltTitles.Values()[i]; - if (key.Length() >= currentAltPrefix.Length() && key.Left(currentAltPrefix.Length()) == currentAltPrefix) - { - value->SetVisible(true); - if (currentAltPrefix.Length() <= key.Length()) - { - value->SetText( - key - .Insert(currentAltPrefix.Length(), L"[") - .Insert(currentAltPrefix.Length() + 2, L"]") - ); - } - else - { - value->SetText(key); - } - visibles++; - } - else - { - value->SetVisible(false); - } - } - return visibles; - } - - void GuiAltActionManager::ClearAltHost() - { - for (auto title : currentActiveAltTitles.Values()) - { - SafeDeleteControl(title); - } - currentActiveAltActions.Clear(); - currentActiveAltTitles.Clear(); - currentAltPrefix = L""; - } - - void GuiAltActionManager::CloseAltHost() - { - ClearAltHost(); - while (currentAltHost) - { - currentAltHost->OnDeactivatedAltHost(); - currentAltHost = currentAltHost->GetPreviousAltHost(); - } - } - - GuiAltActionManager::GuiAltActionManager(controls::GuiControlHost* _controlHost) - :controlHost(_controlHost) - { - } - - GuiAltActionManager::~GuiAltActionManager() - { - } - - bool GuiAltActionManager::KeyDown(const NativeWindowKeyInfo& info) - { - if (!info.ctrl && !info.shift && currentAltHost) - { - if (info.code == VKEY::KEY_ESCAPE) - { - LeaveAltHost(); - return true; - } - else if (info.code == VKEY::KEY_BACK) - { - LeaveAltKey(); - } - else if (VKEY::KEY_NUMPAD0 <= info.code && info.code <= VKEY::KEY_NUMPAD9) - { - if (EnterAltKey((wchar_t)(L'0' + ((vint)info.code - (vint)VKEY::KEY_NUMPAD0)))) - { - supressAltKey = info.code; - return true; - } - } - else if ((VKEY::KEY_0 <= info.code && info.code <= VKEY::KEY_9) || (VKEY::KEY_A <= info.code && info.code <= VKEY::KEY_Z)) - { - if (EnterAltKey((wchar_t)info.code)) - { - supressAltKey = info.code; - return true; - } - } - } - - if (currentAltHost) - { - return true; - } - return false; - } - - bool GuiAltActionManager::KeyUp(const NativeWindowKeyInfo& info) - { - if (!info.ctrl && !info.shift && info.code == supressAltKey) - { - supressAltKey = VKEY::KEY_UNKNOWN; - return true; - } - return false; - } - - bool GuiAltActionManager::SysKeyDown(const NativeWindowKeyInfo& info) - { - if (!info.ctrl && !info.shift && info.code == VKEY::KEY_MENU && !currentAltHost) - { - if (auto altHost = controlHost->QueryTypedService()) - { - if (!altHost->GetPreviousAltHost()) - { - EnterAltHost(altHost); - } - } - } - - if (currentAltHost) - { - return true; - } - return false; - } - - bool GuiAltActionManager::SysKeyUp(const NativeWindowKeyInfo& info) - { - return false; - } - - bool GuiAltActionManager::Char(const NativeWindowCharInfo& info) - { - if (currentAltHost || supressAltKey != VKEY::KEY_UNKNOWN) - { - return true; - } - return false; - } - } - } -} - -/*********************************************************************** -.\GRAPHICSHOST\GUIGRAPHICSHOST_SHORTCUTKEY.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace compositions - { - -/*********************************************************************** -GuiShortcutKeyItem -***********************************************************************/ - - GuiShortcutKeyItem::GuiShortcutKeyItem(GuiShortcutKeyManager* _shortcutKeyManager, bool _ctrl, bool _shift, bool _alt, VKEY _key) - :shortcutKeyManager(_shortcutKeyManager) - ,ctrl(_ctrl) - ,shift(_shift) - ,alt(_alt) - ,key(_key) - { - } - - GuiShortcutKeyItem::~GuiShortcutKeyItem() - { - } - - IGuiShortcutKeyManager* GuiShortcutKeyItem::GetManager() - { - return shortcutKeyManager; - } - - WString GuiShortcutKeyItem::GetName() - { - WString name; - if(ctrl) name+=L"Ctrl+"; - if(shift) name+=L"Shift+"; - if(alt) name+=L"Alt+"; - name+=GetCurrentController()->InputService()->GetKeyName(key); - return name; - } - - bool GuiShortcutKeyItem::CanActivate(const NativeWindowKeyInfo& info) - { - return - info.ctrl==ctrl && - info.shift==shift && - info.alt==alt && - info.code==key; - } - - bool GuiShortcutKeyItem::CanActivate(bool _ctrl, bool _shift, bool _alt, VKEY _key) - { - return - _ctrl==ctrl && - _shift==shift && - _alt==alt && - _key==key; - } - -/*********************************************************************** -GuiShortcutKeyManager -***********************************************************************/ - - GuiShortcutKeyManager::GuiShortcutKeyManager() - { - } - - GuiShortcutKeyManager::~GuiShortcutKeyManager() - { - } - - vint GuiShortcutKeyManager::GetItemCount() - { - return shortcutKeyItems.Count(); - } - - IGuiShortcutKeyItem* GuiShortcutKeyManager::GetItem(vint index) - { - return shortcutKeyItems[index].Obj(); - } - - bool GuiShortcutKeyManager::Execute(const NativeWindowKeyInfo& info) - { - bool executed=false; - for (auto item : shortcutKeyItems) - { - if(item->CanActivate(info)) - { - GuiEventArgs arguments; - item->Executed.Execute(arguments); - executed=true; - } - } - return executed; - } - - IGuiShortcutKeyItem* GuiShortcutKeyManager::CreateShortcut(bool ctrl, bool shift, bool alt, VKEY key) - { - for (auto item : shortcutKeyItems) - { - if(item->CanActivate(ctrl, shift, alt, key)) - { - return item.Obj(); - } - } - auto item=Ptr(new GuiShortcutKeyItem(this, ctrl, shift, alt, key)); - shortcutKeyItems.Add(item); - return item.Obj(); - } - - bool GuiShortcutKeyManager::DestroyShortcut(bool ctrl, bool shift, bool alt, VKEY key) - { - for (auto item : shortcutKeyItems) - { - if(item->CanActivate(ctrl, shift, alt, key)) - { - shortcutKeyItems.Remove(item.Obj()); - return true; - } - } - return false; - } - - IGuiShortcutKeyItem* GuiShortcutKeyManager::TryGetShortcut(bool ctrl, bool shift, bool alt, VKEY key) - { - for (auto item : shortcutKeyItems) - { - if(item->CanActivate(ctrl, shift, alt, key)) - { - return item.Obj(); - } - } - return 0; - } - } - } -} - -/*********************************************************************** -.\GRAPHICSHOST\GUIGRAPHICSHOST_TAB.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace compositions - { - using namespace collections; - using namespace controls; - - const wchar_t* const IGuiTabAction::Identifier = L"vl::presentation::compositions::IGuiTabAction"; - -/*********************************************************************** -GuiTabActionManager -***********************************************************************/ - - namespace tab_focus - { - void CollectControls(GuiControl* current, bool includeCurrent, Group& prioritized) - { - if (includeCurrent) - { - auto tabAction = current->QueryTypedService(); - if (tabAction && (tabAction->IsTabAvailable() || tabAction->GetTabPriority() != -1)) - { - vint priority = tabAction->GetTabPriority(); - vuint64_t normalized = priority < 0 ? ~(vuint64_t)0 : (vuint64_t)priority; - prioritized.Add(normalized, current); - return; - } - } - - vint count = current->GetChildrenCount(); - for (vint i = 0; i < count; i++) - { - CollectControls(current->GetChild(i), true, prioritized); - } - } - - void InsertPrioritized(List& controls, vint index, Group& prioritized) - { - vint count = prioritized.Count(); - for (vint i = 0; i < count; i++) - { - auto& values = prioritized.GetByIndex(i); - for (vint j = 0; j < values.Count(); j++) - { - controls.Insert(index++, values[j]); - } - } - } - } - using namespace tab_focus; - - void GuiTabActionManager::BuildControlList() - { - controlsInOrder.Clear(); - { - Group prioritized; - CollectControls(controlHost, false, prioritized); - InsertPrioritized(controlsInOrder, 0, prioritized); - } - - for (vint i = 0; i < controlsInOrder.Count(); i++) - { - Group prioritized; - CollectControls(controlsInOrder[i], false, prioritized); - InsertPrioritized(controlsInOrder, i + 1, prioritized); - } - } - - controls::GuiControl* GuiTabActionManager::GetNextFocusControl(controls::GuiControl* focusedControl, vint offset) - { - if (!available) - { - BuildControlList(); - available = true; - } -#define STEP_AND_NORMALIZE(INDEX) (((INDEX) + offset + controlsInOrder.Count()) % controlsInOrder.Count()) - - if (controlsInOrder.Count() == 0) return nullptr; - vint startIndex = controlsInOrder.IndexOf(focusedControl); - startIndex = - startIndex == -1 ? 0 : - STEP_AND_NORMALIZE(startIndex); - - vint index = startIndex; - do - { - auto control = controlsInOrder[index]; - if (auto tabAction = control->QueryTypedService()) - { - if (tabAction->IsTabAvailable() && tabAction->IsTabEnabled()) - { - return control; - } - } - - index = STEP_AND_NORMALIZE(index); - } while (index != startIndex); - -#undef STEP_AND_NORMALIZE - - return nullptr; - } - - GuiTabActionManager::GuiTabActionManager(controls::GuiControlHost* _controlHost) - :controlHost(_controlHost) - { - } - - GuiTabActionManager::~GuiTabActionManager() - { - } - - void GuiTabActionManager::InvalidateTabOrderCache() - { - available = false; - controlsInOrder.Clear(); - } - - bool GuiTabActionManager::KeyDown(const NativeWindowKeyInfo& info, GuiGraphicsComposition* focusedComposition) - { - if (!info.ctrl && !info.alt && info.code == VKEY::KEY_TAB) - { - GuiControl* focusedControl = nullptr; - if (focusedComposition) - { - focusedControl = focusedComposition->GetRelatedControl(); - if (focusedControl && focusedControl->GetAcceptTabInput()) - { - return false; - } - } - - if (auto next = GetNextFocusControl(focusedControl, (info.shift ? -1 : 1))) - { - next->SetFocus(); - supressTabOnce = true; - return true; - } - } - return false; - } - - bool GuiTabActionManager::Char(const NativeWindowCharInfo& info) - { - bool supress = supressTabOnce; - supressTabOnce = false; - return supress && info.code == L'\t'; - } - } - } -} - /*********************************************************************** .\NATIVEWINDOW\GUINATIVEWINDOW.CPP ***********************************************************************/ @@ -38247,7 +38127,6 @@ namespace vl namespace presentation { using namespace collections; - using namespace controls; using namespace glr::xml; using namespace glr::json; using namespace regex; @@ -38334,6 +38213,156 @@ IGuiParserManager } } +/*********************************************************************** +.\RESOURCES\GUIPLUGINMANAGER.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + using namespace collections; + +/*********************************************************************** +GuiPluginManager +***********************************************************************/ + + class GuiPluginManager : public Object, public IGuiPluginManager + { + protected: + List> plugins; + bool loaded; + public: + GuiPluginManager() + :loaded(false) + { + } + + ~GuiPluginManager() + { + Unload(); + } + + void AddPlugin(Ptr plugin)override + { + CHECK_ERROR(!loaded, L"GuiPluginManager::AddPlugin(Ptr)#Load function has already been executed."); + auto name = plugin->GetName(); + if (name != L"") + { + for (auto plugin : plugins) + { + CHECK_ERROR(plugin->GetName() != name, L"GuiPluginManager::AddPlugin(Ptr)#Duplicated plugin name."); + } + } + plugins.Add(plugin); + } + + void Load()override + { + CHECK_ERROR(!loaded, L"GuiPluginManager::AddPlugin(Ptr)#Load function has already been executed."); + loaded=true; + + SortedList loaded; + Group loading; + Dictionary> pluginsToLoad; + for (auto plugin : plugins) + { + auto name = plugin->GetName(); + pluginsToLoad.Add(name, plugin); + List dependencies; + plugin->GetDependencies(dependencies); + for (auto dependency : dependencies) + { + loading.Add(name, dependency); + } + } + + while (pluginsToLoad.Count() > 0) + { + vint count = pluginsToLoad.Count(); + { + for (auto [name, index] : indexed(pluginsToLoad.Keys())) + { + if (!loading.Keys().Contains(name)) + { + for (vint i = loading.Count() - 1; i >= 0; i--) + { + loading.Remove(loading.Keys()[i], name); + } + loaded.Add(name); + + auto plugin = pluginsToLoad.Values()[index]; + pluginsToLoad.Remove(name); + plugin->Load(); + break; + } + } + } + if (count == pluginsToLoad.Count()) + { + WString message; + for (auto plugin : pluginsToLoad.Values()) + { + message += L"Cannot load plugin \"" + plugin->GetName() + L"\" because part of its dependencies are not ready:"; + List dependencies; + plugin->GetDependencies(dependencies); + bool first = true; + for (auto dependency : dependencies) + { + if (!loaded.Contains(dependency)) + { + message += L" \"" + dependency + L"\";"; + } + } + message += L"\r\n"; + } + throw Exception(message); + } + } + } + + void Unload()override + { + CHECK_ERROR(loaded, L"GuiPluginManager::AddPlugin(Ptr)#Load function has not been executed."); + loaded=false; + for (auto plugin : plugins) + { + plugin->Unload(); + } + } + + bool IsLoaded()override + { + return loaded; + } + }; + +/*********************************************************************** +Helpers +***********************************************************************/ + + IGuiPluginManager* pluginManager=0; + + IGuiPluginManager* GetPluginManager() + { + if(!pluginManager) + { + pluginManager=new GuiPluginManager; + } + return pluginManager; + } + + void DestroyPluginManager() + { + if(pluginManager) + { + delete pluginManager; + pluginManager=0; + } + } + } +} + /*********************************************************************** .\RESOURCES\GUIRESOURCE.CPP ***********************************************************************/ @@ -38342,7 +38371,6 @@ namespace vl { namespace presentation { - using namespace controls; using namespace collections; using namespace glr::xml; using namespace stream; @@ -40191,7 +40219,6 @@ namespace vl using namespace stream; using namespace glr::xml; using namespace reflection::description; - using namespace controls; /*********************************************************************** Class Name Record (ClassNameRecord) @@ -40454,7 +40481,6 @@ namespace vl namespace presentation { using namespace collections; - using namespace controls; using namespace glr::xml; using namespace stream; diff --git a/Import/GacUI.h b/Import/GacUI.h index 8ef94baf..a774d2be 100644 --- a/Import/GacUI.h +++ b/Import/GacUI.h @@ -3169,7 +3169,7 @@ Native Window Controller #endif /*********************************************************************** -.\GRAPHICSCOMPOSITION\GUIGRAPHICSEVENTRECEIVER.H +.\APPLICATION\GRAPHICSCOMPOSITIONS\GUIGRAPHICSEVENTRECEIVER.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 @@ -3747,7 +3747,7 @@ Workflow to C++ Codegen Helpers #endif /*********************************************************************** -.\GRAPHICSCOMPOSITION\GUIGRAPHICSCOMPOSITIONBASE.H +.\APPLICATION\GRAPHICSCOMPOSITIONS\GUIGRAPHICSCOMPOSITIONBASE.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 @@ -4031,6 +4031,19 @@ Basic Construction Size GetMinPreferredClientSize()override; Rect GetPreferredBounds()override; }; + + /// + /// Represents a composition for the client area in an . + /// + class GuiWindowComposition : public GuiGraphicsSite, public Description + { + public: + GuiWindowComposition(); + ~GuiWindowComposition(); + + Rect GetBounds()override; + void SetMargin(Margin value)override; + }; /*********************************************************************** Helper Functions @@ -4058,7 +4071,7 @@ Helper Functions #endif /*********************************************************************** -.\GRAPHICSCOMPOSITION\GUIGRAPHICSBASICCOMPOSITION.H +.\APPLICATION\GRAPHICSCOMPOSITIONS\GUIGRAPHICSBASICCOMPOSITION.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 @@ -4082,19 +4095,6 @@ namespace vl /*********************************************************************** Basic Compositions ***********************************************************************/ - - /// - /// Represents a composition for the client area in an . - /// - class GuiWindowComposition : public GuiGraphicsSite, public Description - { - public: - GuiWindowComposition(); - ~GuiWindowComposition(); - - Rect GetBounds()override; - void SetMargin(Margin value)override; - }; /// /// Represents a composition that is free to change the expected bounds. @@ -4140,6 +4140,551 @@ Basic Compositions #endif +/*********************************************************************** +.\APPLICATION\GRAPHICSHOST\GUIGRAPHICSHOST_ALT.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Graphics Composition Host + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_ALT +#define VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_ALT + + +namespace vl +{ + namespace presentation + { + namespace controls + { + class GuiControl; + class GuiControlHost; + } + + namespace compositions + { + +/*********************************************************************** +Alt-Combined Shortcut Key Interfaces +***********************************************************************/ + + class IGuiAltActionHost; + + /// IGuiAltAction is the handler when an alt-combined shortcut key is activated. + class IGuiAltAction : public virtual IDescriptable + { + public: + /// The identifier for this service. + static const wchar_t* const Identifier; + + static bool IsLegalAlt(const WString& alt); + + virtual const WString& GetAlt() = 0; + virtual bool IsAltEnabled() = 0; + virtual bool IsAltAvailable() = 0; + virtual GuiGraphicsComposition* GetAltComposition() = 0; + virtual IGuiAltActionHost* GetActivatingAltHost() = 0; + virtual void OnActiveAlt() = 0; + }; + + /// IGuiAltActionContainer enumerates multiple . + class IGuiAltActionContainer : public virtual IDescriptable + { + public: + /// The identifier for this service. + static const wchar_t* const Identifier; + + virtual vint GetAltActionCount() = 0; + virtual IGuiAltAction* GetAltAction(vint index) = 0; + }; + + /// IGuiAltActionHost is an alt-combined shortcut key host. A host can also be entered or leaved, with multiple sub actions enabled or disabled. + class IGuiAltActionHost : public virtual IDescriptable + { + public: + /// The identifier for this service. + static const wchar_t* const Identifier; + + static void CollectAltActionsFromControl(controls::GuiControl* control, bool includeThisControl, collections::Group& actions); + + virtual GuiGraphicsComposition* GetAltComposition() = 0; + virtual IGuiAltActionHost* GetPreviousAltHost() = 0; + virtual void OnActivatedAltHost(IGuiAltActionHost* previousHost) = 0; + virtual void OnDeactivatedAltHost() = 0; + virtual void CollectAltActions(collections::Group& actions) = 0; + }; + + /// Default implementation for + class GuiAltActionHostBase : public virtual IGuiAltActionHost + { + private: + GuiGraphicsComposition* composition = nullptr; + controls::GuiControl* control = nullptr; + bool includeControl = true; + IGuiAltActionHost* previousHost = nullptr; + + protected: + void SetAltComposition(GuiGraphicsComposition* _composition); + void SetAltControl(controls::GuiControl* _control, bool _includeControl); + + public: + GuiGraphicsComposition* GetAltComposition()override; + IGuiAltActionHost* GetPreviousAltHost()override; + void OnActivatedAltHost(IGuiAltActionHost* _previousHost)override; + void OnDeactivatedAltHost()override; + void CollectAltActions(collections::Group& actions)override; + }; + +/*********************************************************************** +Alt-Combined Shortcut Key Interfaces Helpers +***********************************************************************/ + + class GuiAltActionManager : public Object + { + typedef collections::Dictionary AltActionMap; + typedef collections::Dictionary AltControlMap; + protected: + controls::GuiControlHost* controlHost = nullptr; + IGuiAltActionHost* currentAltHost = nullptr; + AltActionMap currentActiveAltActions; + AltControlMap currentActiveAltTitles; + WString currentAltPrefix; + VKEY supressAltKey = VKEY::KEY_UNKNOWN; + + void EnterAltHost(IGuiAltActionHost* host); + void LeaveAltHost(); + bool EnterAltKey(wchar_t key); + void LeaveAltKey(); + void CreateAltTitles(const collections::Group& actions); + vint FilterTitles(); + void ClearAltHost(); + public: + GuiAltActionManager(controls::GuiControlHost* _controlHost); + ~GuiAltActionManager(); + + void CloseAltHost(); + bool KeyDown(const NativeWindowKeyInfo& info); + bool KeyUp(const NativeWindowKeyInfo& info); + bool SysKeyDown(const NativeWindowKeyInfo& info); + bool SysKeyUp(const NativeWindowKeyInfo& info); + bool Char(const NativeWindowCharInfo& info); + }; + } + } +} + +#endif + +/*********************************************************************** +.\APPLICATION\GRAPHICSHOST\GUIGRAPHICSHOST_SHORTCUTKEY.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Graphics Composition Host + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_SHORTCUTKEY +#define VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_SHORTCUTKEY + + +namespace vl +{ + namespace presentation + { + namespace compositions + { + +/*********************************************************************** +Shortcut Key Manager +***********************************************************************/ + + class IGuiShortcutKeyManager; + + /// Shortcut key item. + class IGuiShortcutKeyItem : public virtual IDescriptable, public Description + { + public: + /// Shortcut key executed event. + GuiNotifyEvent Executed; + + /// Get the associated object. + /// The associated shortcut key manager. + virtual IGuiShortcutKeyManager* GetManager()=0; + /// Get the name represents the shortcut key combination for this item. + /// The name represents the shortcut key combination for this item. + virtual WString GetName()=0; + }; + + /// Shortcut key manager item. + class IGuiShortcutKeyManager : public virtual IDescriptable, public Description + { + public: + /// Get the number of shortcut key items that already attached to the manager. + /// T number of shortcut key items that already attached to the manager. + virtual vint GetItemCount()=0; + /// Get the associated with the index. + /// The shortcut key item. + /// The index. + virtual IGuiShortcutKeyItem* GetItem(vint index)=0; + /// Execute shortcut key items using a key event info. + /// Returns true if at least one shortcut key item is executed. + /// The key event info. + virtual bool Execute(const NativeWindowKeyInfo& info)=0; + }; + +/*********************************************************************** +Shortcut Key Manager Helpers +***********************************************************************/ + + class GuiShortcutKeyManager; + + class GuiShortcutKeyItem : public Object, public IGuiShortcutKeyItem + { + protected: + GuiShortcutKeyManager* shortcutKeyManager; + bool ctrl; + bool shift; + bool alt; + VKEY key; + + void AttachManager(GuiShortcutKeyManager* manager); + void DetachManager(GuiShortcutKeyManager* manager); + public: + GuiShortcutKeyItem(GuiShortcutKeyManager* _shortcutKeyManager, bool _ctrl, bool _shift, bool _alt, VKEY _key); + ~GuiShortcutKeyItem(); + + IGuiShortcutKeyManager* GetManager()override; + WString GetName()override; + bool CanActivate(const NativeWindowKeyInfo& info); + bool CanActivate(bool _ctrl, bool _shift, bool _alt, VKEY _key); + }; + + /// A default implementation for . + class GuiShortcutKeyManager : public Object, public IGuiShortcutKeyManager, public Description + { + typedef collections::List> ShortcutKeyItemList; + protected: + ShortcutKeyItemList shortcutKeyItems; + + public: + /// Create the shortcut key manager. + GuiShortcutKeyManager(); + ~GuiShortcutKeyManager(); + + vint GetItemCount()override; + IGuiShortcutKeyItem* GetItem(vint index)override; + bool Execute(const NativeWindowKeyInfo& info)override; + + /// Create a shortcut key item using a key combination. If the item for the key combination exists, this function returns the item that is created before. + /// The created shortcut key item. + /// Set to true if the CTRL key is required. + /// Set to true if the SHIFT key is required. + /// Set to true if the ALT key is required. + /// The non-control key. + IGuiShortcutKeyItem* CreateShortcut(bool ctrl, bool shift, bool alt, VKEY key); + /// Destroy a shortcut key item using a key combination + /// Returns true if the manager destroyed a existing shortcut key item. + /// Set to true if the CTRL key is required. + /// Set to true if the SHIFT key is required. + /// Set to true if the ALT key is required. + /// The non-control key. + bool DestroyShortcut(bool ctrl, bool shift, bool alt, VKEY key); + /// Get a shortcut key item using a key combination. If the item for the key combination does not exist, this function returns null. + /// The shortcut key item. + /// Set to true if the CTRL key is required. + /// Set to true if the SHIFT key is required. + /// Set to true if the ALT key is required. + /// The non-control key. + IGuiShortcutKeyItem* TryGetShortcut(bool ctrl, bool shift, bool alt, VKEY key); + }; + } + } +} + +#endif + +/*********************************************************************** +.\APPLICATION\GRAPHICSHOST\GUIGRAPHICSHOST_TAB.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Graphics Composition Host + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_TAB +#define VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_TAB + + +namespace vl +{ + namespace presentation + { + namespace controls + { + class GuiControl; + class GuiControlHost; + } + + namespace compositions + { + +/*********************************************************************** +Tab-Combined Shortcut Key Interfaces +***********************************************************************/ + + /// IGuiTabAction is the handler when an tab-combined shortcut key is activated. + class IGuiTabAction : public virtual IDescriptable + { + public: + /// The identifier for this service. + static const wchar_t* const Identifier; + + virtual bool GetAcceptTabInput() = 0; + virtual vint GetTabPriority() = 0; + virtual bool IsTabEnabled() = 0; + virtual bool IsTabAvailable() = 0; + }; + +/*********************************************************************** +Tab-Combined Shortcut Key Interfaces Helpers +***********************************************************************/ + + class GuiTabActionManager : public Object + { + using ControlList = collections::List; + protected: + controls::GuiControlHost* controlHost = nullptr; + ControlList controlsInOrder; + bool available = true; + bool supressTabOnce = false; + + void BuildControlList(); + controls::GuiControl* GetNextFocusControl(controls::GuiControl* focusedControl, vint offset); + public: + GuiTabActionManager(controls::GuiControlHost* _controlHost); + ~GuiTabActionManager(); + + void InvalidateTabOrderCache(); + bool KeyDown(const NativeWindowKeyInfo& info, GuiGraphicsComposition* focusedComposition); + bool Char(const NativeWindowCharInfo& info); + }; + } + } +} + +#endif + +/*********************************************************************** +.\APPLICATION\GRAPHICSHOST\GUIGRAPHICSHOST.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Graphics Composition Host + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST +#define VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST + + +namespace vl +{ + namespace presentation + { + namespace controls + { + class GuiWindow; + } + + namespace compositions + { + +/*********************************************************************** +Animation +***********************************************************************/ + + /// + /// Represents a timer callback object. + /// + class IGuiGraphicsTimerCallback : public virtual IDescriptable, public Description + { + public: + /// Called periodically. + /// Returns false to indicate that this callback need to be removed. + virtual bool Play() = 0; + }; + + /// + /// Timer callback manager. + /// + class GuiGraphicsTimerManager : public Object, public Description + { + typedef collections::List> CallbackList; + protected: + CallbackList callbacks; + + public: + GuiGraphicsTimerManager(); + ~GuiGraphicsTimerManager(); + + /// Add a new callback. + /// The new callback to add. + void AddCallback(Ptr callback); + /// Called periodically. + void Play(); + }; + +/*********************************************************************** +Host +***********************************************************************/ + + /// + /// GuiGraphicsHost hosts an in an . The composition will fill the whole window. + /// + class GuiGraphicsHost : public Object, private INativeWindowListener, private INativeControllerListener, public Description + { + typedef collections::List CompositionList; + typedef GuiGraphicsComposition::GraphicsHostRecord HostRecord; + typedef collections::Pair ProcKey; + typedef collections::List> ProcList; + typedef collections::Dictionary> ProcMap; + public: + static const vuint64_t CaretInterval = 500; + + protected: + HostRecord hostRecord; + bool supressPaint = false; + bool needRender = true; + ProcList afterRenderProcs; + ProcMap afterRenderKeyedProcs; + + GuiAltActionManager* altActionManager = nullptr; + GuiTabActionManager* tabActionManager = nullptr; + IGuiShortcutKeyManager* shortcutKeyManager = nullptr; + + controls::GuiControlHost* controlHost = nullptr; + GuiWindowComposition* windowComposition = nullptr; + GuiGraphicsComposition* focusedComposition = nullptr; + NativeSize previousClientSize; + Size minSize; + Point caretPoint; + vuint64_t lastCaretTime = 0; + + GuiGraphicsTimerManager timerManager; + GuiGraphicsComposition* mouseCaptureComposition = nullptr; + CompositionList mouseEnterCompositions; + void RefreshRelatedHostRecord(INativeWindow* nativeWindow); + + void DisconnectCompositionInternal(GuiGraphicsComposition* composition); + void MouseCapture(const NativeWindowMouseInfo& info); + void MouseUncapture(const NativeWindowMouseInfo& info); + void OnCharInput(const NativeWindowCharInfo& info, GuiGraphicsComposition* composition, GuiCharEvent GuiGraphicsEventReceiver::* eventReceiverEvent); + void OnKeyInput(const NativeWindowKeyInfo& info, GuiGraphicsComposition* composition, GuiKeyEvent GuiGraphicsEventReceiver::* eventReceiverEvent); + void RaiseMouseEvent(GuiMouseEventArgs& arguments, GuiGraphicsComposition* composition, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent); + void OnMouseInput(const NativeWindowMouseInfo& info, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent); + void RecreateRenderTarget(); + + private: + INativeWindowListener::HitTestResult HitTest(NativePoint location)override; + void Moving(NativeRect& bounds, bool fixSizeOnly, bool draggingBorder)override; + void Moved()override; + void DpiChanged()override; + void Paint()override; + + void LeftButtonDown(const NativeWindowMouseInfo& info)override; + void LeftButtonUp(const NativeWindowMouseInfo& info)override; + void LeftButtonDoubleClick(const NativeWindowMouseInfo& info)override; + void RightButtonDown(const NativeWindowMouseInfo& info)override; + void RightButtonUp(const NativeWindowMouseInfo& info)override; + void RightButtonDoubleClick(const NativeWindowMouseInfo& info)override; + void MiddleButtonDown(const NativeWindowMouseInfo& info)override; + void MiddleButtonUp(const NativeWindowMouseInfo& info)override; + void MiddleButtonDoubleClick(const NativeWindowMouseInfo& info)override; + void HorizontalWheel(const NativeWindowMouseInfo& info)override; + void VerticalWheel(const NativeWindowMouseInfo& info)override; + void MouseMoving(const NativeWindowMouseInfo& info)override; + void MouseEntered()override; + void MouseLeaved()override; + + void KeyDown(const NativeWindowKeyInfo& info)override; + void KeyUp(const NativeWindowKeyInfo& info)override; + void SysKeyDown(const NativeWindowKeyInfo& info)override; + void SysKeyUp(const NativeWindowKeyInfo& info)override; + void Char(const NativeWindowCharInfo& info)override; + + void GlobalTimer()override; + public: + GuiGraphicsHost(controls::GuiControlHost* _controlHost, GuiGraphicsComposition* boundsComposition); + ~GuiGraphicsHost(); + + /// Get the associated window. + /// The associated window. + INativeWindow* GetNativeWindow(); + /// Associate a window. A will fill and appear in the window. + /// The window to associated. + void SetNativeWindow(INativeWindow* _nativeWindow); + /// Get the main . If a window is associated, everything that put into the main composition will be shown in the window. + /// The main compositoin. + GuiGraphicsComposition* GetMainComposition(); + /// Render the main composition and all content to the associated window. + /// Set to true to force updating layout and then render. + void Render(bool forceUpdate); + /// Request a rendering + void RequestRender(); + /// Invoke a specified function after rendering. + /// The specified function. + /// A key to cancel a previous binded key if not null. + void InvokeAfterRendering(const Func& proc, ProcKey key = { nullptr,-1 }); + + /// Invalidte the internal tab order control list. Next time when TAB is pressed it will be rebuilt. + void InvalidateTabOrderCache(); + /// Get the attached with this graphics host. + /// The shortcut key manager. + IGuiShortcutKeyManager* GetShortcutKeyManager(); + /// Attach or detach the associated with this graphics host. When this graphics host is disposing, the associated shortcut key manager will be deleted if exists. + /// The shortcut key manager. Set to null to detach the previous shortcut key manager from this graphics host. + void SetShortcutKeyManager(IGuiShortcutKeyManager* value); + + /// Set the focus composition. A focused composition will receive keyboard messages. + /// Returns true if this operation succeeded. + /// The composition to set focus. This composition should be or in the main composition. + bool SetFocus(GuiGraphicsComposition* composition); + /// Get the focus composition. A focused composition will receive keyboard messages. + /// The focus composition. + GuiGraphicsComposition* GetFocusedComposition(); + /// Get the caret point. A caret point is the position to place the edit box of the activated input method editor. + /// The caret point. + Point GetCaretPoint(); + /// Set the caret point. A caret point is the position to place the edit box of the activated input method editor. + /// The caret point. + /// The point space. If this argument is null, the "value" argument will use the point space of the client area in the main composition. + void SetCaretPoint(Point value, GuiGraphicsComposition* referenceComposition=0); + + /// Get the timer manager. + /// The timer manager. + GuiGraphicsTimerManager* GetTimerManager(); + /// Notify that a composition is going to disconnect from this graphics host. Generally this happens when a composition's parent line changes. + /// The composition to disconnect + void DisconnectComposition(GuiGraphicsComposition* composition); + }; + } + } +} + +#endif + /*********************************************************************** .\GRAPHICSCOMPOSITION\INCLUDEFORWARD.H ***********************************************************************/ @@ -5781,533 +6326,86 @@ Helpers #endif /*********************************************************************** -.\GRAPHICSHOST\GUIGRAPHICSHOST_ALT.H +.\RESOURCES\GUIPLUGINMANAGER.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) -GacUI::Graphics Composition Host +GacUI::Resource Interfaces: ***********************************************************************/ -#ifndef VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_ALT -#define VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_ALT +#ifndef VCZH_PRESENTATION_RESOURCES_GUIPLUGINMANAGER +#define VCZH_PRESENTATION_RESOURCES_GUIPLUGINMANAGER namespace vl { namespace presentation { - namespace compositions + +/*********************************************************************** +Plugin +***********************************************************************/ + + /// Represents a plugin for the gui. + class IGuiPlugin : public IDescriptable, public Description { + public: + /// Get the name of this plugin. + /// Returns the name of the plugin. + virtual WString GetName() = 0; + /// Get all dependencies of this plugin. + /// To receive all dependencies. + virtual void GetDependencies(collections::List& dependencies) = 0; + /// Called when the plugin manager want to load this plugin. + virtual void Load()=0; + /// Called when the plugin manager want to unload this plugin. + virtual void Unload()=0; + }; -/*********************************************************************** -Alt-Combined Shortcut Key Interfaces -***********************************************************************/ - - class IGuiAltActionHost; - - /// IGuiAltAction is the handler when an alt-combined shortcut key is activated. - class IGuiAltAction : public virtual IDescriptable - { - public: - /// The identifier for this service. - static const wchar_t* const Identifier; - - static bool IsLegalAlt(const WString& alt); - - virtual const WString& GetAlt() = 0; - virtual bool IsAltEnabled() = 0; - virtual bool IsAltAvailable() = 0; - virtual GuiGraphicsComposition* GetAltComposition() = 0; - virtual IGuiAltActionHost* GetActivatingAltHost() = 0; - virtual void OnActiveAlt() = 0; - }; - - /// IGuiAltActionContainer enumerates multiple . - class IGuiAltActionContainer : public virtual IDescriptable - { - public: - /// The identifier for this service. - static const wchar_t* const Identifier; - - virtual vint GetAltActionCount() = 0; - virtual IGuiAltAction* GetAltAction(vint index) = 0; - }; - - /// IGuiAltActionHost is an alt-combined shortcut key host. A host can also be entered or leaved, with multiple sub actions enabled or disabled. - class IGuiAltActionHost : public virtual IDescriptable - { - public: - /// The identifier for this service. - static const wchar_t* const Identifier; - - static void CollectAltActionsFromControl(controls::GuiControl* control, bool includeThisControl, collections::Group& actions); - - virtual GuiGraphicsComposition* GetAltComposition() = 0; - virtual IGuiAltActionHost* GetPreviousAltHost() = 0; - virtual void OnActivatedAltHost(IGuiAltActionHost* previousHost) = 0; - virtual void OnDeactivatedAltHost() = 0; - virtual void CollectAltActions(collections::Group& actions) = 0; - }; - - /// Default implementation for - class GuiAltActionHostBase : public virtual IGuiAltActionHost - { - private: - GuiGraphicsComposition* composition = nullptr; - controls::GuiControl* control = nullptr; - bool includeControl = true; - IGuiAltActionHost* previousHost = nullptr; - - protected: - void SetAltComposition(GuiGraphicsComposition* _composition); - void SetAltControl(controls::GuiControl* _control, bool _includeControl); - - public: - GuiGraphicsComposition* GetAltComposition()override; - IGuiAltActionHost* GetPreviousAltHost()override; - void OnActivatedAltHost(IGuiAltActionHost* _previousHost)override; - void OnDeactivatedAltHost()override; - void CollectAltActions(collections::Group& actions)override; - }; - -/*********************************************************************** -Alt-Combined Shortcut Key Interfaces Helpers -***********************************************************************/ - - class GuiAltActionManager : public Object - { - typedef collections::Dictionary AltActionMap; - typedef collections::Dictionary AltControlMap; - protected: - controls::GuiControlHost* controlHost = nullptr; - IGuiAltActionHost* currentAltHost = nullptr; - AltActionMap currentActiveAltActions; - AltControlMap currentActiveAltTitles; - WString currentAltPrefix; - VKEY supressAltKey = VKEY::KEY_UNKNOWN; - - void EnterAltHost(IGuiAltActionHost* host); - void LeaveAltHost(); - bool EnterAltKey(wchar_t key); - void LeaveAltKey(); - void CreateAltTitles(const collections::Group& actions); - vint FilterTitles(); - void ClearAltHost(); - public: - GuiAltActionManager(controls::GuiControlHost* _controlHost); - ~GuiAltActionManager(); - - void CloseAltHost(); - bool KeyDown(const NativeWindowKeyInfo& info); - bool KeyUp(const NativeWindowKeyInfo& info); - bool SysKeyDown(const NativeWindowKeyInfo& info); - bool SysKeyUp(const NativeWindowKeyInfo& info); - bool Char(const NativeWindowCharInfo& info); - }; - } - } -} - -#endif - -/*********************************************************************** -.\GRAPHICSHOST\GUIGRAPHICSHOST_SHORTCUTKEY.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Graphics Composition Host - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_SHORTCUTKEY -#define VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_SHORTCUTKEY - - -namespace vl -{ - namespace presentation - { - namespace compositions + /// Represents a plugin manager. + class IGuiPluginManager : public IDescriptable, public Description { + public: + /// Add a plugin before [F:vl.presentation.controls.IGuiPluginManager.Load] is called. + /// The plugin. + virtual void AddPlugin(Ptr plugin)=0; + /// Load all plugins, and check if dependencies of all plugins are ready. + virtual void Load()=0; + /// Unload all plugins. + virtual void Unload()=0; + /// Returns true if all plugins are loaded. + virtual bool IsLoaded()=0; + }; /*********************************************************************** -Shortcut Key Manager +Plugin Manager ***********************************************************************/ - class IGuiShortcutKeyManager; + /// Get the global object. + /// The global object. + extern IGuiPluginManager* GetPluginManager(); - /// Shortcut key item. - class IGuiShortcutKeyItem : public virtual IDescriptable, public Description - { - public: - /// Shortcut key executed event. - GuiNotifyEvent Executed; + /// Destroy the global object. + extern void DestroyPluginManager(); - /// Get the associated object. - /// The associated shortcut key manager. - virtual IGuiShortcutKeyManager* GetManager()=0; - /// Get the name represents the shortcut key combination for this item. - /// The name represents the shortcut key combination for this item. - virtual WString GetName()=0; - }; - - /// Shortcut key manager item. - class IGuiShortcutKeyManager : public virtual IDescriptable, public Description - { - public: - /// Get the number of shortcut key items that already attached to the manager. - /// T number of shortcut key items that already attached to the manager. - virtual vint GetItemCount()=0; - /// Get the associated with the index. - /// The shortcut key item. - /// The index. - virtual IGuiShortcutKeyItem* GetItem(vint index)=0; - /// Execute shortcut key items using a key event info. - /// Returns true if at least one shortcut key item is executed. - /// The key event info. - virtual bool Execute(const NativeWindowKeyInfo& info)=0; - }; +#define GUI_REGISTER_PLUGIN(TYPE)\ + class GuiRegisterPluginClass_##TYPE\ + {\ + public:\ + GuiRegisterPluginClass_##TYPE()\ + {\ + vl::presentation::GetPluginManager()->AddPlugin(Ptr(new TYPE));\ + }\ + } instance_GuiRegisterPluginClass_##TYPE;\ -/*********************************************************************** -Shortcut Key Manager Helpers -***********************************************************************/ +#define GUI_PLUGIN_NAME(NAME)\ + vl::WString GetName()override { return L ## #NAME; }\ + void GetDependencies(vl::collections::List& dependencies)override\ - class GuiShortcutKeyManager; - - class GuiShortcutKeyItem : public Object, public IGuiShortcutKeyItem - { - protected: - GuiShortcutKeyManager* shortcutKeyManager; - bool ctrl; - bool shift; - bool alt; - VKEY key; - - void AttachManager(GuiShortcutKeyManager* manager); - void DetachManager(GuiShortcutKeyManager* manager); - public: - GuiShortcutKeyItem(GuiShortcutKeyManager* _shortcutKeyManager, bool _ctrl, bool _shift, bool _alt, VKEY _key); - ~GuiShortcutKeyItem(); - - IGuiShortcutKeyManager* GetManager()override; - WString GetName()override; - bool CanActivate(const NativeWindowKeyInfo& info); - bool CanActivate(bool _ctrl, bool _shift, bool _alt, VKEY _key); - }; - - /// A default implementation for . - class GuiShortcutKeyManager : public Object, public IGuiShortcutKeyManager, public Description - { - typedef collections::List> ShortcutKeyItemList; - protected: - ShortcutKeyItemList shortcutKeyItems; - - public: - /// Create the shortcut key manager. - GuiShortcutKeyManager(); - ~GuiShortcutKeyManager(); - - vint GetItemCount()override; - IGuiShortcutKeyItem* GetItem(vint index)override; - bool Execute(const NativeWindowKeyInfo& info)override; - - /// Create a shortcut key item using a key combination. If the item for the key combination exists, this function returns the item that is created before. - /// The created shortcut key item. - /// Set to true if the CTRL key is required. - /// Set to true if the SHIFT key is required. - /// Set to true if the ALT key is required. - /// The non-control key. - IGuiShortcutKeyItem* CreateShortcut(bool ctrl, bool shift, bool alt, VKEY key); - /// Destroy a shortcut key item using a key combination - /// Returns true if the manager destroyed a existing shortcut key item. - /// Set to true if the CTRL key is required. - /// Set to true if the SHIFT key is required. - /// Set to true if the ALT key is required. - /// The non-control key. - bool DestroyShortcut(bool ctrl, bool shift, bool alt, VKEY key); - /// Get a shortcut key item using a key combination. If the item for the key combination does not exist, this function returns null. - /// The shortcut key item. - /// Set to true if the CTRL key is required. - /// Set to true if the SHIFT key is required. - /// Set to true if the ALT key is required. - /// The non-control key. - IGuiShortcutKeyItem* TryGetShortcut(bool ctrl, bool shift, bool alt, VKEY key); - }; - } - } -} - -#endif - -/*********************************************************************** -.\GRAPHICSHOST\GUIGRAPHICSHOST_TAB.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Graphics Composition Host - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_TAB -#define VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST_TAB - - -namespace vl -{ - namespace presentation - { - namespace compositions - { - -/*********************************************************************** -Tab-Combined Shortcut Key Interfaces -***********************************************************************/ - - /// IGuiTabAction is the handler when an tab-combined shortcut key is activated. - class IGuiTabAction : public virtual IDescriptable - { - public: - /// The identifier for this service. - static const wchar_t* const Identifier; - - virtual bool GetAcceptTabInput() = 0; - virtual vint GetTabPriority() = 0; - virtual bool IsTabEnabled() = 0; - virtual bool IsTabAvailable() = 0; - }; - -/*********************************************************************** -Tab-Combined Shortcut Key Interfaces Helpers -***********************************************************************/ - - class GuiTabActionManager : public Object - { - using ControlList = collections::List; - protected: - controls::GuiControlHost* controlHost = nullptr; - ControlList controlsInOrder; - bool available = true; - bool supressTabOnce = false; - - void BuildControlList(); - controls::GuiControl* GetNextFocusControl(controls::GuiControl* focusedControl, vint offset); - public: - GuiTabActionManager(controls::GuiControlHost* _controlHost); - ~GuiTabActionManager(); - - void InvalidateTabOrderCache(); - bool KeyDown(const NativeWindowKeyInfo& info, GuiGraphicsComposition* focusedComposition); - bool Char(const NativeWindowCharInfo& info); - }; - } - } -} - -#endif - -/*********************************************************************** -.\GRAPHICSHOST\GUIGRAPHICSHOST.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Graphics Composition Host - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST -#define VCZH_PRESENTATION_HOST_GUIGRAPHICSHOST - - -namespace vl -{ - namespace presentation - { - namespace controls - { - class GuiWindow; - } - - namespace compositions - { - -/*********************************************************************** -Animation -***********************************************************************/ - - /// - /// Represents a timer callback object. - /// - class IGuiGraphicsTimerCallback : public virtual IDescriptable, public Description - { - public: - /// Called periodically. - /// Returns false to indicate that this callback need to be removed. - virtual bool Play() = 0; - }; - - /// - /// Timer callback manager. - /// - class GuiGraphicsTimerManager : public Object, public Description - { - typedef collections::List> CallbackList; - protected: - CallbackList callbacks; - - public: - GuiGraphicsTimerManager(); - ~GuiGraphicsTimerManager(); - - /// Add a new callback. - /// The new callback to add. - void AddCallback(Ptr callback); - /// Called periodically. - void Play(); - }; - -/*********************************************************************** -Host -***********************************************************************/ - - /// - /// GuiGraphicsHost hosts an in an . The composition will fill the whole window. - /// - class GuiGraphicsHost : public Object, private INativeWindowListener, private INativeControllerListener, public Description - { - typedef collections::List CompositionList; - typedef GuiGraphicsComposition::GraphicsHostRecord HostRecord; - typedef collections::Pair ProcKey; - typedef collections::List> ProcList; - typedef collections::Dictionary> ProcMap; - public: - static const vuint64_t CaretInterval = 500; - - protected: - HostRecord hostRecord; - bool supressPaint = false; - bool needRender = true; - ProcList afterRenderProcs; - ProcMap afterRenderKeyedProcs; - - GuiAltActionManager* altActionManager = nullptr; - GuiTabActionManager* tabActionManager = nullptr; - IGuiShortcutKeyManager* shortcutKeyManager = nullptr; - - controls::GuiControlHost* controlHost = nullptr; - GuiWindowComposition* windowComposition = nullptr; - GuiGraphicsComposition* focusedComposition = nullptr; - NativeSize previousClientSize; - Size minSize; - Point caretPoint; - vuint64_t lastCaretTime = 0; - - GuiGraphicsTimerManager timerManager; - GuiGraphicsComposition* mouseCaptureComposition = nullptr; - CompositionList mouseEnterCompositions; - void RefreshRelatedHostRecord(INativeWindow* nativeWindow); - - void DisconnectCompositionInternal(GuiGraphicsComposition* composition); - void MouseCapture(const NativeWindowMouseInfo& info); - void MouseUncapture(const NativeWindowMouseInfo& info); - void OnCharInput(const NativeWindowCharInfo& info, GuiGraphicsComposition* composition, GuiCharEvent GuiGraphicsEventReceiver::* eventReceiverEvent); - void OnKeyInput(const NativeWindowKeyInfo& info, GuiGraphicsComposition* composition, GuiKeyEvent GuiGraphicsEventReceiver::* eventReceiverEvent); - void RaiseMouseEvent(GuiMouseEventArgs& arguments, GuiGraphicsComposition* composition, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent); - void OnMouseInput(const NativeWindowMouseInfo& info, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent); - void RecreateRenderTarget(); - - private: - INativeWindowListener::HitTestResult HitTest(NativePoint location)override; - void Moving(NativeRect& bounds, bool fixSizeOnly, bool draggingBorder)override; - void Moved()override; - void DpiChanged()override; - void Paint()override; - - void LeftButtonDown(const NativeWindowMouseInfo& info)override; - void LeftButtonUp(const NativeWindowMouseInfo& info)override; - void LeftButtonDoubleClick(const NativeWindowMouseInfo& info)override; - void RightButtonDown(const NativeWindowMouseInfo& info)override; - void RightButtonUp(const NativeWindowMouseInfo& info)override; - void RightButtonDoubleClick(const NativeWindowMouseInfo& info)override; - void MiddleButtonDown(const NativeWindowMouseInfo& info)override; - void MiddleButtonUp(const NativeWindowMouseInfo& info)override; - void MiddleButtonDoubleClick(const NativeWindowMouseInfo& info)override; - void HorizontalWheel(const NativeWindowMouseInfo& info)override; - void VerticalWheel(const NativeWindowMouseInfo& info)override; - void MouseMoving(const NativeWindowMouseInfo& info)override; - void MouseEntered()override; - void MouseLeaved()override; - - void KeyDown(const NativeWindowKeyInfo& info)override; - void KeyUp(const NativeWindowKeyInfo& info)override; - void SysKeyDown(const NativeWindowKeyInfo& info)override; - void SysKeyUp(const NativeWindowKeyInfo& info)override; - void Char(const NativeWindowCharInfo& info)override; - - void GlobalTimer()override; - public: - GuiGraphicsHost(controls::GuiControlHost* _controlHost, GuiGraphicsComposition* boundsComposition); - ~GuiGraphicsHost(); - - /// Get the associated window. - /// The associated window. - INativeWindow* GetNativeWindow(); - /// Associate a window. A will fill and appear in the window. - /// The window to associated. - void SetNativeWindow(INativeWindow* _nativeWindow); - /// Get the main . If a window is associated, everything that put into the main composition will be shown in the window. - /// The main compositoin. - GuiGraphicsComposition* GetMainComposition(); - /// Render the main composition and all content to the associated window. - /// Set to true to force updating layout and then render. - void Render(bool forceUpdate); - /// Request a rendering - void RequestRender(); - /// Invoke a specified function after rendering. - /// The specified function. - /// A key to cancel a previous binded key if not null. - void InvokeAfterRendering(const Func& proc, ProcKey key = { nullptr,-1 }); - - /// Invalidte the internal tab order control list. Next time when TAB is pressed it will be rebuilt. - void InvalidateTabOrderCache(); - /// Get the attached with this graphics host. - /// The shortcut key manager. - IGuiShortcutKeyManager* GetShortcutKeyManager(); - /// Attach or detach the associated with this graphics host. When this graphics host is disposing, the associated shortcut key manager will be deleted if exists. - /// The shortcut key manager. Set to null to detach the previous shortcut key manager from this graphics host. - void SetShortcutKeyManager(IGuiShortcutKeyManager* value); - - /// Set the focus composition. A focused composition will receive keyboard messages. - /// Returns true if this operation succeeded. - /// The composition to set focus. This composition should be or in the main composition. - bool SetFocus(GuiGraphicsComposition* composition); - /// Get the focus composition. A focused composition will receive keyboard messages. - /// The focus composition. - GuiGraphicsComposition* GetFocusedComposition(); - /// Get the caret point. A caret point is the position to place the edit box of the activated input method editor. - /// The caret point. - Point GetCaretPoint(); - /// Set the caret point. A caret point is the position to place the edit box of the activated input method editor. - /// The caret point. - /// The point space. If this argument is null, the "value" argument will use the point space of the client area in the main composition. - void SetCaretPoint(Point value, GuiGraphicsComposition* referenceComposition=0); - - /// Get the timer manager. - /// The timer manager. - GuiGraphicsTimerManager* GetTimerManager(); - /// Notify that a composition is going to disconnect from this graphics host. Generally this happens when a composition's parent line changes. - /// The composition to disconnect - void DisconnectComposition(GuiGraphicsComposition* composition); - }; - } +#define GUI_PLUGIN_DEPEND(NAME) dependencies.Add(L ## #NAME) } } @@ -7106,7 +7204,7 @@ Resource Resolver Manager #endif /*********************************************************************** -.\CONTROLS\TEMPLATES\GUICONTROLSHARED.H +.\APPLICATION\CONTROLS\GUIINSTANCEROOTOBJECT.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 @@ -7116,130 +7214,27 @@ GacUI::Template System Interfaces: ***********************************************************************/ -#ifndef VCZH_PRESENTATION_CONTROLS_TEMPLATES_GUICONTROLSHARED -#define VCZH_PRESENTATION_CONTROLS_TEMPLATES_GUICONTROLSHARED +#ifndef VCZH_PRESENTATION_CONTROLS_TEMPLATES_GUIINSTANCEROOTOBJECT +#define VCZH_PRESENTATION_CONTROLS_TEMPLATES_GUIINSTANCEROOTOBJECT namespace vl { namespace presentation { + namespace templates + { + class GuiTemplate; + } + namespace controls { class GuiControlHost; class GuiCustomControl; - /// The visual state for button. - enum class ButtonState - { - /// Normal state. - Normal, - /// Active state (when the cursor is hovering on a button). - Active, - /// Pressed state (when the buttin is being pressed). - Pressed, - }; - - /// Represents the sorting state of list view items related to this column. - enum class ColumnSortingState - { - /// Not sorted. - NotSorted, - /// Ascending. - Ascending, - /// Descending. - Descending, - }; - - /// Represents the order of tab pages. - enum class TabPageOrder - { - /// Unknown. - Unknown, - /// Left to right. - LeftToRight, - /// Right to left. - RightToLeft, - /// Top to bottom. - TopToBottom, - /// Bottom to top. - BottomToTop, - }; - - /// A command executor for the combo box to change the control state. - class ITextBoxCommandExecutor : public virtual IDescriptable, public Description - { - public: - /// Override the text content in the control. - /// The new text content. - virtual void UnsafeSetText(const WString& value) = 0; - }; - - /// A command executor for the style controller to change the control state. - class IScrollCommandExecutor : public virtual IDescriptable, public Description - { - public: - /// Do small decrement. - virtual void SmallDecrease() = 0; - /// Do small increment. - virtual void SmallIncrease() = 0; - /// Do big decrement. - virtual void BigDecrease() = 0; - /// Do big increment. - virtual void BigIncrease() = 0; - - /// Change to total size of the scroll. - /// The total size. - virtual void SetTotalSize(vint value) = 0; - /// Change to page size of the scroll. - /// The page size. - virtual void SetPageSize(vint value) = 0; - /// Change to position of the scroll. - /// The position. - virtual void SetPosition(vint value) = 0; - }; - - /// A command executor for the style controller to change the control state. - class ITabCommandExecutor : public virtual IDescriptable, public Description - { - public: - /// Select a tab page. - /// The specified position for the tab page. - /// Set to true to set focus to the tab control. - virtual void ShowTab(vint index, bool setFocus) = 0; - }; - - /// A command executor for the style controller to change the control state. - class IDatePickerCommandExecutor : public virtual IDescriptable, public Description - { - public: - /// Called when the date has been changed. - virtual void NotifyDateChanged() = 0; - /// Called when navigated to a date. - virtual void NotifyDateNavigated() = 0; - /// Called when selected a date. - virtual void NotifyDateSelected() = 0; - }; - - /// A command executor for the style controller to change the control state. - class IRibbonGroupCommandExecutor : public virtual IDescriptable, public Description - { - public: - /// Called when the expand button is clicked. - virtual void NotifyExpandButtonClicked() = 0; - }; - - /// A command executor for the style controller to change the control state. - class IRibbonGalleryCommandExecutor : public virtual IDescriptable, public Description - { - public: - /// Called when the scroll up button is clicked. - virtual void NotifyScrollUp() = 0; - /// Called when the scroll down button is clicked. - virtual void NotifyScrollDown() = 0; - /// Called when the dropdown button is clicked. - virtual void NotifyDropdown() = 0; - }; +/*********************************************************************** +Component +***********************************************************************/ class GuiInstanceRootObject; @@ -7376,6 +7371,1725 @@ Root Object #endif +/*********************************************************************** +.\APPLICATION\CONTROLS\GUITHEMEMANAGER.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control Styles::Common Style Helpers + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUITHEMEMANAGER +#define VCZH_PRESENTATION_CONTROLS_GUITHEMEMANAGER + + +namespace vl +{ + namespace presentation + { + namespace templates + { + +/*********************************************************************** +Theme Builders +***********************************************************************/ + +#define GUI_TEMPLATE_PROPERTY_DECL(CLASS, TYPE, NAME, VALUE)\ + private:\ + TYPE NAME##_ = VALUE;\ + public:\ + TYPE Get##NAME();\ + void Set##NAME(TYPE const& value);\ + compositions::GuiNotifyEvent NAME##Changed;\ + +#define GUI_TEMPLATE_PROPERTY_IMPL(CLASS, TYPE, NAME, VALUE)\ + TYPE CLASS::Get##NAME()\ + {\ + return NAME##_;\ + }\ + void CLASS::Set##NAME(TYPE const& value)\ + {\ + if (NAME##_ != value)\ + {\ + NAME##_ = value;\ + NAME##Changed.Execute(compositions::GuiEventArgs(this));\ + }\ + }\ + +#define GUI_TEMPLATE_PROPERTY_EVENT_INIT(CLASS, TYPE, NAME, VALUE)\ + NAME##Changed.SetAssociatedComposition(this); + +#define GUI_TEMPLATE_CLASS_DECL(CLASS, BASE)\ + class CLASS : public BASE, public AggregatableDescription\ + {\ + public:\ + CLASS();\ + ~CLASS();\ + CLASS ## _PROPERTIES(GUI_TEMPLATE_PROPERTY_DECL)\ + };\ + +#define GUI_TEMPLATE_CLASS_IMPL(CLASS, BASE)\ + CLASS ## _PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL)\ + CLASS::CLASS()\ + {\ + CLASS ## _PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT)\ + }\ + CLASS::~CLASS()\ + {\ + FinalizeAggregation();\ + }\ + +/*********************************************************************** +GuiTemplate +***********************************************************************/ + + /// Represents a user customizable template. + class GuiTemplate : public compositions::GuiBoundsComposition, public controls::GuiInstanceRootObject, public Description + { + protected: + controls::GuiControlHost* GetControlHostForInstance()override; + void OnParentLineChanged()override; + public: + /// Create a template. + GuiTemplate(); + ~GuiTemplate(); + +#define GuiTemplate_PROPERTIES(F)\ + F(GuiTemplate, FontProperties, Font, {} )\ + F(GuiTemplate, description::Value, Context, {} )\ + F(GuiTemplate, WString, Text, {} )\ + F(GuiTemplate, bool, VisuallyEnabled, true)\ + + GuiTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_DECL) + }; + +/*********************************************************************** +Core Themes +***********************************************************************/ + +#define GUI_CORE_CONTROL_TEMPLATE_DECL(F)\ + F(GuiControlTemplate, GuiTemplate) \ + F(GuiLabelTemplate, GuiControlTemplate) \ + F(GuiWindowTemplate, GuiControlTemplate) \ + + enum class BoolOption + { + AlwaysTrue, + AlwaysFalse, + Customizable, + }; + +#define GuiControlTemplate_PROPERTIES(F)\ + F(GuiControlTemplate, compositions::GuiGraphicsComposition*, ContainerComposition, this)\ + F(GuiControlTemplate, compositions::GuiGraphicsComposition*, FocusableComposition, nullptr)\ + F(GuiControlTemplate, bool, Focused, false)\ + +#define GuiLabelTemplate_PROPERTIES(F)\ + F(GuiLabelTemplate, Color, DefaultTextColor, {})\ + F(GuiLabelTemplate, Color, TextColor, {})\ + +#define GuiWindowTemplate_PROPERTIES(F)\ + F(GuiWindowTemplate, BoolOption, MaximizedBoxOption, BoolOption::Customizable)\ + F(GuiWindowTemplate, BoolOption, MinimizedBoxOption, BoolOption::Customizable)\ + F(GuiWindowTemplate, BoolOption, BorderOption, BoolOption::Customizable)\ + F(GuiWindowTemplate, BoolOption, SizeBoxOption, BoolOption::Customizable)\ + F(GuiWindowTemplate, BoolOption, IconVisibleOption, BoolOption::Customizable)\ + F(GuiWindowTemplate, BoolOption, TitleBarOption, BoolOption::Customizable)\ + F(GuiWindowTemplate, bool, MaximizedBox, true)\ + F(GuiWindowTemplate, bool, MinimizedBox, true)\ + F(GuiWindowTemplate, bool, Border, true)\ + F(GuiWindowTemplate, bool, SizeBox, true)\ + F(GuiWindowTemplate, bool, IconVisible, true)\ + F(GuiWindowTemplate, bool, TitleBar, true)\ + F(GuiWindowTemplate, bool, Maximized, false)\ + F(GuiWindowTemplate, bool, Activated, false)\ + F(GuiWindowTemplate, TemplateProperty, TooltipTemplate, {})\ + F(GuiWindowTemplate, TemplateProperty, ShortcutKeyTemplate, {})\ + F(GuiWindowTemplate, bool, CustomFrameEnabled, true)\ + F(GuiWindowTemplate, Margin, CustomFramePadding, {})\ + F(GuiWindowTemplate, Ptr, Icon, {})\ + +/*********************************************************************** +Template Declarations +***********************************************************************/ + + GUI_CORE_CONTROL_TEMPLATE_DECL(GUI_TEMPLATE_CLASS_DECL) + } + +/*********************************************************************** +Theme Names +***********************************************************************/ + + namespace theme + { + +#define GUI_CONTROL_TEMPLATE_TYPES(F) \ + F(WindowTemplate, Window) \ + F(ControlTemplate, CustomControl) \ + F(WindowTemplate, Tooltip) \ + F(LabelTemplate, Label) \ + F(LabelTemplate, ShortcutKey) \ + F(ScrollViewTemplate, ScrollView) \ + F(ControlTemplate, GroupBox) \ + F(TabTemplate, Tab) \ + F(ComboBoxTemplate, ComboBox) \ + F(MultilineTextBoxTemplate, MultilineTextBox) \ + F(SinglelineTextBoxTemplate, SinglelineTextBox) \ + F(DocumentViewerTemplate, DocumentViewer) \ + F(DocumentLabelTemplate, DocumentLabel) \ + F(DocumentLabelTemplate, DocumentTextBox) \ + F(ListViewTemplate, ListView) \ + F(TreeViewTemplate, TreeView) \ + F(TextListTemplate, TextList) \ + F(SelectableButtonTemplate, ListItemBackground) \ + F(SelectableButtonTemplate, TreeItemExpander) \ + F(SelectableButtonTemplate, CheckTextListItem) \ + F(SelectableButtonTemplate, RadioTextListItem) \ + F(MenuTemplate, Menu) \ + F(ControlTemplate, MenuBar) \ + F(ControlTemplate, MenuSplitter) \ + F(ToolstripButtonTemplate, MenuBarButton) \ + F(ToolstripButtonTemplate, MenuItemButton) \ + F(ControlTemplate, ToolstripToolBar) \ + F(ToolstripButtonTemplate, ToolstripButton) \ + F(ToolstripButtonTemplate, ToolstripDropdownButton) \ + F(ToolstripButtonTemplate, ToolstripSplitButton) \ + F(ControlTemplate, ToolstripSplitter) \ + F(RibbonTabTemplate, RibbonTab) \ + F(RibbonGroupTemplate, RibbonGroup) \ + F(RibbonIconLabelTemplate, RibbonIconLabel) \ + F(RibbonIconLabelTemplate, RibbonSmallIconLabel) \ + F(RibbonButtonsTemplate, RibbonButtons) \ + F(RibbonToolstripsTemplate, RibbonToolstrips) \ + F(RibbonGalleryTemplate, RibbonGallery) \ + F(RibbonToolstripMenuTemplate, RibbonToolstripMenu) \ + F(RibbonGalleryListTemplate, RibbonGalleryList) \ + F(TextListTemplate, RibbonGalleryItemList) \ + F(ToolstripButtonTemplate, RibbonSmallButton) \ + F(ToolstripButtonTemplate, RibbonSmallDropdownButton) \ + F(ToolstripButtonTemplate, RibbonSmallSplitButton) \ + F(ToolstripButtonTemplate, RibbonLargeButton) \ + F(ToolstripButtonTemplate, RibbonLargeDropdownButton) \ + F(ToolstripButtonTemplate, RibbonLargeSplitButton) \ + F(ControlTemplate, RibbonSplitter) \ + F(ControlTemplate, RibbonToolstripHeader) \ + F(ButtonTemplate, Button) \ + F(SelectableButtonTemplate, CheckBox) \ + F(SelectableButtonTemplate, RadioButton) \ + F(DatePickerTemplate, DatePicker) \ + F(DateComboBoxTemplate, DateComboBox) \ + F(ScrollTemplate, HScroll) \ + F(ScrollTemplate, VScroll) \ + F(ScrollTemplate, HTracker) \ + F(ScrollTemplate, VTracker) \ + F(ScrollTemplate, ProgressBar) \ + + enum class ThemeName + { + Unknown, +#define GUI_DEFINE_THEME_NAME(TEMPLATE, CONTROL) CONTROL, + GUI_CONTROL_TEMPLATE_TYPES(GUI_DEFINE_THEME_NAME) +#undef GUI_DEFINE_THEME_NAME + }; + + /// Theme interface. A theme creates appropriate style controllers or style providers for default controls. Call [M:vl.presentation.theme.GetCurrentTheme] to access this interface. + class ITheme : public virtual IDescriptable, public Description + { + public: + virtual TemplateProperty CreateStyle(ThemeName themeName) = 0; + }; + + /// Get the current theme style factory object. Call or to change the default theme. + /// The current theme style factory object. + extern ITheme* GetCurrentTheme(); + extern void InitializeTheme(); + extern void FinalizeTheme(); + } + } +} + +#endif + +/*********************************************************************** +.\APPLICATION\CONTROLS\GUIBASICCONTROLS.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUIBASICCONTROLS +#define VCZH_PRESENTATION_CONTROLS_GUIBASICCONTROLS + + +namespace vl +{ + namespace presentation + { + namespace theme + { + enum class ThemeName; + } + + namespace controls + { + template + struct QueryServiceHelper; + + template + struct QueryServiceHelper>> + { + static WString GetIdentifier() + { + return WString::Unmanaged(T::Identifier); + } + }; + + template + struct QueryServiceHelper>> + { + static WString GetIdentifier() + { + return MoveValue(T::GetIdentifier()); + } + }; + +/*********************************************************************** +Basic Construction +***********************************************************************/ + + /// + /// A helper object to test if a control has been deleted or not. + /// + class GuiDisposedFlag : public Object, public Description + { + friend class GuiControl; + protected: + GuiControl* owner = nullptr; + bool disposed = false; + + void SetDisposed(); + public: + GuiDisposedFlag(GuiControl* _owner); + ~GuiDisposedFlag(); + + bool IsDisposed(); + }; + + /// + /// The base class of all controls. + /// When the control is destroyed, it automatically destroys sub controls, and the bounds composition from the style controller. + /// If you want to manually destroy a control, you should first remove it from its parent. + /// The only way to remove a control from a parent control, is to remove the bounds composition from its parent composition. The same to inserting a control. + /// + class GuiControl + : public Object + , protected compositions::IGuiAltAction + , protected compositions::IGuiTabAction + , public Description + { + friend class compositions::GuiGraphicsComposition; + + protected: + using ControlList = collections::List; + using ControlServiceMap = collections::Dictionary>; + using ControlTemplatePropertyType = TemplateProperty; + using IGuiGraphicsEventHandler = compositions::IGuiGraphicsEventHandler; + + private: + theme::ThemeName controlThemeName; + ControlTemplatePropertyType controlTemplate; + templates::GuiControlTemplate* controlTemplateObject = nullptr; + Ptr disposedFlag; + + public: + Ptr GetDisposedFlag(); + + protected: + compositions::GuiBoundsComposition* boundsComposition = nullptr; + compositions::GuiBoundsComposition* containerComposition = nullptr; + compositions::GuiGraphicsComposition* focusableComposition = nullptr; + compositions::GuiGraphicsEventReceiver* eventReceiver = nullptr; + + bool isFocused = false; + Ptr gotFocusHandler; + Ptr lostFocusHandler; + + bool acceptTabInput = false; + vint tabPriority = -1; + bool isEnabled = true; + bool isVisuallyEnabled = true; + bool isVisible = true; + WString alt; + WString text; + Nullable font; + FontProperties displayFont; + description::Value context; + compositions::IGuiAltActionHost* activatingAltHost = nullptr; + ControlServiceMap controlServices; + + GuiControl* parent = nullptr; + ControlList children; + description::Value tag; + GuiControl* tooltipControl = nullptr; + vint tooltipWidth = 0; + + virtual void BeforeControlTemplateUninstalled(); + virtual void AfterControlTemplateInstalled(bool initialize); + virtual void CheckAndStoreControlTemplate(templates::GuiControlTemplate* value); + virtual void EnsureControlTemplateExists(); + virtual void RebuildControlTemplate(); + virtual void OnChildInserted(GuiControl* control); + 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(); + virtual void UpdateDisplayFont(); + void OnGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void SetFocusableComposition(compositions::GuiGraphicsComposition* value); + + bool IsControlVisibleAndEnabled(); + bool IsAltEnabled()override; + bool IsAltAvailable()override; + compositions::GuiGraphicsComposition* GetAltComposition()override; + compositions::IGuiAltActionHost* GetActivatingAltHost()override; + void OnActiveAlt()override; + bool IsTabEnabled()override; + bool IsTabAvailable()override; + + static bool SharedPtrDestructorProc(DescriptableObject* obj, bool forceDisposing); + + public: + using ControlTemplateType = templates::GuiControlTemplate; + + /// Create a control with a specified default theme. + /// The theme name for retriving a default control template. + GuiControl(theme::ThemeName themeName); + ~GuiControl(); + + /// Theme name changed event. This event raises when the theme name is changed. + compositions::GuiNotifyEvent ControlThemeNameChanged; + /// Control template changed event. This event raises when the control template is changed. + compositions::GuiNotifyEvent ControlTemplateChanged; + /// Control signal trigerred. This raises be raised because of multiple reason specified in the argument. + compositions::GuiControlSignalEvent ControlSignalTrigerred; + /// Visible event. This event raises when the visibility state of the control is changed. + compositions::GuiNotifyEvent VisibleChanged; + /// Enabled event. This event raises when the enabling state of the control is changed. + compositions::GuiNotifyEvent EnabledChanged; + /// Focused event. This event raises when the focusing state of the control is changed. + compositions::GuiNotifyEvent FocusedChanged; + /// + /// Enabled event. This event raises when the visually enabling state of the control is changed. A visually enabling is combined by the enabling state and the parent's visually enabling state. + /// A control is rendered as disabled, not only when the control itself is disabled, but also when the parent control is rendered as disabled. + /// + compositions::GuiNotifyEvent VisuallyEnabledChanged; + /// Alt changed event. This event raises when the associated Alt-combined shortcut key of the control is changed. + compositions::GuiNotifyEvent AltChanged; + /// Text changed event. This event raises when the text of the control is changed. + compositions::GuiNotifyEvent TextChanged; + /// Font changed event. This event raises when the font of the control is changed. + compositions::GuiNotifyEvent FontChanged; + /// Display font changed event. This event raises when the display font of the control is changed. + compositions::GuiNotifyEvent DisplayFontChanged; + /// Context changed event. This event raises when the font of the control is changed. + compositions::GuiNotifyEvent ContextChanged; + + void TryDelayExecuteIfNotDeleted(Func proc); + + /// A function to create the argument for notify events that raised by itself. + /// The created argument. + compositions::GuiEventArgs GetNotifyEventArguments(); + /// Get the associated theme name. + /// The theme name. + theme::ThemeName GetControlThemeName(); + /// Set the associated control theme name. + /// The theme name. + void SetControlThemeName(theme::ThemeName value); + /// Get the associated control template. + /// The control template. + ControlTemplatePropertyType GetControlTemplate(); + /// Set the associated control template. + /// The control template. + void SetControlTemplate(const ControlTemplatePropertyType& value); + /// Set the associated control theme name and template and the same time. + /// The theme name. + /// The control template. + void SetControlThemeNameAndTemplate(theme::ThemeName themeNameValue, const ControlTemplatePropertyType& controlTemplateValue); + /// Get the associated style controller. + /// The associated style controller. + templates::GuiControlTemplate* GetControlTemplateObject(); + /// Get the bounds composition for the control. + /// The bounds composition. + compositions::GuiBoundsComposition* GetBoundsComposition(); + /// Get the container composition for the control. + /// The container composition. + compositions::GuiGraphicsComposition* GetContainerComposition(); + /// Get the focusable composition for the control. A focusable composition is the composition to be focused when the control is focused. + /// The focusable composition. + compositions::GuiGraphicsComposition* GetFocusableComposition(); + /// Get the parent control. + /// The parent control. + GuiControl* GetParent(); + /// Get the number of child controls. + /// The number of child controls. + vint GetChildrenCount(); + /// Get the child control using a specified index. + /// The child control. + /// The specified index. + GuiControl* GetChild(vint index); + /// Put another control in the container composition of this control. + /// Returns true if this operation succeeded. + /// The control to put in this control. + bool AddChild(GuiControl* control); + /// Test if a control owned by this control. + /// Returns true if the control is owned by this control. + /// The control to test. + bool HasChild(GuiControl* control); + + /// Get the that contains this control. + /// The that contains this control. + virtual GuiControlHost* GetRelatedControlHost(); + /// Test if this control is rendered as enabled. + /// Returns true if this control is rendered as enabled. + virtual bool GetVisuallyEnabled(); + /// Test if this control is focused. + /// Returns true if this control is focused. + virtual bool GetFocused(); + /// Test if this control accepts tab character input. + /// Returns true if this control accepts tab character input. + virtual bool GetAcceptTabInput()override; + /// Set if this control accepts tab character input. + /// Set to true to make this control accept tab character input. + void SetAcceptTabInput(bool value); + /// Get the tab priority associated with this control. + /// Returns he tab priority associated with this control. + virtual vint GetTabPriority()override; + /// Associate a tab priority with this control. + /// The tab priority to associate. TAB key will go through controls in the order of priority: 0, 1, 2, ..., -1. All negative numbers will be converted to -1. The priority of containers affects all children if it is not -1. + void SetTabPriority(vint value); + /// Test if this control is enabled. + /// Returns true if this control is enabled. + virtual bool GetEnabled(); + /// Make the control enabled or disabled. + /// Set to true to make the control enabled. + virtual void SetEnabled(bool value); + /// Test if this visible or invisible. + /// Returns true if this control is visible. + virtual bool GetVisible(); + /// Make the control visible or invisible. + /// Set to true to make the visible enabled. + virtual void SetVisible(bool value); + /// Get the Alt-combined shortcut key associated with this control. + /// The Alt-combined shortcut key associated with this control. + virtual const WString& GetAlt()override; + /// Associate a Alt-combined shortcut key with this control. + /// Returns true if this operation succeeded. + /// The Alt-combined shortcut key to associate. The key should contain only upper-case letters or digits. + virtual bool SetAlt(const WString& value); + /// Make the control as the parent of multiple Alt-combined shortcut key activatable controls. + /// The alt action host object. + void SetActivatingAltHost(compositions::IGuiAltActionHost* host); + /// Get the text to display on the control. + /// The text to display on the control. + virtual const WString& GetText(); + /// Set the text to display on the control. + /// The text to display on the control. + virtual void SetText(const WString& value); + /// Get the font of this control. + /// The font of this control. + virtual const Nullable& GetFont(); + /// Set the font of this control. + /// The font of this control. + virtual void SetFont(const Nullable& value); + /// Get the font to render the text. If the font of this control is null, then the display font is either the parent control's display font, or the system's default font when there is no parent control. + /// The font to render the text. + virtual const FontProperties& GetDisplayFont(); + /// Get the context of this control. The control template and all item templates (if it has) will see this context property. + /// The context of this context. + virtual description::Value GetContext(); + /// Set the context of this control. + /// The context of this control. + virtual void SetContext(const description::Value& value); + /// Focus this control. + virtual void SetFocus(); + + /// Get the tag object of the control. + /// The tag object of the control. + description::Value GetTag(); + /// Set the tag object of the control. + /// The tag object of the control. + void SetTag(const description::Value& value); + /// Get the tooltip control of the control. + /// The tooltip control of the control. + GuiControl* GetTooltipControl(); + /// Set the tooltip control of the control. The tooltip control will be released when this control is released. If you set a new tooltip control to replace the old one, the old one will not be owned by this control anymore, therefore user should release the old tooltip control manually. + /// The old tooltip control. + /// The tooltip control of the control. + GuiControl* SetTooltipControl(GuiControl* value); + /// Get the tooltip width of the control. + /// The tooltip width of the control. + vint GetTooltipWidth(); + /// Set the tooltip width of the control. + /// The tooltip width of the control. + void SetTooltipWidth(vint value); + /// Display the tooltip. + /// Returns true if this operation succeeded. + /// The relative location to specify the left-top position of the tooltip. + bool DisplayTooltip(Point location); + /// Close the tooltip that owned by this control. + void CloseTooltip(); + + /// Query a service using an identifier. If you want to get a service of type IXXX, use IXXX::Identifier as the identifier. + /// The requested service. If the control doesn't support this service, it will be null. + /// The identifier. + virtual IDescriptable* QueryService(const WString& identifier); + + template + T* QueryTypedService() + { + return dynamic_cast(QueryService(QueryServiceHelper::GetIdentifier())); + } + + templates::GuiControlTemplate* TypedControlTemplateObject(bool ensureExists) + { + if (ensureExists) + { + EnsureControlTemplateExists(); + } + return controlTemplateObject; + } + + /// 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); + }; + + /// Represnets a user customizable control. + class GuiCustomControl : public GuiControl, public GuiInstanceRootObject, public AggregatableDescription + { + protected: + controls::GuiControlHost* GetControlHostForInstance()override; + void OnParentLineChanged()override; + public: + /// Create a control with a specified default theme. + /// The theme name for retriving a default control template. + GuiCustomControl(theme::ThemeName themeName); + ~GuiCustomControl(); + }; + + template + class GuiObjectComponent : public GuiComponent + { + public: + Ptr object; + + GuiObjectComponent() + { + } + + GuiObjectComponent(Ptr _object) + :object(_object) + { + } + }; + +#define GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME_3(UNIQUE) controlTemplateObject ## UNIQUE +#define GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME_2(UNIQUE) GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME_3(UNIQUE) +#define GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME_2(__LINE__) + +#define GUI_SPECIFY_CONTROL_TEMPLATE_TYPE_2(TEMPLATE, BASE_TYPE, NAME) \ + public: \ + using ControlTemplateType = templates::Gui##TEMPLATE; \ + private: \ + templates::Gui##TEMPLATE* NAME = nullptr; \ + void BeforeControlTemplateUninstalled_(); \ + void AfterControlTemplateInstalled_(bool initialize); \ + protected: \ + void BeforeControlTemplateUninstalled()override \ + {\ + BeforeControlTemplateUninstalled_(); \ + BASE_TYPE::BeforeControlTemplateUninstalled(); \ + }\ + void AfterControlTemplateInstalled(bool initialize)override \ + {\ + BASE_TYPE::AfterControlTemplateInstalled(initialize); \ + AfterControlTemplateInstalled_(initialize); \ + }\ + void CheckAndStoreControlTemplate(templates::GuiControlTemplate* value)override \ + { \ + auto ct = dynamic_cast(value); \ + CHECK_ERROR(ct, L"The assigned control template is not vl::presentation::templates::Gui" L ## # TEMPLATE L"."); \ + NAME = ct; \ + BASE_TYPE::CheckAndStoreControlTemplate(value); \ + } \ + public: \ + templates::Gui##TEMPLATE* TypedControlTemplateObject(bool ensureExists) \ + { \ + if (ensureExists) \ + { \ + EnsureControlTemplateExists(); \ + } \ + return NAME; \ + } \ + private: \ + +#define GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(TEMPLATE, BASE_TYPE) GUI_SPECIFY_CONTROL_TEMPLATE_TYPE_2(TEMPLATE, BASE_TYPE, GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME) + + } + } +} + +#endif + + +/*********************************************************************** +.\APPLICATION\CONTROLS\GUILABELCONTROLS.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUILABELCONTROLS +#define VCZH_PRESENTATION_CONTROLS_GUILABELCONTROLS + + +namespace vl +{ + namespace presentation + { + namespace controls + { + +/*********************************************************************** +Label +***********************************************************************/ + + /// A control to display a text. + class GuiLabel : public GuiControl, public Description + { + GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(LabelTemplate, GuiControl) + protected: + Color textColor; + bool textColorConsisted = true; + + public: + /// Create a control with a specified default theme. + /// The theme name for retriving a default control template. + GuiLabel(theme::ThemeName themeName); + ~GuiLabel(); + + /// Get the text color. + /// The text color. + Color GetTextColor(); + /// Set the text color. + /// The text color. + void SetTextColor(Color value); + }; + } + } +} + +#endif + + +/*********************************************************************** +.\APPLICATION\CONTROLS\GUIWINDOWCONTROLS.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUIWINDOWCONTROLS +#define VCZH_PRESENTATION_CONTROLS_GUIWINDOWCONTROLS + + +namespace vl +{ + namespace presentation + { + namespace compositions + { + class IGuiShortcutKeyManager; + class GuiGraphicsTimerManager; + } + + namespace controls + { + +/*********************************************************************** +Control Host +***********************************************************************/ + + /// + /// Represents a control that host by a . + /// + class GuiControlHost : public GuiControl, public GuiInstanceRootObject, protected INativeWindowListener, public Description + { + friend class compositions::GuiGraphicsHost; + protected: + compositions::GuiGraphicsHost* host; + INativeWindow::WindowMode windowMode = INativeWindow::Normal; + + virtual void OnNativeWindowChanged(); + virtual void OnVisualStatusChanged(); + protected: + static const vint TooltipDelayOpenTime = 500; + static const vint TooltipDelayCloseTime = 500; + static const vint TooltipDelayLifeTime = 5000; + + Ptr tooltipOpenDelay; + Ptr tooltipCloseDelay; + Point tooltipLocation; + + bool calledDestroyed = false; + bool deleteWhenDestroyed = false; + + controls::GuiControlHost* GetControlHostForInstance()override; + GuiControl* GetTooltipOwner(Point location); + void MoveIntoTooltipControl(GuiControl* tooltipControl, Point location); + void MouseMoving(const NativeWindowMouseInfo& info)override; + void MouseLeaved()override; + void Moved()override; + void Enabled()override; + void Disabled()override; + void GotFocus()override; + void LostFocus()override; + void Activated()override; + void Deactivated()override; + void Opened()override; + void Closing(bool& cancel)override; + void Closed()override; + void Destroying()override; + + virtual void UpdateClientSizeAfterRendering(Size preferredSize, Size clientSize); + public: + /// Create a control with a specified default theme. + /// The theme name for retriving a default control template. + /// The window mode. + GuiControlHost(theme::ThemeName themeName, INativeWindow::WindowMode mode); + ~GuiControlHost(); + + /// Window got focus event. + compositions::GuiNotifyEvent WindowGotFocus; + /// Window lost focus event. + compositions::GuiNotifyEvent WindowLostFocus; + /// Window activated event. + compositions::GuiNotifyEvent WindowActivated; + /// Window deactivated event. + compositions::GuiNotifyEvent WindowDeactivated; + /// Window opened event. + compositions::GuiNotifyEvent WindowOpened; + /// Window closing event. + compositions::GuiRequestEvent WindowClosing; + /// Window closed event. + compositions::GuiNotifyEvent WindowClosed; + /// Window destroying event. + compositions::GuiNotifyEvent WindowDestroying; + + /// Delete this control host after processing all events. + void DeleteAfterProcessingAllEvents(); + + /// Get the internal object to host the window content. + /// The internal object to host the window content. + compositions::GuiGraphicsHost* GetGraphicsHost(); + /// Get the main composition to host the window content. + /// The main composition to host the window content. + compositions::GuiGraphicsComposition* GetMainComposition(); + /// Get the internal object to host the content. + /// The the internal object to host the content. + INativeWindow* GetNativeWindow(); + /// Set the internal object to host the content. + /// The the internal object to host the content. + void SetNativeWindow(INativeWindow* window); + /// Force to calculate layout and size immediately + void ForceCalculateSizeImmediately(); + + /// Test is the window enabled. + /// Returns true if the window is enabled. + bool GetEnabled()override; + /// Enable or disable the window. + /// Set to true to enable the window. + void SetEnabled(bool value)override; + /// Test is the window focused. + /// Returns true if the window is focused. + bool GetFocused()override; + /// Focus the window. A window with activation disabled cannot receive focus. + void SetFocused(); + /// Test is the window activated. + /// Returns true if the window is activated. + bool GetActivated(); + /// Activate the window. If the window disabled activation, this function enables it again. + void SetActivated(); + /// Test is the window icon shown in the task bar. + /// Returns true if the window is icon shown in the task bar. + bool GetShowInTaskBar(); + /// Show or hide the window icon in the task bar. + /// Set to true to show the window icon in the task bar. + void SetShowInTaskBar(bool value); + /// Test is the window allowed to be activated. + /// Returns true if the window is allowed to be activated. + bool GetEnabledActivate(); + /// + /// Allow or forbid the window to be activated. + /// Clicking a window with activation disabled doesn't bring activation and focus. + /// Activation will be automatically enabled by calling or . + /// + /// Set to true to allow the window to be activated. + void SetEnabledActivate(bool value); + /// + /// Test is the window always on top of the desktop. + /// + /// Returns true if the window is always on top of the desktop. + bool GetTopMost(); + /// + /// Make the window always or never on top of the desktop. + /// + /// True to make the window always on top of the desktop. + void SetTopMost(bool topmost); + + /// Get the attached with this control host. + /// The shortcut key manager. + compositions::IGuiShortcutKeyManager* GetShortcutKeyManager(); + /// Attach or detach the associated with this control host. When this control host is disposing, the associated shortcut key manager will be deleted if exists. + /// The shortcut key manager. Set to null to detach the previous shortcut key manager from this control host. + void SetShortcutKeyManager(compositions::IGuiShortcutKeyManager* value); + /// Get the timer manager. + /// The timer manager. + compositions::GuiGraphicsTimerManager* GetTimerManager(); + + /// Get the client size of the window. + /// The client size of the window. + Size GetClientSize(); + /// Set the client size of the window. + /// The client size of the window. + void SetClientSize(Size value); + /// Get the location of the window in screen space. + /// The location of the window. + NativePoint GetLocation(); + /// Set the location of the window in screen space. + /// The location of the window. + void SetLocation(NativePoint value); + /// Set the location in screen space and the client size of the window. + /// The location of the window. + /// The client size of the window. + void SetBounds(NativePoint location, Size size); + + GuiControlHost* GetRelatedControlHost()override; + const WString& GetText()override; + void SetText(const WString& value)override; + + /// Get the screen that contains the window. + /// The screen that contains the window. + INativeScreen* GetRelatedScreen(); + /// + /// Show the window. + /// If the window disabled activation, this function enables it again. + /// + void Show(); + /// + /// Show the window without activation. + /// + void ShowDeactivated(); + /// + /// Restore the window. + /// + void ShowRestored(); + /// + /// Maximize the window. + /// + void ShowMaximized(); + /// + /// Minimize the window. + /// + void ShowMinimized(); + /// + /// Hide the window. + /// + void Hide(); + /// + /// Close the window and destroy the internal object. + /// + void Close(); + /// Test is the window opened. + /// Returns true if the window is opened. + bool GetOpening(); + }; + +/*********************************************************************** +Window +***********************************************************************/ + + /// + /// Represents a normal window. + /// + class GuiWindow : public GuiControlHost, protected compositions::GuiAltActionHostBase, public AggregatableDescription + { + GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(WindowTemplate, GuiControlHost) + friend class GuiApplication; + protected: + compositions::IGuiAltActionHost* previousAltHost = nullptr; + bool hasMaximizedBox = true; + bool hasMinimizedBox = true; + bool hasBorder = true; + bool hasSizeBox = true; + bool isIconVisible = true; + bool hasTitleBar = true; + Ptr icon; + + void UpdateCustomFramePadding(INativeWindow* window, templates::GuiWindowTemplate* ct); + void SyncNativeWindowProperties(); + void Moved()override; + void DpiChanged()override; + void OnNativeWindowChanged()override; + void OnVisualStatusChanged()override; + + void OnWindowActivated(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void OnWindowDeactivated(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + + /// Create a control with a specified default theme and a window mode. + /// The theme name for retriving a default control template. + /// The window mode. + GuiWindow(theme::ThemeName themeName, INativeWindow::WindowMode mode); + public: + /// Create a control with a specified default theme. + /// The theme name for retriving a default control template. + GuiWindow(theme::ThemeName themeName); + ~GuiWindow(); + + IDescriptable* QueryService(const WString& identifier)override; + + /// Clipboard updated event. + compositions::GuiNotifyEvent ClipboardUpdated; + + /// Move the window to the center of the screen. If multiple screens exist, the window move to the screen that contains the biggest part of the window. + void MoveToScreenCenter(); + /// Move the window to the center of the specified screen. + /// The screen. + void MoveToScreenCenter(INativeScreen* screen); + + /// + /// Test is the maximize box visible. + /// + /// Returns true if the maximize box is visible. + bool GetMaximizedBox(); + /// + /// Make the maximize box visible or invisible. + /// + /// True to make the maximize box visible. + void SetMaximizedBox(bool visible); + /// + /// Test is the minimize box visible. + /// + /// Returns true if the minimize box is visible. + bool GetMinimizedBox(); + /// + /// Make the minimize box visible or invisible. + /// + /// True to make the minimize box visible. + void SetMinimizedBox(bool visible); + /// + /// Test is the border visible. + /// + /// Returns true if the border is visible. + bool GetBorder(); + /// + /// Make the border visible or invisible. + /// + /// True to make the border visible. + void SetBorder(bool visible); + /// + /// Test is the size box visible. + /// + /// Returns true if the size box is visible. + bool GetSizeBox(); + /// + /// Make the size box visible or invisible. + /// + /// True to make the size box visible. + void SetSizeBox(bool visible); + /// + /// Test is the icon visible. + /// + /// Returns true if the icon is visible. + bool GetIconVisible(); + /// + /// Make the icon visible or invisible. + /// + /// True to make the icon visible. + void SetIconVisible(bool visible); + /// + /// Get the icon which replaces the default one. + /// + /// Returns the icon that replaces the default one. + Ptr GetIcon(); + /// + /// Set the icon that replaces the default one. + /// + /// The icon that replaces the default one. + void SetIcon(Ptr value); + /// + /// Test is the title bar visible. + /// + /// Returns true if the title bar is visible. + bool GetTitleBar(); + /// + /// Make the title bar visible or invisible. + /// + /// True to make the title bar visible. + void SetTitleBar(bool visible); + /// + /// Show a model window, get a callback when the window is closed. + /// + /// The window to disable as a parent window. + /// The callback to call after the window is closed. + void ShowModal(GuiWindow* owner, const Func& callback); + /// + /// Show a model window, get a callback when the window is closed, and then delete itself. + /// + /// The window to disable as a parent window. + /// The callback to call after the window is closed. + void ShowModalAndDelete(GuiWindow* owner, const Func& callback); + /// + /// Show a model window as an async operation, which ends when the window is closed. + /// + /// Returns true if the size box is visible. + /// The window to disable as a parent window. + Ptr ShowModalAsync(GuiWindow* owner); + }; + + /// + /// Represents a popup window. When the mouse click on other window or the desktop, the popup window will be closed automatically. + /// + class GuiPopup : public GuiWindow, public Description + { + protected: + union PopupInfo + { + struct _s1 { NativePoint location; INativeScreen* screen; }; + struct _s2 { GuiControl* control; INativeWindow* controlWindow; Rect bounds; bool preferredTopBottomSide; }; + struct _s3 { GuiControl* control; INativeWindow* controlWindow; Point location; }; + struct _s4 { GuiControl* control; INativeWindow* controlWindow; bool preferredTopBottomSide; }; + + _s1 _1; + _s2 _2; + _s3 _3; + _s4 _4; + + PopupInfo() {} + }; + protected: + vint popupType = -1; + PopupInfo popupInfo; + + void UpdateClientSizeAfterRendering(Size preferredSize, Size clientSize)override; + void PopupOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void PopupClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments); + + static bool IsClippedByScreen(NativeSize size, NativePoint location, INativeScreen* screen); + static NativePoint CalculatePopupPosition(NativeSize windowSize, NativePoint location, INativeScreen* screen); + static NativePoint CalculatePopupPosition(NativeSize windowSize, GuiControl* control, INativeWindow* controlWindow, Rect bounds, bool preferredTopBottomSide); + static NativePoint CalculatePopupPosition(NativeSize windowSize, GuiControl* control, INativeWindow* controlWindow, Point location); + static NativePoint CalculatePopupPosition(NativeSize windowSize, GuiControl* control, INativeWindow* controlWindow, bool preferredTopBottomSide); + static NativePoint CalculatePopupPosition(NativeSize windowSize, vint popupType, const PopupInfo& popupInfo); + + void ShowPopupInternal(); + + /// Create a control with a specified default theme and a window mode. + /// The theme name for retriving a default control template. + /// The window mode. + GuiPopup(theme::ThemeName themeName, INativeWindow::WindowMode mode); + public: + /// Create a control with a specified default theme. + /// The theme name for retriving a default control template. + GuiPopup(theme::ThemeName themeName); + ~GuiPopup(); + + /// Test will the whole popup window be in the screen if the popup's left-top position is set to a specified value. + /// Returns true if the whole popup window will be in the screen. + /// The specified left-top position. + bool IsClippedByScreen(Point location); + /// Show the popup window with the left-top position set to a specified value. The position of the popup window will be adjusted to make it totally inside the screen if possible. + /// The specified left-top position. + /// The expected screen. If you don't want to specify any screen, don't set this parameter. + void ShowPopup(NativePoint location, INativeScreen* screen = 0); + /// Show the popup window with the bounds set to a specified control-relative value. The position of the popup window will be adjusted to make it totally inside the screen if possible. + /// The control that owns this popup temporary. And the location is relative to this control. + /// The specified bounds. + /// Set to true if the popup window is expected to be opened at the top or bottom side of that bounds. + void ShowPopup(GuiControl* control, Rect bounds, bool preferredTopBottomSide); + /// Show the popup window with the left-top position set to a specified control-relative value. The position of the popup window will be adjusted to make it totally inside the screen if possible. + /// The control that owns this popup temporary. And the location is relative to this control. + /// The specified left-top position. + void ShowPopup(GuiControl* control, Point location); + /// Show the popup window aligned with a specified control. The position of the popup window will be adjusted to make it totally inside the screen if possible. + /// The control that owns this popup temporary. + /// Set to true if the popup window is expected to be opened at the top or bottom side of that control. + void ShowPopup(GuiControl* control, bool preferredTopBottomSide); + }; + + /// Represents a tooltip window. + class GuiTooltip : public GuiPopup, private INativeControllerListener, public Description + { + protected: + GuiControl* temporaryContentControl = nullptr; + + void GlobalTimer()override; + void TooltipOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void TooltipClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + + public: + /// Create a control with a specified default theme. + /// The theme name for retriving a default control template. + GuiTooltip(theme::ThemeName themeName); + ~GuiTooltip(); + + /// Get the preferred content width. + /// The preferred content width. + vint GetPreferredContentWidth(); + /// Set the preferred content width. + /// The preferred content width. + void SetPreferredContentWidth(vint value); + + /// Get the temporary content control. + /// The temporary content control. + GuiControl* GetTemporaryContentControl(); + /// Set the temporary content control. + /// The temporary content control. + void SetTemporaryContentControl(GuiControl* control); + }; + } + } +} + +#endif + + +/*********************************************************************** +.\APPLICATION\CONTROLS\GUIAPPLICATION.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Application Framework + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUIAPPLICATION +#define VCZH_PRESENTATION_CONTROLS_GUIAPPLICATION + + +namespace vl +{ + namespace presentation + { + namespace controls + { + +/*********************************************************************** +Application +***********************************************************************/ + + /// Represents an GacUI application, for window management and asynchronized operation supporting. Use [M:vl.presentation.controls.GetApplication] to access the instance of this class. + class GuiApplication : public Object, private INativeControllerListener, public Description + { + friend void GuiApplicationInitialize(); + friend class GuiWindow; + friend class GuiPopup; + friend class Ptr; + private: + void InvokeClipboardNotify(compositions::GuiGraphicsComposition* composition, compositions::GuiEventArgs& arguments); + void ClipboardUpdated()override; + protected: + Locale locale; + GuiWindow* mainWindow = nullptr; + GuiWindow* sharedTooltipOwnerWindow = nullptr; + GuiControl* sharedTooltipOwner = nullptr; + GuiTooltip* sharedTooltipControl = nullptr; + bool sharedTooltipHovering = false; + bool sharedTooltipClosing = false; + collections::List windows; + collections::SortedList openingPopups; + + GuiApplication(); + ~GuiApplication(); + + INativeWindow* GetThreadContextNativeWindow(GuiControlHost* controlHost); + void RegisterWindow(GuiWindow* window); + void UnregisterWindow(GuiWindow* window); + void RegisterPopupOpened(GuiPopup* popup); + void RegisterPopupClosed(GuiPopup* popup); + void TooltipMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void TooltipMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + public: + /// Locale changed event. + Event LocaleChanged; + + /// Returns the selected locale for all windows. + /// The selected locale. + Locale GetLocale(); + /// Set the locale for all windows. + /// The selected locale. + void SetLocale(Locale value); + + /// Run a as the main window and show it. This function can only be called once in the entry point. When the main window is closed or hiden, the Run function will finished, and the application should prepare for finalization. + /// The main window. + void Run(GuiWindow* _mainWindow); + /// Get the main window. + /// The main window. + GuiWindow* GetMainWindow(); + /// Get all created instances. This contains normal windows, popup windows, menus, or other types of windows that inherits from . + /// All created instances. + const collections::List& GetWindows(); + /// Get the instance that the mouse cursor are directly in. + /// The instance that the mouse cursor are directly in. + /// The mouse cursor. + GuiWindow* GetWindow(NativePoint location); + /// Show a tooltip. + /// The control that owns this tooltip temporary. + /// The control as the tooltip content. This control is not owned by the tooltip. User should manually release this control if no longer needed (usually when the application exit). + /// The preferred content width for this tooltip. + /// The relative location to specify the left-top position of the tooltip. + void ShowTooltip(GuiControl* owner, GuiControl* tooltip, vint preferredContentWidth, Point location); + /// Close the tooltip + void CloseTooltip(); + /// Get the tooltip owner. When the tooltip closed, it returns null. + /// The tooltip owner. + GuiControl* GetTooltipOwner(); + /// Get the file path of the current executable. + /// The file path of the current executable. + WString GetExecutablePath(); + /// Get the folder of the current executable. + /// The folder of the current executable. + WString GetExecutableFolder(); + + /// Test is the current thread the main thread for GUI. + /// Returns true if the current thread is the main thread for GUI. + /// A control host to access the corressponding main thread. + bool IsInMainThread(GuiControlHost* controlHost); + /// Invoke a specified function asynchronously. + /// The specified function. + void InvokeAsync(const Func& proc); + /// Invoke a specified function in the main thread. + /// A control host to access the corressponding main thread. + /// The specified function. + void InvokeInMainThread(GuiControlHost* controlHost, const Func& proc); + /// Invoke a specified function in the main thread and wait for the function to complete or timeout. + /// Return true if the function complete. Return false if the function has not completed during a specified period of time. + /// A control host to access the corressponding main thread. + /// The specified function. + /// The specified period of time to wait. Set to -1 (default value) to wait forever until the function completed. + bool InvokeInMainThreadAndWait(GuiControlHost* controlHost, const Func& proc, vint milliseconds=-1); + /// Delay execute a specified function with an specified argument asynchronisly. + /// The Delay execution controller for this task. + /// The specified function. + /// Time to delay. + Ptr DelayExecute(const Func& proc, vint milliseconds); + /// Delay execute a specified function with an specified argument in the main thread. + /// The Delay execution controller for this task. + /// The specified function. + /// Time to delay. + Ptr DelayExecuteInMainThread(const Func& proc, vint milliseconds); + /// Run the specified function in the main thread. If the caller is in the main thread, then run the specified function directly. + /// A control host to access the corressponding main thread. + /// The specified function. + void RunGuiTask(GuiControlHost* controlHost, const Func& proc); + + template + T RunGuiValue(GuiControlHost* controlHost, const Func& proc) + { + T result; + RunGuiTask(controlHost, [&result, &proc]() + { + result=proc(); + }); + return result; + } + + template + void InvokeLambdaInMainThread(GuiControlHost* controlHost, const T& proc) + { + InvokeInMainThread(controlHost, Func(proc)); + } + + template + bool InvokeLambdaInMainThreadAndWait(GuiControlHost* controlHost, const T& proc, vint milliseconds=-1) + { + return InvokeInMainThreadAndWait(controlHost, Func(proc), milliseconds); + } + }; + +/*********************************************************************** +Helper Functions +***********************************************************************/ + + /// Get the global object. + /// The global object. + extern GuiApplication* GetApplication(); + } + } +} + +extern void GuiApplicationMain(); + +#define GUI_VALUE(x) vl::presentation::controls::GetApplication()->RunGuiValue(LAMBDA([&](){return (x);})) +#define GUI_RUN(x) vl::presentation::controls::GetApplication()->RunGuiTask([=](){x}) + +#endif + +/*********************************************************************** +.\CONTROLS\GUIDIALOGS.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUIDIALOGS +#define VCZH_PRESENTATION_CONTROLS_GUIDIALOGS + + +namespace vl +{ + namespace presentation + { + namespace controls + { + class GuiWindow; + +/*********************************************************************** +Dialogs +***********************************************************************/ + + /// Base class for dialogs. + class GuiDialogBase abstract : public GuiComponent, public Description + { + protected: + GuiInstanceRootObject* rootObject = nullptr; + + GuiWindow* GetHostWindow(); + public: + GuiDialogBase(); + ~GuiDialogBase(); + + void Attach(GuiInstanceRootObject* _rootObject); + void Detach(GuiInstanceRootObject* _rootObject); + }; + + /// Message dialog. + class GuiMessageDialog : public GuiDialogBase, public Description + { + protected: + INativeDialogService::MessageBoxButtonsInput input = INativeDialogService::DisplayOK; + INativeDialogService::MessageBoxDefaultButton defaultButton = INativeDialogService::DefaultFirst; + INativeDialogService::MessageBoxIcons icon = INativeDialogService::IconNone; + INativeDialogService::MessageBoxModalOptions modalOption = INativeDialogService::ModalWindow; + WString text; + WString title; + + public: + /// Create a message dialog. + GuiMessageDialog(); + ~GuiMessageDialog(); + + /// Get the button combination that appear on the dialog. + /// The button combination. + INativeDialogService::MessageBoxButtonsInput GetInput(); + /// Set the button combination that appear on the dialog. + /// The button combination. + void SetInput(INativeDialogService::MessageBoxButtonsInput value); + + /// Get the default button for the selected button combination. + /// The default button. + INativeDialogService::MessageBoxDefaultButton GetDefaultButton(); + /// Set the default button for the selected button combination. + /// The default button. + void SetDefaultButton(INativeDialogService::MessageBoxDefaultButton value); + + /// Get the icon that appears on the dialog. + /// The icon. + INativeDialogService::MessageBoxIcons GetIcon(); + /// Set the icon that appears on the dialog. + /// The icon. + void SetIcon(INativeDialogService::MessageBoxIcons value); + + /// Get the way that how this dialog disable windows of the current process. + /// The way that how this dialog disable windows of the current process. + INativeDialogService::MessageBoxModalOptions GetModalOption(); + /// Set the way that how this dialog disable windows of the current process. + /// The way that how this dialog disable windows of the current process. + void SetModalOption(INativeDialogService::MessageBoxModalOptions value); + + /// Get the text for the dialog. + /// The text. + const WString& GetText(); + /// Set the text for the dialog. + /// The text. + void SetText(const WString& value); + + /// Get the title for the dialog. + /// The title. + const WString& GetTitle(); + /// Set the title for the dialog. If the title is empty, the dialog will use the title of the window that host this dialog. + /// The title. + void SetTitle(const WString& value); + + /// Show the dialog. + /// Returns the clicked button. + INativeDialogService::MessageBoxButtonsOutput ShowDialog(); + }; + + /// Color dialog. + class GuiColorDialog : public GuiDialogBase, public Description + { + protected: + bool enabledCustomColor = true; + bool openedCustomColor = false; + Color selectedColor; + bool showSelection = true; + collections::List customColors; + + public: + /// Create a color dialog. + GuiColorDialog(); + ~GuiColorDialog(); + + /// Selected color changed event. + compositions::GuiNotifyEvent SelectedColorChanged; + + /// Get if the custom color panel is enabled for the dialog. + /// Returns true if the color panel is enabled for the dialog. + bool GetEnabledCustomColor(); + /// Set if custom color panel is enabled for the dialog. + /// Set to true to enable the custom color panel for the dialog. + void SetEnabledCustomColor(bool value); + + /// Get if the custom color panel is opened by default when it is enabled. + /// Returns true if the custom color panel is opened by default. + bool GetOpenedCustomColor(); + /// Set if the custom color panel is opened by default when it is enabled. + /// Set to true to open custom color panel by default if it is enabled. + void SetOpenedCustomColor(bool value); + + /// Get the selected color. + /// The selected color. + Color GetSelectedColor(); + /// Set the selected color. + /// The selected color. + void SetSelectedColor(Color value); + + /// Get the list to access 16 selected custom colors on the palette. Colors in the list is guaranteed to have exactly 16 items after the dialog is closed. + /// The list to access custom colors on the palette. + collections::List& GetCustomColors(); + + /// Show the dialog. + /// Returns true if the "OK" button is clicked. + bool ShowDialog(); + }; + + /// Font dialog. + class GuiFontDialog : public GuiDialogBase, public Description + { + protected: + FontProperties selectedFont; + Color selectedColor; + bool showSelection = true; + bool showEffect = true; + bool forceFontExist = true; + + public: + /// Create a font dialog. + GuiFontDialog(); + ~GuiFontDialog(); + + /// Selected font changed event. + compositions::GuiNotifyEvent SelectedFontChanged; + /// Selected color changed event. + compositions::GuiNotifyEvent SelectedColorChanged; + + /// Get the selected font. + /// The selected font. + const FontProperties& GetSelectedFont(); + /// Set the selected font. + /// The selected font. + void SetSelectedFont(const FontProperties& value); + + /// Get the selected color. + /// The selected color. + Color GetSelectedColor(); + /// Set the selected color. + /// The selected color. + void SetSelectedColor(Color value); + + /// Get if the selected font is already selected on the dialog when it is opened. + /// Returns true if the selected font is already selected on the dialog when it is opened. + bool GetShowSelection(); + /// Set if the selected font is already selected on the dialog when it is opened. + /// Set to true to select the selected font when the dialog is opened. + void SetShowSelection(bool value); + + /// Get if the font preview is enabled. + /// Returns true if the font preview is enabled. + bool GetShowEffect(); + /// Set if the font preview is enabled. + /// Set to true to enable the font preview. + void SetShowEffect(bool value); + + /// Get if the dialog only accepts an existing font. + /// Returns true if the dialog only accepts an existing font. + bool GetForceFontExist(); + /// Set if the dialog only accepts an existing font. + /// Set to true to let the dialog only accept an existing font. + void SetForceFontExist(bool value); + + /// Show the dialog. + /// Returns true if the "OK" button is clicked. + bool ShowDialog(); + }; + + /// Base class for file dialogs. + class GuiFileDialogBase abstract : public GuiDialogBase, public Description + { + protected: + WString filter = L"All Files (*.*)|*.*"; + vint filterIndex = 0; + bool enabledPreview = false; + WString title; + WString fileName; + WString directory; + WString defaultExtension; + INativeDialogService::FileDialogOptions options; + + public: + GuiFileDialogBase(); + ~GuiFileDialogBase(); + + /// File name changed event. + compositions::GuiNotifyEvent FileNameChanged; + /// Filter index changed event. + compositions::GuiNotifyEvent FilterIndexChanged; + + /// Get the filter. + /// The filter. + const WString& GetFilter(); + /// Set the filter. The filter is formed by pairs of filter name and wildcard concatenated by "|", like "Text Files (*.txt)|*.txt|All Files (*.*)|*.*". + /// The filter. + void SetFilter(const WString& value); + + /// Get the filter index. + /// The filter index. + vint GetFilterIndex(); + /// Set the filter index. + /// The filter index. + void SetFilterIndex(vint value); + + /// Get if the file preview is enabled. + /// Returns true if the file preview is enabled. + bool GetEnabledPreview(); + /// Set if the file preview is enabled. + /// Set to true to enable the file preview. + void SetEnabledPreview(bool value); + + /// Get the title. + /// The title. + WString GetTitle(); + /// Set the title. + /// The title. + void SetTitle(const WString& value); + + /// Get the selected file name. + /// The selected file name. + WString GetFileName(); + /// Set the selected file name. + /// The selected file name. + void SetFileName(const WString& value); + + /// Get the default folder. + /// The default folder. + WString GetDirectory(); + /// Set the default folder. + /// The default folder. + void SetDirectory(const WString& value); + + /// Get the default file extension. + /// The default file extension. + WString GetDefaultExtension(); + /// Set the default file extension like "txt". If the user does not specify a file extension, the default file extension will be appended using "." after the file name. + /// The default file extension. + void SetDefaultExtension(const WString& value); + + /// Get the dialog options. + /// The dialog options. + INativeDialogService::FileDialogOptions GetOptions(); + /// Set the dialog options. + /// The dialog options. + void SetOptions(INativeDialogService::FileDialogOptions value); + }; + + /// Open file dialog. + class GuiOpenFileDialog : public GuiFileDialogBase, public Description + { + protected: + collections::List fileNames; + + public: + /// Create a open file dialog. + GuiOpenFileDialog(); + ~GuiOpenFileDialog(); + + /// Get the list to access multiple selected file names. + /// The list to access multiple selected file names. + collections::List& GetFileNames(); + + /// Show the dialog. + /// Returns true if the "Open" button is clicked. + bool ShowDialog(); + }; + + /// Save file dialog. + class GuiSaveFileDialog : public GuiFileDialogBase, public Description + { + public: + /// Create a save file dialog. + GuiSaveFileDialog(); + ~GuiSaveFileDialog(); + + /// Show the dialog. + /// Returns true if the "Save" button is clicked. + bool ShowDialog(); + }; + } + } +} + +#endif + + /*********************************************************************** .\CONTROLS\TEMPLATES\GUIANIMATION.H ***********************************************************************/ @@ -7423,6 +9137,128 @@ namespace vl #endif +/*********************************************************************** +.\CONTROLS\TOOLSTRIPPACKAGE\GUITOOLSTRIPCOMMAND.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUITOOLSTRIPCOMMAND +#define VCZH_PRESENTATION_CONTROLS_GUITOOLSTRIPCOMMAND + + +namespace vl +{ + namespace presentation + { + namespace compositions + { + class IGuiShortcutKeyItem; + } + + namespace controls + { + /// A command for toolstrip controls. + class GuiToolstripCommand : public GuiComponent, public Description + { + public: + class ShortcutBuilder : public Object + { + public: + WString text; + bool ctrl; + bool shift; + bool alt; + VKEY key; + }; + protected: + Ptr image; + Ptr largeImage; + WString text; + compositions::IGuiShortcutKeyItem* shortcutKeyItem = nullptr; + bool enabled = true; + bool selected = false; + Ptr shortcutKeyItemExecutedHandler; + Ptr shortcutBuilder; + + GuiInstanceRootObject* attachedRootObject = nullptr; + Ptr renderTargetChangedHandler; + GuiControlHost* shortcutOwner = nullptr; + + void OnShortcutKeyItemExecuted(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void OnRenderTargetChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void InvokeDescriptionChanged(); + void ReplaceShortcut(compositions::IGuiShortcutKeyItem* value, Ptr builder); + void BuildShortcut(const WString& builderText); + void UpdateShortcutOwner(); + public: + /// Create the command. + GuiToolstripCommand(); + ~GuiToolstripCommand(); + + void Attach(GuiInstanceRootObject* rootObject)override; + void Detach(GuiInstanceRootObject* rootObject)override; + + /// Executed event. + compositions::GuiNotifyEvent Executed; + + /// Description changed event, raised when any description property is modified. + compositions::GuiNotifyEvent DescriptionChanged; + + /// Get the large image for this command. + /// The large image for this command. + Ptr GetLargeImage(); + /// Set the large image for this command. + /// The large image for this command. + void SetLargeImage(Ptr value); + /// Get the image for this command. + /// The image for this command. + Ptr GetImage(); + /// Set the image for this command. + /// The image for this command. + void SetImage(Ptr value); + /// Get the text for this command. + /// The text for this command. + const WString& GetText(); + /// Set the text for this command. + /// The text for this command. + void SetText(const WString& value); + /// Get the shortcut key item for this command. + /// The shortcut key item for this command. + compositions::IGuiShortcutKeyItem* GetShortcut(); + /// Set the shortcut key item for this command. + /// The shortcut key item for this command. + void SetShortcut(compositions::IGuiShortcutKeyItem* value); + /// Get the shortcut builder for this command. + /// The shortcut builder for this command. + WString GetShortcutBuilder(); + /// Set the shortcut builder for this command. When the command is attached to a window as a component without a shortcut, the command will try to convert the shortcut builder to a shortcut key item. + /// The shortcut builder for this command. + void SetShortcutBuilder(const WString& value); + /// Get the enablility for this command. + /// The enablility for this command. + bool GetEnabled(); + /// Set the enablility for this command. + /// The enablility for this command. + void SetEnabled(bool value); + /// Get the selection for this command. + /// The selection for this command. + bool GetSelected(); + /// Set the selection for this command. + /// The selection for this command. + void SetSelected(bool value); + }; + } + } +} + +#endif + /*********************************************************************** .\RESOURCES\GUIDOCUMENT.H ***********************************************************************/ @@ -9450,60 +11286,134 @@ namespace vl class GuiScroll; } + namespace controls + { + class GuiControlHost; + class GuiCustomControl; + + /// The visual state for button. + enum class ButtonState + { + /// Normal state. + Normal, + /// Active state (when the cursor is hovering on a button). + Active, + /// Pressed state (when the buttin is being pressed). + Pressed, + }; + + /// Represents the sorting state of list view items related to this column. + enum class ColumnSortingState + { + /// Not sorted. + NotSorted, + /// Ascending. + Ascending, + /// Descending. + Descending, + }; + + /// Represents the order of tab pages. + enum class TabPageOrder + { + /// Unknown. + Unknown, + /// Left to right. + LeftToRight, + /// Right to left. + RightToLeft, + /// Top to bottom. + TopToBottom, + /// Bottom to top. + BottomToTop, + }; + + /// A command executor for the combo box to change the control state. + class ITextBoxCommandExecutor : public virtual IDescriptable, public Description + { + public: + /// Override the text content in the control. + /// The new text content. + virtual void UnsafeSetText(const WString& value) = 0; + }; + + /// A command executor for the style controller to change the control state. + class IScrollCommandExecutor : public virtual IDescriptable, public Description + { + public: + /// Do small decrement. + virtual void SmallDecrease() = 0; + /// Do small increment. + virtual void SmallIncrease() = 0; + /// Do big decrement. + virtual void BigDecrease() = 0; + /// Do big increment. + virtual void BigIncrease() = 0; + + /// Change to total size of the scroll. + /// The total size. + virtual void SetTotalSize(vint value) = 0; + /// Change to page size of the scroll. + /// The page size. + virtual void SetPageSize(vint value) = 0; + /// Change to position of the scroll. + /// The position. + virtual void SetPosition(vint value) = 0; + }; + + /// A command executor for the style controller to change the control state. + class ITabCommandExecutor : public virtual IDescriptable, public Description + { + public: + /// Select a tab page. + /// The specified position for the tab page. + /// Set to true to set focus to the tab control. + virtual void ShowTab(vint index, bool setFocus) = 0; + }; + + /// A command executor for the style controller to change the control state. + class IDatePickerCommandExecutor : public virtual IDescriptable, public Description + { + public: + /// Called when the date has been changed. + virtual void NotifyDateChanged() = 0; + /// Called when navigated to a date. + virtual void NotifyDateNavigated() = 0; + /// Called when selected a date. + virtual void NotifyDateSelected() = 0; + }; + + /// A command executor for the style controller to change the control state. + class IRibbonGroupCommandExecutor : public virtual IDescriptable, public Description + { + public: + /// Called when the expand button is clicked. + virtual void NotifyExpandButtonClicked() = 0; + }; + + /// A command executor for the style controller to change the control state. + class IRibbonGalleryCommandExecutor : public virtual IDescriptable, public Description + { + public: + /// Called when the scroll up button is clicked. + virtual void NotifyScrollUp() = 0; + /// Called when the scroll down button is clicked. + virtual void NotifyScrollDown() = 0; + /// Called when the dropdown button is clicked. + virtual void NotifyDropdown() = 0; + }; + } + +/*********************************************************************** +Templates +***********************************************************************/ + namespace templates { -#define GUI_TEMPLATE_PROPERTY_DECL(CLASS, TYPE, NAME, VALUE)\ - private:\ - TYPE NAME##_ = VALUE;\ - public:\ - TYPE Get##NAME();\ - void Set##NAME(TYPE const& value);\ - compositions::GuiNotifyEvent NAME##Changed;\ - -#define GUI_TEMPLATE_PROPERTY_IMPL(CLASS, TYPE, NAME, VALUE)\ - TYPE CLASS::Get##NAME()\ - {\ - return NAME##_;\ - }\ - void CLASS::Set##NAME(TYPE const& value)\ - {\ - if (NAME##_ != value)\ - {\ - NAME##_ = value;\ - NAME##Changed.Execute(compositions::GuiEventArgs(this));\ - }\ - }\ - -#define GUI_TEMPLATE_PROPERTY_EVENT_INIT(CLASS, TYPE, NAME, VALUE)\ - NAME##Changed.SetAssociatedComposition(this); - -#define GUI_TEMPLATE_CLASS_DECL(CLASS, BASE)\ - class CLASS : public BASE, public AggregatableDescription\ - {\ - public:\ - CLASS();\ - ~CLASS();\ - CLASS ## _PROPERTIES(GUI_TEMPLATE_PROPERTY_DECL)\ - };\ - -#define GUI_TEMPLATE_CLASS_IMPL(CLASS, BASE)\ - CLASS ## _PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL)\ - CLASS::CLASS()\ - {\ - CLASS ## _PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT)\ - }\ - CLASS::~CLASS()\ - {\ - FinalizeAggregation();\ - }\ - #define GUI_CONTROL_TEMPLATE_DECL(F)\ - F(GuiControlTemplate, GuiTemplate) \ - F(GuiLabelTemplate, GuiControlTemplate) \ F(GuiSinglelineTextBoxTemplate, GuiControlTemplate) \ F(GuiDocumentLabelTemplate, GuiControlTemplate) \ - F(GuiWindowTemplate, GuiControlTemplate) \ F(GuiMenuTemplate, GuiWindowTemplate) \ F(GuiButtonTemplate, GuiControlTemplate) \ F(GuiSelectableButtonTemplate, GuiButtonTemplate) \ @@ -9537,30 +11447,6 @@ namespace vl F(GuiGridVisualizerTemplate, GuiGridCellTemplate) \ F(GuiGridEditorTemplate, GuiGridCellTemplate) \ -/*********************************************************************** -GuiTemplate -***********************************************************************/ - - /// Represents a user customizable template. - class GuiTemplate : public compositions::GuiBoundsComposition, public controls::GuiInstanceRootObject, public Description - { - protected: - controls::GuiControlHost* GetControlHostForInstance()override; - void OnParentLineChanged()override; - public: - /// Create a template. - GuiTemplate(); - ~GuiTemplate(); - -#define GuiTemplate_PROPERTIES(F)\ - F(GuiTemplate, FontProperties, Font, {} )\ - F(GuiTemplate, description::Value, Context, {} )\ - F(GuiTemplate, WString, Text, {} )\ - F(GuiTemplate, bool, VisuallyEnabled, true)\ - - GuiTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_DECL) - }; - /*********************************************************************** GuiListItemTemplate ***********************************************************************/ @@ -9590,22 +11476,6 @@ GuiListItemTemplate Control Template ***********************************************************************/ - enum class BoolOption - { - AlwaysTrue, - AlwaysFalse, - Customizable, - }; - -#define GuiControlTemplate_PROPERTIES(F)\ - F(GuiControlTemplate, compositions::GuiGraphicsComposition*, ContainerComposition, this)\ - F(GuiControlTemplate, compositions::GuiGraphicsComposition*, FocusableComposition, nullptr)\ - F(GuiControlTemplate, bool, Focused, false)\ - -#define GuiLabelTemplate_PROPERTIES(F)\ - F(GuiLabelTemplate, Color, DefaultTextColor, {})\ - F(GuiLabelTemplate, Color, TextColor, {})\ - #define GuiSinglelineTextBoxTemplate_PROPERTIES(F)\ F(GuiSinglelineTextBoxTemplate, elements::text::ColorEntry, TextColor, {})\ F(GuiSinglelineTextBoxTemplate, Color, CaretColor, {})\ @@ -9614,27 +11484,6 @@ Control Template F(GuiDocumentLabelTemplate, Ptr, BaselineDocument, {})\ F(GuiDocumentLabelTemplate, Color, CaretColor, {})\ -#define GuiWindowTemplate_PROPERTIES(F)\ - F(GuiWindowTemplate, BoolOption, MaximizedBoxOption, BoolOption::Customizable)\ - F(GuiWindowTemplate, BoolOption, MinimizedBoxOption, BoolOption::Customizable)\ - F(GuiWindowTemplate, BoolOption, BorderOption, BoolOption::Customizable)\ - F(GuiWindowTemplate, BoolOption, SizeBoxOption, BoolOption::Customizable)\ - F(GuiWindowTemplate, BoolOption, IconVisibleOption, BoolOption::Customizable)\ - F(GuiWindowTemplate, BoolOption, TitleBarOption, BoolOption::Customizable)\ - F(GuiWindowTemplate, bool, MaximizedBox, true)\ - F(GuiWindowTemplate, bool, MinimizedBox, true)\ - F(GuiWindowTemplate, bool, Border, true)\ - F(GuiWindowTemplate, bool, SizeBox, true)\ - F(GuiWindowTemplate, bool, IconVisible, true)\ - F(GuiWindowTemplate, bool, TitleBar, true)\ - F(GuiWindowTemplate, bool, Maximized, false)\ - F(GuiWindowTemplate, bool, Activated, false)\ - F(GuiWindowTemplate, TemplateProperty, TooltipTemplate, {})\ - F(GuiWindowTemplate, TemplateProperty, ShortcutKeyTemplate, {})\ - F(GuiWindowTemplate, bool, CustomFrameEnabled, true)\ - F(GuiWindowTemplate, Margin, CustomFramePadding, {})\ - F(GuiWindowTemplate, Ptr, Icon, {})\ - #define GuiMenuTemplate_PROPERTIES(F) #define GuiButtonTemplate_PROPERTIES(F)\ @@ -9802,448 +11651,6 @@ Template Declarations #endif -/*********************************************************************** -.\CONTROLS\GUIBASICCONTROLS.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUIBASICCONTROLS -#define VCZH_PRESENTATION_CONTROLS_GUIBASICCONTROLS - - -namespace vl -{ - namespace presentation - { - namespace theme - { - enum class ThemeName; - } - - namespace controls - { - template - struct QueryServiceHelper; - - template - struct QueryServiceHelper>> - { - static WString GetIdentifier() - { - return WString::Unmanaged(T::Identifier); - } - }; - - template - struct QueryServiceHelper>> - { - static WString GetIdentifier() - { - return MoveValue(T::GetIdentifier()); - } - }; - -/*********************************************************************** -Basic Construction -***********************************************************************/ - - /// - /// A helper object to test if a control has been deleted or not. - /// - class GuiDisposedFlag : public Object, public Description - { - friend class GuiControl; - protected: - GuiControl* owner = nullptr; - bool disposed = false; - - void SetDisposed(); - public: - GuiDisposedFlag(GuiControl* _owner); - ~GuiDisposedFlag(); - - bool IsDisposed(); - }; - - /// - /// The base class of all controls. - /// When the control is destroyed, it automatically destroys sub controls, and the bounds composition from the style controller. - /// If you want to manually destroy a control, you should first remove it from its parent. - /// The only way to remove a control from a parent control, is to remove the bounds composition from its parent composition. The same to inserting a control. - /// - class GuiControl - : public Object - , protected compositions::IGuiAltAction - , protected compositions::IGuiTabAction - , public Description - { - friend class compositions::GuiGraphicsComposition; - - protected: - using ControlList = collections::List; - using ControlServiceMap = collections::Dictionary>; - using ControlTemplatePropertyType = TemplateProperty; - using IGuiGraphicsEventHandler = compositions::IGuiGraphicsEventHandler; - - private: - theme::ThemeName controlThemeName; - ControlTemplatePropertyType controlTemplate; - templates::GuiControlTemplate* controlTemplateObject = nullptr; - Ptr disposedFlag; - - public: - Ptr GetDisposedFlag(); - - protected: - compositions::GuiBoundsComposition* boundsComposition = nullptr; - compositions::GuiBoundsComposition* containerComposition = nullptr; - compositions::GuiGraphicsComposition* focusableComposition = nullptr; - compositions::GuiGraphicsEventReceiver* eventReceiver = nullptr; - - bool isFocused = false; - Ptr gotFocusHandler; - Ptr lostFocusHandler; - - bool acceptTabInput = false; - vint tabPriority = -1; - bool isEnabled = true; - bool isVisuallyEnabled = true; - bool isVisible = true; - WString alt; - WString text; - Nullable font; - FontProperties displayFont; - description::Value context; - compositions::IGuiAltActionHost* activatingAltHost = nullptr; - ControlServiceMap controlServices; - - GuiControl* parent = nullptr; - ControlList children; - description::Value tag; - GuiControl* tooltipControl = nullptr; - vint tooltipWidth = 0; - - virtual void BeforeControlTemplateUninstalled(); - virtual void AfterControlTemplateInstalled(bool initialize); - virtual void CheckAndStoreControlTemplate(templates::GuiControlTemplate* value); - virtual void EnsureControlTemplateExists(); - virtual void RebuildControlTemplate(); - virtual void OnChildInserted(GuiControl* control); - 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(); - virtual void UpdateDisplayFont(); - void OnGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void SetFocusableComposition(compositions::GuiGraphicsComposition* value); - - bool IsControlVisibleAndEnabled(); - bool IsAltEnabled()override; - bool IsAltAvailable()override; - compositions::GuiGraphicsComposition* GetAltComposition()override; - compositions::IGuiAltActionHost* GetActivatingAltHost()override; - void OnActiveAlt()override; - bool IsTabEnabled()override; - bool IsTabAvailable()override; - - static bool SharedPtrDestructorProc(DescriptableObject* obj, bool forceDisposing); - - public: - using ControlTemplateType = templates::GuiControlTemplate; - - /// Create a control with a specified default theme. - /// The theme name for retriving a default control template. - GuiControl(theme::ThemeName themeName); - ~GuiControl(); - - /// Theme name changed event. This event raises when the theme name is changed. - compositions::GuiNotifyEvent ControlThemeNameChanged; - /// Control template changed event. This event raises when the control template is changed. - compositions::GuiNotifyEvent ControlTemplateChanged; - /// Control signal trigerred. This raises be raised because of multiple reason specified in the argument. - compositions::GuiControlSignalEvent ControlSignalTrigerred; - /// Visible event. This event raises when the visibility state of the control is changed. - compositions::GuiNotifyEvent VisibleChanged; - /// Enabled event. This event raises when the enabling state of the control is changed. - compositions::GuiNotifyEvent EnabledChanged; - /// Focused event. This event raises when the focusing state of the control is changed. - compositions::GuiNotifyEvent FocusedChanged; - /// - /// Enabled event. This event raises when the visually enabling state of the control is changed. A visually enabling is combined by the enabling state and the parent's visually enabling state. - /// A control is rendered as disabled, not only when the control itself is disabled, but also when the parent control is rendered as disabled. - /// - compositions::GuiNotifyEvent VisuallyEnabledChanged; - /// Alt changed event. This event raises when the associated Alt-combined shortcut key of the control is changed. - compositions::GuiNotifyEvent AltChanged; - /// Text changed event. This event raises when the text of the control is changed. - compositions::GuiNotifyEvent TextChanged; - /// Font changed event. This event raises when the font of the control is changed. - compositions::GuiNotifyEvent FontChanged; - /// Display font changed event. This event raises when the display font of the control is changed. - compositions::GuiNotifyEvent DisplayFontChanged; - /// Context changed event. This event raises when the font of the control is changed. - compositions::GuiNotifyEvent ContextChanged; - - void InvokeOrDelayIfRendering(Func proc); - - /// A function to create the argument for notify events that raised by itself. - /// The created argument. - compositions::GuiEventArgs GetNotifyEventArguments(); - /// Get the associated theme name. - /// The theme name. - theme::ThemeName GetControlThemeName(); - /// Set the associated control theme name. - /// The theme name. - void SetControlThemeName(theme::ThemeName value); - /// Get the associated control template. - /// The control template. - ControlTemplatePropertyType GetControlTemplate(); - /// Set the associated control template. - /// The control template. - void SetControlTemplate(const ControlTemplatePropertyType& value); - /// Set the associated control theme name and template and the same time. - /// The theme name. - /// The control template. - void SetControlThemeNameAndTemplate(theme::ThemeName themeNameValue, const ControlTemplatePropertyType& controlTemplateValue); - /// Get the associated style controller. - /// The associated style controller. - templates::GuiControlTemplate* GetControlTemplateObject(); - /// Get the bounds composition for the control. - /// The bounds composition. - compositions::GuiBoundsComposition* GetBoundsComposition(); - /// Get the container composition for the control. - /// The container composition. - compositions::GuiGraphicsComposition* GetContainerComposition(); - /// Get the focusable composition for the control. A focusable composition is the composition to be focused when the control is focused. - /// The focusable composition. - compositions::GuiGraphicsComposition* GetFocusableComposition(); - /// Get the parent control. - /// The parent control. - GuiControl* GetParent(); - /// Get the number of child controls. - /// The number of child controls. - vint GetChildrenCount(); - /// Get the child control using a specified index. - /// The child control. - /// The specified index. - GuiControl* GetChild(vint index); - /// Put another control in the container composition of this control. - /// Returns true if this operation succeeded. - /// The control to put in this control. - bool AddChild(GuiControl* control); - /// Test if a control owned by this control. - /// Returns true if the control is owned by this control. - /// The control to test. - bool HasChild(GuiControl* control); - - /// Get the that contains this control. - /// The that contains this control. - virtual GuiControlHost* GetRelatedControlHost(); - /// Test if this control is rendered as enabled. - /// Returns true if this control is rendered as enabled. - virtual bool GetVisuallyEnabled(); - /// Test if this control is focused. - /// Returns true if this control is focused. - virtual bool GetFocused(); - /// Test if this control accepts tab character input. - /// Returns true if this control accepts tab character input. - virtual bool GetAcceptTabInput()override; - /// Set if this control accepts tab character input. - /// Set to true to make this control accept tab character input. - void SetAcceptTabInput(bool value); - /// Get the tab priority associated with this control. - /// Returns he tab priority associated with this control. - virtual vint GetTabPriority()override; - /// Associate a tab priority with this control. - /// The tab priority to associate. TAB key will go through controls in the order of priority: 0, 1, 2, ..., -1. All negative numbers will be converted to -1. The priority of containers affects all children if it is not -1. - void SetTabPriority(vint value); - /// Test if this control is enabled. - /// Returns true if this control is enabled. - virtual bool GetEnabled(); - /// Make the control enabled or disabled. - /// Set to true to make the control enabled. - virtual void SetEnabled(bool value); - /// Test if this visible or invisible. - /// Returns true if this control is visible. - virtual bool GetVisible(); - /// Make the control visible or invisible. - /// Set to true to make the visible enabled. - virtual void SetVisible(bool value); - /// Get the Alt-combined shortcut key associated with this control. - /// The Alt-combined shortcut key associated with this control. - virtual const WString& GetAlt()override; - /// Associate a Alt-combined shortcut key with this control. - /// Returns true if this operation succeeded. - /// The Alt-combined shortcut key to associate. The key should contain only upper-case letters or digits. - virtual bool SetAlt(const WString& value); - /// Make the control as the parent of multiple Alt-combined shortcut key activatable controls. - /// The alt action host object. - void SetActivatingAltHost(compositions::IGuiAltActionHost* host); - /// Get the text to display on the control. - /// The text to display on the control. - virtual const WString& GetText(); - /// Set the text to display on the control. - /// The text to display on the control. - virtual void SetText(const WString& value); - /// Get the font of this control. - /// The font of this control. - virtual const Nullable& GetFont(); - /// Set the font of this control. - /// The font of this control. - virtual void SetFont(const Nullable& value); - /// Get the font to render the text. If the font of this control is null, then the display font is either the parent control's display font, or the system's default font when there is no parent control. - /// The font to render the text. - virtual const FontProperties& GetDisplayFont(); - /// Get the context of this control. The control template and all item templates (if it has) will see this context property. - /// The context of this context. - virtual description::Value GetContext(); - /// Set the context of this control. - /// The context of this control. - virtual void SetContext(const description::Value& value); - /// Focus this control. - virtual void SetFocus(); - - /// Get the tag object of the control. - /// The tag object of the control. - description::Value GetTag(); - /// Set the tag object of the control. - /// The tag object of the control. - void SetTag(const description::Value& value); - /// Get the tooltip control of the control. - /// The tooltip control of the control. - GuiControl* GetTooltipControl(); - /// Set the tooltip control of the control. The tooltip control will be released when this control is released. If you set a new tooltip control to replace the old one, the old one will not be owned by this control anymore, therefore user should release the old tooltip control manually. - /// The old tooltip control. - /// The tooltip control of the control. - GuiControl* SetTooltipControl(GuiControl* value); - /// Get the tooltip width of the control. - /// The tooltip width of the control. - vint GetTooltipWidth(); - /// Set the tooltip width of the control. - /// The tooltip width of the control. - void SetTooltipWidth(vint value); - /// Display the tooltip. - /// Returns true if this operation succeeded. - /// The relative location to specify the left-top position of the tooltip. - bool DisplayTooltip(Point location); - /// Close the tooltip that owned by this control. - void CloseTooltip(); - - /// Query a service using an identifier. If you want to get a service of type IXXX, use IXXX::Identifier as the identifier. - /// The requested service. If the control doesn't support this service, it will be null. - /// The identifier. - virtual IDescriptable* QueryService(const WString& identifier); - - template - T* QueryTypedService() - { - return dynamic_cast(QueryService(QueryServiceHelper::GetIdentifier())); - } - - templates::GuiControlTemplate* TypedControlTemplateObject(bool ensureExists) - { - if (ensureExists) - { - EnsureControlTemplateExists(); - } - return controlTemplateObject; - } - - /// 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); - }; - - /// Represnets a user customizable control. - class GuiCustomControl : public GuiControl, public GuiInstanceRootObject, public AggregatableDescription - { - protected: - controls::GuiControlHost* GetControlHostForInstance()override; - void OnParentLineChanged()override; - public: - /// Create a control with a specified default theme. - /// The theme name for retriving a default control template. - GuiCustomControl(theme::ThemeName themeName); - ~GuiCustomControl(); - }; - - template - class GuiObjectComponent : public GuiComponent - { - public: - Ptr object; - - GuiObjectComponent() - { - } - - GuiObjectComponent(Ptr _object) - :object(_object) - { - } - }; - -#define GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME_3(UNIQUE) controlTemplateObject ## UNIQUE -#define GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME_2(UNIQUE) GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME_3(UNIQUE) -#define GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME_2(__LINE__) - -#define GUI_SPECIFY_CONTROL_TEMPLATE_TYPE_2(TEMPLATE, BASE_TYPE, NAME) \ - public: \ - using ControlTemplateType = templates::Gui##TEMPLATE; \ - private: \ - templates::Gui##TEMPLATE* NAME = nullptr; \ - void BeforeControlTemplateUninstalled_(); \ - void AfterControlTemplateInstalled_(bool initialize); \ - protected: \ - void BeforeControlTemplateUninstalled()override \ - {\ - BeforeControlTemplateUninstalled_(); \ - BASE_TYPE::BeforeControlTemplateUninstalled(); \ - }\ - void AfterControlTemplateInstalled(bool initialize)override \ - {\ - BASE_TYPE::AfterControlTemplateInstalled(initialize); \ - AfterControlTemplateInstalled_(initialize); \ - }\ - void CheckAndStoreControlTemplate(templates::GuiControlTemplate* value)override \ - { \ - auto ct = dynamic_cast(value); \ - CHECK_ERROR(ct, L"The assigned control template is not vl::presentation::templates::Gui" L ## # TEMPLATE L"."); \ - NAME = ct; \ - BASE_TYPE::CheckAndStoreControlTemplate(value); \ - } \ - public: \ - templates::Gui##TEMPLATE* TypedControlTemplateObject(bool ensureExists) \ - { \ - if (ensureExists) \ - { \ - EnsureControlTemplateExists(); \ - } \ - return NAME; \ - } \ - private: \ - -#define GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(TEMPLATE, BASE_TYPE) GUI_SPECIFY_CONTROL_TEMPLATE_TYPE_2(TEMPLATE, BASE_TYPE, GUI_GENERATE_CONTROL_TEMPLATE_OBJECT_NAME) - - } - } -} - -#endif - - /*********************************************************************** .\CONTROLS\GUIBUTTONCONTROLS.H ***********************************************************************/ @@ -10414,391 +11821,6 @@ Buttons #endif -/*********************************************************************** -.\CONTROLS\GUIDIALOGS.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUIDIALOGS -#define VCZH_PRESENTATION_CONTROLS_GUIDIALOGS - - -namespace vl -{ - namespace presentation - { - namespace controls - { - class GuiWindow; - -/*********************************************************************** -Dialogs -***********************************************************************/ - - /// Base class for dialogs. - class GuiDialogBase abstract : public GuiComponent, public Description - { - protected: - GuiInstanceRootObject* rootObject = nullptr; - - GuiWindow* GetHostWindow(); - public: - GuiDialogBase(); - ~GuiDialogBase(); - - void Attach(GuiInstanceRootObject* _rootObject); - void Detach(GuiInstanceRootObject* _rootObject); - }; - - /// Message dialog. - class GuiMessageDialog : public GuiDialogBase, public Description - { - protected: - INativeDialogService::MessageBoxButtonsInput input = INativeDialogService::DisplayOK; - INativeDialogService::MessageBoxDefaultButton defaultButton = INativeDialogService::DefaultFirst; - INativeDialogService::MessageBoxIcons icon = INativeDialogService::IconNone; - INativeDialogService::MessageBoxModalOptions modalOption = INativeDialogService::ModalWindow; - WString text; - WString title; - - public: - /// Create a message dialog. - GuiMessageDialog(); - ~GuiMessageDialog(); - - /// Get the button combination that appear on the dialog. - /// The button combination. - INativeDialogService::MessageBoxButtonsInput GetInput(); - /// Set the button combination that appear on the dialog. - /// The button combination. - void SetInput(INativeDialogService::MessageBoxButtonsInput value); - - /// Get the default button for the selected button combination. - /// The default button. - INativeDialogService::MessageBoxDefaultButton GetDefaultButton(); - /// Set the default button for the selected button combination. - /// The default button. - void SetDefaultButton(INativeDialogService::MessageBoxDefaultButton value); - - /// Get the icon that appears on the dialog. - /// The icon. - INativeDialogService::MessageBoxIcons GetIcon(); - /// Set the icon that appears on the dialog. - /// The icon. - void SetIcon(INativeDialogService::MessageBoxIcons value); - - /// Get the way that how this dialog disable windows of the current process. - /// The way that how this dialog disable windows of the current process. - INativeDialogService::MessageBoxModalOptions GetModalOption(); - /// Set the way that how this dialog disable windows of the current process. - /// The way that how this dialog disable windows of the current process. - void SetModalOption(INativeDialogService::MessageBoxModalOptions value); - - /// Get the text for the dialog. - /// The text. - const WString& GetText(); - /// Set the text for the dialog. - /// The text. - void SetText(const WString& value); - - /// Get the title for the dialog. - /// The title. - const WString& GetTitle(); - /// Set the title for the dialog. If the title is empty, the dialog will use the title of the window that host this dialog. - /// The title. - void SetTitle(const WString& value); - - /// Show the dialog. - /// Returns the clicked button. - INativeDialogService::MessageBoxButtonsOutput ShowDialog(); - }; - - /// Color dialog. - class GuiColorDialog : public GuiDialogBase, public Description - { - protected: - bool enabledCustomColor = true; - bool openedCustomColor = false; - Color selectedColor; - bool showSelection = true; - collections::List customColors; - - public: - /// Create a color dialog. - GuiColorDialog(); - ~GuiColorDialog(); - - /// Selected color changed event. - compositions::GuiNotifyEvent SelectedColorChanged; - - /// Get if the custom color panel is enabled for the dialog. - /// Returns true if the color panel is enabled for the dialog. - bool GetEnabledCustomColor(); - /// Set if custom color panel is enabled for the dialog. - /// Set to true to enable the custom color panel for the dialog. - void SetEnabledCustomColor(bool value); - - /// Get if the custom color panel is opened by default when it is enabled. - /// Returns true if the custom color panel is opened by default. - bool GetOpenedCustomColor(); - /// Set if the custom color panel is opened by default when it is enabled. - /// Set to true to open custom color panel by default if it is enabled. - void SetOpenedCustomColor(bool value); - - /// Get the selected color. - /// The selected color. - Color GetSelectedColor(); - /// Set the selected color. - /// The selected color. - void SetSelectedColor(Color value); - - /// Get the list to access 16 selected custom colors on the palette. Colors in the list is guaranteed to have exactly 16 items after the dialog is closed. - /// The list to access custom colors on the palette. - collections::List& GetCustomColors(); - - /// Show the dialog. - /// Returns true if the "OK" button is clicked. - bool ShowDialog(); - }; - - /// Font dialog. - class GuiFontDialog : public GuiDialogBase, public Description - { - protected: - FontProperties selectedFont; - Color selectedColor; - bool showSelection = true; - bool showEffect = true; - bool forceFontExist = true; - - public: - /// Create a font dialog. - GuiFontDialog(); - ~GuiFontDialog(); - - /// Selected font changed event. - compositions::GuiNotifyEvent SelectedFontChanged; - /// Selected color changed event. - compositions::GuiNotifyEvent SelectedColorChanged; - - /// Get the selected font. - /// The selected font. - const FontProperties& GetSelectedFont(); - /// Set the selected font. - /// The selected font. - void SetSelectedFont(const FontProperties& value); - - /// Get the selected color. - /// The selected color. - Color GetSelectedColor(); - /// Set the selected color. - /// The selected color. - void SetSelectedColor(Color value); - - /// Get if the selected font is already selected on the dialog when it is opened. - /// Returns true if the selected font is already selected on the dialog when it is opened. - bool GetShowSelection(); - /// Set if the selected font is already selected on the dialog when it is opened. - /// Set to true to select the selected font when the dialog is opened. - void SetShowSelection(bool value); - - /// Get if the font preview is enabled. - /// Returns true if the font preview is enabled. - bool GetShowEffect(); - /// Set if the font preview is enabled. - /// Set to true to enable the font preview. - void SetShowEffect(bool value); - - /// Get if the dialog only accepts an existing font. - /// Returns true if the dialog only accepts an existing font. - bool GetForceFontExist(); - /// Set if the dialog only accepts an existing font. - /// Set to true to let the dialog only accept an existing font. - void SetForceFontExist(bool value); - - /// Show the dialog. - /// Returns true if the "OK" button is clicked. - bool ShowDialog(); - }; - - /// Base class for file dialogs. - class GuiFileDialogBase abstract : public GuiDialogBase, public Description - { - protected: - WString filter = L"All Files (*.*)|*.*"; - vint filterIndex = 0; - bool enabledPreview = false; - WString title; - WString fileName; - WString directory; - WString defaultExtension; - INativeDialogService::FileDialogOptions options; - - public: - GuiFileDialogBase(); - ~GuiFileDialogBase(); - - /// File name changed event. - compositions::GuiNotifyEvent FileNameChanged; - /// Filter index changed event. - compositions::GuiNotifyEvent FilterIndexChanged; - - /// Get the filter. - /// The filter. - const WString& GetFilter(); - /// Set the filter. The filter is formed by pairs of filter name and wildcard concatenated by "|", like "Text Files (*.txt)|*.txt|All Files (*.*)|*.*". - /// The filter. - void SetFilter(const WString& value); - - /// Get the filter index. - /// The filter index. - vint GetFilterIndex(); - /// Set the filter index. - /// The filter index. - void SetFilterIndex(vint value); - - /// Get if the file preview is enabled. - /// Returns true if the file preview is enabled. - bool GetEnabledPreview(); - /// Set if the file preview is enabled. - /// Set to true to enable the file preview. - void SetEnabledPreview(bool value); - - /// Get the title. - /// The title. - WString GetTitle(); - /// Set the title. - /// The title. - void SetTitle(const WString& value); - - /// Get the selected file name. - /// The selected file name. - WString GetFileName(); - /// Set the selected file name. - /// The selected file name. - void SetFileName(const WString& value); - - /// Get the default folder. - /// The default folder. - WString GetDirectory(); - /// Set the default folder. - /// The default folder. - void SetDirectory(const WString& value); - - /// Get the default file extension. - /// The default file extension. - WString GetDefaultExtension(); - /// Set the default file extension like "txt". If the user does not specify a file extension, the default file extension will be appended using "." after the file name. - /// The default file extension. - void SetDefaultExtension(const WString& value); - - /// Get the dialog options. - /// The dialog options. - INativeDialogService::FileDialogOptions GetOptions(); - /// Set the dialog options. - /// The dialog options. - void SetOptions(INativeDialogService::FileDialogOptions value); - }; - - /// Open file dialog. - class GuiOpenFileDialog : public GuiFileDialogBase, public Description - { - protected: - collections::List fileNames; - - public: - /// Create a open file dialog. - GuiOpenFileDialog(); - ~GuiOpenFileDialog(); - - /// Get the list to access multiple selected file names. - /// The list to access multiple selected file names. - collections::List& GetFileNames(); - - /// Show the dialog. - /// Returns true if the "Open" button is clicked. - bool ShowDialog(); - }; - - /// Save file dialog. - class GuiSaveFileDialog : public GuiFileDialogBase, public Description - { - public: - /// Create a save file dialog. - GuiSaveFileDialog(); - ~GuiSaveFileDialog(); - - /// Show the dialog. - /// Returns true if the "Save" button is clicked. - bool ShowDialog(); - }; - } - } -} - -#endif - - -/*********************************************************************** -.\CONTROLS\GUILABELCONTROLS.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUILABELCONTROLS -#define VCZH_PRESENTATION_CONTROLS_GUILABELCONTROLS - - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -Label -***********************************************************************/ - - /// A control to display a text. - class GuiLabel : public GuiControl, public Description - { - GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(LabelTemplate, GuiControl) - protected: - Color textColor; - bool textColorConsisted = true; - - public: - /// Create a control with a specified default theme. - /// The theme name for retriving a default control template. - GuiLabel(theme::ThemeName themeName); - ~GuiLabel(); - - /// Get the text color. - /// The text color. - Color GetTextColor(); - /// Set the text color. - /// The text color. - void SetTextColor(Color value); - }; - } - } -} - -#endif - - /*********************************************************************** .\CONTROLS\GUISCROLLCONTROLS.H ***********************************************************************/ @@ -11154,714 +12176,6 @@ Scroll View #endif -/*********************************************************************** -.\CONTROLS\GUIWINDOWCONTROLS.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUIWINDOWCONTROLS -#define VCZH_PRESENTATION_CONTROLS_GUIWINDOWCONTROLS - - -namespace vl -{ - namespace presentation - { - namespace compositions - { - class IGuiShortcutKeyManager; - class GuiGraphicsTimerManager; - } - - namespace controls - { - -/*********************************************************************** -Control Host -***********************************************************************/ - - /// - /// Represents a control that host by a . - /// - class GuiControlHost : public GuiControl, public GuiInstanceRootObject, protected INativeWindowListener, public Description - { - friend class compositions::GuiGraphicsHost; - protected: - compositions::GuiGraphicsHost* host; - INativeWindow::WindowMode windowMode = INativeWindow::Normal; - - virtual void OnNativeWindowChanged(); - virtual void OnVisualStatusChanged(); - protected: - static const vint TooltipDelayOpenTime = 500; - static const vint TooltipDelayCloseTime = 500; - static const vint TooltipDelayLifeTime = 5000; - - Ptr tooltipOpenDelay; - Ptr tooltipCloseDelay; - Point tooltipLocation; - - bool calledDestroyed = false; - bool deleteWhenDestroyed = false; - - controls::GuiControlHost* GetControlHostForInstance()override; - GuiControl* GetTooltipOwner(Point location); - void MoveIntoTooltipControl(GuiControl* tooltipControl, Point location); - void MouseMoving(const NativeWindowMouseInfo& info)override; - void MouseLeaved()override; - void Moved()override; - void Enabled()override; - void Disabled()override; - void GotFocus()override; - void LostFocus()override; - void Activated()override; - void Deactivated()override; - void Opened()override; - void Closing(bool& cancel)override; - void Closed()override; - void Destroying()override; - - virtual void UpdateClientSizeAfterRendering(Size preferredSize, Size clientSize); - public: - /// Create a control with a specified default theme. - /// The theme name for retriving a default control template. - /// The window mode. - GuiControlHost(theme::ThemeName themeName, INativeWindow::WindowMode mode); - ~GuiControlHost(); - - /// Window got focus event. - compositions::GuiNotifyEvent WindowGotFocus; - /// Window lost focus event. - compositions::GuiNotifyEvent WindowLostFocus; - /// Window activated event. - compositions::GuiNotifyEvent WindowActivated; - /// Window deactivated event. - compositions::GuiNotifyEvent WindowDeactivated; - /// Window opened event. - compositions::GuiNotifyEvent WindowOpened; - /// Window closing event. - compositions::GuiRequestEvent WindowClosing; - /// Window closed event. - compositions::GuiNotifyEvent WindowClosed; - /// Window destroying event. - compositions::GuiNotifyEvent WindowDestroying; - - /// Delete this control host after processing all events. - void DeleteAfterProcessingAllEvents(); - - /// Get the internal object to host the window content. - /// The internal object to host the window content. - compositions::GuiGraphicsHost* GetGraphicsHost(); - /// Get the main composition to host the window content. - /// The main composition to host the window content. - compositions::GuiGraphicsComposition* GetMainComposition(); - /// Get the internal object to host the content. - /// The the internal object to host the content. - INativeWindow* GetNativeWindow(); - /// Set the internal object to host the content. - /// The the internal object to host the content. - void SetNativeWindow(INativeWindow* window); - /// Force to calculate layout and size immediately - void ForceCalculateSizeImmediately(); - - /// Test is the window enabled. - /// Returns true if the window is enabled. - bool GetEnabled()override; - /// Enable or disable the window. - /// Set to true to enable the window. - void SetEnabled(bool value)override; - /// Test is the window focused. - /// Returns true if the window is focused. - bool GetFocused()override; - /// Focus the window. A window with activation disabled cannot receive focus. - void SetFocused(); - /// Test is the window activated. - /// Returns true if the window is activated. - bool GetActivated(); - /// Activate the window. If the window disabled activation, this function enables it again. - void SetActivated(); - /// Test is the window icon shown in the task bar. - /// Returns true if the window is icon shown in the task bar. - bool GetShowInTaskBar(); - /// Show or hide the window icon in the task bar. - /// Set to true to show the window icon in the task bar. - void SetShowInTaskBar(bool value); - /// Test is the window allowed to be activated. - /// Returns true if the window is allowed to be activated. - bool GetEnabledActivate(); - /// - /// Allow or forbid the window to be activated. - /// Clicking a window with activation disabled doesn't bring activation and focus. - /// Activation will be automatically enabled by calling or . - /// - /// Set to true to allow the window to be activated. - void SetEnabledActivate(bool value); - /// - /// Test is the window always on top of the desktop. - /// - /// Returns true if the window is always on top of the desktop. - bool GetTopMost(); - /// - /// Make the window always or never on top of the desktop. - /// - /// True to make the window always on top of the desktop. - void SetTopMost(bool topmost); - - /// Get the attached with this control host. - /// The shortcut key manager. - compositions::IGuiShortcutKeyManager* GetShortcutKeyManager(); - /// Attach or detach the associated with this control host. When this control host is disposing, the associated shortcut key manager will be deleted if exists. - /// The shortcut key manager. Set to null to detach the previous shortcut key manager from this control host. - void SetShortcutKeyManager(compositions::IGuiShortcutKeyManager* value); - /// Get the timer manager. - /// The timer manager. - compositions::GuiGraphicsTimerManager* GetTimerManager(); - - /// Get the client size of the window. - /// The client size of the window. - Size GetClientSize(); - /// Set the client size of the window. - /// The client size of the window. - void SetClientSize(Size value); - /// Get the location of the window in screen space. - /// The location of the window. - NativePoint GetLocation(); - /// Set the location of the window in screen space. - /// The location of the window. - void SetLocation(NativePoint value); - /// Set the location in screen space and the client size of the window. - /// The location of the window. - /// The client size of the window. - void SetBounds(NativePoint location, Size size); - - GuiControlHost* GetRelatedControlHost()override; - const WString& GetText()override; - void SetText(const WString& value)override; - - /// Get the screen that contains the window. - /// The screen that contains the window. - INativeScreen* GetRelatedScreen(); - /// - /// Show the window. - /// If the window disabled activation, this function enables it again. - /// - void Show(); - /// - /// Show the window without activation. - /// - void ShowDeactivated(); - /// - /// Restore the window. - /// - void ShowRestored(); - /// - /// Maximize the window. - /// - void ShowMaximized(); - /// - /// Minimize the window. - /// - void ShowMinimized(); - /// - /// Hide the window. - /// - void Hide(); - /// - /// Close the window and destroy the internal object. - /// - void Close(); - /// Test is the window opened. - /// Returns true if the window is opened. - bool GetOpening(); - }; - -/*********************************************************************** -Window -***********************************************************************/ - - /// - /// Represents a normal window. - /// - class GuiWindow : public GuiControlHost, protected compositions::GuiAltActionHostBase, public AggregatableDescription - { - GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(WindowTemplate, GuiControlHost) - friend class GuiApplication; - protected: - compositions::IGuiAltActionHost* previousAltHost = nullptr; - bool hasMaximizedBox = true; - bool hasMinimizedBox = true; - bool hasBorder = true; - bool hasSizeBox = true; - bool isIconVisible = true; - bool hasTitleBar = true; - Ptr icon; - - void UpdateCustomFramePadding(INativeWindow* window, templates::GuiWindowTemplate* ct); - void SyncNativeWindowProperties(); - void Moved()override; - void DpiChanged()override; - void OnNativeWindowChanged()override; - void OnVisualStatusChanged()override; - - void OnWindowActivated(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnWindowDeactivated(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - - /// Create a control with a specified default theme and a window mode. - /// The theme name for retriving a default control template. - /// The window mode. - GuiWindow(theme::ThemeName themeName, INativeWindow::WindowMode mode); - public: - /// Create a control with a specified default theme. - /// The theme name for retriving a default control template. - GuiWindow(theme::ThemeName themeName); - ~GuiWindow(); - - IDescriptable* QueryService(const WString& identifier)override; - - /// Clipboard updated event. - compositions::GuiNotifyEvent ClipboardUpdated; - - /// Move the window to the center of the screen. If multiple screens exist, the window move to the screen that contains the biggest part of the window. - void MoveToScreenCenter(); - /// Move the window to the center of the specified screen. - /// The screen. - void MoveToScreenCenter(INativeScreen* screen); - - /// - /// Test is the maximize box visible. - /// - /// Returns true if the maximize box is visible. - bool GetMaximizedBox(); - /// - /// Make the maximize box visible or invisible. - /// - /// True to make the maximize box visible. - void SetMaximizedBox(bool visible); - /// - /// Test is the minimize box visible. - /// - /// Returns true if the minimize box is visible. - bool GetMinimizedBox(); - /// - /// Make the minimize box visible or invisible. - /// - /// True to make the minimize box visible. - void SetMinimizedBox(bool visible); - /// - /// Test is the border visible. - /// - /// Returns true if the border is visible. - bool GetBorder(); - /// - /// Make the border visible or invisible. - /// - /// True to make the border visible. - void SetBorder(bool visible); - /// - /// Test is the size box visible. - /// - /// Returns true if the size box is visible. - bool GetSizeBox(); - /// - /// Make the size box visible or invisible. - /// - /// True to make the size box visible. - void SetSizeBox(bool visible); - /// - /// Test is the icon visible. - /// - /// Returns true if the icon is visible. - bool GetIconVisible(); - /// - /// Make the icon visible or invisible. - /// - /// True to make the icon visible. - void SetIconVisible(bool visible); - /// - /// Get the icon which replaces the default one. - /// - /// Returns the icon that replaces the default one. - Ptr GetIcon(); - /// - /// Set the icon that replaces the default one. - /// - /// The icon that replaces the default one. - void SetIcon(Ptr value); - /// - /// Test is the title bar visible. - /// - /// Returns true if the title bar is visible. - bool GetTitleBar(); - /// - /// Make the title bar visible or invisible. - /// - /// True to make the title bar visible. - void SetTitleBar(bool visible); - /// - /// Show a model window, get a callback when the window is closed. - /// - /// The window to disable as a parent window. - /// The callback to call after the window is closed. - void ShowModal(GuiWindow* owner, const Func& callback); - /// - /// Show a model window, get a callback when the window is closed, and then delete itself. - /// - /// The window to disable as a parent window. - /// The callback to call after the window is closed. - void ShowModalAndDelete(GuiWindow* owner, const Func& callback); - /// - /// Show a model window as an async operation, which ends when the window is closed. - /// - /// Returns true if the size box is visible. - /// The window to disable as a parent window. - Ptr ShowModalAsync(GuiWindow* owner); - }; - - /// - /// Represents a popup window. When the mouse click on other window or the desktop, the popup window will be closed automatically. - /// - class GuiPopup : public GuiWindow, public Description - { - protected: - union PopupInfo - { - struct _s1 { NativePoint location; INativeScreen* screen; }; - struct _s2 { GuiControl* control; INativeWindow* controlWindow; Rect bounds; bool preferredTopBottomSide; }; - struct _s3 { GuiControl* control; INativeWindow* controlWindow; Point location; }; - struct _s4 { GuiControl* control; INativeWindow* controlWindow; bool preferredTopBottomSide; }; - - _s1 _1; - _s2 _2; - _s3 _3; - _s4 _4; - - PopupInfo() {} - }; - protected: - vint popupType = -1; - PopupInfo popupInfo; - - void UpdateClientSizeAfterRendering(Size preferredSize, Size clientSize)override; - void PopupOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void PopupClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments); - - static bool IsClippedByScreen(NativeSize size, NativePoint location, INativeScreen* screen); - static NativePoint CalculatePopupPosition(NativeSize windowSize, NativePoint location, INativeScreen* screen); - static NativePoint CalculatePopupPosition(NativeSize windowSize, GuiControl* control, INativeWindow* controlWindow, Rect bounds, bool preferredTopBottomSide); - static NativePoint CalculatePopupPosition(NativeSize windowSize, GuiControl* control, INativeWindow* controlWindow, Point location); - static NativePoint CalculatePopupPosition(NativeSize windowSize, GuiControl* control, INativeWindow* controlWindow, bool preferredTopBottomSide); - static NativePoint CalculatePopupPosition(NativeSize windowSize, vint popupType, const PopupInfo& popupInfo); - - void ShowPopupInternal(); - - /// Create a control with a specified default theme and a window mode. - /// The theme name for retriving a default control template. - /// The window mode. - GuiPopup(theme::ThemeName themeName, INativeWindow::WindowMode mode); - public: - /// Create a control with a specified default theme. - /// The theme name for retriving a default control template. - GuiPopup(theme::ThemeName themeName); - ~GuiPopup(); - - /// Test will the whole popup window be in the screen if the popup's left-top position is set to a specified value. - /// Returns true if the whole popup window will be in the screen. - /// The specified left-top position. - bool IsClippedByScreen(Point location); - /// Show the popup window with the left-top position set to a specified value. The position of the popup window will be adjusted to make it totally inside the screen if possible. - /// The specified left-top position. - /// The expected screen. If you don't want to specify any screen, don't set this parameter. - void ShowPopup(NativePoint location, INativeScreen* screen = 0); - /// Show the popup window with the bounds set to a specified control-relative value. The position of the popup window will be adjusted to make it totally inside the screen if possible. - /// The control that owns this popup temporary. And the location is relative to this control. - /// The specified bounds. - /// Set to true if the popup window is expected to be opened at the top or bottom side of that bounds. - void ShowPopup(GuiControl* control, Rect bounds, bool preferredTopBottomSide); - /// Show the popup window with the left-top position set to a specified control-relative value. The position of the popup window will be adjusted to make it totally inside the screen if possible. - /// The control that owns this popup temporary. And the location is relative to this control. - /// The specified left-top position. - void ShowPopup(GuiControl* control, Point location); - /// Show the popup window aligned with a specified control. The position of the popup window will be adjusted to make it totally inside the screen if possible. - /// The control that owns this popup temporary. - /// Set to true if the popup window is expected to be opened at the top or bottom side of that control. - void ShowPopup(GuiControl* control, bool preferredTopBottomSide); - }; - - /// Represents a tooltip window. - class GuiTooltip : public GuiPopup, private INativeControllerListener, public Description - { - protected: - GuiControl* temporaryContentControl = nullptr; - - void GlobalTimer()override; - void TooltipOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void TooltipClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - - public: - /// Create a control with a specified default theme. - /// The theme name for retriving a default control template. - GuiTooltip(theme::ThemeName themeName); - ~GuiTooltip(); - - /// Get the preferred content width. - /// The preferred content width. - vint GetPreferredContentWidth(); - /// Set the preferred content width. - /// The preferred content width. - void SetPreferredContentWidth(vint value); - - /// Get the temporary content control. - /// The temporary content control. - GuiControl* GetTemporaryContentControl(); - /// Set the temporary content control. - /// The temporary content control. - void SetTemporaryContentControl(GuiControl* control); - }; - } - } -} - -#endif - - -/*********************************************************************** -.\CONTROLS\GUIAPPLICATION.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Application Framework - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUIAPPLICATION -#define VCZH_PRESENTATION_CONTROLS_GUIAPPLICATION - - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -Application -***********************************************************************/ - - /// Represents an GacUI application, for window management and asynchronized operation supporting. Use [M:vl.presentation.controls.GetApplication] to access the instance of this class. - class GuiApplication : public Object, private INativeControllerListener, public Description - { - friend void GuiApplicationInitialize(); - friend class GuiWindow; - friend class GuiPopup; - friend class Ptr; - private: - void InvokeClipboardNotify(compositions::GuiGraphicsComposition* composition, compositions::GuiEventArgs& arguments); - void ClipboardUpdated()override; - protected: - Locale locale; - GuiWindow* mainWindow = nullptr; - GuiWindow* sharedTooltipOwnerWindow = nullptr; - GuiControl* sharedTooltipOwner = nullptr; - GuiTooltip* sharedTooltipControl = nullptr; - bool sharedTooltipHovering = false; - bool sharedTooltipClosing = false; - collections::List windows; - collections::SortedList openingPopups; - - GuiApplication(); - ~GuiApplication(); - - INativeWindow* GetThreadContextNativeWindow(GuiControlHost* controlHost); - void RegisterWindow(GuiWindow* window); - void UnregisterWindow(GuiWindow* window); - void RegisterPopupOpened(GuiPopup* popup); - void RegisterPopupClosed(GuiPopup* popup); - void TooltipMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void TooltipMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - public: - /// Locale changed event. - Event LocaleChanged; - - /// Returns the selected locale for all windows. - /// The selected locale. - Locale GetLocale(); - /// Set the locale for all windows. - /// The selected locale. - void SetLocale(Locale value); - - /// Run a as the main window and show it. This function can only be called once in the entry point. When the main window is closed or hiden, the Run function will finished, and the application should prepare for finalization. - /// The main window. - void Run(GuiWindow* _mainWindow); - /// Get the main window. - /// The main window. - GuiWindow* GetMainWindow(); - /// Get all created instances. This contains normal windows, popup windows, menus, or other types of windows that inherits from . - /// All created instances. - const collections::List& GetWindows(); - /// Get the instance that the mouse cursor are directly in. - /// The instance that the mouse cursor are directly in. - /// The mouse cursor. - GuiWindow* GetWindow(NativePoint location); - /// Show a tooltip. - /// The control that owns this tooltip temporary. - /// The control as the tooltip content. This control is not owned by the tooltip. User should manually release this control if no longer needed (usually when the application exit). - /// The preferred content width for this tooltip. - /// The relative location to specify the left-top position of the tooltip. - void ShowTooltip(GuiControl* owner, GuiControl* tooltip, vint preferredContentWidth, Point location); - /// Close the tooltip - void CloseTooltip(); - /// Get the tooltip owner. When the tooltip closed, it returns null. - /// The tooltip owner. - GuiControl* GetTooltipOwner(); - /// Get the file path of the current executable. - /// The file path of the current executable. - WString GetExecutablePath(); - /// Get the folder of the current executable. - /// The folder of the current executable. - WString GetExecutableFolder(); - - /// Test is the current thread the main thread for GUI. - /// Returns true if the current thread is the main thread for GUI. - /// A control host to access the corressponding main thread. - bool IsInMainThread(GuiControlHost* controlHost); - /// Invoke a specified function asynchronously. - /// The specified function. - void InvokeAsync(const Func& proc); - /// Invoke a specified function in the main thread. - /// A control host to access the corressponding main thread. - /// The specified function. - void InvokeInMainThread(GuiControlHost* controlHost, const Func& proc); - /// Invoke a specified function in the main thread and wait for the function to complete or timeout. - /// Return true if the function complete. Return false if the function has not completed during a specified period of time. - /// A control host to access the corressponding main thread. - /// The specified function. - /// The specified period of time to wait. Set to -1 (default value) to wait forever until the function completed. - bool InvokeInMainThreadAndWait(GuiControlHost* controlHost, const Func& proc, vint milliseconds=-1); - /// Delay execute a specified function with an specified argument asynchronisly. - /// The Delay execution controller for this task. - /// The specified function. - /// Time to delay. - Ptr DelayExecute(const Func& proc, vint milliseconds); - /// Delay execute a specified function with an specified argument in the main thread. - /// The Delay execution controller for this task. - /// The specified function. - /// Time to delay. - Ptr DelayExecuteInMainThread(const Func& proc, vint milliseconds); - /// Run the specified function in the main thread. If the caller is in the main thread, then run the specified function directly. - /// A control host to access the corressponding main thread. - /// The specified function. - void RunGuiTask(GuiControlHost* controlHost, const Func& proc); - - template - T RunGuiValue(GuiControlHost* controlHost, const Func& proc) - { - T result; - RunGuiTask(controlHost, [&result, &proc]() - { - result=proc(); - }); - return result; - } - - template - void InvokeLambdaInMainThread(GuiControlHost* controlHost, const T& proc) - { - InvokeInMainThread(controlHost, Func(proc)); - } - - template - bool InvokeLambdaInMainThreadAndWait(GuiControlHost* controlHost, const T& proc, vint milliseconds=-1) - { - return InvokeInMainThreadAndWait(controlHost, Func(proc), milliseconds); - } - }; - -/*********************************************************************** -Plugin -***********************************************************************/ - - /// Represents a plugin for the gui. - class IGuiPlugin : public IDescriptable, public Description - { - public: - /// Get the name of this plugin. - /// Returns the name of the plugin. - virtual WString GetName() = 0; - /// Get all dependencies of this plugin. - /// To receive all dependencies. - virtual void GetDependencies(collections::List& dependencies) = 0; - /// Called when the plugin manager want to load this plugin. - virtual void Load()=0; - /// Called when the plugin manager want to unload this plugin. - virtual void Unload()=0; - }; - - /// Represents a plugin manager. - class IGuiPluginManager : public IDescriptable, public Description - { - public: - /// Add a plugin before [F:vl.presentation.controls.IGuiPluginManager.Load] is called. - /// The plugin. - virtual void AddPlugin(Ptr plugin)=0; - /// Load all plugins, and check if dependencies of all plugins are ready. - virtual void Load()=0; - /// Unload all plugins. - virtual void Unload()=0; - /// Returns true if all plugins are loaded. - virtual bool IsLoaded()=0; - }; - -/*********************************************************************** -Helper Functions -***********************************************************************/ - - /// Get the global object. - /// The global object. - extern GuiApplication* GetApplication(); - - /// Get the global object. - /// The global object. - extern IGuiPluginManager* GetPluginManager(); - - /// Destroy the global object. - extern void DestroyPluginManager(); - } - } -} - -extern void GuiApplicationMain(); - -#define GUI_VALUE(x) vl::presentation::controls::GetApplication()->RunGuiValue(LAMBDA([&](){return (x);})) -#define GUI_RUN(x) vl::presentation::controls::GetApplication()->RunGuiTask([=](){x}) - -#define GUI_REGISTER_PLUGIN(TYPE)\ - class GuiRegisterPluginClass_##TYPE\ - {\ - public:\ - GuiRegisterPluginClass_##TYPE()\ - {\ - vl::presentation::controls::GetPluginManager()->AddPlugin(Ptr(new TYPE));\ - }\ - } instance_GuiRegisterPluginClass_##TYPE;\ - -#define GUI_PLUGIN_NAME(NAME)\ - vl::WString GetName()override { return L ## #NAME; }\ - void GetDependencies(vl::collections::List& dependencies)override\ - -#define GUI_PLUGIN_DEPEND(NAME) dependencies.Add(L ## #NAME) - -#endif - /*********************************************************************** .\CONTROLS\INCLUDEFORWARD.H ***********************************************************************/ @@ -13585,82 +13899,6 @@ namespace vl { namespace theme { -#define GUI_CONTROL_TEMPLATE_TYPES(F) \ - F(WindowTemplate, Window) \ - F(ControlTemplate, CustomControl) \ - F(WindowTemplate, Tooltip) \ - F(LabelTemplate, Label) \ - F(LabelTemplate, ShortcutKey) \ - F(ScrollViewTemplate, ScrollView) \ - F(ControlTemplate, GroupBox) \ - F(TabTemplate, Tab) \ - F(ComboBoxTemplate, ComboBox) \ - F(MultilineTextBoxTemplate, MultilineTextBox) \ - F(SinglelineTextBoxTemplate, SinglelineTextBox) \ - F(DocumentViewerTemplate, DocumentViewer) \ - F(DocumentLabelTemplate, DocumentLabel) \ - F(DocumentLabelTemplate, DocumentTextBox) \ - F(ListViewTemplate, ListView) \ - F(TreeViewTemplate, TreeView) \ - F(TextListTemplate, TextList) \ - F(SelectableButtonTemplate, ListItemBackground) \ - F(SelectableButtonTemplate, TreeItemExpander) \ - F(SelectableButtonTemplate, CheckTextListItem) \ - F(SelectableButtonTemplate, RadioTextListItem) \ - F(MenuTemplate, Menu) \ - F(ControlTemplate, MenuBar) \ - F(ControlTemplate, MenuSplitter) \ - F(ToolstripButtonTemplate, MenuBarButton) \ - F(ToolstripButtonTemplate, MenuItemButton) \ - F(ControlTemplate, ToolstripToolBar) \ - F(ToolstripButtonTemplate, ToolstripButton) \ - F(ToolstripButtonTemplate, ToolstripDropdownButton) \ - F(ToolstripButtonTemplate, ToolstripSplitButton) \ - F(ControlTemplate, ToolstripSplitter) \ - F(RibbonTabTemplate, RibbonTab) \ - F(RibbonGroupTemplate, RibbonGroup) \ - F(RibbonIconLabelTemplate, RibbonIconLabel) \ - F(RibbonIconLabelTemplate, RibbonSmallIconLabel) \ - F(RibbonButtonsTemplate, RibbonButtons) \ - F(RibbonToolstripsTemplate, RibbonToolstrips) \ - F(RibbonGalleryTemplate, RibbonGallery) \ - F(RibbonToolstripMenuTemplate, RibbonToolstripMenu) \ - F(RibbonGalleryListTemplate, RibbonGalleryList) \ - F(TextListTemplate, RibbonGalleryItemList) \ - F(ToolstripButtonTemplate, RibbonSmallButton) \ - F(ToolstripButtonTemplate, RibbonSmallDropdownButton) \ - F(ToolstripButtonTemplate, RibbonSmallSplitButton) \ - F(ToolstripButtonTemplate, RibbonLargeButton) \ - F(ToolstripButtonTemplate, RibbonLargeDropdownButton) \ - F(ToolstripButtonTemplate, RibbonLargeSplitButton) \ - F(ControlTemplate, RibbonSplitter) \ - F(ControlTemplate, RibbonToolstripHeader) \ - F(ButtonTemplate, Button) \ - F(SelectableButtonTemplate, CheckBox) \ - F(SelectableButtonTemplate, RadioButton) \ - F(DatePickerTemplate, DatePicker) \ - F(DateComboBoxTemplate, DateComboBox) \ - F(ScrollTemplate, HScroll) \ - F(ScrollTemplate, VScroll) \ - F(ScrollTemplate, HTracker) \ - F(ScrollTemplate, VTracker) \ - F(ScrollTemplate, ProgressBar) \ - - enum class ThemeName - { - Unknown, -#define GUI_DEFINE_THEME_NAME(TEMPLATE, CONTROL) CONTROL, - GUI_CONTROL_TEMPLATE_TYPES(GUI_DEFINE_THEME_NAME) -#undef GUI_DEFINE_THEME_NAME - }; - - /// Theme interface. A theme creates appropriate style controllers or style providers for default controls. Call [M:vl.presentation.theme.GetCurrentTheme] to access this interface. - class ITheme : public virtual IDescriptable, public Description - { - public: - virtual TemplateProperty CreateStyle(ThemeName themeName) = 0; - }; - class Theme; /// Partial control template collections. [F:vl.presentation.theme.GetCurrentTheme] will returns an object, which walks through multiple registered [T:vl.presentation.theme.ThemeTemplates] to create a correct template object for a control. @@ -13682,11 +13920,6 @@ namespace vl #undef GUI_DEFINE_ITEM_PROPERTY }; - /// Get the current theme style factory object. Call or to change the default theme. - /// The current theme style factory object. - extern ITheme* GetCurrentTheme(); - extern void InitializeTheme(); - extern void FinalizeTheme(); /// Register a control template collection object. /// Returns true if this operation succeeded. /// The control template collection object. @@ -18355,128 +18588,6 @@ GalleryItemArranger #endif -/*********************************************************************** -.\CONTROLS\TOOLSTRIPPACKAGE\GUITOOLSTRIPCOMMAND.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUITOOLSTRIPCOMMAND -#define VCZH_PRESENTATION_CONTROLS_GUITOOLSTRIPCOMMAND - - -namespace vl -{ - namespace presentation - { - namespace compositions - { - class IGuiShortcutKeyItem; - } - - namespace controls - { - /// A command for toolstrip controls. - class GuiToolstripCommand : public GuiComponent, public Description - { - public: - class ShortcutBuilder : public Object - { - public: - WString text; - bool ctrl; - bool shift; - bool alt; - VKEY key; - }; - protected: - Ptr image; - Ptr largeImage; - WString text; - compositions::IGuiShortcutKeyItem* shortcutKeyItem = nullptr; - bool enabled = true; - bool selected = false; - Ptr shortcutKeyItemExecutedHandler; - Ptr shortcutBuilder; - - GuiInstanceRootObject* attachedRootObject = nullptr; - Ptr renderTargetChangedHandler; - GuiControlHost* shortcutOwner = nullptr; - - void OnShortcutKeyItemExecuted(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnRenderTargetChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void InvokeDescriptionChanged(); - void ReplaceShortcut(compositions::IGuiShortcutKeyItem* value, Ptr builder); - void BuildShortcut(const WString& builderText); - void UpdateShortcutOwner(); - public: - /// Create the command. - GuiToolstripCommand(); - ~GuiToolstripCommand(); - - void Attach(GuiInstanceRootObject* rootObject)override; - void Detach(GuiInstanceRootObject* rootObject)override; - - /// Executed event. - compositions::GuiNotifyEvent Executed; - - /// Description changed event, raised when any description property is modified. - compositions::GuiNotifyEvent DescriptionChanged; - - /// Get the large image for this command. - /// The large image for this command. - Ptr GetLargeImage(); - /// Set the large image for this command. - /// The large image for this command. - void SetLargeImage(Ptr value); - /// Get the image for this command. - /// The image for this command. - Ptr GetImage(); - /// Set the image for this command. - /// The image for this command. - void SetImage(Ptr value); - /// Get the text for this command. - /// The text for this command. - const WString& GetText(); - /// Set the text for this command. - /// The text for this command. - void SetText(const WString& value); - /// Get the shortcut key item for this command. - /// The shortcut key item for this command. - compositions::IGuiShortcutKeyItem* GetShortcut(); - /// Set the shortcut key item for this command. - /// The shortcut key item for this command. - void SetShortcut(compositions::IGuiShortcutKeyItem* value); - /// Get the shortcut builder for this command. - /// The shortcut builder for this command. - WString GetShortcutBuilder(); - /// Set the shortcut builder for this command. When the command is attached to a window as a component without a shortcut, the command will try to convert the shortcut builder to a shortcut key item. - /// The shortcut builder for this command. - void SetShortcutBuilder(const WString& value); - /// Get the enablility for this command. - /// The enablility for this command. - bool GetEnabled(); - /// Set the enablility for this command. - /// The enablility for this command. - void SetEnabled(bool value); - /// Get the selection for this command. - /// The selection for this command. - bool GetSelected(); - /// Set the selection for this command. - /// The selection for this command. - void SetSelected(bool value); - }; - } - } -} - -#endif - /*********************************************************************** .\CONTROLS\TOOLSTRIPPACKAGE\GUITOOLSTRIPMENU.H ***********************************************************************/