/*********************************************************************** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY DEVELOPER: Zihan Chen(vczh) ***********************************************************************/ #include "GacUI.h" /*********************************************************************** GACUIREFLECTIONHELPER.CPP ***********************************************************************/ namespace vl { namespace reflection { namespace description { using namespace parsing; using namespace parsing::tabling; using namespace parsing::xml; using namespace stream; using namespace collections; using namespace presentation; using namespace presentation::elements; using namespace presentation::compositions; using namespace presentation::controls; using namespace presentation::theme; using namespace presentation::templates; /*********************************************************************** Serialization (Color) ***********************************************************************/ Color TypedValueSerializerProvider::GetDefaultValue() { return Color(); } bool TypedValueSerializerProvider::Serialize(const Color& input, WString& output) { output = input.ToString(); return true; } bool TypedValueSerializerProvider::Deserialize(const WString& input, Color& output) { output = Color::Parse(input); return true; } IValueType::CompareResult TypedValueSerializerProvider::Compare(const presentation::Color& a, const presentation::Color& b) { return TypedValueSerializerProvider::Compare(a.value, b.value); } /*********************************************************************** Serialization (DocumentFontSize) ***********************************************************************/ DocumentFontSize TypedValueSerializerProvider::GetDefaultValue() { return DocumentFontSize(); } bool TypedValueSerializerProvider::Serialize(const DocumentFontSize& input, WString& output) { output = input.ToString(); return true; } bool TypedValueSerializerProvider::Deserialize(const WString& input, DocumentFontSize& output) { output = DocumentFontSize::Parse(input); return true; } IValueType::CompareResult TypedValueSerializerProvider::Compare(const presentation::DocumentFontSize& a, const presentation::DocumentFontSize& b) { return TypedValueSerializerProvider::Compare(a.ToString(), b.ToString()); } /*********************************************************************** Serialization (GlobalStringKey) ***********************************************************************/ GlobalStringKey TypedValueSerializerProvider::GetDefaultValue() { return GlobalStringKey(); } bool TypedValueSerializerProvider::Serialize(const GlobalStringKey& input, WString& output) { output = input.ToString(); return true; } bool TypedValueSerializerProvider::Deserialize(const WString& input, GlobalStringKey& output) { output = GlobalStringKey::Get(input); return true; } IValueType::CompareResult TypedValueSerializerProvider::Compare(const presentation::GlobalStringKey& a, const presentation::GlobalStringKey& b) { return TypedValueSerializerProvider::Compare(a.ToString(), b.ToString()); } /*********************************************************************** External Functions (Basic) ***********************************************************************/ GuiGraphicsAnimationManager* GuiControlHost_GetAnimationManager(GuiControlHost* thisObject) { return thisObject->GetGraphicsHost()->GetAnimationManager(); } Ptr INativeImage_Constructor(const WString& path) { return GetCurrentController()->ImageService()->CreateImageFromFile(path); } INativeCursor* INativeCursor_Constructor1() { return GetCurrentController()->ResourceService()->GetDefaultSystemCursor(); } INativeCursor* INativeCursor_Constructor2(INativeCursor::SystemCursorType type) { return GetCurrentController()->ResourceService()->GetSystemCursor(type); } Ptr DocumentModel_Constructor(const WString& path) { FileStream fileStream(path, FileStream::ReadOnly); if (!fileStream.IsAvailable()) return 0; BomDecoder decoder; DecoderStream decoderStream(fileStream, decoder); StreamReader reader(decoderStream); WString xmlText = reader.ReadToEnd(); Ptr table = XmlLoadTable(); Ptr xml = XmlParseDocument(xmlText, table); if (!xml) return 0; List errors; return DocumentModel::LoadFromXml(xml, GetFolderPath(path), errors); } /*********************************************************************** External Functions (Elements) ***********************************************************************/ text::TextLines* GuiColorizedTextElement_GetLines(GuiColorizedTextElement* thisObject) { return &thisObject->GetLines(); } /*********************************************************************** External Functions (Compositions) ***********************************************************************/ void GuiTableComposition_SetRows(GuiTableComposition* thisObject, vint value) { vint columns = thisObject->GetColumns(); if (columns <= 0) columns = 1; thisObject->SetRowsAndColumns(value, columns); } void GuiTableComposition_SetColumns(GuiTableComposition* thisObject, vint value) { vint row = thisObject->GetRows(); if (row <= 0) row = 1; thisObject->SetRowsAndColumns(row, value); } void IGuiAltActionHost_CollectAltActions(IGuiAltActionHost* host, List& actions) { Group group; host->CollectAltActions(group); for (vint i = 0; i < group.Count(); i++) { CopyFrom(actions, group.GetByIndex(i), true); } } /*********************************************************************** External Functions (Controls) ***********************************************************************/ Ptr CreateWin7Theme() { return new win7::Win7Theme(); } Ptr CreateWin8Theme() { return new win8::Win8Theme(); } list::ListViewItemStyleProvider::IListViewItemContent* ListViewItemStyleProvider_GetItemContent(list::ListViewItemStyleProvider* thisObject, GuiListControl::IItemStyleController* itemStyleController) { return thisObject->GetItemContent(itemStyleController); } list::StringGridProvider* GuiStringGrid_GetGrids(GuiStringGrid* grid) { return &grid->Grids(); } } } } /*********************************************************************** CONTROLS\GUIAPPLICATION.CPP ***********************************************************************/ extern void GuiMain(); namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace compositions; using namespace theme; using namespace description; /*********************************************************************** GuiApplication ***********************************************************************/ void GuiApplication::InvokeClipboardNotify(compositions::GuiGraphicsComposition* composition, compositions::GuiEventArgs& arguments) { if(composition->HasEventReceiver()) { composition->GetEventReceiver()->clipboardNotify.Execute(arguments); } FOREACH(GuiGraphicsComposition*, subComposition, composition->Children()) { InvokeClipboardNotify(subComposition, arguments); } } void GuiApplication::LeftButtonDown(Point position) { OnMouseDown(position); } void GuiApplication::LeftButtonUp(Point position) { } void GuiApplication::RightButtonDown(Point position) { OnMouseDown(position); } void GuiApplication::RightButtonUp(Point position) { } void GuiApplication::ClipboardUpdated() { for(vint i=0;iGetNotifyEventArguments(); windows[i]->ClipboardUpdated.Execute(arguments); InvokeClipboardNotify(windows[i]->GetBoundsComposition(), arguments); } } GuiApplication::GuiApplication() :mainWindow(0) ,sharedTooltipOwnerWindow(0) ,sharedTooltipOwner(0) ,sharedTooltipControl(0) ,sharedTooltipHovering(false) ,sharedTooltipClosing(false) { GetCurrentController()->CallbackService()->InstallListener(this); } GuiApplication::~GuiApplication() { if(sharedTooltipControl) { delete sharedTooltipControl; sharedTooltipControl=0; } GetCurrentController()->CallbackService()->UninstallListener(this); } void GuiApplication::RegisterWindow(GuiWindow* window) { windows.Add(window); } void GuiApplication::UnregisterWindow(GuiWindow* window) { windows.Remove(window); } void GuiApplication::RegisterPopupOpened(GuiPopup* popup) { vint index=openingPopups.IndexOf(popup); if(index==-1) { openingPopups.Add(popup); if(openingPopups.Count()==1) { GetCurrentController()->InputService()->StartHookMouse(); } } } void GuiApplication::RegisterPopupClosed(GuiPopup* popup) { if(openingPopups.Remove(popup)) { if(openingPopups.Count()==0) { GetCurrentController()->InputService()->StopHookMouse(); } } } void GuiApplication::OnMouseDown(Point location) { GuiWindow* window=GetWindow(location); for(vint i=0;iMouseClickedOnOtherWindow(window); } } } void GuiApplication::TooltipMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { sharedTooltipHovering=true; } void GuiApplication::TooltipMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { sharedTooltipHovering=false; if(sharedTooltipClosing) { CloseTooltip(); } } void GuiApplication::Run(GuiWindow* _mainWindow) { if(!mainWindow) { mainWindow=_mainWindow; GetCurrentController()->WindowService()->Run(mainWindow->GetNativeWindow()); mainWindow=0; } } GuiWindow* GuiApplication::GetMainWindow() { return mainWindow; } const collections::List& GuiApplication::GetWindows() { return windows; } GuiWindow* GuiApplication::GetWindow(Point location) { INativeWindow* nativeWindow=GetCurrentController()->WindowService()->GetWindow(location); if(nativeWindow) { for(vint i=0;iGetNativeWindow()==nativeWindow) { return window; } } } return 0; } void GuiApplication::ShowTooltip(GuiControl* owner, GuiControl* tooltip, vint preferredContentWidth, Point location) { GuiWindow* ownerWindow = dynamic_cast(owner->GetRelatedControlHost()); if (sharedTooltipOwnerWindow != ownerWindow) { delete sharedTooltipControl; sharedTooltipControl = 0; } if(!sharedTooltipControl) { GuiWindow::IStyleController* tooltipStyle = 0; if (ownerWindow) { tooltipStyle = dynamic_cast(ownerWindow->GetStyleController())->CreateTooltipStyle(); } if (!tooltipStyle) { tooltipStyle = GetCurrentTheme()->CreateTooltipStyle(); } sharedTooltipControl=new GuiTooltip(tooltipStyle); sharedTooltipControl->GetBoundsComposition()->GetEventReceiver()->mouseEnter.AttachMethod(this, &GuiApplication::TooltipMouseEnter); sharedTooltipControl->GetBoundsComposition()->GetEventReceiver()->mouseLeave.AttachMethod(this, &GuiApplication::TooltipMouseLeave); } sharedTooltipHovering=false; sharedTooltipClosing=false; sharedTooltipOwnerWindow = ownerWindow; sharedTooltipOwner=owner; sharedTooltipControl->SetTemporaryContentControl(tooltip); sharedTooltipControl->SetPreferredContentWidth(preferredContentWidth); sharedTooltipControl->SetClientSize(Size(10, 10)); sharedTooltipControl->ShowPopup(owner, location); } void GuiApplication::CloseTooltip() { if(sharedTooltipControl) { if(sharedTooltipHovering) { sharedTooltipClosing=true; } else { sharedTooltipClosing=false; sharedTooltipControl->Close(); } } } GuiControl* GuiApplication::GetTooltipOwner() { if(!sharedTooltipControl) return 0; if(!sharedTooltipControl->GetTemporaryContentControl()) return 0; return sharedTooltipOwner; } WString GuiApplication::GetExecutablePath() { return GetCurrentController()->GetExecutablePath(); } WString GuiApplication::GetExecutableFolder() { WString path=GetExecutablePath(); for(vint i=path.Length()-1;i>=0;i--) { if(path[i]==L'\\' || path[i]==L'/') { return path.Sub(0, i+1); } } return L""; } bool GuiApplication::IsInMainThread() { return GetCurrentController()->AsyncService()->IsInMainThread(); } void GuiApplication::InvokeAsync(const Func& proc) { GetCurrentController()->AsyncService()->InvokeAsync(proc); } void GuiApplication::InvokeInMainThread(const Func& proc) { GetCurrentController()->AsyncService()->InvokeInMainThread(proc); } bool GuiApplication::InvokeInMainThreadAndWait(const Func& proc, vint milliseconds) { return GetCurrentController()->AsyncService()->InvokeInMainThreadAndWait(proc, milliseconds); } Ptr GuiApplication::DelayExecute(const Func& proc, vint milliseconds) { return GetCurrentController()->AsyncService()->DelayExecute(proc, milliseconds); } Ptr GuiApplication::DelayExecuteInMainThread(const Func& proc, vint milliseconds) { return GetCurrentController()->AsyncService()->DelayExecuteInMainThread(proc, milliseconds); } void GuiApplication::RunGuiTask(const Func& proc) { if(IsInMainThread()) { return proc(); } else { InvokeInMainThreadAndWait([&proc]() { proc(); }); } } /*********************************************************************** GuiPluginManager ***********************************************************************/ class GuiPluginManager : public Object, public IGuiPluginManager { protected: List> plugins; bool loaded; public: GuiPluginManager() :loaded(false) { } ~GuiPluginManager() { Unload(); } void AddPlugin(Ptr plugin)override { plugins.Add(plugin); if(loaded) { plugin->Load(); } } void Load()override { if(!loaded) { loaded=true; FOREACH(Ptr, plugin, plugins) { plugin->Load(); } FOREACH(Ptr, plugin, plugins) { plugin->AfterLoad(); } } } void Unload()override { if(loaded) { loaded=false; FOREACH(Ptr, 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 ***********************************************************************/ void GuiApplicationInitialize() { Ptr theme; { WString osVersion=GetCurrentController()->GetOSVersion(); vint index=osVersion.IndexOf(L';'); if (index == -1) { theme=new win8::Win8Theme; } else { WString osMainVersion=osVersion.Sub(0, index); if(osMainVersion==L"Windows 8" || osMainVersion==L"Windows Server 2012") { theme=new win8::Win8Theme; } else { theme=new win7::Win7Theme; } } } GetCurrentController()->InputService()->StartTimer(); GuiApplication app; application=&app; GetGlobalTypeManager()->Load(); GetPluginManager()->Load(); theme::SetCurrentTheme(theme.Obj()); GuiMain(); theme::SetCurrentTheme(0); DestroyPluginManager(); DestroyGlobalTypeManager(); ThreadLocalStorage::DisposeStorages(); } } } } void GuiApplicationMain() { vl::presentation::controls::GuiApplicationInitialize(); } /*********************************************************************** CONTROLS\GUIBASICCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace compositions; using namespace collections; using namespace reflection::description; /*********************************************************************** GuiControl::EmptyStyleController ***********************************************************************/ GuiControl::EmptyStyleController::EmptyStyleController() { boundsComposition=new GuiBoundsComposition; } GuiControl::EmptyStyleController::~EmptyStyleController() { } compositions::GuiBoundsComposition* GuiControl::EmptyStyleController::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* GuiControl::EmptyStyleController::GetContainerComposition() { return boundsComposition; } void GuiControl::EmptyStyleController::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void GuiControl::EmptyStyleController::SetText(const WString& value) { } void GuiControl::EmptyStyleController::SetFont(const FontProperties& value) { } void GuiControl::EmptyStyleController::SetVisuallyEnabled(bool value) { } /*********************************************************************** GuiControl ***********************************************************************/ void GuiControl::OnChildInserted(GuiControl* control) { GuiControl* oldParent=control->parent; children.Add(control); control->parent=this; control->OnParentChanged(oldParent, control->parent); control->UpdateVisuallyEnabled(); } void GuiControl::OnChildRemoved(GuiControl* control) { GuiControl* oldParent=control->parent; control->parent=0; children.Remove(control); control->OnParentChanged(oldParent, control->parent); } void GuiControl::OnParentChanged(GuiControl* oldParent, GuiControl* newParent) { OnParentLineChanged(); } void GuiControl::OnParentLineChanged() { for(vint i=0;iOnParentLineChanged(); } } void GuiControl::OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget) { } void GuiControl::OnBeforeReleaseGraphicsHost() { for(vint i=0;iOnBeforeReleaseGraphicsHost(); } } void GuiControl::UpdateVisuallyEnabled() { bool newValue=isEnabled && (parent==0?true:parent->GetVisuallyEnabled()); if(isVisuallyEnabled!=newValue) { isVisuallyEnabled=newValue; styleController->SetVisuallyEnabled(isVisuallyEnabled); VisuallyEnabledChanged.Execute(GetNotifyEventArguments()); for(vint i=0;iUpdateVisuallyEnabled(); } } } void GuiControl::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { if(focusableComposition!=value) { focusableComposition=value; styleController->SetFocusableComposition(focusableComposition); } } bool GuiControl::IsAltEnabled() { GuiControl* control = this; while (control) { if (!control->GetVisible() || !control->GetEnabled()) { return false; } control = control->GetParent(); } return true; } bool GuiControl::IsAltAvailable() { return focusableComposition != 0 && alt != L""; } compositions::GuiGraphicsComposition* GuiControl::GetAltComposition() { return boundsComposition; } compositions::IGuiAltActionHost* GuiControl::GetActivatingAltHost() { return activatingAltHost; } void GuiControl::OnActiveAlt() { SetFocus(); } bool GuiControl::SharedPtrDestructorProc(DescriptableObject* obj, bool forceDisposing) { GuiControl* value=dynamic_cast(obj); if(value->GetBoundsComposition()->GetParent()) { if (!forceDisposing) return false; } SafeDeleteControl(value); return true; } GuiControl::GuiControl(IStyleController* _styleController) :styleController(_styleController) ,boundsComposition(_styleController->GetBoundsComposition()) ,focusableComposition(0) ,eventReceiver(_styleController->GetBoundsComposition()->GetEventReceiver()) ,isEnabled(true) ,isVisuallyEnabled(true) ,isVisible(true) ,activatingAltHost(0) ,parent(0) ,tooltipControl(0) ,tooltipWidth(50) { boundsComposition->SetAssociatedControl(this); VisibleChanged.SetAssociatedComposition(boundsComposition); EnabledChanged.SetAssociatedComposition(boundsComposition); VisuallyEnabledChanged.SetAssociatedComposition(boundsComposition); AltChanged.SetAssociatedComposition(boundsComposition); TextChanged.SetAssociatedComposition(boundsComposition); FontChanged.SetAssociatedComposition(boundsComposition); font=GetCurrentController()->ResourceService()->GetDefaultFont(); styleController->SetFont(font); styleController->SetText(text); styleController->SetVisuallyEnabled(isVisuallyEnabled); sharedPtrDestructorProc = &GuiControl::SharedPtrDestructorProc; } GuiControl::~GuiControl() { if(tooltipControl) { // the only legal parent is the GuiApplication::sharedTooltipWindow if(tooltipControl->GetBoundsComposition()->GetParent()) { tooltipControl->GetBoundsComposition()->GetParent()->RemoveChild(tooltipControl->GetBoundsComposition()); } delete tooltipControl; } if(parent || !styleController) { for(vint i=0;i=0;i--) { GuiControl* child=children[i]; child->GetBoundsComposition()->GetParent()->RemoveChild(child->GetBoundsComposition()); delete child; } delete boundsComposition; } } compositions::GuiEventArgs GuiControl::GetNotifyEventArguments() { return GuiEventArgs(boundsComposition); } GuiControl::IStyleController* GuiControl::GetStyleController() { return styleController.Obj(); } compositions::GuiBoundsComposition* GuiControl::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* GuiControl::GetContainerComposition() { return styleController->GetContainerComposition(); } compositions::GuiGraphicsComposition* GuiControl::GetFocusableComposition() { return focusableComposition; } compositions::GuiGraphicsEventReceiver* GuiControl::GetEventReceiver() { return eventReceiver; } GuiControl* GuiControl::GetParent() { return parent; } vint GuiControl::GetChildrenCount() { return children.Count(); } GuiControl* GuiControl::GetChild(vint index) { return children[index]; } bool GuiControl::AddChild(GuiControl* control) { return GetContainerComposition()->AddChild(control->GetBoundsComposition()); } bool GuiControl::HasChild(GuiControl* control) { return children.Contains(control); } GuiControlHost* GuiControl::GetRelatedControlHost() { return parent?parent->GetRelatedControlHost():0; } bool GuiControl::GetVisuallyEnabled() { return isVisuallyEnabled; } bool GuiControl::GetEnabled() { return isEnabled; } void GuiControl::SetEnabled(bool value) { if(isEnabled!=value) { isEnabled=value; EnabledChanged.Execute(GetNotifyEventArguments()); UpdateVisuallyEnabled(); } } bool GuiControl::GetVisible() { return isVisible; } void GuiControl::SetVisible(bool value) { boundsComposition->SetVisible(value); if(isVisible!=value) { isVisible=value; VisibleChanged.Execute(GetNotifyEventArguments()); } } const WString& GuiControl::GetAlt() { return alt; } bool GuiControl::SetAlt(const WString& value) { if (!IGuiAltAction::IsLegalAlt(value)) return false; if (alt != value) { alt = value; AltChanged.Execute(GetNotifyEventArguments()); } return true; } void GuiControl::SetActivatingAltHost(compositions::IGuiAltActionHost* host) { activatingAltHost = host; } const WString& GuiControl::GetText() { return text; } void GuiControl::SetText(const WString& value) { if(text!=value) { text=value; styleController->SetText(text); TextChanged.Execute(GetNotifyEventArguments()); } } const FontProperties& GuiControl::GetFont() { return font; } void GuiControl::SetFont(const FontProperties& value) { if(font!=value) { font=value; styleController->SetFont(font); FontChanged.Execute(GetNotifyEventArguments()); } } void GuiControl::SetFocus() { if(focusableComposition) { GuiGraphicsHost* host=focusableComposition->GetRelatedGraphicsHost(); if(host) { host->SetFocus(focusableComposition); } } } description::Value GuiControl::GetTag() { return tag; } void GuiControl::SetTag(const description::Value& value) { tag=value; } GuiControl* GuiControl::GetTooltipControl() { return tooltipControl; } GuiControl* GuiControl::SetTooltipControl(GuiControl* value) { GuiControl* oldTooltipControl=tooltipControl; tooltipControl=value; return oldTooltipControl; } vint GuiControl::GetTooltipWidth() { return tooltipWidth; } void GuiControl::SetTooltipWidth(vint value) { tooltipWidth=value; } bool GuiControl::DisplayTooltip(Point location) { if(!tooltipControl) return false; GetApplication()->ShowTooltip(this, tooltipControl, tooltipWidth, location); return true; } void GuiControl::CloseTooltip() { if(GetApplication()->GetTooltipOwner()==this) { GetApplication()->CloseTooltip(); } } IDescriptable* GuiControl::QueryService(const WString& identifier) { if (identifier == IGuiAltAction::Identifier) { return (IGuiAltAction*)this; } else if (identifier == IGuiAltActionContainer::Identifier) { return 0; } else if(parent) { return parent->QueryService(identifier); } else { return 0; } } /*********************************************************************** GuiComponent ***********************************************************************/ GuiComponent::GuiComponent() { } GuiComponent::~GuiComponent() { } void GuiComponent::Attach(GuiInstanceRootObject* rootObject) { } void GuiComponent::Detach(GuiInstanceRootObject* rootObject) { } /*********************************************************************** GuiInstanceRootObject ***********************************************************************/ void GuiInstanceRootObject::FinalizeInstance() { ClearSubscriptions(); ClearComponents(); } GuiInstanceRootObject::GuiInstanceRootObject() { } GuiInstanceRootObject::~GuiInstanceRootObject() { } Ptr GuiInstanceRootObject::AddSubscription(Ptr subscription) { if (subscriptions.Contains(subscription.Obj())) { return 0; } else { subscriptions.Add(subscription); return subscription; } } bool GuiInstanceRootObject::RemoveSubscription(Ptr subscription) { return subscriptions.Remove(subscription.Obj()); } bool GuiInstanceRootObject::ContainsSubscription(Ptr subscription) { return subscriptions.Contains(subscription.Obj()); } void GuiInstanceRootObject::ClearSubscriptions() { FOREACH(Ptr, subscription, subscriptions) { subscription->Close(); } subscriptions.Clear(); } bool GuiInstanceRootObject::AddComponent(GuiComponent* component) { if(components.Contains(component)) { return false; } else { components.Add(component); component->Attach(this); return true; } } bool GuiInstanceRootObject::AddControlHostComponent(GuiControlHost* controlHost) { return AddComponent(new GuiObjectComponent(controlHost)); } bool GuiInstanceRootObject::RemoveComponent(GuiComponent* component) { vint index = components.IndexOf(component); if (index == -1) { return false; } { component->Detach(this); return components.RemoveAt(index); } } bool GuiInstanceRootObject::ContainsComponent(GuiComponent* component) { return components.Contains(component); } void GuiInstanceRootObject::ClearComponents() { for(vint i=0;iDetach(this); } for(vint i=0;iGetDefaultTextColor(); styleController->SetTextColor(textColor); } GuiLabel::~GuiLabel() { } Color GuiLabel::GetTextColor() { return textColor; } void GuiLabel::SetTextColor(Color value) { if(textColor!=value) { textColor=value; styleController->SetTextColor(textColor); } } /*********************************************************************** GuiButton ***********************************************************************/ void GuiButton::OnParentLineChanged() { GuiControl::OnParentLineChanged(); if(GetRelatedControlHost()==0) { mousePressing=false; mouseHoving=false; UpdateControlState(); } } void GuiButton::OnActiveAlt() { Clicked.Execute(GetNotifyEventArguments()); } void GuiButton::UpdateControlState() { ControlState newControlState=Normal; if(mousePressing) { if(mouseHoving) { newControlState=Pressed; } else { newControlState=Active; } } else { if(mouseHoving) { newControlState=Active; } else { newControlState=Normal; } } if(controlState!=newControlState) { controlState=newControlState; styleController->Transfer(controlState); } } void GuiButton::OnLeftButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(arguments.eventSource==boundsComposition) { mousePressing=true; boundsComposition->GetRelatedGraphicsHost()->SetFocus(boundsComposition); UpdateControlState(); if(!clickOnMouseUp && arguments.eventSource->GetAssociatedControl()==this) { Clicked.Execute(GetNotifyEventArguments()); } } } void GuiButton::OnLeftButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(arguments.eventSource==boundsComposition) { mousePressing=false; UpdateControlState(); } if(GetVisuallyEnabled()) { if(mouseHoving && clickOnMouseUp && arguments.eventSource->GetAssociatedControl()==this) { Clicked.Execute(GetNotifyEventArguments()); } } } void GuiButton::OnMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(arguments.eventSource==boundsComposition) { mouseHoving=true; UpdateControlState(); } } void GuiButton::OnMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(arguments.eventSource==boundsComposition) { mouseHoving=false; UpdateControlState(); } } GuiButton::GuiButton(IStyleController* _styleController) :GuiControl(_styleController) ,styleController(_styleController) ,clickOnMouseUp(true) ,mousePressing(false) ,mouseHoving(false) ,controlState(Normal) { Clicked.SetAssociatedComposition(boundsComposition); styleController->Transfer(Normal); SetFocusableComposition(boundsComposition); GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiButton::OnLeftButtonDown); GetEventReceiver()->leftButtonUp.AttachMethod(this, &GuiButton::OnLeftButtonUp); GetEventReceiver()->mouseEnter.AttachMethod(this, &GuiButton::OnMouseEnter); GetEventReceiver()->mouseLeave.AttachMethod(this, &GuiButton::OnMouseLeave); } GuiButton::~GuiButton() { } bool GuiButton::GetClickOnMouseUp() { return clickOnMouseUp; } void GuiButton::SetClickOnMouseUp(bool value) { clickOnMouseUp=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::OnClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(autoSelection) { SetSelected(!GetSelected()); } } GuiSelectableButton::GuiSelectableButton(IStyleController* _styleController) :GuiButton(_styleController) ,styleController(_styleController) ,groupController(0) ,autoSelection(true) ,isSelected(false) { GroupControllerChanged.SetAssociatedComposition(boundsComposition); AutoSelectionChanged.SetAssociatedComposition(boundsComposition); SelectedChanged.SetAssociatedComposition(boundsComposition); Clicked.AttachMethod(this, &GuiSelectableButton::OnClicked); styleController->SetSelected(isSelected); } 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; styleController->SetSelected(isSelected); if(groupController) { groupController->OnSelectedChanged(this); } SelectedChanged.Execute(GetNotifyEventArguments()); } } /*********************************************************************** 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 ***********************************************************************/ GuiScroll::GuiScroll(IStyleController* _styleController) :GuiControl(_styleController) ,styleController(_styleController) ,totalSize(100) ,pageSize(10) ,position(0) ,smallMove(1) ,bigMove(10) { TotalSizeChanged.SetAssociatedComposition(boundsComposition); PageSizeChanged.SetAssociatedComposition(boundsComposition); PositionChanged.SetAssociatedComposition(boundsComposition); SmallMoveChanged.SetAssociatedComposition(boundsComposition); BigMoveChanged.SetAssociatedComposition(boundsComposition); commandExecutor=new CommandExecutor(this); styleController->SetCommandExecutor(commandExecutor.Obj()); styleController->SetPageSize(pageSize); styleController->SetTotalSize(totalSize); styleController->SetPosition(position); } GuiScroll::~GuiScroll() { } vint GuiScroll::GetTotalSize() { return totalSize; } void GuiScroll::SetTotalSize(vint value) { if(totalSize!=value && 0totalSize) { SetPageSize(totalSize); } if(position>GetMaxPosition()) { SetPosition(GetMaxPosition()); } styleController->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()); } styleController->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; styleController->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; } /*********************************************************************** 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\GUICONTAINERCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace compositions; namespace controls { /*********************************************************************** GuiTabPage ***********************************************************************/ bool GuiTabPage::AssociateTab(GuiTab* _owner) { if(owner) { return false; } else { owner=_owner; PageInstalled.Execute(containerControl->GetNotifyEventArguments()); return true; } } bool GuiTabPage::DeassociateTab(GuiTab* _owner) { if(owner && owner==_owner) { PageUninstalled.Execute(containerControl->GetNotifyEventArguments()); owner=0; return true; } else { return false; } } compositions::GuiGraphicsComposition* GuiTabPage::GetAltComposition() { return containerControl->GetContainerComposition(); } compositions::IGuiAltActionHost* GuiTabPage::GetPreviousAltHost() { return previousAltHost; } void GuiTabPage::OnActivatedAltHost(compositions::IGuiAltActionHost* previousHost) { previousAltHost = previousHost; } void GuiTabPage::OnDeactivatedAltHost() { previousAltHost = 0; } void GuiTabPage::CollectAltActions(collections::Group& actions) { IGuiAltActionHost::CollectAltActionsFromControl(containerControl, actions); } GuiTabPage::GuiTabPage() :containerControl(0) ,owner(0) ,previousAltHost(0) { containerControl = new GuiControl(new GuiControl::EmptyStyleController()); containerControl->GetBoundsComposition()->SetAlignmentToParent(Margin(2, 2, 2, 2)); AltChanged.SetAssociatedComposition(containerControl->GetBoundsComposition()); TextChanged.SetAssociatedComposition(containerControl->GetBoundsComposition()); PageInstalled.SetAssociatedComposition(containerControl->GetBoundsComposition()); PageUninstalled.SetAssociatedComposition(containerControl->GetBoundsComposition()); } GuiTabPage::~GuiTabPage() { if (!containerControl->GetParent()) { delete containerControl; } } compositions::GuiGraphicsComposition* GuiTabPage::GetContainerComposition() { return containerControl->GetContainerComposition(); } GuiTab* GuiTabPage::GetOwnerTab() { return owner; } const WString& GuiTabPage::GetAlt() { return alt; } bool GuiTabPage::SetAlt(const WString& value) { if (!IGuiAltAction::IsLegalAlt(value)) return false; if(owner) { owner->styleController->SetTabAlt(owner->tabPages.IndexOf(this), text, this); } if (alt != value) { alt = value; AltChanged.Execute(containerControl->GetNotifyEventArguments()); } return true; } const WString& GuiTabPage::GetText() { return text; } void GuiTabPage::SetText(const WString& value) { if(text!=value) { text=value; if(owner) { owner->styleController->SetTabText(owner->tabPages.IndexOf(this), text); } TextChanged.Execute(containerControl->GetNotifyEventArguments()); } } bool GuiTabPage::GetSelected() { return owner->GetSelectedPage()==this; } /*********************************************************************** GuiTab ***********************************************************************/ GuiTab::CommandExecutor::CommandExecutor(GuiTab* _tab) :tab(_tab) { } GuiTab::CommandExecutor::~CommandExecutor() { } void GuiTab::CommandExecutor::ShowTab(vint index) { tab->SetSelectedPage(tab->GetPages().Get(index)); } vint GuiTab::GetAltActionCount() { return tabPages.Count(); } compositions::IGuiAltAction* GuiTab::GetAltAction(vint index) { return styleController->GetTabAltAction(index); } GuiTab::GuiTab(IStyleController* _styleController) :GuiControl(_styleController) ,styleController(_styleController) ,selectedPage(0) { commandExecutor=new CommandExecutor(this); styleController->SetCommandExecutor(commandExecutor.Obj()); } GuiTab::~GuiTab() { for(vint i=0;i=0 && index>=tabPages.Count()) { index=tabPages.Count()-1; } else if(index<-1) { index=-1; } if(page->AssociateTab(this)) { index=index==-1?tabPages.Add(page):tabPages.Insert(index, page); GetContainerComposition()->AddChild(page->GetContainerComposition()); styleController->InsertTab(index); styleController->SetTabText(index, page->GetText()); styleController->SetTabAlt(index, page->GetAlt(), page); if(!selectedPage) { SetSelectedPage(page); } page->GetContainerComposition()->SetVisible(page==selectedPage); return true; } else { return false; } } bool GuiTab::RemovePage(GuiTabPage* page) { if(page->GetOwnerTab()==this && page->DeassociateTab(this)) { vint index=tabPages.IndexOf(page); styleController->RemoveTab(index); GetContainerComposition()->RemoveChild(page->GetContainerComposition()); tabPages.RemoveAt(index); if(tabPages.Count()==0) { SetSelectedPage(0); return 0; } else if(selectedPage==page) { SetSelectedPage(tabPages[0]); } return true; } else { return false; } } bool GuiTab::MovePage(GuiTabPage* page, vint newIndex) { if(!page) return false; vint index=tabPages.IndexOf(page); if(index==-1) return false; tabPages.RemoveAt(index); tabPages.Insert(newIndex, page); styleController->MoveTab(index, newIndex); styleController->SetSelectedTab(tabPages.IndexOf(selectedPage)); return true; } const collections::List& GuiTab::GetPages() { return tabPages; } GuiTabPage* GuiTab::GetSelectedPage() { return selectedPage; } bool GuiTab::SetSelectedPage(GuiTabPage* value) { if(!value) { if(tabPages.Count()==0) { selectedPage=0; } } else if(value->GetOwnerTab()==this) { if(selectedPage!=value) { selectedPage=value; for(vint i=0;iGetContainerComposition()->SetVisible(selected); if(selected) { styleController->SetSelectedTab(i); } } SelectedPageChanged.Execute(GetNotifyEventArguments()); } } return selectedPage==value; } /*********************************************************************** GuiScrollView::StyleController ***********************************************************************/ void GuiScrollView::StyleController::UpdateTable() { if(horizontalScroll->GetEnabled() || horizontalAlwaysVisible) { tableComposition->SetRowOption(1, GuiCellOption::AbsoluteOption(styleProvider->GetDefaultScrollSize())); } else { tableComposition->SetRowOption(1, GuiCellOption::AbsoluteOption(0)); } if(verticalScroll->GetEnabled() || verticalAlwaysVisible) { tableComposition->SetColumnOption(1, GuiCellOption::AbsoluteOption(styleProvider->GetDefaultScrollSize())); } else { tableComposition->SetColumnOption(1, GuiCellOption::AbsoluteOption(0)); } tableComposition->UpdateCellBounds(); } GuiScrollView::StyleController::StyleController(IStyleProvider* _styleProvider) :styleProvider(_styleProvider) ,scrollView(0) ,horizontalAlwaysVisible(true) ,verticalAlwaysVisible(true) { horizontalScroll=new GuiScroll(styleProvider->CreateHorizontalScrollStyle()); horizontalScroll->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); horizontalScroll->SetEnabled(false); verticalScroll=new GuiScroll(styleProvider->CreateVerticalScrollStyle()); verticalScroll->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); verticalScroll->SetEnabled(false); boundsComposition=new GuiBoundsComposition; GuiGraphicsComposition* tableContainerComposition=styleProvider->InstallBackground(boundsComposition); tableComposition=new GuiTableComposition; tableContainerComposition->AddChild(tableComposition); tableComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); tableComposition->SetRowsAndColumns(2, 2); tableComposition->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); tableComposition->SetRowOption(1, GuiCellOption::MinSizeOption()); tableComposition->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); tableComposition->SetColumnOption(1, GuiCellOption::MinSizeOption()); UpdateTable(); { GuiCellComposition* cell=new GuiCellComposition; tableComposition->AddChild(cell); cell->SetSite(1, 0, 1, 1); cell->AddChild(horizontalScroll->GetBoundsComposition()); } { GuiCellComposition* cell=new GuiCellComposition; tableComposition->AddChild(cell); cell->SetSite(0, 1, 1, 1); cell->AddChild(verticalScroll->GetBoundsComposition()); } containerCellComposition=new GuiCellComposition; tableComposition->AddChild(containerCellComposition); containerCellComposition->SetSite(0, 0, 1, 1); containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); containerCellComposition->AddChild(containerComposition); styleProvider->AssociateStyleController(this); } GuiScrollView::StyleController::~StyleController() { } void GuiScrollView::StyleController::SetScrollView(GuiScrollView* _scrollView) { scrollView=_scrollView; } void GuiScrollView::StyleController::AdjustView(Size fullSize) { Size viewSize=containerComposition->GetBounds().GetSize(); if(fullSize.x<=viewSize.x) { horizontalScroll->SetEnabled(false); horizontalScroll->SetPosition(0); } else { horizontalScroll->SetEnabled(true); horizontalScroll->SetTotalSize(fullSize.x); horizontalScroll->SetPageSize(viewSize.x); } if(fullSize.y<=viewSize.y) { verticalScroll->SetEnabled(false); verticalScroll->SetPosition(0); } else { verticalScroll->SetEnabled(true); verticalScroll->SetTotalSize(fullSize.y); verticalScroll->SetPageSize(viewSize.y); } UpdateTable(); } GuiScrollView::IStyleProvider* GuiScrollView::StyleController::GetStyleProvider() { return styleProvider.Obj(); } GuiScroll* GuiScrollView::StyleController::GetHorizontalScroll() { return horizontalScroll; } GuiScroll* GuiScrollView::StyleController::GetVerticalScroll() { return verticalScroll; } compositions::GuiTableComposition* GuiScrollView::StyleController::GetInternalTableComposition() { return tableComposition; } compositions::GuiBoundsComposition* GuiScrollView::StyleController::GetInternalContainerComposition() { return containerComposition; } bool GuiScrollView::StyleController::GetHorizontalAlwaysVisible() { return horizontalAlwaysVisible; } void GuiScrollView::StyleController::SetHorizontalAlwaysVisible(bool value) { if(horizontalAlwaysVisible!=value) { horizontalAlwaysVisible=value; scrollView->CalculateView(); } } bool GuiScrollView::StyleController::GetVerticalAlwaysVisible() { return verticalAlwaysVisible; } void GuiScrollView::StyleController::SetVerticalAlwaysVisible(bool value) { if(verticalAlwaysVisible!=value) { verticalAlwaysVisible=value; scrollView->CalculateView(); } } compositions::GuiBoundsComposition* GuiScrollView::StyleController::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* GuiScrollView::StyleController::GetContainerComposition() { return containerComposition; } void GuiScrollView::StyleController::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { styleProvider->SetFocusableComposition(value); } void GuiScrollView::StyleController::SetText(const WString& value) { styleProvider->SetText(value); } void GuiScrollView::StyleController::SetFont(const FontProperties& value) { styleProvider->SetFont(value); } void GuiScrollView::StyleController::SetVisuallyEnabled(bool value) { styleProvider->SetVisuallyEnabled(value); } /*********************************************************************** GuiScrollView ***********************************************************************/ 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) { auto scroll = styleController->GetHorizontalScroll(); 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()) { auto scroll = styleController->GetVerticalScroll(); vint position = scroll->GetPosition(); vint move = scroll->GetSmallMove(); position -= move*arguments.wheel / 60; scroll->SetPosition(position); } } void GuiScrollView::CallUpdateView() { Rect viewBounds=GetViewBounds(); UpdateView(viewBounds); } void GuiScrollView::Initialize() { styleController=dynamic_cast(GetStyleController()); styleController->SetScrollView(this); styleController->GetInternalContainerComposition()->BoundsChanged.AttachMethod(this, &GuiScrollView::OnContainerBoundsChanged); styleController->GetHorizontalScroll()->PositionChanged.AttachMethod(this, &GuiScrollView::OnHorizontalScroll); styleController->GetVerticalScroll()->PositionChanged.AttachMethod(this, &GuiScrollView::OnVerticalScroll); styleController->GetBoundsComposition()->GetEventReceiver()->horizontalWheel.AttachMethod(this, &GuiScrollView::OnHorizontalWheel); styleController->GetBoundsComposition()->GetEventReceiver()->verticalWheel.AttachMethod(this, &GuiScrollView::OnVerticalWheel); } GuiScrollView::GuiScrollView(StyleController* _styleController) :GuiControl(_styleController) ,supressScrolling(false) { Initialize(); } GuiScrollView::GuiScrollView(IStyleProvider* styleProvider) :GuiControl(new StyleController(styleProvider)) ,supressScrolling(false) { Initialize(); } vint GuiScrollView::GetSmallMove() { return GetFont().size * 2; } Size GuiScrollView::GetBigMove() { return GetViewSize(); } GuiScrollView::~GuiScrollView() { } void GuiScrollView::SetFont(const FontProperties& value) { GuiControl::SetFont(value); CalculateView(); } void GuiScrollView::CalculateView() { if(!supressScrolling) { Size fullSize = QueryFullSize(); while(true) { styleController->AdjustView(fullSize); styleController->AdjustView(fullSize); supressScrolling = true; CallUpdateView(); supressScrolling = false; Size newSize=QueryFullSize(); if (fullSize == newSize) { vint smallMove = GetSmallMove(); styleController->GetHorizontalScroll()->SetSmallMove(smallMove); styleController->GetVerticalScroll()->SetSmallMove(smallMove); Size bigMove = GetBigMove(); styleController->GetHorizontalScroll()->SetBigMove(bigMove.x); styleController->GetVerticalScroll()->SetBigMove(bigMove.y); break; } else { fullSize=newSize; } } } } Size GuiScrollView::GetViewSize() { Size viewSize=styleController->GetInternalContainerComposition()->GetBounds().GetSize(); return viewSize; } Rect GuiScrollView::GetViewBounds() { Point viewPosition= Point( styleController->GetHorizontalScroll()->GetPosition(), styleController->GetVerticalScroll()->GetPosition() ); Size viewSize=GetViewSize(); return Rect(viewPosition, viewSize); } GuiScroll* GuiScrollView::GetHorizontalScroll() { return styleController->GetHorizontalScroll(); } GuiScroll* GuiScrollView::GetVerticalScroll() { return styleController->GetVerticalScroll(); } bool GuiScrollView::GetHorizontalAlwaysVisible() { return styleController->GetHorizontalAlwaysVisible(); } void GuiScrollView::SetHorizontalAlwaysVisible(bool value) { styleController->SetHorizontalAlwaysVisible(value); } bool GuiScrollView::GetVerticalAlwaysVisible() { return styleController->GetVerticalAlwaysVisible(); } void GuiScrollView::SetVerticalAlwaysVisible(bool value) { styleController->SetVerticalAlwaysVisible(value); } /*********************************************************************** GuiScrollContainer::StyleController ***********************************************************************/ GuiScrollContainer::StyleController::StyleController(GuiScrollView::IStyleProvider* styleProvider) :GuiScrollView::StyleController(styleProvider) ,extendToFullWidth(false) { controlContainerComposition=new GuiBoundsComposition; controlContainerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GetInternalContainerComposition()->AddChild(controlContainerComposition); } GuiScrollContainer::StyleController::~StyleController() { } compositions::GuiGraphicsComposition* GuiScrollContainer::StyleController::GetContainerComposition() { return controlContainerComposition; } void GuiScrollContainer::StyleController::MoveContainer(Point leftTop) { controlContainerComposition->SetBounds(Rect(leftTop, Size(0, 0))); } bool GuiScrollContainer::StyleController::GetExtendToFullWidth() { return extendToFullWidth; } void GuiScrollContainer::StyleController::SetExtendToFullWidth(bool value) { if(extendToFullWidth!=value) { extendToFullWidth=value; if(value) { controlContainerComposition->SetAlignmentToParent(Margin(0, -1, 0, -1)); } else { controlContainerComposition->SetAlignmentToParent(Margin(-1, -1, -1, -1)); } } } /*********************************************************************** GuiScrollContainer ***********************************************************************/ void GuiScrollContainer::OnControlContainerBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { CalculateView(); } Size GuiScrollContainer::QueryFullSize() { return styleController->GetContainerComposition()->GetBounds().GetSize(); } void GuiScrollContainer::UpdateView(Rect viewBounds) { styleController->MoveContainer(Point(-viewBounds.x1, -viewBounds.y1)); } GuiScrollContainer::GuiScrollContainer(GuiScrollContainer::IStyleProvider* styleProvider) :GuiScrollView(new StyleController(styleProvider)) ,styleController(0) { styleController=dynamic_cast(GetStyleController()); GuiBoundsComposition* composition=dynamic_cast(styleController->GetContainerComposition()); composition->BoundsChanged.AttachMethod(this, &GuiScrollContainer::OnControlContainerBoundsChanged); } GuiScrollContainer::~GuiScrollContainer() { } bool GuiScrollContainer::GetExtendToFullWidth() { return styleController->GetExtendToFullWidth(); } void GuiScrollContainer::SetExtendToFullWidth(bool value) { styleController->SetExtendToFullWidth(value); } } } } /*********************************************************************** CONTROLS\GUIDATETIMECONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace compositions; using namespace elements; /*********************************************************************** GuiDatePicker::StyleController ***********************************************************************/ vint GetDayCountForMonth(vint year, vint month) { bool isLeapYear=(year%100==0)?(year%400==0):(year%4==0); switch(month) { case 1:case 3:case 5:case 7:case 8:case 10:case 12: return 31; case 4:case 6:case 9:case 11: return 30; default: return isLeapYear?29:28; } } void StepPreviousMonth(vint& year, vint& month) { if(month==1) { year--; month=12; } else { month--; } } void StepNextMonth(vint& year, vint& month) { if(month==12) { year++; month=1; } else { month++; } } void GuiDatePicker::StyleController::SetDay(const DateTime& day, vint& index, bool currentMonth) { dateDays[index]=day; GuiSolidLabelElement* label=labelDays[index]; label->SetText(itow(day.day)); label->SetColor(currentMonth?styleProvider->GetPrimaryTextColor():styleProvider->GetSecondaryTextColor()); index++; } void GuiDatePicker::StyleController::comboYearMonth_SelectedIndexChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(!preventComboEvent) { if(comboYear->GetSelectedIndex()!=-1 && comboMonth->GetSelectedIndex()!=-1) { vint year=comboYear->GetSelectedIndex()+YearFirst; vint month=comboMonth->GetSelectedIndex()+1; SetDate(DateTime::FromDateTime(year, month, 1)); datePicker->NotifyDateChanged(); datePicker->DateNavigated.Execute(datePicker->GetNotifyEventArguments()); } } } void GuiDatePicker::StyleController::buttonDay_SelectedChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(!preventButtonEvent) { GuiSelectableButton* button=dynamic_cast(sender->GetRelatedControl()); if(button->GetSelected()) { vint index=buttonDays.IndexOf(button); if(index!=-1) { DateTime day=dateDays[index]; if(day.year!=currentDate.year || day.month!=currentDate.month) { SetDate(day); } else { currentDate=day; } datePicker->NotifyDateChanged(); datePicker->DateSelected.Execute(datePicker->GetNotifyEventArguments()); } } } } void GuiDatePicker::StyleController::DisplayMonth(vint year, vint month) { if(YearFirst<=year && year<=YearLast && 1<=month && month<=12) { preventComboEvent=true; comboYear->SetSelectedIndex(year-YearFirst); comboMonth->SetSelectedIndex(month-1); preventComboEvent=false; } vint yearPrev=year, yearNext=year, monthPrev=month, monthNext=month; StepPreviousMonth(yearPrev, monthPrev); StepNextMonth(yearNext, monthNext); vint countPrev=GetDayCountForMonth(yearPrev, monthPrev); vint count=GetDayCountForMonth(year, month); vint countNext=GetDayCountForMonth(yearNext, monthNext); DateTime firstDay=DateTime::FromDateTime(year, month, 1); vint showPrev=firstDay.dayOfWeek; if(showPrev==0) showPrev=DaysOfWeek; vint show=count; vint showNext=DaysOfWeek*DayRows-showPrev-show; vint index=0; for(vint i=0;iSetSelected(true); preventButtonEvent=false; break; } } } GuiDatePicker::StyleController::StyleController(IStyleProvider* _styleProvider) :styleProvider(_styleProvider) ,datePicker(0) ,preventComboEvent(false) ,preventButtonEvent(false) { GuiTableComposition* monthTable=0; GuiTableComposition* dayTable=0; { listYears=styleProvider->CreateTextList(); listYears->SetHorizontalAlwaysVisible(false); for(vint i=YearFirst;i<=YearLast;i++) { listYears->GetItems().Add(new list::TextItem(itow(i))); } comboYear=new GuiComboBoxListControl(styleProvider->CreateComboBoxStyle(), listYears); comboYear->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 2, 0)); comboYear->SelectedIndexChanged.AttachMethod(this, &StyleController::comboYearMonth_SelectedIndexChanged); } { listMonths=styleProvider->CreateTextList(); listMonths->SetHorizontalAlwaysVisible(false); comboMonth=new GuiComboBoxListControl(styleProvider->CreateComboBoxStyle(), listMonths); comboMonth->GetBoundsComposition()->SetAlignmentToParent(Margin(2, 0, 0, 0)); comboMonth->SelectedIndexChanged.AttachMethod(this, &StyleController::comboYearMonth_SelectedIndexChanged); } { monthTable=new GuiTableComposition; monthTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); monthTable->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); monthTable->SetRowsAndColumns(1, 2); monthTable->SetRowOption(0, GuiCellOption::MinSizeOption()); monthTable->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); monthTable->SetColumnOption(1, GuiCellOption::PercentageOption(0.5)); { GuiCellComposition* cell=new GuiCellComposition; monthTable->AddChild(cell); cell->SetSite(0, 0, 1, 1); cell->AddChild(comboYear->GetBoundsComposition()); } { GuiCellComposition* cell=new GuiCellComposition; monthTable->AddChild(cell); cell->SetSite(0, 1, 1, 1); cell->AddChild(comboMonth->GetBoundsComposition()); } } { dayTable=new GuiTableComposition; dayTable->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); dayTable->SetCellPadding(4); dayTable->SetRowsAndColumns(DayRows+DayRowStart, DaysOfWeek); for(vint i=0;iSetRowOption(i, GuiCellOption::MinSizeOption()); } for(vint i=0;iSetRowOption(i+DayRowStart, GuiCellOption::PercentageOption(1.0)); } for(vint i=0;iSetColumnOption(i, GuiCellOption::PercentageOption(1.0)); } { GuiCellComposition* cell=new GuiCellComposition; dayTable->AddChild(cell); cell->SetSite(0, 0, 1, DaysOfWeek); cell->AddChild(monthTable); } labelDaysOfWeek.Resize(7); for(vint i=0;iAddChild(cell); cell->SetSite(1, i, 1, 1); GuiSolidLabelElement* element=GuiSolidLabelElement::Create(); element->SetAlignments(Alignment::Center, Alignment::Center); element->SetColor(styleProvider->GetPrimaryTextColor()); labelDaysOfWeek[i]=element; cell->SetOwnedElement(element); } buttonDays.Resize(DaysOfWeek*DayRows); labelDays.Resize(DaysOfWeek*DayRows); dateDays.Resize(DaysOfWeek*DayRows); dayMutexController=new GuiSelectableButton::MutexGroupController; for(vint i=0;iAddChild(cell); cell->SetSite(j+DayRowStart, i, 1, 1); GuiSelectableButton* button=new GuiSelectableButton(styleProvider->CreateDateButtonStyle()); button->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); button->SetGroupController(dayMutexController.Obj()); button->SelectedChanged.AttachMethod(this, &StyleController::buttonDay_SelectedChanged); cell->AddChild(button->GetBoundsComposition()); buttonDays[j*DaysOfWeek+i]=button; GuiSolidLabelElement* element=GuiSolidLabelElement::Create(); element->SetAlignments(Alignment::Center, Alignment::Center); element->SetText(L"0"); labelDays[j*DaysOfWeek+i]=element; GuiBoundsComposition* elementBounds=new GuiBoundsComposition; elementBounds->SetOwnedElement(element); elementBounds->SetAlignmentToParent(Margin(0, 0, 0, 0)); elementBounds->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); button->GetContainerComposition()->AddChild(elementBounds); } } } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(styleProvider->GetBackgroundColor()); dayTable->SetOwnedElement(element); } boundsComposition=dayTable; } GuiDatePicker::StyleController::~StyleController() { delete styleProvider; } compositions::GuiBoundsComposition* GuiDatePicker::StyleController::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* GuiDatePicker::StyleController::GetContainerComposition() { return boundsComposition; } void GuiDatePicker::StyleController::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void GuiDatePicker::StyleController::SetText(const WString& value) { } void GuiDatePicker::StyleController::SetFont(const FontProperties& value) { comboYear->SetFont(value); listYears->SetFont(value); comboMonth->SetFont(value); listMonths->SetFont(value); FOREACH(GuiSolidLabelElement*, label, From(labelDaysOfWeek).Concat(labelDays)) { label->SetFont(value); } } void GuiDatePicker::StyleController::SetVisuallyEnabled(bool value) { } void GuiDatePicker::StyleController::SetDatePicker(GuiDatePicker* _datePicker) { datePicker=_datePicker; } void GuiDatePicker::StyleController::SetDateLocale(const Locale& _dateLocale) { dateLocale=_dateLocale; for(vint i=0;iSetText(dateLocale.GetShortDayOfWeekName(i)); } listMonths->GetItems().Clear(); for(vint i=1;i<=12;i++) { listMonths->GetItems().Add(new list::TextItem(dateLocale.GetLongMonthName(i))); } SetDate(currentDate, true); } const DateTime& GuiDatePicker::StyleController::GetDate() { return currentDate; } void GuiDatePicker::StyleController::SetDate(const DateTime& value, bool forceUpdate) { if(forceUpdate || currentDate.year!=value.year || currentDate.month!=value.month || currentDate.day!=value.day) { currentDate=value; DisplayMonth(value.year, value.month); SelectDay(value.day); } } /*********************************************************************** GuiDatePicker ***********************************************************************/ void GuiDatePicker::UpdateText() { GuiControl::SetText(dateLocale.FormatDate(dateFormat, styleController->GetDate())); } void GuiDatePicker::NotifyDateChanged() { UpdateText(); DateChanged.Execute(GetNotifyEventArguments()); } GuiDatePicker::GuiDatePicker(IStyleProvider* _styleProvider) :GuiControl(new StyleController(_styleProvider)) { styleController=dynamic_cast(GetStyleController()); styleController->SetDatePicker(this); SetDateLocale(Locale::UserDefault()); SetDate(DateTime::LocalTime()); DateChanged.SetAssociatedComposition(GetBoundsComposition()); DateNavigated.SetAssociatedComposition(GetBoundsComposition()); DateSelected.SetAssociatedComposition(GetBoundsComposition()); DateFormatChanged.SetAssociatedComposition(GetBoundsComposition()); DateLocaleChanged.SetAssociatedComposition(GetBoundsComposition()); NotifyDateChanged(); } GuiDatePicker::~GuiDatePicker() { } const DateTime& GuiDatePicker::GetDate() { return styleController->GetDate(); } void GuiDatePicker::SetDate(const DateTime& value) { styleController->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]; } styleController->SetDateLocale(dateLocale); UpdateText(); DateFormatChanged.Execute(GetNotifyEventArguments()); DateLocaleChanged.Execute(GetNotifyEventArguments()); } void GuiDatePicker::SetText(const WString& value) { } /*********************************************************************** GuiDateComboBox ***********************************************************************/ 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(); SelectItem(); NotifyUpdateSelectedDate(); } GuiDateComboBox::GuiDateComboBox(IStyleController* _styleController, GuiDatePicker* _datePicker) :GuiComboBoxBase(_styleController) ,datePicker(_datePicker) { SelectedDateChanged.SetAssociatedComposition(GetBoundsComposition()); 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()); selectedDate=datePicker->GetDate(); SubMenuOpeningChanged.AttachMethod(this, &GuiDateComboBox::OnSubMenuOpeningChanged); SetFont(GetFont()); SetText(datePicker->GetText()); } GuiDateComboBox::~GuiDateComboBox() { } void GuiDateComboBox::SetFont(const FontProperties& 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\GUIWINDOWCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace compositions; using namespace collections; /*********************************************************************** GuiControlHost ***********************************************************************/ void GuiControlHost::OnNativeWindowChanged() { } void GuiControlHost::OnVisualStatusChanged() { } GuiControl* GuiControlHost::GetTooltipOwner(Point location) { GuiGraphicsComposition* composition=this->GetBoundsComposition()->FindComposition(location); if(composition) { GuiControl* control=composition->GetRelatedControl(); while(control) { if(control->GetTooltipControl()) { return control; } control=control->GetParent(); } } return 0; } void GuiControlHost::MoveIntoTooltipControl(GuiControl* tooltipControl, Point location) { if(tooltipLocation!=location) { tooltipLocation=location; { GuiControl* currentOwner=GetApplication()->GetTooltipOwner(); if(currentOwner && currentOwner!=tooltipControl) { if(tooltipCloseDelay) { tooltipCloseDelay->Cancel(); tooltipCloseDelay=0; } GetApplication()->DelayExecuteInMainThread([=]() { currentOwner->CloseTooltip(); }, TooltipDelayCloseTime); } } if(!tooltipControl) { if(tooltipOpenDelay) { tooltipOpenDelay->Cancel(); tooltipOpenDelay=0; } } else if(tooltipOpenDelay) { tooltipOpenDelay->Delay(TooltipDelayOpenTime); } else if(GetApplication()->GetTooltipOwner()!=tooltipControl) { tooltipOpenDelay=GetApplication()->DelayExecuteInMainThread([this]() { GuiControl* owner=GetTooltipOwner(tooltipLocation); if(owner) { Point offset=owner->GetBoundsComposition()->GetGlobalBounds().LeftTop(); Point p(tooltipLocation.x-offset.x, tooltipLocation.y-offset.y+24); owner->DisplayTooltip(p); tooltipOpenDelay=0; /* When you use VS2010 to compiler this code, you will see there is an error here. This is due to VS2010's bug about processing [this] capture. I don't want to do workaround in my code, but I can tell you how to do that: Use a variable to save the value of "this", and capture [theThisValue, owner] instead of [this, owner]. */ tooltipCloseDelay=GetApplication()->DelayExecuteInMainThread([this, owner]() { owner->CloseTooltip(); }, TooltipDelayLifeTime); } }, TooltipDelayOpenTime); } } } void GuiControlHost::MouseMoving(const NativeWindowMouseInfo& info) { if(!info.left && !info.middle && !info.right) { GuiControl* tooltipControl=GetTooltipOwner(tooltipLocation); MoveIntoTooltipControl(tooltipControl, Point(info.x, info.y)); } } void GuiControlHost::MouseLeaved() { MoveIntoTooltipControl(0, Point(-1, -1)); } void GuiControlHost::Moved() { OnVisualStatusChanged(); } void GuiControlHost::Enabled() { GuiControl::SetEnabled(true); OnVisualStatusChanged(); } void GuiControlHost::Disabled() { GuiControl::SetEnabled(false); OnVisualStatusChanged(); } void GuiControlHost::GotFocus() { WindowGotFocus.Execute(GetNotifyEventArguments()); OnVisualStatusChanged(); } void GuiControlHost::LostFocus() { WindowLostFocus.Execute(GetNotifyEventArguments()); OnVisualStatusChanged(); } void GuiControlHost::Activated() { WindowActivated.Execute(GetNotifyEventArguments()); OnVisualStatusChanged(); } void GuiControlHost::Deactivated() { WindowDeactivated.Execute(GetNotifyEventArguments()); OnVisualStatusChanged(); } void GuiControlHost::Opened() { WindowOpened.Execute(GetNotifyEventArguments()); } void GuiControlHost::Closing(bool& cancel) { GuiRequestEventArgs arguments(GetStyleController()->GetBoundsComposition()); arguments.cancel=cancel; WindowClosing.Execute(arguments); if(!arguments.handled) { cancel=arguments.cancel; } } void GuiControlHost::Closed() { WindowClosed.Execute(GetNotifyEventArguments()); } void GuiControlHost::Destroying() { WindowDestroying.Execute(GetNotifyEventArguments()); SetNativeWindow(0); } GuiControlHost::GuiControlHost(GuiControl::IStyleController* _styleController) :GuiControl(_styleController) { GetStyleController()->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); WindowGotFocus.SetAssociatedComposition(GetStyleController()->GetBoundsComposition()); WindowLostFocus.SetAssociatedComposition(GetStyleController()->GetBoundsComposition()); WindowActivated.SetAssociatedComposition(GetStyleController()->GetBoundsComposition()); WindowDeactivated.SetAssociatedComposition(GetStyleController()->GetBoundsComposition()); WindowOpened.SetAssociatedComposition(GetStyleController()->GetBoundsComposition()); WindowClosing.SetAssociatedComposition(GetStyleController()->GetBoundsComposition()); WindowClosed.SetAssociatedComposition(GetStyleController()->GetBoundsComposition()); WindowDestroying.SetAssociatedComposition(GetStyleController()->GetBoundsComposition()); host=new GuiGraphicsHost; host->GetMainComposition()->AddChild(GetStyleController()->GetBoundsComposition()); sharedPtrDestructorProc = 0; } GuiControlHost::~GuiControlHost() { OnBeforeReleaseGraphicsHost(); FinalizeInstance(); styleController=0; delete host; } compositions::GuiGraphicsHost* GuiControlHost::GetGraphicsHost() { return host; } compositions::GuiGraphicsComposition* GuiControlHost::GetMainComposition() { return host->GetMainComposition(); } INativeWindow* GuiControlHost::GetNativeWindow() { return host->GetNativeWindow(); } void GuiControlHost::SetNativeWindow(INativeWindow* window) { if(host->GetNativeWindow()) { host->GetNativeWindow()->UninstallListener(this); } host->SetNativeWindow(window); if(host->GetNativeWindow()) { host->GetNativeWindow()->InstallListener(this); } OnNativeWindowChanged(); } void GuiControlHost::ForceCalculateSizeImmediately() { boundsComposition->ForceCalculateSizeImmediately(); SetBounds(GetBounds()); } bool GuiControlHost::GetEnabled() { if(host->GetNativeWindow()) { return host->GetNativeWindow()->IsEnabled(); } else { return false; } } void GuiControlHost::SetEnabled(bool value) { if(host->GetNativeWindow()) { if(value) { host->GetNativeWindow()->Enable(); } else { host->GetNativeWindow()->Disable(); } } } bool GuiControlHost::GetFocused() { if(host->GetNativeWindow()) { return host->GetNativeWindow()->IsFocused(); } else { return false; } } void GuiControlHost::SetFocused() { if(host->GetNativeWindow()) { host->GetNativeWindow()->SetFocus(); } } bool GuiControlHost::GetActivated() { if(host->GetNativeWindow()) { return host->GetNativeWindow()->IsActivated(); } else { return false; } } void GuiControlHost::SetActivated() { if(host->GetNativeWindow()) { host->GetNativeWindow()->SetActivate(); } } bool GuiControlHost::GetShowInTaskBar() { if(host->GetNativeWindow()) { return host->GetNativeWindow()->IsAppearedInTaskBar(); } else { return false; } } void GuiControlHost::SetShowInTaskBar(bool value) { if(host->GetNativeWindow()) { if(value) { host->GetNativeWindow()->ShowInTaskBar(); } else { host->GetNativeWindow()->HideInTaskBar(); } } } bool GuiControlHost::GetEnabledActivate() { if(host->GetNativeWindow()) { return host->GetNativeWindow()->IsEnabledActivate(); } else { return false; } } void GuiControlHost::SetEnabledActivate(bool value) { if(host->GetNativeWindow()) { if(value) { host->GetNativeWindow()->EnableActivate(); } else { host->GetNativeWindow()->DisableActivate(); } } } bool GuiControlHost::GetTopMost() { if(host->GetNativeWindow()) { return host->GetNativeWindow()->GetTopMost(); } else { return false; } } void GuiControlHost::SetTopMost(bool topmost) { if(host->GetNativeWindow()) { host->GetNativeWindow()->SetTopMost(topmost); } } compositions::IGuiShortcutKeyManager* GuiControlHost::GetShortcutKeyManager() { return host->GetShortcutKeyManager(); } void GuiControlHost::SetShortcutKeyManager(compositions::IGuiShortcutKeyManager* value) { host->SetShortcutKeyManager(value); } compositions::GuiGraphicsAnimationManager* GuiControlHost::GetAnimationManager() { return host->GetAnimationManager(); } Size GuiControlHost::GetClientSize() { if(host->GetNativeWindow()) { return host->GetNativeWindow()->GetClientSize(); } else { return Size(0, 0); } } void GuiControlHost::SetClientSize(Size value) { if(host->GetNativeWindow()) { host->GetNativeWindow()->SetClientSize(value); } } Rect GuiControlHost::GetBounds() { if(host->GetNativeWindow()) { return host->GetNativeWindow()->GetBounds(); } else { return Rect(); } } void GuiControlHost::SetBounds(Rect value) { if(host->GetNativeWindow()) { host->GetNativeWindow()->SetBounds(value); } } GuiControlHost* GuiControlHost::GetRelatedControlHost() { return this; } const WString& GuiControlHost::GetText() { WString result; if(host->GetNativeWindow()) { result=host->GetNativeWindow()->GetTitle(); } if(result!=GuiControl::GetText()) { GuiControl::SetText(result); } return GuiControl::GetText(); } void GuiControlHost::SetText(const WString& value) { if(host->GetNativeWindow()) { host->GetNativeWindow()->SetTitle(value); GuiControl::SetText(value); } } INativeScreen* GuiControlHost::GetRelatedScreen() { if(host->GetNativeWindow()) { return GetCurrentController()->ScreenService()->GetScreen(host->GetNativeWindow()); } else { return 0; } } void GuiControlHost::Show() { if(host->GetNativeWindow()) { host->GetNativeWindow()->Show(); } } void GuiControlHost::ShowDeactivated() { if(host->GetNativeWindow()) { host->GetNativeWindow()->ShowDeactivated(); } } void GuiControlHost::ShowRestored() { if(host->GetNativeWindow()) { host->GetNativeWindow()->ShowRestored(); } } void GuiControlHost::ShowMaximized() { if(host->GetNativeWindow()) { host->GetNativeWindow()->ShowMaximized(); } } void GuiControlHost::ShowMinimized() { if(host->GetNativeWindow()) { host->GetNativeWindow()->ShowMinimized(); } } void GuiControlHost::Hide() { if(host->GetNativeWindow()) { host->GetNativeWindow()->Hide(); } } void GuiControlHost::Close() { INativeWindow* window=host->GetNativeWindow(); if(window) { if(GetCurrentController()->WindowService()->GetMainWindow()!=window) { window->Hide(); } else { SetNativeWindow(0); GetCurrentController()->WindowService()->DestroyNativeWindow(window); } } } bool GuiControlHost::GetOpening() { INativeWindow* window=host->GetNativeWindow(); if(window) { return window->IsVisible(); } return false; } /*********************************************************************** GuiWindow::DefaultBehaviorStyleController ***********************************************************************/ GuiWindow::DefaultBehaviorStyleController::DefaultBehaviorStyleController() :window(0) { } GuiWindow::DefaultBehaviorStyleController::~DefaultBehaviorStyleController() { } void GuiWindow::DefaultBehaviorStyleController::AttachWindow(GuiWindow* _window) { window=_window; } void GuiWindow::DefaultBehaviorStyleController::InitializeNativeWindowProperties() { } void GuiWindow::DefaultBehaviorStyleController::SetSizeState(INativeWindow::WindowSizeState value) { } bool GuiWindow::DefaultBehaviorStyleController::GetMaximizedBox() { if(window->GetNativeWindow()) { return window->GetNativeWindow()->GetMaximizedBox(); } else { return false; } } void GuiWindow::DefaultBehaviorStyleController::SetMaximizedBox(bool visible) { if(window->GetNativeWindow()) { window->GetNativeWindow()->SetMaximizedBox(visible); } } bool GuiWindow::DefaultBehaviorStyleController::GetMinimizedBox() { if(window->GetNativeWindow()) { return window->GetNativeWindow()->GetMinimizedBox(); } else { return false; } } void GuiWindow::DefaultBehaviorStyleController::SetMinimizedBox(bool visible) { if(window->GetNativeWindow()) { window->GetNativeWindow()->SetMinimizedBox(visible); } } bool GuiWindow::DefaultBehaviorStyleController::GetBorder() { if(window->GetNativeWindow()) { return window->GetNativeWindow()->GetBorder(); } else { return false; } } void GuiWindow::DefaultBehaviorStyleController::SetBorder(bool visible) { if(window->GetNativeWindow()) { window->GetNativeWindow()->SetBorder(visible); } } bool GuiWindow::DefaultBehaviorStyleController::GetSizeBox() { if(window->GetNativeWindow()) { return window->GetNativeWindow()->GetSizeBox(); } else { return false; } } void GuiWindow::DefaultBehaviorStyleController::SetSizeBox(bool visible) { if(window->GetNativeWindow()) { window->GetNativeWindow()->SetSizeBox(visible); } } bool GuiWindow::DefaultBehaviorStyleController::GetIconVisible() { if(window->GetNativeWindow()) { return window->GetNativeWindow()->GetIconVisible(); } else { return false; } } void GuiWindow::DefaultBehaviorStyleController::SetIconVisible(bool visible) { if(window->GetNativeWindow()) { window->GetNativeWindow()->SetIconVisible(visible); } } bool GuiWindow::DefaultBehaviorStyleController::GetTitleBar() { if(window->GetNativeWindow()) { return window->GetNativeWindow()->GetTitleBar(); } else { return false; } } void GuiWindow::DefaultBehaviorStyleController::SetTitleBar(bool visible) { if(window->GetNativeWindow()) { window->GetNativeWindow()->SetTitleBar(visible); } } GuiWindow::IStyleController* GuiWindow::DefaultBehaviorStyleController::CreateTooltipStyle() { return 0; } GuiLabel::IStyleController* GuiWindow::DefaultBehaviorStyleController::CreateShortcutKeyStyle() { return 0; } /*********************************************************************** GuiWindow ***********************************************************************/ void GuiWindow::Moved() { GuiControlHost::Moved(); styleController->SetSizeState(GetNativeWindow()->GetSizeState()); } void GuiWindow::OnNativeWindowChanged() { styleController->InitializeNativeWindowProperties(); GuiControlHost::OnNativeWindowChanged(); } void GuiWindow::OnVisualStatusChanged() { GuiControlHost::OnVisualStatusChanged(); } void GuiWindow::MouseClickedOnOtherWindow(GuiWindow* window) { } compositions::GuiGraphicsComposition* GuiWindow::GetAltComposition() { return boundsComposition; } compositions::IGuiAltActionHost* GuiWindow::GetPreviousAltHost() { return previousAltHost; } void GuiWindow::OnActivatedAltHost(IGuiAltActionHost* previousHost) { previousAltHost = previousHost; } void GuiWindow::OnDeactivatedAltHost() { previousAltHost = 0; } void GuiWindow::CollectAltActions(collections::Group& actions) { IGuiAltActionHost::CollectAltActionsFromControl(this, actions); } GuiWindow::GuiWindow(IStyleController* _styleController) :GuiControlHost(_styleController) ,styleController(_styleController) ,previousAltHost(0) { INativeWindow* window=GetCurrentController()->WindowService()->CreateNativeWindow(); styleController->AttachWindow(this); SetNativeWindow(window); GetApplication()->RegisterWindow(this); ClipboardUpdated.SetAssociatedComposition(GetBoundsComposition()); } GuiWindow::~GuiWindow() { FinalizeAggregation(); GetApplication()->UnregisterWindow(this); INativeWindow* window=host->GetNativeWindow(); if(window) { SetNativeWindow(0); GetCurrentController()->WindowService()->DestroyNativeWindow(window); } } IDescriptable* GuiWindow::QueryService(const WString& identifier) { if (identifier == IGuiAltActionHost::Identifier) { return (IGuiAltActionHost*)this; } else { return GuiControlHost::QueryService(identifier); } } void GuiWindow::MoveToScreenCenter() { INativeScreen* screen=GetRelatedScreen(); if(screen) { Rect screenBounds=screen->GetClientBounds(); Rect windowBounds=GetBounds(); SetBounds( Rect( Point( screenBounds.Left()+(screenBounds.Width()-windowBounds.Width())/2, screenBounds.Top()+(screenBounds.Height()-windowBounds.Height())/2 ), windowBounds.GetSize() ) ); } } bool GuiWindow::GetMaximizedBox() { return styleController->GetMaximizedBox(); } void GuiWindow::SetMaximizedBox(bool visible) { styleController->SetMaximizedBox(visible); } bool GuiWindow::GetMinimizedBox() { return styleController->GetMinimizedBox(); } void GuiWindow::SetMinimizedBox(bool visible) { styleController->SetMinimizedBox(visible); } bool GuiWindow::GetBorder() { return styleController->GetBorder(); } void GuiWindow::SetBorder(bool visible) { styleController->SetBorder(visible); } bool GuiWindow::GetSizeBox() { return styleController->GetSizeBox(); } void GuiWindow::SetSizeBox(bool visible) { styleController->SetSizeBox(visible); } bool GuiWindow::GetIconVisible() { return styleController->GetIconVisible(); } void GuiWindow::SetIconVisible(bool visible) { styleController->SetIconVisible(visible); } bool GuiWindow::GetTitleBar() { return styleController->GetTitleBar(); } void GuiWindow::SetTitleBar(bool visible) { styleController->SetTitleBar(visible); } void GuiWindow::ShowModal(GuiWindow* owner, const Func& callback) { owner->SetEnabled(false); GetNativeWindow()->SetParent(owner->GetNativeWindow()); auto container = CreateEventHandlerContainer(); container->handler = WindowClosed.AttachLambda([=](GuiGraphicsComposition* sender, GuiEventArgs& arguments) { GetApplication()->InvokeInMainThread([=]() { WindowClosed.Detach(container->handler); GetNativeWindow()->SetParent(0); callback(); owner->SetEnabled(true); owner->SetActivated(); }); }); Show(); } void GuiWindow::ShowModalAndDelete(GuiWindow* owner, const Func& callback) { owner->SetEnabled(false); GetNativeWindow()->SetParent(owner->GetNativeWindow()); WindowClosed.AttachLambda([=](GuiGraphicsComposition* sender, GuiEventArgs& arguments) { GetApplication()->InvokeInMainThread([=]() { GetNativeWindow()->SetParent(0); callback(); owner->SetEnabled(true); owner->SetActivated(); delete this; }); }); Show(); } /*********************************************************************** GuiPopup ***********************************************************************/ void GuiPopup::MouseClickedOnOtherWindow(GuiWindow* window) { Hide(); } void GuiPopup::PopupOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { GetApplication()->RegisterPopupOpened(this); } void GuiPopup::PopupClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { GetApplication()->RegisterPopupClosed(this); INativeWindow* window=GetNativeWindow(); if(window) { window->SetParent(0); } } GuiPopup::GuiPopup(IStyleController* _styleController) :GuiWindow(_styleController) { SetMinimizedBox(false); SetMaximizedBox(false); SetSizeBox(false); SetTitleBar(false); SetShowInTaskBar(false); GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); WindowOpened.AttachMethod(this, &GuiPopup::PopupOpened); WindowClosed.AttachMethod(this, &GuiPopup::PopupClosed); } GuiPopup::~GuiPopup() { GetApplication()->RegisterPopupClosed(this); } bool GuiPopup::IsClippedByScreen(Point location) { SetBounds(Rect(location, GetBounds().GetSize())); INativeWindow* window=GetNativeWindow(); if(window) { INativeScreen* screen=GetCurrentController()->ScreenService()->GetScreen(window); if(screen) { Rect screenBounds=screen->GetClientBounds(); Rect windowBounds=window->GetBounds(); return !screenBounds.Contains(windowBounds.LeftTop()) || !screenBounds.Contains(windowBounds.RightBottom()); } } return true; } void GuiPopup::ShowPopup(Point location, INativeScreen* screen) { INativeWindow* window=GetNativeWindow(); if(window) { if (!screen) { SetBounds(Rect(location, GetBounds().GetSize())); screen = GetCurrentController()->ScreenService()->GetScreen(window); } if(screen) { Rect screenBounds=screen->GetClientBounds(); Size size=window->GetBounds().GetSize(); if(location.xscreenBounds.x2) { location.x=screenBounds.x2-size.x; } if(location.yscreenBounds.y2) { location.y=screenBounds.y2-size.y; } } SetBounds(Rect(location, GetBounds().GetSize())); bool value=GetNativeWindow()->IsEnabledActivate(); ShowDeactivated(); } } void GuiPopup::ShowPopup(GuiControl* control, Rect bounds, bool preferredTopBottomSide) { INativeWindow* window=GetNativeWindow(); if(window) { Point locations[4]; Size size=window->GetBounds().GetSize(); GuiControlHost* controlHost=control->GetBoundsComposition()->GetRelatedControlHost(); if(controlHost) { INativeWindow* controlWindow=controlHost->GetNativeWindow(); if(controlWindow) { Point controlClientOffset=control->GetBoundsComposition()->GetGlobalBounds().LeftTop(); Point controlWindowOffset=controlWindow->GetClientBoundsInScreen().LeftTop(); bounds.x1+=controlClientOffset.x+controlWindowOffset.x; bounds.x2+=controlClientOffset.x+controlWindowOffset.x; bounds.y1+=controlClientOffset.y+controlWindowOffset.y; bounds.y2+=controlClientOffset.y+controlWindowOffset.y; if(preferredTopBottomSide) { locations[0]=Point(bounds.x1, bounds.y2); locations[1]=Point(bounds.x2-size.x, bounds.y2); locations[2]=Point(bounds.x1, bounds.y1-size.y); locations[3]=Point(bounds.x2-size.x, bounds.y1-size.y); } else { locations[0]=Point(bounds.x2, bounds.y1); locations[1]=Point(bounds.x2, bounds.y2-size.y); locations[2]=Point(bounds.x1-size.x, bounds.y1); locations[3]=Point(bounds.x1-size.x, bounds.y2-size.y); } window->SetParent(controlWindow); for(vint i=0;i<4;i++) { if(!IsClippedByScreen(locations[i])) { ShowPopup(locations[i]); return; } } ShowPopup(locations[0], GetCurrentController()->ScreenService()->GetScreen(controlWindow)); } } } } void GuiPopup::ShowPopup(GuiControl* control, Point location) { INativeWindow* window=GetNativeWindow(); if(window) { Point locations[4]; Size size=window->GetBounds().GetSize(); Rect controlBounds=control->GetBoundsComposition()->GetGlobalBounds(); GuiControlHost* controlHost=control->GetBoundsComposition()->GetRelatedControlHost(); if(controlHost) { INativeWindow* controlWindow=controlHost->GetNativeWindow(); if(controlWindow) { Point controlClientOffset=controlWindow->GetClientBoundsInScreen().LeftTop(); vint x=controlBounds.x1+controlClientOffset.x+location.x; vint y=controlBounds.y1+controlClientOffset.y+location.y; window->SetParent(controlWindow); ShowPopup(Point(x, y), GetCurrentController()->ScreenService()->GetScreen(controlWindow)); } } } } void GuiPopup::ShowPopup(GuiControl* control, bool preferredTopBottomSide) { INativeWindow* window=GetNativeWindow(); if(window) { Rect bounds(Point(0, 0), control->GetBoundsComposition()->GetBounds().GetSize()); ShowPopup(control, bounds, preferredTopBottomSide); } } /*********************************************************************** GuiPopup ***********************************************************************/ void GuiTooltip::GlobalTimer() { SetClientSize(GetClientSize()); } void GuiTooltip::TooltipOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { } void GuiTooltip::TooltipClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { SetTemporaryContentControl(0); } GuiTooltip::GuiTooltip(IStyleController* _styleController) :GuiPopup(_styleController) ,temporaryContentControl(0) { GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GetContainerComposition()->SetPreferredMinSize(Size(20, 10)); GetCurrentController()->CallbackService()->InstallListener(this); WindowOpened.AttachMethod(this, &GuiTooltip::TooltipOpened); WindowClosed.AttachMethod(this, &GuiTooltip::TooltipClosed); } GuiTooltip::~GuiTooltip() { GetCurrentController()->CallbackService()->UninstallListener(this); } vint GuiTooltip::GetPreferredContentWidth() { return GetContainerComposition()->GetPreferredMinSize().x; } void GuiTooltip::SetPreferredContentWidth(vint value) { GetContainerComposition()->SetPreferredMinSize(Size(value, 10)); } GuiControl* GuiTooltip::GetTemporaryContentControl() { return temporaryContentControl; } void GuiTooltip::SetTemporaryContentControl(GuiControl* control) { if(temporaryContentControl && HasChild(temporaryContentControl)) { GetContainerComposition()->RemoveChild(temporaryContentControl->GetBoundsComposition()); temporaryContentControl=0; } temporaryContentControl=control; if(control) { control->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); AddChild(control); } } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUIBINDABLELISTCONTROL.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace list; using namespace tree; using namespace reflection::description; using namespace templates; Value ReadProperty(const Value& thisObject, const WString& propertyName) { if (!thisObject.IsNull() && propertyName != L"") { auto td = thisObject.GetTypeDescriptor(); auto info = td->GetPropertyByName(propertyName, true); if (info && info->IsReadable()) { return info->GetValue(thisObject); } else { return Value(); } } return thisObject; } void WriteProperty(Value& thisObject, const WString& propertyName, const Value& newValue) { if (!thisObject.IsNull() && propertyName != L"") { auto td = thisObject.GetTypeDescriptor(); auto info = td->GetPropertyByName(propertyName, true); if (info && info->IsWritable()) { info->SetValue(thisObject, newValue); } } } WString GetValueText(Value& value) { if (auto td = value.GetTypeDescriptor()) { if (auto st = td->GetSerializableType()) { WString result; st->Serialize(value, result); return result; } return L"<" + td->GetTypeName() + L">"; } return L""; } /*********************************************************************** GuiBindableTextList::ItemSource ***********************************************************************/ GuiBindableTextList::ItemSource::ItemSource() { } GuiBindableTextList::ItemSource::~ItemSource() { SetItemSource(nullptr); } Ptr GuiBindableTextList::ItemSource::GetItemSource() { return itemSource; } void GuiBindableTextList::ItemSource::SetItemSource(Ptr _itemSource) { vint oldCount = 0; if (itemSource) { oldCount = itemSource->GetCount(); } if (itemChangedEventHandler) { auto ol = itemSource.Cast(); ol->ItemChanged.Remove(itemChangedEventHandler); } itemSource = nullptr; itemChangedEventHandler = nullptr; if (_itemSource) { if (auto ol = _itemSource.Cast()) { itemSource = ol; itemChangedEventHandler = ol->ItemChanged.Add([this](vint start, vint oldCount, vint newCount) { InvokeOnItemModified(start, oldCount, newCount); }); } else if (auto rl = _itemSource.Cast()) { itemSource = rl; } else { itemSource = IValueList::Create(GetLazyList(_itemSource)); } } InvokeOnItemModified(0, oldCount, itemSource ? itemSource->GetCount() : 0); } description::Value GuiBindableTextList::ItemSource::Get(vint index) { if (!itemSource) return Value(); return itemSource->Get(index); } void GuiBindableTextList::ItemSource::UpdateBindingProperties() { InvokeOnItemModified(0, Count(), Count()); } // ===================== GuiListControl::IItemProvider ===================== vint GuiBindableTextList::ItemSource::Count() { if (!itemSource) return 0; return itemSource->GetCount(); } IDescriptable* GuiBindableTextList::ItemSource::RequestView(const WString& identifier) { if (identifier == GuiListControl::IItemBindingView::Identifier) { return (GuiListControl::IItemBindingView*)this; } else if (identifier == GuiListControl::IItemPrimaryTextView::Identifier) { return (GuiListControl::IItemPrimaryTextView*)this; } else if (identifier == TextItemStyleProvider::ITextItemView::Identifier) { return (TextItemStyleProvider::ITextItemView*)this; } else { return 0; } } void GuiBindableTextList::ItemSource::ReleaseView(IDescriptable* view) { } // ===================== GuiListControl::IItemBindingView ===================== description::Value GuiBindableTextList::ItemSource::GetBindingValue(vint itemIndex) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount()) { return itemSource->Get(itemIndex); } } return Value(); } // ===================== GuiListControl::IItemPrimaryTextView ===================== WString GuiBindableTextList::ItemSource::GetPrimaryTextViewText(vint itemIndex) { return GetText(itemIndex); } bool GuiBindableTextList::ItemSource::ContainsPrimaryText(vint itemIndex) { if (!itemSource) return false; return 0 <= itemIndex && itemIndex < itemSource->GetCount(); } // ===================== list::TextItemStyleProvider::ITextItemView ===================== WString GuiBindableTextList::ItemSource::GetText(vint itemIndex) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount()) { return GetValueText(ReadProperty(itemSource->Get(itemIndex), textProperty)); } } return L""; } bool GuiBindableTextList::ItemSource::GetChecked(vint itemIndex) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount()) { auto value = ReadProperty(itemSource->Get(itemIndex), checkedProperty); if (value.GetTypeDescriptor() == description::GetTypeDescriptor()) { return UnboxValue(value); } } } return false; } void GuiBindableTextList::ItemSource::SetCheckedSilently(vint itemIndex, bool value) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount()) { auto thisValue = itemSource->Get(itemIndex); WriteProperty(thisValue, checkedProperty, BoxValue(value)); } } } /*********************************************************************** GuiBindableTextList ***********************************************************************/ GuiBindableTextList::GuiBindableTextList(IStyleProvider* _styleProvider, list::TextItemStyleProvider::IBulletFactory* _bulletFactory) :GuiVirtualTextList(_styleProvider, _bulletFactory, new ItemSource) { itemSource = dynamic_cast(GetItemProvider()); TextPropertyChanged.SetAssociatedComposition(boundsComposition); TextPropertyChanged.SetAssociatedComposition(boundsComposition); } GuiBindableTextList::~GuiBindableTextList() { } Ptr GuiBindableTextList::GetItemSource() { return itemSource->GetItemSource(); } void GuiBindableTextList::SetItemSource(Ptr _itemSource) { itemSource->SetItemSource(_itemSource); } const WString& GuiBindableTextList::GetTextProperty() { return itemSource->textProperty; } void GuiBindableTextList::SetTextProperty(const WString& value) { if (itemSource->textProperty != value) { itemSource->textProperty = value; itemSource->UpdateBindingProperties(); TextPropertyChanged.Execute(GetNotifyEventArguments()); } } const WString& GuiBindableTextList::GetCheckedProperty() { return itemSource->checkedProperty; } void GuiBindableTextList::SetCheckedProperty(const WString& value) { if (itemSource->checkedProperty != value) { itemSource->checkedProperty = value; itemSource->UpdateBindingProperties(); CheckedPropertyChanged.Execute(GetNotifyEventArguments()); } } description::Value GuiBindableTextList::GetSelectedItem() { vint index = GetSelectedItemIndex(); if (index == -1) return Value(); return itemSource->Get(index); } /*********************************************************************** GuiBindableListView::ItemSource ***********************************************************************/ GuiBindableListView::ItemSource::ItemSource() :columns(this) , dataColumns(this) { } GuiBindableListView::ItemSource::~ItemSource() { SetItemSource(nullptr); } Ptr GuiBindableListView::ItemSource::GetItemSource() { return itemSource; } void GuiBindableListView::ItemSource::SetItemSource(Ptr _itemSource) { vint oldCount = 0; if (itemSource) { oldCount = itemSource->GetCount(); } if (itemChangedEventHandler) { auto ol = itemSource.Cast(); ol->ItemChanged.Remove(itemChangedEventHandler); } itemSource = nullptr; itemChangedEventHandler = nullptr; if (_itemSource) { if (auto ol = _itemSource.Cast()) { itemSource = ol; itemChangedEventHandler = ol->ItemChanged.Add([this](vint start, vint oldCount, vint newCount) { InvokeOnItemModified(start, oldCount, newCount); }); } else if (auto rl = _itemSource.Cast()) { itemSource = rl; } else { itemSource = IValueList::Create(GetLazyList(_itemSource)); } } InvokeOnItemModified(0, oldCount, itemSource ? itemSource->GetCount() : 0); } description::Value GuiBindableListView::ItemSource::Get(vint index) { if (!itemSource) return Value(); return itemSource->Get(index); } void GuiBindableListView::ItemSource::UpdateBindingProperties() { InvokeOnItemModified(0, Count(), Count()); } bool GuiBindableListView::ItemSource::NotifyUpdate(vint start, vint count) { if (!itemSource) return false; if (start<0 || start >= itemSource->GetCount() || count <= 0 || start + count > itemSource->GetCount()) { return false; } else { InvokeOnItemModified(start, count, count); return true; } } list::ListViewDataColumns& GuiBindableListView::ItemSource::GetDataColumns() { return dataColumns; } list::ListViewColumns& GuiBindableListView::ItemSource::GetColumns() { return columns; } // ===================== list::IListViewItemProvider ===================== void GuiBindableListView::ItemSource::NotifyAllItemsUpdate() { NotifyUpdate(0, Count()); } void GuiBindableListView::ItemSource::NotifyAllColumnsUpdate() { for (vint i = 0; i < columnItemViewCallbacks.Count(); i++) { columnItemViewCallbacks[i]->OnColumnChanged(); } } // ===================== GuiListControl::IItemProvider ===================== vint GuiBindableListView::ItemSource::Count() { if (!itemSource) return 0; return itemSource->GetCount(); } IDescriptable* GuiBindableListView::ItemSource::RequestView(const WString& identifier) { if (identifier == GuiListControl::IItemBindingView::Identifier) { return (GuiListControl::IItemBindingView*)this; } else if(identifier==ListViewItemStyleProvider::IListViewItemView::Identifier) { return (ListViewItemStyleProvider::IListViewItemView*)this; } else if(identifier==ListViewColumnItemArranger::IColumnItemView::Identifier) { return (ListViewColumnItemArranger::IColumnItemView*)this; } else if(identifier==GuiListControl::IItemPrimaryTextView::Identifier) { return (GuiListControl::IItemPrimaryTextView*)this; } else { return 0; } } void GuiBindableListView::ItemSource::ReleaseView(IDescriptable* view) { } // ===================== GuiListControl::IItemBindingView ===================== description::Value GuiBindableListView::ItemSource::GetBindingValue(vint itemIndex) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount()) { return itemSource->Get(itemIndex); } } return Value(); } // ===================== GuiListControl::IItemPrimaryTextView ===================== WString GuiBindableListView::ItemSource::GetPrimaryTextViewText(vint itemIndex) { return GetText(itemIndex); } bool GuiBindableListView::ItemSource::ContainsPrimaryText(vint itemIndex) { return true; } // ===================== list::ListViewItemStyleProvider::IListViewItemView ===================== Ptr GuiBindableListView::ItemSource::GetSmallImage(vint itemIndex) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount()) { auto value = ReadProperty(itemSource->Get(itemIndex), smallImageProperty); return value.GetSharedPtr().Cast(); } } return nullptr; } Ptr GuiBindableListView::ItemSource::GetLargeImage(vint itemIndex) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount()) { auto value = ReadProperty(itemSource->Get(itemIndex), largeImageProperty); return value.GetSharedPtr().Cast(); } } return nullptr; } WString GuiBindableListView::ItemSource::GetText(vint itemIndex) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount() && columns.Count()>0) { return GetValueText(ReadProperty(itemSource->Get(itemIndex), columns[0]->GetTextProperty())); } } return L""; } WString GuiBindableListView::ItemSource::GetSubItem(vint itemIndex, vint index) { if (itemSource) { if (0 <= itemIndex && itemIndex < itemSource->GetCount() && 0 <= index && index < columns.Count() - 1) { return GetValueText(ReadProperty(itemSource->Get(itemIndex), columns[index + 1]->GetTextProperty())); } } return L""; } vint GuiBindableListView::ItemSource::GetDataColumnCount() { return dataColumns.Count(); } vint GuiBindableListView::ItemSource::GetDataColumn(vint index) { return dataColumns[index]; } // ===================== list::ListViewColumnItemArranger::IColumnItemView ===================== bool GuiBindableListView::ItemSource::AttachCallback(ListViewColumnItemArranger::IColumnItemViewCallback* value) { if(columnItemViewCallbacks.Contains(value)) { return false; } else { columnItemViewCallbacks.Add(value); return true; } } bool GuiBindableListView::ItemSource::DetachCallback(ListViewColumnItemArranger::IColumnItemViewCallback* value) { vint index = columnItemViewCallbacks.IndexOf(value); if (index == -1) { return false; } else { columnItemViewCallbacks.Remove(value); return true; } } vint GuiBindableListView::ItemSource::GetColumnCount() { return columns.Count(); } WString GuiBindableListView::ItemSource::GetColumnText(vint index) { if (index < 0 || index >= columns.Count()) { return L""; } else { return columns[index]->GetText(); } } vint GuiBindableListView::ItemSource::GetColumnSize(vint index) { if (index < 0 || index >= columns.Count()) { return 0; } else { return columns[index]->GetSize(); } } void GuiBindableListView::ItemSource::SetColumnSize(vint index, vint value) { if (index >= 0 && index < columns.Count()) { columns[index]->SetSize(value); } } GuiMenu* GuiBindableListView::ItemSource::GetDropdownPopup(vint index) { if (index < 0 || index >= columns.Count()) { return 0; } else { return columns[index]->GetDropdownPopup(); } } GuiListViewColumnHeader::ColumnSortingState GuiBindableListView::ItemSource::GetSortingState(vint index) { if (index < 0 || index >= columns.Count()) { return GuiListViewColumnHeader::NotSorted; } else { return columns[index]->GetSortingState(); } } /*********************************************************************** GuiBindableListView ***********************************************************************/ GuiBindableListView::GuiBindableListView(IStyleProvider* _styleProvider) :GuiVirtualListView(_styleProvider, new ItemSource) { itemSource = dynamic_cast(GetItemProvider()); LargeImagePropertyChanged.SetAssociatedComposition(boundsComposition); SmallImagePropertyChanged.SetAssociatedComposition(boundsComposition); } GuiBindableListView::~GuiBindableListView() { } list::ListViewDataColumns& GuiBindableListView::GetDataColumns() { return itemSource->GetDataColumns(); } list::ListViewColumns& GuiBindableListView::GetColumns() { return itemSource->GetColumns(); } Ptr GuiBindableListView::GetItemSource() { return itemSource->GetItemSource(); } void GuiBindableListView::SetItemSource(Ptr _itemSource) { itemSource->SetItemSource(_itemSource); } const WString& GuiBindableListView::GetLargeImageProperty() { return itemSource->largeImageProperty; } void GuiBindableListView::SetLargeImageProperty(const WString& value) { if (itemSource->largeImageProperty != value) { itemSource->largeImageProperty = value; itemSource->UpdateBindingProperties(); LargeImagePropertyChanged.Execute(GetNotifyEventArguments()); } } const WString& GuiBindableListView::GetSmallImageProperty() { return itemSource->smallImageProperty; } void GuiBindableListView::SetSmallImageProperty(const WString& value) { if (itemSource->smallImageProperty != value) { itemSource->smallImageProperty = value; itemSource->UpdateBindingProperties(); SmallImagePropertyChanged.Execute(GetNotifyEventArguments()); } } description::Value GuiBindableListView::GetSelectedItem() { vint index = GetSelectedItemIndex(); if (index == -1) return Value(); return itemSource->Get(index); } /*********************************************************************** GuiBindableTreeView::ItemSourceNode ***********************************************************************/ void GuiBindableTreeView::ItemSourceNode::PrepareChildren() { if (!childrenVirtualList) { auto value = ReadProperty(itemSource, rootProvider->childrenProperty); if (auto td = value.GetTypeDescriptor()) { if (td->CanConvertTo(description::GetTypeDescriptor())) { auto ol = UnboxValue>(value); itemChangedEventHandler = ol->ItemChanged.Add([this](vint start, vint oldCount, vint newCount) { callback->OnBeforeItemModified(this, start, oldCount, newCount); children.RemoveRange(start, oldCount); for (vint i = 0; i < newCount; i++) { Value value = childrenVirtualList->Get(start + i); auto node = new ItemSourceNode(value, this); children.Insert(start + i, node); } callback->OnAfterItemModified(this, start, oldCount, newCount); }); childrenVirtualList = ol; } else if (td->CanConvertTo(description::GetTypeDescriptor())) { childrenVirtualList = UnboxValue>(value); } else if (td->CanConvertTo(description::GetTypeDescriptor())) { auto e = UnboxValue>(value); childrenVirtualList = IValueList::Create(GetLazyList(e)); } } if (!childrenVirtualList) { childrenVirtualList = IValueList::Create(); } vint count = childrenVirtualList->GetCount(); for (vint i = 0; i < count; i++) { Value value = childrenVirtualList->Get(i); auto node = new ItemSourceNode(value, this); children.Add(node); } } } void GuiBindableTreeView::ItemSourceNode::UnprepareChildren() { if (itemChangedEventHandler) { auto ol = childrenVirtualList.Cast(); ol->ItemChanged.Remove(itemChangedEventHandler); itemChangedEventHandler = nullptr; } childrenVirtualList = nullptr; FOREACH(Ptr, node, children) { node->UnprepareChildren(); } children.Clear(); } GuiBindableTreeView::ItemSourceNode::ItemSourceNode(const description::Value& _itemSource, ItemSourceNode* _parent) :itemSource(_itemSource) , rootProvider(_parent->rootProvider) , parent(_parent) , callback(_parent->callback) { } GuiBindableTreeView::ItemSourceNode::ItemSourceNode(ItemSource* _rootProvider) :rootProvider(_rootProvider) , parent(nullptr) , callback(_rootProvider) { } GuiBindableTreeView::ItemSourceNode::~ItemSourceNode() { SetItemSource(Value()); } description::Value GuiBindableTreeView::ItemSourceNode::GetItemSource() { return itemSource; } void GuiBindableTreeView::ItemSourceNode::SetItemSource(const description::Value& _itemSource) { vint oldCount = GetChildCount(); UnprepareChildren(); itemSource = _itemSource; vint newCount = GetChildCount(); callback->OnBeforeItemModified(this, 0, oldCount, newCount); callback->OnAfterItemModified(this, 0, oldCount, newCount); } bool GuiBindableTreeView::ItemSourceNode::GetExpanding() { return this == rootProvider->rootNode.Obj() ? true : expanding; } void GuiBindableTreeView::ItemSourceNode::SetExpanding(bool value) { if (this != rootProvider->rootNode.Obj() && expanding != value) { expanding = value; if (expanding) { callback->OnItemExpanded(this); } else { callback->OnItemCollapsed(this); } } } vint GuiBindableTreeView::ItemSourceNode::CalculateTotalVisibleNodes() { if (!GetExpanding()) { return 1; } PrepareChildren(); vint count = 1; FOREACH(Ptr, child, children) { count += child->CalculateTotalVisibleNodes(); } return count; } vint GuiBindableTreeView::ItemSourceNode::GetChildCount() { PrepareChildren(); return children.Count(); } tree::INodeProvider* GuiBindableTreeView::ItemSourceNode::GetParent() { return parent; } tree::INodeProvider* GuiBindableTreeView::ItemSourceNode::GetChild(vint index) { PrepareChildren(); if (0 <= index && index < children.Count()) { return children[index].Obj(); } return 0; } void GuiBindableTreeView::ItemSourceNode::Increase() { } void GuiBindableTreeView::ItemSourceNode::Release() { } /*********************************************************************** GuiBindableTreeView::ItemSource ***********************************************************************/ GuiBindableTreeView::ItemSource::ItemSource() { rootNode = new ItemSourceNode(this); } GuiBindableTreeView::ItemSource::~ItemSource() { } description::Value GuiBindableTreeView::ItemSource::GetItemSource() { return rootNode->GetItemSource(); } void GuiBindableTreeView::ItemSource::SetItemSource(const description::Value& _itemSource) { rootNode->SetItemSource(_itemSource); } void GuiBindableTreeView::ItemSource::UpdateBindingProperties(bool updateChildrenProperty) { vint oldCount = rootNode->GetChildCount(); if (updateChildrenProperty) { rootNode->UnprepareChildren(); } vint newCount = rootNode->GetChildCount(); OnBeforeItemModified(rootNode.Obj(), 0, oldCount, newCount); OnAfterItemModified(rootNode.Obj(), 0, oldCount, newCount); } // ===================== tree::INodeRootProvider ===================== tree::INodeProvider* GuiBindableTreeView::ItemSource::GetRootNode() { return rootNode.Obj(); } IDescriptable* GuiBindableTreeView::ItemSource::RequestView(const WString& identifier) { if(identifier==INodeItemBindingView::Identifier) { return (INodeItemBindingView*)this; } else if(identifier==INodeItemPrimaryTextView::Identifier) { return (INodeItemPrimaryTextView*)this; } else if(identifier==ITreeViewItemView::Identifier) { return (ITreeViewItemView*)this; } else { return 0; } } void GuiBindableTreeView::ItemSource::ReleaseView(IDescriptable* view) { } // ===================== tree::INodeItemBindingView ===================== description::Value GuiBindableTreeView::ItemSource::GetBindingValue(tree::INodeProvider* node) { if (auto itemSourceNode = dynamic_cast(node)) { return itemSourceNode->GetItemSource(); } return Value(); } // ===================== tree::INodeItemPrimaryTextView ===================== WString GuiBindableTreeView::ItemSource::GetPrimaryTextViewText(tree::INodeProvider* node) { return GetNodeText(node); } // ===================== tree::ITreeViewItemView ===================== Ptr GuiBindableTreeView::ItemSource::GetNodeImage(tree::INodeProvider* node) { if (auto itemSourceNode = dynamic_cast(node)) { auto value = ReadProperty(itemSourceNode->GetItemSource(), imageProperty); return value.GetSharedPtr().Cast(); } return nullptr; } WString GuiBindableTreeView::ItemSource::GetNodeText(tree::INodeProvider* node) { if (auto itemSourceNode = dynamic_cast(node)) { return GetValueText(ReadProperty(itemSourceNode->GetItemSource(), textProperty)); } return L""; } /*********************************************************************** GuiBindableTreeView ***********************************************************************/ GuiBindableTreeView::GuiBindableTreeView(IStyleProvider* _styleProvider) :GuiVirtualTreeView(_styleProvider, new ItemSource) { itemSource = dynamic_cast(GetNodeRootProvider()); TextPropertyChanged.SetAssociatedComposition(boundsComposition); ImagePropertyChanged.SetAssociatedComposition(boundsComposition); ChildrenPropertyChanged.SetAssociatedComposition(boundsComposition); } GuiBindableTreeView::~GuiBindableTreeView() { } description::Value GuiBindableTreeView::GetItemSource() { return itemSource->GetItemSource(); } void GuiBindableTreeView::SetItemSource(description::Value _itemSource) { itemSource->SetItemSource(_itemSource); } const WString& GuiBindableTreeView::GetTextProperty() { return itemSource->textProperty; } void GuiBindableTreeView::SetTextProperty(const WString& value) { if (itemSource->textProperty != value) { itemSource->textProperty = value; itemSource->UpdateBindingProperties(false); TextPropertyChanged.Execute(GetNotifyEventArguments()); } } const WString& GuiBindableTreeView::GetImageProperty() { return itemSource->imageProperty; } void GuiBindableTreeView::SetImageProperty(const WString& value) { if (itemSource->imageProperty != value) { itemSource->imageProperty = value; itemSource->UpdateBindingProperties(false); ImagePropertyChanged.Execute(GetNotifyEventArguments()); } } const WString& GuiBindableTreeView::GetChildrenProperty() { return itemSource->childrenProperty; } void GuiBindableTreeView::SetChildrenProperty(const WString& value) { if (itemSource->childrenProperty != value) { itemSource->childrenProperty = value; itemSource->UpdateBindingProperties(true); ChildrenPropertyChanged.Execute(GetNotifyEventArguments()); } } description::Value GuiBindableTreeView::GetSelectedItem() { vint index = GetSelectedItemIndex(); if (index == -1) return Value(); Value result; if (auto node = nodeItemView->RequestNode(index)) { if (auto itemSourceNode = dynamic_cast(node)) { result = itemSourceNode->GetItemSource(); } nodeItemView->ReleaseNode(node); } return result; } namespace list { /*********************************************************************** GuiBindableDataColumn ***********************************************************************/ BindableDataColumn::BindableDataColumn() :dataProvider(nullptr) { } BindableDataColumn::~BindableDataColumn() { } void BindableDataColumn::SaveCellData(vint row, IDataEditor* dataEditor) { if (auto editor = dynamic_cast(dataEditor)) { SetCellValue(row, editor->GetEditedCellValue()); } if (commandExecutor) { commandExecutor->OnDataProviderItemModified(row, 1, 1); } } WString BindableDataColumn::GetCellText(vint row) { return GetValueText(GetCellValue(row)); } description::Value BindableDataColumn::GetCellValue(vint row) { if (dataProvider->itemSource) { if (0 <= row && row < dataProvider->itemSource->GetCount()) { return ReadProperty(dataProvider->itemSource->Get(row), valueProperty); } } return Value(); } void BindableDataColumn::SetCellValue(vint row, description::Value value) { if (dataProvider->itemSource) { if (0 <= row && row < dataProvider->itemSource->GetCount()) { auto rowValue = dataProvider->itemSource->Get(row); return WriteProperty(rowValue, valueProperty, value); } } } const WString& BindableDataColumn::GetValueProperty() { return valueProperty; } void BindableDataColumn::SetValueProperty(const WString& value) { if (valueProperty != value) { valueProperty = value; if (commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } compositions::GuiEventArgs arguments; ValuePropertyChanged.Execute(arguments); } } const description::Value& BindableDataColumn::GetViewModelContext() { return dataProvider->viewModelContext; } /*********************************************************************** GuiBindableDataProvider ***********************************************************************/ BindableDataProvider::BindableDataProvider(const description::Value& _viewModelContext) :viewModelContext(_viewModelContext) { } BindableDataProvider::~BindableDataProvider() { SetItemSource(nullptr); } Ptr BindableDataProvider::GetItemSource() { return itemSource; } void BindableDataProvider::SetItemSource(Ptr _itemSource) { vint oldCount = 0; if (itemSource) { oldCount = itemSource->GetCount(); } if (itemChangedEventHandler) { auto ol = itemSource.Cast(); ol->ItemChanged.Remove(itemChangedEventHandler); } itemSource = nullptr; itemChangedEventHandler = nullptr; if (_itemSource) { if (auto ol = _itemSource.Cast()) { itemSource = ol; itemChangedEventHandler = ol->ItemChanged.Add([this](vint start, vint oldCount, vint newCount) { commandExecutor->OnDataProviderItemModified(start, oldCount, newCount); }); } else if (auto rl = _itemSource.Cast()) { itemSource = rl; } else { itemSource = IValueList::Create(GetLazyList(_itemSource)); } } commandExecutor->OnDataProviderItemModified(0, oldCount, itemSource ? itemSource->GetCount() : 0); } vint BindableDataProvider::GetRowCount() { if (!itemSource) return 0; return itemSource->GetCount(); } description::Value BindableDataProvider::GetRowValue(vint row) { if (itemSource) { if (0 <= row && row < itemSource->GetCount()) { return itemSource->Get(row); } } return Value(); } bool BindableDataProvider::InsertBindableColumn(vint index, Ptr column) { if (InsertColumnInternal(index, column, true)) { column->dataProvider = this; return true; } else { return false; } } bool BindableDataProvider::AddBindableColumn(Ptr column) { if (AddColumnInternal(column, true)) { column->dataProvider = this; return true; } else { return false; } } bool BindableDataProvider::RemoveBindableColumn(Ptr column) { if (RemoveColumnInternal(column, true)) { column->dataProvider = nullptr; return true; } else { return false; } } bool BindableDataProvider::ClearBindableColumns() { FOREACH(Ptr, column, columns) { column.Cast()->dataProvider = nullptr; } return ClearColumnsInternal(true); } Ptr BindableDataProvider::GetBindableColumn(vint index) { if (0 <= index && index < GetColumnCount()) { return columns[index].Cast(); } else { return nullptr; } } const description::Value& BindableDataProvider::GetViewModelContext() { return viewModelContext; } } /*********************************************************************** GuiBindableDataGrid ***********************************************************************/ GuiBindableDataGrid::GuiBindableDataGrid(IStyleProvider* _styleProvider, const description::Value& _viewModelContext) :GuiVirtualDataGrid(_styleProvider, new BindableDataProvider(_viewModelContext)) { bindableDataProvider = GetStructuredDataProvider()->GetStructuredDataProvider().Cast(); } GuiBindableDataGrid::~GuiBindableDataGrid() { } Ptr GuiBindableDataGrid::GetItemSource() { return bindableDataProvider->GetItemSource(); } void GuiBindableDataGrid::SetItemSource(Ptr _itemSource) { bindableDataProvider->SetItemSource(_itemSource); } bool GuiBindableDataGrid::InsertBindableColumn(vint index, Ptr column) { return bindableDataProvider->InsertBindableColumn(index, column); } bool GuiBindableDataGrid::AddBindableColumn(Ptr column) { return bindableDataProvider->AddBindableColumn(column); } bool GuiBindableDataGrid::RemoveBindableColumn(Ptr column) { return bindableDataProvider->RemoveBindableColumn(column); } bool GuiBindableDataGrid::ClearBindableColumns() { return bindableDataProvider->ClearBindableColumns(); } Ptr GuiBindableDataGrid::GetBindableColumn(vint index) { return bindableDataProvider->GetBindableColumn(index); } description::Value GuiBindableDataGrid::GetSelectedRowValue() { return bindableDataProvider->GetRowValue(GetSelectedCell().row); } description::Value GuiBindableDataGrid::GetSelectedCellValue() { auto cell = GetSelectedCell(); auto column = GetBindableColumn(cell.column); if (column) { return column->GetCellValue(cell.row); } return Value(); } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUICOMBOCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { /*********************************************************************** GuiComboBoxBase::CommandExecutor ***********************************************************************/ GuiComboBoxBase::CommandExecutor::CommandExecutor(GuiComboBoxBase* _combo) :combo(_combo) { } GuiComboBoxBase::CommandExecutor::~CommandExecutor() { } void GuiComboBoxBase::CommandExecutor::SelectItem() { combo->SelectItem(); } /*********************************************************************** GuiComboBoxBase ***********************************************************************/ bool GuiComboBoxBase::IsAltAvailable() { return false; } IGuiMenuService::Direction GuiComboBoxBase::GetSubMenuDirection() { return IGuiMenuService::Horizontal; } void GuiComboBoxBase::SelectItem() { styleController->OnItemSelected(); ItemSelected.Execute(GetNotifyEventArguments()); } void GuiComboBoxBase::OnBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { Size size=GetPreferredMenuClientSize(); size.x=GetBoundsComposition()->GetBounds().Width(); SetPreferredMenuClientSize(size); } GuiComboBoxBase::GuiComboBoxBase(IStyleController* _styleController) :GuiMenuButton(_styleController) { commandExecutor=new CommandExecutor(this); styleController=dynamic_cast(GetStyleController()); styleController->SetCommandExecutor(commandExecutor.Obj()); CreateSubMenu(); SetCascadeAction(false); GetBoundsComposition()->BoundsChanged.AttachMethod(this, &GuiComboBoxBase::OnBoundsChanged); } GuiComboBoxBase::~GuiComboBoxBase() { } /*********************************************************************** GuiComboBoxListControl ***********************************************************************/ void GuiComboBoxListControl::RemoveStyleController() { if (itemStyleController) { SafeDeleteComposition(itemStyleController->GetBoundsComposition()); itemStyleController = nullptr; } } void GuiComboBoxListControl::InstallStyleController(vint itemIndex) { if (itemBindingView != nullptr && itemStyleProvider) { if (itemIndex != -1) { auto item = itemBindingView->GetBindingValue(itemIndex); if (!item.IsNull()) { itemStyleController = itemStyleProvider->CreateItemStyle(item); if (itemStyleController) { itemStyleController->SetText(GetText()); itemStyleController->SetFont(GetFont()); itemStyleController->SetVisuallyEnabled(GetVisuallyEnabled()); auto composition = itemStyleController->GetBoundsComposition(); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); GetContainerComposition()->AddChild(composition); } } } } } void GuiComboBoxListControl::DisplaySelectedContent(vint itemIndex) { if(primaryTextView) { if(itemIndex==-1) { SetText(L""); } else if(primaryTextView->ContainsPrimaryText(itemIndex)) { WString text=primaryTextView->GetPrimaryTextViewText(itemIndex); SetText(text); GetSubMenu()->Hide(); } } RemoveStyleController(); InstallStyleController(itemIndex); } void GuiComboBoxListControl::OnTextChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if (itemStyleController) { itemStyleController->SetText(GetText()); } } void GuiComboBoxListControl::OnFontChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if (itemStyleController) { itemStyleController->SetFont(GetFont()); } auto args = GetNotifyEventArguments(); OnListControlAdoptedSizeInvalidated(nullptr, args); } void GuiComboBoxListControl::OnVisuallyEnabledChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if (itemStyleController) { itemStyleController->SetVisuallyEnabled(GetVisuallyEnabled()); } } void GuiComboBoxListControl::OnListControlAdoptedSizeInvalidated(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { Size expectedSize(0, GetFont().size * 20); Size adoptedSize = containedListControl->GetAdoptedSize(expectedSize); Size clientSize = GetPreferredMenuClientSize(); clientSize.y = adoptedSize.y + GetSubMenu()->GetClientSize().y - containedListControl->GetBoundsComposition()->GetBounds().Height(); SetPreferredMenuClientSize(clientSize); if (GetSubMenuOpening()) { GetSubMenu()->SetClientSize(clientSize); } } void GuiComboBoxListControl::OnListControlSelectionChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { DisplaySelectedContent(GetSelectedIndex()); SelectItem(); SelectedIndexChanged.Execute(GetNotifyEventArguments()); } GuiComboBoxListControl::GuiComboBoxListControl(IStyleController* _styleController, GuiSelectableListControl* _containedListControl) :GuiComboBoxBase(_styleController) , styleController(_styleController) , containedListControl(_containedListControl) { styleController->SetTextVisible(true); TextChanged.AttachMethod(this, &GuiComboBoxListControl::OnTextChanged); FontChanged.AttachMethod(this, &GuiComboBoxListControl::OnFontChanged); VisuallyEnabledChanged.AttachMethod(this, &GuiComboBoxListControl::OnVisuallyEnabledChanged); containedListControl->SetMultiSelect(false); containedListControl->AdoptedSizeInvalidated.AttachMethod(this, &GuiComboBoxListControl::OnListControlAdoptedSizeInvalidated); containedListControl->SelectionChanged.AttachMethod(this, &GuiComboBoxListControl::OnListControlSelectionChanged); auto itemProvider = containedListControl->GetItemProvider(); primaryTextView = dynamic_cast(itemProvider->RequestView(GuiListControl::IItemPrimaryTextView::Identifier)); itemBindingView = dynamic_cast(itemProvider->RequestView(GuiListControl::IItemBindingView::Identifier)); SelectedIndexChanged.SetAssociatedComposition(GetBoundsComposition()); containedListControl->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); GetSubMenu()->GetContainerComposition()->AddChild(containedListControl->GetBoundsComposition()); SetFont(GetFont()); } GuiComboBoxListControl::~GuiComboBoxListControl() { if(primaryTextView) { containedListControl->GetItemProvider()->ReleaseView(primaryTextView); } } GuiSelectableListControl* GuiComboBoxListControl::GetContainedListControl() { return containedListControl; } GuiComboBoxListControl::IItemStyleProvider* GuiComboBoxListControl::GetStyleProvider() { return itemStyleProvider.Obj(); } Ptr GuiComboBoxListControl::SetStyleProvider(Ptr value) { RemoveStyleController(); auto old = itemStyleProvider; if (itemStyleProvider) { itemStyleProvider->DetachComboBox(); } itemStyleProvider = value; if (itemStyleProvider) { itemStyleProvider->AttachComboBox(this); styleController->SetTextVisible(false); InstallStyleController(GetSelectedIndex()); } else { styleController->SetTextVisible(true); } StyleProviderChanged.Execute(GetNotifyEventArguments()); return old; } vint GuiComboBoxListControl::GetSelectedIndex() { if(containedListControl->GetSelectedItems().Count()==1) { return containedListControl->GetSelectedItems()[0]; } else { return -1; } } void GuiComboBoxListControl::SetSelectedIndex(vint value) { containedListControl->SetSelected(value, true); } description::Value GuiComboBoxListControl::GetSelectedItem() { auto selectedIndex = GetSelectedIndex(); if (selectedIndex != -1) { if (itemBindingView) { return itemBindingView->GetBindingValue(selectedIndex); } } return description::Value(); } GuiListControl::IItemProvider* GuiComboBoxListControl::GetItemProvider() { return containedListControl->GetItemProvider(); } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUIDATAGRIDCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { namespace list { using namespace compositions; using namespace collections; const wchar_t* const IDataProvider::Identifier = L"vl::presentation::controls::list::IDataProvider"; /*********************************************************************** DataGridItemProvider ***********************************************************************/ void DataGridItemProvider::InvokeOnItemModified(vint start, vint count, vint newCount) { for(vint i=0;iOnItemModified(start, count, newCount); } } void DataGridItemProvider::InvokeOnColumnChanged() { for(vint i=0;iOnColumnChanged(); } } void DataGridItemProvider::OnDataProviderColumnChanged() { InvokeOnColumnChanged(); } void DataGridItemProvider::OnDataProviderItemModified(vint start, vint count, vint newCount) { InvokeOnItemModified(start, count, newCount); } DataGridItemProvider::DataGridItemProvider(IDataProvider* _dataProvider) :dataProvider(_dataProvider) { dataProvider->SetCommandExecutor(this); } DataGridItemProvider::~DataGridItemProvider() { } IDataProvider* DataGridItemProvider::GetDataProvider() { return dataProvider; } void DataGridItemProvider::SortByColumn(vint column, bool ascending) { dataProvider->SortByColumn(column, ascending); } // ===================== GuiListControl::IItemProvider ===================== bool DataGridItemProvider::AttachCallback(GuiListControl::IItemProviderCallback* value) { if(itemProviderCallbacks.Contains(value)) { return false; } else { itemProviderCallbacks.Add(value); value->OnAttached(this); return true; } } bool DataGridItemProvider::DetachCallback(GuiListControl::IItemProviderCallback* value) { vint index=itemProviderCallbacks.IndexOf(value); if(index==-1) { return false; } else { value->OnAttached(0); itemProviderCallbacks.Remove(value); return true; } } vint DataGridItemProvider::Count() { return dataProvider->GetRowCount(); } IDescriptable* DataGridItemProvider::RequestView(const WString& identifier) { if(identifier==IDataProvider::Identifier) { return dataProvider; } else if(identifier==ListViewItemStyleProvider::IListViewItemView::Identifier) { return (ListViewItemStyleProvider::IListViewItemView*)this; } else if(identifier==ListViewColumnItemArranger::IColumnItemView::Identifier) { return (ListViewColumnItemArranger::IColumnItemView*)this; } else if(identifier==GuiListControl::IItemPrimaryTextView::Identifier) { return (GuiListControl::IItemPrimaryTextView*)this; } else { return 0; } } void DataGridItemProvider::ReleaseView(IDescriptable* view) { } // ===================== GuiListControl::IItemPrimaryTextView ===================== WString DataGridItemProvider::GetPrimaryTextViewText(vint itemIndex) { return GetText(itemIndex); } bool DataGridItemProvider::ContainsPrimaryText(vint itemIndex) { return true; } // ===================== list::ListViewItemStyleProvider::IListViewItemView ===================== Ptr DataGridItemProvider::GetSmallImage(vint itemIndex) { return dataProvider->GetRowSmallImage(itemIndex); } Ptr DataGridItemProvider::GetLargeImage(vint itemIndex) { return dataProvider->GetRowLargeImage(itemIndex); } WString DataGridItemProvider::GetText(vint itemIndex) { return dataProvider->GetCellText(itemIndex, 0); } WString DataGridItemProvider::GetSubItem(vint itemIndex, vint index) { return dataProvider->GetCellText(itemIndex, index+1); } vint DataGridItemProvider::GetDataColumnCount() { return 0; } vint DataGridItemProvider::GetDataColumn(vint index) { return 0; } // ===================== list::ListViewColumnItemArranger::IColumnItemView ===================== bool DataGridItemProvider::AttachCallback(ListViewColumnItemArranger::IColumnItemViewCallback* value) { if(columnItemViewCallbacks.Contains(value)) { return false; } else { columnItemViewCallbacks.Add(value); return true; } } bool DataGridItemProvider::DetachCallback(ListViewColumnItemArranger::IColumnItemViewCallback* value) { vint index=columnItemViewCallbacks.IndexOf(value); if(index==-1) { return false; } else { columnItemViewCallbacks.Remove(value); return true; } } vint DataGridItemProvider::GetColumnCount() { return dataProvider->GetColumnCount(); } WString DataGridItemProvider::GetColumnText(vint index) { return dataProvider->GetColumnText(index); } vint DataGridItemProvider::GetColumnSize(vint index) { return dataProvider->GetColumnSize(index); } void DataGridItemProvider::SetColumnSize(vint index, vint value) { dataProvider->SetColumnSize(index, value); for(vint i=0;iOnColumnChanged(); } } GuiMenu* DataGridItemProvider::GetDropdownPopup(vint index) { return dataProvider->GetColumnPopup(index); } GuiListViewColumnHeader::ColumnSortingState DataGridItemProvider::GetSortingState(vint index) { if(index==dataProvider->GetSortedColumn()) { return dataProvider->IsSortOrderAscending() ?GuiListViewColumnHeader::Ascending :GuiListViewColumnHeader::Descending; } else { return GuiListViewColumnHeader::NotSorted; } } /*********************************************************************** DataGridContentProvider::ItemContent ***********************************************************************/ void DataGridContentProvider::ItemContent::RemoveCellsAndDataVisualizers() { for(vint i=0;iGetBoundsComposition(); if(composition->GetParent()) { composition->GetParent()->RemoveChild(composition); } dataVisualizers[i]=0; } dataVisualizers.Resize(0); for(vint i=0;iGetColumns();i++) { GuiCellComposition* cell=textTable->GetSitedCell(0, i); SafeDeleteComposition(cell); } } IDataVisualizerFactory* DataGridContentProvider::ItemContent::GetDataVisualizerFactory(vint row, vint column) { IDataVisualizerFactory* factory=contentProvider->dataProvider->GetCellDataVisualizerFactory(row, column); if(factory) { return factory; } else if(column==0) { return &contentProvider->mainColumnDataVisualizerFactory; } else { return &contentProvider->subColumnDataVisualizerFactory; } } vint DataGridContentProvider::ItemContent::GetCellColumnIndex(compositions::GuiGraphicsComposition* composition) { for(vint i=0;iGetColumns();i++) { GuiCellComposition* cell=textTable->GetSitedCell(0, i); if(composition==cell) { return i; } } return -1; } void DataGridContentProvider::ItemContent::OnCellButtonUp(compositions::GuiGraphicsComposition* sender, bool openEditor) { vint index=GetCellColumnIndex(sender); if(index!=-1) { if(currentEditor && contentProvider->currentCell.column==index) { return; } GuiListControl::IItemStyleController* itemStyle=contentProvider->listViewItemStyleProvider->GetItemStyleControllerFromItemContent(this); vint currentRow=contentProvider->dataGrid->GetArranger()->GetVisibleIndex(itemStyle); IDataEditorFactory* factory=openEditor?contentProvider->dataProvider->GetCellDataEditorFactory(currentRow, index):0; currentEditor=contentProvider->OpenEditor(currentRow, index, factory); if(currentEditor) { GuiCellComposition* cell=dynamic_cast(sender); currentEditor->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(currentEditor->GetBoundsComposition()); } } } bool DataGridContentProvider::ItemContent::IsInEditor(compositions::GuiMouseEventArgs& arguments) { if(!contentProvider->currentEditor) return false; GuiGraphicsComposition* editorComposition=contentProvider->currentEditor->GetBoundsComposition(); GuiGraphicsComposition* stopComposition=GetContentComposition(); GuiGraphicsComposition* currentComposition=arguments.eventSource; while(currentComposition) { if(currentComposition==editorComposition) { arguments.handled=true; return true; } else if(currentComposition==stopComposition) { break; } else { currentComposition=currentComposition->GetParent(); } } return false; } void DataGridContentProvider::ItemContent::OnCellButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { IsInEditor(arguments); } void DataGridContentProvider::ItemContent::OnCellLeftButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(!IsInEditor(arguments)) { if(contentProvider->dataGrid->GetVisuallyEnabled()) { OnCellButtonUp(sender, true); } } } void DataGridContentProvider::ItemContent::OnCellRightButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(!IsInEditor(arguments)) { if(contentProvider->dataGrid->GetVisuallyEnabled()) { OnCellButtonUp(sender, false); } } } DataGridContentProvider::ItemContent::ItemContent(DataGridContentProvider* _contentProvider, const FontProperties& _font) :contentComposition(0) ,contentProvider(_contentProvider) ,font(_font) ,currentEditor(0) { contentComposition=new GuiBoundsComposition; contentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); textTable=new GuiTableComposition; textTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); textTable->SetRowsAndColumns(1, 1); textTable->SetRowOption(0, GuiCellOption::MinSizeOption()); textTable->SetColumnOption(0, GuiCellOption::AbsoluteOption(0)); contentComposition->AddChild(textTable); } DataGridContentProvider::ItemContent::~ItemContent() { RemoveCellsAndDataVisualizers(); } compositions::GuiBoundsComposition* DataGridContentProvider::ItemContent::GetContentComposition() { return contentComposition; } compositions::GuiBoundsComposition* DataGridContentProvider::ItemContent::GetBackgroundDecorator() { return 0; } void DataGridContentProvider::ItemContent::UpdateSubItemSize() { vint columnCount=contentProvider->columnItemView->GetColumnCount(); if(columnCount>textTable->GetColumns()) { columnCount=textTable->GetColumns(); } for(vint i=0;iSetColumnOption(i, GuiCellOption::AbsoluteOption(contentProvider->columnItemView->GetColumnSize(i))); } textTable->UpdateCellBounds(); } void DataGridContentProvider::ItemContent::ForceSetEditor(vint column, IDataEditor* editor) { currentEditor=editor; if(currentEditor) { GuiCellComposition* cell=textTable->GetSitedCell(0, column); GuiBoundsComposition* editorBounds=currentEditor->GetBoundsComposition(); if(editorBounds->GetParent() && editorBounds->GetParent()!=cell) { editorBounds->GetParent()->RemoveChild(editorBounds); } currentEditor->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(currentEditor->GetBoundsComposition()); } } void DataGridContentProvider::ItemContent::NotifyCloseEditor() { if(currentEditor) { GuiGraphicsComposition* composition=currentEditor->GetBoundsComposition(); if(composition->GetParent()) { composition->GetParent()->RemoveChild(composition); } currentEditor=0; } } void DataGridContentProvider::ItemContent::NotifySelectCell(vint column) { for(vint i=0;iSetSelected(i==column); } } void DataGridContentProvider::ItemContent::Install(GuiListViewBase::IStyleProvider* styleProvider, ListViewItemStyleProvider::IListViewItemView* view, vint itemIndex) { bool refresh=false; if(dataVisualizers.Count()!=contentProvider->columnItemView->GetColumnCount()) { refresh=true; } else { for(vint i=0;iGetFactory(); if(factory!=GetDataVisualizerFactory(itemIndex, i)) { refresh=true; break; } } } if(refresh) { RemoveCellsAndDataVisualizers(); vint columnCount=contentProvider->columnItemView->GetColumnCount(); dataVisualizers.Resize(columnCount); for(vint i=0;iCreateVisualizer(font, styleProvider); } textTable->SetRowsAndColumns(1, columnCount); for(vint i=0;iAddChild(cell); cell->SetSite(0, i, 1, 1); cell->GetEventReceiver()->leftButtonDown.AttachMethod(this, &ItemContent::OnCellButtonDown); cell->GetEventReceiver()->rightButtonDown.AttachMethod(this, &ItemContent::OnCellButtonDown); cell->GetEventReceiver()->leftButtonUp.AttachMethod(this, &ItemContent::OnCellLeftButtonUp); cell->GetEventReceiver()->rightButtonUp.AttachMethod(this, &ItemContent::OnCellRightButtonUp); GuiBoundsComposition* composition=dataVisualizers[i]->GetBoundsComposition(); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(composition); } } for(vint i=0;iBeforeVisualizeCell(contentProvider->dataProvider, itemIndex, i); contentProvider->dataProvider->VisualizeCell(itemIndex, i, dataVisualizer); } GridPos selectedCell=contentProvider->GetSelectedCell(); if(selectedCell.row==itemIndex) { NotifySelectCell(selectedCell.column); } else { NotifySelectCell(-1); } UpdateSubItemSize(); } void DataGridContentProvider::ItemContent::Uninstall() { if(currentEditor) { contentProvider->CloseEditor(false); } currentEditor=0; } /*********************************************************************** DataGridContentProvider ***********************************************************************/ void DataGridContentProvider::OnColumnChanged() { vint count=listViewItemStyleProvider->GetCreatedItemStyles().Count(); for(vint i=0;iGetCreatedItemStyles().Get(i); ItemContent* itemContent=listViewItemStyleProvider->GetItemContent(itemStyleController); if(itemContent) { itemContent->UpdateSubItemSize(); } } } void DataGridContentProvider::OnAttached(GuiListControl::IItemProvider* provider) { } void DataGridContentProvider::OnItemModified(vint start, vint count, vint newCount) { if(!currentEditorRequestingSaveData) { CloseEditor(false); } } void DataGridContentProvider::NotifyCloseEditor() { if(listViewItemStyleProvider) { vint count=listViewItemStyleProvider->GetCreatedItemStyles().Count(); for(vint i=0;iGetCreatedItemStyles().Get(i); ItemContent* itemContent=listViewItemStyleProvider->GetItemContent(itemStyleController); if(itemContent) { itemContent->NotifyCloseEditor(); } } } } void DataGridContentProvider::NotifySelectCell(vint row, vint column) { currentCell=GridPos(row, column); dataGrid->NotifySelectedCellChanged(); if(listViewItemStyleProvider) { GuiListControl::IItemStyleController* selectedStyleController=0; GuiListControl::IItemArranger* arranger=dataGrid->GetArranger(); if(arranger) { selectedStyleController=arranger->GetVisibleStyle(row); } vint count=listViewItemStyleProvider->GetCreatedItemStyles().Count(); for(vint i=0;iGetCreatedItemStyles().Get(i); ItemContent* itemContent=listViewItemStyleProvider->GetItemContent(itemStyleController); if(itemContent) { if(itemStyleController==selectedStyleController) { itemContent->NotifySelectCell(column); } else { itemContent->NotifySelectCell(-1); } } } } } void DataGridContentProvider::RequestSaveData() { if(currentEditor && !currentEditorOpening) { GuiControl* focusedControl = nullptr; if (auto controlHost = dataGrid->GetRelatedControlHost()) { if (auto graphicsHost = controlHost->GetGraphicsHost()) { if (auto focusComposition = graphicsHost->GetFocusedComposition()) { focusedControl = focusComposition->GetRelatedControl(); } } } currentEditorRequestingSaveData=true; dataProvider->SaveCellData(currentCell.row, currentCell.column, currentEditor.Obj()); currentEditorRequestingSaveData=false; if(currentEditor) { GuiListControl::IItemArranger* arranger=dataGrid->GetArranger(); if(!arranger) return; GuiListControl::IItemStyleController* styleController=arranger->GetVisibleStyle(currentCell.row); if(!styleController) return; ItemContent* itemContent=listViewItemStyleProvider->GetItemContent(styleController); if(!itemContent) return; itemContent->ForceSetEditor(currentCell.column, currentEditor.Obj()); currentEditor->ReinstallEditor(); if (focusedControl) { focusedControl->SetFocus(); } } } } IDataEditor* DataGridContentProvider::OpenEditor(vint row, vint column, IDataEditorFactory* editorFactory) { CloseEditor(true); NotifySelectCell(row, column); if(editorFactory) { currentEditorOpening=true; currentEditor=editorFactory->CreateEditor(this); currentEditor->BeforeEditCell(dataProvider, row, column); dataProvider->BeforeEditCell(row, column, currentEditor.Obj()); currentEditorOpening=false; } return currentEditor.Obj(); } void DataGridContentProvider::CloseEditor(bool forOpenNewEditor) { if(currentEditorRequestingSaveData) { NotifyCloseEditor(); } else { if(currentCell!=GridPos(-1, -1)) { if(currentEditor) { NotifyCloseEditor(); currentEditor=0; } if(!forOpenNewEditor) { NotifySelectCell(-1, -1); } } } } DataGridContentProvider::DataGridContentProvider() :dataGrid(0) ,itemProvider(0) ,columnItemView(0) ,dataProvider(0) ,listViewItemStyleProvider(0) ,currentCell(-1, -1) ,currentEditorRequestingSaveData(false) ,currentEditorOpening(false) { } DataGridContentProvider::~DataGridContentProvider() { CloseEditor(false); } compositions::IGuiAxis* DataGridContentProvider::CreatePreferredAxis() { return new GuiDefaultAxis; } GuiListControl::IItemArranger* DataGridContentProvider::CreatePreferredArranger() { return new ListViewColumnItemArranger; } ListViewItemStyleProvider::IListViewItemContent* DataGridContentProvider::CreateItemContent(const FontProperties& font) { return new ItemContent(this, font); } void DataGridContentProvider::AttachListControl(GuiListControl* value) { dataGrid=dynamic_cast(value); listViewItemStyleProvider=dynamic_cast(value->GetStyleProvider()); itemProvider=value->GetItemProvider(); itemProvider->AttachCallback(this); columnItemView=dynamic_cast(itemProvider->RequestView(ListViewColumnItemArranger::IColumnItemView::Identifier)); if(columnItemView) { columnItemView->AttachCallback(this); } dataProvider=dynamic_cast(itemProvider->RequestView(IDataProvider::Identifier)); } void DataGridContentProvider::DetachListControl() { dataProvider=0; if(columnItemView) { columnItemView->DetachCallback(this); itemProvider->ReleaseView(columnItemView); columnItemView=0; } itemProvider->DetachCallback(this); itemProvider=0; listViewItemStyleProvider=0; } GridPos DataGridContentProvider::GetSelectedCell() { return currentCell; } bool DataGridContentProvider::SetSelectedCell(const GridPos& value, bool openEditor) { if(currentCell!=value) { if(value==GridPos(-1, -1)) { CloseEditor(false); return true; } else if(0<=value.row && value.rowGetRowCount() && 0<=value.column && value.columnGetColumnCount()) { IDataEditorFactory* editorFactory=openEditor?dataProvider->GetCellDataEditorFactory(value.row, value.column):0; OpenEditor(value.row, value.column, editorFactory); return true; } return false; } return true; } } /*********************************************************************** GuiVirtualDataGrid ***********************************************************************/ using namespace list; void GuiVirtualDataGrid::OnColumnClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiItemEventArgs& arguments) { if(dataProvider->IsColumnSortable(arguments.itemIndex)) { switch(itemProvider->GetSortingState(arguments.itemIndex)) { case GuiListViewColumnHeader::NotSorted: itemProvider->SortByColumn(arguments.itemIndex, true); break; case GuiListViewColumnHeader::Ascending: itemProvider->SortByColumn(arguments.itemIndex, false); break; case GuiListViewColumnHeader::Descending: itemProvider->SortByColumn(-1); break; } } } void GuiVirtualDataGrid::Initialize() { itemProvider=dynamic_cast(GetItemProvider()); dataProvider=itemProvider->GetDataProvider(); structuredDataProvider=dataProvider.Cast(); ChangeItemStyle(new DataGridContentProvider); ColumnClicked.AttachMethod(this, &GuiVirtualDataGrid::OnColumnClicked); SelectedCellChanged.SetAssociatedComposition(GetBoundsComposition()); } void GuiVirtualDataGrid::NotifySelectedCellChanged() { SelectedCellChanged.Execute(GetNotifyEventArguments()); } GuiVirtualDataGrid::GuiVirtualDataGrid(IStyleProvider* _styleProvider, list::IDataProvider* _dataProvider) :GuiVirtualListView(_styleProvider, new DataGridItemProvider(_dataProvider)) { Initialize(); } GuiVirtualDataGrid::GuiVirtualDataGrid(IStyleProvider* _styleProvider, list::IStructuredDataProvider* _dataProvider) :GuiVirtualListView(_styleProvider, new DataGridItemProvider(new StructuredDataProvider(_dataProvider))) ,itemProvider(0) ,contentProvider(0) { Initialize(); } GuiVirtualDataGrid::~GuiVirtualDataGrid() { SetSelectedCell(GridPos(-1, -1)); } list::IDataProvider* GuiVirtualDataGrid::GetDataProvider() { return dataProvider.Obj(); } list::StructuredDataProvider* GuiVirtualDataGrid::GetStructuredDataProvider() { return structuredDataProvider.Obj(); } GridPos GuiVirtualDataGrid::GetSelectedCell() { return contentProvider->GetSelectedCell(); } void GuiVirtualDataGrid::SetSelectedCell(const GridPos& value) { if(contentProvider->SetSelectedCell(value, false)) { if(0<=value.row && value.rowGetRowCount()) { EnsureItemVisible(value.row); ClearSelection(); SetSelected(value.row, true); } } } Ptr GuiVirtualDataGrid::SetStyleProvider(Ptr value) { Ptr styleProvider=value.Cast(); if(styleProvider) { list::DataGridContentProvider* dataGridContentProvider=dynamic_cast(styleProvider->GetItemContentProvider()); if(dataGridContentProvider) { Ptr result=GuiVirtualListView::SetStyleProvider(value); if(result) { contentProvider=dataGridContentProvider; return result; } } } return 0; } bool GuiVirtualDataGrid::ChangeItemStyle(Ptr contentProvider) { if(contentProvider.Cast()) { return GuiVirtualListView::ChangeItemStyle(contentProvider); } else { return false; } } namespace list { /*********************************************************************** StringGridDataVisualizer ***********************************************************************/ StringGridDataVisualizer::StringGridDataVisualizer() { } void StringGridDataVisualizer::BeforeVisualizeCell(IDataProvider* dataProvider, vint row, vint column) { ListViewSubColumnDataVisualizer::BeforeVisualizeCell(dataProvider, row, column); text->SetColor(styleProvider->GetPrimaryTextColor()); } void StringGridDataVisualizer::SetSelected(bool value) { ListViewSubColumnDataVisualizer::SetSelected(value); FontProperties font=text->GetFont(); font.bold=value; text->SetFont(font); } /*********************************************************************** StringGridProvider ***********************************************************************/ StringGridColumn::StringGridColumn(StringGridProvider* _provider) :StrongTypedColumnProviderBase(_provider) ,provider(_provider) { } StringGridColumn::~StringGridColumn() { } void StringGridColumn::GetCellData(const Ptr& rowData, WString& cellData) { vint index=provider->columns.IndexOf(this); if(0<=index && indexstrings.Count()) { cellData=rowData->strings[index]; } else { cellData=L""; } } void StringGridColumn::SetCellData(const Ptr& rowData, const WString& cellData) { vint index=provider->columns.IndexOf(this); if(0<=index && indexstrings.Count()) { rowData->strings[index]=cellData; } } WString StringGridColumn::GetCellDataText(const WString& cellData) { return cellData; } void StringGridColumn::BeforeEditCell(vint row, IDataEditor* dataEditor) { TextBoxDataEditor* editor=dynamic_cast(dataEditor); if(editor) { vint column=provider->columns.IndexOf(this); editor->GetTextBox()->SetText(provider->GetGridString(row, column)); editor->GetTextBox()->SelectAll(); } } void StringGridColumn::SaveCellData(vint row, IDataEditor* dataEditor) { TextBoxDataEditor* editor=dynamic_cast(dataEditor); if(editor) { vint column=provider->columns.IndexOf(this); provider->SetGridString(row, column, editor->GetTextBox()->GetText()); } } /*********************************************************************** StringGridProvider ***********************************************************************/ void StringGridProvider::GetRowData(vint row, Ptr& rowData) { rowData=items[row]; } bool StringGridProvider::GetReadonly() { return readonly; } void StringGridProvider::SetReadonly(bool value) { if(readonly!=value) { readonly=value; FOREACH(Ptr, column, columns) { column->SetEditorFactory(readonly ? nullptr : editorFactory); } } } StringGridProvider::StringGridProvider() :readonly(false) { visualizerFactory=new list::CellBorderDataVisualizer::Factory(new list::StringGridDataVisualizer::Factory); editorFactory=new list::TextBoxDataEditor::Factory; } StringGridProvider::~StringGridProvider() { } vint StringGridProvider::GetRowCount() { return items.Count(); } vint StringGridProvider::GetColumnCount() { return columns.Count(); } bool StringGridProvider::InsertRow(vint row) { if(row<0 || items.Count() item=new StringGridItem; for(vint i=0;istrings.Add(L""); } items.Insert(row, item); commandExecutor->OnDataProviderItemModified(row, 0, 1); return true; } vint StringGridProvider::AppendRow() { InsertRow(items.Count()); return items.Count()-1; } bool StringGridProvider::MoveRow(vint source, vint target) { if(source<0 || items.Count()<=source) return false; if(target<0 || items.Count()<=target) return false; Ptr item=items[source]; items.RemoveAt(source); commandExecutor->OnDataProviderItemModified(source, 1, 0); items.Insert(target, item); commandExecutor->OnDataProviderItemModified(target, 0, 1); return true; } bool StringGridProvider::RemoveRow(vint row) { if(row<0 || items.Count()<=row) return false; items.RemoveAt(row); commandExecutor->OnDataProviderItemModified(row, 1, 0); return true; } bool StringGridProvider::ClearRows() { vint oldCount=items.Count(); items.Clear(); commandExecutor->OnDataProviderItemModified(0, oldCount, 0); return true; } WString StringGridProvider::GetGridString(vint row, vint column) { if(row<0 || items.Count()<=row) return L""; if(column<0 || columns.Count()<=column) return L""; return items[row]->strings[column]; } bool StringGridProvider::SetGridString(vint row, vint column, const WString& value) { if(row<0 || items.Count()<=row) return false; if(column<0 || columns.Count()<=column) return false; items[row]->strings[column]=value; commandExecutor->OnDataProviderItemModified(row, 1, 1); return true; } bool StringGridProvider::InsertColumn(vint column, const WString& text, vint size) { Ptr columnProvider=new StringGridColumn(this); columnProvider->SetText(text); columnProvider->SetSize(size); columnProvider->SetVisualizerFactory(visualizerFactory); columnProvider->SetEditorFactory(readonly ? nullptr : editorFactory); if(!InsertColumnInternal(column, columnProvider, false)) return false; FOREACH(Ptr, item, items) { item->strings.Insert(column, L""); } if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return true; } vint StringGridProvider::AppendColumn(const WString& text, vint size) { InsertColumn(columns.Count(), text, size); return columns.Count()-1; } bool StringGridProvider::MoveColumn(vint source, vint target) { if(source<0 || columns.Count()<=source) return false; if(target<0 || columns.Count()<=target) return false; Ptr columnProvider=columns[source].Cast(); columns.RemoveAt(source); columns.Insert(target, columnProvider); FOREACH(Ptr, item, items) { WString text=item->strings[source]; item->strings.RemoveAt(source); item->strings.Insert(target, text); } if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return true; } bool StringGridProvider::RemoveColumn(vint column) { if(column<0 || columns.Count()<=column) return false; Ptr columnProvider=columns[column].Cast(); if(!RemoveColumnInternal(columnProvider, false)) return false; FOREACH(Ptr, item, items) { item->strings.RemoveAt(column); } if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return true; } bool StringGridProvider::ClearColumns() { if(!ClearColumnsInternal(false)) return false; FOREACH(Ptr, item, items) { item->strings.Clear(); } if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return true; } WString StringGridProvider::GetColumnText(vint column) { if(column<0 || columns.Count()<=column) return L""; return columns[column]->GetText(); } bool StringGridProvider::SetColumnText(vint column, const WString& value) { if(column<0 || columns.Count()<=column) return false; columns[column]->SetText(value); return true; } } /*********************************************************************** GuiStringGrid ***********************************************************************/ GuiStringGrid::GuiStringGrid(IStyleProvider* _styleProvider) :GuiVirtualDataGrid(_styleProvider, grids=new list::StringGridProvider) { } GuiStringGrid::~GuiStringGrid() { } list::StringGridProvider& GuiStringGrid::Grids() { return *grids; } bool GuiStringGrid::GetReadonly() { return grids->GetReadonly(); } void GuiStringGrid::SetReadonly(bool value) { SetSelectedCell(GridPos(-1, -1)); grids->SetReadonly(value); } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUIDATAGRIDEXTENSIONS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { namespace list { using namespace compositions; using namespace elements; using namespace theme; /*********************************************************************** DataVisualizerBase ***********************************************************************/ DataVisualizerBase::DataVisualizerBase(Ptr _decoratedDataVisualizer) :factory(0) ,styleProvider(0) ,boundsComposition(0) ,decoratedDataVisualizer(_decoratedDataVisualizer) { } DataVisualizerBase::~DataVisualizerBase() { if(decoratedDataVisualizer) { GuiBoundsComposition* composition=decoratedDataVisualizer->GetBoundsComposition(); if(composition->GetParent()) { composition->GetParent()->RemoveChild(composition); } decoratedDataVisualizer=0; } if(boundsComposition) { SafeDeleteComposition(boundsComposition); } } IDataVisualizerFactory* DataVisualizerBase::GetFactory() { return factory; } compositions::GuiBoundsComposition* DataVisualizerBase::GetBoundsComposition() { if(!boundsComposition) { GuiBoundsComposition* decoratedComposition=0; if(decoratedDataVisualizer) { decoratedComposition=decoratedDataVisualizer->GetBoundsComposition(); } boundsComposition=CreateBoundsCompositionInternal(decoratedComposition); } return boundsComposition; } void DataVisualizerBase::BeforeVisualizeCell(IDataProvider* dataProvider, vint row, vint column) { if(decoratedDataVisualizer) { decoratedDataVisualizer->BeforeVisualizeCell(dataProvider, row, column); } } IDataVisualizer* DataVisualizerBase::GetDecoratedDataVisualizer() { return decoratedDataVisualizer.Obj(); } void DataVisualizerBase::SetSelected(bool value) { if(decoratedDataVisualizer) { decoratedDataVisualizer->SetSelected(value); } } /*********************************************************************** DataEditorBase ***********************************************************************/ DataEditorBase::DataEditorBase() :factory(0) ,callback(0) ,boundsComposition(0) { } DataEditorBase::~DataEditorBase() { if(boundsComposition) { SafeDeleteComposition(boundsComposition); } } IDataEditorFactory* DataEditorBase::GetFactory() { return factory; } compositions::GuiBoundsComposition* DataEditorBase::GetBoundsComposition() { if(!boundsComposition) { boundsComposition=CreateBoundsCompositionInternal(); } return boundsComposition; } void DataEditorBase::BeforeEditCell(IDataProvider* dataProvider, vint row, vint column) { } void DataEditorBase::ReinstallEditor() { } /*********************************************************************** ListViewMainColumnDataVisualizer ***********************************************************************/ compositions::GuiBoundsComposition* ListViewMainColumnDataVisualizer::CreateBoundsCompositionInternal(compositions::GuiBoundsComposition* decoratedComposition) { GuiTableComposition* table=new GuiTableComposition; table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); table->SetRowsAndColumns(3, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); table->SetCellPadding(2); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(1, 0, 1, 1); cell->SetPreferredMinSize(Size(16, 16)); image=GuiImageFrameElement::Create(); image->SetStretch(true); cell->SetOwnedElement(image); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 3, 1); cell->SetMargin(Margin(0, 0, 8, 0)); text=GuiSolidLabelElement::Create(); cell->SetOwnedElement(text); } return table; } ListViewMainColumnDataVisualizer::ListViewMainColumnDataVisualizer() :image(0) ,text(0) { } void ListViewMainColumnDataVisualizer::BeforeVisualizeCell(IDataProvider* dataProvider, vint row, vint column) { DataVisualizerBase::BeforeVisualizeCell(dataProvider, row, column); Ptr imageData=dataProvider->GetRowSmallImage(row); if(imageData) { image->SetImage(imageData->GetImage(), imageData->GetFrameIndex()); } else { image->SetImage(0); } text->SetAlignments(Alignment::Left, Alignment::Center); text->SetFont(font); text->SetColor(styleProvider->GetPrimaryTextColor()); text->SetEllipse(true); text->SetText(dataProvider->GetCellText(row, column)); } elements::GuiSolidLabelElement* ListViewMainColumnDataVisualizer::GetTextElement() { return text; } /*********************************************************************** ListViewSubColumnDataVisualizer ***********************************************************************/ compositions::GuiBoundsComposition* ListViewSubColumnDataVisualizer::CreateBoundsCompositionInternal(compositions::GuiBoundsComposition* decoratedComposition) { GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); composition->SetMargin(Margin(8, 0, 8, 0)); text=GuiSolidLabelElement::Create(); composition->SetOwnedElement(text); return composition; } ListViewSubColumnDataVisualizer::ListViewSubColumnDataVisualizer() :text(0) { } void ListViewSubColumnDataVisualizer::BeforeVisualizeCell(IDataProvider* dataProvider, vint row, vint column) { DataVisualizerBase::BeforeVisualizeCell(dataProvider, row, column); text->SetAlignments(Alignment::Left, Alignment::Center); text->SetFont(font); text->SetColor(styleProvider->GetSecondaryTextColor()); text->SetEllipse(true); text->SetText(dataProvider->GetCellText(row, column)); } elements::GuiSolidLabelElement* ListViewSubColumnDataVisualizer::GetTextElement() { return text; } /*********************************************************************** HyperlinkDataVisualizer ***********************************************************************/ void HyperlinkDataVisualizer::label_MouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { FontProperties font=text->GetFont(); font.underline=true; text->SetFont(font); } void HyperlinkDataVisualizer::label_MouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { FontProperties font=text->GetFont(); font.underline=false; text->SetFont(font); } compositions::GuiBoundsComposition* HyperlinkDataVisualizer::CreateBoundsCompositionInternal(compositions::GuiBoundsComposition* decoratedComposition) { GuiBoundsComposition* composition=ListViewSubColumnDataVisualizer::CreateBoundsCompositionInternal(decoratedComposition); composition->GetEventReceiver()->mouseEnter.AttachMethod(this, &HyperlinkDataVisualizer::label_MouseEnter); composition->GetEventReceiver()->mouseLeave.AttachMethod(this, &HyperlinkDataVisualizer::label_MouseLeave); composition->SetAssociatedCursor(GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::Hand)); return composition; } HyperlinkDataVisualizer::HyperlinkDataVisualizer() { } void HyperlinkDataVisualizer::BeforeVisualizeCell(IDataProvider* dataProvider, vint row, vint column) { ListViewSubColumnDataVisualizer::BeforeVisualizeCell(dataProvider, row, column); text->SetColor(Color(0, 0, 255)); } /*********************************************************************** ImageDataVisualizer ***********************************************************************/ compositions::GuiBoundsComposition* ImageDataVisualizer::CreateBoundsCompositionInternal(compositions::GuiBoundsComposition* decoratedComposition) { GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); composition->SetMargin(Margin(2, 2, 2, 2)); image=GuiImageFrameElement::Create(); composition->SetOwnedElement(image); return composition; } ImageDataVisualizer::ImageDataVisualizer() :image(0) { } void ImageDataVisualizer::BeforeVisualizeCell(IDataProvider* dataProvider, vint row, vint column) { DataVisualizerBase::BeforeVisualizeCell(dataProvider, row, column); image->SetImage(0, -1); image->SetAlignments(Alignment::Center, Alignment::Center); image->SetStretch(false); image->SetEnabled(true); } elements::GuiImageFrameElement* ImageDataVisualizer::GetImageElement() { return image; } /*********************************************************************** CellBorderDataVisualizer ***********************************************************************/ compositions::GuiBoundsComposition* CellBorderDataVisualizer::CreateBoundsCompositionInternal(compositions::GuiBoundsComposition* decoratedComposition) { GuiBoundsComposition* border1=0; GuiBoundsComposition* border2=0; { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(styleProvider->GetItemSeparatorColor()); border1=new GuiBoundsComposition; border1->SetOwnedElement(element); border1->SetAlignmentToParent(Margin(-1, 0, 0, 0)); } { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(styleProvider->GetItemSeparatorColor()); border2=new GuiBoundsComposition; border2->SetOwnedElement(element); border2->SetAlignmentToParent(Margin(0, -1, 0, 0)); } decoratedComposition->SetAlignmentToParent(Margin(0, 0, 1, 1)); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); composition->AddChild(border1); composition->AddChild(border2); composition->AddChild(decoratedComposition); return composition; } CellBorderDataVisualizer::CellBorderDataVisualizer(Ptr decoratedDataVisualizer) :DataVisualizerBase(decoratedDataVisualizer) { } /*********************************************************************** NotifyIconDataVisualizer ***********************************************************************/ compositions::GuiBoundsComposition* NotifyIconDataVisualizer::CreateBoundsCompositionInternal(compositions::GuiBoundsComposition* decoratedComposition) { GuiTableComposition* table=new GuiTableComposition; table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); table->SetRowsAndColumns(1, 3); table->SetRowOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(2, GuiCellOption::MinSizeOption()); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 0, 1, 1); cell->SetInternalMargin(Margin(2, 2, 0, 2)); leftImage=GuiImageFrameElement::Create(); cell->SetOwnedElement(leftImage); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 1, 1); decoratedComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(decoratedComposition); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 2, 1, 1); cell->SetInternalMargin(Margin(0, 2, 2, 2)); rightImage=GuiImageFrameElement::Create(); cell->SetOwnedElement(rightImage); } return table; } NotifyIconDataVisualizer::NotifyIconDataVisualizer(Ptr decoratedDataVisualizer) :DataVisualizerBase(decoratedDataVisualizer) ,leftImage(0) ,rightImage(0) { } void NotifyIconDataVisualizer::BeforeVisualizeCell(IDataProvider* dataProvider, vint row, vint column) { DataVisualizerBase::BeforeVisualizeCell(dataProvider, row, column); leftImage->SetImage(0, -1); leftImage->SetAlignments(Alignment::Center, Alignment::Center); leftImage->SetStretch(false); leftImage->SetEnabled(true); rightImage->SetImage(0, -1); rightImage->SetAlignments(Alignment::Center, Alignment::Center); rightImage->SetStretch(false); rightImage->SetEnabled(true); } elements::GuiImageFrameElement* NotifyIconDataVisualizer::GetLeftImageElement() { return leftImage; } elements::GuiImageFrameElement* NotifyIconDataVisualizer::GetRightImageElement() { return rightImage; } /*********************************************************************** TextBoxDataEditor ***********************************************************************/ void TextBoxDataEditor::OnTextChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { callback->RequestSaveData(); } compositions::GuiBoundsComposition* TextBoxDataEditor::CreateBoundsCompositionInternal() { return textBox->GetBoundsComposition(); } TextBoxDataEditor::TextBoxDataEditor() { textBox=g::NewTextBox(); textBox->TextChanged.AttachMethod(this, &TextBoxDataEditor::OnTextChanged); } void TextBoxDataEditor::BeforeEditCell(IDataProvider* dataProvider, vint row, vint column) { DataEditorBase::BeforeEditCell(dataProvider, row, column); textBox->SetText(L""); GetApplication()->InvokeInMainThread([this]() { textBox->SetFocus(); }); } GuiSinglelineTextBox* TextBoxDataEditor::GetTextBox() { return textBox; } /*********************************************************************** TextComboBoxDataEditor ***********************************************************************/ void TextComboBoxDataEditor::OnSelectedIndexChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { callback->RequestSaveData(); } compositions::GuiBoundsComposition* TextComboBoxDataEditor::CreateBoundsCompositionInternal() { return comboBox->GetBoundsComposition(); } TextComboBoxDataEditor::TextComboBoxDataEditor() { textList=g::NewTextList(); comboBox=g::NewComboBox(textList); comboBox->SelectedIndexChanged.AttachMethod(this, &TextComboBoxDataEditor::OnSelectedIndexChanged); } void TextComboBoxDataEditor::BeforeEditCell(IDataProvider* dataProvider, vint row, vint column) { DataEditorBase::BeforeEditCell(dataProvider, row, column); textList->GetItems().Clear(); } GuiComboBoxListControl* TextComboBoxDataEditor::GetComboBoxControl() { return comboBox; } GuiTextList* TextComboBoxDataEditor::GetTextListControl() { return textList; } /*********************************************************************** DateComboBoxDataEditor ***********************************************************************/ void DateComboBoxDataEditor::OnSelectedDateChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { callback->RequestSaveData(); } compositions::GuiBoundsComposition* DateComboBoxDataEditor::CreateBoundsCompositionInternal() { return comboBox->GetBoundsComposition(); } DateComboBoxDataEditor::DateComboBoxDataEditor() { comboBox=g::NewDateComboBox(); comboBox->SelectedDateChanged.AttachMethod(this, &DateComboBoxDataEditor::OnSelectedDateChanged); } void DateComboBoxDataEditor::BeforeEditCell(IDataProvider* dataProvider, vint row, vint column) { DataEditorBase::BeforeEditCell(dataProvider, row, column); comboBox->SetSelectedDate(DateTime::LocalTime()); } GuiDateComboBox* DateComboBoxDataEditor::GetComboBoxControl() { return comboBox; } GuiDatePicker* DateComboBoxDataEditor::GetDatePickerControl() { return comboBox->GetDatePicker(); } } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUIDATAGRIDSTRUCTURED.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { namespace list { using namespace collections; /*********************************************************************** StructuredDataFilterBase ***********************************************************************/ void StructuredDataFilterBase::InvokeOnFilterChanged() { if(commandExecutor) { commandExecutor->OnFilterChanged(); } } StructuredDataFilterBase::StructuredDataFilterBase() :commandExecutor(0) { } void StructuredDataFilterBase::SetCommandExecutor(IStructuredDataFilterCommandExecutor* value) { commandExecutor=value; } /*********************************************************************** StructuredDataMultipleFilter ***********************************************************************/ StructuredDataMultipleFilter::StructuredDataMultipleFilter() { } bool StructuredDataMultipleFilter::AddSubFilter(Ptr value) { if(!value) return false; if(filters.Contains(value.Obj())) return false; filters.Add(value); value->SetCommandExecutor(commandExecutor); InvokeOnFilterChanged(); return true; } bool StructuredDataMultipleFilter::RemoveSubFilter(Ptr value) { if(!value) return false; if(!filters.Contains(value.Obj())) return false; value->SetCommandExecutor(0); filters.Remove(value.Obj()); InvokeOnFilterChanged(); return true; } void StructuredDataMultipleFilter::SetCommandExecutor(IStructuredDataFilterCommandExecutor* value) { StructuredDataFilterBase::SetCommandExecutor(value); for(vint i=0;iSetCommandExecutor(value); } } /*********************************************************************** StructuredDataAndFilter ***********************************************************************/ StructuredDataAndFilter::StructuredDataAndFilter() { } bool StructuredDataAndFilter::Filter(vint row) { return From(filters) .All([row](Ptr filter) { return filter->Filter(row); }); } /*********************************************************************** StructuredDataOrFilter ***********************************************************************/ StructuredDataOrFilter::StructuredDataOrFilter() { } bool StructuredDataOrFilter::Filter(vint row) { return From(filters) .Any([row](Ptr filter) { return filter->Filter(row); }); } /*********************************************************************** StructuredDataNotFilter ***********************************************************************/ StructuredDataNotFilter::StructuredDataNotFilter() { } bool StructuredDataNotFilter::SetSubFilter(Ptr value) { if(filter==value) return false; if(filter) { filter->SetCommandExecutor(0); } filter=value; if(filter) { filter->SetCommandExecutor(commandExecutor); } InvokeOnFilterChanged(); return true; } void StructuredDataNotFilter::SetCommandExecutor(IStructuredDataFilterCommandExecutor* value) { StructuredDataFilterBase::SetCommandExecutor(value); if(filter) { filter->SetCommandExecutor(value); } } bool StructuredDataNotFilter::Filter(vint row) { return filter?true:!filter->Filter(row); } /*********************************************************************** StructuredDataMultipleSorter ***********************************************************************/ StructuredDataMultipleSorter::StructuredDataMultipleSorter() { } bool StructuredDataMultipleSorter::SetLeftSorter(Ptr value) { if(leftSorter==value) return false; leftSorter=value; return true; } bool StructuredDataMultipleSorter::SetRightSorter(Ptr value) { if(rightSorter==value) return false; rightSorter=value; return true; } vint StructuredDataMultipleSorter::Compare(vint row1, vint row2) { if(leftSorter) { vint result=leftSorter->Compare(row1, row2); if(result!=0) return result; } if(rightSorter) { vint result=rightSorter->Compare(row1, row2); if(result!=0) return result; } return 0; } /*********************************************************************** StructuredDataReverseSorter ***********************************************************************/ StructuredDataReverseSorter::StructuredDataReverseSorter() { } bool StructuredDataReverseSorter::SetSubSorter(Ptr value) { if(sorter==value) return false; sorter=value; return true; } vint StructuredDataReverseSorter::Compare(vint row1, vint row2) { return sorter?-sorter->Compare(row1, row2):0; } /*********************************************************************** StructuredDataProvider ***********************************************************************/ void StructuredDataProvider::OnDataProviderColumnChanged() { vint oldRowCount=GetRowCount(); RebuildFilter(true); ReorderRows(true); } void StructuredDataProvider::OnDataProviderItemModified(vint start, vint count, vint newCount) { // optimized for cell editing if(!currentSorter && !currentFilter) { if(count!=newCount) { ReorderRows(false); } commandExecutor->OnDataProviderItemModified(start, count, newCount); } else { ReorderRows(true); } } void StructuredDataProvider::OnFilterChanged() { ReorderRows(true); if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } } void StructuredDataProvider::RebuildFilter(bool invokeCallback) { if(currentFilter) { currentFilter->SetCommandExecutor(0); currentFilter=0; } List> selectedFilters; CopyFrom( selectedFilters, Range(0, GetColumnCount()) .Select([this](vint column){return structuredDataProvider->GetColumn(column)->GetInherentFilter();}) .Where([](Ptr filter){return (bool)filter;}) ); if(additionalFilter) { selectedFilters.Add(additionalFilter); } if(selectedFilters.Count()>0) { Ptr andFilter=new StructuredDataAndFilter; FOREACH(Ptr, filter, selectedFilters) { andFilter->AddSubFilter(filter); } currentFilter=andFilter; } if(currentFilter) { currentFilter->SetCommandExecutor(this); } if(invokeCallback && commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } } void StructuredDataProvider::ReorderRows(bool invokeCallback) { vint oldRowCount=reorderedRows.Count(); reorderedRows.Clear(); vint rowCount=structuredDataProvider->GetRowCount(); if(currentFilter) { for(vint i=0;iFilter(i)) { reorderedRows.Add(i); } } } else { for(vint i=0;i0) { IStructuredDataSorter* sorter=currentSorter.Obj(); SortLambda(&reorderedRows[0], reorderedRows.Count(), [sorter](vint a, vint b){return sorter->Compare(a, b);}); } if(invokeCallback && commandExecutor) { commandExecutor->OnDataProviderItemModified(0, oldRowCount, GetRowCount()); } } vint StructuredDataProvider::TranslateRowNumber(vint row) { return reorderedRows[row]; } Ptr StructuredDataProvider::GetStructuredDataProvider() { return structuredDataProvider; } Ptr StructuredDataProvider::GetAdditionalFilter() { return additionalFilter; } void StructuredDataProvider::SetAdditionalFilter(Ptr value) { additionalFilter=value; RebuildFilter(true); ReorderRows(true); } StructuredDataProvider::StructuredDataProvider(Ptr provider) :structuredDataProvider(provider) ,commandExecutor(0) { structuredDataProvider->SetCommandExecutor(this); RebuildFilter(false); ReorderRows(false); } StructuredDataProvider::~StructuredDataProvider() { } void StructuredDataProvider::SetCommandExecutor(IDataProviderCommandExecutor* value) { commandExecutor=value; } vint StructuredDataProvider::GetColumnCount() { return structuredDataProvider->GetColumnCount(); } WString StructuredDataProvider::GetColumnText(vint column) { return structuredDataProvider->GetColumn(column)->GetText(); } vint StructuredDataProvider::GetColumnSize(vint column) { return structuredDataProvider->GetColumn(column)->GetSize(); } void StructuredDataProvider::SetColumnSize(vint column, vint value) { structuredDataProvider->GetColumn(column)->SetSize(value); } GuiMenu* StructuredDataProvider::GetColumnPopup(vint column) { return structuredDataProvider->GetColumn(column)->GetPopup(); } bool StructuredDataProvider::IsColumnSortable(vint column) { return structuredDataProvider->GetColumn(column)->GetInherentSorter(); } void StructuredDataProvider::SortByColumn(vint column, bool ascending) { if(0<=column && columnGetColumnCount()) { Ptr sorter=structuredDataProvider->GetColumn(column)->GetInherentSorter(); if(!sorter) { currentSorter=0; } else if(ascending) { currentSorter=sorter; } else { Ptr reverseSorter=new StructuredDataReverseSorter(); reverseSorter->SetSubSorter(sorter); currentSorter=reverseSorter; } } else { currentSorter=0; } for(vint i=0;iGetColumnCount();i++) { structuredDataProvider->GetColumn(i)->SetSortingState( i!=column?GuiListViewColumnHeader::NotSorted: ascending?GuiListViewColumnHeader::Ascending: GuiListViewColumnHeader::Descending ); } ReorderRows(true); if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } } vint StructuredDataProvider::GetSortedColumn() { for(vint i=0;iGetColumnCount();i++) { GuiListViewColumnHeader::ColumnSortingState state=structuredDataProvider->GetColumn(i)->GetSortingState(); if(state!=GuiListViewColumnHeader::NotSorted) { return i; } } return -1; } bool StructuredDataProvider::IsSortOrderAscending() { for(vint i=0;iGetColumnCount();i++) { GuiListViewColumnHeader::ColumnSortingState state=structuredDataProvider->GetColumn(i)->GetSortingState(); if(state!=GuiListViewColumnHeader::NotSorted) { return state==GuiListViewColumnHeader::Ascending; } } return true; } vint StructuredDataProvider::GetRowCount() { return reorderedRows.Count(); } Ptr StructuredDataProvider::GetRowLargeImage(vint row) { return structuredDataProvider->GetRowLargeImage(TranslateRowNumber(row)); } Ptr StructuredDataProvider::GetRowSmallImage(vint row) { return structuredDataProvider->GetRowSmallImage(TranslateRowNumber(row)); } vint StructuredDataProvider::GetCellSpan(vint row, vint column) { return 1; } WString StructuredDataProvider::GetCellText(vint row, vint column) { return structuredDataProvider->GetColumn(column)->GetCellText(TranslateRowNumber(row)); } IDataVisualizerFactory* StructuredDataProvider::GetCellDataVisualizerFactory(vint row, vint column) { return structuredDataProvider->GetColumn(column)->GetCellDataVisualizerFactory(TranslateRowNumber(row)); } void StructuredDataProvider::VisualizeCell(vint row, vint column, IDataVisualizer* dataVisualizer) { structuredDataProvider->GetColumn(column)->VisualizeCell(TranslateRowNumber(row), dataVisualizer); } IDataEditorFactory* StructuredDataProvider::GetCellDataEditorFactory(vint row, vint column) { return structuredDataProvider->GetColumn(column)->GetCellDataEditorFactory(TranslateRowNumber(row)); } void StructuredDataProvider::BeforeEditCell(vint row, vint column, IDataEditor* dataEditor) { structuredDataProvider->GetColumn(column)->BeforeEditCell(TranslateRowNumber(row), dataEditor); } void StructuredDataProvider::SaveCellData(vint row, vint column, IDataEditor* dataEditor) { structuredDataProvider->GetColumn(column)->SaveCellData(TranslateRowNumber(row), dataEditor); } /*********************************************************************** StructuredColummProviderBase ***********************************************************************/ StructuredColummProviderBase::StructuredColummProviderBase() :commandExecutor(0) ,size(0) ,sortingState(GuiListViewColumnHeader::NotSorted) ,popup(0) { } StructuredColummProviderBase::~StructuredColummProviderBase() { } void StructuredColummProviderBase::SetCommandExecutor(IDataProviderCommandExecutor* value) { commandExecutor=value; } StructuredColummProviderBase* StructuredColummProviderBase::SetText(const WString& value) { text=value; if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return this; } StructuredColummProviderBase* StructuredColummProviderBase::SetPopup(GuiMenu* value) { popup=value; if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return this; } StructuredColummProviderBase* StructuredColummProviderBase::SetInherentFilter(Ptr value) { inherentFilter=value; if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return this; } StructuredColummProviderBase* StructuredColummProviderBase::SetInherentSorter(Ptr value) { inherentSorter=value; if(commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return this; } Ptr StructuredColummProviderBase::GetVisualizerFactory() { return visualizerFactory; } StructuredColummProviderBase* StructuredColummProviderBase::SetVisualizerFactory(Ptr value) { visualizerFactory=value; return this; } Ptr StructuredColummProviderBase::GetEditorFactory() { return editorFactory; } StructuredColummProviderBase* StructuredColummProviderBase::SetEditorFactory(Ptr value) { editorFactory=value; return this; } WString StructuredColummProviderBase::GetText() { return text; } vint StructuredColummProviderBase::GetSize() { return size; } void StructuredColummProviderBase::SetSize(vint value) { size=value; } GuiListViewColumnHeader::ColumnSortingState StructuredColummProviderBase::GetSortingState() { return sortingState; } void StructuredColummProviderBase::SetSortingState(GuiListViewColumnHeader::ColumnSortingState value) { sortingState=value; } GuiMenu* StructuredColummProviderBase::GetPopup() { return popup; } Ptr StructuredColummProviderBase::GetInherentFilter() { return inherentFilter; } Ptr StructuredColummProviderBase::GetInherentSorter() { return inherentSorter; } IDataVisualizerFactory* StructuredColummProviderBase::GetCellDataVisualizerFactory(vint row) { return visualizerFactory.Obj(); } void StructuredColummProviderBase::VisualizeCell(vint row, IDataVisualizer* dataVisualizer) { } IDataEditorFactory* StructuredColummProviderBase::GetCellDataEditorFactory(vint row) { return editorFactory.Obj(); } void StructuredColummProviderBase::BeforeEditCell(vint row, IDataEditor* dataEditor) { } void StructuredColummProviderBase::SaveCellData(vint row, IDataEditor* dataEditor) { } /*********************************************************************** StructuredDataProviderBase ***********************************************************************/ bool StructuredDataProviderBase::InsertColumnInternal(vint column, Ptr value, bool callback) { if(column<0 || columns.Count()SetCommandExecutor(commandExecutor); if(callback && commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return true; } bool StructuredDataProviderBase::AddColumnInternal(Ptr value, bool callback) { return InsertColumnInternal(columns.Count(), value, callback); } bool StructuredDataProviderBase::RemoveColumnInternal(Ptr value, bool callback) { if(!columns.Contains(value.Obj())) return false; value->SetCommandExecutor(0); columns.Remove(value.Obj()); if(callback && commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return true; } bool StructuredDataProviderBase::ClearColumnsInternal(bool callback) { FOREACH(Ptr, column, columns) { column->SetCommandExecutor(0); } columns.Clear(); if(callback && commandExecutor) { commandExecutor->OnDataProviderColumnChanged(); } return true; } StructuredDataProviderBase::StructuredDataProviderBase() :commandExecutor(0) { } StructuredDataProviderBase::~StructuredDataProviderBase() { } void StructuredDataProviderBase::SetCommandExecutor(IDataProviderCommandExecutor* value) { commandExecutor=value; FOREACH(Ptr, column, columns) { column->SetCommandExecutor(commandExecutor); } } vint StructuredDataProviderBase::GetColumnCount() { return columns.Count(); } IStructuredColumnProvider* StructuredDataProviderBase::GetColumn(vint column) { return columns[column].Obj(); } Ptr StructuredDataProviderBase::GetRowLargeImage(vint row) { return 0; } Ptr StructuredDataProviderBase::GetRowSmallImage(vint row) { return 0; } } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUILISTCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace elements; using namespace compositions; const wchar_t* const GuiListControl::IItemPrimaryTextView::Identifier = L"vl::presnetation::controls::GuiListControl::IItemPrimaryTextView"; const wchar_t* const GuiListControl::IItemBindingView::Identifier = L"vl::presnetation::controls::GuiListControl::IItemBindingView"; /*********************************************************************** GuiListControl::ItemCallback ***********************************************************************/ GuiListControl::ItemCallback::ItemCallback(GuiListControl* _listControl) :listControl(_listControl) { } GuiListControl::ItemCallback::~ItemCallback() { ClearCache(); } void GuiListControl::ItemCallback::ClearCache() { for(vint i=0;iitemStyleProvider->DestroyItemStyle(cachedStyles[i]); } for(vint i=0;iitemStyleProvider->DestroyItemStyle(installedStyles[i]); } cachedStyles.Clear(); installedStyles.Clear(); } void GuiListControl::ItemCallback::OnAttached(IItemProvider* provider) { } void GuiListControl::ItemCallback::OnItemModified(vint start, vint count, vint newCount) { listControl->OnItemModified(start, count, newCount); } GuiListControl::IItemStyleController* GuiListControl::ItemCallback::RequestItem(vint itemIndex) { vint id=listControl->itemStyleProvider->GetItemStyleId(itemIndex); IItemStyleController* style=0; for(vint i=0;iGetItemStyleId()==id) { style=cachedStyle; cachedStyles.RemoveAt(i); break; } } if(!style) { style=listControl->itemStyleProvider->CreateItemStyle(id); } listControl->itemStyleProvider->Install(style, itemIndex); style->OnInstalled(); installedStyles.Add(style); listControl->GetContainerComposition()->AddChild(style->GetBoundsComposition()); listControl->OnStyleInstalled(itemIndex, style); return style; } void GuiListControl::ItemCallback::ReleaseItem(IItemStyleController* style) { vint index=installedStyles.IndexOf(style); if(index!=-1) { listControl->OnStyleUninstalled(style); listControl->GetContainerComposition()->RemoveChild(style->GetBoundsComposition()); installedStyles.RemoveAt(index); style->OnUninstalled(); if(style->IsCacheable()) { cachedStyles.Add(style); } else { listControl->itemStyleProvider->DestroyItemStyle(style); } } } void GuiListControl::ItemCallback::SetViewLocation(Point value) { Rect virtualRect(value, listControl->GetViewSize()); Rect realRect=listControl->axis->VirtualRectToRealRect(listControl->fullSize, virtualRect); listControl->GetHorizontalScroll()->SetPosition(realRect.Left()); listControl->GetVerticalScroll()->SetPosition(realRect.Top()); } Size GuiListControl::ItemCallback::GetStylePreferredSize(IItemStyleController* style) { Size size=style->GetBoundsComposition()->GetPreferredBounds().GetSize(); return listControl->axis->RealSizeToVirtualSize(size); } void GuiListControl::ItemCallback::SetStyleAlignmentToParent(IItemStyleController* style, Margin margin) { Margin newMargin=listControl->axis->VirtualMarginToRealMargin(margin); style->GetBoundsComposition()->SetAlignmentToParent(newMargin); } Rect GuiListControl::ItemCallback::GetStyleBounds(IItemStyleController* style) { Rect bounds=style->GetBoundsComposition()->GetBounds(); return listControl->axis->RealRectToVirtualRect(listControl->GetViewSize(), bounds); } void GuiListControl::ItemCallback::SetStyleBounds(IItemStyleController* style, Rect bounds) { Rect newBounds=listControl->axis->VirtualRectToRealRect(listControl->GetViewSize(), bounds); return style->GetBoundsComposition()->SetBounds(newBounds); } compositions::GuiGraphicsComposition* GuiListControl::ItemCallback::GetContainerComposition() { return listControl->GetContainerComposition(); } void GuiListControl::ItemCallback::OnTotalSizeChanged() { listControl->CalculateView(); } /*********************************************************************** GuiListControl ***********************************************************************/ void GuiListControl::OnItemModified(vint start, vint count, vint newCount) { } void GuiListControl::OnStyleInstalled(vint itemIndex, IItemStyleController* style) { AttachItemEvents(style); } void GuiListControl::OnStyleUninstalled(IItemStyleController* style) { DetachItemEvents(style); } void GuiListControl::OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget) { SetStyleProviderAndArranger(itemStyleProvider, itemArranger); GuiScrollView::OnRenderTargetChanged(renderTarget); } void GuiListControl::OnBeforeReleaseGraphicsHost() { GuiScrollView::OnBeforeReleaseGraphicsHost(); SetStyleProviderAndArranger(0, 0); } Size GuiListControl::QueryFullSize() { Size virtualSize=itemArranger?itemArranger->GetTotalSize():Size(0, 0); fullSize=axis->VirtualSizeToRealSize(virtualSize); return fullSize; } void GuiListControl::UpdateView(Rect viewBounds) { if(itemArranger) { Rect newBounds=axis->RealRectToVirtualRect(fullSize, viewBounds); itemArranger->OnViewChanged(newBounds); } } void GuiListControl::OnBoundsMouseButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(GetVisuallyEnabled()) { boundsComposition->GetRelatedGraphicsHost()->SetFocus(boundsComposition); } } void GuiListControl::SetStyleProviderAndArranger(Ptr styleProvider, Ptr arranger) { if(itemStyleProvider) { itemStyleProvider->DetachListControl(); } if(itemArranger) { itemArranger->DetachListControl(); itemArranger->SetCallback(0); itemProvider->DetachCallback(itemArranger.Obj()); } callback->ClearCache(); itemStyleProvider=styleProvider; itemArranger=arranger; GetVerticalScroll()->SetPosition(0); GetHorizontalScroll()->SetPosition(0); if(itemStyleProvider) { itemStyleProvider->AttachListControl(this); } if(itemArranger) { itemProvider->AttachCallback(itemArranger.Obj()); itemArranger->SetCallback(callback.Obj()); itemArranger->AttachListControl(this); } CalculateView(); } void GuiListControl::OnItemMouseEvent(compositions::GuiItemMouseEvent& itemEvent, IItemStyleController* style, compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(itemArranger && GetVisuallyEnabled()) { vint itemIndex=itemArranger->GetVisibleIndex(style); if(itemIndex!=-1) { GuiItemMouseEventArgs redirectArguments; (GuiMouseEventArgs&)redirectArguments=arguments; redirectArguments.compositionSource=GetBoundsComposition(); redirectArguments.eventSource=GetBoundsComposition(); redirectArguments.itemIndex=itemIndex; itemEvent.Execute(redirectArguments); arguments=redirectArguments; } } } void GuiListControl::OnItemNotifyEvent(compositions::GuiItemNotifyEvent& itemEvent, IItemStyleController* style, compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(itemArranger && GetVisuallyEnabled()) { vint itemIndex=itemArranger->GetVisibleIndex(style); if(itemIndex!=-1) { GuiItemEventArgs redirectArguments; (GuiEventArgs&)redirectArguments=arguments; redirectArguments.compositionSource=GetBoundsComposition(); redirectArguments.eventSource=GetBoundsComposition(); redirectArguments.itemIndex=itemIndex; itemEvent.Execute(redirectArguments); arguments=redirectArguments; } } } #define ATTACH_ITEM_MOUSE_EVENT(EVENTNAME, ITEMEVENTNAME)\ {\ Func func(this, &GuiListControl::OnItemMouseEvent);\ helper->EVENTNAME##Handler=style->GetBoundsComposition()->GetEventReceiver()->EVENTNAME.AttachFunction(\ Curry(Curry(func)(ITEMEVENTNAME))(style)\ );\ }\ #define ATTACH_ITEM_NOTIFY_EVENT(EVENTNAME, ITEMEVENTNAME)\ {\ Func func(this, &GuiListControl::OnItemNotifyEvent);\ helper->EVENTNAME##Handler=style->GetBoundsComposition()->GetEventReceiver()->EVENTNAME.AttachFunction(\ Curry(Curry(func)(ITEMEVENTNAME))(style)\ );\ }\ void GuiListControl::AttachItemEvents(IItemStyleController* style) { vint index=visibleStyles.Keys().IndexOf(style); if(index==-1) { Ptr helper=new VisibleStyleHelper; visibleStyles.Add(style, helper); ATTACH_ITEM_MOUSE_EVENT(leftButtonDown, ItemLeftButtonDown); ATTACH_ITEM_MOUSE_EVENT(leftButtonUp, ItemLeftButtonUp); ATTACH_ITEM_MOUSE_EVENT(leftButtonDoubleClick, ItemLeftButtonDoubleClick); ATTACH_ITEM_MOUSE_EVENT(middleButtonDown, ItemMiddleButtonDown); ATTACH_ITEM_MOUSE_EVENT(middleButtonUp, ItemMiddleButtonUp); ATTACH_ITEM_MOUSE_EVENT(middleButtonDoubleClick, ItemMiddleButtonDoubleClick); ATTACH_ITEM_MOUSE_EVENT(rightButtonDown, ItemRightButtonDown); ATTACH_ITEM_MOUSE_EVENT(rightButtonUp, ItemRightButtonUp); ATTACH_ITEM_MOUSE_EVENT(rightButtonDoubleClick, ItemRightButtonDoubleClick); ATTACH_ITEM_MOUSE_EVENT(mouseMove, ItemMouseMove); ATTACH_ITEM_NOTIFY_EVENT(mouseEnter, ItemMouseEnter); ATTACH_ITEM_NOTIFY_EVENT(mouseLeave, ItemMouseLeave); } } #undef ATTACH_ITEM_MOUSE_EVENT #undef ATTACH_ITEM_NOTIFY_EVENT #define DETACH_ITEM_EVENT(EVENTNAME) style->GetBoundsComposition()->GetEventReceiver()->EVENTNAME.Detach(helper->EVENTNAME##Handler) void GuiListControl::DetachItemEvents(IItemStyleController* style) { vint index=visibleStyles.Keys().IndexOf(style); if(index!=-1) { Ptr helper=visibleStyles.Values().Get(index); visibleStyles.Remove(style); DETACH_ITEM_EVENT(leftButtonDown); DETACH_ITEM_EVENT(leftButtonUp); DETACH_ITEM_EVENT(leftButtonDoubleClick); DETACH_ITEM_EVENT(middleButtonDown); DETACH_ITEM_EVENT(middleButtonUp); DETACH_ITEM_EVENT(middleButtonDoubleClick); DETACH_ITEM_EVENT(rightButtonDown); DETACH_ITEM_EVENT(rightButtonUp); DETACH_ITEM_EVENT(rightButtonDoubleClick); DETACH_ITEM_EVENT(mouseMove); DETACH_ITEM_EVENT(mouseEnter); DETACH_ITEM_EVENT(mouseLeave); } } #undef DETACH_ITEM_EVENT GuiListControl::GuiListControl(IStyleProvider* _styleProvider, IItemProvider* _itemProvider, bool acceptFocus) :GuiScrollView(_styleProvider) ,itemProvider(_itemProvider) { StyleProviderChanged.SetAssociatedComposition(boundsComposition); ArrangerChanged.SetAssociatedComposition(boundsComposition); AxisChanged.SetAssociatedComposition(boundsComposition); ItemLeftButtonDown.SetAssociatedComposition(boundsComposition); ItemLeftButtonUp.SetAssociatedComposition(boundsComposition); ItemLeftButtonDoubleClick.SetAssociatedComposition(boundsComposition); ItemMiddleButtonDown.SetAssociatedComposition(boundsComposition); ItemMiddleButtonUp.SetAssociatedComposition(boundsComposition); ItemMiddleButtonDoubleClick.SetAssociatedComposition(boundsComposition); ItemRightButtonDown.SetAssociatedComposition(boundsComposition); ItemRightButtonUp.SetAssociatedComposition(boundsComposition); ItemRightButtonDoubleClick.SetAssociatedComposition(boundsComposition); ItemMouseMove.SetAssociatedComposition(boundsComposition); ItemMouseEnter.SetAssociatedComposition(boundsComposition); ItemMouseLeave.SetAssociatedComposition(boundsComposition); callback=new ItemCallback(this); itemProvider->AttachCallback(callback.Obj()); axis=new GuiDefaultAxis; if(acceptFocus) { boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiListControl::OnBoundsMouseButtonDown); boundsComposition->GetEventReceiver()->middleButtonDown.AttachMethod(this, &GuiListControl::OnBoundsMouseButtonDown); boundsComposition->GetEventReceiver()->rightButtonDown.AttachMethod(this, &GuiListControl::OnBoundsMouseButtonDown); SetFocusableComposition(boundsComposition); } } GuiListControl::~GuiListControl() { if(itemArranger) { itemProvider->DetachCallback(itemArranger.Obj()); } callback->ClearCache(); itemStyleProvider=0; itemArranger=0; } GuiListControl::IItemProvider* GuiListControl::GetItemProvider() { return itemProvider.Obj(); } GuiListControl::IItemStyleProvider* GuiListControl::GetStyleProvider() { return itemStyleProvider.Obj(); } Ptr GuiListControl::SetStyleProvider(Ptr value) { Ptr old=itemStyleProvider; SetStyleProviderAndArranger(value, itemArranger); StyleProviderChanged.Execute(GetNotifyEventArguments()); return old; } GuiListControl::IItemArranger* GuiListControl::GetArranger() { return itemArranger.Obj(); } Ptr GuiListControl::SetArranger(Ptr value) { Ptr old=itemArranger; SetStyleProviderAndArranger(itemStyleProvider, value); ArrangerChanged.Execute(GetNotifyEventArguments()); return old; } compositions::IGuiAxis* GuiListControl::GetAxis() { return axis.Obj(); } Ptr GuiListControl::SetAxis(Ptr value) { Ptr old=axis; axis=value; SetStyleProviderAndArranger(itemStyleProvider, itemArranger); AxisChanged.Execute(GetNotifyEventArguments()); return old; } bool GuiListControl::EnsureItemVisible(vint itemIndex) { if(itemIndex<0 || itemIndex>=itemProvider->Count()) { return false; } return itemArranger?itemArranger->EnsureItemVisible(itemIndex):false; } Size GuiListControl::GetAdoptedSize(Size expectedSize) { if (itemArranger) { Size controlSize = GetBoundsComposition()->GetBounds().GetSize(); Size viewSize = GetContainerComposition()->GetBounds().GetSize(); vint x = controlSize.x - viewSize.x; vint y = controlSize.y - viewSize.y; Size expectedViewSize(expectedSize.x - x, expectedSize.y - y); if (axis) { expectedViewSize = axis->RealSizeToVirtualSize(expectedViewSize); } Size adoptedViewSize = itemArranger->GetAdoptedSize(expectedViewSize); if (axis) { adoptedViewSize = axis->VirtualSizeToRealSize(adoptedViewSize); } return Size(adoptedViewSize.x + x, adoptedViewSize.y + y); } return expectedSize; } /*********************************************************************** GuiSelectableListControl ***********************************************************************/ void GuiSelectableListControl::OnItemModified(vint start, vint count, vint newCount) { GuiListControl::OnItemModified(start, count, newCount); if(count!=newCount) { ClearSelection(); } } void GuiSelectableListControl::OnStyleInstalled(vint itemIndex, IItemStyleController* style) { GuiListControl::OnStyleInstalled(itemIndex, style); selectableStyleProvider->SetStyleSelected(style, selectedItems.Contains(itemIndex)); } void GuiSelectableListControl::OnStyleUninstalled(IItemStyleController* style) { GuiListControl::OnStyleUninstalled(style); } void GuiSelectableListControl::OnItemSelectionChanged(vint itemIndex, bool value) { GuiListControl::IItemStyleController* style=itemArranger->GetVisibleStyle(itemIndex); if(style) { selectableStyleProvider->SetStyleSelected(style, value); } } void GuiSelectableListControl::OnItemSelectionCleared() { for(vint i=0;iSetStyleSelected(visibleStyles.Keys()[i], false); } } void GuiSelectableListControl::OnItemLeftButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiItemMouseEventArgs& arguments) { if(GetVisuallyEnabled()) { SelectItemsByClick(arguments.itemIndex, arguments.ctrl, arguments.shift, true); } } void GuiSelectableListControl::OnItemRightButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiItemMouseEventArgs& arguments) { if(GetVisuallyEnabled()) { SelectItemsByClick(arguments.itemIndex, arguments.ctrl, arguments.shift, false); } } void GuiSelectableListControl::NormalizeSelectedItemIndexStartEnd() { if(selectedItemIndexStart<0 || selectedItemIndexStart>=itemProvider->Count()) { selectedItemIndexStart=0; } if(selectedItemIndexEnd<0 || selectedItemIndexEnd>=itemProvider->Count()) { selectedItemIndexEnd=0; } } void GuiSelectableListControl::SetMultipleItemsSelectedSilently(vint start, vint end, bool selected) { if(start>end) { vint temp=start; start=end; end=temp; } vint count=itemProvider->Count(); if(start<0) start=0; if(end>=count) end=count-1; for(vint i=start;i<=end;i++) { if(selected) { if(!selectedItems.Contains(i)) { selectedItems.Add(i); } } else { selectedItems.Remove(i); } OnItemSelectionChanged(i, selected); } } void GuiSelectableListControl::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) { if(GetVisuallyEnabled()) { if(SelectItemsByKey(arguments.code, arguments.ctrl, arguments.shift)) { arguments.handled=true; } } } GuiSelectableListControl::GuiSelectableListControl(IStyleProvider* _styleProvider, IItemProvider* _itemProvider) :GuiListControl(_styleProvider, _itemProvider, true) ,multiSelect(false) ,selectedItemIndexStart(-1) ,selectedItemIndexEnd(-1) { SelectionChanged.SetAssociatedComposition(boundsComposition); ItemLeftButtonDown.AttachMethod(this, &GuiSelectableListControl::OnItemLeftButtonDown); ItemRightButtonDown.AttachMethod(this, &GuiSelectableListControl::OnItemRightButtonDown); if(focusableComposition) { focusableComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiSelectableListControl::OnKeyDown); } } GuiSelectableListControl::~GuiSelectableListControl() { } Ptr GuiSelectableListControl::SetStyleProvider(Ptr value) { selectableStyleProvider = value ? value.Cast() : nullptr; return GuiListControl::SetStyleProvider(value); } bool GuiSelectableListControl::GetMultiSelect() { return multiSelect; } void GuiSelectableListControl::SetMultiSelect(bool value) { if(multiSelect!=value) { multiSelect=value; ClearSelection(); } } const collections::SortedList& GuiSelectableListControl::GetSelectedItems() { return selectedItems; } vint GuiSelectableListControl::GetSelectedItemIndex() { return selectedItems.Count() == 1 ? selectedItems[0] : -1; } WString GuiSelectableListControl::GetSelectedItemText() { vint index = GetSelectedItemIndex(); if (index != -1) { if (auto view = dynamic_cast(itemProvider->RequestView(IItemPrimaryTextView::Identifier))) { WString result = view->GetPrimaryTextViewText(index); itemProvider->ReleaseView(view); return result; } } return L""; } bool GuiSelectableListControl::GetSelected(vint itemIndex) { return selectedItems.Contains(itemIndex); } void GuiSelectableListControl::SetSelected(vint itemIndex, bool value) { if(value) { if(!selectedItems.Contains(itemIndex)) { if(!multiSelect) { selectedItems.Clear(); OnItemSelectionCleared(); } selectedItems.Add(itemIndex); OnItemSelectionChanged(itemIndex, value); SelectionChanged.Execute(GetNotifyEventArguments()); } } else { if(selectedItems.Remove(itemIndex)) { OnItemSelectionChanged(itemIndex, value); SelectionChanged.Execute(GetNotifyEventArguments()); } } } bool GuiSelectableListControl::SelectItemsByClick(vint itemIndex, bool ctrl, bool shift, bool leftButton) { NormalizeSelectedItemIndexStartEnd(); if(0<=itemIndex && itemIndexCount()) { if(!leftButton) { if(selectedItems.Contains(itemIndex)) { return true; } } if(!multiSelect) { shift=false; ctrl=false; } if(shift) { if(!ctrl) { SetMultipleItemsSelectedSilently(selectedItemIndexStart, selectedItemIndexEnd, false); } selectedItemIndexEnd=itemIndex; SetMultipleItemsSelectedSilently(selectedItemIndexStart, selectedItemIndexEnd, true); SelectionChanged.Execute(GetNotifyEventArguments()); } else { if(ctrl) { vint index=selectedItems.IndexOf(itemIndex); if(index==-1) { selectedItems.Add(itemIndex); } else { selectedItems.RemoveAt(index); } OnItemSelectionChanged(itemIndex, index==-1); SelectionChanged.Execute(GetNotifyEventArguments()); } else { selectedItems.Clear(); OnItemSelectionCleared(); selectedItems.Add(itemIndex); OnItemSelectionChanged(itemIndex, true); SelectionChanged.Execute(GetNotifyEventArguments()); } selectedItemIndexStart=itemIndex; selectedItemIndexEnd=itemIndex; } return true; } return false; } bool GuiSelectableListControl::SelectItemsByKey(vint code, bool ctrl, bool shift) { if(!GetArranger()) return false; NormalizeSelectedItemIndexStartEnd(); KeyDirection keyDirection=KeyDirection::Up; switch(code) { case VKEY_UP: keyDirection=KeyDirection::Up; break; case VKEY_DOWN: keyDirection=KeyDirection::Down; break; case VKEY_LEFT: keyDirection=KeyDirection::Left; break; case VKEY_RIGHT: keyDirection=KeyDirection::Right; break; case VKEY_HOME: keyDirection=KeyDirection::Home; break; case VKEY_END: keyDirection=KeyDirection::End; break; case VKEY_PRIOR: keyDirection=KeyDirection::PageUp; break; case VKEY_NEXT: keyDirection=KeyDirection::PageDown; break; default: return false; } if(GetAxis()) { keyDirection=GetAxis()->RealKeyDirectionToVirtualKeyDirection(keyDirection); } vint itemIndex=GetArranger()->FindItem(selectedItemIndexEnd, keyDirection); if(SelectItemsByClick(itemIndex, ctrl, shift, true)) { return EnsureItemVisible(itemIndex); } else { return false; } } void GuiSelectableListControl::ClearSelection() { if(selectedItems.Count()>0) { selectedItems.Clear(); OnItemSelectionCleared(); SelectionChanged.Execute(GetNotifyEventArguments()); } } namespace list { /*********************************************************************** RangedItemArrangerBase ***********************************************************************/ void RangedItemArrangerBase::InvalidateAdoptedSize() { if (listControl) { listControl->AdoptedSizeInvalidated.Execute(listControl->GetNotifyEventArguments()); } } vint RangedItemArrangerBase::CalculateAdoptedSize(vint expectedSize, vint count, vint itemSize) { vint visibleCount = expectedSize / itemSize; if (count < visibleCount) { visibleCount = count; } else if (count > visibleCount) { vint deltaA = expectedSize - count * itemSize; vint deltaB = itemSize - deltaA; if (deltaB < deltaA) { visibleCount++; } } return visibleCount * itemSize; } void RangedItemArrangerBase::ClearStyles() { startIndex=0; if(callback) { for(vint i=0;iReleaseItem(style); } } visibleStyles.Clear(); viewBounds=Rect(0, 0, 0, 0); OnStylesCleared(); } RangedItemArrangerBase::RangedItemArrangerBase() :listControl(0) ,callback(0) ,startIndex(0) { } RangedItemArrangerBase::~RangedItemArrangerBase() { } void RangedItemArrangerBase::OnAttached(GuiListControl::IItemProvider* provider) { itemProvider=provider; if(provider) { OnItemModified(0, 0, provider->Count()); } } void RangedItemArrangerBase::OnItemModified(vint start, vint count, vint newCount) { if(callback) { vint visibleCount=visibleStyles.Count(); vint itemCount=itemProvider->Count(); SortedList reusedStyles; for(vint i=0;i=itemCount) { break; } vint oldIndex=-1; if(index=start+newCount) { oldIndex=index-newCount+count; } if(oldIndex!=-1) { if(oldIndex>=startIndex && oldIndexRequestItem(index); visibleStyles.Add(style); } } for(vint i=0;iReleaseItem(style); } } visibleStyles.RemoveRange(0, visibleCount); if (listControl && listControl->GetStyleProvider()) { for (vint i = 0; i < visibleStyles.Count(); i++) { listControl->GetStyleProvider()->SetStyleIndex(visibleStyles[i], startIndex + i); } } callback->OnTotalSizeChanged(); callback->SetViewLocation(viewBounds.LeftTop()); InvalidateAdoptedSize(); } } void RangedItemArrangerBase::AttachListControl(GuiListControl* value) { listControl = value; InvalidateAdoptedSize(); } void RangedItemArrangerBase::DetachListControl() { listControl = 0; } GuiListControl::IItemArrangerCallback* RangedItemArrangerBase::GetCallback() { return callback; } void RangedItemArrangerBase::SetCallback(GuiListControl::IItemArrangerCallback* value) { if(!value) { ClearStyles(); } callback=value; } Size RangedItemArrangerBase::GetTotalSize() { return OnCalculateTotalSize(); } GuiListControl::IItemStyleController* RangedItemArrangerBase::GetVisibleStyle(vint itemIndex) { if(startIndex<=itemIndex && itemIndexSetStyleAlignmentToParent(style, Margin(0, -1, 0, -1)); callback->SetStyleBounds(style, Rect(Point(0, top), Size(0, rowHeight))); } else { callback->SetStyleAlignmentToParent(style, Margin(-1, -1, -1, -1)); callback->SetStyleBounds(style, Rect(Point(x0, top), Size(width, rowHeight))); } } } vint FixedHeightItemArranger::GetWidth() { return -1; } vint FixedHeightItemArranger::GetYOffset() { return 0; } void FixedHeightItemArranger::OnStylesCleared() { rowHeight=1; InvalidateAdoptedSize(); } Size FixedHeightItemArranger::OnCalculateTotalSize() { if(callback) { vint width=GetWidth(); if(width<0) width=0; return Size(width, rowHeight*itemProvider->Count()+GetYOffset()); } else { return Size(0, 0); } } void FixedHeightItemArranger::OnViewChangedInternal(Rect oldBounds, Rect newBounds) { if(callback) { if(!suppressOnViewChanged) { vint oldVisibleCount=visibleStyles.Count(); vint newRowHeight=rowHeight; vint newStartIndex=(newBounds.Top()-GetYOffset())/rowHeight; if(newStartIndex<0) newStartIndex=0; vint endIndex=startIndex+visibleStyles.Count()-1; vint newEndIndex=(newBounds.Bottom()-1)/newRowHeight; vint itemCount=itemProvider->Count(); for(vint i=newStartIndex;i<=newEndIndex && iRequestItem(i); visibleStyles.Add(style); vint styleHeight=callback->GetStylePreferredSize(style).y; if(newRowHeightReleaseItem(style); } } visibleStyles.RemoveRange(0, oldVisibleCount); if(rowHeight!=newRowHeight) { vint offset=oldBounds.Top()-rowHeight*startIndex; rowHeight=newRowHeight; suppressOnViewChanged=true; callback->OnTotalSizeChanged(); callback->SetViewLocation(Point(0, rowHeight*newStartIndex+offset)); suppressOnViewChanged=false; InvalidateAdoptedSize(); } startIndex=newStartIndex; RearrangeItemBounds(); } } } FixedHeightItemArranger::FixedHeightItemArranger() :rowHeight(1) ,suppressOnViewChanged(false) { } FixedHeightItemArranger::~FixedHeightItemArranger() { } vint FixedHeightItemArranger::FindItem(vint itemIndex, compositions::KeyDirection key) { vint count=itemProvider->Count(); if(count==0) return -1; vint groupCount=viewBounds.Height()/rowHeight; if(groupCount==0) groupCount=1; switch(key) { case KeyDirection::Up: itemIndex--; break; case KeyDirection::Down: itemIndex++; break; case KeyDirection::Home: itemIndex=0; break; case KeyDirection::End: itemIndex=count; break; case KeyDirection::PageUp: itemIndex-=groupCount; break; case KeyDirection::PageDown: itemIndex+=groupCount; break; default: return -1; } if(itemIndex<0) return 0; else if(itemIndex>=count) return count-1; else return itemIndex; } bool FixedHeightItemArranger::EnsureItemVisible(vint itemIndex) { if(callback) { if(itemIndex<0 || itemIndex>=itemProvider->Count()) { return false; } while(true) { vint yOffset=GetYOffset(); vint top=itemIndex*rowHeight; vint bottom=top+rowHeight+yOffset; if(viewBounds.Height()SetViewLocation(location); } return true; } return false; } Size FixedHeightItemArranger::GetAdoptedSize(Size expectedSize) { if (itemProvider) { vint offset = GetYOffset(); vint y = expectedSize.y - offset; vint itemCount = itemProvider->Count(); return Size(expectedSize.x, offset + CalculateAdoptedSize(y, itemCount, rowHeight)); } return expectedSize; } /*********************************************************************** FixedSizeMultiColumnItemArranger ***********************************************************************/ void FixedSizeMultiColumnItemArranger::RearrangeItemBounds() { vint y0=-viewBounds.Top(); vint rowItems=viewBounds.Width()/itemSize.x; if(rowItems<1) rowItems=1; for(vint i=0;iSetStyleBounds(style, Rect(Point(col*itemSize.x, y0+row*itemSize.y), itemSize)); } } void FixedSizeMultiColumnItemArranger::CalculateRange(Size itemSize, Rect bounds, vint count, vint& start, vint& end) { vint startRow=bounds.Top()/itemSize.y; if(startRow<0) startRow=0; vint endRow=(bounds.Bottom()-1)/itemSize.y; vint cols=bounds.Width()/itemSize.x; if(cols<1) cols=1; start=startRow*cols; end=(endRow+1)*cols-1; if(end>=count) end=count-1; } void FixedSizeMultiColumnItemArranger::OnStylesCleared() { itemSize=Size(1, 1); InvalidateAdoptedSize(); } Size FixedSizeMultiColumnItemArranger::OnCalculateTotalSize() { if(callback) { vint rowItems=viewBounds.Width()/itemSize.x; if(rowItems<1) rowItems=1; vint rows=itemProvider->Count()/rowItems; if(itemProvider->Count()%rowItems) rows++; return Size(itemSize.x*rowItems, itemSize.y*rows); } else { return Size(0, 0); } } void FixedSizeMultiColumnItemArranger::OnViewChangedInternal(Rect oldBounds, Rect newBounds) { if(callback) { if(!suppressOnViewChanged) { vint oldVisibleCount=visibleStyles.Count(); Size newItemSize=itemSize; vint endIndex=startIndex+visibleStyles.Count()-1; vint newStartIndex=0; vint newEndIndex=0; vint itemCount=itemProvider->Count(); CalculateRange(newItemSize, newBounds, itemCount, newStartIndex, newEndIndex); if(newItemSize==Size(1, 1) && newStartIndexpreviousEndIndex) { GuiListControl::IItemStyleController* style=callback->RequestItem(i); if(iGetStylePreferredSize(style); if(newItemSize.xnewEndIndex; previousStartIndex=newStartIndex; previousEndIndex=newEndIndex; if(updatedStartIndexnewEndIndex) newEndIndex=updatedEndIndex; if(!again) break; } for(vint i=0;iReleaseItem(style); } } visibleStyles.RemoveRange(0, oldVisibleCount); if(itemSize!=newItemSize) { itemSize=newItemSize; suppressOnViewChanged=true; callback->OnTotalSizeChanged(); suppressOnViewChanged=false; InvalidateAdoptedSize(); } startIndex=newStartIndex; RearrangeItemBounds(); } } } FixedSizeMultiColumnItemArranger::FixedSizeMultiColumnItemArranger() :itemSize(1, 1) ,suppressOnViewChanged(false) { } FixedSizeMultiColumnItemArranger::~FixedSizeMultiColumnItemArranger() { } vint FixedSizeMultiColumnItemArranger::FindItem(vint itemIndex, compositions::KeyDirection key) { vint count=itemProvider->Count(); vint columnCount=viewBounds.Width()/itemSize.x; if(columnCount==0) columnCount=1; vint rowCount=viewBounds.Height()/itemSize.y; if(rowCount==0) rowCount=1; switch(key) { case KeyDirection::Up: itemIndex-=columnCount; break; case KeyDirection::Down: itemIndex+=columnCount; break; case KeyDirection::Left: itemIndex--; break; case KeyDirection::Right: itemIndex++; break; case KeyDirection::Home: itemIndex=0; break; case KeyDirection::End: itemIndex=count; break; case KeyDirection::PageUp: itemIndex-=columnCount*rowCount; break; case KeyDirection::PageDown: itemIndex+=columnCount*rowCount; break; case KeyDirection::PageLeft: itemIndex-=itemIndex%columnCount; break; case KeyDirection::PageRight: itemIndex+=columnCount-itemIndex%columnCount-1; break; default: return -1; } if(itemIndex<0) return 0; else if(itemIndex>=count) return count-1; else return itemIndex; } bool FixedSizeMultiColumnItemArranger::EnsureItemVisible(vint itemIndex) { if(callback) { if(itemIndex<0 || itemIndex>=itemProvider->Count()) { return false; } while(true) { vint rowHeight=itemSize.y; vint columnCount=viewBounds.Width()/itemSize.x; if(columnCount==0) columnCount=1; vint rowIndex=itemIndex/columnCount; vint top=rowIndex*rowHeight; vint bottom=top+rowHeight; if(viewBounds.Height()SetViewLocation(location); } return true; } return false; } Size FixedSizeMultiColumnItemArranger::GetAdoptedSize(Size expectedSize) { if (itemProvider) { vint count = itemProvider->Count(); vint columnCount = viewBounds.Width() / itemSize.x; vint rowCount = viewBounds.Height() / itemSize.y; return Size( CalculateAdoptedSize(expectedSize.x, columnCount, itemSize.x), CalculateAdoptedSize(expectedSize.y, rowCount, itemSize.y) ); } return expectedSize; } /*********************************************************************** FixedHeightMultiColumnItemArranger ***********************************************************************/ void FixedHeightMultiColumnItemArranger::RearrangeItemBounds() { vint rows=0; vint startColumn=0; CalculateRange(itemHeight, viewBounds, rows, startColumn); vint currentWidth=0; vint totalWidth=0; for(vint i=0;iGetStylePreferredSize(style).x; if(currentWidthSetStyleBounds(style, Rect(Point(totalWidth, itemHeight*column), Size(0, 0))); } } void FixedHeightMultiColumnItemArranger::CalculateRange(vint itemHeight, Rect bounds, vint& rows, vint& startColumn) { rows=bounds.Height()/itemHeight; if(rows<1) rows=1; startColumn=bounds.Left()/bounds.Width(); } void FixedHeightMultiColumnItemArranger::OnStylesCleared() { itemHeight=1; InvalidateAdoptedSize(); } Size FixedHeightMultiColumnItemArranger::OnCalculateTotalSize() { if(callback) { vint rows=viewBounds.Height()/itemHeight; if(rows<1) rows=1; vint columns=itemProvider->Count()/rows; if(itemProvider->Count()%rows) columns+=1; return Size(viewBounds.Width()*columns, 0); } else { return Size(0, 0); } } void FixedHeightMultiColumnItemArranger::OnViewChangedInternal(Rect oldBounds, Rect newBounds) { if(callback) { if(!suppressOnViewChanged) { vint oldVisibleCount=visibleStyles.Count(); vint endIndex=startIndex+oldVisibleCount-1; vint newItemHeight=itemHeight; vint itemCount=itemProvider->Count(); vint previousStartIndex=-1; vint previousEndIndex=-1; vint newStartIndex=-1; vint newEndIndex=-1; while(true) { vint newRows=0; vint newStartColumn=0; vint currentWidth=0; vint totalWidth=0; CalculateRange(newItemHeight, newBounds, newRows, newStartColumn); newStartIndex=newRows*newStartColumn; vint currentItemHeight=newItemHeight; for(vint i=newStartIndex;i=newBounds.Width()) { break; } } newEndIndex=i; if(startIndex<=i && i<=endIndex) { GuiListControl::IItemStyleController* style=visibleStyles[i-startIndex]; visibleStyles.Add(style); } else if(ipreviousEndIndex) { GuiListControl::IItemStyleController* style=callback->RequestItem(i); if(iGetStylePreferredSize(style); if(currentWidthnewEndIndex) previousEndIndex=newEndIndex; if(currentItemHeight==newItemHeight) { break; } } newStartIndex=previousStartIndex; newEndIndex=previousEndIndex; for(vint i=0;iReleaseItem(style); } } visibleStyles.RemoveRange(0, oldVisibleCount); if(itemHeight!=newItemHeight) { itemHeight=newItemHeight; suppressOnViewChanged=true; callback->OnTotalSizeChanged(); suppressOnViewChanged=false; InvalidateAdoptedSize(); } startIndex=newStartIndex; RearrangeItemBounds(); } } } FixedHeightMultiColumnItemArranger::FixedHeightMultiColumnItemArranger() :itemHeight(1) ,suppressOnViewChanged(false) { } FixedHeightMultiColumnItemArranger::~FixedHeightMultiColumnItemArranger() { } vint FixedHeightMultiColumnItemArranger::FindItem(vint itemIndex, compositions::KeyDirection key) { vint count=itemProvider->Count(); vint groupCount=viewBounds.Height()/itemHeight; if(groupCount==0) groupCount=1; switch(key) { case KeyDirection::Up: itemIndex--; break; case KeyDirection::Down: itemIndex++; break; case KeyDirection::Left: itemIndex-=groupCount; break; case KeyDirection::Right: itemIndex+=groupCount; break; case KeyDirection::Home: itemIndex=0; break; case KeyDirection::End: itemIndex=count; break; case KeyDirection::PageUp: itemIndex-=itemIndex%groupCount; break; case KeyDirection::PageDown: itemIndex+=groupCount-itemIndex%groupCount-1; break; default: return -1; } if(itemIndex<0) return 0; else if(itemIndex>=count) return count-1; else return itemIndex; } bool FixedHeightMultiColumnItemArranger::EnsureItemVisible(vint itemIndex) { if(callback) { if(itemIndex<0 || itemIndex>=itemProvider->Count()) { return false; } while(true) { vint rowCount=viewBounds.Height()/itemHeight; if(rowCount==0) rowCount=1; vint columnIndex=itemIndex/rowCount; vint minIndex=startIndex; vint maxIndex=startIndex+visibleStyles.Count()-1; Point location=viewBounds.LeftTop(); if(minIndex<=itemIndex && itemIndex<=maxIndex) { Rect bounds=callback->GetStyleBounds(visibleStyles[itemIndex-startIndex]); if(0viewBounds.Width()) { break; } else if(bounds.Left()<0) { location.x-=viewBounds.Width(); } else if(bounds.Right()>viewBounds.Width()) { location.x+=viewBounds.Width(); } else { break; } } else if(columnIndex=maxIndex/rowCount) { location.x+=viewBounds.Width(); } else { break; } callback->SetViewLocation(location); } return true; } return false; } Size FixedHeightMultiColumnItemArranger::GetAdoptedSize(Size expectedSize) { if (itemProvider) { vint count = itemProvider->Count(); return Size(expectedSize.x, CalculateAdoptedSize(expectedSize.y, count, itemHeight)); } return expectedSize; } /*********************************************************************** ItemStyleControllerBase ***********************************************************************/ void ItemStyleControllerBase::Initialize(compositions::GuiBoundsComposition* _boundsComposition, GuiControl* _associatedControl) { boundsComposition=_boundsComposition; associatedControl=_associatedControl; } void ItemStyleControllerBase::Finalize() { if(boundsComposition && !isInstalled) { if(associatedControl) { delete associatedControl; } else { delete boundsComposition; } } boundsComposition=0; associatedControl=0; } ItemStyleControllerBase::ItemStyleControllerBase(GuiListControl::IItemStyleProvider* _provider, vint _styleId) :provider(_provider) ,styleId(_styleId) ,boundsComposition(0) ,associatedControl(0) ,isInstalled(false) { } ItemStyleControllerBase::~ItemStyleControllerBase() { Finalize(); } GuiListControl::IItemStyleProvider* ItemStyleControllerBase::GetStyleProvider() { return provider; } vint ItemStyleControllerBase::GetItemStyleId() { return styleId; } compositions::GuiBoundsComposition* ItemStyleControllerBase::GetBoundsComposition() { return boundsComposition; } bool ItemStyleControllerBase::IsCacheable() { return true; } bool ItemStyleControllerBase::IsInstalled() { return isInstalled; } void ItemStyleControllerBase::OnInstalled() { isInstalled=true; } void ItemStyleControllerBase::OnUninstalled() { isInstalled=false; } /*********************************************************************** ItemProviderBase ***********************************************************************/ void ItemProviderBase::InvokeOnItemModified(vint start, vint count, vint newCount) { for(vint i=0;iOnItemModified(start, count, newCount); } } ItemProviderBase::ItemProviderBase() { } ItemProviderBase::~ItemProviderBase() { for(vint i=0;iOnAttached(0); } } bool ItemProviderBase::AttachCallback(GuiListControl::IItemProviderCallback* value) { if(callbacks.Contains(value)) { return false; } else { callbacks.Add(value); value->OnAttached(this); return true; } } bool ItemProviderBase::DetachCallback(GuiListControl::IItemProviderCallback* value) { vint index=callbacks.IndexOf(value); if(index==-1) { return false; } else { value->OnAttached(0); callbacks.Remove(value); return true; } } } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUILISTVIEWCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace compositions; using namespace collections; using namespace reflection::description; namespace list { /*********************************************************************** ListViewItemStyleProviderBase::TextItemStyleController ***********************************************************************/ ListViewItemStyleProviderBase::ListViewItemStyleController::ListViewItemStyleController(ListViewItemStyleProviderBase* provider) :ItemStyleControllerBase(provider, 0) ,backgroundButton(0) ,listViewItemStyleProvider(provider) { backgroundButton=new GuiSelectableButton(listViewItemStyleProvider->listControl->GetListViewStyleProvider()->CreateItemBackground()); backgroundButton->SetAutoSelection(false); Initialize(backgroundButton->GetBoundsComposition(), backgroundButton); } ListViewItemStyleProviderBase::ListViewItemStyleController::~ListViewItemStyleController() { } bool ListViewItemStyleProviderBase::ListViewItemStyleController::GetSelected() { return backgroundButton->GetSelected(); } void ListViewItemStyleProviderBase::ListViewItemStyleController::SetSelected(bool value) { backgroundButton->SetSelected(value); } /*********************************************************************** ListViewItemStyleProviderBase ***********************************************************************/ ListViewItemStyleProviderBase::ListViewItemStyleProviderBase() :listControl(0) { } ListViewItemStyleProviderBase::~ListViewItemStyleProviderBase() { } void ListViewItemStyleProviderBase::AttachListControl(GuiListControl* value) { listControl=dynamic_cast(value); } void ListViewItemStyleProviderBase::DetachListControl() { listControl=0; } vint ListViewItemStyleProviderBase::GetItemStyleId(vint itemIndex) { return 0; } void ListViewItemStyleProviderBase::SetStyleSelected(GuiListControl::IItemStyleController* style, bool value) { ListViewItemStyleController* textStyle=dynamic_cast(style); textStyle->SetSelected(value); } } /*********************************************************************** GuiListViewColumnHeader ***********************************************************************/ GuiListViewColumnHeader::GuiListViewColumnHeader(IStyleController* _styleController) :GuiMenuButton(_styleController) ,columnSortingState(NotSorted) ,styleController(_styleController) { styleController->SetColumnSortingState(columnSortingState); } GuiListViewColumnHeader::~GuiListViewColumnHeader() { } bool GuiListViewColumnHeader::IsAltAvailable() { return false; } GuiListViewColumnHeader::ColumnSortingState GuiListViewColumnHeader::GetColumnSortingState() { return columnSortingState; } void GuiListViewColumnHeader::SetColumnSortingState(ColumnSortingState value) { if(columnSortingState!=value) { columnSortingState=value; styleController->SetColumnSortingState(columnSortingState); } } /*********************************************************************** GuiListViewBase ***********************************************************************/ GuiListViewBase::GuiListViewBase(IStyleProvider* _styleProvider, GuiListControl::IItemProvider* _itemProvider) :GuiSelectableListControl(_styleProvider, _itemProvider) ,styleProvider(0) { styleProvider=dynamic_cast(styleController->GetStyleProvider()); ColumnClicked.SetAssociatedComposition(boundsComposition); } GuiListViewBase::~GuiListViewBase() { } GuiListViewBase::IStyleProvider* GuiListViewBase::GetListViewStyleProvider() { return styleProvider; } Ptr GuiListViewBase::SetStyleProvider(Ptr value) { if(value.Cast()) { return GuiSelectableListControl::SetStyleProvider(value); } else { return 0; } } namespace list { /*********************************************************************** ListViewItemStyleProvider::ListViewContentItemStyleController ***********************************************************************/ ListViewItemStyleProvider::ListViewContentItemStyleController::ListViewContentItemStyleController(ListViewItemStyleProvider* provider) :ListViewItemStyleController(provider) ,listViewItemStyleProvider(provider) { content=listViewItemStyleProvider->listViewItemContentProvider->CreateItemContent(backgroundButton->GetFont()); GuiBoundsComposition* composition=content->GetContentComposition(); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); backgroundButton->GetContainerComposition()->AddChild(composition); GuiBoundsComposition* decorator=content->GetBackgroundDecorator(); if(decorator) { backgroundButton->GetBoundsComposition()->AddChild(decorator); backgroundButton->GetBoundsComposition()->MoveChild(decorator, 0); } } ListViewItemStyleProvider::ListViewContentItemStyleController::~ListViewContentItemStyleController() { } void ListViewItemStyleProvider::ListViewContentItemStyleController::OnUninstalled() { ListViewItemStyleController::OnUninstalled(); content->Uninstall(); } ListViewItemStyleProvider::IListViewItemContent* ListViewItemStyleProvider::ListViewContentItemStyleController::GetItemContent() { return content.Obj(); } void ListViewItemStyleProvider::ListViewContentItemStyleController::Install(IListViewItemView* view, vint itemIndex) { content->Install(listViewItemStyleProvider->listControl->GetListViewStyleProvider(), view, itemIndex); } /*********************************************************************** ListViewItemStyleProvider ***********************************************************************/ const wchar_t* const ListViewItemStyleProvider::IListViewItemView::Identifier = L"vl::presentation::controls::list::ListViewItemStyleProvider::IListViewItemView"; ListViewItemStyleProvider::ListViewItemStyleProvider(Ptr itemContentProvider) :listViewItemView(0) ,listViewItemContentProvider(itemContentProvider) { } ListViewItemStyleProvider::~ListViewItemStyleProvider() { } void ListViewItemStyleProvider::AttachListControl(GuiListControl* value) { ListViewItemStyleProviderBase::AttachListControl(value); listViewItemView=dynamic_cast(value->GetItemProvider()->RequestView(IListViewItemView::Identifier)); listViewItemContentProvider->AttachListControl(value); } void ListViewItemStyleProvider::DetachListControl() { listViewItemContentProvider->DetachListControl(); listControl->GetItemProvider()->ReleaseView(listViewItemView); listViewItemView=0; ListViewItemStyleProviderBase::DetachListControl(); } GuiListControl::IItemStyleController* ListViewItemStyleProvider::CreateItemStyle(vint styleId) { ListViewContentItemStyleController* itemStyle=new ListViewContentItemStyleController(this); itemStyles.Add(itemStyle); return itemStyle; } void ListViewItemStyleProvider::DestroyItemStyle(GuiListControl::IItemStyleController* style) { ListViewContentItemStyleController* itemStyle=dynamic_cast(style); if(itemStyle) { itemStyles.Remove(itemStyle); delete itemStyle; } } void ListViewItemStyleProvider::Install(GuiListControl::IItemStyleController* style, vint itemIndex) { ListViewContentItemStyleController* itemStyle=dynamic_cast(style); itemStyle->Install(listViewItemView, itemIndex); } void ListViewItemStyleProvider::SetStyleIndex(GuiListControl::IItemStyleController* style, vint value) { } ListViewItemStyleProvider::IListViewItemContentProvider* ListViewItemStyleProvider::GetItemContentProvider() { return listViewItemContentProvider.Obj(); } const ListViewItemStyleProvider::ItemStyleList& ListViewItemStyleProvider::GetCreatedItemStyles() { return itemStyles; } bool ListViewItemStyleProvider::IsItemStyleAttachedToListView(GuiListControl::IItemStyleController* itemStyle) { return itemStyle && itemStyle->GetBoundsComposition()->GetParent(); } ListViewItemStyleProvider::IListViewItemContent* ListViewItemStyleProvider::GetItemContentFromItemStyleController(GuiListControl::IItemStyleController* itemStyleController) { if(itemStyleController) { ListViewContentItemStyleController* item=dynamic_cast(itemStyleController); if(item) { return item->GetItemContent(); } } return 0; } GuiListControl::IItemStyleController* ListViewItemStyleProvider::GetItemStyleControllerFromItemContent(IListViewItemContent* itemContent) { FOREACH(GuiListControl::IItemStyleController*, style, itemStyles) { if(GetItemContentFromItemStyleController(style)==itemContent) { return style; } } return 0; } /*********************************************************************** ListViewBigIconContentProvider ***********************************************************************/ ListViewBigIconContentProvider::ItemContent::ItemContent(Size minIconSize, bool fitImage, const FontProperties& font) :contentComposition(0) { contentComposition=new GuiBoundsComposition; contentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GuiTableComposition* table=new GuiTableComposition; contentComposition->AddChild(table); table->SetRowsAndColumns(2, 3); table->SetRowOption(0, GuiCellOption::MinSizeOption()); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); table->SetColumnOption(2, GuiCellOption::PercentageOption(0.5)); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetCellPadding(5); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 1, 1); cell->SetPreferredMinSize(minIconSize); if (!fitImage) { cell->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } image=GuiImageFrameElement::Create(); image->SetStretch(true); cell->SetOwnedElement(image); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); cell->SetSite(1, 0, 1, 3); cell->SetPreferredMinSize(Size(64, 40)); text=GuiSolidLabelElement::Create(); text->SetAlignments(Alignment::Center, Alignment::Top); text->SetFont(font); text->SetWrapLine(true); text->SetEllipse(true); cell->SetOwnedElement(text); } } ListViewBigIconContentProvider::ItemContent::~ItemContent() { } compositions::GuiBoundsComposition* ListViewBigIconContentProvider::ItemContent::GetContentComposition() { return contentComposition; } compositions::GuiBoundsComposition* ListViewBigIconContentProvider::ItemContent::GetBackgroundDecorator() { return 0; } void ListViewBigIconContentProvider::ItemContent::Install(GuiListViewBase::IStyleProvider* styleProvider, ListViewItemStyleProvider::IListViewItemView* view, vint itemIndex) { Ptr imageData=view->GetLargeImage(itemIndex); if(imageData) { image->SetImage(imageData->GetImage(), imageData->GetFrameIndex()); } else { image->SetImage(0); } text->SetText(view->GetText(itemIndex)); text->SetColor(styleProvider->GetPrimaryTextColor()); } void ListViewBigIconContentProvider::ItemContent::Uninstall() { } ListViewBigIconContentProvider::ListViewBigIconContentProvider(Size _minIconSize, bool _fitImage) :minIconSize(_minIconSize) ,fitImage(_fitImage) { } ListViewBigIconContentProvider::~ListViewBigIconContentProvider() { } compositions::IGuiAxis* ListViewBigIconContentProvider::CreatePreferredAxis() { return new GuiDefaultAxis; } GuiListControl::IItemArranger* ListViewBigIconContentProvider::CreatePreferredArranger() { return new FixedSizeMultiColumnItemArranger; } ListViewItemStyleProvider::IListViewItemContent* ListViewBigIconContentProvider::CreateItemContent(const FontProperties& font) { return new ItemContent(minIconSize, fitImage, font); } void ListViewBigIconContentProvider::AttachListControl(GuiListControl* value) { } void ListViewBigIconContentProvider::DetachListControl() { } /*********************************************************************** ListViewSmallIconContentProvider ***********************************************************************/ ListViewSmallIconContentProvider::ItemContent::ItemContent(Size minIconSize, bool fitImage, const FontProperties& font) :contentComposition(0) { contentComposition=new GuiBoundsComposition; contentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GuiTableComposition* table=new GuiTableComposition; contentComposition->AddChild(table); table->SetRowsAndColumns(3, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetCellPadding(2); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(1, 0, 1, 1); cell->SetPreferredMinSize(minIconSize); if (!fitImage) { cell->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } image=GuiImageFrameElement::Create(); image->SetStretch(true); cell->SetOwnedElement(image); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 3, 1); cell->SetPreferredMinSize(Size(192, 0)); text=GuiSolidLabelElement::Create(); text->SetAlignments(Alignment::Left, Alignment::Center); text->SetFont(font); text->SetEllipse(true); cell->SetOwnedElement(text); } } ListViewSmallIconContentProvider::ItemContent::~ItemContent() { } compositions::GuiBoundsComposition* ListViewSmallIconContentProvider::ItemContent::GetContentComposition() { return contentComposition; } compositions::GuiBoundsComposition* ListViewSmallIconContentProvider::ItemContent::GetBackgroundDecorator() { return 0; } void ListViewSmallIconContentProvider::ItemContent::Install(GuiListViewBase::IStyleProvider* styleProvider, ListViewItemStyleProvider::IListViewItemView* view, vint itemIndex) { Ptr imageData=view->GetSmallImage(itemIndex); if(imageData) { image->SetImage(imageData->GetImage(), imageData->GetFrameIndex()); } else { image->SetImage(0); } text->SetText(view->GetText(itemIndex)); text->SetColor(styleProvider->GetPrimaryTextColor()); } void ListViewSmallIconContentProvider::ItemContent::Uninstall() { } ListViewSmallIconContentProvider::ListViewSmallIconContentProvider(Size _minIconSize, bool _fitImage) :minIconSize(_minIconSize) ,fitImage(_fitImage) { } ListViewSmallIconContentProvider::~ListViewSmallIconContentProvider() { } compositions::IGuiAxis* ListViewSmallIconContentProvider::CreatePreferredAxis() { return new GuiDefaultAxis; } GuiListControl::IItemArranger* ListViewSmallIconContentProvider::CreatePreferredArranger() { return new FixedSizeMultiColumnItemArranger; } ListViewItemStyleProvider::IListViewItemContent* ListViewSmallIconContentProvider::CreateItemContent(const FontProperties& font) { return new ItemContent(minIconSize, fitImage, font); } void ListViewSmallIconContentProvider::AttachListControl(GuiListControl* value) { } void ListViewSmallIconContentProvider::DetachListControl() { } /*********************************************************************** ListViewListContentProvider ***********************************************************************/ ListViewListContentProvider::ItemContent::ItemContent(Size minIconSize, bool fitImage, const FontProperties& font) :contentComposition(0) { contentComposition=new GuiBoundsComposition; contentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GuiTableComposition* table=new GuiTableComposition; contentComposition->AddChild(table); table->SetRowsAndColumns(3, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetCellPadding(2); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(1, 0, 1, 1); cell->SetPreferredMinSize(minIconSize); if (!fitImage) { cell->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } image=GuiImageFrameElement::Create(); image->SetStretch(true); cell->SetOwnedElement(image); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 3, 1); cell->SetMargin(Margin(0, 0, 16, 0)); text=GuiSolidLabelElement::Create(); text->SetAlignments(Alignment::Left, Alignment::Center); text->SetFont(font); cell->SetOwnedElement(text); } } ListViewListContentProvider::ItemContent::~ItemContent() { } compositions::GuiBoundsComposition* ListViewListContentProvider::ItemContent::GetContentComposition() { return contentComposition; } compositions::GuiBoundsComposition* ListViewListContentProvider::ItemContent::GetBackgroundDecorator() { return 0; } void ListViewListContentProvider::ItemContent::Install(GuiListViewBase::IStyleProvider* styleProvider, ListViewItemStyleProvider::IListViewItemView* view, vint itemIndex) { Ptr imageData=view->GetSmallImage(itemIndex); if(imageData) { image->SetImage(imageData->GetImage(), imageData->GetFrameIndex()); } else { image->SetImage(0); } text->SetText(view->GetText(itemIndex)); text->SetColor(styleProvider->GetPrimaryTextColor()); } void ListViewListContentProvider::ItemContent::Uninstall() { } ListViewListContentProvider::ListViewListContentProvider(Size _minIconSize, bool _fitImage) :minIconSize(_minIconSize) ,fitImage(_fitImage) { } ListViewListContentProvider::~ListViewListContentProvider() { } compositions::IGuiAxis* ListViewListContentProvider::CreatePreferredAxis() { return new GuiDefaultAxis; } GuiListControl::IItemArranger* ListViewListContentProvider::CreatePreferredArranger() { return new FixedHeightMultiColumnItemArranger; } ListViewItemStyleProvider::IListViewItemContent* ListViewListContentProvider::CreateItemContent(const FontProperties& font) { return new ItemContent(minIconSize, fitImage, font); } void ListViewListContentProvider::AttachListControl(GuiListControl* value) { } void ListViewListContentProvider::DetachListControl() { } /*********************************************************************** ListViewTileContentProvider ***********************************************************************/ void ListViewTileContentProvider::ItemContent::RemoveTextElement(vint textRow) { GuiCellComposition* cell=textTable->GetSitedCell(textRow+1, 0); textTable->RemoveChild(cell); delete cell; } elements::GuiSolidLabelElement* ListViewTileContentProvider::ItemContent::CreateTextElement(vint textRow, const FontProperties& font) { GuiCellComposition* cell=new GuiCellComposition; textTable->AddChild(cell); cell->SetSite(textRow+1, 0, 1, 1); elements::GuiSolidLabelElement* textElement=GuiSolidLabelElement::Create(); textElement->SetAlignments(Alignment::Left, Alignment::Center); textElement->SetFont(font); textElement->SetEllipse(true); cell->SetOwnedElement(textElement); return textElement; } void ListViewTileContentProvider::ItemContent::ResetTextTable(vint textRows) { textTable->SetRowsAndColumns(textRows+2, 1); textTable->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); for(vint i=0;iSetRowOption(i+1, GuiCellOption::MinSizeOption()); } textTable->SetRowOption(textRows+1, GuiCellOption::PercentageOption(0.5)); textTable->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); } ListViewTileContentProvider::ItemContent::ItemContent(Size minIconSize, bool fitImage, const FontProperties& font) :contentComposition(0) { contentComposition=new GuiBoundsComposition; contentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GuiTableComposition* table=new GuiTableComposition; contentComposition->AddChild(table); table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); table->SetRowsAndColumns(3, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetCellPadding(4); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(1, 0, 1, 1); cell->SetPreferredMinSize(minIconSize); if (!fitImage) { cell->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } image=GuiImageFrameElement::Create(); image->SetStretch(true); cell->SetOwnedElement(image); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 3, 1); cell->SetPreferredMinSize(Size(224, 0)); textTable=new GuiTableComposition; textTable->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); textTable->SetCellPadding(1); ResetTextTable(1); textTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(textTable); { text=CreateTextElement(0, font); } } } ListViewTileContentProvider::ItemContent::~ItemContent() { } compositions::GuiBoundsComposition* ListViewTileContentProvider::ItemContent::GetContentComposition() { return contentComposition; } compositions::GuiBoundsComposition* ListViewTileContentProvider::ItemContent::GetBackgroundDecorator() { return 0; } void ListViewTileContentProvider::ItemContent::Install(GuiListViewBase::IStyleProvider* styleProvider, ListViewItemStyleProvider::IListViewItemView* view, vint itemIndex) { Ptr imageData=view->GetLargeImage(itemIndex); if(imageData) { image->SetImage(imageData->GetImage(), imageData->GetFrameIndex()); } else { image->SetImage(0); } text->SetText(view->GetText(itemIndex)); text->SetColor(styleProvider->GetPrimaryTextColor()); for(vint i=0;iGetDataColumnCount(); ResetTextTable(dataColumnCount+1); dataTexts.Resize(dataColumnCount); for(vint i=0;iGetFont()); dataTexts[i]->SetText(view->GetSubItem(itemIndex, view->GetDataColumn(i))); dataTexts[i]->SetColor(styleProvider->GetSecondaryTextColor()); } } void ListViewTileContentProvider::ItemContent::Uninstall() { } ListViewTileContentProvider::ListViewTileContentProvider(Size _minIconSize, bool _fitImage) :minIconSize(_minIconSize) ,fitImage(_fitImage) { } ListViewTileContentProvider::~ListViewTileContentProvider() { } compositions::IGuiAxis* ListViewTileContentProvider::CreatePreferredAxis() { return new GuiDefaultAxis; } GuiListControl::IItemArranger* ListViewTileContentProvider::CreatePreferredArranger() { return new FixedSizeMultiColumnItemArranger; } ListViewItemStyleProvider::IListViewItemContent* ListViewTileContentProvider::CreateItemContent(const FontProperties& font) { return new ItemContent(minIconSize, fitImage, font); } void ListViewTileContentProvider::AttachListControl(GuiListControl* value) { } void ListViewTileContentProvider::DetachListControl() { } /*********************************************************************** ListViewInformationContentProvider ***********************************************************************/ ListViewInformationContentProvider::ItemContent::ItemContent(Size minIconSize, bool fitImage, const FontProperties& font) :contentComposition(0) ,baselineFont(font) { contentComposition=new GuiBoundsComposition; contentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); { bottomLine=GuiSolidBackgroundElement::Create(); bottomLineComposition=new GuiBoundsComposition; bottomLineComposition->SetOwnedElement(bottomLine); bottomLineComposition->SetAlignmentToParent(Margin(8, -1, 8, 0)); bottomLineComposition->SetPreferredMinSize(Size(0, 1)); } GuiTableComposition* table=new GuiTableComposition; contentComposition->AddChild(table); table->SetRowsAndColumns(3, 3); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(2, GuiCellOption::MinSizeOption()); table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetCellPadding(4); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(1, 0, 1, 1); cell->SetPreferredMinSize(minIconSize); if (!fitImage) { cell->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } image=GuiImageFrameElement::Create(); image->SetStretch(true); cell->SetOwnedElement(image); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 3, 1); FontProperties textFont=font; textFont.size=(vint)(textFont.size*1.2); text=GuiSolidLabelElement::Create(); text->SetFont(textFont); text->SetEllipse(true); cell->SetOwnedElement(text); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 2, 3, 1); cell->SetPreferredMinSize(Size(224, 0)); textTable=new GuiTableComposition; textTable->SetCellPadding(4); textTable->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); textTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(textTable); } } ListViewInformationContentProvider::ItemContent::~ItemContent() { } compositions::GuiBoundsComposition* ListViewInformationContentProvider::ItemContent::GetContentComposition() { return contentComposition; } compositions::GuiBoundsComposition* ListViewInformationContentProvider::ItemContent::GetBackgroundDecorator() { return bottomLineComposition; } void ListViewInformationContentProvider::ItemContent::Install(GuiListViewBase::IStyleProvider* styleProvider, ListViewItemStyleProvider::IListViewItemView* view, vint itemIndex) { Ptr imageData = view->GetLargeImage(itemIndex); if (imageData) { image->SetImage(imageData->GetImage(), imageData->GetFrameIndex()); } else { image->SetImage(0); } text->SetText(view->GetText(itemIndex)); text->SetColor(styleProvider->GetPrimaryTextColor()); bottomLine->SetColor(styleProvider->GetItemSeparatorColor()); for (vint i = 0; i < dataTexts.Count(); i++) { GuiCellComposition* cell = textTable->GetSitedCell(i, 0); textTable->RemoveChild(cell); delete cell; } vint dataColumnCount = view->GetDataColumnCount(); dataTexts.Resize(dataColumnCount); textTable->SetRowsAndColumns(dataColumnCount + 2, 1); textTable->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); for (vint i = 0; i < dataColumnCount; i++) { textTable->SetRowOption(i + 1, GuiCellOption::MinSizeOption()); } textTable->SetRowOption(dataColumnCount + 1, GuiCellOption::PercentageOption(0.5)); textTable->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); for (vint i = 0; i < dataColumnCount; i++) { GuiCellComposition* cell = new GuiCellComposition; textTable->AddChild(cell); cell->SetSite(i + 1, 0, 1, 1); GuiTableComposition* dataTable = new GuiTableComposition; dataTable->SetRowsAndColumns(1, 2); dataTable->SetRowOption(0, GuiCellOption::MinSizeOption()); dataTable->SetColumnOption(0, GuiCellOption::MinSizeOption()); dataTable->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); dataTable->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); dataTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(dataTable); { GuiCellComposition* cell = new GuiCellComposition; dataTable->AddChild(cell); cell->SetSite(0, 0, 1, 1); GuiSolidLabelElement* textColumn = GuiSolidLabelElement::Create(); textColumn->SetFont(baselineFont); textColumn->SetText(view->GetColumnText(view->GetDataColumn(i) + 1) + L": "); textColumn->SetColor(styleProvider->GetSecondaryTextColor()); cell->SetOwnedElement(textColumn); } { GuiCellComposition* cell = new GuiCellComposition; dataTable->AddChild(cell); cell->SetSite(0, 1, 1, 1); GuiSolidLabelElement* textData = GuiSolidLabelElement::Create(); textData->SetFont(baselineFont); textData->SetEllipse(true); textData->SetText(view->GetSubItem(itemIndex, view->GetDataColumn(i))); textData->SetColor(styleProvider->GetPrimaryTextColor()); cell->SetOwnedElement(textData); } } } void ListViewInformationContentProvider::ItemContent::Uninstall() { } ListViewInformationContentProvider::ListViewInformationContentProvider(Size _minIconSize, bool _fitImage) :minIconSize(_minIconSize) ,fitImage(_fitImage) { } ListViewInformationContentProvider::~ListViewInformationContentProvider() { } compositions::IGuiAxis* ListViewInformationContentProvider::CreatePreferredAxis() { return new GuiDefaultAxis; } GuiListControl::IItemArranger* ListViewInformationContentProvider::CreatePreferredArranger() { return new FixedHeightItemArranger; } ListViewItemStyleProvider::IListViewItemContent* ListViewInformationContentProvider::CreateItemContent(const FontProperties& font) { return new ItemContent(minIconSize, fitImage, font); } void ListViewInformationContentProvider::AttachListControl(GuiListControl* value) { } void ListViewInformationContentProvider::DetachListControl() { } /*********************************************************************** ListViewColumnItemArranger::ColumnItemViewCallback ***********************************************************************/ ListViewColumnItemArranger::ColumnItemViewCallback::ColumnItemViewCallback(ListViewColumnItemArranger* _arranger) :arranger(_arranger) { } ListViewColumnItemArranger::ColumnItemViewCallback::~ColumnItemViewCallback() { } void ListViewColumnItemArranger::ColumnItemViewCallback::OnColumnChanged() { arranger->RebuildColumns(); } /*********************************************************************** ListViewColumnItemArranger ***********************************************************************/ const wchar_t* const ListViewColumnItemArranger::IColumnItemView::Identifier = L"vl::presentation::controls::list::ListViewColumnItemArranger::IColumnItemView"; void ListViewColumnItemArranger::ColumnClicked(vint index, compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { GuiItemEventArgs args(listView->ColumnClicked.GetAssociatedComposition()); args.itemIndex=index; listView->ColumnClicked.Execute(args); } void ListViewColumnItemArranger::ColumnBoundsChanged(vint index, compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { GuiBoundsComposition* buttonBounds=columnHeaderButtons[index]->GetBoundsComposition(); vint size=buttonBounds->GetBounds().Width(); if(size>columnItemView->GetColumnSize(index)) { columnItemView->SetColumnSize(index, size); } } void ListViewColumnItemArranger::ColumnHeaderSplitterLeftButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(listView->GetVisuallyEnabled()) { arguments.handled=true; splitterDragging=true; splitterLatestX=arguments.x; } } void ListViewColumnItemArranger::ColumnHeaderSplitterLeftButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(listView->GetVisuallyEnabled()) { arguments.handled=true; splitterDragging=false; splitterLatestX=0; } } void ListViewColumnItemArranger::ColumnHeaderSplitterMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(splitterDragging) { vint offset=arguments.x-splitterLatestX; vint index=columnHeaderSplitters.IndexOf(dynamic_cast(sender)); if(index!=-1) { GuiBoundsComposition* buttonBounds=columnHeaderButtons[index]->GetBoundsComposition(); Rect bounds=buttonBounds->GetBounds(); Rect newBounds(bounds.LeftTop(), Size(bounds.Width()+offset, bounds.Height())); buttonBounds->SetBounds(newBounds); vint finalSize=buttonBounds->GetBounds().Width(); columnItemView->SetColumnSize(index, finalSize); } } } void ListViewColumnItemArranger::RearrangeItemBounds() { FixedHeightItemArranger::RearrangeItemBounds(); vint count=columnHeaders->GetParent()->Children().Count(); columnHeaders->GetParent()->MoveChild(columnHeaders, count-1); columnHeaders->SetBounds(Rect(Point(-viewBounds.Left(), 0), Size(0, 0))); } vint ListViewColumnItemArranger::GetWidth() { vint width=columnHeaders->GetBounds().Width()-SplitterWidth; if(widthGetBounds().Height(); } Size ListViewColumnItemArranger::OnCalculateTotalSize() { Size size=FixedHeightItemArranger::OnCalculateTotalSize(); size.x+=SplitterWidth; return size; } void ListViewColumnItemArranger::DeleteColumnButtons() { for(vint i=columnHeaders->GetStackItems().Count()-1;i>=0;i--) { GuiStackItemComposition* item=columnHeaders->GetStackItems().Get(i); columnHeaders->RemoveChild(item); GuiControl* button=item->Children().Get(0)->GetAssociatedControl(); if(button) { item->RemoveChild(button->GetBoundsComposition()); delete button; } delete item; } columnHeaderButtons.Clear(); columnHeaderSplitters.Clear(); } void ListViewColumnItemArranger::RebuildColumns() { if(columnItemView && columnHeaderButtons.Count()==columnItemView->GetColumnCount()) { for(vint i=0;iGetColumnCount();i++) { GuiListViewColumnHeader* button=columnHeaderButtons[i]; button->SetText(columnItemView->GetColumnText(i)); button->SetSubMenu(columnItemView->GetDropdownPopup(i), false); button->SetColumnSortingState(columnItemView->GetSortingState(i)); button->GetBoundsComposition()->SetBounds(Rect(Point(0, 0), Size(columnItemView->GetColumnSize(i), 0))); } } else { DeleteColumnButtons(); if(columnItemView) { for(vint i=0;iGetColumnCount();i++) { GuiBoundsComposition* splitterComposition=new GuiBoundsComposition; splitterComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); splitterComposition->SetAssociatedCursor(GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::SizeWE)); splitterComposition->SetAlignmentToParent(Margin(0, 0, -1, 0)); splitterComposition->SetPreferredMinSize(Size(SplitterWidth, 0)); columnHeaderSplitters.Add(splitterComposition); splitterComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &ListViewColumnItemArranger::ColumnHeaderSplitterLeftButtonDown); splitterComposition->GetEventReceiver()->leftButtonUp.AttachMethod(this, &ListViewColumnItemArranger::ColumnHeaderSplitterLeftButtonUp); splitterComposition->GetEventReceiver()->mouseMove.AttachMethod(this, &ListViewColumnItemArranger::ColumnHeaderSplitterMouseMove); } for(vint i=0;iGetColumnCount();i++) { GuiListViewColumnHeader* button=new GuiListViewColumnHeader(styleProvider->CreateColumnStyle()); button->SetText(columnItemView->GetColumnText(i)); button->SetSubMenu(columnItemView->GetDropdownPopup(i), false); button->SetColumnSortingState(columnItemView->GetSortingState(i)); button->GetBoundsComposition()->SetBounds(Rect(Point(0, 0), Size(columnItemView->GetColumnSize(i), 0))); button->Clicked.AttachLambda(Curry(Func(this, &ListViewColumnItemArranger::ColumnClicked))(i)); button->GetBoundsComposition()->BoundsChanged.AttachLambda(Curry(Func(this, &ListViewColumnItemArranger::ColumnBoundsChanged))(i)); columnHeaderButtons.Add(button); if(i>0) { button->GetContainerComposition()->AddChild(columnHeaderSplitters[i-1]); } GuiStackItemComposition* item=new GuiStackItemComposition; item->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); item->AddChild(button->GetBoundsComposition()); columnHeaders->AddChild(item); } if(columnItemView->GetColumnCount()>0) { GuiBoundsComposition* splitterComposition=columnHeaderSplitters[columnItemView->GetColumnCount()-1]; GuiStackItemComposition* item=new GuiStackItemComposition; item->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); item->AddChild(splitterComposition); columnHeaders->AddChild(item); } } } callback->OnTotalSizeChanged(); } ListViewColumnItemArranger::ListViewColumnItemArranger() :listView(0) ,styleProvider(0) ,columnItemView(0) ,splitterDragging(false) ,splitterLatestX(0) { columnHeaders=new GuiStackComposition; columnHeaders->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); columnItemViewCallback=new ColumnItemViewCallback(this); } ListViewColumnItemArranger::~ListViewColumnItemArranger() { if(!columnHeaders->GetParent()) { DeleteColumnButtons(); delete columnHeaders; } } void ListViewColumnItemArranger::AttachListControl(GuiListControl* value) { FixedHeightItemArranger::AttachListControl(value); listView=dynamic_cast(value); if(listView) { styleProvider=listView->GetListViewStyleProvider(); listView->GetContainerComposition()->AddChild(columnHeaders); columnItemView=dynamic_cast(listView->GetItemProvider()->RequestView(IColumnItemView::Identifier)); if(columnItemView) { columnItemView->AttachCallback(columnItemViewCallback.Obj()); RebuildColumns(); } } } void ListViewColumnItemArranger::DetachListControl() { if(listView) { if(columnItemView) { columnItemView->DetachCallback(columnItemViewCallback.Obj()); listView->GetItemProvider()->ReleaseView(columnItemView); columnItemView=0; } listView->GetContainerComposition()->RemoveChild(columnHeaders); styleProvider=0; listView=0; } FixedHeightItemArranger::DetachListControl(); } /*********************************************************************** ListViewDetailContentProvider ***********************************************************************/ ListViewDetailContentProvider::ItemContent::ItemContent(Size minIconSize, bool fitImage, const FontProperties& font, GuiListControl::IItemProvider* _itemProvider) :contentComposition(0) ,itemProvider(_itemProvider) { columnItemView=dynamic_cast(itemProvider->RequestView(ListViewColumnItemArranger::IColumnItemView::Identifier)); contentComposition=new GuiBoundsComposition; contentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); textTable=new GuiTableComposition; textTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); textTable->SetRowsAndColumns(1, 1); textTable->SetRowOption(0, GuiCellOption::MinSizeOption()); textTable->SetColumnOption(0, GuiCellOption::AbsoluteOption(0)); contentComposition->AddChild(textTable); { GuiCellComposition* cell=new GuiCellComposition; textTable->AddChild(cell); cell->SetSite(0, 0, 1, 1); GuiTableComposition* table=new GuiTableComposition; cell->AddChild(table); table->SetRowsAndColumns(3, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetCellPadding(2); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(1, 0, 1, 1); cell->SetPreferredMinSize(minIconSize); if (!fitImage) { cell->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } image=GuiImageFrameElement::Create(); image->SetStretch(true); cell->SetOwnedElement(image); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 3, 1); cell->SetMargin(Margin(0, 0, 8, 0)); text=GuiSolidLabelElement::Create(); text->SetAlignments(Alignment::Left, Alignment::Center); text->SetFont(font); text->SetEllipse(true); cell->SetOwnedElement(text); } } } ListViewDetailContentProvider::ItemContent::~ItemContent() { if(columnItemView) { itemProvider->ReleaseView(columnItemView); } } compositions::GuiBoundsComposition* ListViewDetailContentProvider::ItemContent::GetContentComposition() { return contentComposition; } compositions::GuiBoundsComposition* ListViewDetailContentProvider::ItemContent::GetBackgroundDecorator() { return 0; } void ListViewDetailContentProvider::ItemContent::UpdateSubItemSize() { vint columnCount=columnItemView->GetColumnCount(); if(columnCount>textTable->GetColumns()) { columnCount=textTable->GetColumns(); } for(vint i=0;iSetColumnOption(i, GuiCellOption::AbsoluteOption(columnItemView->GetColumnSize(i))); } textTable->UpdateCellBounds(); } void ListViewDetailContentProvider::ItemContent::Install(GuiListViewBase::IStyleProvider* styleProvider, ListViewItemStyleProvider::IListViewItemView* view, vint itemIndex) { for(vint i=1;iGetColumns();i++) { GuiCellComposition* cell=textTable->GetSitedCell(0, i); textTable->RemoveChild(cell); delete cell; } Ptr imageData=view->GetSmallImage(itemIndex); if(imageData) { image->SetImage(imageData->GetImage(), imageData->GetFrameIndex()); } else { image->SetImage(0); } text->SetText(view->GetText(itemIndex)); text->SetColor(styleProvider->GetPrimaryTextColor()); vint columnCount=columnItemView->GetColumnCount(); textTable->SetRowsAndColumns(1, columnCount); for(vint i=1;iAddChild(cell); cell->SetSite(0, i, 1, 1); cell->SetMargin(Margin(8, 0, 8, 0)); GuiSolidLabelElement* subText=GuiSolidLabelElement::Create(); subText->SetAlignments(Alignment::Left, Alignment::Center); subText->SetFont(text->GetFont()); subText->SetEllipse(true); subText->SetText(view->GetSubItem(itemIndex, i-1)); subText->SetColor(styleProvider->GetSecondaryTextColor()); cell->SetOwnedElement(subText); } UpdateSubItemSize(); } void ListViewDetailContentProvider::ItemContent::Uninstall() { } void ListViewDetailContentProvider::OnColumnChanged() { vint count=listViewItemStyleProvider->GetCreatedItemStyles().Count(); for(vint i=0;iGetCreatedItemStyles().Get(i); ItemContent* itemContent=listViewItemStyleProvider->GetItemContent(itemStyleController); if(itemContent) { itemContent->UpdateSubItemSize(); } } } ListViewDetailContentProvider::ListViewDetailContentProvider(Size _minIconSize, bool _fitImage) :minIconSize(_minIconSize) ,fitImage(_fitImage) ,itemProvider(0) ,columnItemView(0) ,listViewItemStyleProvider(0) { } ListViewDetailContentProvider::~ListViewDetailContentProvider() { } compositions::IGuiAxis* ListViewDetailContentProvider::CreatePreferredAxis() { return new GuiDefaultAxis; } GuiListControl::IItemArranger* ListViewDetailContentProvider::CreatePreferredArranger() { return new ListViewColumnItemArranger; } ListViewItemStyleProvider::IListViewItemContent* ListViewDetailContentProvider::CreateItemContent(const FontProperties& font) { return new ItemContent(minIconSize, fitImage, font, itemProvider); } void ListViewDetailContentProvider::AttachListControl(GuiListControl* value) { listViewItemStyleProvider=dynamic_cast(value->GetStyleProvider()); itemProvider=value->GetItemProvider(); columnItemView=dynamic_cast(itemProvider->RequestView(ListViewColumnItemArranger::IColumnItemView::Identifier)); if(columnItemView) { columnItemView->AttachCallback(this); } } void ListViewDetailContentProvider::DetachListControl() { if(columnItemView) { columnItemView->DetachCallback(this); itemProvider->ReleaseView(columnItemView); } itemProvider=0; listViewItemStyleProvider=0; } /*********************************************************************** ListViewSubItems ***********************************************************************/ void ListViewSubItems::NotifyUpdateInternal(vint start, vint count, vint newCount) { owner->NotifyUpdate(); } /*********************************************************************** ListViewItem ***********************************************************************/ void ListViewItem::NotifyUpdate() { if (owner) { vint index = owner->IndexOf(this); owner->NotifyUpdateInternal(index, 1, 1); } } ListViewItem::ListViewItem() :owner(0) { subItems.owner = this; } ListViewSubItems& ListViewItem::GetSubItems() { return subItems; } Ptr ListViewItem::GetSmallImage() { return smallImage; } void ListViewItem::SetSmallImage(Ptr value) { smallImage = value; NotifyUpdate(); } Ptr ListViewItem::GetLargeImage() { return largeImage; } void ListViewItem::SetLargeImage(Ptr value) { largeImage = value; NotifyUpdate(); } const WString& ListViewItem::GetText() { return text; } void ListViewItem::SetText(const WString& value) { text = value; NotifyUpdate(); } description::Value ListViewItem::GetTag() { return tag; } void ListViewItem::SetTag(const description::Value& value) { tag = value; NotifyUpdate(); } /*********************************************************************** ListViewColumn ***********************************************************************/ void ListViewColumn::NotifyUpdate() { if (owner) { vint index = owner->IndexOf(this); owner->NotifyUpdate(index, 1); } } ListViewColumn::ListViewColumn(const WString& _text, vint _size) :owner(0) ,text(_text) ,size(_size) ,dropdownPopup(0) ,sortingState(GuiListViewColumnHeader::NotSorted) { } const WString& ListViewColumn::GetText() { return text; } void ListViewColumn::SetText(const WString& value) { text = value; NotifyUpdate(); } const WString& ListViewColumn::GetTextProperty() { return textProperty; } void ListViewColumn::SetTextProperty(const WString& value) { textProperty = value; NotifyUpdate(); } vint ListViewColumn::GetSize() { return size; } void ListViewColumn::SetSize(vint value) { size = value; NotifyUpdate(); } GuiMenu* ListViewColumn::GetDropdownPopup() { return dropdownPopup; } void ListViewColumn::SetDropdownPopup(GuiMenu* value) { dropdownPopup = value; NotifyUpdate(); } GuiListViewColumnHeader::ColumnSortingState ListViewColumn::GetSortingState() { return sortingState; } void ListViewColumn::SetSortingState(GuiListViewColumnHeader::ColumnSortingState value) { sortingState = value; NotifyUpdate(); } /*********************************************************************** ListViewDataColumns ***********************************************************************/ void ListViewDataColumns::NotifyUpdateInternal(vint start, vint count, vint newCount) { itemProvider->NotifyAllItemsUpdate(); } ListViewDataColumns::ListViewDataColumns(IListViewItemProvider* _itemProvider) :itemProvider(_itemProvider) { } ListViewDataColumns::~ListViewDataColumns() { } /*********************************************************************** ListViewColumns ***********************************************************************/ void ListViewColumns::AfterInsert(vint index, const Ptr& value) { ItemsBase>::AfterInsert(index, value); value->owner = this; } void ListViewColumns::BeforeRemove(vint index, const Ptr& value) { value->owner = 0; ItemsBase>::BeforeRemove(index, value); } void ListViewColumns::NotifyUpdateInternal(vint start, vint count, vint newCount) { itemProvider->NotifyAllColumnsUpdate(); itemProvider->NotifyAllItemsUpdate(); } ListViewColumns::ListViewColumns(IListViewItemProvider* _itemProvider) :itemProvider(_itemProvider) { } ListViewColumns::~ListViewColumns() { } /*********************************************************************** ListViewItemProvider ***********************************************************************/ void ListViewItemProvider::AfterInsert(vint index, const Ptr& value) { ListProvider>::AfterInsert(index, value); value->owner = this; } void ListViewItemProvider::BeforeRemove(vint index, const Ptr& value) { value->owner = 0; ListProvider>::AfterInsert(index, value); } void ListViewItemProvider::NotifyAllItemsUpdate() { NotifyUpdate(0, Count()); } void ListViewItemProvider::NotifyAllColumnsUpdate() { for (vint i = 0; i < columnItemViewCallbacks.Count(); i++) { columnItemViewCallbacks[i]->OnColumnChanged(); } } bool ListViewItemProvider::ContainsPrimaryText(vint itemIndex) { return true; } WString ListViewItemProvider::GetPrimaryTextViewText(vint itemIndex) { return Get(itemIndex)->text; } Ptr ListViewItemProvider::GetSmallImage(vint itemIndex) { return Get(itemIndex)->smallImage; } Ptr ListViewItemProvider::GetLargeImage(vint itemIndex) { return Get(itemIndex)->largeImage; } WString ListViewItemProvider::GetText(vint itemIndex) { return Get(itemIndex)->text; } WString ListViewItemProvider::GetSubItem(vint itemIndex, vint index) { Ptr item=Get(itemIndex); if(index<0 || index>=item->GetSubItems().Count()) { return L""; } else { return item->GetSubItems()[index]; } } vint ListViewItemProvider::GetDataColumnCount() { return dataColumns.Count(); } vint ListViewItemProvider::GetDataColumn(vint index) { return dataColumns[index]; } bool ListViewItemProvider::AttachCallback(ListViewColumnItemArranger::IColumnItemViewCallback* value) { if(columnItemViewCallbacks.Contains(value)) { return false; } else { columnItemViewCallbacks.Add(value); return true; } } bool ListViewItemProvider::DetachCallback(ListViewColumnItemArranger::IColumnItemViewCallback* value) { vint index=columnItemViewCallbacks.IndexOf(value); if(index==-1) { return false; } else { columnItemViewCallbacks.Remove(value); return true; } } vint ListViewItemProvider::GetColumnCount() { return columns.Count(); } WString ListViewItemProvider::GetColumnText(vint index) { if(index<0 || index>=columns.Count()) { return L""; } else { return columns[index]->GetText(); } } vint ListViewItemProvider::GetColumnSize(vint index) { if(index<0 || index>=columns.Count()) { return 0; } else { return columns[index]->GetSize(); } } void ListViewItemProvider::SetColumnSize(vint index, vint value) { if(index>=0 && indexSetSize(value); } } GuiMenu* ListViewItemProvider::GetDropdownPopup(vint index) { if(index<0 || index>=columns.Count()) { return 0; } else { return columns[index]->GetDropdownPopup(); } } GuiListViewColumnHeader::ColumnSortingState ListViewItemProvider::GetSortingState(vint index) { if(index<0 || index>=columns.Count()) { return GuiListViewColumnHeader::NotSorted; } else { return columns[index]->GetSortingState(); } } description::Value ListViewItemProvider::GetBindingValue(vint itemIndex) { return Value::From(Get(itemIndex)); } ListViewItemProvider::ListViewItemProvider() :columns(this) , dataColumns(this) { } ListViewItemProvider::~ListViewItemProvider() { } IDescriptable* ListViewItemProvider::RequestView(const WString& identifier) { if(identifier==ListViewItemStyleProvider::IListViewItemView::Identifier) { return (ListViewItemStyleProvider::IListViewItemView*)this; } else if(identifier==ListViewColumnItemArranger::IColumnItemView::Identifier) { return (ListViewColumnItemArranger::IColumnItemView*)this; } else if(identifier==GuiListControl::IItemPrimaryTextView::Identifier) { return (GuiListControl::IItemPrimaryTextView*)this; } else if(identifier==GuiListControl::IItemBindingView::Identifier) { return (GuiListControl::IItemBindingView*)this; } else { return 0; } } void ListViewItemProvider::ReleaseView(IDescriptable* view) { } ListViewDataColumns& ListViewItemProvider::GetDataColumns() { return dataColumns; } ListViewColumns& ListViewItemProvider::GetColumns() { return columns; } } /*********************************************************************** GuiListView ***********************************************************************/ GuiVirtualListView::GuiVirtualListView(IStyleProvider* _styleProvider, GuiListControl::IItemProvider* _itemProvider) :GuiListViewBase(_styleProvider, _itemProvider) { ChangeItemStyle(new list::ListViewBigIconContentProvider); } GuiVirtualListView::~GuiVirtualListView() { } bool GuiVirtualListView::ChangeItemStyle(Ptr contentProvider) { SetStyleProvider(0); SetArranger(0); SetAxis(contentProvider->CreatePreferredAxis()); SetStyleProvider(new list::ListViewItemStyleProvider(contentProvider)); SetArranger(contentProvider->CreatePreferredArranger()); return true; } /*********************************************************************** GuiListView ***********************************************************************/ GuiListView::GuiListView(IStyleProvider* _styleProvider) :GuiVirtualListView(_styleProvider, new list::ListViewItemProvider) { items=dynamic_cast(itemProvider.Obj()); } GuiListView::~GuiListView() { } list::ListViewItemProvider& GuiListView::GetItems() { return *items; } list::ListViewDataColumns& GuiListView::GetDataColumns() { return items->GetDataColumns(); } list::ListViewColumns& GuiListView::GetColumns() { return items->GetColumns(); } Ptr GuiListView::GetSelectedItem() { vint index = GetSelectedItemIndex(); if (index == -1) return 0; return items->Get(index); } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUITEXTLISTCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace elements; using namespace compositions; using namespace reflection::description; namespace list { /*********************************************************************** TextItemStyleProvider::TextItemStyleController ***********************************************************************/ void TextItemStyleProvider::TextItemStyleController::OnBulletSelectedChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { textItemStyleProvider->OnStyleCheckedChanged(this); } TextItemStyleProvider::TextItemStyleController::TextItemStyleController(TextItemStyleProvider* provider) :ItemStyleControllerBase(provider, 0) ,backgroundButton(0) ,bulletButton(0) ,textElement(0) ,textItemStyleProvider(provider) { auto styleProvider = textItemStyleProvider->listControl->GetTextListStyleProvider(); backgroundButton=new GuiSelectableButton(styleProvider->CreateItemBackground()); backgroundButton->SetAutoSelection(false); textElement=GuiSolidLabelElement::Create(); textElement->SetAlignments(Alignment::Left, Alignment::Center); textElement->SetFont(backgroundButton->GetFont()); textElement->SetColor(styleProvider->GetTextColor()); GuiBoundsComposition* textComposition=new GuiBoundsComposition; textComposition->SetOwnedElement(textElement); textComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); GuiSelectableButton::IStyleController* bulletStyleController=textItemStyleProvider->bulletFactory->CreateBulletStyleController(); if(bulletStyleController) { bulletButton=new GuiSelectableButton(bulletStyleController); bulletButton->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); bulletButton->SelectedChanged.AttachMethod(this, &TextItemStyleController::OnBulletSelectedChanged); GuiTableComposition* table=new GuiTableComposition; backgroundButton->GetContainerComposition()->AddChild(table); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); table->SetRowsAndColumns(1, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::MinSizeOption()); table->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 0, 1, 1); cell->AddChild(bulletButton->GetBoundsComposition()); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 1, 1); cell->AddChild(textComposition); textComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); } } else { backgroundButton->GetContainerComposition()->AddChild(textComposition); textComposition->SetAlignmentToParent(Margin(5, 0, 0, 0)); } Initialize(backgroundButton->GetBoundsComposition(), backgroundButton); } TextItemStyleProvider::TextItemStyleController::~TextItemStyleController() { } bool TextItemStyleProvider::TextItemStyleController::GetSelected() { return backgroundButton->GetSelected(); } void TextItemStyleProvider::TextItemStyleController::SetSelected(bool value) { backgroundButton->SetSelected(value); } bool TextItemStyleProvider::TextItemStyleController::GetChecked() { return bulletButton?bulletButton->GetSelected():false; } void TextItemStyleProvider::TextItemStyleController::SetChecked(bool value) { if(bulletButton) bulletButton->SetSelected(value); } const WString& TextItemStyleProvider::TextItemStyleController::GetText() { return textElement->GetText(); } void TextItemStyleProvider::TextItemStyleController::SetText(const WString& value) { textElement->SetText(value); } /*********************************************************************** TextItemStyleProvider ***********************************************************************/ const wchar_t* const TextItemStyleProvider::ITextItemView::Identifier = L"vl::presentation::controls::list::TextItemStyleProvider::ITextItemView"; void TextItemStyleProvider::OnStyleCheckedChanged(TextItemStyleController* style) { vint index=listControl->GetArranger()->GetVisibleIndex(style); if(index!=-1) { textItemView->SetCheckedSilently(index, style->GetChecked()); GuiItemEventArgs arguments(style->GetBoundsComposition()); arguments.itemIndex=index; listControl->ItemChecked.Execute(arguments); } } TextItemStyleProvider::TextItemStyleProvider(IBulletFactory* _bulletFactory) :bulletFactory(_bulletFactory) ,textItemView(0) ,listControl(0) { } TextItemStyleProvider::~TextItemStyleProvider() { } void TextItemStyleProvider::AttachListControl(GuiListControl* value) { listControl=dynamic_cast(value); textItemView=dynamic_cast(value->GetItemProvider()->RequestView(ITextItemView::Identifier)); } void TextItemStyleProvider::DetachListControl() { listControl->GetItemProvider()->ReleaseView(textItemView); textItemView=0; listControl=0; } vint TextItemStyleProvider::GetItemStyleId(vint itemIndex) { return 0; } GuiListControl::IItemStyleController* TextItemStyleProvider::CreateItemStyle(vint styleId) { return new TextItemStyleController(this); } void TextItemStyleProvider::DestroyItemStyle(GuiListControl::IItemStyleController* style) { delete dynamic_cast(style); } void TextItemStyleProvider::Install(GuiListControl::IItemStyleController* style, vint itemIndex) { TextItemStyleController* textStyle=dynamic_cast(style); textStyle->SetText(textItemView->GetText(itemIndex)); textStyle->SetChecked(textItemView->GetChecked(itemIndex)); } void TextItemStyleProvider::SetStyleIndex(GuiListControl::IItemStyleController* style, vint value) { } void TextItemStyleProvider::SetStyleSelected(GuiListControl::IItemStyleController* style, bool value) { TextItemStyleController* textStyle=dynamic_cast(style); textStyle->SetSelected(value); } /*********************************************************************** TextItem ***********************************************************************/ TextItem::TextItem() :owner(0) , checked(false) { } TextItem::TextItem(const WString& _text, bool _checked) :owner(0) , text(_text) , checked(_checked) { } TextItem::~TextItem() { } bool TextItem::operator==(const TextItem& value)const { return text==value.text; } bool TextItem::operator!=(const TextItem& value)const { return text!=value.text; } const WString& TextItem::GetText() { return text; } void TextItem::SetText(const WString& value) { text = value; if (owner) { vint index = owner->IndexOf(this); owner->InvokeOnItemModified(index, 1, 1); } } bool TextItem::GetChecked() { return checked; } void TextItem::SetChecked(bool value) { checked = value; if (owner) { vint index = owner->IndexOf(this); owner->InvokeOnItemModified(index, 1, 1); GuiItemEventArgs arguments; arguments.itemIndex=index; owner->listControl->ItemChecked.Execute(arguments); } } /*********************************************************************** TextItemProvider ***********************************************************************/ void TextItemProvider::AfterInsert(vint item, const Ptr& value) { ListProvider>::AfterInsert(item, value); value->owner = this; } void TextItemProvider::BeforeRemove(vint item, const Ptr& value) { value->owner = 0; ListProvider>::BeforeRemove(item, value); } bool TextItemProvider::ContainsPrimaryText(vint itemIndex) { return true; } WString TextItemProvider::GetPrimaryTextViewText(vint itemIndex) { return Get(itemIndex)->GetText(); } WString TextItemProvider::GetText(vint itemIndex) { return Get(itemIndex)->GetText(); } bool TextItemProvider::GetChecked(vint itemIndex) { return Get(itemIndex)->GetChecked(); } void TextItemProvider::SetCheckedSilently(vint itemIndex, bool value) { items[itemIndex]->checked=value; } description::Value TextItemProvider::GetBindingValue(vint itemIndex) { return Value::From(Get(itemIndex)); } TextItemProvider::TextItemProvider() :listControl(0) { } TextItemProvider::~TextItemProvider() { } IDescriptable* TextItemProvider::RequestView(const WString& identifier) { if(identifier==TextItemStyleProvider::ITextItemView::Identifier) { return (TextItemStyleProvider::ITextItemView*)this; } else if(identifier==GuiListControl::IItemPrimaryTextView::Identifier) { return (GuiListControl::IItemPrimaryTextView*)this; } else if(identifier==GuiListControl::IItemBindingView::Identifier) { return (GuiListControl::IItemBindingView*)this; } else { return 0; } } void TextItemProvider::ReleaseView(IDescriptable* view) { } } /*********************************************************************** GuiTextList ***********************************************************************/ GuiVirtualTextList::GuiVirtualTextList(IStyleProvider* _styleProvider, list::TextItemStyleProvider::IBulletFactory* _bulletFactory, GuiListControl::IItemProvider* _itemProvider) :GuiSelectableListControl(_styleProvider, _itemProvider) { ItemChecked.SetAssociatedComposition(boundsComposition); styleProvider = dynamic_cast(styleController->GetStyleProvider()); ChangeItemStyle(_bulletFactory); SetArranger(new list::FixedHeightItemArranger); } GuiVirtualTextList::~GuiVirtualTextList() { } GuiVirtualTextList::IStyleProvider* GuiVirtualTextList::GetTextListStyleProvider() { return styleProvider; } Ptr GuiVirtualTextList::ChangeItemStyle(list::TextItemStyleProvider::IBulletFactory* bulletFactory) { if(bulletFactory) { return SetStyleProvider(new list::TextItemStyleProvider(bulletFactory)); } else { return 0; } } /*********************************************************************** GuiTextList ***********************************************************************/ GuiTextList::GuiTextList(IStyleProvider* _styleProvider, list::TextItemStyleProvider::IBulletFactory* _bulletFactory) :GuiVirtualTextList(_styleProvider, _bulletFactory, new list::TextItemProvider) { items=dynamic_cast(itemProvider.Obj()); items->listControl=this; } GuiTextList::~GuiTextList() { } list::TextItemProvider& GuiTextList::GetItems() { return *items; } Ptr GuiTextList::GetSelectedItem() { vint index = GetSelectedItemIndex(); if (index == -1) return 0; return items->Get(index); } } } } /*********************************************************************** CONTROLS\LISTCONTROLPACKAGE\GUITREEVIEWCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace compositions; using namespace reflection::description; namespace tree { const wchar_t* const INodeItemView::Identifier = L"vl::presentation::controls::tree::INodeItemView"; const wchar_t* const INodeItemPrimaryTextView::Identifier = L"vl::presentation::cotnrols::tree::INodeItemPrimaryTextView"; const wchar_t* const INodeItemBindingView::Identifier = L"vl::presentation::cotnrols::tree::INodeItemBindingView"; /*********************************************************************** NodeItemProvider ***********************************************************************/ INodeProvider* NodeItemProvider::GetNodeByOffset(INodeProvider* provider, vint offset) { if(offset==0) return provider; INodeProvider* result=0; if(provider->GetExpanding() && offset>0) { offset-=1; vint count=provider->GetChildCount(); for(vint i=0;(!result && iGetChild(i); vint visibleCount=child->CalculateTotalVisibleNodes(); if(offsetGetExpanding()) { for(vint i=0;iGetChild(start+i); offset+=child->CalculateTotalVisibleNodes(); child->Release(); } } offsetBeforeChildModifieds.Set(parentNode, offset); } void NodeItemProvider::OnAfterItemModified(INodeProvider* parentNode, vint start, vint count, vint newCount) { vint offsetBeforeChildModified = 0; { vint index = offsetBeforeChildModifieds.Keys().IndexOf(parentNode); if (index != -1) { offsetBeforeChildModified = offsetBeforeChildModifieds.Values().Get(index); offsetBeforeChildModifieds.Remove(parentNode); } } vint base=CalculateNodeVisibilityIndexInternal(parentNode); if(base!=-2 && parentNode->GetExpanding()) { vint offset=0; vint firstChildStart=-1; for(vint i=0;iGetChild(start+i); if(i==0) { firstChildStart=CalculateNodeVisibilityIndexInternal(child); } offset+=child->CalculateTotalVisibleNodes(); child->Release(); } if(firstChildStart==-1) { vint childCount=parentNode->GetChildCount(); if(childCount==0) { firstChildStart=base+1; } else if(startGetChild(start); firstChildStart=CalculateNodeVisibilityIndexInternal(child); child->Release(); } else { INodeProvider* child=parentNode->GetChild(start-1); firstChildStart=CalculateNodeVisibilityIndexInternal(child); firstChildStart+=child->CalculateTotalVisibleNodes(); child->Release(); } } InvokeOnItemModified(firstChildStart, offsetBeforeChildModified, offset); } } void NodeItemProvider::OnItemExpanded(INodeProvider* node) { vint base=CalculateNodeVisibilityIndexInternal(node); if(base!=-2) { vint visibility=node->CalculateTotalVisibleNodes(); InvokeOnItemModified(base+1, 0, visibility-1); } } void NodeItemProvider::OnItemCollapsed(INodeProvider* node) { vint base=CalculateNodeVisibilityIndexInternal(node); if(base!=-2) { vint visibility=0; vint count=node->GetChildCount(); for(vint i=0;iGetChild(i); visibility+=child->CalculateTotalVisibleNodes(); child->Release(); } InvokeOnItemModified(base+1, visibility, 0); } } vint NodeItemProvider::CalculateNodeVisibilityIndexInternal(INodeProvider* node) { INodeProvider* parent=node->GetParent(); if(parent==0) { return -1; } if(!parent->GetExpanding()) { return -2; } vint index=CalculateNodeVisibilityIndexInternal(parent); if(index==-2) { return -2; } vint count=parent->GetChildCount(); for(vint i=0;iGetChild(i); bool findResult=child==node; if(findResult) { index++; } else { index+=child->CalculateTotalVisibleNodes(); } child->Release(); if(findResult) { return index; } } return -1; } vint NodeItemProvider::CalculateNodeVisibilityIndex(INodeProvider* node) { vint result=CalculateNodeVisibilityIndexInternal(node); return result<0?-1:result; } bool NodeItemProvider::ContainsPrimaryText(vint itemIndex) { if(nodeItemPrimaryTextView) { INodeProvider* node=RequestNode(itemIndex); if(node) { bool result=node->GetChildCount()==0; ReleaseNode(node); return result; } } return true; } WString NodeItemProvider::GetPrimaryTextViewText(vint itemIndex) { if(nodeItemPrimaryTextView) { INodeProvider* node=RequestNode(itemIndex); if(node) { WString result=nodeItemPrimaryTextView->GetPrimaryTextViewText(node); ReleaseNode(node); return result; } } return L""; } INodeProvider* NodeItemProvider::RequestNode(vint index) { if(root->CanGetNodeByVisibleIndex()) { return root->GetNodeByVisibleIndex(index+1); } else { return GetNodeByOffset(root->GetRootNode(), index+1); } } void NodeItemProvider::ReleaseNode(INodeProvider* node) { if(node) { node->Release(); } } NodeItemProvider::NodeItemProvider(Ptr _root) :root(_root) { root->AttachCallback(this); nodeItemPrimaryTextView=dynamic_cast(root->RequestView(INodeItemPrimaryTextView::Identifier)); } NodeItemProvider::~NodeItemProvider() { if(nodeItemPrimaryTextView) { root->ReleaseView(nodeItemPrimaryTextView); } root->DetachCallback(this); } Ptr NodeItemProvider::GetRoot() { return root; } vint NodeItemProvider::Count() { return root->GetRootNode()->CalculateTotalVisibleNodes()-1; } IDescriptable* NodeItemProvider::RequestView(const WString& identifier) { if(identifier==INodeItemView::Identifier) { return (INodeItemView*)this; } else if(identifier==GuiListControl::IItemPrimaryTextView::Identifier) { return (GuiListControl::IItemPrimaryTextView*)this; } else { return root->RequestView(identifier); } } void NodeItemProvider::ReleaseView(IDescriptable* view) { if(dynamic_cast(view)==0) { root->ReleaseView(view); } } /*********************************************************************** NodeItemProvider ***********************************************************************/ NodeItemStyleProvider::NodeItemStyleProvider(Ptr provider) :nodeItemStyleProvider(provider) ,listControl(0) ,nodeItemView(0) { nodeItemStyleProvider->BindItemStyleProvider(this); } NodeItemStyleProvider::~NodeItemStyleProvider() { } void NodeItemStyleProvider::AttachListControl(GuiListControl* value) { listControl=value; nodeItemView=dynamic_cast(listControl->GetItemProvider()->RequestView(INodeItemView::Identifier)); nodeItemStyleProvider->AttachListControl(value); } void NodeItemStyleProvider::DetachListControl() { nodeItemStyleProvider->DetachListControl(); if(nodeItemView) { listControl->GetItemProvider()->ReleaseView(nodeItemView); nodeItemView=0; } listControl=0; } vint NodeItemStyleProvider::GetItemStyleId(vint itemIndex) { vint result=-1; if(nodeItemView) { INodeProvider* node=nodeItemView->RequestNode(itemIndex); if(node) { result=nodeItemStyleProvider->GetItemStyleId(node); nodeItemView->ReleaseNode(node); } } return result; } GuiListControl::IItemStyleController* NodeItemStyleProvider::CreateItemStyle(vint styleId) { return nodeItemStyleProvider->CreateItemStyle(styleId); } void NodeItemStyleProvider::DestroyItemStyle(GuiListControl::IItemStyleController* style) { INodeItemStyleController* nodeStyle=dynamic_cast(style); if(nodeStyle) { nodeItemStyleProvider->DestroyItemStyle(nodeStyle); } } void NodeItemStyleProvider::Install(GuiListControl::IItemStyleController* style, vint itemIndex) { if(nodeItemView) { INodeItemStyleController* nodeStyle=dynamic_cast(style); if(nodeStyle) { INodeProvider* node=nodeItemView->RequestNode(itemIndex); if(node) { nodeItemStyleProvider->Install(nodeStyle, node, itemIndex); } } } } void NodeItemStyleProvider::SetStyleIndex(GuiListControl::IItemStyleController* style, vint value) { if(nodeItemView) { INodeItemStyleController* nodeStyle=dynamic_cast(style); if(nodeStyle) { nodeItemStyleProvider->SetStyleIndex(nodeStyle, value); } } } void NodeItemStyleProvider::SetStyleSelected(GuiListControl::IItemStyleController* style, bool value) { if(nodeItemView) { INodeItemStyleController* nodeStyle=dynamic_cast(style); if(nodeStyle) { nodeItemStyleProvider->SetStyleSelected(nodeStyle, value); } } } /*********************************************************************** MemoryNodeProvider::NodeCollection ***********************************************************************/ void MemoryNodeProvider::NodeCollection::OnBeforeChildModified(vint start, vint count, vint newCount) { ownerProvider->offsetBeforeChildModified=0; if(ownerProvider->expanding) { for(vint i=0;ioffsetBeforeChildModified+=items[start+i]->totalVisibleNodeCount; } } INodeProviderCallback* proxy=ownerProvider->GetCallbackProxyInternal(); if(proxy) { proxy->OnBeforeItemModified(ownerProvider, start, count, newCount); } } void MemoryNodeProvider::NodeCollection::OnAfterChildModified(vint start, vint count, vint newCount) { ownerProvider->childCount+=(newCount-count); if(ownerProvider->expanding) { vint offset=0; for(vint i=0;itotalVisibleNodeCount; } ownerProvider->OnChildTotalVisibleNodesChanged(offset-ownerProvider->offsetBeforeChildModified); } INodeProviderCallback* proxy=ownerProvider->GetCallbackProxyInternal(); if(proxy) { proxy->OnAfterItemModified(ownerProvider, start, count, newCount); } } bool MemoryNodeProvider::NodeCollection::QueryInsert(vint index, Ptr const& child) { return child->parent == 0; } bool MemoryNodeProvider::NodeCollection::QueryRemove(vint index, Ptr const& child) { return child->parent == ownerProvider; } void MemoryNodeProvider::NodeCollection::BeforeInsert(vint index, Ptr const& child) { OnBeforeChildModified(index, 0, 1); child->parent = ownerProvider; } void MemoryNodeProvider::NodeCollection::BeforeRemove(vint index, Ptr const& child) { OnBeforeChildModified(index, 1, 0); child->parent = 0; } void MemoryNodeProvider::NodeCollection::AfterInsert(vint index, Ptr const& child) { OnAfterChildModified(index, 0, 1); } void MemoryNodeProvider::NodeCollection::AfterRemove(vint index, vint count) { OnAfterChildModified(index, count, 0); } MemoryNodeProvider::NodeCollection::NodeCollection() :ownerProvider(0) { } /*********************************************************************** MemoryNodeProvider ***********************************************************************/ INodeProviderCallback* MemoryNodeProvider::GetCallbackProxyInternal() { if(parent) { return parent->GetCallbackProxyInternal(); } else { return 0; } } void MemoryNodeProvider::OnChildTotalVisibleNodesChanged(vint offset) { totalVisibleNodeCount+=offset; if(parent) { parent->OnChildTotalVisibleNodesChanged(offset); } } MemoryNodeProvider::MemoryNodeProvider() :parent(0) ,expanding(false) ,childCount(0) ,totalVisibleNodeCount(1) ,offsetBeforeChildModified(0) { children.ownerProvider=this; } MemoryNodeProvider::MemoryNodeProvider(const Ptr& _data) :parent(0) ,expanding(false) ,childCount(0) ,totalVisibleNodeCount(1) ,offsetBeforeChildModified(0) ,data(_data) { children.ownerProvider=this; } MemoryNodeProvider::~MemoryNodeProvider() { } Ptr MemoryNodeProvider::GetData() { return data; } void MemoryNodeProvider::SetData(const Ptr& value) { data=value; NotifyDataModified(); } void MemoryNodeProvider::NotifyDataModified() { if(parent) { vint index=parent->children.IndexOf(this); INodeProviderCallback* proxy=GetCallbackProxyInternal(); if(proxy) { proxy->OnBeforeItemModified(parent, index, 1, 1); proxy->OnAfterItemModified(parent, index, 1, 1); } } } MemoryNodeProvider::NodeCollection& MemoryNodeProvider::Children() { return children; } bool MemoryNodeProvider::GetExpanding() { return expanding; } void MemoryNodeProvider::SetExpanding(bool value) { if(expanding!=value) { expanding=value; vint offset=0; for(vint i=0;itotalVisibleNodeCount; } OnChildTotalVisibleNodesChanged(expanding?offset:-offset); INodeProviderCallback* proxy=GetCallbackProxyInternal(); if(proxy) { if(expanding) { proxy->OnItemExpanded(this); } else { proxy->OnItemCollapsed(this); } } } } vint MemoryNodeProvider::CalculateTotalVisibleNodes() { return totalVisibleNodeCount; } vint MemoryNodeProvider::GetChildCount() { return childCount; } INodeProvider* MemoryNodeProvider::GetParent() { return parent; } INodeProvider* MemoryNodeProvider::GetChild(vint index) { if(0<=index && indexOnBeforeItemModified(parentNode, start, count, newCount); } } void NodeRootProviderBase::OnAfterItemModified(INodeProvider* parentNode, vint start, vint count, vint newCount) { for(vint i=0;iOnAfterItemModified(parentNode, start, count, newCount); } } void NodeRootProviderBase::OnItemExpanded(INodeProvider* node) { for(vint i=0;iOnItemExpanded(node); } } void NodeRootProviderBase::OnItemCollapsed(INodeProvider* node) { for(vint i=0;iOnItemCollapsed(node); } } NodeRootProviderBase::NodeRootProviderBase() { } NodeRootProviderBase::~NodeRootProviderBase() { } bool NodeRootProviderBase::CanGetNodeByVisibleIndex() { return false; } INodeProvider* NodeRootProviderBase::GetNodeByVisibleIndex(vint index) { return 0; } bool NodeRootProviderBase::AttachCallback(INodeProviderCallback* value) { if(callbacks.Contains(value)) { return false; } else { callbacks.Add(value); value->OnAttached(this); return true; } } bool NodeRootProviderBase::DetachCallback(INodeProviderCallback* value) { vint index=callbacks.IndexOf(value); if(index==-1) { return false; } else { value->OnAttached(0); callbacks.Remove(value); return true; } } IDescriptable* NodeRootProviderBase::RequestView(const WString& identifier) { return 0; } void NodeRootProviderBase::ReleaseView(IDescriptable* view) { } /*********************************************************************** MemoryNodeRootProvider ***********************************************************************/ INodeProviderCallback* MemoryNodeRootProvider::GetCallbackProxyInternal() { return this; } MemoryNodeRootProvider::MemoryNodeRootProvider() { SetExpanding(true); } MemoryNodeRootProvider::~MemoryNodeRootProvider() { } INodeProvider* MemoryNodeRootProvider::GetRootNode() { return this; } MemoryNodeProvider* MemoryNodeRootProvider::GetMemoryNode(INodeProvider* node) { return dynamic_cast(node); } } /*********************************************************************** GuiVirtualTreeListControl ***********************************************************************/ void GuiVirtualTreeListControl::OnAttached(tree::INodeRootProvider* provider) { } void GuiVirtualTreeListControl::OnBeforeItemModified(tree::INodeProvider* parentNode, vint start, vint count, vint newCount) { } void GuiVirtualTreeListControl::OnAfterItemModified(tree::INodeProvider* parentNode, vint start, vint count, vint newCount) { } void GuiVirtualTreeListControl::OnItemExpanded(tree::INodeProvider* node) { GuiNodeEventArgs arguments; (GuiEventArgs&)arguments=GetNotifyEventArguments(); arguments.node=node; NodeExpanded.Execute(arguments); } void GuiVirtualTreeListControl::OnItemCollapsed(tree::INodeProvider* node) { GuiNodeEventArgs arguments; (GuiEventArgs&)arguments=GetNotifyEventArguments(); arguments.node=node; NodeCollapsed.Execute(arguments); } void GuiVirtualTreeListControl::OnItemMouseEvent(compositions::GuiNodeMouseEvent& nodeEvent, compositions::GuiGraphicsComposition* sender, compositions::GuiItemMouseEventArgs& arguments) { tree::INodeProvider* node=GetNodeItemView()->RequestNode(arguments.itemIndex); if(node) { GuiNodeMouseEventArgs redirectArguments; (GuiMouseEventArgs&)redirectArguments=arguments; redirectArguments.node=node; nodeEvent.Execute(redirectArguments); (GuiMouseEventArgs&)arguments=redirectArguments; GetNodeItemView()->ReleaseNode(node); } } void GuiVirtualTreeListControl::OnItemNotifyEvent(compositions::GuiNodeNotifyEvent& nodeEvent, compositions::GuiGraphicsComposition* sender, compositions::GuiItemEventArgs& arguments) { tree::INodeProvider* node=GetNodeItemView()->RequestNode(arguments.itemIndex); if(node) { GuiNodeEventArgs redirectArguments; (GuiEventArgs&)redirectArguments=arguments; redirectArguments.node=node; nodeEvent.Execute(redirectArguments); (GuiEventArgs&)arguments=redirectArguments; GetNodeItemView()->ReleaseNode(node); } } #define ATTACH_ITEM_MOUSE_EVENT(NODEEVENTNAME, ITEMEVENTNAME)\ {\ Func func(this, &GuiVirtualTreeListControl::OnItemMouseEvent);\ ITEMEVENTNAME.AttachFunction(Curry(func)(NODEEVENTNAME));\ }\ #define ATTACH_ITEM_NOTIFY_EVENT(NODEEVENTNAME, ITEMEVENTNAME)\ {\ Func func(this, &GuiVirtualTreeListControl::OnItemNotifyEvent);\ ITEMEVENTNAME.AttachFunction(Curry(func)(NODEEVENTNAME));\ }\ GuiVirtualTreeListControl::GuiVirtualTreeListControl(IStyleProvider* _styleProvider, Ptr _nodeRootProvider) :GuiSelectableListControl(_styleProvider, new tree::NodeItemProvider(_nodeRootProvider)) { nodeItemProvider=dynamic_cast(GetItemProvider()); nodeItemView=dynamic_cast(GetItemProvider()->RequestView(tree::INodeItemView::Identifier)); NodeLeftButtonDown.SetAssociatedComposition(boundsComposition); NodeLeftButtonUp.SetAssociatedComposition(boundsComposition); NodeLeftButtonDoubleClick.SetAssociatedComposition(boundsComposition); NodeMiddleButtonDown.SetAssociatedComposition(boundsComposition); NodeMiddleButtonUp.SetAssociatedComposition(boundsComposition); NodeMiddleButtonDoubleClick.SetAssociatedComposition(boundsComposition); NodeRightButtonDown.SetAssociatedComposition(boundsComposition); NodeRightButtonUp.SetAssociatedComposition(boundsComposition); NodeRightButtonDoubleClick.SetAssociatedComposition(boundsComposition); NodeMouseMove.SetAssociatedComposition(boundsComposition); NodeMouseEnter.SetAssociatedComposition(boundsComposition); NodeMouseLeave.SetAssociatedComposition(boundsComposition); NodeExpanded.SetAssociatedComposition(boundsComposition); NodeCollapsed.SetAssociatedComposition(boundsComposition); ATTACH_ITEM_MOUSE_EVENT(NodeLeftButtonDown, ItemLeftButtonDown); ATTACH_ITEM_MOUSE_EVENT(NodeLeftButtonUp, ItemLeftButtonUp); ATTACH_ITEM_MOUSE_EVENT(NodeLeftButtonDoubleClick, ItemLeftButtonDoubleClick); ATTACH_ITEM_MOUSE_EVENT(NodeMiddleButtonDown, ItemMiddleButtonDown); ATTACH_ITEM_MOUSE_EVENT(NodeMiddleButtonUp, ItemMiddleButtonUp); ATTACH_ITEM_MOUSE_EVENT(NodeMiddleButtonDoubleClick, ItemMiddleButtonDoubleClick); ATTACH_ITEM_MOUSE_EVENT(NodeRightButtonDown, ItemRightButtonDown); ATTACH_ITEM_MOUSE_EVENT(NodeRightButtonUp, ItemRightButtonUp); ATTACH_ITEM_MOUSE_EVENT(NodeRightButtonDoubleClick, ItemRightButtonDoubleClick); ATTACH_ITEM_MOUSE_EVENT(NodeMouseMove, ItemMouseMove); ATTACH_ITEM_NOTIFY_EVENT(NodeMouseEnter, ItemMouseEnter); ATTACH_ITEM_NOTIFY_EVENT(NodeMouseLeave, ItemMouseLeave); nodeItemProvider->GetRoot()->AttachCallback(this); } #undef ATTACH_ITEM_MOUSE_EVENT #undef ATTACH_ITEM_NOTIFY_EVENT GuiVirtualTreeListControl::~GuiVirtualTreeListControl() { GetItemProvider()->ReleaseView(nodeItemView); } tree::INodeItemView* GuiVirtualTreeListControl::GetNodeItemView() { return nodeItemView; } tree::INodeRootProvider* GuiVirtualTreeListControl::GetNodeRootProvider() { return nodeItemProvider->GetRoot().Obj(); } tree::INodeItemStyleProvider* GuiVirtualTreeListControl::GetNodeStyleProvider() { return nodeStyleProvider.Obj(); } Ptr GuiVirtualTreeListControl::SetNodeStyleProvider(Ptr styleProvider) { Ptr old=nodeStyleProvider; nodeStyleProvider=styleProvider; GuiSelectableListControl::SetStyleProvider(new tree::NodeItemStyleProvider(nodeStyleProvider)); return old; } namespace tree { /*********************************************************************** TreeViewItem ***********************************************************************/ const wchar_t* const ITreeViewItemView::Identifier = L"vl::presentation::controls::tree::ITreeViewItemView"; TreeViewItem::TreeViewItem() { } TreeViewItem::TreeViewItem(const Ptr& _image, const WString& _text) :image(_image) ,text(_text) { } /*********************************************************************** TreeViewItemRootProvider ***********************************************************************/ WString TreeViewItemRootProvider::GetPrimaryTextViewText(INodeProvider* node) { return GetNodeText(node); } Ptr TreeViewItemRootProvider::GetNodeImage(INodeProvider* node) { MemoryNodeProvider* memoryNode=dynamic_cast(node); if(memoryNode) { Ptr data=memoryNode->GetData().Cast(); if(data) { return data->image; } } return 0; } WString TreeViewItemRootProvider::GetNodeText(INodeProvider* node) { MemoryNodeProvider* memoryNode=dynamic_cast(node); if(memoryNode) { Ptr data=memoryNode->GetData().Cast(); if(data) { return data->text; } } return L""; } description::Value TreeViewItemRootProvider::GetBindingValue(INodeProvider* node) { return Value::From(GetTreeViewData(node)); } TreeViewItemRootProvider::TreeViewItemRootProvider() { } TreeViewItemRootProvider::~TreeViewItemRootProvider() { } IDescriptable* TreeViewItemRootProvider::RequestView(const WString& identifier) { if(identifier==ITreeViewItemView::Identifier) { return (ITreeViewItemView*)this; } else if(identifier==INodeItemPrimaryTextView::Identifier) { return (INodeItemPrimaryTextView*)this; } else if(identifier==INodeItemBindingView::Identifier) { return (INodeItemBindingView*)this; } else { return MemoryNodeRootProvider::RequestView(identifier); } } void TreeViewItemRootProvider::ReleaseView(IDescriptable* view) { return MemoryNodeRootProvider::ReleaseView(view); } Ptr TreeViewItemRootProvider::GetTreeViewData(INodeProvider* node) { MemoryNodeProvider* memoryNode=GetMemoryNode(node); if(memoryNode) { return memoryNode->GetData().Cast(); } else { return 0; } } void TreeViewItemRootProvider::SetTreeViewData(INodeProvider* node, Ptr value) { MemoryNodeProvider* memoryNode=GetMemoryNode(node); if(memoryNode) { memoryNode->SetData(value); } } void TreeViewItemRootProvider::UpdateTreeViewData(INodeProvider* node) { MemoryNodeProvider* memoryNode=GetMemoryNode(node); if(memoryNode) { memoryNode->NotifyDataModified(); } } } /*********************************************************************** GuiVirtualTreeView ***********************************************************************/ GuiVirtualTreeView::GuiVirtualTreeView(IStyleProvider* _styleProvider, Ptr _nodeRootProvider) :GuiVirtualTreeListControl(_styleProvider, _nodeRootProvider) { styleProvider=dynamic_cast(styleController->GetStyleProvider()); SetNodeStyleProvider(new tree::TreeViewNodeItemStyleProvider); SetArranger(new list::FixedHeightItemArranger); } GuiVirtualTreeView::~GuiVirtualTreeView() { } GuiVirtualTreeView::IStyleProvider* GuiVirtualTreeView::GetTreeViewStyleProvider() { return styleProvider; } /*********************************************************************** GuiTreeView ***********************************************************************/ GuiTreeView::GuiTreeView(IStyleProvider* _styleProvider) :GuiVirtualTreeView(_styleProvider, new tree::TreeViewItemRootProvider) { nodes = nodeItemProvider->GetRoot().Cast(); } GuiTreeView::~GuiTreeView() { } Ptr GuiTreeView::Nodes() { return nodes; } Ptr GuiTreeView::GetSelectedItem() { Ptr result; vint index = GetSelectedItemIndex(); if (index != -1) { if (auto node = nodeItemView->RequestNode(index)) { if (auto memoryNode = dynamic_cast(node)) { result = memoryNode->GetData().Cast(); } nodeItemView->ReleaseNode(node); } } return result; } namespace tree { /*********************************************************************** TreeViewNodeItemStyleProvider::ItemController ***********************************************************************/ void TreeViewNodeItemStyleProvider::ItemController::SwitchNodeExpanding() { if(backgroundButton->GetBoundsComposition()->GetParent()) { GuiListControl::IItemArranger* arranger=styleProvider->treeControl->GetArranger(); vint index=arranger->GetVisibleIndex(this); if(index!=-1) { INodeItemView* view=styleProvider->treeControl->GetNodeItemView(); INodeProvider* node=view->RequestNode(index); if(node) { bool expanding=node->GetExpanding(); node->SetExpanding(!expanding); view->ReleaseNode(node); } } } } void TreeViewNodeItemStyleProvider::ItemController::OnBackgroundButtonDoubleClick(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(backgroundButton->GetVisuallyEnabled()) { SwitchNodeExpanding(); } } void TreeViewNodeItemStyleProvider::ItemController::OnExpandingButtonDoubleClick(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { arguments.handled=true; } void TreeViewNodeItemStyleProvider::ItemController::OnExpandingButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(expandingButton->GetVisuallyEnabled()) { SwitchNodeExpanding(); } } TreeViewNodeItemStyleProvider::ItemController::ItemController(TreeViewNodeItemStyleProvider* _styleProvider, Size minIconSize, bool fitImage) :list::ItemStyleControllerBase(_styleProvider->GetBindedItemStyleProvider(), 0) ,styleProvider(_styleProvider) { backgroundButton=new GuiSelectableButton(styleProvider->treeControl->GetTreeViewStyleProvider()->CreateItemBackground()); backgroundButton->SetAutoSelection(false); backgroundButton->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); backgroundButton->GetEventReceiver()->leftButtonDoubleClick.AttachMethod(this, &ItemController::OnBackgroundButtonDoubleClick); table=new GuiTableComposition; backgroundButton->GetBoundsComposition()->AddChild(table); table->SetRowsAndColumns(3, 4); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::AbsoluteOption(0)); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); table->SetColumnOption(2, GuiCellOption::MinSizeOption()); table->SetColumnOption(3, GuiCellOption::MinSizeOption()); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetCellPadding(2); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 3, 1); cell->SetPreferredMinSize(Size(16, 16)); expandingButton=new GuiSelectableButton(styleProvider->treeControl->GetTreeViewStyleProvider()->CreateItemExpandingDecorator()); expandingButton->SetAutoSelection(false); expandingButton->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); expandingButton->GetEventReceiver()->leftButtonDoubleClick.AttachMethod(this, &ItemController::OnExpandingButtonDoubleClick); expandingButton->Clicked.AttachMethod(this, &ItemController::OnExpandingButtonClicked); cell->AddChild(expandingButton->GetBoundsComposition()); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(1, 2, 1, 1); cell->SetPreferredMinSize(minIconSize); if (!fitImage) { cell->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } image=GuiImageFrameElement::Create(); image->SetStretch(true); cell->SetOwnedElement(image); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 3, 3, 1); cell->SetPreferredMinSize(Size(192, 0)); text=GuiSolidLabelElement::Create(); text->SetAlignments(Alignment::Left, Alignment::Center); text->SetFont(styleProvider->treeControl->GetFont()); text->SetEllipse(true); cell->SetOwnedElement(text); } Initialize(backgroundButton->GetBoundsComposition(), backgroundButton); } INodeItemStyleProvider* TreeViewNodeItemStyleProvider::ItemController::GetNodeStyleProvider() { return styleProvider; } void TreeViewNodeItemStyleProvider::ItemController::Install(INodeProvider* node) { ITreeViewItemView* view=styleProvider->treeViewItemView; Ptr imageData=view->GetNodeImage(node); if(imageData) { image->SetImage(imageData->GetImage(), imageData->GetFrameIndex()); } else { image->SetImage(0); } text->SetText(view->GetNodeText(node)); text->SetColor(styleProvider->treeControl->GetTreeViewStyleProvider()->GetTextColor()); UpdateExpandingButton(node); vint level=-2; while(node) { node=node->GetParent(); level++; } table->SetColumnOption(0, GuiCellOption::AbsoluteOption(level*16)); } bool TreeViewNodeItemStyleProvider::ItemController::GetSelected() { return backgroundButton->GetSelected(); } void TreeViewNodeItemStyleProvider::ItemController::SetSelected(bool value) { backgroundButton->SetSelected(value); } void TreeViewNodeItemStyleProvider::ItemController::UpdateExpandingButton(INodeProvider* associatedNode) { expandingButton->SetSelected(associatedNode->GetExpanding()); expandingButton->SetVisible(associatedNode->GetChildCount()>0); } /*********************************************************************** TreeViewNodeItemStyleProvider ***********************************************************************/ TreeViewNodeItemStyleProvider::ItemController* TreeViewNodeItemStyleProvider::GetRelatedController(INodeProvider* node) { vint index=treeControl->GetNodeItemView()->CalculateNodeVisibilityIndex(node); if(index!=-1) { GuiListControl::IItemStyleController* style=treeControl->GetArranger()->GetVisibleStyle(index); if(style) { ItemController* itemController=dynamic_cast(style); return itemController; } } return 0; } void TreeViewNodeItemStyleProvider::UpdateExpandingButton(INodeProvider* node) { ItemController* itemController=GetRelatedController(node); if(itemController) { itemController->UpdateExpandingButton(node); } } void TreeViewNodeItemStyleProvider::OnAttached(INodeRootProvider* provider) { } void TreeViewNodeItemStyleProvider::OnBeforeItemModified(INodeProvider* parentNode, vint start, vint count, vint newCount) { } void TreeViewNodeItemStyleProvider::OnAfterItemModified(INodeProvider* parentNode, vint start, vint count, vint newCount) { UpdateExpandingButton(parentNode); } void TreeViewNodeItemStyleProvider::OnItemExpanded(INodeProvider* node) { UpdateExpandingButton(node); } void TreeViewNodeItemStyleProvider::OnItemCollapsed(INodeProvider* node) { UpdateExpandingButton(node); } TreeViewNodeItemStyleProvider::TreeViewNodeItemStyleProvider(Size _minIconSize, bool _fitImage) :treeControl(0) ,bindedItemStyleProvider(0) ,treeViewItemView(0) , minIconSize(_minIconSize) , fitImage(_fitImage) { } TreeViewNodeItemStyleProvider::~TreeViewNodeItemStyleProvider() { } void TreeViewNodeItemStyleProvider::BindItemStyleProvider(GuiListControl::IItemStyleProvider* styleProvider) { bindedItemStyleProvider=styleProvider; } GuiListControl::IItemStyleProvider* TreeViewNodeItemStyleProvider::GetBindedItemStyleProvider() { return bindedItemStyleProvider; } void TreeViewNodeItemStyleProvider::AttachListControl(GuiListControl* value) { treeControl=dynamic_cast(value); if(treeControl) { treeViewItemView=dynamic_cast(treeControl->GetItemProvider()->RequestView(ITreeViewItemView::Identifier)); treeControl->GetNodeRootProvider()->AttachCallback(this); } } void TreeViewNodeItemStyleProvider::DetachListControl() { if(treeViewItemView) { treeControl->GetItemProvider()->ReleaseView(treeViewItemView); treeViewItemView=0; } if(treeControl) { treeControl->GetNodeRootProvider()->DetachCallback(this); treeControl=0; } } vint TreeViewNodeItemStyleProvider::GetItemStyleId(INodeProvider* node) { return 0; } INodeItemStyleController* TreeViewNodeItemStyleProvider::CreateItemStyle(vint styleId) { return new ItemController(this, minIconSize, fitImage); } void TreeViewNodeItemStyleProvider::DestroyItemStyle(INodeItemStyleController* style) { ItemController* itemController=dynamic_cast(style); if(itemController) { delete itemController; } } void TreeViewNodeItemStyleProvider::Install(INodeItemStyleController* style, INodeProvider* node, vint itemIndex) { ItemController* itemController=dynamic_cast(style); if(itemController) { itemController->Install(node); } } void TreeViewNodeItemStyleProvider::SetStyleIndex(INodeItemStyleController* style, vint value) { } void TreeViewNodeItemStyleProvider::SetStyleSelected(INodeItemStyleController* style, bool value) { ItemController* itemController=dynamic_cast(style); if(itemController) { itemController->SetSelected(value); } } } } } } /*********************************************************************** CONTROLS\STYLES\GUICOMMONSTYLES.CPP ***********************************************************************/ #include namespace vl { namespace presentation { namespace common_styles { using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** CommonScrollStyle ***********************************************************************/ void CommonScrollStyle::UpdateHandle() { double handlePageSize=(double)pageSize/totalSize; double handleRatio=(double)position/totalSize; switch(direction) { case Horizontal: handleComposition->SetWidthRatio(handleRatio); handleComposition->SetWidthPageSize(handlePageSize); break; case Vertical: handleComposition->SetHeightRatio(handleRatio); handleComposition->SetHeightPageSize(handlePageSize); break; } } void CommonScrollStyle::OnDecreaseButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(commandExecutor) { commandExecutor->SmallDecrease(); } } void CommonScrollStyle::OnIncreaseButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(commandExecutor) { commandExecutor->SmallIncrease(); } } void CommonScrollStyle::OnHandleMouseDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(commandExecutor && handleButton->GetVisuallyEnabled()) { draggingHandle=true; draggingStartLocation=Point(arguments.x, arguments.y); } } void CommonScrollStyle::OnHandleMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(draggingHandle) { vint totalPixels=0; vint currentOffset=0; vint newOffset=0; switch(direction) { case Horizontal: totalPixels=handleComposition->GetParent()->GetBounds().Width(); currentOffset=handleComposition->GetBounds().Left(); newOffset=currentOffset+(arguments.x-draggingStartLocation.x); break; case Vertical: totalPixels=handleComposition->GetParent()->GetBounds().Height(); currentOffset=handleComposition->GetBounds().Top(); newOffset=currentOffset+(arguments.y-draggingStartLocation.y); break; } double ratio=(double)newOffset/totalPixels; vint newPosition=(vint)(ratio*totalSize); vint offset1=(vint)(((double)newPosition/totalSize)*totalPixels); vint offset2=vint(((double)(newPosition+1)/totalSize)*totalPixels); vint delta1=abs((int)(offset1-newOffset)); vint delta2=abs((int)(offset2-newOffset)); if(delta1SetPosition(newPosition); } else { commandExecutor->SetPosition(newPosition+1); } } } void CommonScrollStyle::OnHandleMouseUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { draggingHandle=false; } void CommonScrollStyle::OnBigMoveMouseDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(commandExecutor && handleButton->GetVisuallyEnabled()) { if(arguments.eventSource==arguments.compositionSource) { Rect handleBounds=handleComposition->GetBounds(); switch(direction) { case Horizontal: if(arguments.xBigDecrease(); } else if(arguments.x>=handleBounds.x2) { commandExecutor->BigIncrease(); } break; case Vertical: if(arguments.yBigDecrease(); } else if(arguments.y>=handleBounds.y2) { commandExecutor->BigIncrease(); } break; } } } } void CommonScrollStyle::BuildStyle(vint defaultSize, vint arrowSize) { boundsComposition=new GuiBoundsComposition; containerComposition=InstallBackground(boundsComposition, direction); { GuiBoundsComposition* handleBoundsComposition=new GuiBoundsComposition; containerComposition->AddChild(handleBoundsComposition); handleComposition=new GuiPartialViewComposition; handleBoundsComposition->AddChild(handleComposition); handleBoundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &CommonScrollStyle::OnBigMoveMouseDown); switch(direction) { case Horizontal: handleBoundsComposition->SetAlignmentToParent(Margin(defaultSize, 0, defaultSize, 0)); handleComposition->SetPreferredMinSize(Size(defaultSize, 0)); boundsComposition->SetPreferredMinSize(Size(0, defaultSize)); break; case Vertical: handleBoundsComposition->SetAlignmentToParent(Margin(0, defaultSize, 0, defaultSize)); handleComposition->SetPreferredMinSize(Size(0, defaultSize)); boundsComposition->SetPreferredMinSize(Size(defaultSize, 0)); break; } handleButton=new GuiButton(CreateHandleButtonStyle(direction)); handleButton->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); handleComposition->AddChild(handleButton->GetBoundsComposition()); handleButton->GetBoundsComposition()->GetEventReceiver()->leftButtonDown.AttachMethod(this, &CommonScrollStyle::OnHandleMouseDown); handleButton->GetBoundsComposition()->GetEventReceiver()->mouseMove.AttachMethod(this, &CommonScrollStyle::OnHandleMouseMove); handleButton->GetBoundsComposition()->GetEventReceiver()->leftButtonUp.AttachMethod(this, &CommonScrollStyle::OnHandleMouseUp); } { decreaseButton=new GuiButton(CreateDecreaseButtonStyle(direction)); decreaseButton->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); decreaseButton->Clicked.AttachMethod(this, &CommonScrollStyle::OnDecreaseButtonClicked); increaseButton=new GuiButton(CreateIncreaseButtonStyle(direction)); increaseButton->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); increaseButton->Clicked.AttachMethod(this, &CommonScrollStyle::OnIncreaseButtonClicked); } { GuiSideAlignedComposition* decreaseComposition=new GuiSideAlignedComposition; decreaseComposition->SetMaxLength(defaultSize); decreaseComposition->SetMaxRatio(0.5); decreaseComposition->AddChild(decreaseButton->GetBoundsComposition()); containerComposition->AddChild(decreaseComposition); GuiSideAlignedComposition* increaseComposition=new GuiSideAlignedComposition; increaseComposition->SetMaxLength(defaultSize); increaseComposition->SetMaxRatio(0.5); increaseComposition->AddChild(increaseButton->GetBoundsComposition()); containerComposition->AddChild(increaseComposition); switch(direction) { case Horizontal: { decreaseComposition->SetDirection(GuiSideAlignedComposition::Left); increaseComposition->SetDirection(GuiSideAlignedComposition::Right); } break; case Vertical: { decreaseComposition->SetDirection(GuiSideAlignedComposition::Top); increaseComposition->SetDirection(GuiSideAlignedComposition::Bottom); } break; } } } CommonScrollStyle::CommonScrollStyle(Direction _direction) :direction(_direction) ,commandExecutor(0) ,decreaseButton(0) ,increaseButton(0) ,boundsComposition(0) ,containerComposition(0) ,totalSize(1) ,pageSize(1) ,position(0) ,draggingHandle(false) { } CommonScrollStyle::~CommonScrollStyle() { } compositions::GuiBoundsComposition* CommonScrollStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* CommonScrollStyle::GetContainerComposition() { return containerComposition; } void CommonScrollStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void CommonScrollStyle::SetText(const WString& value) { } void CommonScrollStyle::SetFont(const FontProperties& value) { } void CommonScrollStyle::SetVisuallyEnabled(bool value) { } void CommonScrollStyle::SetCommandExecutor(controls::GuiScroll::ICommandExecutor* value) { commandExecutor=value; } void CommonScrollStyle::SetTotalSize(vint value) { if(totalSize!=value) { totalSize=value; UpdateHandle(); } } void CommonScrollStyle::SetPageSize(vint value) { if(pageSize!=value) { pageSize=value; UpdateHandle(); } } void CommonScrollStyle::SetPosition(vint value) { if(position!=value) { position=value; UpdateHandle(); } } /*********************************************************************** CommonTrackStyle ***********************************************************************/ void CommonTrackStyle::UpdateHandle() { vint maxSize=totalSize-pageSize; if(maxSize<1) maxSize=1; double ratio=(double)position/maxSize; switch(direction) { case Horizontal: handleComposition->SetColumnOption(0, GuiCellOption::PercentageOption(ratio)); handleComposition->SetColumnOption(2, GuiCellOption::PercentageOption(1-ratio)); break; case Vertical: handleComposition->SetRowOption(0, GuiCellOption::PercentageOption(1-ratio)); handleComposition->SetRowOption(2, GuiCellOption::PercentageOption(ratio)); break; } handleComposition->UpdateCellBounds(); } void CommonTrackStyle::OnHandleMouseDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(commandExecutor && handleButton->GetVisuallyEnabled()) { draggingHandle=true; draggingStartLocation=Point(arguments.x, arguments.y); } } void CommonTrackStyle::OnHandleMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(draggingHandle) { vint totalPixels=0; vint currentOffset=0; vint newOffset=0; Rect handleArea=handleComposition->GetBounds(); Rect handleBounds=handleButton->GetBoundsComposition()->GetParent()->GetBounds(); switch(direction) { case Horizontal: totalPixels=handleArea.Width()-handleBounds.Width(); currentOffset=handleBounds.Left(); newOffset=currentOffset+(arguments.x-draggingStartLocation.x); break; case Vertical: totalPixels=handleArea.Height()-handleBounds.Height(); currentOffset=handleArea.Height()-handleBounds.Bottom(); newOffset=currentOffset-(arguments.y-draggingStartLocation.y); break; } double ratio=(double)newOffset/totalPixels; vint maxSize=totalSize-pageSize; if(maxSize<1) maxSize=1; vint newPosition=(vint)(ratio*maxSize); vint offset1=(vint)(((double)newPosition/maxSize)*totalPixels); vint offset2=vint(((double)(newPosition+1)/maxSize)*totalPixels); vint delta1=abs((int)(offset1-newOffset)); vint delta2=abs((int)(offset2-newOffset)); if(delta1SetPosition(newPosition); } else { commandExecutor->SetPosition(newPosition+1); } } } void CommonTrackStyle::OnHandleMouseUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { draggingHandle=false; } void CommonTrackStyle::BuildStyle(vint trackThickness, vint trackPadding, vint handleLong, vint handleShort) { boundsComposition=new GuiBoundsComposition; InstallBackground(boundsComposition, direction); { GuiTableComposition* table=new GuiTableComposition; boundsComposition->AddChild(table); boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetRowsAndColumns(3, 3); table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); switch(direction) { case Horizontal: table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::AbsoluteOption(handleLong)); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::AbsoluteOption(trackPadding)); table->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(2, GuiCellOption::AbsoluteOption(trackPadding)); break; case Vertical: table->SetRowOption(0, GuiCellOption::AbsoluteOption(trackPadding)); table->SetRowOption(1, GuiCellOption::PercentageOption(1.0)); table->SetRowOption(2, GuiCellOption::AbsoluteOption(trackPadding)); table->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(1, GuiCellOption::AbsoluteOption(handleLong)); table->SetColumnOption(2, GuiCellOption::PercentageOption(0.5)); break; } { GuiCellComposition* contentCell=new GuiCellComposition; table->AddChild(contentCell); contentCell->SetSite(1, 1, 1, 1); { GuiTableComposition* trackTable=new GuiTableComposition; trackTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); contentCell->AddChild(trackTable); GuiCellComposition* trackCell=new GuiCellComposition; trackTable->AddChild(trackCell); switch(direction) { case Horizontal: trackTable->SetRowsAndColumns(3, 1); trackTable->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); trackTable->SetRowOption(1, GuiCellOption::AbsoluteOption(trackThickness)); trackTable->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); trackCell->SetSite(1, 0, 1, 1); break; case Vertical: trackTable->SetRowsAndColumns(1, 3); trackTable->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); trackTable->SetColumnOption(1, GuiCellOption::AbsoluteOption(trackThickness)); trackTable->SetColumnOption(2, GuiCellOption::PercentageOption(0.5)); trackCell->SetSite(0, 1, 1, 1); break; } InstallTrack(trackCell, direction); } { handleComposition=new GuiTableComposition; handleComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); contentCell->AddChild(handleComposition); GuiCellComposition* handleCell=new GuiCellComposition; handleComposition->AddChild(handleCell); switch(direction) { case Horizontal: handleComposition->SetRowsAndColumns(1, 3); handleComposition->SetColumnOption(0, GuiCellOption::PercentageOption(0.0)); handleComposition->SetColumnOption(1, GuiCellOption::AbsoluteOption(handleShort)); handleComposition->SetColumnOption(2, GuiCellOption::PercentageOption(1.0)); handleCell->SetSite(0, 1, 1, 1); break; case Vertical: handleComposition->SetRowsAndColumns(3, 1); handleComposition->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); handleComposition->SetRowOption(1, GuiCellOption::AbsoluteOption(handleShort)); handleComposition->SetRowOption(2, GuiCellOption::PercentageOption(0.0)); handleCell->SetSite(1, 0, 1, 1); break; } handleButton=new GuiButton(CreateHandleButtonStyle(direction)); handleButton->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); handleCell->AddChild(handleButton->GetBoundsComposition()); handleButton->GetBoundsComposition()->GetEventReceiver()->leftButtonDown.AttachMethod(this, &CommonTrackStyle::OnHandleMouseDown); handleButton->GetBoundsComposition()->GetEventReceiver()->mouseMove.AttachMethod(this, &CommonTrackStyle::OnHandleMouseMove); handleButton->GetBoundsComposition()->GetEventReceiver()->leftButtonUp.AttachMethod(this, &CommonTrackStyle::OnHandleMouseUp); } } } } CommonTrackStyle::CommonTrackStyle(Direction _direction) :direction(_direction) ,commandExecutor(0) ,totalSize(1) ,pageSize(1) ,position(0) ,draggingHandle(false) { } CommonTrackStyle::~CommonTrackStyle() { } compositions::GuiBoundsComposition* CommonTrackStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* CommonTrackStyle::GetContainerComposition() { return boundsComposition; } void CommonTrackStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void CommonTrackStyle::SetText(const WString& value) { } void CommonTrackStyle::SetFont(const FontProperties& value) { } void CommonTrackStyle::SetVisuallyEnabled(bool value) { } void CommonTrackStyle::SetCommandExecutor(controls::GuiScroll::ICommandExecutor* value) { commandExecutor=value; if(value) { value->SetPageSize(0); } } void CommonTrackStyle::SetTotalSize(vint value) { if(totalSize!=value) { totalSize=value; UpdateHandle(); } } void CommonTrackStyle::SetPageSize(vint value) { if(pageSize!=value) { pageSize=value; UpdateHandle(); } } void CommonTrackStyle::SetPosition(vint value) { if(position!=value) { position=value; UpdateHandle(); } } /*********************************************************************** CommonFragmentBuilder ***********************************************************************/ void CommonFragmentBuilder::FillUpArrow(elements::GuiPolygonElement* element) { Point points[]={Point(0, 3), Point(3, 0), Point(6, 3)}; element->SetSize(Size(7, 4)); element->SetPoints(points, sizeof(points)/sizeof(*points)); } void CommonFragmentBuilder::FillDownArrow(elements::GuiPolygonElement* element) { Point points[]={Point(0, 0), Point(3, 3), Point(6, 0)}; element->SetSize(Size(7, 4)); element->SetPoints(points, sizeof(points)/sizeof(*points)); } void CommonFragmentBuilder::FillLeftArrow(elements::GuiPolygonElement* element) { Point points[]={Point(3, 0), Point(0, 3), Point(3, 6)}; element->SetSize(Size(4, 7)); element->SetPoints(points, sizeof(points)/sizeof(*points)); } void CommonFragmentBuilder::FillRightArrow(elements::GuiPolygonElement* element) { Point points[]={Point(0, 0), Point(3, 3), Point(0, 6)}; element->SetSize(Size(4, 7)); element->SetPoints(points, sizeof(points)/sizeof(*points)); } elements::GuiPolygonElement* CommonFragmentBuilder::BuildUpArrow() { GuiPolygonElement* element=GuiPolygonElement::Create(); FillUpArrow(element); element->SetBorderColor(Color(0, 0, 0)); element->SetBackgroundColor(Color(0, 0, 0)); return element; } elements::GuiPolygonElement* CommonFragmentBuilder::BuildDownArrow() { GuiPolygonElement* element=GuiPolygonElement::Create(); FillDownArrow(element); element->SetBorderColor(Color(0, 0, 0)); element->SetBackgroundColor(Color(0, 0, 0)); return element; } elements::GuiPolygonElement* CommonFragmentBuilder::BuildLeftArrow() { GuiPolygonElement* element=GuiPolygonElement::Create(); FillLeftArrow(element); element->SetBorderColor(Color(0, 0, 0)); element->SetBackgroundColor(Color(0, 0, 0)); return element; } elements::GuiPolygonElement* CommonFragmentBuilder::BuildRightArrow() { GuiPolygonElement* element=GuiPolygonElement::Create(); FillRightArrow(element); element->SetBorderColor(Color(0, 0, 0)); element->SetBackgroundColor(Color(0, 0, 0)); return element; } compositions::GuiBoundsComposition* CommonFragmentBuilder::BuildDockedElementContainer(elements::IGuiGraphicsElement* element) { GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetOwnedElement(element); composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); return composition; } compositions::GuiBoundsComposition* CommonFragmentBuilder::BuildUpArrow(elements::GuiPolygonElement*& elementOut) { elementOut=BuildUpArrow(); return BuildDockedElementContainer(elementOut); } compositions::GuiBoundsComposition* CommonFragmentBuilder::BuildDownArrow(elements::GuiPolygonElement*& elementOut) { elementOut=BuildDownArrow(); return BuildDockedElementContainer(elementOut); } compositions::GuiBoundsComposition* CommonFragmentBuilder::BuildLeftArrow(elements::GuiPolygonElement*& elementOut) { elementOut=BuildLeftArrow(); return BuildDockedElementContainer(elementOut); } compositions::GuiBoundsComposition* CommonFragmentBuilder::BuildRightArrow(elements::GuiPolygonElement*& elementOut) { elementOut=BuildRightArrow(); return BuildDockedElementContainer(elementOut); } } /*********************************************************************** Helpers ***********************************************************************/ unsigned char IntToColor(vint color) { return color<0?0:color>255?255:(unsigned char)color; } Color BlendColor(Color c1, Color c2, vint currentPosition, vint totalLength) { return Color( (unsigned char)IntToColor((c2.r*currentPosition+c1.r*(totalLength-currentPosition))/totalLength), (unsigned char)IntToColor((c2.g*currentPosition+c1.g*(totalLength-currentPosition))/totalLength), (unsigned char)IntToColor((c2.b*currentPosition+c1.b*(totalLength-currentPosition))/totalLength), (unsigned char)IntToColor((c2.a*currentPosition+c1.a*(totalLength-currentPosition))/totalLength) ); } } } /*********************************************************************** CONTROLS\STYLES\GUITHEMESTYLEFACTORY.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace theme { ITheme* currentTheme=0; ITheme* GetCurrentTheme() { return currentTheme; } void SetCurrentTheme(ITheme* theme) { currentTheme=theme; } namespace g { controls::GuiWindow* NewWindow() { return new controls::GuiWindow(GetCurrentTheme()->CreateWindowStyle()); } controls::GuiCustomControl* NewCustomControl() { return new controls::GuiCustomControl(GetCurrentTheme()->CreateCustomControlStyle()); } controls::GuiLabel* NewLabel() { return new controls::GuiLabel(GetCurrentTheme()->CreateLabelStyle()); } controls::GuiScrollContainer* NewScrollContainer() { return new controls::GuiScrollContainer(GetCurrentTheme()->CreateScrollContainerStyle()); } controls::GuiControl* NewGroupBox() { return new controls::GuiControl(GetCurrentTheme()->CreateGroupBoxStyle()); } controls::GuiTab* NewTab() { return new controls::GuiTab(GetCurrentTheme()->CreateTabStyle()); } controls::GuiComboBoxListControl* NewComboBox(controls::GuiSelectableListControl* containedListControl) { return new controls::GuiComboBoxListControl(GetCurrentTheme()->CreateComboBoxStyle(), containedListControl); } controls::GuiMultilineTextBox* NewMultilineTextBox() { return new controls::GuiMultilineTextBox(GetCurrentTheme()->CreateMultilineTextBoxStyle()); } controls::GuiSinglelineTextBox* NewTextBox() { return new controls::GuiSinglelineTextBox(GetCurrentTheme()->CreateTextBoxStyle()); } controls::GuiDocumentViewer* NewDocumentViewer() { return new controls::GuiDocumentViewer(GetCurrentTheme()->CreateDocumentViewerStyle()); } controls::GuiDocumentLabel* NewDocumentLabel() { return new controls::GuiDocumentLabel(GetCurrentTheme()->CreateDocumentLabelStyle()); } controls::GuiListView* NewListViewBigIcon() { controls::GuiListView* listview=new controls::GuiListView(GetCurrentTheme()->CreateListViewStyle()); listview->ChangeItemStyle(new controls::list::ListViewBigIconContentProvider); return listview; } controls::GuiListView* NewListViewSmallIcon() { controls::GuiListView* listview=new controls::GuiListView(GetCurrentTheme()->CreateListViewStyle()); listview->ChangeItemStyle(new controls::list::ListViewSmallIconContentProvider); return listview; } controls::GuiListView* NewListViewList() { controls::GuiListView* listview=new controls::GuiListView(GetCurrentTheme()->CreateListViewStyle()); listview->ChangeItemStyle(new controls::list::ListViewListContentProvider); return listview; } controls::GuiListView* NewListViewDetail() { controls::GuiListView* listview=new controls::GuiListView(GetCurrentTheme()->CreateListViewStyle()); listview->ChangeItemStyle(new controls::list::ListViewDetailContentProvider); return listview; } controls::GuiListView* NewListViewTile() { controls::GuiListView* listview=new controls::GuiListView(GetCurrentTheme()->CreateListViewStyle()); listview->ChangeItemStyle(new controls::list::ListViewTileContentProvider); return listview; } controls::GuiListView* NewListViewInformation() { controls::GuiListView* listview=new controls::GuiListView(GetCurrentTheme()->CreateListViewStyle()); listview->ChangeItemStyle(new controls::list::ListViewInformationContentProvider); return listview; } controls::GuiTreeView* NewTreeView() { return new controls::GuiTreeView(GetCurrentTheme()->CreateTreeViewStyle()); } controls::GuiStringGrid* NewStringGrid() { return new controls::GuiStringGrid(GetCurrentTheme()->CreateListViewStyle()); } controls::GuiToolstripMenu* NewMenu(controls::GuiControl* owner) { return new controls::GuiToolstripMenu(GetCurrentTheme()->CreateMenuStyle(), owner); } controls::GuiToolstripMenuBar* NewMenuBar() { return new controls::GuiToolstripMenuBar(GetCurrentTheme()->CreateMenuBarStyle()); } controls::GuiControl* NewMenuSplitter() { return new controls::GuiControl(GetCurrentTheme()->CreateMenuSplitterStyle()); } controls::GuiToolstripButton* NewMenuBarButton() { return new controls::GuiToolstripButton(GetCurrentTheme()->CreateMenuBarButtonStyle()); } controls::GuiToolstripButton* NewMenuItemButton() { return new controls::GuiToolstripButton(GetCurrentTheme()->CreateMenuItemButtonStyle()); } controls::GuiToolstripToolBar* NewToolBar() { return new controls::GuiToolstripToolBar(GetCurrentTheme()->CreateToolBarStyle()); } controls::GuiToolstripButton* NewToolBarButton() { return new controls::GuiToolstripButton(GetCurrentTheme()->CreateToolBarButtonStyle()); } controls::GuiToolstripButton* NewToolBarDropdownButton() { return new controls::GuiToolstripButton(GetCurrentTheme()->CreateToolBarDropdownButtonStyle()); } controls::GuiToolstripButton* NewToolBarSplitButton() { return new controls::GuiToolstripButton(GetCurrentTheme()->CreateToolBarSplitButtonStyle()); } controls::GuiControl* NewToolBarSplitter() { return new controls::GuiControl(GetCurrentTheme()->CreateToolBarSplitterStyle()); } controls::GuiButton* NewButton() { return new controls::GuiButton(GetCurrentTheme()->CreateButtonStyle()); } controls::GuiSelectableButton* NewCheckBox() { return new controls::GuiSelectableButton(GetCurrentTheme()->CreateCheckBoxStyle()); } controls::GuiSelectableButton* NewRadioButton() { return new controls::GuiSelectableButton(GetCurrentTheme()->CreateRadioButtonStyle()); } controls::GuiDatePicker* NewDatePicker() { return new controls::GuiDatePicker(GetCurrentTheme()->CreateDatePickerStyle()); } controls::GuiDateComboBox* NewDateComboBox() { return new controls::GuiDateComboBox(GetCurrentTheme()->CreateComboBoxStyle(), NewDatePicker()); } controls::GuiScroll* NewHScroll() { return new controls::GuiScroll(GetCurrentTheme()->CreateHScrollStyle()); } controls::GuiScroll* NewVScroll() { return new controls::GuiScroll(GetCurrentTheme()->CreateVScrollStyle()); } controls::GuiScroll* NewHTracker() { controls::GuiScroll* scroll=new controls::GuiScroll(GetCurrentTheme()->CreateHTrackerStyle()); scroll->SetPageSize(0); return scroll; } controls::GuiScroll* NewVTracker() { controls::GuiScroll* scroll=new controls::GuiScroll(GetCurrentTheme()->CreateVTrackerStyle()); scroll->SetPageSize(0); return scroll; } controls::GuiScroll* NewProgressBar() { controls::GuiScroll* scroll=new controls::GuiScroll(GetCurrentTheme()->CreateProgressBarStyle()); scroll->SetPageSize(0); return scroll; } controls::GuiTextList* NewTextList() { return new controls::GuiTextList(GetCurrentTheme()->CreateTextListStyle(), GetCurrentTheme()->CreateTextListItemStyle()); } controls::GuiTextList* NewCheckTextList() { return new controls::GuiTextList(GetCurrentTheme()->CreateTextListStyle(), GetCurrentTheme()->CreateCheckTextListItemStyle()); } controls::GuiTextList* NewRadioTextList() { return new controls::GuiTextList(GetCurrentTheme()->CreateTextListStyle(), GetCurrentTheme()->CreateRadioTextListItemStyle()); } } } } } /*********************************************************************** CONTROLS\STYLES\GUIWIN7STYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7Theme ***********************************************************************/ Win7Theme::Win7Theme() { } Win7Theme::~Win7Theme() { } controls::GuiWindow::IStyleController* Win7Theme::CreateWindowStyle() { return new Win7WindowStyle; } controls::GuiCustomControl::IStyleController* Win7Theme::CreateCustomControlStyle() { return new GuiCustomControl::EmptyStyleController; } controls::GuiTooltip::IStyleController* Win7Theme::CreateTooltipStyle() { return new Win7TooltipStyle; } controls::GuiLabel::IStyleController* Win7Theme::CreateLabelStyle() { return new Win7LabelStyle(false); } controls::GuiLabel::IStyleController* Win7Theme::CreateShortcutKeyStyle() { return new Win7LabelStyle(true); } controls::GuiScrollContainer::IStyleProvider* Win7Theme::CreateScrollContainerStyle() { return new Win7ScrollViewProvider; } controls::GuiControl::IStyleController* Win7Theme::CreateGroupBoxStyle() { return new Win7GroupBoxStyle; } controls::GuiTab::IStyleController* Win7Theme::CreateTabStyle() { return new Win7TabStyle; } controls::GuiComboBoxListControl::IStyleController* Win7Theme::CreateComboBoxStyle() { return new Win7DropDownComboBoxStyle; } controls::GuiScrollView::IStyleProvider* Win7Theme::CreateMultilineTextBoxStyle() { return new Win7MultilineTextBoxProvider; } controls::GuiSinglelineTextBox::IStyleProvider* Win7Theme::CreateTextBoxStyle() { return new Win7SinglelineTextBoxProvider; } elements::text::ColorEntry Win7Theme::GetDefaultTextBoxColorEntry() { return Win7GetTextBoxTextColor(); } controls::GuiDocumentViewer::IStyleProvider* Win7Theme::CreateDocumentViewerStyle() { return new Win7DocumentViewerStyle; } controls::GuiDocumentLabel::IStyleController* Win7Theme::CreateDocumentLabelStyle() { return new Win7DocumentLabelStyle; } controls::GuiDocumentLabel::IStyleController* Win7Theme::CreateDocumentTextBoxStyle() { return new Win7DocumentTextBoxStyle; } controls::GuiListView::IStyleProvider* Win7Theme::CreateListViewStyle() { return new Win7ListViewProvider; } controls::GuiTreeView::IStyleProvider* Win7Theme::CreateTreeViewStyle() { return new Win7TreeViewProvider; } controls::GuiSelectableButton::IStyleController* Win7Theme::CreateListItemBackgroundStyle() { return new Win7SelectableItemStyle(); } controls::GuiToolstripMenu::IStyleController* Win7Theme::CreateMenuStyle() { return new Win7MenuStyle; } controls::GuiToolstripMenuBar::IStyleController* Win7Theme::CreateMenuBarStyle() { return new Win7MenuBarStyle; } controls::GuiControl::IStyleController* Win7Theme::CreateMenuSplitterStyle() { return new Win7MenuSplitterStyle; } controls::GuiToolstripButton::IStyleController* Win7Theme::CreateMenuBarButtonStyle() { return new Win7MenuBarButtonStyle; } controls::GuiToolstripButton::IStyleController* Win7Theme::CreateMenuItemButtonStyle() { return new Win7MenuItemButtonStyle; } controls::GuiControl::IStyleController* Win7Theme::CreateToolBarStyle() { return new Win7ToolstripToolBarStyle; } controls::GuiToolstripButton::IStyleController* Win7Theme::CreateToolBarButtonStyle() { return new Win7ToolstripButtonStyle(Win7ToolstripButtonStyle::CommandButton); } controls::GuiToolstripButton::IStyleController* Win7Theme::CreateToolBarDropdownButtonStyle() { return new Win7ToolstripButtonStyle(Win7ToolstripButtonStyle::DropdownButton); } controls::GuiToolstripButton::IStyleController* Win7Theme::CreateToolBarSplitButtonStyle() { return new Win7ToolstripButtonStyle(Win7ToolstripButtonStyle::SplitButton); } controls::GuiControl::IStyleController* Win7Theme::CreateToolBarSplitterStyle() { return new Win7ToolstripSplitterStyle; } controls::GuiButton::IStyleController* Win7Theme::CreateButtonStyle() { return new Win7ButtonStyle; } controls::GuiSelectableButton::IStyleController* Win7Theme::CreateCheckBoxStyle() { return new Win7CheckBoxStyle(Win7CheckBoxStyle::CheckBox); } controls::GuiSelectableButton::IStyleController* Win7Theme::CreateRadioButtonStyle() { return new Win7CheckBoxStyle(Win7CheckBoxStyle::RadioButton); } controls::GuiDatePicker::IStyleProvider* Win7Theme::CreateDatePickerStyle() { return new Win7DatePickerStyle; } controls::GuiScroll::IStyleController* Win7Theme::CreateHScrollStyle() { return new Win7ScrollStyle(Win7ScrollStyle::Horizontal); } controls::GuiScroll::IStyleController* Win7Theme::CreateVScrollStyle() { return new Win7ScrollStyle(Win7ScrollStyle::Vertical); } controls::GuiScroll::IStyleController* Win7Theme::CreateHTrackerStyle() { return new Win7TrackStyle(Win7TrackStyle::Horizontal); } controls::GuiScroll::IStyleController* Win7Theme::CreateVTrackerStyle() { return new Win7TrackStyle(Win7TrackStyle::Vertical); } controls::GuiScroll::IStyleController* Win7Theme::CreateProgressBarStyle() { return new Win7ProgressBarStyle; } vint Win7Theme::GetScrollDefaultSize() { return Win7ScrollStyle::DefaultSize; } vint Win7Theme::GetTrackerDefaultSize() { return Win7TrackStyle::HandleLong; } controls::GuiVirtualTextList::IStyleProvider* Win7Theme::CreateTextListStyle() { return new Win7TextListProvider; } controls::list::TextItemStyleProvider::IBulletFactory* Win7Theme::CreateTextListItemStyle() { return new Win7TextListItemProvider; } controls::list::TextItemStyleProvider::IBulletFactory* Win7Theme::CreateCheckTextListItemStyle() { return new Win7CheckTextListItemProvider; } controls::list::TextItemStyleProvider::IBulletFactory* Win7Theme::CreateRadioTextListItemStyle() { return new Win7RadioTextListItemProvider; } } } } /*********************************************************************** CONTROLS\STYLES\GUIWIN8STYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win8Theme ***********************************************************************/ Win8Theme::Win8Theme() { } Win8Theme::~Win8Theme() { } controls::GuiWindow::IStyleController* Win8Theme::CreateWindowStyle() { return new Win8WindowStyle; } controls::GuiCustomControl::IStyleController* Win8Theme::CreateCustomControlStyle() { return new GuiCustomControl::EmptyStyleController; } controls::GuiTooltip::IStyleController* Win8Theme::CreateTooltipStyle() { return new Win8TooltipStyle; } controls::GuiLabel::IStyleController* Win8Theme::CreateLabelStyle() { return new Win8LabelStyle(false); } controls::GuiLabel::IStyleController* Win8Theme::CreateShortcutKeyStyle() { return new Win8LabelStyle(true); } controls::GuiScrollContainer::IStyleProvider* Win8Theme::CreateScrollContainerStyle() { return new Win8ScrollViewProvider; } controls::GuiControl::IStyleController* Win8Theme::CreateGroupBoxStyle() { return new Win8GroupBoxStyle; } controls::GuiTab::IStyleController* Win8Theme::CreateTabStyle() { return new Win8TabStyle; } controls::GuiComboBoxListControl::IStyleController* Win8Theme::CreateComboBoxStyle() { return new Win8DropDownComboBoxStyle; } controls::GuiScrollView::IStyleProvider* Win8Theme::CreateMultilineTextBoxStyle() { return new Win8MultilineTextBoxProvider; } controls::GuiSinglelineTextBox::IStyleProvider* Win8Theme::CreateTextBoxStyle() { return new Win8SinglelineTextBoxProvider; } elements::text::ColorEntry Win8Theme::GetDefaultTextBoxColorEntry() { return Win8GetTextBoxTextColor(); } controls::GuiDocumentViewer::IStyleProvider* Win8Theme::CreateDocumentViewerStyle() { return new Win8DocumentViewerStyle; } controls::GuiDocumentLabel::IStyleController* Win8Theme::CreateDocumentLabelStyle() { return new Win8DocumentLabelStyle; } controls::GuiDocumentLabel::IStyleController* Win8Theme::CreateDocumentTextBoxStyle() { return new Win8DocumentTextBoxStyle; } controls::GuiListView::IStyleProvider* Win8Theme::CreateListViewStyle() { return new Win8ListViewProvider; } controls::GuiTreeView::IStyleProvider* Win8Theme::CreateTreeViewStyle() { return new Win8TreeViewProvider; } controls::GuiSelectableButton::IStyleController* Win8Theme::CreateListItemBackgroundStyle() { return new Win8SelectableItemStyle(); } controls::GuiToolstripMenu::IStyleController* Win8Theme::CreateMenuStyle() { return new Win8MenuStyle; } controls::GuiToolstripMenuBar::IStyleController* Win8Theme::CreateMenuBarStyle() { return new Win8MenuBarStyle; } controls::GuiControl::IStyleController* Win8Theme::CreateMenuSplitterStyle() { return new Win8MenuSplitterStyle; } controls::GuiToolstripButton::IStyleController* Win8Theme::CreateMenuBarButtonStyle() { return new Win8MenuBarButtonStyle; } controls::GuiToolstripButton::IStyleController* Win8Theme::CreateMenuItemButtonStyle() { return new Win8MenuItemButtonStyle; } controls::GuiControl::IStyleController* Win8Theme::CreateToolBarStyle() { return new Win8ToolstripToolBarStyle; } controls::GuiToolstripButton::IStyleController* Win8Theme::CreateToolBarButtonStyle() { return new Win8ToolstripButtonStyle(Win8ToolstripButtonStyle::CommandButton); } controls::GuiToolstripButton::IStyleController* Win8Theme::CreateToolBarDropdownButtonStyle() { return new Win8ToolstripButtonStyle(Win8ToolstripButtonStyle::DropdownButton); } controls::GuiToolstripButton::IStyleController* Win8Theme::CreateToolBarSplitButtonStyle() { return new Win8ToolstripButtonStyle(Win8ToolstripButtonStyle::SplitButton); } controls::GuiControl::IStyleController* Win8Theme::CreateToolBarSplitterStyle() { return new Win8ToolstripSplitterStyle; } controls::GuiButton::IStyleController* Win8Theme::CreateButtonStyle() { return new Win8ButtonStyle; } controls::GuiSelectableButton::IStyleController* Win8Theme::CreateCheckBoxStyle() { return new Win8CheckBoxStyle(Win8CheckBoxStyle::CheckBox); } controls::GuiSelectableButton::IStyleController* Win8Theme::CreateRadioButtonStyle() { return new Win8CheckBoxStyle(Win8CheckBoxStyle::RadioButton); } controls::GuiDatePicker::IStyleProvider* Win8Theme::CreateDatePickerStyle() { return new Win8DatePickerStyle; } controls::GuiScroll::IStyleController* Win8Theme::CreateHScrollStyle() { return new Win8ScrollStyle(common_styles::CommonScrollStyle::Horizontal); } controls::GuiScroll::IStyleController* Win8Theme::CreateVScrollStyle() { return new Win8ScrollStyle(common_styles::CommonScrollStyle::Vertical); } controls::GuiScroll::IStyleController* Win8Theme::CreateHTrackerStyle() { return new Win8TrackStyle(common_styles::CommonTrackStyle::Horizontal); } controls::GuiScroll::IStyleController* Win8Theme::CreateVTrackerStyle() { return new Win8TrackStyle(common_styles::CommonTrackStyle::Vertical); } controls::GuiScroll::IStyleController* Win8Theme::CreateProgressBarStyle() { return new Win8ProgressBarStyle; } vint Win8Theme::GetScrollDefaultSize() { return Win8ScrollStyle::DefaultSize; } vint Win8Theme::GetTrackerDefaultSize() { return Win8TrackStyle::HandleLong; } controls::GuiVirtualTextList::IStyleProvider* Win8Theme::CreateTextListStyle() { return new Win8TextListProvider; } controls::list::TextItemStyleProvider::IBulletFactory* Win8Theme::CreateTextListItemStyle() { return new Win8TextListItemProvider; } controls::list::TextItemStyleProvider::IBulletFactory* Win8Theme::CreateCheckTextListItemStyle() { return new Win8CheckTextListItemProvider; } controls::list::TextItemStyleProvider::IBulletFactory* Win8Theme::CreateRadioTextListItemStyle() { return new Win8RadioTextListItemProvider; } } } } /*********************************************************************** CONTROLS\STYLES\WIN7STYLES\GUIWIN7BUTTONSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7ButtonStyleBase ***********************************************************************/ IMPLEMENT_TRANSFERRING_ANIMATION(Win7ButtonColors, Win7ButtonStyleBase) { colorCurrent=Win7ButtonColors::Blend(colorBegin, colorEnd, currentPosition, totalLength); style->elements.Apply(colorCurrent); style->AfterApplyColors(colorCurrent); } void Win7ButtonStyleBase::AfterApplyColors(const Win7ButtonColors& colors) { } Win7ButtonStyleBase::Win7ButtonStyleBase(bool verticalGradient, bool roundBorder, const Win7ButtonColors& initialColor, Alignment horizontal, Alignment vertical) :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) ,transparentWhenInactive(false) ,transparentWhenDisabled(false) { elements=Win7ButtonElements::Create(verticalGradient, roundBorder, horizontal, vertical); elements.Apply(initialColor); transferringAnimation=new TransferringAnimation(this, initialColor); } Win7ButtonStyleBase::~Win7ButtonStyleBase() { transferringAnimation->Disable(); } compositions::GuiBoundsComposition* Win7ButtonStyleBase::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win7ButtonStyleBase::GetContainerComposition() { return elements.mainComposition; } void Win7ButtonStyleBase::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7ButtonStyleBase::SetText(const WString& value) { elements.textElement->SetText(value); } void Win7ButtonStyleBase::SetFont(const FontProperties& value) { Win7SetFont(elements.textElement, elements.textComposition, value); } void Win7ButtonStyleBase::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win7ButtonStyleBase::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win7ButtonStyleBase::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } bool Win7ButtonStyleBase::GetTransparentWhenInactive() { return transparentWhenInactive; } void Win7ButtonStyleBase::SetTransparentWhenInactive(bool value) { transparentWhenInactive=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } bool Win7ButtonStyleBase::GetTransparentWhenDisabled() { return transparentWhenDisabled; } void Win7ButtonStyleBase::SetTransparentWhenDisabled(bool value) { transparentWhenDisabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } bool Win7ButtonStyleBase::GetAutoSizeForText() { return elements.textComposition->GetMinSizeLimitation()!=GuiGraphicsComposition::NoLimit; } void Win7ButtonStyleBase::SetAutoSizeForText(bool value) { if(value) { elements.textComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); } else { elements.textComposition->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } } /*********************************************************************** Win7ButtonStyle ***********************************************************************/ void Win7ButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { Win7ButtonColors targetColor; if(enabled) { switch(value) { case GuiButton::Normal: targetColor=Win7ButtonColors::ButtonNormal(); if(transparentWhenInactive) { targetColor.SetAlphaWithoutText(0); } break; case GuiButton::Active: targetColor=Win7ButtonColors::ButtonActive(); break; case GuiButton::Pressed: targetColor=Win7ButtonColors::ButtonPressed(); break; } } else { targetColor=Win7ButtonColors::ButtonDisabled(); if(transparentWhenDisabled) { targetColor.SetAlphaWithoutText(0); } } transferringAnimation->Transfer(targetColor); } Win7ButtonStyle::Win7ButtonStyle(bool verticalGradient) :Win7ButtonStyleBase(verticalGradient, true, Win7ButtonColors::ButtonNormal(), Alignment::Center, Alignment::Center) { } Win7ButtonStyle::~Win7ButtonStyle() { } /*********************************************************************** Win7CheckBoxStyle ***********************************************************************/ IMPLEMENT_TRANSFERRING_ANIMATION(Win7ButtonColors, Win7CheckBoxStyle) { colorCurrent=Win7ButtonColors::Blend(colorBegin, colorEnd, currentPosition, totalLength); style->elements.Apply(colorCurrent); } void Win7CheckBoxStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { if(enabled) { switch(value) { case GuiButton::Normal: transferringAnimation->Transfer(Win7ButtonColors::CheckedNormal(selected)); break; case GuiButton::Active: transferringAnimation->Transfer(Win7ButtonColors::CheckedActive(selected)); break; case GuiButton::Pressed: transferringAnimation->Transfer(Win7ButtonColors::CheckedPressed(selected)); break; } } else { transferringAnimation->Transfer(Win7ButtonColors::CheckedDisabled(selected)); } } Win7CheckBoxStyle::Win7CheckBoxStyle(BulletStyle bulletStyle, bool backgroundVisible) :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) { Win7ButtonColors initialColor=Win7ButtonColors::CheckedNormal(isSelected); elements=Win7CheckedButtonElements::Create(bulletStyle==CheckBox?ElementShape::Rectangle:ElementShape::Ellipse, backgroundVisible); elements.Apply(initialColor); transferringAnimation=new TransferringAnimation(this, initialColor); } Win7CheckBoxStyle::~Win7CheckBoxStyle() { transferringAnimation->Disable(); } compositions::GuiBoundsComposition* Win7CheckBoxStyle::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win7CheckBoxStyle::GetContainerComposition() { return elements.mainComposition; } void Win7CheckBoxStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7CheckBoxStyle::SetText(const WString& value) { elements.textElement->SetText(value); } void Win7CheckBoxStyle::SetFont(const FontProperties& value) { Win7SetFont(elements.textElement, elements.textComposition, value); } void Win7CheckBoxStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win7CheckBoxStyle::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win7CheckBoxStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } } } } /*********************************************************************** CONTROLS\STYLES\WIN7STYLES\GUIWIN7CONTROLSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7EmptyStyle ***********************************************************************/ Win7EmptyStyle::Win7EmptyStyle(Color color) { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(color); boundsComposition=new GuiBoundsComposition; boundsComposition->SetOwnedElement(element); } Win7EmptyStyle::~Win7EmptyStyle() { } compositions::GuiBoundsComposition* Win7EmptyStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7EmptyStyle::GetContainerComposition() { return boundsComposition; } void Win7EmptyStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7EmptyStyle::SetText(const WString& value) { } void Win7EmptyStyle::SetFont(const FontProperties& value) { } void Win7EmptyStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win7WindowStyle ***********************************************************************/ Win7WindowStyle::Win7WindowStyle() { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win7GetSystemWindowColor()); boundsComposition=new GuiBoundsComposition; boundsComposition->SetOwnedElement(element); } Win7WindowStyle::~Win7WindowStyle() { } compositions::GuiBoundsComposition* Win7WindowStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7WindowStyle::GetContainerComposition() { return boundsComposition; } void Win7WindowStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7WindowStyle::SetText(const WString& value) { } void Win7WindowStyle::SetFont(const FontProperties& value) { } void Win7WindowStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win7TooltipStyle ***********************************************************************/ Win7TooltipStyle::Win7TooltipStyle() { boundsComposition=new GuiBoundsComposition; boundsComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Color(100, 100, 100)); boundsComposition->SetOwnedElement(element); } containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(1, 1, 1, 1)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Color(255, 255, 225)); containerComposition->SetOwnedElement(element); } } Win7TooltipStyle::~Win7TooltipStyle() { } compositions::GuiBoundsComposition* Win7TooltipStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7TooltipStyle::GetContainerComposition() { return containerComposition; } void Win7TooltipStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7TooltipStyle::SetText(const WString& value) { } void Win7TooltipStyle::SetFont(const FontProperties& value) { } void Win7TooltipStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win7LabelStyle ***********************************************************************/ Win7LabelStyle::Win7LabelStyle(bool forShortcutKey) { textElement=GuiSolidLabelElement::Create(); textElement->SetColor(GetDefaultTextColor()); boundsComposition=new GuiBoundsComposition; boundsComposition->SetMinSizeLimitation(GuiBoundsComposition::LimitToElementAndChildren); if (forShortcutKey) { { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Color(100, 100, 100)); boundsComposition->SetOwnedElement(element); } auto containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(1, 1, 1, 1)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Color(255, 255, 225)); containerComposition->SetOwnedElement(element); } auto labelComposition = new GuiBoundsComposition; labelComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); labelComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); labelComposition->SetOwnedElement(textElement); containerComposition->AddChild(labelComposition); } else { boundsComposition->SetOwnedElement(textElement); } } Win7LabelStyle::~Win7LabelStyle() { } compositions::GuiBoundsComposition* Win7LabelStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7LabelStyle::GetContainerComposition() { return boundsComposition; } void Win7LabelStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7LabelStyle::SetText(const WString& value) { textElement->SetText(value); } void Win7LabelStyle::SetFont(const FontProperties& value) { textElement->SetFont(value); } void Win7LabelStyle::SetVisuallyEnabled(bool value) { } Color Win7LabelStyle::GetDefaultTextColor() { return Win7GetSystemTextColor(true); } void Win7LabelStyle::SetTextColor(Color value) { textElement->SetColor(value); } /*********************************************************************** Win7GroupBoxStyle ***********************************************************************/ IMPLEMENT_TRANSFERRING_ANIMATION(Color, Win7GroupBoxStyle) { colorCurrent=BlendColor(colorBegin, colorEnd, currentPosition, totalLength); style->textElement->SetColor(colorCurrent); } void Win7GroupBoxStyle::SetMargins(vint fontSize) { fontSize+=4; vint half=fontSize/2; sinkBorderComposition->SetAlignmentToParent(Margin(0, half, 1, 1)); raisedBorderComposition->SetAlignmentToParent(Margin(1, half+1, 0, 0)); containerComposition->SetAlignmentToParent(Margin(2, fontSize, 2, 2)); textBackgroundComposition->SetAlignmentToParent(Margin(half, 2, -1, -1)); } Win7GroupBoxStyle::Win7GroupBoxStyle() { boundsComposition=new GuiBoundsComposition; { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win7GetSystemWindowColor()); boundsComposition->SetOwnedElement(element); boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } sinkBorderComposition=new GuiBoundsComposition; { GuiRoundBorderElement* element=GuiRoundBorderElement::Create(); element->SetRadius(3); element->SetColor(Color(213, 223, 229)); sinkBorderComposition->SetOwnedElement(element); boundsComposition->AddChild(sinkBorderComposition); } raisedBorderComposition=new GuiBoundsComposition; { GuiRoundBorderElement* element=GuiRoundBorderElement::Create(); element->SetRadius(3); element->SetColor(Color(255, 255, 255)); raisedBorderComposition->SetOwnedElement(element); boundsComposition->AddChild(raisedBorderComposition); } textBackgroundComposition=new GuiBoundsComposition; { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win7GetSystemWindowColor()); textBackgroundComposition->SetOwnedElement(element); textBackgroundComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(textBackgroundComposition); } textComposition=new GuiBoundsComposition; { GuiSolidLabelElement* element=GuiSolidLabelElement::Create(); element->SetColor(Win7GetSystemTextColor(true)); textElement=element; textComposition->SetOwnedElement(element); textComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); textComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); textBackgroundComposition->AddChild(textComposition); } containerComposition=new GuiBoundsComposition; { boundsComposition->AddChild(containerComposition); } SetMargins(0); transferringAnimation=new TransferringAnimation(this, Win7GetSystemTextColor(true)); } Win7GroupBoxStyle::~Win7GroupBoxStyle() { transferringAnimation->Disable(); } compositions::GuiBoundsComposition* Win7GroupBoxStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7GroupBoxStyle::GetContainerComposition() { return containerComposition; } void Win7GroupBoxStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7GroupBoxStyle::SetText(const WString& value) { textElement->SetText(value); } void Win7GroupBoxStyle::SetFont(const FontProperties& value) { textElement->SetFont(value); SetMargins(value.size); } void Win7GroupBoxStyle::SetVisuallyEnabled(bool value) { if(value) { transferringAnimation->Transfer(Win7GetSystemTextColor(true)); } else { transferringAnimation->Transfer(Win7GetSystemTextColor(false)); } } /*********************************************************************** Win7DatePickerStyle ***********************************************************************/ Win7DatePickerStyle::Win7DatePickerStyle() { } Win7DatePickerStyle::~Win7DatePickerStyle() { } void Win7DatePickerStyle::AssociateStyleController(controls::GuiControl::IStyleController* controller) { } void Win7DatePickerStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7DatePickerStyle::SetText(const WString& value) { } void Win7DatePickerStyle::SetFont(const FontProperties& value) { } void Win7DatePickerStyle::SetVisuallyEnabled(bool value) { } controls::GuiSelectableButton::IStyleController* Win7DatePickerStyle::CreateDateButtonStyle() { return new Win7SelectableItemStyle; } controls::GuiTextList* Win7DatePickerStyle::CreateTextList() { return new GuiTextList(new Win7TextListProvider, new Win7TextListItemProvider); } controls::GuiComboBoxListControl::IStyleController* Win7DatePickerStyle::CreateComboBoxStyle() { return new Win7DropDownComboBoxStyle; } Color Win7DatePickerStyle::GetBackgroundColor() { return Win7GetSystemWindowColor(); } Color Win7DatePickerStyle::GetPrimaryTextColor() { return Win7GetSystemTextColor(true); } Color Win7DatePickerStyle::GetSecondaryTextColor() { return Win7GetSystemTextColor(false); } } } } /*********************************************************************** CONTROLS\STYLES\WIN7STYLES\GUIWIN7LISTSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7SelectableItemStyle ***********************************************************************/ void Win7SelectableItemStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { if(!enabled) { transferringAnimation->Transfer(Win7ButtonColors::ItemDisabled()); } else if(selected) { transferringAnimation->Transfer(Win7ButtonColors::ItemSelected()); } else { switch(value) { case GuiButton::Normal: transferringAnimation->Transfer(Win7ButtonColors::ItemNormal()); break; case GuiButton::Active: transferringAnimation->Transfer(Win7ButtonColors::ItemActive()); break; case GuiButton::Pressed: transferringAnimation->Transfer(Win7ButtonColors::ItemSelected()); break; } } } Win7SelectableItemStyle::Win7SelectableItemStyle() :Win7ButtonStyleBase(true, true, Win7ButtonColors::ItemNormal(), Alignment::Left, Alignment::Center) { transferringAnimation->SetEnableAnimation(false); } Win7SelectableItemStyle::~Win7SelectableItemStyle() { } /*********************************************************************** Win7ListViewColumnDropDownStyle ***********************************************************************/ void Win7ListViewColumnDropDownStyle::TransferInternal(controls::GuiButton::ControlState value, bool enabled, bool selected) { if(!enabled) value=GuiButton::Normal; switch(value) { case GuiButton::Normal: { leftBorderComposition->SetVisible(true); borderComposition->SetVisible(false); gradientComposition->SetVisible(false); leftBorderElement->SetColors(Color(223, 234, 247), Color(252, 252, 252)); } break; case GuiButton::Active: case GuiButton::Pressed: { leftBorderComposition->SetVisible(false); borderComposition->SetVisible(true); gradientComposition->SetVisible(true); borderElement->SetColor(Color(192, 203, 217)); gradientElement->SetColors(Color(230, 241, 255), Color(224, 226, 253)); } break; } } Win7ListViewColumnDropDownStyle::Win7ListViewColumnDropDownStyle() :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) { mainComposition=new GuiBoundsComposition; mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); leftBorderElement=GuiGradientBackgroundElement::Create(); leftBorderElement->SetDirection(GuiGradientBackgroundElement::Vertical); leftBorderComposition=new GuiBoundsComposition; leftBorderComposition->SetOwnedElement(leftBorderElement); leftBorderComposition->SetAlignmentToParent(Margin(0, 1, -1, 1)); leftBorderComposition->SetPreferredMinSize(Size(1, 1)); mainComposition->AddChild(leftBorderComposition); borderElement=GuiSolidBorderElement::Create(); borderComposition=new GuiBoundsComposition; borderComposition->SetOwnedElement(borderElement); borderComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); mainComposition->AddChild(borderComposition); gradientElement=GuiGradientBackgroundElement::Create(); gradientElement->SetDirection(GuiGradientBackgroundElement::Vertical); gradientComposition=new GuiBoundsComposition; gradientComposition->SetOwnedElement(gradientElement); gradientComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); gradientComposition->SetPreferredMinSize(Size(0, 4)); mainComposition->AddChild(gradientComposition); arrowElement=common_styles::CommonFragmentBuilder::BuildDownArrow(); arrowElement->SetBackgroundColor(Color(76, 96, 122)); arrowElement->SetBorderColor(Color(76, 96, 122)); arrowComposition=new GuiBoundsComposition; arrowComposition->SetOwnedElement(arrowElement); arrowComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); arrowComposition->SetAlignmentToParent(Margin(3, 3, 3, 3)); mainComposition->AddChild(arrowComposition); TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } Win7ListViewColumnDropDownStyle::~Win7ListViewColumnDropDownStyle() { } compositions::GuiBoundsComposition* Win7ListViewColumnDropDownStyle::GetBoundsComposition() { return mainComposition; } compositions::GuiGraphicsComposition* Win7ListViewColumnDropDownStyle::GetContainerComposition() { return mainComposition; } void Win7ListViewColumnDropDownStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7ListViewColumnDropDownStyle::SetText(const WString& value) { } void Win7ListViewColumnDropDownStyle::SetFont(const FontProperties& value) { } void Win7ListViewColumnDropDownStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win7ListViewColumnDropDownStyle::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win7ListViewColumnDropDownStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } /*********************************************************************** Win7ListViewColumnHeaderStyle ***********************************************************************/ void Win7ListViewColumnHeaderStyle::TransferInternal(controls::GuiButton::ControlState value, bool enabled, bool subMenuExisting, bool subMenuOpening) { if(!enabled) value=GuiButton::Normal; switch(value) { case GuiButton::Normal: { rightBorderComposition->SetVisible(true); borderComposition->SetVisible(false); gradientComposition->SetVisible(false); backgroundElement->SetColor(Color(252, 252, 252)); rightBorderElement->SetColors(Color(223, 234, 247), Color(252, 252, 252)); dropdownButton->SetVisible(subMenuOpening); } break; case GuiButton::Active: { rightBorderComposition->SetVisible(false); borderComposition->SetVisible(true); gradientComposition->SetVisible(true); gradientComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); backgroundElement->SetColor(Color(252, 252, 252)); borderElement->SetColor(Color(223, 233, 246)); gradientElement->SetColors(Color(243, 248, 253), Color(239, 243, 249)); dropdownButton->SetVisible(isSubMenuExisting); } break; case GuiButton::Pressed: { rightBorderComposition->SetVisible(false); borderComposition->SetVisible(true); gradientComposition->SetVisible(true); gradientComposition->SetAlignmentToParent(Margin(1, 0, 1, -1)); backgroundElement->SetColor(Color(246, 247, 248)); borderElement->SetColor(Color(192, 203, 217)); gradientElement->SetColors(Color(193, 204, 218), Color(252, 252, 252)); dropdownButton->SetVisible(isSubMenuExisting); } break; } } Win7ListViewColumnHeaderStyle::Win7ListViewColumnHeaderStyle() :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSubMenuExisting(false) ,isSubMenuOpening(false) { backgroundElement=GuiSolidBackgroundElement::Create(); mainComposition=new GuiBoundsComposition; mainComposition->SetOwnedElement(backgroundElement); mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); rightBorderElement=GuiGradientBackgroundElement::Create(); rightBorderElement->SetDirection(GuiGradientBackgroundElement::Vertical); rightBorderComposition=new GuiBoundsComposition; rightBorderComposition->SetOwnedElement(rightBorderElement); rightBorderComposition->SetAlignmentToParent(Margin(-1, 0, 0, 0)); rightBorderComposition->SetPreferredMinSize(Size(1, 1)); mainComposition->AddChild(rightBorderComposition); borderElement=GuiSolidBorderElement::Create(); borderComposition=new GuiBoundsComposition; borderComposition->SetOwnedElement(borderElement); borderComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); mainComposition->AddChild(borderComposition); gradientElement=GuiGradientBackgroundElement::Create(); gradientElement->SetDirection(GuiGradientBackgroundElement::Vertical); gradientComposition=new GuiBoundsComposition; gradientComposition->SetOwnedElement(gradientElement); gradientComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); gradientComposition->SetPreferredMinSize(Size(0, 4)); mainComposition->AddChild(gradientComposition); textElement=GuiSolidLabelElement::Create(); textElement->SetColor(Color(76, 96, 122)); textComposition=new GuiBoundsComposition; textComposition->SetOwnedElement(textElement); textComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); textComposition->SetAlignmentToParent(Margin(15, 7, 18, 5)); mainComposition->AddChild(textComposition); arrowElement=GuiPolygonElement::Create(); arrowElement->SetBackgroundColor(Color(76, 96, 122)); arrowElement->SetBorderColor(Color(76, 96, 122)); arrowComposition=new GuiBoundsComposition; arrowComposition->SetOwnedElement(arrowElement); arrowComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); arrowComposition->SetAlignmentToParent(Margin(0, 2, 0, -1)); mainComposition->AddChild(arrowComposition); dropdownButton=new GuiButton(new Win7ListViewColumnDropDownStyle); dropdownButton->GetBoundsComposition()->SetAlignmentToParent(Margin(-1, 0, 0, 0)); dropdownButton->SetVisible(false); mainComposition->AddChild(dropdownButton->GetBoundsComposition()); TransferInternal(controlStyle, isVisuallyEnabled, isSubMenuExisting, isSubMenuOpening); } Win7ListViewColumnHeaderStyle::~Win7ListViewColumnHeaderStyle() { } compositions::GuiBoundsComposition* Win7ListViewColumnHeaderStyle::GetBoundsComposition() { return mainComposition; } compositions::GuiGraphicsComposition* Win7ListViewColumnHeaderStyle::GetContainerComposition() { return mainComposition; } void Win7ListViewColumnHeaderStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7ListViewColumnHeaderStyle::SetText(const WString& value) { textElement->SetText(value); } void Win7ListViewColumnHeaderStyle::SetFont(const FontProperties& value) { textElement->SetFont(value); } void Win7ListViewColumnHeaderStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSubMenuExisting, isSubMenuOpening); } } void Win7ListViewColumnHeaderStyle::SetSelected(bool value) { } void Win7ListViewColumnHeaderStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSubMenuExisting, isSubMenuOpening); } } controls::GuiMenu::IStyleController* Win7ListViewColumnHeaderStyle::CreateSubMenuStyleController() { return new Win7MenuStyle; } void Win7ListViewColumnHeaderStyle::SetSubMenuExisting(bool value) { if(isSubMenuExisting!=value) { isSubMenuExisting=value; TransferInternal(controlStyle, isVisuallyEnabled, isSubMenuExisting, isSubMenuOpening); } } void Win7ListViewColumnHeaderStyle::SetSubMenuOpening(bool value) { if(isSubMenuOpening!=value) { isSubMenuOpening=value; TransferInternal(controlStyle, isVisuallyEnabled, isSubMenuExisting, isSubMenuOpening); } } controls::GuiButton* Win7ListViewColumnHeaderStyle::GetSubMenuHost() { return dropdownButton; } void Win7ListViewColumnHeaderStyle::SetImage(Ptr value) { } void Win7ListViewColumnHeaderStyle::SetShortcutText(const WString& value) { } void Win7ListViewColumnHeaderStyle::SetColumnSortingState(controls::GuiListViewColumnHeader::ColumnSortingState value) { Margin margin=arrowComposition->GetAlignmentToParent(); switch(value) { case controls::GuiListViewColumnHeader::NotSorted: arrowElement->SetPoints(0, 0); break; case controls::GuiListViewColumnHeader::Ascending: common_styles::CommonFragmentBuilder::FillUpArrow(arrowElement); break; case controls::GuiListViewColumnHeader::Descending: common_styles::CommonFragmentBuilder::FillDownArrow(arrowElement); break; } } /*********************************************************************** Win7TreeViewExpandingButtonStyle ***********************************************************************/ void Win7TreeViewExpandingButtonStyle::TransferInternal(controls::GuiButton::ControlState value, bool enabled, bool selected) { bool expanding=false; bool activated=false; if(isVisuallyEnabled) { expanding=selected; activated=value!=GuiButton::Normal; } Point points[3]; if(expanding) { points[0]=Point(5, 2); points[1]=Point(5, 7); points[2]=Point(0, 7); } else { points[0]=Point(0, 1); points[1]=Point(4, 5); points[2]=Point(0, 9); } polygonElement->SetPoints(points, sizeof(points)/sizeof(*points)); if(activated) { polygonElement->SetBorderColor(Color(28, 196, 247)); polygonElement->SetBackgroundColor(Color(130, 223, 251)); } else if(expanding) { polygonElement->SetBorderColor(Color(38, 38, 38)); polygonElement->SetBackgroundColor(Color(89, 89, 89)); } else { polygonElement->SetBorderColor(Color(166, 166, 166)); polygonElement->SetBackgroundColor(Color(255, 255, 255)); } } Win7TreeViewExpandingButtonStyle::Win7TreeViewExpandingButtonStyle() :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) { polygonElement=GuiPolygonElement::Create(); polygonElement->SetSize(Size(6, 11)); mainComposition=new GuiBoundsComposition; mainComposition->SetOwnedElement(polygonElement); mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); TransferInternal(controlStyle, true, isSelected); } Win7TreeViewExpandingButtonStyle::~Win7TreeViewExpandingButtonStyle() { } compositions::GuiBoundsComposition* Win7TreeViewExpandingButtonStyle::GetBoundsComposition() { return mainComposition; } compositions::GuiGraphicsComposition* Win7TreeViewExpandingButtonStyle::GetContainerComposition() { return mainComposition; } void Win7TreeViewExpandingButtonStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7TreeViewExpandingButtonStyle::SetText(const WString& value) { } void Win7TreeViewExpandingButtonStyle::SetFont(const FontProperties& value) { } void Win7TreeViewExpandingButtonStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win7TreeViewExpandingButtonStyle::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win7TreeViewExpandingButtonStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } /*********************************************************************** Win7DropDownComboBoxStyle ***********************************************************************/ void Win7DropDownComboBoxStyle::TransferInternal(controls::GuiButton::ControlState value, bool enabled, bool selected) { Win7ButtonColors targetColor; if(enabled) { if(selected) value=GuiButton::Pressed; switch(value) { case GuiButton::Normal: targetColor=Win7ButtonColors::ButtonNormal(); break; case GuiButton::Active: targetColor=Win7ButtonColors::ButtonActive(); break; case GuiButton::Pressed: targetColor=Win7ButtonColors::ButtonPressed(); break; } } else { targetColor=Win7ButtonColors::ButtonDisabled(); } transferringAnimation->Transfer(targetColor); } void Win7DropDownComboBoxStyle::AfterApplyColors(const Win7ButtonColors& colors) { Win7ButtonStyle::AfterApplyColors(colors); dropDownElement->SetBorderColor(colors.textColor); dropDownElement->SetBackgroundColor(colors.textColor); } Win7DropDownComboBoxStyle::Win7DropDownComboBoxStyle() :Win7ButtonStyle(true) , commandExecutor(0) , textVisible(true) { table=new GuiTableComposition; table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetRowsAndColumns(3, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); elements.textComposition->AddChild(table); elements.textComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); textComposition=new GuiCellComposition; table->AddChild(textComposition); textComposition->SetSite(1, 0, 1, 1); Ptr element=elements.textComposition->GetOwnedElement(); elements.textComposition->SetOwnedElement(0); textComposition->SetOwnedElement(element); elements.textElement->SetEllipse(true); elements.textElement->SetAlignments(Alignment::Left, Alignment::Center); dropDownElement=common_styles::CommonFragmentBuilder::BuildDownArrow(); dropDownComposition=new GuiCellComposition; table->AddChild(dropDownComposition); dropDownComposition->SetSite(1, 1, 1, 1); dropDownComposition->SetOwnedElement(dropDownElement); dropDownComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); dropDownComposition->SetMargin(Margin(3, 0, 3, 0)); } Win7DropDownComboBoxStyle::~Win7DropDownComboBoxStyle() { } compositions::GuiGraphicsComposition* Win7DropDownComboBoxStyle::GetContainerComposition() { return textComposition; } GuiMenu::IStyleController* Win7DropDownComboBoxStyle::CreateSubMenuStyleController() { return new Win7MenuStyle; } void Win7DropDownComboBoxStyle::SetSubMenuExisting(bool value) { } void Win7DropDownComboBoxStyle::SetSubMenuOpening(bool value) { SetSelected(value); } GuiButton* Win7DropDownComboBoxStyle::GetSubMenuHost() { return 0; } void Win7DropDownComboBoxStyle::SetImage(Ptr value) { } void Win7DropDownComboBoxStyle::SetShortcutText(const WString& value) { } void Win7DropDownComboBoxStyle::SetCommandExecutor(controls::GuiComboBoxBase::ICommandExecutor* value) { commandExecutor=value; } void Win7DropDownComboBoxStyle::OnItemSelected() { } void Win7DropDownComboBoxStyle::SetText(const WString& value) { text = value; if (textVisible) { Win7ButtonStyle::SetText(text); } } void Win7DropDownComboBoxStyle::SetTextVisible(bool value) { if (textVisible != value) { if ((textVisible = value)) { Win7ButtonStyle::SetText(text); } else { Win7ButtonStyle::SetText(L""); } } } /*********************************************************************** Win7TextListItemProvider ***********************************************************************/ Win7TextListItemProvider::Win7TextListItemProvider() { } Win7TextListItemProvider::~Win7TextListItemProvider() { } controls::GuiSelectableButton::IStyleController* Win7TextListItemProvider::CreateBulletStyleController() { return 0; } /*********************************************************************** Win7CheckTextListItemProvider ***********************************************************************/ Win7CheckTextListItemProvider::Win7CheckTextListItemProvider() { } Win7CheckTextListItemProvider::~Win7CheckTextListItemProvider() { } controls::GuiSelectableButton::IStyleController* Win7CheckTextListItemProvider::CreateBulletStyleController() { return new Win7CheckBoxStyle(Win7CheckBoxStyle::CheckBox, false); } /*********************************************************************** Win7RadioTextListItemProvider ***********************************************************************/ Win7RadioTextListItemProvider::Win7RadioTextListItemProvider() { } Win7RadioTextListItemProvider::~Win7RadioTextListItemProvider() { } controls::GuiSelectableButton::IStyleController* Win7RadioTextListItemProvider::CreateBulletStyleController() { return new Win7CheckBoxStyle(Win7CheckBoxStyle::RadioButton, false); } /*********************************************************************** Win7TextListProvider ***********************************************************************/ Win7TextListProvider::Win7TextListProvider() { } Win7TextListProvider::~Win7TextListProvider() { } controls::GuiSelectableButton::IStyleController* Win7TextListProvider::CreateItemBackground() { return new Win7SelectableItemStyle; } Color Win7TextListProvider::GetTextColor() { return Win7GetSystemTextColor(true); } /*********************************************************************** Win7ListViewProvider ***********************************************************************/ Win7ListViewProvider::Win7ListViewProvider() { } Win7ListViewProvider::~Win7ListViewProvider() { } controls::GuiSelectableButton::IStyleController* Win7ListViewProvider::CreateItemBackground() { return new Win7SelectableItemStyle; } controls::GuiListViewColumnHeader::IStyleController* Win7ListViewProvider::CreateColumnStyle() { return new Win7ListViewColumnHeaderStyle; } Color Win7ListViewProvider::GetPrimaryTextColor() { return Win7GetSystemTextColor(true); } Color Win7ListViewProvider::GetSecondaryTextColor() { return Win7GetSystemTextColor(false); } Color Win7ListViewProvider::GetItemSeparatorColor() { return Color(220, 220, 220); } /*********************************************************************** Win7TreeViewProvider ***********************************************************************/ Win7TreeViewProvider::Win7TreeViewProvider() { } Win7TreeViewProvider::~Win7TreeViewProvider() { } controls::GuiSelectableButton::IStyleController* Win7TreeViewProvider::CreateItemBackground() { return new Win7SelectableItemStyle; } controls::GuiSelectableButton::IStyleController* Win7TreeViewProvider::CreateItemExpandingDecorator() { return new Win7TreeViewExpandingButtonStyle; } Color Win7TreeViewProvider::GetTextColor() { return Win7GetSystemTextColor(true); } } } } /*********************************************************************** CONTROLS\STYLES\WIN7STYLES\GUIWIN7MENUSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7MenuStyle ***********************************************************************/ Win7MenuStyle::Win7MenuStyle() { { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Color(151, 151, 151)); boundsComposition=new GuiBoundsComposition; boundsComposition->SetOwnedElement(element); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Color(245, 245, 245)); GuiBoundsComposition* subBorder=new GuiBoundsComposition; subBorder->SetOwnedElement(element); subBorder->SetAlignmentToParent(Margin(1, 1, 1, 1)); boundsComposition->AddChild(subBorder); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win7GetSystemWindowColor()); containerComposition=new GuiBoundsComposition; containerComposition->SetOwnedElement(element); containerComposition->SetAlignmentToParent(Margin(3, 3, 3, 3)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); } } Win7MenuStyle::~Win7MenuStyle() { } compositions::GuiBoundsComposition* Win7MenuStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7MenuStyle::GetContainerComposition() { return containerComposition; } void Win7MenuStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7MenuStyle::SetText(const WString& value) { } void Win7MenuStyle::SetFont(const FontProperties& value) { } void Win7MenuStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win7MenuBarStyle ***********************************************************************/ Win7MenuBarStyle::Win7MenuBarStyle() { GuiTableComposition* table=new GuiTableComposition; table->SetAlignmentToParent(Margin(0, 0, 0, 1)); table->SetRowsAndColumns(2, 1); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); { GuiGradientBackgroundElement* gradient=GuiGradientBackgroundElement::Create(); gradient->SetDirection(GuiGradientBackgroundElement::Vertical); gradient->SetColors(Color(252, 253, 254), Color(229, 234, 245)); GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 0, 1, 1); cell->SetOwnedElement(gradient); } { GuiGradientBackgroundElement* gradient=GuiGradientBackgroundElement::Create(); gradient->SetDirection(GuiGradientBackgroundElement::Vertical); gradient->SetColors(Color(212, 219, 237), Color(225, 230, 246)); GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(1, 0, 1, 1); cell->SetOwnedElement(gradient); } boundsComposition=new GuiBoundsComposition; { GuiSolidBackgroundElement* solid=GuiSolidBackgroundElement::Create(); solid->SetColor(Color(182, 188, 204)); boundsComposition->SetOwnedElement(solid); boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } boundsComposition->AddChild(table); } Win7MenuBarStyle::~Win7MenuBarStyle() { } compositions::GuiBoundsComposition* Win7MenuBarStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7MenuBarStyle::GetContainerComposition() { return boundsComposition; } void Win7MenuBarStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7MenuBarStyle::SetText(const WString& value) { } void Win7MenuBarStyle::SetFont(const FontProperties& value) { } void Win7MenuBarStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win7MenuBarButtonStyle ***********************************************************************/ void Win7MenuBarButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool opening) { Win7ButtonColors targetColor; if(!enabled) { targetColor=Win7ButtonColors::MenuBarButtonDisabled(); targetColor.SetAlphaWithoutText(0); } else if(opening) { targetColor=Win7ButtonColors::MenuBarButtonPressed(); } else { switch(value) { case GuiButton::Normal: targetColor=Win7ButtonColors::MenuBarButtonNormal(); targetColor.SetAlphaWithoutText(0); break; case GuiButton::Active: targetColor=Win7ButtonColors::MenuBarButtonActive(); break; case GuiButton::Pressed: targetColor=Win7ButtonColors::MenuBarButtonPressed(); break; } } elements.Apply(targetColor); } Win7MenuBarButtonStyle::Win7MenuBarButtonStyle() :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isOpening(false) { Win7ButtonColors initialColor=Win7ButtonColors::MenuBarButtonNormal(); initialColor.SetAlphaWithoutText(0); elements=Win7ButtonElements::Create(true, true, Alignment::Center, Alignment::Center); elements.Apply(initialColor); } Win7MenuBarButtonStyle::~Win7MenuBarButtonStyle() { } compositions::GuiBoundsComposition* Win7MenuBarButtonStyle::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win7MenuBarButtonStyle::GetContainerComposition() { return elements.mainComposition; } void Win7MenuBarButtonStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7MenuBarButtonStyle::SetText(const WString& value) { elements.textElement->SetText(value); } void Win7MenuBarButtonStyle::SetFont(const FontProperties& value) { Win7SetFont(elements.textElement, elements.textComposition, value); Margin margin=elements.textComposition->GetMargin(); margin.left*=3; margin.right*=3; elements.textComposition->SetMargin(margin); } void Win7MenuBarButtonStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isOpening); } } void Win7MenuBarButtonStyle::SetSelected(bool value) { } controls::GuiMenu::IStyleController* Win7MenuBarButtonStyle::CreateSubMenuStyleController() { return new Win7MenuStyle; } void Win7MenuBarButtonStyle::SetSubMenuExisting(bool value) { } void Win7MenuBarButtonStyle::SetSubMenuOpening(bool value) { if(isOpening!=value) { isOpening=value; TransferInternal(controlStyle, isVisuallyEnabled, isOpening); } } controls::GuiButton* Win7MenuBarButtonStyle::GetSubMenuHost() { return 0; } void Win7MenuBarButtonStyle::SetImage(Ptr value) { } void Win7MenuBarButtonStyle::SetShortcutText(const WString& value) { } void Win7MenuBarButtonStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isOpening); } } /*********************************************************************** Win7MenuItemButtonStyle ***********************************************************************/ void Win7MenuItemButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected, bool opening) { Win7ButtonColors targetColor; bool active=false; if(enabled) { if(opening) { targetColor=Win7ButtonColors::MenuItemButtonNormalActive(); active=true; } else { switch(value) { case GuiButton::Normal: targetColor=selected?Win7ButtonColors::MenuItemButtonSelected():Win7ButtonColors::MenuItemButtonNormal(); break; case GuiButton::Active: case GuiButton::Pressed: targetColor=selected?Win7ButtonColors::MenuItemButtonSelectedActive():Win7ButtonColors::MenuItemButtonNormalActive(); active=true; break; } } } else { switch(value) { case GuiButton::Normal: targetColor=Win7ButtonColors::MenuItemButtonDisabled(); break; case GuiButton::Active: case GuiButton::Pressed: targetColor=Win7ButtonColors::MenuItemButtonDisabledActive(); active=true; break; } } elements.Apply(targetColor); elements.SetActive(active || selected); } Win7MenuItemButtonStyle::Win7MenuItemButtonStyle() :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) ,isOpening(false) { elements=Win7MenuItemButtonElements::Create(); elements.Apply(Win7ButtonColors::MenuItemButtonNormal()); } Win7MenuItemButtonStyle::~Win7MenuItemButtonStyle() { } compositions::GuiBoundsComposition* Win7MenuItemButtonStyle::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win7MenuItemButtonStyle::GetContainerComposition() { return elements.mainComposition; } void Win7MenuItemButtonStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7MenuItemButtonStyle::SetText(const WString& value) { elements.textElement->SetText(value); } void Win7MenuItemButtonStyle::SetFont(const FontProperties& value) { Win7SetFont(elements.textElement, elements.textComposition, value); Win7SetFont(elements.shortcutElement, elements.shortcutComposition, value); } void Win7MenuItemButtonStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; elements.imageElement->SetEnabled(value); TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } void Win7MenuItemButtonStyle::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } controls::GuiMenu::IStyleController* Win7MenuItemButtonStyle::CreateSubMenuStyleController() { return new Win7MenuStyle; } void Win7MenuItemButtonStyle::SetSubMenuExisting(bool value) { elements.SetSubMenuExisting(value); } void Win7MenuItemButtonStyle::SetSubMenuOpening(bool value) { if(isOpening!=value) { isOpening=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } controls::GuiButton* Win7MenuItemButtonStyle::GetSubMenuHost() { return 0; } void Win7MenuItemButtonStyle::SetImage(Ptr value) { if(value) { elements.imageElement->SetImage(value->GetImage(), value->GetFrameIndex()); } else { elements.imageElement->SetImage(0, 0); } } void Win7MenuItemButtonStyle::SetShortcutText(const WString& value) { elements.shortcutElement->SetText(value); } void Win7MenuItemButtonStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } /*********************************************************************** Win7MenuSplitterStyle ***********************************************************************/ Win7MenuSplitterStyle::Win7MenuSplitterStyle() { Color dark=Win7GetSystemBorderSinkColor(); Color bright=Win7GetSystemBorderRaiseColor(); GuiTableComposition* table=new GuiTableComposition; table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetRowsAndColumns(1, 3); table->SetPreferredMinSize(Size(0, 6)); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::AbsoluteOption(26)); table->SetColumnOption(1, GuiCellOption::AbsoluteOption(2)); table->SetColumnOption(2, GuiCellOption::MinSizeOption()); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 1, 1); Gui3DSplitterElement* element=Gui3DSplitterElement::Create(); element->SetDirection(Gui3DSplitterElement::Vertical); element->SetColors(dark, bright); cell->SetOwnedElement(element); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 2, 1, 1); Gui3DSplitterElement* element=Gui3DSplitterElement::Create(); element->SetDirection(Gui3DSplitterElement::Horizontal); element->SetColors(dark, bright); cell->SetOwnedElement(element); } boundsComposition=table; } Win7MenuSplitterStyle::~Win7MenuSplitterStyle() { } compositions::GuiBoundsComposition* Win7MenuSplitterStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7MenuSplitterStyle::GetContainerComposition() { return boundsComposition; } void Win7MenuSplitterStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7MenuSplitterStyle::SetText(const WString& value) { } void Win7MenuSplitterStyle::SetFont(const FontProperties& value) { } void Win7MenuSplitterStyle::SetVisuallyEnabled(bool value) { } } } } /*********************************************************************** CONTROLS\STYLES\WIN7STYLES\GUIWIN7SCROLLABLESTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7ButtonStyle ***********************************************************************/ void Win7ScrollArrowButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { Win7ButtonColors targetColor; if(enabled) { switch(value) { case GuiButton::Normal: targetColor=Win7ButtonColors::ButtonNormal(); targetColor.SetAlphaWithoutText(0); break; case GuiButton::Active: targetColor=Win7ButtonColors::ButtonActive(); break; case GuiButton::Pressed: targetColor=Win7ButtonColors::ButtonPressed(); break; } } else { targetColor=Win7ButtonColors::ButtonDisabled(); targetColor.SetAlphaWithoutText(0); } transferringAnimation->Transfer(targetColor); } void Win7ScrollArrowButtonStyle::AfterApplyColors(const Win7ButtonColors& colors) { Win7ButtonStyleBase::AfterApplyColors(colors); arrowElement->SetBorderColor(colors.textColor); arrowElement->SetBackgroundColor(colors.textColor); } Win7ScrollArrowButtonStyle::Win7ScrollArrowButtonStyle(common_styles::CommonScrollStyle::Direction direction, bool increaseButton) :Win7ButtonStyleBase(direction==common_styles::CommonScrollStyle::Horizontal, true, Win7ButtonColors::ButtonNormal(), Alignment::Center, Alignment::Center) { switch(direction) { case common_styles::CommonScrollStyle::Horizontal: if(increaseButton) { GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildRightArrow(arrowElement)); } else { GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildLeftArrow(arrowElement)); } break; case common_styles::CommonScrollStyle::Vertical: if(increaseButton) { GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildDownArrow(arrowElement)); } else { GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildUpArrow(arrowElement)); } break; } } Win7ScrollArrowButtonStyle::~Win7ScrollArrowButtonStyle() { } /*********************************************************************** Win7ScrollStyle ***********************************************************************/ controls::GuiButton::IStyleController* Win7ScrollStyle::CreateDecreaseButtonStyle(Direction direction) { Win7ScrollArrowButtonStyle* decreaseButtonStyle=new Win7ScrollArrowButtonStyle(direction, false); return decreaseButtonStyle; } controls::GuiButton::IStyleController* Win7ScrollStyle::CreateIncreaseButtonStyle(Direction direction) { Win7ScrollArrowButtonStyle* increaseButtonStyle=new Win7ScrollArrowButtonStyle(direction, true); return increaseButtonStyle; } controls::GuiButton::IStyleController* Win7ScrollStyle::CreateHandleButtonStyle(Direction direction) { Win7ButtonStyle* handleButtonStyle=new Win7ButtonStyle(direction==Horizontal); handleButtonStyle->SetTransparentWhenDisabled(true); return handleButtonStyle; } compositions::GuiBoundsComposition* Win7ScrollStyle::InstallBackground(compositions::GuiBoundsComposition* boundsComposition, Direction direction) { Color sinkColor=Win7GetSystemBorderSinkColor(); GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win7GetSystemWindowColor()); boundsComposition->SetOwnedElement(element); { GuiSideAlignedComposition* composition=new GuiSideAlignedComposition; composition->SetMaxLength(DefaultSize); composition->SetMaxRatio(0.2); boundsComposition->AddChild(composition); GuiGradientBackgroundElement* gradient=GuiGradientBackgroundElement::Create(); gradient->SetColors(sinkColor, Win7GetSystemWindowColor()); composition->SetOwnedElement(gradient); switch(direction) { case Horizontal: composition->SetDirection(GuiSideAlignedComposition::Top); gradient->SetDirection(GuiGradientBackgroundElement::Vertical); break; case Vertical: composition->SetDirection(GuiSideAlignedComposition::Left); gradient->SetDirection(GuiGradientBackgroundElement::Horizontal); break; } } { GuiSideAlignedComposition* composition=new GuiSideAlignedComposition; composition->SetMaxLength(DefaultSize); composition->SetMaxRatio(0.2); boundsComposition->AddChild(composition); GuiGradientBackgroundElement* gradient=GuiGradientBackgroundElement::Create(); gradient->SetColors(Win7GetSystemWindowColor(), sinkColor); composition->SetOwnedElement(gradient); switch(direction) { case Horizontal: composition->SetDirection(GuiSideAlignedComposition::Bottom); gradient->SetDirection(GuiGradientBackgroundElement::Vertical); break; case Vertical: composition->SetDirection(GuiSideAlignedComposition::Right); gradient->SetDirection(GuiGradientBackgroundElement::Horizontal); break; } } { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(sinkColor); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); composition->SetOwnedElement(element); boundsComposition->AddChild(composition); } return boundsComposition; } Win7ScrollStyle::Win7ScrollStyle(Direction _direction) :CommonScrollStyle(_direction) { BuildStyle(DefaultSize, ArrowSize); } Win7ScrollStyle::~Win7ScrollStyle() { } /*********************************************************************** Win7TrackStyle ***********************************************************************/ controls::GuiButton::IStyleController* Win7TrackStyle::CreateHandleButtonStyle(Direction direction) { Win7ButtonStyle* handleButtonStyle=new Win7ButtonStyle(direction==Horizontal); return handleButtonStyle; } void Win7TrackStyle::InstallBackground(compositions::GuiGraphicsComposition* boundsComposition, Direction direction) { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win7GetSystemWindowColor()); boundsComposition->SetOwnedElement(element); } void Win7TrackStyle::InstallTrack(compositions::GuiGraphicsComposition* trackComposition, Direction direction) { Gui3DBorderElement* element=Gui3DBorderElement::Create(); element->SetColors(Color(176, 176, 176), Color(252, 252, 252)); trackComposition->SetOwnedElement(element); } Win7TrackStyle::Win7TrackStyle(Direction _direction) :CommonTrackStyle(_direction) { BuildStyle(TrackThickness, TrackPadding, HandleLong, HandleShort); } Win7TrackStyle::~Win7TrackStyle() { } /*********************************************************************** Win7ProgressBarStyle ***********************************************************************/ void Win7ProgressBarStyle::UpdateProgressBar() { vint max=totalSize-pageSize; if(position<0) { progressComposition->SetWidthPageSize(0); } else if(position>=max) { progressComposition->SetWidthPageSize(1); } else { progressComposition->SetWidthPageSize((double)position/max); } } void Win7ProgressBarStyle::FillProgressColors(compositions::GuiGraphicsComposition* parent, Color g1, Color g2, Color g3, Color g4, Color g5) { { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); element->SetDirection(GuiGradientBackgroundElement::Vertical); element->SetColors(g1, g2); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetAlignmentToParent(Margin(0, 0, 0, -1)); composition->SetPreferredMinSize(Size(0, 6)); composition->SetOwnedElement(element); parent->AddChild(composition); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); element->SetDirection(GuiGradientBackgroundElement::Vertical); element->SetColors(g3, g4); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetAlignmentToParent(Margin(0, 6, 0, 6)); composition->SetOwnedElement(element); parent->AddChild(composition); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); element->SetDirection(GuiGradientBackgroundElement::Vertical); element->SetColors(g4, g5); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetAlignmentToParent(Margin(0, -1, 0, 0)); composition->SetPreferredMinSize(Size(0, 6)); composition->SetOwnedElement(element); parent->AddChild(composition); } } Win7ProgressBarStyle::Win7ProgressBarStyle() :totalSize(1) ,pageSize(0) ,position(0) { { boundsComposition=new GuiBoundsComposition; } { containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(1, 1, 1, 1)); boundsComposition->AddChild(containerComposition); FillProgressColors(containerComposition, Color(239, 239, 239), Color(218, 218, 218), Color(201, 201, 201), Color(203, 203, 203), Color(213, 213, 213)); } { GuiRoundBorderElement* element=GuiRoundBorderElement::Create(); element->SetColor(Color(178, 178, 178)); element->SetRadius(2); GuiBoundsComposition* borderComposition=new GuiBoundsComposition; borderComposition->SetOwnedElement(element); borderComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); boundsComposition->AddChild(borderComposition); } { progressComposition=new GuiPartialViewComposition; progressComposition->SetWidthRatio(0); progressComposition->SetWidthPageSize(0); progressComposition->SetHeightRatio(0); progressComposition->SetHeightPageSize(1); containerComposition->AddChild(progressComposition); FillProgressColors(progressComposition, Color(205, 255, 205), Color(156, 238, 172), Color(0, 211, 40), Color(0, 213, 47), Color(74, 232, 93)); } } Win7ProgressBarStyle::~Win7ProgressBarStyle() { } compositions::GuiBoundsComposition* Win7ProgressBarStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7ProgressBarStyle::GetContainerComposition() { return containerComposition; } void Win7ProgressBarStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7ProgressBarStyle::SetText(const WString& value) { } void Win7ProgressBarStyle::SetFont(const FontProperties& value) { } void Win7ProgressBarStyle::SetVisuallyEnabled(bool value) { } void Win7ProgressBarStyle::SetCommandExecutor(controls::GuiScroll::ICommandExecutor* value) { } void Win7ProgressBarStyle::SetTotalSize(vint value) { totalSize=value; UpdateProgressBar(); } void Win7ProgressBarStyle::SetPageSize(vint value) { pageSize=value; UpdateProgressBar(); } void Win7ProgressBarStyle::SetPosition(vint value) { position=value; UpdateProgressBar(); } /*********************************************************************** Win7ScrollViewProvider ***********************************************************************/ Win7ScrollViewProvider::Win7ScrollViewProvider() { } Win7ScrollViewProvider::~Win7ScrollViewProvider() { } void Win7ScrollViewProvider::AssociateStyleController(controls::GuiControl::IStyleController* controller) { } void Win7ScrollViewProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7ScrollViewProvider::SetText(const WString& value) { } void Win7ScrollViewProvider::SetFont(const FontProperties& value) { } void Win7ScrollViewProvider::SetVisuallyEnabled(bool value) { } controls::GuiScroll::IStyleController* Win7ScrollViewProvider::CreateHorizontalScrollStyle() { return new Win7ScrollStyle(Win7ScrollStyle::Horizontal); } controls::GuiScroll::IStyleController* Win7ScrollViewProvider::CreateVerticalScrollStyle() { return new Win7ScrollStyle(Win7ScrollStyle::Vertical); } vint Win7ScrollViewProvider::GetDefaultScrollSize() { return Win7ScrollStyle::DefaultSize; } compositions::GuiGraphicsComposition* Win7ScrollViewProvider::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { GuiSolidBorderElement* border=GuiSolidBorderElement::Create(); border->SetColor(Win7GetSystemBorderColor()); boundsComposition->SetOwnedElement(border); boundsComposition->SetInternalMargin(Margin(1, 1, 1, 1)); GuiSolidBackgroundElement* background=GuiSolidBackgroundElement::Create(); background->SetColor(Win7GetSystemWindowColor()); GuiBoundsComposition* backgroundComposition=new GuiBoundsComposition; boundsComposition->AddChild(backgroundComposition); backgroundComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); backgroundComposition->SetOwnedElement(background); return boundsComposition; } /*********************************************************************** Win7TextBoxBackground ***********************************************************************/ #define HOST_GETTER_BY_FOCUSABLE_COMPOSITION(STYLE) (style->focusableComposition->GetRelatedGraphicsHost()) IMPLEMENT_TRANSFERRING_ANIMATION_BASE(Win7TextBoxColors, Win7TextBoxBackground, HOST_GETTER_BY_FOCUSABLE_COMPOSITION) { colorCurrent=Win7TextBoxColors::Blend(colorBegin, colorEnd, currentPosition, totalLength); style->Apply(colorCurrent); } void Win7TextBoxBackground::UpdateStyle() { if(!isVisuallyEnabled) { transferringAnimation->Transfer(Win7TextBoxColors::Disabled()); } else if(isFocused) { transferringAnimation->Transfer(Win7TextBoxColors::Focused()); } else if(isMouseEnter) { transferringAnimation->Transfer(Win7TextBoxColors::Active()); } else { transferringAnimation->Transfer(Win7TextBoxColors::Normal()); } } void Win7TextBoxBackground::Apply(const Win7TextBoxColors& colors) { borderElement->SetColor(colors.borderColor); backgroundElement->SetColor(colors.backgroundColor); } void Win7TextBoxBackground::OnBoundsMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { isMouseEnter=true; UpdateStyle(); } void Win7TextBoxBackground::OnBoundsMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { isMouseEnter=false; UpdateStyle(); } void Win7TextBoxBackground::OnBoundsGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { isFocused=true; UpdateStyle(); } void Win7TextBoxBackground::OnBoundsLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { isFocused=false; UpdateStyle(); } Win7TextBoxBackground::Win7TextBoxBackground() :backgroundElement(0) ,borderElement(0) ,focusableComposition(0) ,isMouseEnter(false) ,isFocused(false) ,isVisuallyEnabled(false) ,styleController(0) ,textElement(0) { transferringAnimation=new TransferringAnimation(this, Win7TextBoxColors::Normal()); } Win7TextBoxBackground::~Win7TextBoxBackground() { transferringAnimation->Disable(); } void Win7TextBoxBackground::AssociateStyleController(controls::GuiControl::IStyleController* controller) { styleController=controller; } void Win7TextBoxBackground::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { focusableComposition=value; focusableComposition->GetEventReceiver()->mouseEnter.AttachMethod(this, &Win7TextBoxBackground::OnBoundsMouseEnter); focusableComposition->GetEventReceiver()->mouseLeave.AttachMethod(this, &Win7TextBoxBackground::OnBoundsMouseLeave); focusableComposition->GetEventReceiver()->gotFocus.AttachMethod(this, &Win7TextBoxBackground::OnBoundsGotFocus); focusableComposition->GetEventReceiver()->lostFocus.AttachMethod(this, &Win7TextBoxBackground::OnBoundsLostFocus); } void Win7TextBoxBackground::SetVisuallyEnabled(bool value) { isVisuallyEnabled=value; UpdateStyle(); } compositions::GuiGraphicsComposition* Win7TextBoxBackground::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { { GuiSolidBackgroundElement* background=GuiSolidBackgroundElement::Create(); background->SetColor(Color(255, 255, 255)); GuiBoundsComposition* backgroundComposition=new GuiBoundsComposition; boundsComposition->AddChild(backgroundComposition); backgroundComposition->SetAlignmentToParent(Margin(1, 1, 1, 1)); backgroundComposition->SetOwnedElement(background); backgroundElement=background; } { GuiRoundBorderElement* border=GuiRoundBorderElement::Create(); border->SetColor(Win7GetSystemBorderColor()); border->SetRadius(2); borderElement=border; GuiBoundsComposition* borderComposition=new GuiBoundsComposition; boundsComposition->AddChild(borderComposition); borderComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); borderComposition->SetOwnedElement(border); } Apply(Win7TextBoxColors::Normal()); { GuiBoundsComposition* containerComposition=new GuiBoundsComposition; boundsComposition->AddChild(containerComposition); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); containerComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); return containerComposition; } } void Win7TextBoxBackground::InitializeTextElement(elements::GuiColorizedTextElement* _textElement) { textElement=_textElement; Array colors; colors.Resize(1); { colors[0]=Win7GetTextBoxTextColor(); } textElement->SetColors(colors); textElement->SetCaretColor(Color(0, 0, 0)); } /*********************************************************************** Win7MultilineTextBoxProvider ***********************************************************************/ Win7MultilineTextBoxProvider::Win7MultilineTextBoxProvider() :styleController(0) { } Win7MultilineTextBoxProvider::~Win7MultilineTextBoxProvider() { } void Win7MultilineTextBoxProvider::AssociateStyleController(controls::GuiControl::IStyleController* controller) { styleController=controller; background.AssociateStyleController(controller); } void Win7MultilineTextBoxProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { background.SetFocusableComposition(value); GuiMultilineTextBox::StyleController* textBoxController=dynamic_cast(styleController); if(textBoxController) { background.InitializeTextElement(textBoxController->GetTextElement()); } } void Win7MultilineTextBoxProvider::SetVisuallyEnabled(bool value) { background.SetVisuallyEnabled(value); } compositions::GuiGraphicsComposition* Win7MultilineTextBoxProvider::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { return background.InstallBackground(boundsComposition); } /*********************************************************************** Win7SinglelineTextBoxProvider ***********************************************************************/ Win7SinglelineTextBoxProvider::Win7SinglelineTextBoxProvider() :styleController(0) { } Win7SinglelineTextBoxProvider::~Win7SinglelineTextBoxProvider() { } void Win7SinglelineTextBoxProvider::AssociateStyleController(controls::GuiControl::IStyleController* controller) { styleController=controller; background.AssociateStyleController(controller); } void Win7SinglelineTextBoxProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { background.SetFocusableComposition(value); GuiSinglelineTextBox::StyleController* textBoxController=dynamic_cast(styleController); background.InitializeTextElement(textBoxController->GetTextElement()); } void Win7SinglelineTextBoxProvider::SetText(const WString& value) { } void Win7SinglelineTextBoxProvider::SetFont(const FontProperties& value) { } void Win7SinglelineTextBoxProvider::SetVisuallyEnabled(bool value) { background.SetVisuallyEnabled(value); } compositions::GuiGraphicsComposition* Win7SinglelineTextBoxProvider::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { return background.InstallBackground(boundsComposition); } /*********************************************************************** Win7DocumentViewerStyle ***********************************************************************/ Win7DocumentViewerStyle::Win7DocumentViewerStyle() { } Win7DocumentViewerStyle::~Win7DocumentViewerStyle() { } Ptr Win7DocumentViewerStyle::GetBaselineDocument() { return nullptr; } /*********************************************************************** Win7DocumentlabelStyle ***********************************************************************/ Win7DocumentLabelStyle::Win7DocumentLabelStyle() { } Win7DocumentLabelStyle::~Win7DocumentLabelStyle() { } Ptr Win7DocumentLabelStyle::GetBaselineDocument() { return nullptr; } /*********************************************************************** Win7DocumentTextBoxStyle ***********************************************************************/ Win7DocumentTextBoxStyle::Win7DocumentTextBoxStyle() { boundsComposition = new GuiBoundsComposition; boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); containerComposition = background.InstallBackground(boundsComposition); background.AssociateStyleController(this); } Win7DocumentTextBoxStyle::~Win7DocumentTextBoxStyle() { } compositions::GuiBoundsComposition* Win7DocumentTextBoxStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7DocumentTextBoxStyle::GetContainerComposition() { return containerComposition; } void Win7DocumentTextBoxStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { background.SetFocusableComposition(value); } void Win7DocumentTextBoxStyle::SetText(const WString& value) { } void Win7DocumentTextBoxStyle::SetFont(const FontProperties& value) { } void Win7DocumentTextBoxStyle::SetVisuallyEnabled(bool value) { background.SetVisuallyEnabled(value); } Ptr Win7DocumentTextBoxStyle::GetBaselineDocument() { return nullptr; } } } } /*********************************************************************** CONTROLS\STYLES\WIN7STYLES\GUIWIN7STYLESCOMMON.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7ButtonColors ***********************************************************************/ void Win7ButtonColors::SetAlphaWithoutText(unsigned char a) { borderColor.a=a; backgroundColor.a=a; g1.a=a; g2.a=a; g3.a=a; g4.a=a; } Win7ButtonColors Win7ButtonColors::Blend(const Win7ButtonColors& c1, const Win7ButtonColors& c2, vint ratio, vint total) { if(ratio<0) ratio=0; else if(ratio>total) ratio=total; Win7ButtonColors result; result.borderColor=BlendColor(c1.borderColor, c2.borderColor, ratio, total); result.backgroundColor=BlendColor(c1.backgroundColor, c2.backgroundColor, ratio, total); result.g1=BlendColor(c1.g1, c2.g1, ratio, total); result.g2=BlendColor(c1.g2, c2.g2, ratio, total); result.g3=BlendColor(c1.g3, c2.g3, ratio, total); result.g4=BlendColor(c1.g4, c2.g4, ratio, total); result.textColor=BlendColor(c1.textColor, c2.textColor, ratio, total); result.bulletLight=BlendColor(c1.bulletLight, c2.bulletLight, ratio, total); result.bulletDark=BlendColor(c1.bulletDark, c2.bulletDark, ratio, total); return result; } //--------------------------------------------------------- Win7ButtonColors Win7ButtonColors::ButtonNormal() { Win7ButtonColors colors= { Color(122, 122, 122), Color(251, 251, 251), Color(250, 250, 250), Color(235, 235, 235), Color(221, 221, 221), Color(207, 207, 207), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ButtonActive() { Win7ButtonColors colors= { Color(60, 127, 177), Color(220, 244, 254), Color(246, 252, 255), Color(240, 250, 255), Color(225, 245, 254), Color(215, 245, 254), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ButtonPressed() { Win7ButtonColors colors= { Color(44, 98, 139), Color(158, 176, 186), Color(225, 246, 255), Color(204, 239, 254), Color(181, 231, 253), Color(164, 225, 251), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ButtonDisabled() { Win7ButtonColors colors= { Color(173, 178, 181), Color(252, 252, 252), Color(244, 244, 244), Color(244, 244, 244), Color(244, 244, 244), Color(244, 244, 244), Win7GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win7ButtonColors Win7ButtonColors::ItemNormal() { Win7ButtonColors colors= { Color(184, 214, 251, 0), Color(252, 253, 254, 0), Color(250, 251, 253, 0), Color(242, 247, 253, 0), Color(242, 247, 253, 0), Color(235, 243, 253, 0), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ItemActive() { Win7ButtonColors colors= { Color(184, 214, 251), Color(252, 253, 254), Color(250, 251, 253), Color(242, 247, 253), Color(242, 247, 253), Color(235, 243, 253), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ItemSelected() { Win7ButtonColors colors= { Color(118, 158, 206), Color(235, 244, 253), Color(220, 235, 252), Color(208, 227, 252), Color(208, 227, 252), Color(193, 219, 252), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ItemDisabled() { Win7ButtonColors colors= { Color(184, 214, 251, 0), Color(252, 253, 254, 0), Color(250, 251, 253, 0), Color(242, 247, 253, 0), Color(242, 247, 253, 0), Color(235, 243, 253, 0), Win7GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win7ButtonColors Win7ButtonColors::CheckedNormal(bool selected) { Win7ButtonColors colors= { Color(142, 143, 143), Color(244, 244, 244), Color(174, 179, 185), Color(233, 233, 234), Color(203, 207, 213), Color(235, 235, 236), Win7GetSystemTextColor(true), Color(76, 97, 152), Color(76, 97, 152), }; if(!selected) { colors.bulletLight.a=0; colors.bulletDark.a=0; } return colors; } Win7ButtonColors Win7ButtonColors::CheckedActive(bool selected) { Win7ButtonColors colors= { Color(85, 134, 163), Color(222, 249, 250), Color(121, 198, 249), Color(207, 236, 253), Color(177, 233, 253), Color(231, 247, 254), Win7GetSystemTextColor(true), Color(4, 34, 113), Color(4, 34, 113), }; if(!selected) { colors.bulletLight.a=0; colors.bulletDark.a=0; } return colors; } Win7ButtonColors Win7ButtonColors::CheckedPressed(bool selected) { Win7ButtonColors colors= { Color(44, 98, 139), Color(194, 228, 254), Color(94, 182, 247), Color(193, 230, 252), Color(157, 213, 252), Color(224, 244, 254), Win7GetSystemTextColor(true), Color(63, 93, 153), Color(63, 93, 153), }; if(!selected) { colors.bulletLight.a=0; colors.bulletDark.a=0; } return colors; } Win7ButtonColors Win7ButtonColors::CheckedDisabled(bool selected) { Win7ButtonColors colors= { Color(177, 177, 177), Color(240, 240, 240), Color(240, 240, 240), Color(240, 240, 240), Color(240, 240, 240), Color(240, 240, 240), Win7GetSystemTextColor(false), Color(177, 177, 177), Color(177, 177, 177), }; if(!selected) { colors.bulletLight.a=0; colors.bulletDark.a=0; } return colors; } //--------------------------------------------------------- Win7ButtonColors Win7ButtonColors::ToolstripButtonNormal() { Win7ButtonColors colors= { Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ToolstripButtonActive() { Win7ButtonColors colors= { Color(168, 168, 168), Color(248, 248, 248), Color(250, 250, 250), Color(232, 232, 232), Color(218, 218, 218), Color(240, 240, 240), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ToolstripButtonPressed() { Win7ButtonColors colors= { Color(84, 84, 84), Color(156, 156, 156), Color(240, 240, 240), Color(228, 228, 228), Color(222, 222, 222), Color(230, 230, 230), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ToolstripButtonSelected() { Win7ButtonColors colors= { Color(84, 84, 84), Color(250, 250, 250), Color(250, 250, 250), Color(250, 250, 250), Color(250, 250, 250), Color(250, 250, 250), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::ToolstripButtonDisabled() { Win7ButtonColors colors= { Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemWindowColor(), Win7GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win7ButtonColors Win7ButtonColors::MenuBarButtonNormal() { Win7ButtonColors colors= { Color(176, 176, 176), Color(234, 238, 247), Color(246, 248, 250), Color(211, 217, 231), Color(199, 204, 218), Color(224, 228, 243), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::MenuBarButtonActive() { Win7ButtonColors colors= { Color(176, 176, 176), Color(234, 238, 247), Color(246, 248, 250), Color(211, 217, 231), Color(199, 204, 218), Color(224, 228, 243), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::MenuBarButtonPressed() { Win7ButtonColors colors= { Color(88, 88, 89), Color(159, 160, 162), Color(200, 202, 208), Color(205, 209, 219), Color(197, 204, 221), Color(213, 218, 233), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::MenuBarButtonDisabled() { Win7ButtonColors colors= { Color(176, 176, 176), Color(234, 238, 247), Color(246, 248, 250), Color(211, 217, 231), Color(199, 204, 218), Color(224, 228, 243), Win7GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win7ButtonColors Win7ButtonColors::MenuItemButtonNormal() { Win7ButtonColors colors= { Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(227, 227, 227), Color(255, 255, 255), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::MenuItemButtonNormalActive() { Win7ButtonColors colors= { Color(175, 208, 247), Color(248, 248, 250), Color(243, 245, 247), Color(231, 238, 247), Color(229, 233, 238), Color(245, 249, 255), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::MenuItemButtonSelected() { Win7ButtonColors colors= { Color(175, 208, 247), Color(248, 248, 250), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::MenuItemButtonSelectedActive() { Win7ButtonColors colors= { Color(175, 208, 247), Color(248, 248, 250), Color(243, 245, 247), Color(231, 238, 247), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::MenuItemButtonDisabled() { Win7ButtonColors colors= { Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(227, 227, 227), Color(255, 255, 255), Win7GetSystemTextColor(false), }; return colors; } Win7ButtonColors Win7ButtonColors::MenuItemButtonDisabledActive() { Win7ButtonColors colors= { Color(212, 212, 212), Color(244, 244, 244), Color(243, 243, 243), Color(229, 229, 229), Color(232, 232, 232), Color(239, 239, 239), Win7GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win7ButtonColors Win7ButtonColors::TabPageHeaderNormal() { Win7ButtonColors colors= { Color(137, 140, 149), Color(243, 243, 243), Color(242, 242, 242), Color(235, 235, 235), Color(219, 219, 219), Color(207, 207, 207), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::TabPageHeaderActive() { Win7ButtonColors colors= { Color(60, 127, 177), Color(233, 245, 252), Color(234, 246, 253), Color(217, 240, 252), Color(188, 229, 252), Color(167, 217, 245), Win7GetSystemTextColor(true), }; return colors; } Win7ButtonColors Win7ButtonColors::TabPageHeaderSelected() { Win7ButtonColors colors= { Color(137, 140, 149), Win7GetSystemTabContentColor(), Win7GetSystemTabContentColor(), Win7GetSystemTabContentColor(), Win7GetSystemTabContentColor(), Win7GetSystemTabContentColor(), Win7GetSystemTextColor(true), }; return colors; } /*********************************************************************** Win7ButtonElements ***********************************************************************/ Win7ButtonElements Win7ButtonElements::Create(bool verticalGradient, bool roundBorder, Alignment horizontal, Alignment vertical) { Win7ButtonElements button; button.rectBorderElement=0; button.roundBorderElement=0; { button.mainComposition=new GuiBoundsComposition; button.mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } if(roundBorder) { { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); button.backgroundElement=element; GuiBoundsComposition* composition=new GuiBoundsComposition; button.backgroundComposition=composition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(1, 1, 1, 1)); composition->SetOwnedElement(element); } { GuiRoundBorderElement* element=GuiRoundBorderElement::Create(); button.roundBorderElement=element; element->SetRadius(2); GuiBoundsComposition* composition=new GuiBoundsComposition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); composition->SetOwnedElement(element); } } else { { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); button.rectBorderElement=element; GuiBoundsComposition* composition=new GuiBoundsComposition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); composition->SetOwnedElement(element); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); button.backgroundElement=element; GuiBoundsComposition* composition=new GuiBoundsComposition; button.backgroundComposition=composition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(1, 1, 1, 1)); composition->SetOwnedElement(element); } } { GuiTableComposition* table=new GuiTableComposition; button.gradientComposition=table; table->SetAlignmentToParent(Margin(2, 2, 2, 2)); button.mainComposition->AddChild(table); if(verticalGradient) { table->SetRowsAndColumns(2, 1); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); } else { table->SetRowsAndColumns(1, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); table->SetColumnOption(1, GuiCellOption::PercentageOption(0.5)); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); button.topGradientElement=element; element->SetDirection(verticalGradient?GuiGradientBackgroundElement::Vertical:GuiGradientBackgroundElement::Horizontal); GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 0, 1, 1); cell->SetOwnedElement(element); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); button.bottomGradientElement=element; element->SetDirection(verticalGradient?GuiGradientBackgroundElement::Vertical:GuiGradientBackgroundElement::Horizontal); GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); if(verticalGradient) { cell->SetSite(1, 0, 1, 1); } else { cell->SetSite(0, 1, 1, 1); } cell->SetOwnedElement(element); } } { Win7CreateSolidLabelElement(button.textElement, button.textComposition, horizontal, vertical); button.mainComposition->AddChild(button.textComposition); } return button; } void Win7ButtonElements::Apply(const Win7ButtonColors& colors) { if(rectBorderElement) { rectBorderElement->SetColor(colors.borderColor); } if(roundBorderElement) { roundBorderElement->SetColor(colors.borderColor); } backgroundElement->SetColor(colors.backgroundColor); topGradientElement->SetColors(colors.g1, colors.g2); bottomGradientElement->SetColors(colors.g3, colors.g4); textElement->SetColor(colors.textColor); } /*********************************************************************** Win7CheckedButtonElements ***********************************************************************/ Win7CheckedButtonElements Win7CheckedButtonElements::Create(elements::ElementShape shape, bool backgroundVisible) { const vint checkSize=13; const vint checkPadding=2; Win7CheckedButtonElements button; { button.mainComposition=new GuiBoundsComposition; button.mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } { GuiTableComposition* mainTable=new GuiTableComposition; button.mainComposition->AddChild(mainTable); if(backgroundVisible) { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win7GetSystemWindowColor()); mainTable->SetOwnedElement(element); } mainTable->SetRowsAndColumns(1, 2); mainTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); mainTable->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); mainTable->SetColumnOption(0, GuiCellOption::AbsoluteOption(checkSize+2*checkPadding)); mainTable->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); { GuiCellComposition* cell=new GuiCellComposition; mainTable->AddChild(cell); cell->SetSite(0, 0, 1, 1); GuiTableComposition* table=new GuiTableComposition; cell->AddChild(table); table->SetRowsAndColumns(3, 1); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); { GuiCellComposition* checkCell=new GuiCellComposition; table->AddChild(checkCell); checkCell->SetSite(1, 0, 1, 1); { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); button.backgroundElement=element; element->SetShape(shape); GuiBoundsComposition* borderBounds=new GuiBoundsComposition; checkCell->AddChild(borderBounds); borderBounds->SetOwnedElement(element); borderBounds->SetAlignmentToParent(Margin(checkPadding, -1, checkPadding, -1)); borderBounds->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); button.borderElement=element; element->SetShape(shape); GuiBoundsComposition* bounds=new GuiBoundsComposition; borderBounds->AddChild(bounds); bounds->SetOwnedElement(element); bounds->SetAlignmentToParent(Margin(0, 0, 0, 0)); bounds->SetBounds(Rect(Point(0, 0), Size(checkSize, checkSize))); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); button.outerGradientElement=element; element->SetShape(shape); element->SetDirection(GuiGradientBackgroundElement::Backslash); GuiBoundsComposition* bounds=new GuiBoundsComposition; borderBounds->AddChild(bounds); bounds->SetOwnedElement(element); bounds->SetAlignmentToParent(Margin(2, 2, 2, 2)); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); button.innerGradientElement=element; element->SetDirection(GuiGradientBackgroundElement::Backslash); element->SetShape(shape); GuiBoundsComposition* bounds=new GuiBoundsComposition; borderBounds->AddChild(bounds); bounds->SetOwnedElement(element); bounds->SetAlignmentToParent(Margin(3, 3, 3, 3)); } } button.bulletCheckElement=0; button.bulletRadioElement=0; if(shape==ElementShape::Rectangle) { button.bulletCheckElement=GuiSolidLabelElement::Create(); { FontProperties font; font.fontFamily=L"Webdings"; font.size=16; font.bold=true; button.bulletCheckElement->SetFont(font); } button.bulletCheckElement->SetText(L"a"); button.bulletCheckElement->SetAlignments(Alignment::Center, Alignment::Center); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetOwnedElement(button.bulletCheckElement); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); checkCell->AddChild(composition); } else { button.bulletRadioElement=GuiSolidBackgroundElement::Create(); button.bulletRadioElement->SetShape(ElementShape::Ellipse); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetOwnedElement(button.bulletRadioElement); composition->SetAlignmentToParent(Margin(checkPadding+3, 3, checkPadding+3, 3)); checkCell->AddChild(composition); } } } { GuiCellComposition* textCell=new GuiCellComposition; mainTable->AddChild(textCell); textCell->SetSite(0, 1, 1, 1); { Win7CreateSolidLabelElement(button.textElement, button.textComposition, Alignment::Left, Alignment::Center); textCell->AddChild(button.textComposition); } } } return button; } void Win7CheckedButtonElements::Apply(const Win7ButtonColors& colors) { borderElement->SetColor(colors.borderColor); backgroundElement->SetColor(colors.backgroundColor); outerGradientElement->SetColors(colors.g1, colors.g2); innerGradientElement->SetColors(colors.g3, colors.g4); textElement->SetColor(colors.textColor); if(bulletCheckElement) { bulletCheckElement->SetColor(colors.bulletDark); } if(bulletRadioElement) { bulletRadioElement->SetColor(colors.bulletDark); } } /*********************************************************************** Win7MenuItemButtonElements ***********************************************************************/ Win7MenuItemButtonElements Win7MenuItemButtonElements::Create() { Win7MenuItemButtonElements button; { button.mainComposition=new GuiBoundsComposition; button.mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); button.backgroundElement=element; GuiBoundsComposition* composition=new GuiBoundsComposition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(1, 1, 1, 1)); composition->SetOwnedElement(element); } { GuiRoundBorderElement* element=GuiRoundBorderElement::Create(); button.borderElement=element; element->SetRadius(2); GuiBoundsComposition* composition=new GuiBoundsComposition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); composition->SetOwnedElement(element); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); button.gradientElement=element; element->SetDirection(GuiGradientBackgroundElement::Vertical); GuiBoundsComposition* composition=new GuiBoundsComposition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(2, 2, 2, 2)); composition->SetOwnedElement(element); } { GuiTableComposition* table=new GuiTableComposition; button.mainComposition->AddChild(table); table->SetAlignmentToParent(Margin(2, 0, 2, 0)); table->SetRowsAndColumns(1, 5); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::AbsoluteOption(24)); table->SetColumnOption(1, GuiCellOption::AbsoluteOption(2)); table->SetColumnOption(2, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(3, GuiCellOption::MinSizeOption()); table->SetColumnOption(4, GuiCellOption::AbsoluteOption(10)); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 0, 1, 1); button.splitterComposition=cell; GuiImageFrameElement* element=GuiImageFrameElement::Create(); button.imageElement=element; element->SetStretch(false); element->SetAlignments(Alignment::Center, Alignment::Center); cell->SetOwnedElement(element); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 1, 1); button.splitterComposition=cell; Gui3DSplitterElement* element=Gui3DSplitterElement::Create(); button.splitterElement=element; element->SetDirection(Gui3DSplitterElement::Vertical); cell->SetOwnedElement(element); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 2, 1, 1); Win7CreateSolidLabelElement(button.textElement, button.textComposition, L"MenuItem-Text", Alignment::Left, Alignment::Center); cell->AddChild(button.textComposition); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 3, 1, 1); Win7CreateSolidLabelElement(button.shortcutElement, button.shortcutComposition, L"MenuItem-Shortcut", Alignment::Right, Alignment::Center); cell->AddChild(button.shortcutComposition); } { button.subMenuArrowElement=common_styles::CommonFragmentBuilder::BuildRightArrow(); GuiCellComposition* cell=new GuiCellComposition; button.subMenuArrowComposition=cell; cell->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); table->AddChild(cell); cell->SetSite(0, 4, 1, 1); cell->SetOwnedElement(button.subMenuArrowElement); cell->SetVisible(false); } } return button; } void Win7MenuItemButtonElements::Apply(const Win7ButtonColors& colors) { borderElement->SetColor(colors.borderColor); backgroundElement->SetColor(colors.backgroundColor); gradientElement->SetColors(colors.g1, colors.g2); splitterElement->SetColors(colors.g3, colors.g4); textElement->SetColor(colors.textColor); shortcutElement->SetColor(colors.textColor); subMenuArrowElement->SetBackgroundColor(colors.textColor); subMenuArrowElement->SetBorderColor(colors.textColor); } void Win7MenuItemButtonElements::SetActive(bool value) { if(value) { splitterComposition->SetMargin(Margin(0, 1, 0, 2)); } else { splitterComposition->SetMargin(Margin(0, 0, 0, 0)); } } void Win7MenuItemButtonElements::SetSubMenuExisting(bool value) { subMenuArrowComposition->SetVisible(value); } /*********************************************************************** Win7TextBoxColors ***********************************************************************/ Win7TextBoxColors Win7TextBoxColors::Blend(const Win7TextBoxColors& c1, const Win7TextBoxColors& c2, vint ratio, vint total) { if(ratio<0) ratio=0; else if(ratio>total) ratio=total; Win7TextBoxColors result; result.borderColor=BlendColor(c1.borderColor, c2.borderColor, ratio, total); result.backgroundColor=BlendColor(c1.backgroundColor, c2.backgroundColor, ratio, total); return result; } Win7TextBoxColors Win7TextBoxColors::Normal() { Win7TextBoxColors result= { Color(197, 197, 197), Color(255, 255, 255), }; return result; } Win7TextBoxColors Win7TextBoxColors::Active() { Win7TextBoxColors result= { Color(197, 218, 237), Color(255, 255, 255), }; return result; } Win7TextBoxColors Win7TextBoxColors::Focused() { Win7TextBoxColors result= { Color(61, 123, 173), Color(255, 255, 255), }; return result; } Win7TextBoxColors Win7TextBoxColors::Disabled() { Win7TextBoxColors result= { Color(175, 175, 175), Win7GetSystemWindowColor(), }; return result; } /*********************************************************************** Helpers ***********************************************************************/ Color Win7GetSystemWindowColor() { return Color(240, 240, 240); } Color Win7GetSystemTabContentColor() { return Color(255, 255, 255); } Color Win7GetSystemBorderColor() { return Color(100, 100, 100); } Color Win7GetSystemBorderSinkColor() { return Color(227, 227, 227); } Color Win7GetSystemBorderRaiseColor() { return Color(255, 255, 255); } Color Win7GetSystemTextColor(bool enabled) { return enabled?Color(0, 0, 0):Color(131, 131, 131); } void Win7SetFont(GuiSolidLabelElement* element, GuiBoundsComposition* composition, const FontProperties& fontProperties) { vint margin=3; element->SetFont(fontProperties); composition->SetMargin(Margin(margin, margin, margin, margin)); } void Win7CreateSolidLabelElement(GuiSolidLabelElement*& element, GuiBoundsComposition*& composition, Alignment horizontal, Alignment vertical) { element=GuiSolidLabelElement::Create(); element->SetAlignments(horizontal, vertical); composition=new GuiBoundsComposition; composition->SetOwnedElement(element); composition->SetMargin(Margin(0, 0, 0, 0)); composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); } void Win7CreateSolidLabelElement(elements::GuiSolidLabelElement*& element, compositions::GuiSharedSizeItemComposition*& composition, const WString& group, Alignment horizontal, Alignment vertical) { element=GuiSolidLabelElement::Create(); element->SetAlignments(horizontal, vertical); composition=new GuiSharedSizeItemComposition; composition->SetGroup(group); composition->SetSharedWidth(true); composition->SetOwnedElement(element); composition->SetMargin(Margin(0, 0, 0, 0)); composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); } elements::text::ColorEntry Win7GetTextBoxTextColor() { elements::text::ColorEntry entry; entry.normal.text=Color(0, 0, 0); entry.normal.background=Color(0, 0, 0, 0); entry.selectedFocused.text=Color(255, 255, 255); entry.selectedFocused.background=Color(51, 153, 255); entry.selectedUnfocused.text=Color(255, 255, 255); entry.selectedUnfocused.background=Color(51, 153, 255); return entry; } } } } /*********************************************************************** CONTROLS\STYLES\WIN7STYLES\GUIWIN7TABSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7TabPageHeaderStyle ***********************************************************************/ void Win7TabPageHeaderStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { if(selected) { transferringAnimation->Transfer(Win7ButtonColors::TabPageHeaderSelected()); } else { switch(value) { case GuiButton::Normal: transferringAnimation->Transfer(Win7ButtonColors::TabPageHeaderNormal()); break; case GuiButton::Active: case GuiButton::Pressed: transferringAnimation->Transfer(Win7ButtonColors::TabPageHeaderActive()); break; } } } Win7TabPageHeaderStyle::Win7TabPageHeaderStyle() :Win7ButtonStyleBase(true, false, Win7ButtonColors::TabPageHeaderNormal(), Alignment::Left, Alignment::Center) { transferringAnimation->SetEnableAnimation(false); { Margin margin=elements.backgroundComposition->GetAlignmentToParent(); margin.bottom=0; elements.backgroundComposition->SetAlignmentToParent(margin); } { Margin margin=elements.gradientComposition->GetAlignmentToParent(); margin.bottom=0; elements.gradientComposition->SetAlignmentToParent(margin); } } Win7TabPageHeaderStyle::~Win7TabPageHeaderStyle() { } void Win7TabPageHeaderStyle::SetFont(const FontProperties& value) { Win7ButtonStyleBase::SetFont(value); Margin margin=elements.textComposition->GetMargin(); margin.left*=2; margin.right*=2; elements.textComposition->SetMargin(margin); } /*********************************************************************** Win7TabStyle ***********************************************************************/ void Win7TabStyle::OnHeaderButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(commandExecutor) { vint index=headerButtons.IndexOf(dynamic_cast(sender->GetAssociatedControl())); if(index!=-1) { commandExecutor->ShowTab(index); } } } void Win7TabStyle::OnTabHeaderBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { vint height=headerOverflowButton->GetBoundsComposition()->GetBounds().Height(); headerOverflowButton->GetBoundsComposition()->SetBounds(Rect(Point(0, 0), Size(height, 0))); UpdateHeaderLayout(); } void Win7TabStyle::OnHeaderOverflowButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { headerOverflowMenu->SetClientSize(Size(0, 0)); headerOverflowMenu->ShowPopup(headerOverflowButton, true); } void Win7TabStyle::OnHeaderOverflowMenuButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { vint index=headerOverflowMenu->GetToolstripItems().IndexOf(sender->GetRelatedControl()); commandExecutor->ShowTab(index); } void Win7TabStyle::UpdateHeaderOverflowButtonVisibility() { if(tabHeaderComposition->IsStackItemClipped()) { boundsComposition->SetColumnOption(1, GuiCellOption::MinSizeOption()); } else { boundsComposition->SetColumnOption(1, GuiCellOption::AbsoluteOption(0)); } boundsComposition->ForceCalculateSizeImmediately(); } void Win7TabStyle::UpdateHeaderZOrder() { vint itemCount=tabHeaderComposition->GetStackItems().Count(); vint childCount=tabHeaderComposition->Children().Count(); for(vint i=0;iGetStackItems().Get(i); if(headerButtons[i]->GetSelected()) { tabHeaderComposition->MoveChild(item, childCount-1); item->SetExtraMargin(Margin(2, 2, 2, 0)); } else { item->SetExtraMargin(Margin(0, 0, 0, 0)); } } if(childCount>1) { tabHeaderComposition->MoveChild(tabContentTopLineComposition, childCount-2); } } void Win7TabStyle::UpdateHeaderVisibilityIndex() { vint itemCount=tabHeaderComposition->GetStackItems().Count(); vint selectedItem=-1; for(vint i=0;iGetSelected()) { selectedItem=i; } } if(selectedItem!=-1) { tabHeaderComposition->EnsureVisible(selectedItem); } } void Win7TabStyle::UpdateHeaderLayout() { UpdateHeaderZOrder(); UpdateHeaderVisibilityIndex(); UpdateHeaderOverflowButtonVisibility(); } void Win7TabStyle::Initialize() { boundsComposition=new GuiTableComposition; boundsComposition->SetRowsAndColumns(2, 2); boundsComposition->SetRowOption(0, GuiCellOption::MinSizeOption()); boundsComposition->SetRowOption(1, GuiCellOption::PercentageOption(1.0)); boundsComposition->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); boundsComposition->SetColumnOption(1, GuiCellOption::AbsoluteOption(0)); { GuiCellComposition* cell=new GuiCellComposition; boundsComposition->AddChild(cell); cell->SetSite(0, 0, 1, 1); tabHeaderComposition=new GuiStackComposition; tabHeaderComposition->SetExtraMargin(Margin(2, 2, 2, 0)); tabHeaderComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); tabHeaderComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); tabHeaderComposition->BoundsChanged.AttachMethod(this, &Win7TabStyle::OnTabHeaderBoundsChanged); cell->AddChild(tabHeaderComposition); } { GuiCellComposition* cell=new GuiCellComposition; boundsComposition->AddChild(cell); cell->SetSite(0, 1, 1, 1); headerOverflowButton=new GuiButton(CreateMenuButtonStyleController()); headerOverflowButton->GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildDownArrow(headerOverflowArrowElement)); headerOverflowButton->GetBoundsComposition()->SetAlignmentToParent(Margin(-1, 0, 0, 0)); headerOverflowButton->Clicked.AttachMethod(this, &Win7TabStyle::OnHeaderOverflowButtonClicked); cell->AddChild(headerOverflowButton->GetBoundsComposition()); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(GetBorderColor()); tabContentTopLineComposition=new GuiBoundsComposition; tabContentTopLineComposition->SetOwnedElement(element); tabContentTopLineComposition->SetAlignmentToParent(Margin(0, -1, 0, 0)); tabContentTopLineComposition->SetPreferredMinSize(Size(0, 1)); tabHeaderComposition->AddChild(tabContentTopLineComposition); } { GuiCellComposition* cell=new GuiCellComposition; boundsComposition->AddChild(cell); cell->SetSite(1, 0, 1, 2); GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(GetBackgroundColor()); containerComposition=new GuiBoundsComposition; containerComposition->SetOwnedElement(element); containerComposition->SetAlignmentToParent(Margin(1, 0, 1, 1)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); cell->AddChild(containerComposition); { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(GetBorderColor()); cell->SetOwnedElement(element); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win7GetSystemTabContentColor()); containerComposition->SetOwnedElement(element); } } headerOverflowMenu=new GuiToolstripMenu(CreateMenuStyleController(), 0); headerController=new GuiSelectableButton::MutexGroupController; } controls::GuiSelectableButton::IStyleController* Win7TabStyle::CreateHeaderStyleController() { return new Win7TabPageHeaderStyle; } controls::GuiButton::IStyleController* Win7TabStyle::CreateMenuButtonStyleController() { return new Win7ButtonStyle; } controls::GuiToolstripMenu::IStyleController* Win7TabStyle::CreateMenuStyleController() { return new Win7MenuStyle; } controls::GuiToolstripButton::IStyleController* Win7TabStyle::CreateMenuItemStyleController() { return new Win7MenuItemButtonStyle; } Color Win7TabStyle::GetBorderColor() { return Win7ButtonColors::TabPageHeaderNormal().borderColor; } Color Win7TabStyle::GetBackgroundColor() { return Win7GetSystemTabContentColor(); } Win7TabStyle::Win7TabStyle(bool initialize) :boundsComposition(0) ,containerComposition(0) ,tabHeaderComposition(0) ,tabContentTopLineComposition(0) ,commandExecutor(0) ,headerOverflowArrowElement(0) ,headerOverflowButton(0) ,headerOverflowMenu(0) { if(initialize) { Initialize(); } } Win7TabStyle::~Win7TabStyle() { delete headerOverflowMenu; } compositions::GuiBoundsComposition* Win7TabStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7TabStyle::GetContainerComposition() { return containerComposition; } void Win7TabStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7TabStyle::SetText(const WString& value) { } void Win7TabStyle::SetFont(const FontProperties& value) { headerFont=value; } void Win7TabStyle::SetVisuallyEnabled(bool value) { } void Win7TabStyle::SetCommandExecutor(controls::GuiTab::ICommandExecutor* value) { commandExecutor=value; } void Win7TabStyle::InsertTab(vint index) { GuiSelectableButton* button=new GuiSelectableButton(CreateHeaderStyleController()); button->SetAutoSelection(false); button->SetFont(headerFont); button->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); button->SetGroupController(headerController.Obj()); button->Clicked.AttachMethod(this, &Win7TabStyle::OnHeaderButtonClicked); GuiStackItemComposition* item=new GuiStackItemComposition; item->AddChild(button->GetBoundsComposition()); tabHeaderComposition->InsertStackItem(index, item); headerButtons.Insert(index, button); GuiToolstripButton* menuItem=new GuiToolstripButton(CreateMenuItemStyleController()); menuItem->Clicked.AttachMethod(this, &Win7TabStyle::OnHeaderOverflowMenuButtonClicked); headerOverflowMenu->GetToolstripItems().Insert(index, menuItem); UpdateHeaderLayout(); } void Win7TabStyle::SetTabText(vint index, const WString& value) { headerButtons[index]->SetText(value); headerOverflowMenu->GetToolstripItems().Get(index)->SetText(value); UpdateHeaderLayout(); } void Win7TabStyle::RemoveTab(vint index) { GuiStackItemComposition* item=tabHeaderComposition->GetStackItems().Get(index); GuiSelectableButton* button=headerButtons[index]; tabHeaderComposition->RemoveChild(item); item->RemoveChild(button->GetBoundsComposition()); headerButtons.RemoveAt(index); headerOverflowMenu->GetToolstripItems().RemoveAt(index); delete item; delete button; UpdateHeaderLayout(); } void Win7TabStyle::MoveTab(vint oldIndex, vint newIndex) { GuiStackItemComposition* item=tabHeaderComposition->GetStackItems().Get(oldIndex); tabHeaderComposition->RemoveChild(item); tabHeaderComposition->InsertStackItem(newIndex, item); GuiSelectableButton* button=headerButtons[oldIndex]; headerButtons.RemoveAt(oldIndex); headerButtons.Insert(newIndex, button); UpdateHeaderLayout(); } void Win7TabStyle::SetSelectedTab(vint index) { headerButtons[index]->SetSelected(true); UpdateHeaderLayout(); } void Win7TabStyle::SetTabAlt(vint index, const WString& value, compositions::IGuiAltActionHost* host) { auto button = headerButtons[index]; button->SetAlt(value); button->SetActivatingAltHost(host); } compositions::IGuiAltAction* Win7TabStyle::GetTabAltAction(vint index) { return headerButtons[index]->QueryTypedService(); } } } } /*********************************************************************** CONTROLS\STYLES\WIN7STYLES\GUIWIN7TOOLSTRIPSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win7 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win7WindowStyle ***********************************************************************/ Win7ToolstripToolBarStyle::Win7ToolstripToolBarStyle() :Win7EmptyStyle(Win7GetSystemWindowColor()) { boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } Win7ToolstripToolBarStyle::~Win7ToolstripToolBarStyle() { } /*********************************************************************** Win7ToolstripButtonDropdownStyle ***********************************************************************/ void Win7ToolstripButtonDropdownStyle::TransferInternal(controls::GuiButton::ControlState value, bool enabled) { splitterComposition->SetVisible(value!=GuiButton::Normal && enabled); } Win7ToolstripButtonDropdownStyle::Win7ToolstripButtonDropdownStyle() :isVisuallyEnabled(false) ,controlState(GuiButton::Normal) { boundsComposition=new GuiBoundsComposition; boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); { Gui3DSplitterElement* splitterElement=Gui3DSplitterElement::Create(); splitterElement->SetColors(Win7GetSystemBorderSinkColor(), Win7GetSystemBorderRaiseColor()); splitterElement->SetDirection(Gui3DSplitterElement::Vertical); splitterComposition=new GuiBoundsComposition; splitterComposition->SetAlignmentToParent(Margin(0, 3, -1, 3)); splitterComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); splitterComposition->SetOwnedElement(splitterElement); splitterComposition->SetPreferredMinSize(Size(2, 0)); splitterComposition->SetVisible(false); boundsComposition->AddChild(splitterComposition); } { containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(4, 0, 4, 0)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); } } Win7ToolstripButtonDropdownStyle::~Win7ToolstripButtonDropdownStyle() { } compositions::GuiBoundsComposition* Win7ToolstripButtonDropdownStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7ToolstripButtonDropdownStyle::GetContainerComposition() { return containerComposition; } void Win7ToolstripButtonDropdownStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7ToolstripButtonDropdownStyle::SetText(const WString& value) { } void Win7ToolstripButtonDropdownStyle::SetFont(const FontProperties& value) { } void Win7ToolstripButtonDropdownStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlState, isVisuallyEnabled); } } void Win7ToolstripButtonDropdownStyle::Transfer(controls::GuiButton::ControlState value) { if(controlState!=value) { controlState=value; TransferInternal(controlState, isVisuallyEnabled); } } /*********************************************************************** Win7ToolstripButtonStyle ***********************************************************************/ IMPLEMENT_TRANSFERRING_ANIMATION(Win7ButtonColors, Win7ToolstripButtonStyle) { colorCurrent=Win7ButtonColors::Blend(colorBegin, colorEnd, currentPosition, totalLength); style->elements.Apply(colorCurrent); } void Win7ToolstripButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected, bool menuOpening) { Win7ButtonColors targetColor; if(enabled) { if(menuOpening) { value=GuiButton::Pressed; } switch(value) { case GuiButton::Normal: targetColor=selected?Win7ButtonColors::ToolstripButtonSelected():Win7ButtonColors::ToolstripButtonNormal(); break; case GuiButton::Active: targetColor=selected?Win7ButtonColors::ToolstripButtonSelected():Win7ButtonColors::ToolstripButtonActive(); break; case GuiButton::Pressed: targetColor=Win7ButtonColors::ToolstripButtonPressed(); break; } } else { targetColor=Win7ButtonColors::ToolstripButtonDisabled(); } transferringAnimation->Transfer(targetColor); } Win7ToolstripButtonStyle::Win7ToolstripButtonStyle(ButtonStyle _buttonStyle) :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) ,isOpening(false) ,buttonStyle(_buttonStyle) ,subMenuHost(0) { elements=Win7ButtonElements::Create(true, true, Alignment::Center, Alignment::Center); elements.Apply(Win7ButtonColors::ToolstripButtonNormal()); transferringAnimation=new TransferringAnimation(this, Win7ButtonColors::ToolstripButtonNormal()); elements.textComposition->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); imageElement=GuiImageFrameElement::Create(); imageComposition=new GuiBoundsComposition; imageComposition->SetOwnedElement(imageElement); imageComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); imageComposition->SetAlignmentToParent(Margin(4, 4, 4, 4)); if(_buttonStyle==CommandButton) { GetContainerComposition()->AddChild(imageComposition); } else { GuiTableComposition* table=new GuiTableComposition; table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetRowsAndColumns(1, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 0, 1, 1); cell->AddChild(imageComposition); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 1, 1); GuiPolygonElement* arrow=0; GuiBoundsComposition* arrowComposition=common_styles::CommonFragmentBuilder::BuildDownArrow(arrow); switch(_buttonStyle) { case DropdownButton: { arrowComposition->SetAlignmentToParent(Margin(0, 0, 4, 0)); cell->AddChild(arrowComposition); } break; case SplitButton: { subMenuHost=new GuiButton(new Win7ToolstripButtonDropdownStyle); subMenuHost->GetContainerComposition()->AddChild(arrowComposition); subMenuHost->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(subMenuHost->GetBoundsComposition()); } break; default:; } } GetContainerComposition()->AddChild(table); } } Win7ToolstripButtonStyle::~Win7ToolstripButtonStyle() { transferringAnimation->Disable(); } compositions::GuiBoundsComposition* Win7ToolstripButtonStyle::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win7ToolstripButtonStyle::GetContainerComposition() { return elements.mainComposition; } void Win7ToolstripButtonStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7ToolstripButtonStyle::SetText(const WString& value) { } void Win7ToolstripButtonStyle::SetFont(const FontProperties& value) { Win7SetFont(elements.textElement, elements.textComposition, value); } void Win7ToolstripButtonStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; imageElement->SetEnabled(value); TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } void Win7ToolstripButtonStyle::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } controls::GuiMenu::IStyleController* Win7ToolstripButtonStyle::CreateSubMenuStyleController() { return new Win7MenuStyle; } void Win7ToolstripButtonStyle::SetSubMenuExisting(bool value) { } void Win7ToolstripButtonStyle::SetSubMenuOpening(bool value) { if(isOpening!=value) { isOpening=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } controls::GuiButton* Win7ToolstripButtonStyle::GetSubMenuHost() { return subMenuHost; } void Win7ToolstripButtonStyle::SetImage(Ptr value) { if(value) { imageElement->SetImage(value->GetImage(), value->GetFrameIndex()); } else { imageElement->SetImage(0, 0); } } void Win7ToolstripButtonStyle::SetShortcutText(const WString& value) { } void Win7ToolstripButtonStyle::Transfer(controls::GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } /*********************************************************************** Win7ToolstripSplitterStyle ***********************************************************************/ Win7ToolstripSplitterStyle::Win7ToolstripSplitterStyle() { Color dark=Win7GetSystemBorderSinkColor(); Color bright=Win7GetSystemBorderRaiseColor(); GuiBoundsComposition* bounds=new GuiBoundsComposition; bounds->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition=bounds; GuiSolidBackgroundElement* backgroundElement=GuiSolidBackgroundElement::Create(); bounds->SetOwnedElement(backgroundElement); backgroundElement->SetColor(Win7GetSystemWindowColor()); GuiBoundsComposition* splitterComposition=new GuiBoundsComposition; bounds->AddChild(splitterComposition); splitterComposition->SetAlignmentToParent(Margin(3, 3, 3, 3)); Gui3DSplitterElement* splitterElement=Gui3DSplitterElement::Create(); splitterComposition->SetOwnedElement(splitterElement); splitterElement->SetColors(dark, bright); splitterElement->SetDirection(Gui3DSplitterElement::Vertical); } Win7ToolstripSplitterStyle::~Win7ToolstripSplitterStyle() { } compositions::GuiBoundsComposition* Win7ToolstripSplitterStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win7ToolstripSplitterStyle::GetContainerComposition() { return boundsComposition; } void Win7ToolstripSplitterStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win7ToolstripSplitterStyle::SetText(const WString& value) { } void Win7ToolstripSplitterStyle::SetFont(const FontProperties& value) { } void Win7ToolstripSplitterStyle::SetVisuallyEnabled(bool value) { } } } } /*********************************************************************** CONTROLS\STYLES\WIN8STYLES\GUIWIN8BUTTONSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win8ButtonStyleBase ***********************************************************************/ IMPLEMENT_TRANSFERRING_ANIMATION(Win8ButtonColors, Win8ButtonStyleBase) { colorCurrent=Win8ButtonColors::Blend(colorBegin, colorEnd, currentPosition, totalLength); style->elements.Apply(colorCurrent); style->AfterApplyColors(colorCurrent); } void Win8ButtonStyleBase::AfterApplyColors(const Win8ButtonColors& colors) { } Win8ButtonStyleBase::Win8ButtonStyleBase(const Win8ButtonColors& initialColor, Alignment horizontal, Alignment vertical) :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) ,transparentWhenInactive(false) ,transparentWhenDisabled(false) { elements=Win8ButtonElements::Create(horizontal, vertical); elements.Apply(initialColor); transferringAnimation=new TransferringAnimation(this, initialColor); } Win8ButtonStyleBase::~Win8ButtonStyleBase() { transferringAnimation->Disable(); } compositions::GuiBoundsComposition* Win8ButtonStyleBase::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win8ButtonStyleBase::GetContainerComposition() { return elements.mainComposition; } void Win8ButtonStyleBase::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8ButtonStyleBase::SetText(const WString& value) { elements.textElement->SetText(value); } void Win8ButtonStyleBase::SetFont(const FontProperties& value) { Win8SetFont(elements.textElement, elements.textComposition, value); } void Win8ButtonStyleBase::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win8ButtonStyleBase::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win8ButtonStyleBase::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } bool Win8ButtonStyleBase::GetTransparentWhenInactive() { return transparentWhenInactive; } void Win8ButtonStyleBase::SetTransparentWhenInactive(bool value) { transparentWhenInactive=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } bool Win8ButtonStyleBase::GetTransparentWhenDisabled() { return transparentWhenDisabled; } void Win8ButtonStyleBase::SetTransparentWhenDisabled(bool value) { transparentWhenDisabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } bool Win8ButtonStyleBase::GetAutoSizeForText() { return elements.textComposition->GetMinSizeLimitation()!=GuiGraphicsComposition::NoLimit; } void Win8ButtonStyleBase::SetAutoSizeForText(bool value) { if(value) { elements.textComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); } else { elements.textComposition->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); } } /*********************************************************************** Win8ButtonStyle ***********************************************************************/ void Win8ButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { Win8ButtonColors targetColor; if(enabled) { switch(value) { case GuiButton::Normal: targetColor=Win8ButtonColors::ButtonNormal(); if(transparentWhenInactive) { targetColor.SetAlphaWithoutText(0); } break; case GuiButton::Active: targetColor=Win8ButtonColors::ButtonActive(); break; case GuiButton::Pressed: targetColor=Win8ButtonColors::ButtonPressed(); break; } } else { targetColor=Win8ButtonColors::ButtonDisabled(); if(transparentWhenDisabled) { targetColor.SetAlphaWithoutText(0); } } transferringAnimation->Transfer(targetColor); } Win8ButtonStyle::Win8ButtonStyle() :Win8ButtonStyleBase(Win8ButtonColors::ButtonNormal(), Alignment::Center, Alignment::Center) { } Win8ButtonStyle::~Win8ButtonStyle() { } /*********************************************************************** Win7CheckBoxStyle ***********************************************************************/ IMPLEMENT_TRANSFERRING_ANIMATION(Win8ButtonColors, Win8CheckBoxStyle) { colorCurrent=Win8ButtonColors::Blend(colorBegin, colorEnd, currentPosition, totalLength); style->elements.Apply(colorCurrent); } void Win8CheckBoxStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { if(enabled) { switch(value) { case GuiButton::Normal: transferringAnimation->Transfer(Win8ButtonColors::CheckedNormal(selected)); break; case GuiButton::Active: transferringAnimation->Transfer(Win8ButtonColors::CheckedActive(selected)); break; case GuiButton::Pressed: transferringAnimation->Transfer(Win8ButtonColors::CheckedPressed(selected)); break; } } else { transferringAnimation->Transfer(Win8ButtonColors::CheckedDisabled(selected)); } } Win8CheckBoxStyle::Win8CheckBoxStyle(BulletStyle bulletStyle, bool backgroundVisible) :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) { Win8ButtonColors initialColor=Win8ButtonColors::CheckedNormal(isSelected); elements=Win8CheckedButtonElements::Create(bulletStyle==CheckBox?ElementShape::Rectangle:ElementShape::Ellipse, backgroundVisible); elements.Apply(initialColor); transferringAnimation=new TransferringAnimation(this, initialColor); } Win8CheckBoxStyle::~Win8CheckBoxStyle() { transferringAnimation->Disable(); } compositions::GuiBoundsComposition* Win8CheckBoxStyle::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win8CheckBoxStyle::GetContainerComposition() { return elements.mainComposition; } void Win8CheckBoxStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8CheckBoxStyle::SetText(const WString& value) { elements.textElement->SetText(value); } void Win8CheckBoxStyle::SetFont(const FontProperties& value) { Win8SetFont(elements.textElement, elements.textComposition, value); } void Win8CheckBoxStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win8CheckBoxStyle::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } void Win8CheckBoxStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected); } } } } } /*********************************************************************** CONTROLS\STYLES\WIN8STYLES\GUIWIN8CONTROLSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win8EmptyStyle ***********************************************************************/ Win8EmptyStyle::Win8EmptyStyle(Color color) { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(color); boundsComposition=new GuiBoundsComposition; boundsComposition->SetOwnedElement(element); } Win8EmptyStyle::~Win8EmptyStyle() { } compositions::GuiBoundsComposition* Win8EmptyStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8EmptyStyle::GetContainerComposition() { return boundsComposition; } void Win8EmptyStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8EmptyStyle::SetText(const WString& value) { } void Win8EmptyStyle::SetFont(const FontProperties& value) { } void Win8EmptyStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win8WindowStyle ***********************************************************************/ Win8WindowStyle::Win8WindowStyle() { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); boundsComposition=new GuiBoundsComposition; boundsComposition->SetOwnedElement(element); } Win8WindowStyle::~Win8WindowStyle() { } compositions::GuiBoundsComposition* Win8WindowStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8WindowStyle::GetContainerComposition() { return boundsComposition; } void Win8WindowStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8WindowStyle::SetText(const WString& value) { } void Win8WindowStyle::SetFont(const FontProperties& value) { } void Win8WindowStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win8TooltipStyle ***********************************************************************/ Win8TooltipStyle::Win8TooltipStyle() { boundsComposition=new GuiBoundsComposition; boundsComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Color(100, 100, 100)); boundsComposition->SetOwnedElement(element); } containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(1, 1, 1, 1)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Color(255, 255, 225)); containerComposition->SetOwnedElement(element); } } Win8TooltipStyle::~Win8TooltipStyle() { } compositions::GuiBoundsComposition* Win8TooltipStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8TooltipStyle::GetContainerComposition() { return containerComposition; } void Win8TooltipStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8TooltipStyle::SetText(const WString& value) { } void Win8TooltipStyle::SetFont(const FontProperties& value) { } void Win8TooltipStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win8LabelStyle ***********************************************************************/ Win8LabelStyle::Win8LabelStyle(bool forShortcutKey) { textElement=GuiSolidLabelElement::Create(); textElement->SetColor(GetDefaultTextColor()); boundsComposition=new GuiBoundsComposition; boundsComposition->SetMinSizeLimitation(GuiBoundsComposition::LimitToElementAndChildren); if (forShortcutKey) { { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Color(100, 100, 100)); boundsComposition->SetOwnedElement(element); } auto containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(1, 1, 1, 1)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Color(255, 255, 225)); containerComposition->SetOwnedElement(element); } auto labelComposition = new GuiBoundsComposition; labelComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); labelComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); labelComposition->SetOwnedElement(textElement); containerComposition->AddChild(labelComposition); } else { boundsComposition->SetOwnedElement(textElement); } } Win8LabelStyle::~Win8LabelStyle() { } compositions::GuiBoundsComposition* Win8LabelStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8LabelStyle::GetContainerComposition() { return boundsComposition; } void Win8LabelStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8LabelStyle::SetText(const WString& value) { textElement->SetText(value); } void Win8LabelStyle::SetFont(const FontProperties& value) { textElement->SetFont(value); } void Win8LabelStyle::SetVisuallyEnabled(bool value) { } Color Win8LabelStyle::GetDefaultTextColor() { return Win8GetSystemTextColor(true); } void Win8LabelStyle::SetTextColor(Color value) { textElement->SetColor(value); } /*********************************************************************** Win8GroupBoxStyle ***********************************************************************/ IMPLEMENT_TRANSFERRING_ANIMATION(Color, Win8GroupBoxStyle) { colorCurrent=BlendColor(colorBegin, colorEnd, currentPosition, totalLength); style->textElement->SetColor(colorCurrent); } void Win8GroupBoxStyle::SetMargins(vint fontSize) { fontSize+=4; vint half=fontSize/2; borderComposition->SetAlignmentToParent(Margin(0, half, 0, 0)); containerComposition->SetAlignmentToParent(Margin(1, fontSize, 1, 1)); textBackgroundComposition->SetAlignmentToParent(Margin(half, 2, -1, -1)); } Win8GroupBoxStyle::Win8GroupBoxStyle() { boundsComposition=new GuiBoundsComposition; { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); boundsComposition->SetOwnedElement(element); boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } borderComposition=new GuiBoundsComposition; { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Color(221, 221, 221)); borderComposition->SetOwnedElement(element); boundsComposition->AddChild(borderComposition); } textBackgroundComposition=new GuiBoundsComposition; { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); textBackgroundComposition->SetOwnedElement(element); textBackgroundComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(textBackgroundComposition); } textComposition=new GuiBoundsComposition; { GuiSolidLabelElement* element=GuiSolidLabelElement::Create(); element->SetColor(Win8GetSystemTextColor(true)); textElement=element; textComposition->SetOwnedElement(element); textComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); textComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); textBackgroundComposition->AddChild(textComposition); } containerComposition=new GuiBoundsComposition; { boundsComposition->AddChild(containerComposition); } SetMargins(0); transferringAnimation=new TransferringAnimation(this, Win8GetSystemTextColor(true)); } Win8GroupBoxStyle::~Win8GroupBoxStyle() { transferringAnimation->Disable(); } compositions::GuiBoundsComposition* Win8GroupBoxStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8GroupBoxStyle::GetContainerComposition() { return containerComposition; } void Win8GroupBoxStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8GroupBoxStyle::SetText(const WString& value) { textElement->SetText(value); } void Win8GroupBoxStyle::SetFont(const FontProperties& value) { textElement->SetFont(value); SetMargins(value.size); } void Win8GroupBoxStyle::SetVisuallyEnabled(bool value) { if(value) { transferringAnimation->Transfer(Win8GetSystemTextColor(true)); } else { transferringAnimation->Transfer(Win8GetSystemTextColor(false)); } } /*********************************************************************** Win8DatePickerStyle ***********************************************************************/ Win8DatePickerStyle::Win8DatePickerStyle() { } Win8DatePickerStyle::~Win8DatePickerStyle() { } void Win8DatePickerStyle::AssociateStyleController(controls::GuiControl::IStyleController* controller) { } void Win8DatePickerStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8DatePickerStyle::SetText(const WString& value) { } void Win8DatePickerStyle::SetFont(const FontProperties& value) { } void Win8DatePickerStyle::SetVisuallyEnabled(bool value) { } controls::GuiSelectableButton::IStyleController* Win8DatePickerStyle::CreateDateButtonStyle() { return new Win8SelectableItemStyle; } controls::GuiTextList* Win8DatePickerStyle::CreateTextList() { return new GuiTextList(new Win8TextListProvider, new Win8TextListItemProvider); } controls::GuiComboBoxListControl::IStyleController* Win8DatePickerStyle::CreateComboBoxStyle() { return new Win8DropDownComboBoxStyle; } Color Win8DatePickerStyle::GetBackgroundColor() { return Win8GetSystemWindowColor(); } Color Win8DatePickerStyle::GetPrimaryTextColor() { return Win8GetSystemTextColor(true); } Color Win8DatePickerStyle::GetSecondaryTextColor() { return Win8GetSystemTextColor(false); } } } } /*********************************************************************** CONTROLS\STYLES\WIN8STYLES\GUIWIN8LISTSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win8SelectableItemStyle ***********************************************************************/ void Win8SelectableItemStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { if(!enabled) { transferringAnimation->Transfer(Win8ButtonColors::ItemDisabled()); } else if(selected) { transferringAnimation->Transfer(Win8ButtonColors::ItemSelected()); } else { switch(value) { case GuiButton::Normal: transferringAnimation->Transfer(Win8ButtonColors::ItemNormal()); break; case GuiButton::Active: transferringAnimation->Transfer(Win8ButtonColors::ItemActive()); break; case GuiButton::Pressed: transferringAnimation->Transfer(Win8ButtonColors::ItemSelected()); break; } } } Win8SelectableItemStyle::Win8SelectableItemStyle() :Win8ButtonStyleBase(Win8ButtonColors::ItemNormal(), Alignment::Left, Alignment::Center) { transferringAnimation->SetEnableAnimation(false); } Win8SelectableItemStyle::~Win8SelectableItemStyle() { } /*********************************************************************** Win8DropDownComboBoxStyle ***********************************************************************/ void Win8DropDownComboBoxStyle::TransferInternal(controls::GuiButton::ControlState value, bool enabled, bool selected) { Win8ButtonColors targetColor; if(enabled) { if(selected) value=GuiButton::Pressed; switch(value) { case GuiButton::Normal: targetColor=Win8ButtonColors::ButtonNormal(); break; case GuiButton::Active: targetColor=Win8ButtonColors::ButtonActive(); break; case GuiButton::Pressed: targetColor=Win8ButtonColors::ButtonPressed(); break; } } else { targetColor=Win8ButtonColors::ButtonDisabled(); } transferringAnimation->Transfer(targetColor); } void Win8DropDownComboBoxStyle::AfterApplyColors(const Win8ButtonColors& colors) { Win8ButtonStyle::AfterApplyColors(colors); dropDownElement->SetBorderColor(colors.textColor); dropDownElement->SetBackgroundColor(colors.textColor); } Win8DropDownComboBoxStyle::Win8DropDownComboBoxStyle() :commandExecutor(0) , textVisible(true) { table=new GuiTableComposition; table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetRowsAndColumns(3, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); elements.textComposition->AddChild(table); elements.textComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); textComposition=new GuiCellComposition; table->AddChild(textComposition); textComposition->SetSite(1, 0, 1, 1); Ptr element=elements.textComposition->GetOwnedElement(); elements.textComposition->SetOwnedElement(0); textComposition->SetOwnedElement(element); elements.textElement->SetEllipse(true); elements.textElement->SetAlignments(Alignment::Left, Alignment::Center); dropDownElement=common_styles::CommonFragmentBuilder::BuildDownArrow(); dropDownComposition=new GuiCellComposition; table->AddChild(dropDownComposition); dropDownComposition->SetSite(1, 1, 1, 1); dropDownComposition->SetOwnedElement(dropDownElement); dropDownComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); dropDownComposition->SetMargin(Margin(3, 0, 3, 0)); } Win8DropDownComboBoxStyle::~Win8DropDownComboBoxStyle() { } compositions::GuiGraphicsComposition* Win8DropDownComboBoxStyle::GetContainerComposition() { return textComposition; } GuiMenu::IStyleController* Win8DropDownComboBoxStyle::CreateSubMenuStyleController() { return new Win8MenuStyle; } void Win8DropDownComboBoxStyle::SetSubMenuExisting(bool value) { } void Win8DropDownComboBoxStyle::SetSubMenuOpening(bool value) { SetSelected(value); } GuiButton* Win8DropDownComboBoxStyle::GetSubMenuHost() { return 0; } void Win8DropDownComboBoxStyle::SetImage(Ptr value) { } void Win8DropDownComboBoxStyle::SetShortcutText(const WString& value) { } void Win8DropDownComboBoxStyle::SetCommandExecutor(controls::GuiComboBoxBase::ICommandExecutor* value) { commandExecutor=value; } void Win8DropDownComboBoxStyle::OnItemSelected() { } void Win8DropDownComboBoxStyle::SetText(const WString& value) { text = value; if (textVisible) { Win8ButtonStyle::SetText(text); } } void Win8DropDownComboBoxStyle::SetTextVisible(bool value) { if (textVisible != value) { if ((textVisible = value)) { Win8ButtonStyle::SetText(text); } else { Win8ButtonStyle::SetText(L""); } } } /*********************************************************************** Win8TextListItemProvider ***********************************************************************/ Win8TextListItemProvider::Win8TextListItemProvider() { } Win8TextListItemProvider::~Win8TextListItemProvider() { } controls::GuiSelectableButton::IStyleController* Win8TextListItemProvider::CreateBulletStyleController() { return 0; } /*********************************************************************** Win8CheckTextListItemProvider ***********************************************************************/ Win8CheckTextListItemProvider::Win8CheckTextListItemProvider() { } Win8CheckTextListItemProvider::~Win8CheckTextListItemProvider() { } controls::GuiSelectableButton::IStyleController* Win8CheckTextListItemProvider::CreateBulletStyleController() { return new Win8CheckBoxStyle(Win8CheckBoxStyle::CheckBox, false); } /*********************************************************************** Win8RadioTextListItemProvider ***********************************************************************/ Win8RadioTextListItemProvider::Win8RadioTextListItemProvider() { } Win8RadioTextListItemProvider::~Win8RadioTextListItemProvider() { } controls::GuiSelectableButton::IStyleController* Win8RadioTextListItemProvider::CreateBulletStyleController() { return new Win8CheckBoxStyle(Win8CheckBoxStyle::RadioButton, false); } /*********************************************************************** Win8TextListProvider ***********************************************************************/ Win8TextListProvider::Win8TextListProvider() { } Win8TextListProvider::~Win8TextListProvider() { } controls::GuiSelectableButton::IStyleController* Win8TextListProvider::CreateItemBackground() { return new Win8SelectableItemStyle; } Color Win8TextListProvider::GetTextColor() { return Win8GetSystemTextColor(true); } /*********************************************************************** Win8ListViewProvider ***********************************************************************/ Win8ListViewProvider::Win8ListViewProvider() { } Win8ListViewProvider::~Win8ListViewProvider() { } controls::GuiSelectableButton::IStyleController* Win8ListViewProvider::CreateItemBackground() { return new Win8SelectableItemStyle; } controls::GuiListViewColumnHeader::IStyleController* Win8ListViewProvider::CreateColumnStyle() { return new win7::Win7ListViewColumnHeaderStyle; } Color Win8ListViewProvider::GetPrimaryTextColor() { return Win8GetSystemTextColor(true); } Color Win8ListViewProvider::GetSecondaryTextColor() { return Win8GetSystemTextColor(false); } Color Win8ListViewProvider::GetItemSeparatorColor() { return Color(220, 220, 220); } /*********************************************************************** Win8TreeViewProvider ***********************************************************************/ Win8TreeViewProvider::Win8TreeViewProvider() { } Win8TreeViewProvider::~Win8TreeViewProvider() { } controls::GuiSelectableButton::IStyleController* Win8TreeViewProvider::CreateItemBackground() { return new Win8SelectableItemStyle; } controls::GuiSelectableButton::IStyleController* Win8TreeViewProvider::CreateItemExpandingDecorator() { return new win7::Win7TreeViewExpandingButtonStyle; } Color Win8TreeViewProvider::GetTextColor() { return Win8GetSystemTextColor(true); } } } } /*********************************************************************** CONTROLS\STYLES\WIN8STYLES\GUIWIN8MENUSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win8MenuStyle ***********************************************************************/ Win8MenuStyle::Win8MenuStyle() { { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Win8GetMenuBorderColor()); boundsComposition=new GuiBoundsComposition; boundsComposition->SetOwnedElement(element); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); GuiBoundsComposition* subBorder=new GuiBoundsComposition; subBorder->SetOwnedElement(element); subBorder->SetAlignmentToParent(Margin(1, 1, 1, 1)); boundsComposition->AddChild(subBorder); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); containerComposition=new GuiBoundsComposition; containerComposition->SetOwnedElement(element); containerComposition->SetAlignmentToParent(Margin(3, 3, 3, 3)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); } } Win8MenuStyle::~Win8MenuStyle() { } compositions::GuiBoundsComposition* Win8MenuStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8MenuStyle::GetContainerComposition() { return containerComposition; } void Win8MenuStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8MenuStyle::SetText(const WString& value) { } void Win8MenuStyle::SetFont(const FontProperties& value) { } void Win8MenuStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win8MenuBarStyle ***********************************************************************/ Win8MenuBarStyle::Win8MenuBarStyle() { boundsComposition=new GuiBoundsComposition; { GuiSolidBackgroundElement* solid=GuiSolidBackgroundElement::Create(); solid->SetColor(Color(245, 246, 247)); boundsComposition->SetOwnedElement(solid); boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } { Gui3DSplitterElement* element=Gui3DSplitterElement::Create(); element->SetColors(Color(232, 233, 234), Color(240, 240, 240)); element->SetDirection(Gui3DSplitterElement::Horizontal); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetOwnedElement(element); composition->SetPreferredMinSize(Size(0, 2)); composition->SetAlignmentToParent(Margin(0, -1, 0, 0)); boundsComposition->AddChild(composition); } containerComposition=new GuiBoundsComposition; { containerComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); } } Win8MenuBarStyle::~Win8MenuBarStyle() { } compositions::GuiBoundsComposition* Win8MenuBarStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8MenuBarStyle::GetContainerComposition() { return containerComposition; } void Win8MenuBarStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8MenuBarStyle::SetText(const WString& value) { } void Win8MenuBarStyle::SetFont(const FontProperties& value) { } void Win8MenuBarStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win8MenuBarButtonStyle ***********************************************************************/ void Win8MenuBarButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool opening) { Win8ButtonColors targetColor; if(!enabled) { targetColor=Win8ButtonColors::MenuBarButtonDisabled(); targetColor.SetAlphaWithoutText(0); } else if(opening) { targetColor=Win8ButtonColors::MenuBarButtonPressed(); } else { switch(value) { case GuiButton::Normal: targetColor=Win8ButtonColors::MenuBarButtonNormal(); targetColor.SetAlphaWithoutText(0); break; case GuiButton::Active: targetColor=Win8ButtonColors::MenuBarButtonActive(); break; case GuiButton::Pressed: targetColor=Win8ButtonColors::MenuBarButtonPressed(); break; } } elements.Apply(targetColor); } Win8MenuBarButtonStyle::Win8MenuBarButtonStyle() :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isOpening(false) { Win8ButtonColors initialColor=Win8ButtonColors::MenuBarButtonNormal(); initialColor.SetAlphaWithoutText(0); elements=Win8ButtonElements::Create(Alignment::Center, Alignment::Center); elements.Apply(initialColor); } Win8MenuBarButtonStyle::~Win8MenuBarButtonStyle() { } compositions::GuiBoundsComposition* Win8MenuBarButtonStyle::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win8MenuBarButtonStyle::GetContainerComposition() { return elements.mainComposition; } void Win8MenuBarButtonStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8MenuBarButtonStyle::SetText(const WString& value) { elements.textElement->SetText(value); } void Win8MenuBarButtonStyle::SetFont(const FontProperties& value) { Win8SetFont(elements.textElement, elements.textComposition, value); Margin margin=elements.textComposition->GetMargin(); margin.left*=3; margin.right*=3; elements.textComposition->SetMargin(margin); } void Win8MenuBarButtonStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlStyle, isVisuallyEnabled, isOpening); } } void Win8MenuBarButtonStyle::SetSelected(bool value) { } controls::GuiMenu::IStyleController* Win8MenuBarButtonStyle::CreateSubMenuStyleController() { return new Win8MenuStyle; } void Win8MenuBarButtonStyle::SetSubMenuExisting(bool value) { } void Win8MenuBarButtonStyle::SetSubMenuOpening(bool value) { if(isOpening!=value) { isOpening=value; TransferInternal(controlStyle, isVisuallyEnabled, isOpening); } } controls::GuiButton* Win8MenuBarButtonStyle::GetSubMenuHost() { return 0; } void Win8MenuBarButtonStyle::SetImage(Ptr value) { } void Win8MenuBarButtonStyle::SetShortcutText(const WString& value) { } void Win8MenuBarButtonStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isOpening); } } /*********************************************************************** Win8MenuItemButtonStyle ***********************************************************************/ void Win8MenuItemButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected, bool opening) { Win8ButtonColors targetColor; bool active=false; if(enabled) { if(opening) { targetColor=Win8ButtonColors::MenuItemButtonNormalActive(); active=true; } else { switch(value) { case GuiButton::Normal: targetColor=selected?Win8ButtonColors::MenuItemButtonSelected():Win8ButtonColors::MenuItemButtonNormal(); break; case GuiButton::Active: case GuiButton::Pressed: targetColor=selected?Win8ButtonColors::MenuItemButtonSelectedActive():Win8ButtonColors::MenuItemButtonNormalActive(); active=true; break; } } } else { switch(value) { case GuiButton::Normal: targetColor=Win8ButtonColors::MenuItemButtonDisabled(); break; case GuiButton::Active: case GuiButton::Pressed: targetColor=Win8ButtonColors::MenuItemButtonDisabledActive(); active=true; break; } } elements.Apply(targetColor); elements.SetActive(active || selected); } Win8MenuItemButtonStyle::Win8MenuItemButtonStyle() :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) ,isOpening(false) { elements=Win8MenuItemButtonElements::Create(); elements.Apply(Win8ButtonColors::MenuItemButtonNormal()); } Win8MenuItemButtonStyle::~Win8MenuItemButtonStyle() { } compositions::GuiBoundsComposition* Win8MenuItemButtonStyle::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win8MenuItemButtonStyle::GetContainerComposition() { return elements.mainComposition; } void Win8MenuItemButtonStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8MenuItemButtonStyle::SetText(const WString& value) { elements.textElement->SetText(value); } void Win8MenuItemButtonStyle::SetFont(const FontProperties& value) { Win8SetFont(elements.textElement, elements.textComposition, value); Win8SetFont(elements.shortcutElement, elements.shortcutComposition, value); } void Win8MenuItemButtonStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; elements.imageElement->SetEnabled(value); TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } void Win8MenuItemButtonStyle::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } controls::GuiMenu::IStyleController* Win8MenuItemButtonStyle::CreateSubMenuStyleController() { return new Win8MenuStyle; } void Win8MenuItemButtonStyle::SetSubMenuExisting(bool value) { elements.SetSubMenuExisting(value); } void Win8MenuItemButtonStyle::SetSubMenuOpening(bool value) { if(isOpening!=value) { isOpening=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } controls::GuiButton* Win8MenuItemButtonStyle::GetSubMenuHost() { return 0; } void Win8MenuItemButtonStyle::SetImage(Ptr value) { if(value) { elements.imageElement->SetImage(value->GetImage(), value->GetFrameIndex()); } else { elements.imageElement->SetImage(0, 0); } } void Win8MenuItemButtonStyle::SetShortcutText(const WString& value) { elements.shortcutElement->SetText(value); } void Win8MenuItemButtonStyle::Transfer(GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } /*********************************************************************** Win8MenuSplitterStyle ***********************************************************************/ Win8MenuSplitterStyle::Win8MenuSplitterStyle() { boundsComposition=new GuiBoundsComposition; boundsComposition->SetPreferredMinSize(Size(26, 5)); { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Win8GetMenuSplitterColor()); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetPreferredMinSize(Size(1, 0)); composition->SetOwnedElement(element); composition->SetAlignmentToParent(Margin(26, 0, -1, 0)); boundsComposition->AddChild(composition); } { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Win8GetMenuSplitterColor()); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetPreferredMinSize(Size(0, 1)); composition->SetOwnedElement(element); composition->SetAlignmentToParent(Margin(27, 2, 0, 2)); boundsComposition->AddChild(composition); } } Win8MenuSplitterStyle::~Win8MenuSplitterStyle() { } compositions::GuiBoundsComposition* Win8MenuSplitterStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8MenuSplitterStyle::GetContainerComposition() { return boundsComposition; } void Win8MenuSplitterStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8MenuSplitterStyle::SetText(const WString& value) { } void Win8MenuSplitterStyle::SetFont(const FontProperties& value) { } void Win8MenuSplitterStyle::SetVisuallyEnabled(bool value) { } } } } /*********************************************************************** CONTROLS\STYLES\WIN8STYLES\GUIWIN8SCROLLABLESTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win8ScrollHandleButtonStyle ***********************************************************************/ void Win8ScrollHandleButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { Win8ButtonColors targetColor; if(enabled) { switch(value) { case GuiButton::Normal: targetColor=Win8ButtonColors::ScrollHandleNormal(); break; case GuiButton::Active: targetColor=Win8ButtonColors::ScrollHandleActive(); break; case GuiButton::Pressed: targetColor=Win8ButtonColors::ScrollHandlePressed(); break; } } else { targetColor=Win8ButtonColors::ScrollHandleDisabled(); } transferringAnimation->Transfer(targetColor); } Win8ScrollHandleButtonStyle::Win8ScrollHandleButtonStyle() :Win8ButtonStyleBase(Win8ButtonColors::ScrollHandleNormal(), Alignment::Center, Alignment::Center) { } Win8ScrollHandleButtonStyle::~Win8ScrollHandleButtonStyle() { } /*********************************************************************** Win8ScrollArrowButtonStyle ***********************************************************************/ void Win8ScrollArrowButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { Win8ButtonColors targetColor; if(enabled) { switch(value) { case GuiButton::Normal: targetColor=Win8ButtonColors::ScrollArrowNormal(); break; case GuiButton::Active: targetColor=Win8ButtonColors::ScrollArrowActive(); break; case GuiButton::Pressed: targetColor=Win8ButtonColors::ScrollArrowPressed(); break; } } else { targetColor=Win8ButtonColors::ScrollArrowDisabled(); } transferringAnimation->Transfer(targetColor); } void Win8ScrollArrowButtonStyle::AfterApplyColors(const Win8ButtonColors& colors) { Win8ButtonStyleBase::AfterApplyColors(colors); arrowElement->SetBorderColor(colors.textColor); arrowElement->SetBackgroundColor(colors.textColor); } Win8ScrollArrowButtonStyle::Win8ScrollArrowButtonStyle(common_styles::CommonScrollStyle::Direction direction, bool increaseButton) :Win8ButtonStyleBase(Win8ButtonColors::ScrollArrowNormal(), Alignment::Center, Alignment::Center) { switch(direction) { case common_styles::CommonScrollStyle::Horizontal: if(increaseButton) { GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildRightArrow(arrowElement)); } else { GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildLeftArrow(arrowElement)); } break; case common_styles::CommonScrollStyle::Vertical: if(increaseButton) { GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildDownArrow(arrowElement)); } else { GetContainerComposition()->AddChild(common_styles::CommonFragmentBuilder::BuildUpArrow(arrowElement)); } break; } } Win8ScrollArrowButtonStyle::~Win8ScrollArrowButtonStyle() { } /*********************************************************************** Win8ScrollStyle ***********************************************************************/ controls::GuiButton::IStyleController* Win8ScrollStyle::CreateDecreaseButtonStyle(Direction direction) { Win8ScrollArrowButtonStyle* decreaseButtonStyle=new Win8ScrollArrowButtonStyle(direction, false); return decreaseButtonStyle; } controls::GuiButton::IStyleController* Win8ScrollStyle::CreateIncreaseButtonStyle(Direction direction) { Win8ScrollArrowButtonStyle* increaseButtonStyle=new Win8ScrollArrowButtonStyle(direction, true); return increaseButtonStyle; } controls::GuiButton::IStyleController* Win8ScrollStyle::CreateHandleButtonStyle(Direction direction) { Win8ScrollHandleButtonStyle* handleButtonStyle=new Win8ScrollHandleButtonStyle; return handleButtonStyle; } compositions::GuiBoundsComposition* Win8ScrollStyle::InstallBackground(compositions::GuiBoundsComposition* boundsComposition, Direction direction) { { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); boundsComposition->SetOwnedElement(element); } return boundsComposition; } Win8ScrollStyle::Win8ScrollStyle(Direction _direction) :CommonScrollStyle(_direction) { BuildStyle(DefaultSize, ArrowSize); } Win8ScrollStyle::~Win8ScrollStyle() { } /*********************************************************************** Win8TrackStyle ***********************************************************************/ controls::GuiButton::IStyleController* Win8TrackStyle::CreateHandleButtonStyle(Direction direction) { Win8ButtonStyle* handleButtonStyle=new Win8ButtonStyle; return handleButtonStyle; } void Win8TrackStyle::InstallBackground(compositions::GuiGraphicsComposition* boundsComposition, Direction direction) { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); boundsComposition->SetOwnedElement(element); } void Win8TrackStyle::InstallTrack(compositions::GuiGraphicsComposition* trackComposition, Direction direction) { { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Color(231, 234, 234)); trackComposition->SetOwnedElement(element); } { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Color(214, 214, 214)); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetOwnedElement(element); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); trackComposition->AddChild(composition); } } Win8TrackStyle::Win8TrackStyle(Direction _direction) :CommonTrackStyle(_direction) { BuildStyle(TrackThickness, TrackPadding, HandleLong, HandleShort); } Win8TrackStyle::~Win8TrackStyle() { } /*********************************************************************** Win8ProgressBarStyle ***********************************************************************/ void Win8ProgressBarStyle::UpdateProgressBar() { vint max=totalSize-pageSize; if(position<0) { progressComposition->SetWidthPageSize(0); } else if(position>=max) { progressComposition->SetWidthPageSize(1); } else { progressComposition->SetWidthPageSize((double)position/max); } } Win8ProgressBarStyle::Win8ProgressBarStyle() :totalSize(1) ,pageSize(0) ,position(0) { { boundsComposition=new GuiBoundsComposition; } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Color(230, 230, 230)); containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(1, 1, 1, 1)); containerComposition->SetOwnedElement(element); boundsComposition->AddChild(containerComposition); } { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); element->SetColor(Color(188, 188, 188)); GuiBoundsComposition* borderComposition=new GuiBoundsComposition; borderComposition->SetOwnedElement(element); borderComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); boundsComposition->AddChild(borderComposition); } { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Color(6, 176, 37)); progressComposition=new GuiPartialViewComposition; progressComposition->SetWidthRatio(0); progressComposition->SetWidthPageSize(0); progressComposition->SetHeightRatio(0); progressComposition->SetHeightPageSize(1); progressComposition->SetOwnedElement(element); containerComposition->AddChild(progressComposition); } } Win8ProgressBarStyle::~Win8ProgressBarStyle() { } compositions::GuiBoundsComposition* Win8ProgressBarStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8ProgressBarStyle::GetContainerComposition() { return containerComposition; } void Win8ProgressBarStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8ProgressBarStyle::SetText(const WString& value) { } void Win8ProgressBarStyle::SetFont(const FontProperties& value) { } void Win8ProgressBarStyle::SetVisuallyEnabled(bool value) { } void Win8ProgressBarStyle::SetCommandExecutor(controls::GuiScroll::ICommandExecutor* value) { } void Win8ProgressBarStyle::SetTotalSize(vint value) { totalSize=value; UpdateProgressBar(); } void Win8ProgressBarStyle::SetPageSize(vint value) { pageSize=value; UpdateProgressBar(); } void Win8ProgressBarStyle::SetPosition(vint value) { position=value; UpdateProgressBar(); } /*********************************************************************** Win8ScrollViewProvider ***********************************************************************/ Win8ScrollViewProvider::Win8ScrollViewProvider() { } Win8ScrollViewProvider::~Win8ScrollViewProvider() { } void Win8ScrollViewProvider::AssociateStyleController(controls::GuiControl::IStyleController* controller) { } void Win8ScrollViewProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8ScrollViewProvider::SetText(const WString& value) { } void Win8ScrollViewProvider::SetFont(const FontProperties& value) { } void Win8ScrollViewProvider::SetVisuallyEnabled(bool value) { } controls::GuiScroll::IStyleController* Win8ScrollViewProvider::CreateHorizontalScrollStyle() { return new Win8ScrollStyle(Win8ScrollStyle::Horizontal); } controls::GuiScroll::IStyleController* Win8ScrollViewProvider::CreateVerticalScrollStyle() { return new Win8ScrollStyle(Win8ScrollStyle::Vertical); } vint Win8ScrollViewProvider::GetDefaultScrollSize() { return Win8ScrollStyle::DefaultSize; } compositions::GuiGraphicsComposition* Win8ScrollViewProvider::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { GuiSolidBorderElement* border=GuiSolidBorderElement::Create(); border->SetColor(Win8GetSystemBorderColor()); boundsComposition->SetOwnedElement(border); boundsComposition->SetInternalMargin(Margin(1, 1, 1, 1)); GuiSolidBackgroundElement* background=GuiSolidBackgroundElement::Create(); background->SetColor(Win8GetSystemWindowColor()); GuiBoundsComposition* backgroundComposition=new GuiBoundsComposition; boundsComposition->AddChild(backgroundComposition); backgroundComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); backgroundComposition->SetOwnedElement(background); return boundsComposition; } /*********************************************************************** Win8TextBoxBackground ***********************************************************************/ #define HOST_GETTER_BY_FOCUSABLE_COMPOSITION(STYLE) (style->focusableComposition->GetRelatedGraphicsHost()) IMPLEMENT_TRANSFERRING_ANIMATION_BASE(Win8TextBoxColors, Win8TextBoxBackground, HOST_GETTER_BY_FOCUSABLE_COMPOSITION) { colorCurrent=Win8TextBoxColors::Blend(colorBegin, colorEnd, currentPosition, totalLength); style->Apply(colorCurrent); } void Win8TextBoxBackground::UpdateStyle() { if(!isVisuallyEnabled) { transferringAnimation->Transfer(Win8TextBoxColors::Disabled()); } else if(isFocused) { transferringAnimation->Transfer(Win8TextBoxColors::Focused()); } else if(isMouseEnter) { transferringAnimation->Transfer(Win8TextBoxColors::Active()); } else { transferringAnimation->Transfer(Win8TextBoxColors::Normal()); } } void Win8TextBoxBackground::Apply(const Win8TextBoxColors& colors) { borderElement->SetColor(colors.borderColor); backgroundElement->SetColor(colors.backgroundColor); } void Win8TextBoxBackground::OnBoundsMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { isMouseEnter=true; UpdateStyle(); } void Win8TextBoxBackground::OnBoundsMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { isMouseEnter=false; UpdateStyle(); } void Win8TextBoxBackground::OnBoundsGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { isFocused=true; UpdateStyle(); } void Win8TextBoxBackground::OnBoundsLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { isFocused=false; UpdateStyle(); } Win8TextBoxBackground::Win8TextBoxBackground() :backgroundElement(0) ,borderElement(0) ,focusableComposition(0) ,isMouseEnter(false) ,isFocused(false) ,isVisuallyEnabled(false) ,styleController(0) ,textElement(0) { transferringAnimation=new TransferringAnimation(this, Win8TextBoxColors::Normal()); } Win8TextBoxBackground::~Win8TextBoxBackground() { transferringAnimation->Disable(); } void Win8TextBoxBackground::AssociateStyleController(controls::GuiControl::IStyleController* controller) { styleController=controller; } void Win8TextBoxBackground::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { focusableComposition=value; focusableComposition->GetEventReceiver()->mouseEnter.AttachMethod(this, &Win8TextBoxBackground::OnBoundsMouseEnter); focusableComposition->GetEventReceiver()->mouseLeave.AttachMethod(this, &Win8TextBoxBackground::OnBoundsMouseLeave); focusableComposition->GetEventReceiver()->gotFocus.AttachMethod(this, &Win8TextBoxBackground::OnBoundsGotFocus); focusableComposition->GetEventReceiver()->lostFocus.AttachMethod(this, &Win8TextBoxBackground::OnBoundsLostFocus); } void Win8TextBoxBackground::SetVisuallyEnabled(bool value) { isVisuallyEnabled=value; UpdateStyle(); } compositions::GuiGraphicsComposition* Win8TextBoxBackground::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { { GuiSolidBackgroundElement* background=GuiSolidBackgroundElement::Create(); background->SetColor(Color(255, 255, 255)); GuiBoundsComposition* backgroundComposition=new GuiBoundsComposition; boundsComposition->AddChild(backgroundComposition); backgroundComposition->SetAlignmentToParent(Margin(1, 1, 1, 1)); backgroundComposition->SetOwnedElement(background); } { GuiSolidBackgroundElement* background=GuiSolidBackgroundElement::Create(); background->SetColor(Color(255, 255, 255)); GuiBoundsComposition* backgroundComposition=new GuiBoundsComposition; boundsComposition->AddChild(backgroundComposition); backgroundComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); backgroundComposition->SetOwnedElement(background); backgroundElement=background; } { GuiSolidBorderElement* border=GuiSolidBorderElement::Create(); border->SetColor(Win8GetSystemBorderColor()); borderElement=border; GuiBoundsComposition* borderComposition=new GuiBoundsComposition; boundsComposition->AddChild(borderComposition); borderComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); borderComposition->SetOwnedElement(border); } Apply(Win8TextBoxColors::Normal()); { GuiBoundsComposition* containerComposition=new GuiBoundsComposition; boundsComposition->AddChild(containerComposition); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); containerComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); return containerComposition; } } void Win8TextBoxBackground::InitializeTextElement(elements::GuiColorizedTextElement* _textElement) { textElement=_textElement; Array colors; colors.Resize(1); { colors[0]=Win8GetTextBoxTextColor(); } textElement->SetColors(colors); textElement->SetCaretColor(Color(0, 0, 0)); } /*********************************************************************** Win8MultilineTextBoxProvider ***********************************************************************/ Win8MultilineTextBoxProvider::Win8MultilineTextBoxProvider() :styleController(0) { } Win8MultilineTextBoxProvider::~Win8MultilineTextBoxProvider() { } void Win8MultilineTextBoxProvider::AssociateStyleController(controls::GuiControl::IStyleController* controller) { styleController=controller; background.AssociateStyleController(controller); } void Win8MultilineTextBoxProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { background.SetFocusableComposition(value); GuiMultilineTextBox::StyleController* textBoxController=dynamic_cast(styleController); if(textBoxController) { background.InitializeTextElement(textBoxController->GetTextElement()); } } void Win8MultilineTextBoxProvider::SetVisuallyEnabled(bool value) { background.SetVisuallyEnabled(value); } compositions::GuiGraphicsComposition* Win8MultilineTextBoxProvider::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { return background.InstallBackground(boundsComposition); } /*********************************************************************** Win8SinglelineTextBoxProvider ***********************************************************************/ Win8SinglelineTextBoxProvider::Win8SinglelineTextBoxProvider() :styleController(0) { } Win8SinglelineTextBoxProvider::~Win8SinglelineTextBoxProvider() { } void Win8SinglelineTextBoxProvider::AssociateStyleController(controls::GuiControl::IStyleController* controller) { styleController=controller; background.AssociateStyleController(controller); } void Win8SinglelineTextBoxProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { background.SetFocusableComposition(value); GuiSinglelineTextBox::StyleController* textBoxController=dynamic_cast(styleController); background.InitializeTextElement(textBoxController->GetTextElement()); } void Win8SinglelineTextBoxProvider::SetText(const WString& value) { } void Win8SinglelineTextBoxProvider::SetFont(const FontProperties& value) { } void Win8SinglelineTextBoxProvider::SetVisuallyEnabled(bool value) { background.SetVisuallyEnabled(value); } compositions::GuiGraphicsComposition* Win8SinglelineTextBoxProvider::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { return background.InstallBackground(boundsComposition); } /*********************************************************************** Win8DocumentViewerStyle ***********************************************************************/ Win8DocumentViewerStyle::Win8DocumentViewerStyle() { } Win8DocumentViewerStyle::~Win8DocumentViewerStyle() { } Ptr Win8DocumentViewerStyle::GetBaselineDocument() { return nullptr; } /*********************************************************************** Win8DocumentlabelStyle ***********************************************************************/ Win8DocumentLabelStyle::Win8DocumentLabelStyle() { } Win8DocumentLabelStyle::~Win8DocumentLabelStyle() { } Ptr Win8DocumentLabelStyle::GetBaselineDocument() { return nullptr; } /*********************************************************************** Win8DocumentTextBoxStyle ***********************************************************************/ Win8DocumentTextBoxStyle::Win8DocumentTextBoxStyle() { boundsComposition = new GuiBoundsComposition; boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); containerComposition = background.InstallBackground(boundsComposition); background.AssociateStyleController(this); } Win8DocumentTextBoxStyle::~Win8DocumentTextBoxStyle() { } compositions::GuiBoundsComposition* Win8DocumentTextBoxStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8DocumentTextBoxStyle::GetContainerComposition() { return containerComposition; } void Win8DocumentTextBoxStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { background.SetFocusableComposition(value); } void Win8DocumentTextBoxStyle::SetText(const WString& value) { } void Win8DocumentTextBoxStyle::SetFont(const FontProperties& value) { } void Win8DocumentTextBoxStyle::SetVisuallyEnabled(bool value) { background.SetVisuallyEnabled(value); } Ptr Win8DocumentTextBoxStyle::GetBaselineDocument() { return nullptr; } } } } /*********************************************************************** CONTROLS\STYLES\WIN8STYLES\GUIWIN8STYLESCOMMON.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win8ButtonColors ***********************************************************************/ void Win8ButtonColors::SetAlphaWithoutText(unsigned char a) { borderColor.a=a; g1.a=a; g2.a=a; } Win8ButtonColors Win8ButtonColors::Blend(const Win8ButtonColors& c1, const Win8ButtonColors& c2, vint ratio, vint total) { if(ratio<0) ratio=0; else if(ratio>total) ratio=total; Win8ButtonColors result; result.borderColor=BlendColor(c1.borderColor, c2.borderColor, ratio, total); result.g1=BlendColor(c1.g1, c2.g1, ratio, total); result.g2=BlendColor(c1.g2, c2.g2, ratio, total); result.textColor=BlendColor(c1.textColor, c2.textColor, ratio, total); result.bullet=BlendColor(c1.bullet, c2.bullet, ratio, total); return result; } //--------------------------------------------------------- Win8ButtonColors Win8ButtonColors::ButtonNormal() { Win8ButtonColors colors= { Color(172, 172, 172), Color(239, 239, 239), Color(229, 229, 229), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ButtonActive() { Win8ButtonColors colors= { Color(126, 180, 234), Color(235, 244, 252), Color(220, 236, 252), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ButtonPressed() { Win8ButtonColors colors= { Color(86, 157, 229), Color(218, 236, 252), Color(196, 224, 252), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ButtonDisabled() { Win8ButtonColors colors= { Color(173, 178, 181), Color(252, 252, 252), Color(252, 252, 252), Win8GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win8ButtonColors Win8ButtonColors::ItemNormal() { Win8ButtonColors colors= { Color(112, 192, 231, 0), Color(229, 243, 251, 0), Color(229, 243, 251, 0), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ItemActive() { Win8ButtonColors colors= { Color(112, 192, 231), Color(229, 243, 251), Color(229, 243, 251), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ItemSelected() { Win8ButtonColors colors= { Color(102, 167, 232), Color(209, 232, 255), Color(209, 232, 255), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ItemDisabled() { Win8ButtonColors colors= { Color(112, 192, 231, 0), Color(229, 243, 251, 0), Color(229, 243, 251, 0), Win8GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win8ButtonColors Win8ButtonColors::CheckedNormal(bool selected) { Win8ButtonColors colors= { Color(112, 112, 112), Color(255, 255, 255), Color(255, 255, 255), Win8GetSystemTextColor(true), Color(0, 0, 0), }; if(!selected) { colors.bullet.a=0; } return colors; } Win8ButtonColors Win8ButtonColors::CheckedActive(bool selected) { Win8ButtonColors colors= { Color(51, 153, 255), Color(243, 249, 255), Color(243, 249, 255), Win8GetSystemTextColor(true), Color(33, 33, 33), }; if(!selected) { colors.bullet.a=0; } return colors; } Win8ButtonColors Win8ButtonColors::CheckedPressed(bool selected) { Win8ButtonColors colors= { Color(0, 124, 222), Color(217, 236, 255), Color(217, 236, 255), Win8GetSystemTextColor(true), Color(0, 0, 0), }; if(!selected) { colors.bullet.a=0; } return colors; } Win8ButtonColors Win8ButtonColors::CheckedDisabled(bool selected) { Win8ButtonColors colors= { Color(188, 188, 188), Color(230, 230, 230), Color(230, 230, 230), Win8GetSystemTextColor(false), Color(112, 112, 112), }; if(!selected) { colors.bullet.a=0; } return colors; } //--------------------------------------------------------- Win8ButtonColors Win8ButtonColors::ToolstripButtonNormal() { Win8ButtonColors colors= { Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ToolstripButtonActive() { Win8ButtonColors colors= { Color(120, 174, 229), Color(209, 226, 242), Color(209, 226, 242), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ToolstripButtonPressed() { Win8ButtonColors colors= { Color(96, 161, 226), Color(180, 212, 244), Color(180, 212, 244), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ToolstripButtonSelected() { Win8ButtonColors colors= { Color(96, 161, 226), Color(233, 241, 250), Color(233, 241, 250), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::ToolstripButtonDisabled() { Win8ButtonColors colors= { Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Win8GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win8ButtonColors Win8ButtonColors::ScrollHandleNormal() { Win8ButtonColors colors= { Color(205, 205, 205), Color(205, 205, 205), Color(205, 205, 205), }; return colors; } Win8ButtonColors Win8ButtonColors::ScrollHandleActive() { Win8ButtonColors colors= { Color(166, 166, 166), Color(166, 166, 166), Color(166, 166, 166), }; return colors; } Win8ButtonColors Win8ButtonColors::ScrollHandlePressed() { Win8ButtonColors colors= { Color(166, 166, 166), Color(166, 166, 166), Color(166, 166, 166), }; return colors; } Win8ButtonColors Win8ButtonColors::ScrollHandleDisabled() { Win8ButtonColors colors= { Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), }; return colors; } Win8ButtonColors Win8ButtonColors::ScrollArrowNormal() { Win8ButtonColors colors= { Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Color(96, 96, 96), }; return colors; } Win8ButtonColors Win8ButtonColors::ScrollArrowActive() { Win8ButtonColors colors= { Color(218, 218, 218), Color(218, 218, 218), Color(218, 218, 218), Color(0, 0, 0), }; return colors; } Win8ButtonColors Win8ButtonColors::ScrollArrowPressed() { Win8ButtonColors colors= { Color(96, 96, 96), Color(96, 96, 96), Color(96, 96, 96), Color(255, 255, 255), }; return colors; } Win8ButtonColors Win8ButtonColors::ScrollArrowDisabled() { Win8ButtonColors colors= { Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Win8GetSystemWindowColor(), Color(191, 191, 191), }; return colors; } //--------------------------------------------------------- Win8ButtonColors Win8ButtonColors::MenuBarButtonNormal() { Win8ButtonColors colors= { Color(245, 246, 247), Color(245, 246, 247), Color(245, 246, 247), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::MenuBarButtonActive() { Win8ButtonColors colors= { Color(122, 177, 232), Color(213, 231, 248), Color(213, 231, 248), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::MenuBarButtonPressed() { Win8ButtonColors colors= { Color(98, 163, 229), Color(184, 216, 249), Color(184, 216, 249), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::MenuBarButtonDisabled() { Win8ButtonColors colors= { Color(245, 246, 247), Color(245, 246, 247), Color(245, 246, 247), Win8GetSystemTextColor(false), }; return colors; } //--------------------------------------------------------- Win8ButtonColors Win8ButtonColors::MenuItemButtonNormal() { Win8ButtonColors colors= { Color(240, 240, 240), Color(240, 240, 240), Color(240, 240, 240), Win8GetSystemTextColor(true), Win8GetMenuSplitterColor(), }; return colors; } Win8ButtonColors Win8ButtonColors::MenuItemButtonNormalActive() { Win8ButtonColors colors= { Color(120, 174, 229), Color(209, 226, 242), Color(209, 226, 242), Win8GetSystemTextColor(true), Color(187, 204, 220), }; return colors; } Win8ButtonColors Win8ButtonColors::MenuItemButtonSelected() { Win8ButtonColors colors= { Color(120, 174, 229), Color(233, 241, 250), Color(233, 241, 250), Win8GetSystemTextColor(true), Color(233, 241, 250), }; return colors; } Win8ButtonColors Win8ButtonColors::MenuItemButtonSelectedActive() { Win8ButtonColors colors= { Color(120, 174, 229), Color(233, 241, 250), Color(233, 241, 250), Win8GetSystemTextColor(true), Color(187, 204, 220), }; return colors; } Win8ButtonColors Win8ButtonColors::MenuItemButtonDisabled() { Win8ButtonColors colors= { Color(240, 240, 240), Color(240, 240, 240), Color(240, 240, 240), Win8GetSystemTextColor(false), Win8GetMenuSplitterColor(), }; return colors; } Win8ButtonColors Win8ButtonColors::MenuItemButtonDisabledActive() { Win8ButtonColors colors= { Color(120, 174, 229), Color(209, 226, 242), Color(209, 226, 242), Win8GetSystemTextColor(false), Win8GetMenuSplitterColor(), }; return colors; } Win8ButtonColors Win8ButtonColors::TabPageHeaderNormal() { Win8ButtonColors colors= { Color(172, 172, 172), Color(239, 239, 239), Color(229, 229, 229), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::TabPageHeaderActive() { Win8ButtonColors colors= { Color(126, 180, 234), Color(236, 244, 252), Color(221, 237, 252), Win8GetSystemTextColor(true), }; return colors; } Win8ButtonColors Win8ButtonColors::TabPageHeaderSelected() { Win8ButtonColors colors= { Color(172, 172, 172), Color(255, 255, 255), Color(255, 255, 255), Win8GetSystemTextColor(true), }; return colors; } /*********************************************************************** Win8ButtonElements ***********************************************************************/ Win8ButtonElements Win8ButtonElements::Create(Alignment horizontal, Alignment vertical) { Win8ButtonElements button; { button.mainComposition=new GuiBoundsComposition; button.mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); button.rectBorderElement=element; GuiBoundsComposition* composition=new GuiBoundsComposition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); composition->SetOwnedElement(element); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); button.backgroundElement=element; element->SetDirection(GuiGradientBackgroundElement::Vertical); element->SetShape(ElementShape::Rectangle); GuiBoundsComposition* composition=new GuiBoundsComposition; button.backgroundComposition=composition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(1, 1, 1, 1)); composition->SetOwnedElement(element); } { Win8CreateSolidLabelElement(button.textElement, button.textComposition, horizontal, vertical); button.mainComposition->AddChild(button.textComposition); } return button; } void Win8ButtonElements::Apply(const Win8ButtonColors& colors) { if(rectBorderElement) { rectBorderElement->SetColor(colors.borderColor); } backgroundElement->SetColors(colors.g1, colors.g2); textElement->SetColor(colors.textColor); } /*********************************************************************** Win8CheckedButtonElements ***********************************************************************/ Win8CheckedButtonElements Win8CheckedButtonElements::Create(elements::ElementShape shape, bool backgroundVisible) { const vint checkSize=13; const vint checkPadding=2; Win8CheckedButtonElements button; { button.mainComposition=new GuiBoundsComposition; button.mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } { GuiTableComposition* mainTable=new GuiTableComposition; button.mainComposition->AddChild(mainTable); if(backgroundVisible) { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); mainTable->SetOwnedElement(element); } mainTable->SetRowsAndColumns(1, 2); mainTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); mainTable->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); mainTable->SetColumnOption(0, GuiCellOption::AbsoluteOption(checkSize+2*checkPadding)); mainTable->SetColumnOption(1, GuiCellOption::PercentageOption(1.0)); { GuiCellComposition* cell=new GuiCellComposition; mainTable->AddChild(cell); cell->SetSite(0, 0, 1, 1); GuiTableComposition* table=new GuiTableComposition; cell->AddChild(table); table->SetRowsAndColumns(3, 1); table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); table->SetRowOption(1, GuiCellOption::MinSizeOption()); table->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); { GuiCellComposition* checkCell=new GuiCellComposition; table->AddChild(checkCell); checkCell->SetSite(1, 0, 1, 1); { GuiBoundsComposition* borderBounds=new GuiBoundsComposition; checkCell->AddChild(borderBounds); borderBounds->SetAlignmentToParent(Margin(checkPadding, -1, checkPadding, -1)); borderBounds->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); button.bulletBorderElement=element; element->SetShape(shape); GuiBoundsComposition* bounds=new GuiBoundsComposition; borderBounds->AddChild(bounds); bounds->SetOwnedElement(element); bounds->SetAlignmentToParent(Margin(0, 0, 0, 0)); bounds->SetBounds(Rect(Point(0, 0), Size(checkSize, checkSize))); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); button.bulletBackgroundElement=element; element->SetShape(shape); element->SetDirection(GuiGradientBackgroundElement::Vertical); GuiBoundsComposition* bounds=new GuiBoundsComposition; borderBounds->AddChild(bounds); bounds->SetOwnedElement(element); bounds->SetAlignmentToParent(Margin(1, 1, 1, 1)); } } button.bulletCheckElement=0; button.bulletRadioElement=0; if(shape==ElementShape::Rectangle) { button.bulletCheckElement=GuiSolidLabelElement::Create(); { FontProperties font; font.fontFamily=L"Webdings"; font.size=16; font.bold=true; button.bulletCheckElement->SetFont(font); } button.bulletCheckElement->SetText(L"a"); button.bulletCheckElement->SetAlignments(Alignment::Center, Alignment::Center); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetOwnedElement(button.bulletCheckElement); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); checkCell->AddChild(composition); } else { button.bulletRadioElement=GuiSolidBackgroundElement::Create(); button.bulletRadioElement->SetShape(ElementShape::Ellipse); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetOwnedElement(button.bulletRadioElement); composition->SetAlignmentToParent(Margin(checkPadding+3, 3, checkPadding+3, 3)); checkCell->AddChild(composition); } } } { GuiCellComposition* textCell=new GuiCellComposition; mainTable->AddChild(textCell); textCell->SetSite(0, 1, 1, 1); { Win8CreateSolidLabelElement(button.textElement, button.textComposition, Alignment::Left, Alignment::Center); textCell->AddChild(button.textComposition); } } } return button; } void Win8CheckedButtonElements::Apply(const Win8ButtonColors& colors) { bulletBorderElement->SetColor(colors.borderColor); bulletBackgroundElement->SetColors(colors.g1, colors.g2); textElement->SetColor(colors.textColor); if(bulletCheckElement) { bulletCheckElement->SetColor(colors.bullet); } if(bulletRadioElement) { bulletRadioElement->SetColor(colors.bullet); } } /*********************************************************************** Win8MenuItemButtonElements ***********************************************************************/ Win8MenuItemButtonElements Win8MenuItemButtonElements::Create() { Win8MenuItemButtonElements button; { button.mainComposition=new GuiBoundsComposition; button.mainComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } { GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); button.borderElement=element; GuiBoundsComposition* composition=new GuiBoundsComposition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); composition->SetOwnedElement(element); } { GuiGradientBackgroundElement* element=GuiGradientBackgroundElement::Create(); button.backgroundElement=element; element->SetDirection(GuiGradientBackgroundElement::Vertical); GuiBoundsComposition* composition=new GuiBoundsComposition; button.mainComposition->AddChild(composition); composition->SetAlignmentToParent(Margin(1, 1, 1, 1)); composition->SetOwnedElement(element); } { GuiTableComposition* table=new GuiTableComposition; button.mainComposition->AddChild(table); table->SetAlignmentToParent(Margin(2, 0, 2, 0)); table->SetRowsAndColumns(1, 5); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::AbsoluteOption(24)); table->SetColumnOption(1, GuiCellOption::AbsoluteOption(1)); table->SetColumnOption(2, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(3, GuiCellOption::MinSizeOption()); table->SetColumnOption(4, GuiCellOption::AbsoluteOption(10)); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 0, 1, 1); button.splitterComposition=cell; GuiImageFrameElement* element=GuiImageFrameElement::Create(); button.imageElement=element; element->SetStretch(false); element->SetAlignments(Alignment::Center, Alignment::Center); cell->SetOwnedElement(element); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 1, 1); button.splitterComposition=cell; GuiSolidBorderElement* element=GuiSolidBorderElement::Create(); button.splitterElement=element; cell->SetOwnedElement(element); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 2, 1, 1); Win8CreateSolidLabelElement(button.textElement, button.textComposition, L"MenuItem-Text", Alignment::Left, Alignment::Center); cell->AddChild(button.textComposition); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 3, 1, 1); Win8CreateSolidLabelElement(button.shortcutElement, button.shortcutComposition, L"MenuItem-Shortcut", Alignment::Right, Alignment::Center); cell->AddChild(button.shortcutComposition); } { button.subMenuArrowElement=common_styles::CommonFragmentBuilder::BuildRightArrow(); GuiCellComposition* cell=new GuiCellComposition; button.subMenuArrowComposition=cell; cell->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); table->AddChild(cell); cell->SetSite(0, 4, 1, 1); cell->SetOwnedElement(button.subMenuArrowElement); cell->SetVisible(false); } } return button; } void Win8MenuItemButtonElements::Apply(const Win8ButtonColors& colors) { borderElement->SetColor(colors.borderColor); backgroundElement->SetColors(colors.g1, colors.g2); splitterElement->SetColor(colors.bullet); textElement->SetColor(colors.textColor); shortcutElement->SetColor(colors.textColor); subMenuArrowElement->SetBackgroundColor(colors.textColor); subMenuArrowElement->SetBorderColor(colors.textColor); } void Win8MenuItemButtonElements::SetActive(bool value) { if(value) { splitterComposition->SetMargin(Margin(0, 1, 0, 2)); } else { splitterComposition->SetMargin(Margin(0, 0, 0, 0)); } } void Win8MenuItemButtonElements::SetSubMenuExisting(bool value) { subMenuArrowComposition->SetVisible(value); } /*********************************************************************** Win8TextBoxColors ***********************************************************************/ Win8TextBoxColors Win8TextBoxColors::Blend(const Win8TextBoxColors& c1, const Win8TextBoxColors& c2, vint ratio, vint total) { if(ratio<0) ratio=0; else if(ratio>total) ratio=total; Win8TextBoxColors result; result.borderColor=BlendColor(c1.borderColor, c2.borderColor, ratio, total); result.backgroundColor=BlendColor(c1.backgroundColor, c2.backgroundColor, ratio, total); return result; } Win8TextBoxColors Win8TextBoxColors::Normal() { Win8TextBoxColors result= { Color(171, 173, 179), Color(255, 255, 255), }; return result; } Win8TextBoxColors Win8TextBoxColors::Active() { Win8TextBoxColors result= { Color(126, 180, 234), Color(255, 255, 255), }; return result; } Win8TextBoxColors Win8TextBoxColors::Focused() { Win8TextBoxColors result= { Color(86, 157, 229), Color(255, 255, 255), }; return result; } Win8TextBoxColors Win8TextBoxColors::Disabled() { Win8TextBoxColors result= { Color(217, 217, 217), Win8GetSystemWindowColor(), }; return result; } /*********************************************************************** Helpers ***********************************************************************/ Color Win8GetSystemWindowColor() { return Color(240, 240, 240); } Color Win8GetSystemTabContentColor() { return Color(255, 255, 255); } Color Win8GetSystemBorderColor() { return Color(171, 173, 179); } Color Win8GetSystemTextColor(bool enabled) { return enabled?Color(0, 0, 0):Color(131, 131, 131); } Color Win8GetMenuBorderColor() { return Color(151, 151, 151); } Color Win8GetMenuSplitterColor() { return Color(215, 215, 215); } void Win8SetFont(GuiSolidLabelElement* element, GuiBoundsComposition* composition, const FontProperties& fontProperties) { vint margin=3; element->SetFont(fontProperties); composition->SetMargin(Margin(margin, margin, margin, margin)); } void Win8CreateSolidLabelElement(GuiSolidLabelElement*& element, GuiBoundsComposition*& composition, Alignment horizontal, Alignment vertical) { element=GuiSolidLabelElement::Create(); element->SetAlignments(horizontal, vertical); composition=new GuiBoundsComposition; composition->SetOwnedElement(element); composition->SetMargin(Margin(0, 0, 0, 0)); composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); } void Win8CreateSolidLabelElement(elements::GuiSolidLabelElement*& element, compositions::GuiSharedSizeItemComposition*& composition, const WString& group, Alignment horizontal, Alignment vertical) { element=GuiSolidLabelElement::Create(); element->SetAlignments(horizontal, vertical); composition=new GuiSharedSizeItemComposition; composition->SetGroup(group); composition->SetSharedWidth(true); composition->SetOwnedElement(element); composition->SetMargin(Margin(0, 0, 0, 0)); composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); composition->SetAlignmentToParent(Margin(0, 0, 0, 0)); } elements::text::ColorEntry Win8GetTextBoxTextColor() { elements::text::ColorEntry entry; entry.normal.text=Color(0, 0, 0); entry.normal.background=Color(0, 0, 0, 0); entry.selectedFocused.text=Color(255, 255, 255); entry.selectedFocused.background=Color(51, 153, 255); entry.selectedUnfocused.text=Color(255, 255, 255); entry.selectedUnfocused.background=Color(51, 153, 255); return entry; } } } } /*********************************************************************** CONTROLS\STYLES\WIN8STYLES\GUIWIN8TABSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace controls; /*********************************************************************** Win8TabPageHeaderStyle ***********************************************************************/ void Win8TabPageHeaderStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected) { if(selected) { transferringAnimation->Transfer(Win8ButtonColors::TabPageHeaderSelected()); } else { switch(value) { case GuiButton::Normal: transferringAnimation->Transfer(Win8ButtonColors::TabPageHeaderNormal()); break; case GuiButton::Active: case GuiButton::Pressed: transferringAnimation->Transfer(Win8ButtonColors::TabPageHeaderActive()); break; } } } Win8TabPageHeaderStyle::Win8TabPageHeaderStyle() :Win8ButtonStyleBase(Win8ButtonColors::TabPageHeaderNormal(), Alignment::Left, Alignment::Center) { transferringAnimation->SetEnableAnimation(false); { Margin margin=elements.backgroundComposition->GetAlignmentToParent(); margin.bottom=0; elements.backgroundComposition->SetAlignmentToParent(margin); } } Win8TabPageHeaderStyle::~Win8TabPageHeaderStyle() { } void Win8TabPageHeaderStyle::SetFont(const FontProperties& value) { Win8ButtonStyleBase::SetFont(value); Margin margin=elements.textComposition->GetMargin(); margin.left*=2; margin.right*=2; elements.textComposition->SetMargin(margin); } /*********************************************************************** Win8TabStyle ***********************************************************************/ controls::GuiSelectableButton::IStyleController* Win8TabStyle::CreateHeaderStyleController() { return new Win8TabPageHeaderStyle; } controls::GuiButton::IStyleController* Win8TabStyle::CreateMenuButtonStyleController() { return new Win8ButtonStyle; } controls::GuiToolstripMenu::IStyleController* Win8TabStyle::CreateMenuStyleController() { return new Win8MenuStyle; } controls::GuiToolstripButton::IStyleController* Win8TabStyle::CreateMenuItemStyleController() { return new Win8MenuItemButtonStyle; } Color Win8TabStyle::GetBorderColor() { return Win8ButtonColors::TabPageHeaderNormal().borderColor; } Color Win8TabStyle::GetBackgroundColor() { return Win8GetSystemTabContentColor(); } Win8TabStyle::Win8TabStyle() :Win7TabStyle(false) { Initialize(); } Win8TabStyle::~Win8TabStyle() { } } } } /*********************************************************************** CONTROLS\STYLES\WIN8STYLES\GUIWIN8TOOLSTRIPSTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace win8 { using namespace collections; using namespace elements; using namespace compositions; using namespace controls; /*********************************************************************** Win8WindowStyle ***********************************************************************/ Win8ToolstripToolBarStyle::Win8ToolstripToolBarStyle() { { GuiSolidBackgroundElement* element=GuiSolidBackgroundElement::Create(); element->SetColor(Win8GetSystemWindowColor()); boundsComposition=new GuiBoundsComposition; boundsComposition->SetOwnedElement(element); boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } { Gui3DSplitterElement* element=Gui3DSplitterElement::Create(); element->SetColors(Color(160, 160, 160), Color(255, 255, 255)); element->SetDirection(Gui3DSplitterElement::Horizontal); GuiBoundsComposition* composition=new GuiBoundsComposition; composition->SetPreferredMinSize(Size(0, 2)); composition->SetAlignmentToParent(Margin(0, 0, 0, -1)); composition->SetOwnedElement(element); boundsComposition->AddChild(composition); } { containerComposition=new GuiBoundsComposition; containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); containerComposition->SetAlignmentToParent(Margin(0, 2, 0, 0)); boundsComposition->AddChild(containerComposition); } } Win8ToolstripToolBarStyle::~Win8ToolstripToolBarStyle() { } compositions::GuiBoundsComposition* Win8ToolstripToolBarStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8ToolstripToolBarStyle::GetContainerComposition() { return containerComposition; } void Win8ToolstripToolBarStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8ToolstripToolBarStyle::SetText(const WString& value) { } void Win8ToolstripToolBarStyle::SetFont(const FontProperties& value) { } void Win8ToolstripToolBarStyle::SetVisuallyEnabled(bool value) { } /*********************************************************************** Win8ToolstripButtonDropdownStyle ***********************************************************************/ void Win8ToolstripButtonDropdownStyle::TransferInternal(controls::GuiButton::ControlState value, bool enabled) { splitterComposition->SetVisible(value!=GuiButton::Normal && enabled); } Win8ToolstripButtonDropdownStyle::Win8ToolstripButtonDropdownStyle() :isVisuallyEnabled(false) ,controlState(GuiButton::Normal) { boundsComposition=new GuiBoundsComposition; boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); { GuiSolidBorderElement* splitterElement=GuiSolidBorderElement::Create(); splitterElement->SetColor(Color(132, 132, 132)); splitterComposition=new GuiBoundsComposition; splitterComposition->SetAlignmentToParent(Margin(0, 3, -1, 3)); splitterComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); splitterComposition->SetOwnedElement(splitterElement); splitterComposition->SetPreferredMinSize(Size(1, 0)); splitterComposition->SetVisible(false); boundsComposition->AddChild(splitterComposition); } { containerComposition=new GuiBoundsComposition; containerComposition->SetAlignmentToParent(Margin(4, 0, 4, 0)); containerComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition->AddChild(containerComposition); } } Win8ToolstripButtonDropdownStyle::~Win8ToolstripButtonDropdownStyle() { } compositions::GuiBoundsComposition* Win8ToolstripButtonDropdownStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8ToolstripButtonDropdownStyle::GetContainerComposition() { return containerComposition; } void Win8ToolstripButtonDropdownStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8ToolstripButtonDropdownStyle::SetText(const WString& value) { } void Win8ToolstripButtonDropdownStyle::SetFont(const FontProperties& value) { } void Win8ToolstripButtonDropdownStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; TransferInternal(controlState, isVisuallyEnabled); } } void Win8ToolstripButtonDropdownStyle::Transfer(controls::GuiButton::ControlState value) { if(controlState!=value) { controlState=value; TransferInternal(controlState, isVisuallyEnabled); } } /*********************************************************************** Win8ToolstripButtonStyle ***********************************************************************/ IMPLEMENT_TRANSFERRING_ANIMATION(Win8ButtonColors, Win8ToolstripButtonStyle) { colorCurrent=Win8ButtonColors::Blend(colorBegin, colorEnd, currentPosition, totalLength); style->elements.Apply(colorCurrent); } void Win8ToolstripButtonStyle::TransferInternal(GuiButton::ControlState value, bool enabled, bool selected, bool menuOpening) { Win8ButtonColors targetColor; if(enabled) { if(menuOpening) { value=GuiButton::Pressed; } switch(value) { case GuiButton::Normal: targetColor=selected?Win8ButtonColors::ToolstripButtonSelected():Win8ButtonColors::ToolstripButtonNormal(); break; case GuiButton::Active: targetColor=selected?Win8ButtonColors::ToolstripButtonSelected():Win8ButtonColors::ToolstripButtonActive(); break; case GuiButton::Pressed: targetColor=Win8ButtonColors::ToolstripButtonPressed(); break; } } else { targetColor=Win8ButtonColors::ToolstripButtonDisabled(); } transferringAnimation->Transfer(targetColor); } Win8ToolstripButtonStyle::Win8ToolstripButtonStyle(ButtonStyle _buttonStyle) :controlStyle(GuiButton::Normal) ,isVisuallyEnabled(true) ,isSelected(false) ,isOpening(false) ,buttonStyle(_buttonStyle) ,subMenuHost(0) { elements=Win8ButtonElements::Create(Alignment::Center, Alignment::Center); elements.Apply(Win8ButtonColors::ToolstripButtonNormal()); transferringAnimation=new TransferringAnimation(this, Win8ButtonColors::ToolstripButtonNormal()); elements.textComposition->SetMinSizeLimitation(GuiGraphicsComposition::NoLimit); imageElement=GuiImageFrameElement::Create(); imageComposition=new GuiBoundsComposition; imageComposition->SetOwnedElement(imageElement); imageComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); imageComposition->SetAlignmentToParent(Margin(4, 4, 4, 4)); if(_buttonStyle==CommandButton) { GetContainerComposition()->AddChild(imageComposition); } else { GuiTableComposition* table=new GuiTableComposition; table->SetAlignmentToParent(Margin(0, 0, 0, 0)); table->SetRowsAndColumns(1, 2); table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); table->SetColumnOption(1, GuiCellOption::MinSizeOption()); { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 0, 1, 1); cell->AddChild(imageComposition); } { GuiCellComposition* cell=new GuiCellComposition; table->AddChild(cell); cell->SetSite(0, 1, 1, 1); GuiPolygonElement* arrow=0; GuiBoundsComposition* arrowComposition=common_styles::CommonFragmentBuilder::BuildDownArrow(arrow); switch(_buttonStyle) { case DropdownButton: { arrowComposition->SetAlignmentToParent(Margin(0, 0, 4, 0)); cell->AddChild(arrowComposition); } break; case SplitButton: { subMenuHost=new GuiButton(new Win8ToolstripButtonDropdownStyle); subMenuHost->GetContainerComposition()->AddChild(arrowComposition); subMenuHost->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); cell->AddChild(subMenuHost->GetBoundsComposition()); } break; default:; } } GetContainerComposition()->AddChild(table); } } Win8ToolstripButtonStyle::~Win8ToolstripButtonStyle() { transferringAnimation->Disable(); } compositions::GuiBoundsComposition* Win8ToolstripButtonStyle::GetBoundsComposition() { return elements.mainComposition; } compositions::GuiGraphicsComposition* Win8ToolstripButtonStyle::GetContainerComposition() { return elements.mainComposition; } void Win8ToolstripButtonStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8ToolstripButtonStyle::SetText(const WString& value) { } void Win8ToolstripButtonStyle::SetFont(const FontProperties& value) { Win8SetFont(elements.textElement, elements.textComposition, value); } void Win8ToolstripButtonStyle::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; imageElement->SetEnabled(value); TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } void Win8ToolstripButtonStyle::SetSelected(bool value) { if(isSelected!=value) { isSelected=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } controls::GuiMenu::IStyleController* Win8ToolstripButtonStyle::CreateSubMenuStyleController() { return new Win8MenuStyle; } void Win8ToolstripButtonStyle::SetSubMenuExisting(bool value) { } void Win8ToolstripButtonStyle::SetSubMenuOpening(bool value) { if(isOpening!=value) { isOpening=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } controls::GuiButton* Win8ToolstripButtonStyle::GetSubMenuHost() { return subMenuHost; } void Win8ToolstripButtonStyle::SetImage(Ptr value) { if(value) { imageElement->SetImage(value->GetImage(), value->GetFrameIndex()); } else { imageElement->SetImage(0, 0); } } void Win8ToolstripButtonStyle::SetShortcutText(const WString& value) { } void Win8ToolstripButtonStyle::Transfer(controls::GuiButton::ControlState value) { if(controlStyle!=value) { controlStyle=value; TransferInternal(controlStyle, isVisuallyEnabled, isSelected, isOpening); } } /*********************************************************************** Win8ToolstripSplitterStyle ***********************************************************************/ Win8ToolstripSplitterStyle::Win8ToolstripSplitterStyle() { GuiBoundsComposition* bounds=new GuiBoundsComposition; bounds->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); boundsComposition=bounds; GuiSolidBackgroundElement* backgroundElement=GuiSolidBackgroundElement::Create(); bounds->SetOwnedElement(backgroundElement); backgroundElement->SetColor(Win8GetSystemWindowColor()); GuiBoundsComposition* splitterComposition=new GuiBoundsComposition; bounds->AddChild(splitterComposition); splitterComposition->SetPreferredMinSize(Size(1, 0)); splitterComposition->SetAlignmentToParent(Margin(3, 3, 3, 3)); GuiSolidBorderElement* splitterElement=GuiSolidBorderElement::Create(); splitterComposition->SetOwnedElement(splitterElement); splitterElement->SetColor(Color(132, 132, 132)); } Win8ToolstripSplitterStyle::~Win8ToolstripSplitterStyle() { } compositions::GuiBoundsComposition* Win8ToolstripSplitterStyle::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* Win8ToolstripSplitterStyle::GetContainerComposition() { return boundsComposition; } void Win8ToolstripSplitterStyle::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { } void Win8ToolstripSplitterStyle::SetText(const WString& value) { } void Win8ToolstripSplitterStyle::SetFont(const FontProperties& value) { } void Win8ToolstripSplitterStyle::SetVisuallyEnabled(bool value) { } } } } /*********************************************************************** CONTROLS\TEMPLATES\GUICONTROLTEMPLATES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace templates { using namespace description; using namespace collections; using namespace controls; using namespace compositions; /*********************************************************************** GuiTemplate::IFactory ***********************************************************************/ class GuiTemplateReflectableFactory : public Object, public virtual GuiTemplate::IFactory { protected: List types; public: GuiTemplateReflectableFactory(const List& _types) { CopyFrom(types, _types); } GuiTemplate* CreateTemplate(const description::Value& viewModel)override { FOREACH(ITypeDescriptor*, type, types) { auto group = type->GetConstructorGroup(); vint count = group->GetMethodCount(); for (vint i = 0; i < count; i++) { auto ctor = group->GetMethod(i); if (ctor->GetReturn()->GetDecorator() == ITypeInfo::RawPtr && ctor->GetParameterCount() <= 1) { Array arguments(ctor->GetParameterCount()); if (ctor->GetParameterCount() == 1) { if (!viewModel.CanConvertTo(ctor->GetParameter(0)->GetType())) { continue; } arguments[0] = viewModel; } return dynamic_cast(ctor->Invoke(Value(), arguments).GetRawPtr()); } } } WString message = L"Unable to create a template from types {"; FOREACH_INDEXER(ITypeDescriptor*, type, index, types) { if (index > 0) message += L", "; message += type->GetTypeName(); } message += L"} using view model: "; if (viewModel.IsNull()) { message += L"null."; } else { message += viewModel.GetTypeDescriptor()->GetTypeName() + L"."; } throw ArgumentException(message); } }; Ptr GuiTemplate::IFactory::CreateTemplateFactory(const collections::List& types) { return new GuiTemplateReflectableFactory(types); } /*********************************************************************** GuiTemplate ***********************************************************************/ GuiTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiTemplate::GuiTemplate() :VisuallyEnabled_(true) { GuiTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiTemplate::~GuiTemplate() { FinalizeInstance(); } /*********************************************************************** GuiControlTemplate ***********************************************************************/ GuiControlTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiControlTemplate::GuiControlTemplate() :ContainerComposition_(this) , FocusableComposition_(0) { GuiControlTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiControlTemplate::~GuiControlTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiLabelTemplate ***********************************************************************/ GuiLabelTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiLabelTemplate::GuiLabelTemplate() { GuiLabelTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiLabelTemplate::~GuiLabelTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiSinglelineTextBoxTemplate ***********************************************************************/ GuiSinglelineTextBoxTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiSinglelineTextBoxTemplate::GuiSinglelineTextBoxTemplate() { GuiSinglelineTextBoxTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiSinglelineTextBoxTemplate::~GuiSinglelineTextBoxTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiDocumentLabelTemplate ***********************************************************************/ GuiDocumentLabelTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiDocumentLabelTemplate::GuiDocumentLabelTemplate() { GuiDocumentLabelTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiDocumentLabelTemplate::~GuiDocumentLabelTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiMenuTemplate ***********************************************************************/ GuiMenuTemplate::GuiMenuTemplate() { } GuiMenuTemplate::~GuiMenuTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiWindowTemplate ***********************************************************************/ GuiWindowTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiWindowTemplate::GuiWindowTemplate() :MaximizedBoxOption_(BoolOption::Customizable) , MinimizedBoxOption_(BoolOption::Customizable) , BorderOption_(BoolOption::Customizable) , SizeBoxOption_(BoolOption::Customizable) , IconVisibleOption_(BoolOption::Customizable) , TitleBarOption_(BoolOption::Customizable) , MaximizedBox_(true) , MinimizedBox_(true) , Border_(true) , SizeBox_(true) , IconVisible_(true) , TitleBar_(true) , CustomizedBorder_(false) , Maximized_(false) { GuiWindowTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiWindowTemplate::~GuiWindowTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiButtonTemplate ***********************************************************************/ GuiButtonTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiButtonTemplate::GuiButtonTemplate() :State_(GuiButton::Normal) { GuiButtonTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiButtonTemplate::~GuiButtonTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiSelectableButtonTemplate ***********************************************************************/ GuiSelectableButtonTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiSelectableButtonTemplate::GuiSelectableButtonTemplate() :Selected_(false) { GuiSelectableButtonTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiSelectableButtonTemplate::~GuiSelectableButtonTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiToolstripButtonTemplate ***********************************************************************/ GuiToolstripButtonTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiToolstripButtonTemplate::GuiToolstripButtonTemplate() :SubMenuExisting_(false) , SubMenuOpening_(false) , SubMenuHost_(0) { GuiToolstripButtonTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiToolstripButtonTemplate::~GuiToolstripButtonTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiListViewColumnHeaderTemplate ***********************************************************************/ GuiListViewColumnHeaderTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiListViewColumnHeaderTemplate::GuiListViewColumnHeaderTemplate() :SortingState_(GuiListViewColumnHeader::NotSorted) { GuiListViewColumnHeaderTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiListViewColumnHeaderTemplate::~GuiListViewColumnHeaderTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiComboBoxTemplate ***********************************************************************/ GuiComboBoxTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiComboBoxTemplate::GuiComboBoxTemplate() :Commands_(0) , TextVisible_(true) { GuiComboBoxTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiComboBoxTemplate::~GuiComboBoxTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiDatePickerTemplate ***********************************************************************/ GuiDatePickerTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiDatePickerTemplate::GuiDatePickerTemplate() { GuiDatePickerTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiDatePickerTemplate::~GuiDatePickerTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiDateComboBoxTemplate ***********************************************************************/ GuiDateComboBoxTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiDateComboBoxTemplate::GuiDateComboBoxTemplate() { GuiDateComboBoxTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiDateComboBoxTemplate::~GuiDateComboBoxTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiScrollTemplate ***********************************************************************/ GuiScrollTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiScrollTemplate::GuiScrollTemplate() :Commands_(0) , TotalSize_(100) , PageSize_(10) , Position_(0) { GuiScrollTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiScrollTemplate::~GuiScrollTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiScrollViewTemplate ***********************************************************************/ GuiScrollViewTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiScrollViewTemplate::GuiScrollViewTemplate() :DefaultScrollSize_(0) { GuiScrollViewTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiScrollViewTemplate::~GuiScrollViewTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiMultilineTextBoxTemplate ***********************************************************************/ GuiMultilineTextBoxTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiMultilineTextBoxTemplate::GuiMultilineTextBoxTemplate() { GuiMultilineTextBoxTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiMultilineTextBoxTemplate::~GuiMultilineTextBoxTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiTextListTemplate ***********************************************************************/ GuiTextListTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiTextListTemplate::GuiTextListTemplate() { GuiTextListTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiTextListTemplate::~GuiTextListTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiDocumentViewerTemplate ***********************************************************************/ GuiDocumentViewerTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiDocumentViewerTemplate::GuiDocumentViewerTemplate() { GuiDocumentViewerTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiDocumentViewerTemplate::~GuiDocumentViewerTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiListViewTemplate ***********************************************************************/ GuiListViewTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiListViewTemplate::GuiListViewTemplate() { GuiListViewTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiListViewTemplate::~GuiListViewTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiTreeViewTemplate ***********************************************************************/ GuiTreeViewTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiTreeViewTemplate::GuiTreeViewTemplate() { GuiTreeViewTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiTreeViewTemplate::~GuiTreeViewTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiTabTemplate ***********************************************************************/ GuiTabTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiTabTemplate::GuiTabTemplate() :HeaderPadding_(0) , HeaderComposition_(0) { GuiTabTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiTabTemplate::~GuiTabTemplate() { } /*********************************************************************** GuiListItemTemplate ***********************************************************************/ GuiListItemTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiListItemTemplate::GuiListItemTemplate() :Selected_(false) , Index_(0) { GuiListItemTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiListItemTemplate::~GuiListItemTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiTextListItemTemplate ***********************************************************************/ GuiTextListItemTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiTextListItemTemplate::GuiTextListItemTemplate() { GuiTextListItemTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiTextListItemTemplate::~GuiTextListItemTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiTreeItemTemplate ***********************************************************************/ GuiTreeItemTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiTreeItemTemplate::GuiTreeItemTemplate() :Expanding_(false) { GuiTreeItemTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiTreeItemTemplate::~GuiTreeItemTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiGridVisualizerTemplate ***********************************************************************/ GuiGridVisualizerTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiGridVisualizerTemplate::GuiGridVisualizerTemplate() { GuiGridVisualizerTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiGridVisualizerTemplate::~GuiGridVisualizerTemplate() { FinalizeAggregation(); } /*********************************************************************** GuiGridEditorTemplate ***********************************************************************/ GuiGridEditorTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_IMPL) GuiGridEditorTemplate::GuiGridEditorTemplate() { GuiGridEditorTemplate_PROPERTIES(GUI_TEMPLATE_PROPERTY_EVENT_INIT) } GuiGridEditorTemplate::~GuiGridEditorTemplate() { FinalizeAggregation(); } } } } /*********************************************************************** CONTROLS\TEMPLATES\GUICONTROLTEMPLATESTYLES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace templates { using namespace compositions; using namespace elements; using namespace controls; using namespace controls::list; using namespace reflection::description; using namespace collections; #define INITIALIZE_FACTORY_FROM_TEMPLATE(VARIABLE, PROPERTY)\ controlTemplate->PROPERTY##Changed.AttachLambda([this](GuiGraphicsComposition*, GuiEventArgs&)\ {\ this->VARIABLE = 0;\ });\ #define GET_FACTORY_FROM_TEMPLATE(TEMPLATE, VARIABLE, PROPERTY)\ if (!this->VARIABLE)\ {\ this->VARIABLE = CreateTemplateFactory(controlTemplate->Get##PROPERTY());\ }\ return new TEMPLATE##_StyleProvider(this->VARIABLE);\ #define GET_FACTORY_FROM_TEMPLATE_OPT(TEMPLATE, VARIABLE, PROPERTY)\ if (controlTemplate->Get##PROPERTY() == L"")\ {\ return 0;\ }\ GET_FACTORY_FROM_TEMPLATE(TEMPLATE, VARIABLE, PROPERTY)\ /*********************************************************************** GuiControlTemplate_StyleProvider ***********************************************************************/ GuiControlTemplate_StyleProvider::GuiControlTemplate_StyleProvider(Ptr factory, description::Value viewModel) :associatedStyleController(0) , controlTemplate(0) { GuiTemplate* itemTemplate = factory->CreateTemplate(viewModel); if (!(controlTemplate = dynamic_cast(itemTemplate))) { delete itemTemplate; CHECK_FAIL(L"GuiControlTemplate_StyleProvider::GuiControlTemplate_StyleProvider()#An instance of GuiTemplate is expected."); } } GuiControlTemplate_StyleProvider::~GuiControlTemplate_StyleProvider() { } compositions::GuiBoundsComposition* GuiControlTemplate_StyleProvider::GetBoundsComposition() { return controlTemplate; } compositions::GuiGraphicsComposition* GuiControlTemplate_StyleProvider::GetContainerComposition() { return controlTemplate->GetContainerComposition(); } void GuiControlTemplate_StyleProvider::AssociateStyleController(controls::GuiControl::IStyleController* controller) { associatedStyleController = controller; } void GuiControlTemplate_StyleProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { controlTemplate->SetFocusableComposition(value); } void GuiControlTemplate_StyleProvider::SetText(const WString& value) { controlTemplate->SetText(value); } void GuiControlTemplate_StyleProvider::SetFont(const FontProperties& value) { controlTemplate->SetFont(value); } void GuiControlTemplate_StyleProvider::SetVisuallyEnabled(bool value) { controlTemplate->SetVisuallyEnabled(value); } /*********************************************************************** GuiLabelTemplate_StyleProvider ***********************************************************************/ GuiLabelTemplate_StyleProvider::GuiLabelTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiLabelTemplate_StyleProvider::GuiLabelTemplate_StyleProvider()#An instance of GuiLabelTemplate is expected."); } } GuiLabelTemplate_StyleProvider::~GuiLabelTemplate_StyleProvider() { } Color GuiLabelTemplate_StyleProvider::GetDefaultTextColor() { return controlTemplate->GetDefaultTextColor(); } void GuiLabelTemplate_StyleProvider::SetTextColor(Color value) { controlTemplate->SetTextColor(value); } /*********************************************************************** GuiSinglelineTextBoxTemplate_StyleProvider ***********************************************************************/ GuiSinglelineTextBoxTemplate_StyleProvider::GuiSinglelineTextBoxTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiSinglelineTextBoxTemplate_StyleProvider::GuiSinglelineTextBoxTemplate_StyleProvider()#An instance of GuiSinglelineTextBoxTemplate is expected."); } } GuiSinglelineTextBoxTemplate_StyleProvider::~GuiSinglelineTextBoxTemplate_StyleProvider() { } void GuiSinglelineTextBoxTemplate_StyleProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { GuiControlTemplate_StyleProvider::SetFocusableComposition(value); if (auto style = dynamic_cast(associatedStyleController)) { auto element = style->GetTextElement(); Array colors(1); colors[0] = controlTemplate->GetTextColor(); element->SetColors(colors); element->SetCaretColor(controlTemplate->GetCaretColor()); } } compositions::GuiGraphicsComposition* GuiSinglelineTextBoxTemplate_StyleProvider::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { controlTemplate->SetAlignmentToParent(Margin(0, 0, 0, 0)); boundsComposition->AddChild(controlTemplate); return controlTemplate->GetContainerComposition(); } /*********************************************************************** GuiDocumentLabelTemplate_StyleProvider ***********************************************************************/ GuiDocumentLabelTemplate_StyleProvider::GuiDocumentLabelTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiDocumentLabelTemplate_StyleProvider::GuiDocumentLabelTemplate_StyleProvider()#An instance of GuiDocumentLabelTemplate is expected."); } } GuiDocumentLabelTemplate_StyleProvider::~GuiDocumentLabelTemplate_StyleProvider() { } Ptr GuiDocumentLabelTemplate_StyleProvider::GetBaselineDocument() { return controlTemplate->GetBaselineDocument(); } /*********************************************************************** GuiMenuTemplate_StyleProvider ***********************************************************************/ GuiMenuTemplate_StyleProvider::GuiMenuTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { } GuiMenuTemplate_StyleProvider::~GuiMenuTemplate_StyleProvider() { } /*********************************************************************** GuiWindowTemplate_StyleProvider ***********************************************************************/ GuiWindowTemplate_StyleProvider::GuiWindowTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) , window(0) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiWindowTemplate_StyleProvider::GuiWindowTemplate_StyleProvider()#An instance of GuiWindowTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(tooltipTemplateFactory, TooltipTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(shortcutKeyTemplateFactory, ShortcutKeyTemplate); } GuiWindowTemplate_StyleProvider::~GuiWindowTemplate_StyleProvider() { } void GuiWindowTemplate_StyleProvider::AttachWindow(GuiWindow* _window) { window = _window; } void GuiWindowTemplate_StyleProvider::InitializeNativeWindowProperties() { if (window && window->GetNativeWindow()) { window->GetNativeWindow()->EnableCustomFrameMode(); window->GetNativeWindow()->SetBorder(false); } } void GuiWindowTemplate_StyleProvider::SetSizeState(INativeWindow::WindowSizeState value) { controlTemplate->SetMaximized(value == INativeWindow::Maximized); } #define WINDOW_TEMPLATE_GET(PROPERTY)\ switch (controlTemplate->Get##PROPERTY##Option())\ {\ case BoolOption::AlwaysTrue: return true;\ case BoolOption::AlwaysFalse: return false;\ default: return controlTemplate->Get##PROPERTY();\ }\ #define WINDOW_TEMPLATE_SET(PROPERTY)\ if (controlTemplate->Get##PROPERTY##Option() == BoolOption::Customizable)\ {\ controlTemplate->Set##PROPERTY(visible);\ if (!controlTemplate->GetCustomizedBorder() && window && window->GetNativeWindow())\ {\ window->GetNativeWindow()->Set##PROPERTY(visible);\ }\ }\ bool GuiWindowTemplate_StyleProvider::GetMaximizedBox() { WINDOW_TEMPLATE_GET(MaximizedBox); } void GuiWindowTemplate_StyleProvider::SetMaximizedBox(bool visible) { WINDOW_TEMPLATE_SET(MaximizedBox); } bool GuiWindowTemplate_StyleProvider::GetMinimizedBox() { WINDOW_TEMPLATE_GET(MinimizedBox); } void GuiWindowTemplate_StyleProvider::SetMinimizedBox(bool visible) { WINDOW_TEMPLATE_SET(MinimizedBox); } bool GuiWindowTemplate_StyleProvider::GetBorder() { WINDOW_TEMPLATE_GET(Border); } void GuiWindowTemplate_StyleProvider::SetBorder(bool visible) { WINDOW_TEMPLATE_SET(Border); } bool GuiWindowTemplate_StyleProvider::GetSizeBox() { WINDOW_TEMPLATE_GET(SizeBox); } void GuiWindowTemplate_StyleProvider::SetSizeBox(bool visible) { WINDOW_TEMPLATE_SET(SizeBox); } bool GuiWindowTemplate_StyleProvider::GetIconVisible() { WINDOW_TEMPLATE_GET(IconVisible); } void GuiWindowTemplate_StyleProvider::SetIconVisible(bool visible) { WINDOW_TEMPLATE_SET(IconVisible); } bool GuiWindowTemplate_StyleProvider::GetTitleBar() { WINDOW_TEMPLATE_GET(TitleBar); } void GuiWindowTemplate_StyleProvider::SetTitleBar(bool visible) { WINDOW_TEMPLATE_SET(TitleBar); } controls::GuiWindow::IStyleController* GuiWindowTemplate_StyleProvider::CreateTooltipStyle() { GET_FACTORY_FROM_TEMPLATE_OPT(GuiWindowTemplate, tooltipTemplateFactory, TooltipTemplate); } controls::GuiLabel::IStyleController* GuiWindowTemplate_StyleProvider::CreateShortcutKeyStyle() { GET_FACTORY_FROM_TEMPLATE_OPT(GuiLabelTemplate, shortcutKeyTemplateFactory, ShortcutKeyTemplate); } #undef WINDOW_TEMPLATE_GET #undef WINDOW_TEMPLATE_SET /*********************************************************************** GuiButtonTemplate_StyleProvider ***********************************************************************/ GuiButtonTemplate_StyleProvider::GuiButtonTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiButtonTemplate_StyleProvider::GuiButtonTemplate_StyleProvider()#An instance of GuiButtonTemplate is expected."); } } GuiButtonTemplate_StyleProvider::~GuiButtonTemplate_StyleProvider() { } void GuiButtonTemplate_StyleProvider::Transfer(controls::GuiButton::ControlState value) { controlTemplate->SetState(value); } /*********************************************************************** GuiSelectableButtonTemplate_StyleProvider ***********************************************************************/ GuiSelectableButtonTemplate_StyleProvider::GuiSelectableButtonTemplate_StyleProvider(Ptr factory) :GuiButtonTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiButtonTemplate_StyleProvider::GuiButtonTemplate_StyleProvider()#An instance of GuiSelectableButtonTemplate is expected."); } } GuiSelectableButtonTemplate_StyleProvider::~GuiSelectableButtonTemplate_StyleProvider() { } void GuiSelectableButtonTemplate_StyleProvider::SetSelected(bool value) { controlTemplate->SetSelected(value); } /*********************************************************************** GuiToolstripButtonTemplate_StyleProvider ***********************************************************************/ GuiToolstripButtonTemplate_StyleProvider::GuiToolstripButtonTemplate_StyleProvider(Ptr factory) :GuiSelectableButtonTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiButtonTemplate_StyleProvider::GuiButtonTemplate_StyleProvider()#An instance of GuiToolstripButtonTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(subMenuTemplateFactory, SubMenuTemplate); } GuiToolstripButtonTemplate_StyleProvider::~GuiToolstripButtonTemplate_StyleProvider() { } controls::GuiMenu::IStyleController* GuiToolstripButtonTemplate_StyleProvider::CreateSubMenuStyleController() { GET_FACTORY_FROM_TEMPLATE(GuiMenuTemplate, subMenuTemplateFactory, SubMenuTemplate); } void GuiToolstripButtonTemplate_StyleProvider::SetSubMenuExisting(bool value) { controlTemplate->SetSubMenuExisting(value); } void GuiToolstripButtonTemplate_StyleProvider::SetSubMenuOpening(bool value) { controlTemplate->SetSubMenuOpening(value); } controls::GuiButton* GuiToolstripButtonTemplate_StyleProvider::GetSubMenuHost() { return controlTemplate->GetSubMenuHost(); } void GuiToolstripButtonTemplate_StyleProvider::SetImage(Ptr value) { controlTemplate->SetImage(value); } void GuiToolstripButtonTemplate_StyleProvider::SetShortcutText(const WString& value) { controlTemplate->SetShortcutText(value); } /*********************************************************************** GuiListViewColumnHeaderTemplate_StyleProvider ***********************************************************************/ GuiListViewColumnHeaderTemplate_StyleProvider::GuiListViewColumnHeaderTemplate_StyleProvider(Ptr factory) :GuiToolstripButtonTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiListViewColumnHeaderTemplate_StyleProvider::GuiListViewColumnHeaderTemplate_StyleProvider()#An instance of GuiListViewColumnHeaderTemplate is expected."); } } GuiListViewColumnHeaderTemplate_StyleProvider::~GuiListViewColumnHeaderTemplate_StyleProvider() { } void GuiListViewColumnHeaderTemplate_StyleProvider::SetColumnSortingState(controls::GuiListViewColumnHeader::ColumnSortingState value) { controlTemplate->SetSortingState(value); } /*********************************************************************** GuiComboBoxTemplate_StyleProvider ***********************************************************************/ GuiComboBoxTemplate_StyleProvider::GuiComboBoxTemplate_StyleProvider(Ptr factory) :GuiToolstripButtonTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiComboBoxTemplate_StyleProvider::GuiComboBoxTemplate_StyleProvider()#An instance of GuiComboBoxTemplate is expected."); } } GuiComboBoxTemplate_StyleProvider::~GuiComboBoxTemplate_StyleProvider() { } void GuiComboBoxTemplate_StyleProvider::SetCommandExecutor(controls::GuiComboBoxBase::ICommandExecutor* value) { controlTemplate->SetCommands(value); } void GuiComboBoxTemplate_StyleProvider::OnItemSelected() { } void GuiComboBoxTemplate_StyleProvider::SetTextVisible(bool value) { controlTemplate->SetTextVisible(value); } /*********************************************************************** GuiDatePickerTemplate_StyleProvider ***********************************************************************/ GuiDatePickerTemplate_StyleProvider::GuiDatePickerTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiDatePickerTemplate_StyleProvider::GuiDatePickerTemplate_StyleProvider()#An instance of GuiDatePickerTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(dateButtonTemplateFactory, DateButtonTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(dateTextListTemplateFactory, DateTextListTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(dateComboBoxTemplateFactory, DateComboBoxTemplate); } GuiDatePickerTemplate_StyleProvider::~GuiDatePickerTemplate_StyleProvider() { delete controlTemplate; } controls::GuiSelectableButton::IStyleController* GuiDatePickerTemplate_StyleProvider::CreateDateButtonStyle() { GET_FACTORY_FROM_TEMPLATE(GuiSelectableButtonTemplate, dateButtonTemplateFactory, DateButtonTemplate); } GuiTextListTemplate_StyleProvider* GuiDatePickerTemplate_StyleProvider::CreateTextListStyle() { GET_FACTORY_FROM_TEMPLATE(GuiTextListTemplate, dateTextListTemplateFactory, DateTextListTemplate); } controls::GuiTextList* GuiDatePickerTemplate_StyleProvider::CreateTextList() { auto style = CreateTextListStyle(); return new GuiTextList(style, style->CreateArgument()); } controls::GuiComboBoxListControl::IStyleController* GuiDatePickerTemplate_StyleProvider::CreateComboBoxStyle() { GET_FACTORY_FROM_TEMPLATE(GuiComboBoxTemplate, dateComboBoxTemplateFactory, DateComboBoxTemplate); } Color GuiDatePickerTemplate_StyleProvider::GetBackgroundColor() { return controlTemplate->GetBackgroundColor(); } Color GuiDatePickerTemplate_StyleProvider::GetPrimaryTextColor() { return controlTemplate->GetPrimaryTextColor(); } Color GuiDatePickerTemplate_StyleProvider::GetSecondaryTextColor() { return controlTemplate->GetSecondaryTextColor(); } /*********************************************************************** GuiDateComboBoxTemplate_StyleProvider ***********************************************************************/ GuiDateComboBoxTemplate_StyleProvider::GuiDateComboBoxTemplate_StyleProvider(Ptr factory) :GuiComboBoxTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiDateComboBoxTemplate_StyleProvider::GuiDateComboBoxTemplate_StyleProvider()#An instance of GuiDateComboBoxTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(datePickerTemplateFactory, DatePickerTemplate); } GuiDateComboBoxTemplate_StyleProvider::~GuiDateComboBoxTemplate_StyleProvider() { } controls::GuiDatePicker* GuiDateComboBoxTemplate_StyleProvider::CreateArgument() { return new GuiDatePicker(CreateDatePickerStyle()); } controls::GuiDatePicker::IStyleProvider* GuiDateComboBoxTemplate_StyleProvider::CreateDatePickerStyle() { GET_FACTORY_FROM_TEMPLATE(GuiDatePickerTemplate, datePickerTemplateFactory, DatePickerTemplate); } /*********************************************************************** GuiScrollTemplate_StyleProvider ***********************************************************************/ GuiScrollTemplate_StyleProvider::GuiScrollTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiButtonTemplate_StyleProvider::GuiButtonTemplate_StyleProvider()#An instance of GuiScrollTemplate is expected."); } } GuiScrollTemplate_StyleProvider::~GuiScrollTemplate_StyleProvider() { } void GuiScrollTemplate_StyleProvider::SetCommandExecutor(controls::GuiScroll::ICommandExecutor* value) { controlTemplate->SetCommands(value); } void GuiScrollTemplate_StyleProvider::SetTotalSize(vint value) { controlTemplate->SetTotalSize(value); } void GuiScrollTemplate_StyleProvider::SetPageSize(vint value) { controlTemplate->SetPageSize(value); } void GuiScrollTemplate_StyleProvider::SetPosition(vint value) { controlTemplate->SetPosition(value); } /*********************************************************************** GuiScrollViewTemplate_StyleProvider ***********************************************************************/ GuiScrollViewTemplate_StyleProvider::GuiScrollViewTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiScrollViewTemplate_StyleProvider::GuiScrollViewTemplate_StyleProvider()#An instance of GuiScrollViewTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(hScrollTemplateFactory, HScrollTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(vScrollTemplateFactory, VScrollTemplate); } GuiScrollViewTemplate_StyleProvider::~GuiScrollViewTemplate_StyleProvider() { } controls::GuiScroll::IStyleController* GuiScrollViewTemplate_StyleProvider::CreateHorizontalScrollStyle() { GET_FACTORY_FROM_TEMPLATE(GuiScrollTemplate, hScrollTemplateFactory, HScrollTemplate); } controls::GuiScroll::IStyleController* GuiScrollViewTemplate_StyleProvider::CreateVerticalScrollStyle() { GET_FACTORY_FROM_TEMPLATE(GuiScrollTemplate, vScrollTemplateFactory, VScrollTemplate); } vint GuiScrollViewTemplate_StyleProvider::GetDefaultScrollSize() { return controlTemplate->GetDefaultScrollSize(); } compositions::GuiGraphicsComposition* GuiScrollViewTemplate_StyleProvider::InstallBackground(compositions::GuiBoundsComposition* boundsComposition) { controlTemplate->SetAlignmentToParent(Margin(0, 0, 0, 0)); boundsComposition->AddChild(controlTemplate); return controlTemplate->GetContainerComposition(); } /*********************************************************************** GuiSinglelineTextBoxTemplate_StyleProvider ***********************************************************************/ GuiMultilineTextBoxTemplate_StyleProvider::GuiMultilineTextBoxTemplate_StyleProvider(Ptr factory) :GuiScrollViewTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiMultilineTextBoxTemplate_StyleProvider::GuiMultilineTextBoxTemplate_StyleProvider()#An instance of GuiMultilineTextBoxTemplate is expected."); } } GuiMultilineTextBoxTemplate_StyleProvider::~GuiMultilineTextBoxTemplate_StyleProvider() { } void GuiMultilineTextBoxTemplate_StyleProvider::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { GuiScrollViewTemplate_StyleProvider::SetFocusableComposition(value); if (auto style = dynamic_cast(associatedStyleController)) { auto element = style->GetTextElement(); Array colors(1); colors[0] = controlTemplate->GetTextColor(); element->SetColors(colors); element->SetCaretColor(controlTemplate->GetCaretColor()); } } /*********************************************************************** GuiDocumentViewerTemplate_StyleProvider ***********************************************************************/ GuiDocumentViewerTemplate_StyleProvider::GuiDocumentViewerTemplate_StyleProvider(Ptr factory) :GuiScrollViewTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiDocumentViewerTemplate_StyleProvider::GuiDocumentViewerTemplate_StyleProvider()#An instance of GuiDocumentViewerTemplate is expected."); } } GuiDocumentViewerTemplate_StyleProvider::~GuiDocumentViewerTemplate_StyleProvider() { } Ptr GuiDocumentViewerTemplate_StyleProvider::GetBaselineDocument() { return controlTemplate->GetBaselineDocument(); } /*********************************************************************** GuiTextListTemplate_StyleProvider::ItemStyleProvider ***********************************************************************/ GuiTextListTemplate_StyleProvider::ItemStyleProvider::ItemStyleProvider(GuiTextListTemplate_StyleProvider* _styleProvider) :styleProvider(_styleProvider) { } GuiTextListTemplate_StyleProvider::ItemStyleProvider::~ItemStyleProvider() { } controls::GuiSelectableButton::IStyleController* GuiTextListTemplate_StyleProvider::ItemStyleProvider::CreateBulletStyleController() { return styleProvider->CreateBulletStyle(); } /*********************************************************************** GuiTextListTemplate_StyleProvider ***********************************************************************/ GuiTextListTemplate_StyleProvider::GuiTextListTemplate_StyleProvider(Ptr factory) :GuiScrollViewTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiTextListTemplate_StyleProvider::GuiTextListTemplate_StyleProvider()#An instance of GuiTextListTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(backgroundTemplateFactory, BackgroundTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(bulletTemplateFactory, BulletTemplate); } GuiTextListTemplate_StyleProvider::~GuiTextListTemplate_StyleProvider() { } controls::GuiSelectableButton::IStyleController* GuiTextListTemplate_StyleProvider::CreateItemBackground() { GET_FACTORY_FROM_TEMPLATE(GuiSelectableButtonTemplate, backgroundTemplateFactory, BackgroundTemplate); } Color GuiTextListTemplate_StyleProvider::GetTextColor() { return controlTemplate->GetTextColor(); } controls::list::TextItemStyleProvider::IBulletFactory* GuiTextListTemplate_StyleProvider::CreateArgument() { return new ItemStyleProvider(this); } controls::GuiSelectableButton::IStyleController* GuiTextListTemplate_StyleProvider::CreateBulletStyle() { GET_FACTORY_FROM_TEMPLATE_OPT(GuiSelectableButtonTemplate, bulletTemplateFactory, BulletTemplate); } /*********************************************************************** GuiListViewTemplate_StyleProvider ***********************************************************************/ GuiListViewTemplate_StyleProvider::GuiListViewTemplate_StyleProvider(Ptr factory) :GuiScrollViewTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiListViewTemplate_StyleProvider::GuiListViewTemplate_StyleProvider()#An instance of GuiListViewTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(backgroundTemplateFactory, BackgroundTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(columnHeaderTemplateFactory, ColumnHeaderTemplate); } GuiListViewTemplate_StyleProvider::~GuiListViewTemplate_StyleProvider() { } controls::GuiSelectableButton::IStyleController* GuiListViewTemplate_StyleProvider::CreateItemBackground() { GET_FACTORY_FROM_TEMPLATE(GuiSelectableButtonTemplate, backgroundTemplateFactory, BackgroundTemplate); } controls::GuiListViewColumnHeader::IStyleController* GuiListViewTemplate_StyleProvider::CreateColumnStyle() { GET_FACTORY_FROM_TEMPLATE(GuiListViewColumnHeaderTemplate, columnHeaderTemplateFactory, ColumnHeaderTemplate); } Color GuiListViewTemplate_StyleProvider::GetPrimaryTextColor() { return controlTemplate->GetPrimaryTextColor(); } Color GuiListViewTemplate_StyleProvider::GetSecondaryTextColor() { return controlTemplate->GetSecondaryTextColor(); } Color GuiListViewTemplate_StyleProvider::GetItemSeparatorColor() { return controlTemplate->GetItemSeparatorColor(); } /*********************************************************************** GuiTreeViewTemplate_StyleProvider ***********************************************************************/ GuiTreeViewTemplate_StyleProvider::GuiTreeViewTemplate_StyleProvider(Ptr factory) :GuiScrollViewTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiTreeViewTemplate_StyleProvider::GuiTreeViewTemplate_StyleProvider()#An instance of GuiTreeViewTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(backgroundTemplateFactory, BackgroundTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(expandingDecoratorTemplateFactory, ExpandingDecoratorTemplate); } GuiTreeViewTemplate_StyleProvider::~GuiTreeViewTemplate_StyleProvider() { } controls::GuiSelectableButton::IStyleController* GuiTreeViewTemplate_StyleProvider::CreateItemBackground() { GET_FACTORY_FROM_TEMPLATE(GuiSelectableButtonTemplate, backgroundTemplateFactory, BackgroundTemplate); } controls::GuiSelectableButton::IStyleController* GuiTreeViewTemplate_StyleProvider::CreateItemExpandingDecorator() { GET_FACTORY_FROM_TEMPLATE(GuiSelectableButtonTemplate, expandingDecoratorTemplateFactory, ExpandingDecoratorTemplate); } Color GuiTreeViewTemplate_StyleProvider::GetTextColor() { return controlTemplate->GetTextColor(); } /*********************************************************************** GuiTabTemplate_StyleProvider ***********************************************************************/ void GuiTabTemplate_StyleProvider::OnHeaderButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(commandExecutor) { vint index=headerButtons.IndexOf(dynamic_cast(sender->GetAssociatedControl())); if(index!=-1) { commandExecutor->ShowTab(index); } } } void GuiTabTemplate_StyleProvider::OnTabHeaderBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { vint height=headerOverflowButton->GetBoundsComposition()->GetBounds().Height(); headerOverflowButton->GetBoundsComposition()->SetBounds(Rect(Point(0, 0), Size(height, 0))); UpdateHeaderLayout(); } void GuiTabTemplate_StyleProvider::OnHeaderOverflowButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { headerOverflowMenu->SetClientSize(Size(0, 0)); headerOverflowMenu->ShowPopup(headerOverflowButton, true); } void GuiTabTemplate_StyleProvider::OnHeaderOverflowMenuButtonClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { vint index=headerOverflowMenu->GetToolstripItems().IndexOf(sender->GetRelatedControl()); commandExecutor->ShowTab(index); } void GuiTabTemplate_StyleProvider::UpdateHeaderOverflowButtonVisibility() { if(tabHeaderComposition->IsStackItemClipped()) { tabBoundsComposition->SetColumnOption(1, GuiCellOption::MinSizeOption()); } else { tabBoundsComposition->SetColumnOption(1, GuiCellOption::AbsoluteOption(0)); } tabBoundsComposition->ForceCalculateSizeImmediately(); } void GuiTabTemplate_StyleProvider::UpdateHeaderZOrder() { vint itemCount=tabHeaderComposition->GetStackItems().Count(); vint childCount=tabHeaderComposition->Children().Count(); for(vint i=0;iGetStackItems().Get(i); if(headerButtons[i]->GetSelected()) { tabHeaderComposition->MoveChild(item, childCount-1); vint padding = controlTemplate->GetHeaderPadding(); item->SetExtraMargin(Margin(padding, padding, padding, 0)); } else { item->SetExtraMargin(Margin(0, 0, 0, 0)); } } if(childCount>1) { tabHeaderComposition->MoveChild(tabContentTopLineComposition, childCount-2); } } void GuiTabTemplate_StyleProvider::UpdateHeaderVisibilityIndex() { vint itemCount=tabHeaderComposition->GetStackItems().Count(); vint selectedItem=-1; for(vint i=0;iGetSelected()) { selectedItem=i; } } if(selectedItem!=-1) { tabHeaderComposition->EnsureVisible(selectedItem); } } void GuiTabTemplate_StyleProvider::UpdateHeaderLayout() { UpdateHeaderZOrder(); UpdateHeaderVisibilityIndex(); UpdateHeaderOverflowButtonVisibility(); } void GuiTabTemplate_StyleProvider::Initialize() { tabBoundsComposition=new GuiTableComposition; tabBoundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); tabBoundsComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); tabBoundsComposition->SetRowsAndColumns(1, 2); tabBoundsComposition->SetRowOption(0, GuiCellOption::MinSizeOption()); tabBoundsComposition->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); tabBoundsComposition->SetColumnOption(1, GuiCellOption::AbsoluteOption(0)); controlTemplate->GetHeaderComposition()->AddChild(tabBoundsComposition); vint padding = controlTemplate->GetHeaderPadding(); { GuiCellComposition* cell=new GuiCellComposition; tabBoundsComposition->AddChild(cell); cell->SetSite(0, 0, 1, 1); vint padding = controlTemplate->GetHeaderPadding(); tabHeaderComposition=new GuiStackComposition; tabHeaderComposition->SetExtraMargin(Margin(padding, padding, padding, 0)); tabHeaderComposition->SetAlignmentToParent(Margin(0, 0, 1, 0)); tabHeaderComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); tabHeaderComposition->BoundsChanged.AttachMethod(this, &GuiTabTemplate_StyleProvider::OnTabHeaderBoundsChanged); cell->AddChild(tabHeaderComposition); } { GuiCellComposition* cell=new GuiCellComposition; tabBoundsComposition->AddChild(cell); cell->SetSite(0, 1, 1, 1); headerOverflowButton=new GuiButton(CreateDropdownTemplate()); headerOverflowButton->GetBoundsComposition()->SetAlignmentToParent(Margin(-1, padding, 0, 0)); headerOverflowButton->Clicked.AttachMethod(this, &GuiTabTemplate_StyleProvider::OnHeaderOverflowButtonClicked); cell->AddChild(headerOverflowButton->GetBoundsComposition()); } headerOverflowMenu=new GuiToolstripMenu(CreateMenuTemplate(), 0); headerController=new GuiSelectableButton::MutexGroupController; } controls::GuiSelectableButton::IStyleController* GuiTabTemplate_StyleProvider::CreateHeaderTemplate() { GET_FACTORY_FROM_TEMPLATE(GuiSelectableButtonTemplate, headerTemplateFactory, HeaderTemplate); } controls::GuiButton::IStyleController* GuiTabTemplate_StyleProvider::CreateDropdownTemplate() { GET_FACTORY_FROM_TEMPLATE(GuiButtonTemplate, dropdownTemplateFactory, DropdownTemplate); } controls::GuiMenu::IStyleController* GuiTabTemplate_StyleProvider::CreateMenuTemplate() { GET_FACTORY_FROM_TEMPLATE(GuiMenuTemplate, menuTemplateFactory, MenuTemplate); } controls::GuiToolstripButton::IStyleController* GuiTabTemplate_StyleProvider::CreateMenuItemTemplate() { GET_FACTORY_FROM_TEMPLATE(GuiToolstripButtonTemplate, menuItemTemplateFactory, MenuItemTemplate); } GuiTabTemplate_StyleProvider::GuiTabTemplate_StyleProvider(Ptr factory) :GuiControlTemplate_StyleProvider(factory) { if (!(controlTemplate = dynamic_cast(GetBoundsComposition()))) { CHECK_FAIL(L"GuiTabTemplate_StyleProvider::GuiTabTemplate_StyleProvider()#An instance of GuiTabTemplate is expected."); } INITIALIZE_FACTORY_FROM_TEMPLATE(headerTemplateFactory, HeaderTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(dropdownTemplateFactory, DropdownTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(menuTemplateFactory, MenuTemplate); INITIALIZE_FACTORY_FROM_TEMPLATE(menuItemTemplateFactory, MenuItemTemplate); Initialize(); } GuiTabTemplate_StyleProvider::~GuiTabTemplate_StyleProvider() { delete headerOverflowMenu; } void GuiTabTemplate_StyleProvider::SetCommandExecutor(controls::GuiTab::ICommandExecutor* value) { commandExecutor=value; } void GuiTabTemplate_StyleProvider::InsertTab(vint index) { GuiSelectableButton* button=new GuiSelectableButton(CreateHeaderTemplate()); button->SetAutoSelection(false); button->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); button->SetGroupController(headerController.Obj()); button->Clicked.AttachMethod(this, &GuiTabTemplate_StyleProvider::OnHeaderButtonClicked); GuiStackItemComposition* item=new GuiStackItemComposition; item->AddChild(button->GetBoundsComposition()); tabHeaderComposition->InsertStackItem(index, item); headerButtons.Insert(index, button); GuiToolstripButton* menuItem=new GuiToolstripButton(CreateMenuItemTemplate()); menuItem->Clicked.AttachMethod(this, &GuiTabTemplate_StyleProvider::OnHeaderOverflowMenuButtonClicked); headerOverflowMenu->GetToolstripItems().Insert(index, menuItem); UpdateHeaderLayout(); } void GuiTabTemplate_StyleProvider::SetTabText(vint index, const WString& value) { headerButtons[index]->SetText(value); headerOverflowMenu->GetToolstripItems().Get(index)->SetText(value); UpdateHeaderLayout(); } void GuiTabTemplate_StyleProvider::RemoveTab(vint index) { GuiStackItemComposition* item=tabHeaderComposition->GetStackItems().Get(index); GuiSelectableButton* button=headerButtons[index]; tabHeaderComposition->RemoveChild(item); item->RemoveChild(button->GetBoundsComposition()); headerButtons.RemoveAt(index); headerOverflowMenu->GetToolstripItems().RemoveAt(index); delete item; delete button; UpdateHeaderLayout(); } void GuiTabTemplate_StyleProvider::MoveTab(vint oldIndex, vint newIndex) { GuiStackItemComposition* item=tabHeaderComposition->GetStackItems().Get(oldIndex); tabHeaderComposition->RemoveChild(item); tabHeaderComposition->InsertStackItem(newIndex, item); GuiSelectableButton* button=headerButtons[oldIndex]; headerButtons.RemoveAt(oldIndex); headerButtons.Insert(newIndex, button); UpdateHeaderLayout(); } void GuiTabTemplate_StyleProvider::SetSelectedTab(vint index) { headerButtons[index]->SetSelected(true); UpdateHeaderLayout(); } void GuiTabTemplate_StyleProvider::SetTabAlt(vint index, const WString& value, compositions::IGuiAltActionHost* host) { auto button = headerButtons[index]; button->SetAlt(value); button->SetActivatingAltHost(host); } compositions::IGuiAltAction* GuiTabTemplate_StyleProvider::GetTabAltAction(vint index) { return headerButtons[index]->QueryTypedService(); } /*********************************************************************** GuiControlTemplate_ItemStyleProvider ***********************************************************************/ GuiControlTemplate_ItemStyleProvider::GuiControlTemplate_ItemStyleProvider(Ptr _factory) :factory(_factory) { } GuiControlTemplate_ItemStyleProvider::~GuiControlTemplate_ItemStyleProvider() { } void GuiControlTemplate_ItemStyleProvider::AttachComboBox(controls::GuiComboBoxListControl* value) { } void GuiControlTemplate_ItemStyleProvider::DetachComboBox() { } controls::GuiControl::IStyleController* GuiControlTemplate_ItemStyleProvider::CreateItemStyle(description::Value item) { return new GuiControlTemplate_StyleProvider(factory, item); } /*********************************************************************** GuiTextListItemTemplate_ItemStyleProvider ***********************************************************************/ GuiTextListItemTemplate_ItemStyleProvider::GuiTextListItemTemplate_ItemStyleProvider(Ptr _factory) :factory(_factory) , listControl(0) , bindingView(0) { } GuiTextListItemTemplate_ItemStyleProvider::~GuiTextListItemTemplate_ItemStyleProvider() { } void GuiTextListItemTemplate_ItemStyleProvider::AttachListControl(controls::GuiListControl* value) { listControl = dynamic_cast(value); bindingView = dynamic_cast(listControl->GetItemProvider()->RequestView(GuiListControl::IItemBindingView::Identifier)); } void GuiTextListItemTemplate_ItemStyleProvider::DetachListControl() { if (listControl && bindingView) { listControl->GetItemProvider()->ReleaseView(bindingView); } listControl = 0; bindingView = 0; } vint GuiTextListItemTemplate_ItemStyleProvider::GetItemStyleId(vint itemIndex) { return 0; } controls::GuiListControl::IItemStyleController* GuiTextListItemTemplate_ItemStyleProvider::CreateItemStyle(vint styleId) { return new GuiTextListItemTemplate_ItemStyleController(this); } void GuiTextListItemTemplate_ItemStyleProvider::DestroyItemStyle(controls::GuiListControl::IItemStyleController* style) { delete style; } void GuiTextListItemTemplate_ItemStyleProvider::Install(controls::GuiListControl::IItemStyleController* style, vint itemIndex) { if (auto controller = dynamic_cast(style)) { Value viewModel; if (bindingView) { viewModel = bindingView->GetBindingValue(itemIndex); } GuiTemplate* itemTemplate = factory->CreateTemplate(viewModel); if (auto listItemTemplate = dynamic_cast(itemTemplate)) { listItemTemplate->SetFont(listControl->GetFont()); listItemTemplate->SetIndex(itemIndex); listItemTemplate->SetTextColor(listControl->GetTextListStyleProvider()->GetTextColor()); controller->SetTemplate(listItemTemplate); } else { delete itemTemplate; } } } void GuiTextListItemTemplate_ItemStyleProvider::SetStyleIndex(controls::GuiListControl::IItemStyleController* style, vint value) { if (auto controller = dynamic_cast(style)) { if (auto itemTemplate = controller->GetTemplate()) { itemTemplate->SetIndex(value); } } } void GuiTextListItemTemplate_ItemStyleProvider::SetStyleSelected(controls::GuiListControl::IItemStyleController* style, bool value) { if (auto controller = dynamic_cast(style)) { controller->backgroundButton->SetSelected(value); if (auto itemTemplate = controller->GetTemplate()) { itemTemplate->SetSelected(value); } } } /*********************************************************************** GuiTextListItemTemplate_ItemStyleController ***********************************************************************/ GuiTextListItemTemplate_ItemStyleController::GuiTextListItemTemplate_ItemStyleController(GuiTextListItemTemplate_ItemStyleProvider* _itemStyleProvider) :itemStyleProvider(_itemStyleProvider) , itemTemplate(0) , installed(false) , backgroundButton(0) { backgroundButton = new GuiSelectableButton(itemStyleProvider->listControl->GetTextListStyleProvider()->CreateItemBackground()); backgroundButton->SetAutoSelection(false); } GuiTextListItemTemplate_ItemStyleController::~GuiTextListItemTemplate_ItemStyleController() { SafeDeleteControl(backgroundButton); } GuiTextListItemTemplate* GuiTextListItemTemplate_ItemStyleController::GetTemplate() { return itemTemplate; } void GuiTextListItemTemplate_ItemStyleController::SetTemplate(GuiTextListItemTemplate* _itemTemplate) { SafeDeleteComposition(itemTemplate); itemTemplate = _itemTemplate; itemTemplate->SetAlignmentToParent(Margin(0, 0, 0, 0)); backgroundButton->GetContainerComposition()->AddChild(itemTemplate); } controls::GuiListControl::IItemStyleProvider* GuiTextListItemTemplate_ItemStyleController::GetStyleProvider() { return itemStyleProvider; } vint GuiTextListItemTemplate_ItemStyleController::GetItemStyleId() { return 0; } compositions::GuiBoundsComposition* GuiTextListItemTemplate_ItemStyleController::GetBoundsComposition() { return backgroundButton->GetBoundsComposition(); } bool GuiTextListItemTemplate_ItemStyleController::IsCacheable() { return false; } bool GuiTextListItemTemplate_ItemStyleController::IsInstalled() { return installed; } void GuiTextListItemTemplate_ItemStyleController::OnInstalled() { installed = true; } void GuiTextListItemTemplate_ItemStyleController::OnUninstalled() { installed = false; } /*********************************************************************** GuiTreeItemTemplate_ItemStyleProvider ***********************************************************************/ void GuiTreeItemTemplate_ItemStyleProvider::UpdateExpandingButton(controls::tree::INodeProvider* node) { vint index=treeListControl->GetNodeItemView()->CalculateNodeVisibilityIndex(node); if(index!=-1) { if(auto style = treeListControl->GetArranger()->GetVisibleStyle(index)) { if (auto controller = dynamic_cast(style)) { if (auto itemTemplate = dynamic_cast(controller->GetTemplate())) { itemTemplate->SetExpanding(node->GetExpanding()); } } } } } void GuiTreeItemTemplate_ItemStyleProvider::OnAttached(controls::tree::INodeRootProvider* provider) { } void GuiTreeItemTemplate_ItemStyleProvider::OnBeforeItemModified(controls::tree::INodeProvider* parentNode, vint start, vint count, vint newCount) { } void GuiTreeItemTemplate_ItemStyleProvider::OnAfterItemModified(controls::tree::INodeProvider* parentNode, vint start, vint count, vint newCount) { UpdateExpandingButton(parentNode); } void GuiTreeItemTemplate_ItemStyleProvider::OnItemExpanded(controls::tree::INodeProvider* node) { UpdateExpandingButton(node); } void GuiTreeItemTemplate_ItemStyleProvider::OnItemCollapsed(controls::tree::INodeProvider* node) { UpdateExpandingButton(node); } GuiTreeItemTemplate_ItemStyleProvider::GuiTreeItemTemplate_ItemStyleProvider(Ptr _factory) :factory(_factory) , treeListControl(0) , bindingView(0) , itemStyleProvider(0) { } GuiTreeItemTemplate_ItemStyleProvider::~GuiTreeItemTemplate_ItemStyleProvider() { } void GuiTreeItemTemplate_ItemStyleProvider::BindItemStyleProvider(controls::GuiListControl::IItemStyleProvider* styleProvider) { itemStyleProvider = styleProvider; } controls::GuiListControl::IItemStyleProvider* GuiTreeItemTemplate_ItemStyleProvider::GetBindedItemStyleProvider() { return itemStyleProvider; } void GuiTreeItemTemplate_ItemStyleProvider::AttachListControl(GuiListControl* value) { treeListControl = dynamic_cast(value); if (treeListControl) { treeListControl->GetNodeRootProvider()->AttachCallback(this); bindingView = dynamic_cast(treeListControl->GetNodeRootProvider()->RequestView(tree::INodeItemBindingView::Identifier)); } } void GuiTreeItemTemplate_ItemStyleProvider::DetachListControl() { if (treeListControl) { treeListControl->GetNodeRootProvider()->DetachCallback(this); if (bindingView) { treeListControl->GetNodeRootProvider()->ReleaseView(bindingView); } } treeListControl = 0; bindingView = 0; } vint GuiTreeItemTemplate_ItemStyleProvider::GetItemStyleId(controls::tree::INodeProvider* node) { return 0; } controls::tree::INodeItemStyleController* GuiTreeItemTemplate_ItemStyleProvider::CreateItemStyle(vint styleId) { return new GuiTreeItemTemplate_ItemStyleController(this); } void GuiTreeItemTemplate_ItemStyleProvider::DestroyItemStyle(controls::tree::INodeItemStyleController* style) { delete style; } void GuiTreeItemTemplate_ItemStyleProvider::Install(controls::tree::INodeItemStyleController* style, controls::tree::INodeProvider* node, vint itemIndex) { if (auto controller = dynamic_cast(style)) { Value viewModel; if (bindingView) { viewModel = bindingView->GetBindingValue(node); } GuiTemplate* itemTemplate = factory->CreateTemplate(viewModel); if (auto treeItemTemplate = dynamic_cast(itemTemplate)) { treeItemTemplate->SetFont(treeListControl->GetFont()); treeItemTemplate->SetIndex(itemIndex); controller->SetTemplate(treeItemTemplate); } else { delete itemTemplate; } } } void GuiTreeItemTemplate_ItemStyleProvider::SetStyleIndex(controls::tree::INodeItemStyleController* style, vint value) { if (auto controller = dynamic_cast(style)) { if (auto itemTemplate = controller->GetTemplate()) { itemTemplate->SetIndex(value); } } } void GuiTreeItemTemplate_ItemStyleProvider::SetStyleSelected(controls::tree::INodeItemStyleController* style, bool value) { if (auto controller = dynamic_cast(style)) { if (auto itemTemplate = controller->GetTemplate()) { itemTemplate->SetSelected(value); } } } /*********************************************************************** GuiTreeItemTemplate_ItemStyleController ***********************************************************************/ GuiTreeItemTemplate_ItemStyleController::GuiTreeItemTemplate_ItemStyleController(GuiTreeItemTemplate_ItemStyleProvider* _nodeStyleProvider) :nodeStyleProvider(_nodeStyleProvider) , itemTemplate(0) , installed(false) { } GuiTreeItemTemplate_ItemStyleController::~GuiTreeItemTemplate_ItemStyleController() { } GuiTreeItemTemplate* GuiTreeItemTemplate_ItemStyleController::GetTemplate() { return itemTemplate; } void GuiTreeItemTemplate_ItemStyleController::SetTemplate(GuiTreeItemTemplate* _itemTemplate) { SafeDeleteComposition(itemTemplate); itemTemplate = _itemTemplate; } controls::GuiListControl::IItemStyleProvider* GuiTreeItemTemplate_ItemStyleController::GetStyleProvider() { return nodeStyleProvider->GetBindedItemStyleProvider(); } vint GuiTreeItemTemplate_ItemStyleController::GetItemStyleId() { return 0; } compositions::GuiBoundsComposition* GuiTreeItemTemplate_ItemStyleController::GetBoundsComposition() { return itemTemplate; } bool GuiTreeItemTemplate_ItemStyleController::IsCacheable() { return false; } bool GuiTreeItemTemplate_ItemStyleController::IsInstalled() { return installed; } void GuiTreeItemTemplate_ItemStyleController::OnInstalled() { installed = true; } void GuiTreeItemTemplate_ItemStyleController::OnUninstalled() { installed = false; } controls::tree::INodeItemStyleProvider* GuiTreeItemTemplate_ItemStyleController::GetNodeStyleProvider() { return nodeStyleProvider; } /*********************************************************************** GuiBindableDataVisualizer::Factory ***********************************************************************/ GuiBindableDataVisualizer::Factory::Factory(Ptr _templateFactory, controls::list::BindableDataColumn* _ownerColumn) :templateFactory(_templateFactory) , ownerColumn(_ownerColumn) { } GuiBindableDataVisualizer::Factory::~Factory() { } Ptr GuiBindableDataVisualizer::Factory::CreateVisualizer(const FontProperties& font, controls::GuiListViewBase::IStyleProvider* styleProvider) { auto visualizer = DataVisualizerFactory::CreateVisualizer(font, styleProvider).Cast(); if (visualizer) { visualizer->templateFactory = templateFactory; visualizer->ownerColumn = ownerColumn; } return visualizer; } /*********************************************************************** GuiBindableDataVisualizer::DecoratedFactory ***********************************************************************/ GuiBindableDataVisualizer::DecoratedFactory::DecoratedFactory(Ptr _templateFactory, controls::list::BindableDataColumn* _ownerColumn, Ptr _decoratedFactory) :DataDecoratableVisualizerFactory(_decoratedFactory) , templateFactory(_templateFactory) , ownerColumn(_ownerColumn) { } GuiBindableDataVisualizer::DecoratedFactory::~DecoratedFactory() { } Ptr GuiBindableDataVisualizer::DecoratedFactory::CreateVisualizer(const FontProperties& font, controls::GuiListViewBase::IStyleProvider* styleProvider) { auto visualizer = DataDecoratableVisualizerFactory::CreateVisualizer(font, styleProvider).Cast(); if (visualizer) { visualizer->templateFactory = templateFactory; visualizer->ownerColumn = ownerColumn; } return visualizer; } /*********************************************************************** GuiBindableDataVisualizer ***********************************************************************/ compositions::GuiBoundsComposition* GuiBindableDataVisualizer::CreateBoundsCompositionInternal(compositions::GuiBoundsComposition* decoratedComposition) { GuiTemplate* itemTemplate = templateFactory->CreateTemplate(ownerColumn->GetViewModelContext()); if (!(visualizerTemplate = dynamic_cast(itemTemplate))) { delete itemTemplate; CHECK_FAIL(L"GuiBindableDataVisualizer::CreateBoundsCompositionInternal(presentation::compositions::GuiBoundsComposition*)#An instance of GuiGridVisualizerTemplate is expected."); } if (decoratedComposition) { decoratedComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); visualizerTemplate->GetContainerComposition()->AddChild(decoratedComposition); } visualizerTemplate->SetFont(font); return visualizerTemplate; } GuiBindableDataVisualizer::GuiBindableDataVisualizer() { } GuiBindableDataVisualizer::GuiBindableDataVisualizer(Ptr _decoratedVisualizer) :DataVisualizerBase(_decoratedVisualizer) { } GuiBindableDataVisualizer::~GuiBindableDataVisualizer() { } void GuiBindableDataVisualizer::BeforeVisualizeCell(controls::list::IDataProvider* dataProvider, vint row, vint column) { DataVisualizerBase::BeforeVisualizeCell(dataProvider, row, column); if (!visualizerTemplate) return; visualizerTemplate->SetText(dataProvider->GetCellText(row, column)); auto structuredDataProvider = dynamic_cast(dataProvider); if (!structuredDataProvider) return; auto bindableDataProvider = structuredDataProvider->GetStructuredDataProvider().Cast(); if (!bindableDataProvider) return; auto columnProvider = bindableDataProvider->GetBindableColumn(column); if (!columnProvider) return; visualizerTemplate->SetRowValue(bindableDataProvider->GetRowValue(row)); visualizerTemplate->SetCellValue(columnProvider->GetCellValue(row)); } void GuiBindableDataVisualizer::SetSelected(bool value) { DataVisualizerBase::SetSelected(value); if (visualizerTemplate) { visualizerTemplate->SetSelected(value); } } /*********************************************************************** GuiBindableDataEditor::Factory ***********************************************************************/ GuiBindableDataEditor::Factory::Factory(Ptr _templateFactory, controls::list::BindableDataColumn* _ownerColumn) :templateFactory(_templateFactory) , ownerColumn(_ownerColumn) { } GuiBindableDataEditor::Factory::~Factory() { } Ptr GuiBindableDataEditor::Factory::CreateEditor(controls::list::IDataEditorCallback* callback) { auto editor = DataEditorFactory::CreateEditor(callback).Cast(); if (editor) { editor->templateFactory = templateFactory; editor->ownerColumn = ownerColumn; // Invoke GuiBindableDataEditor::CreateBoundsCompositionInternal // so that GuiBindableDataEditor::BeforeEditCell is able to set RowValue and CellValue to the editor editor->GetBoundsComposition(); } return editor; } /*********************************************************************** GuiBindableDataEditor ***********************************************************************/ compositions::GuiBoundsComposition* GuiBindableDataEditor::CreateBoundsCompositionInternal() { GuiTemplate* itemTemplate = templateFactory->CreateTemplate(ownerColumn->GetViewModelContext()); if (!(editorTemplate = dynamic_cast(itemTemplate))) { delete itemTemplate; CHECK_FAIL(L"GuiBindableDataEditor::CreateBoundsCompositionInternal()#An instance of GuiGridEditorTemplate is expected."); } editorTemplate->CellValueChanged.AttachMethod(this, &GuiBindableDataEditor::editorTemplate_CellValueChanged); return editorTemplate; } void GuiBindableDataEditor::editorTemplate_CellValueChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if (callback) { callback->RequestSaveData(); } } GuiBindableDataEditor::GuiBindableDataEditor() { } GuiBindableDataEditor::~GuiBindableDataEditor() { } void GuiBindableDataEditor::BeforeEditCell(controls::list::IDataProvider* dataProvider, vint row, vint column) { DataEditorBase::BeforeEditCell(dataProvider, row, column); if (!editorTemplate) return; editorTemplate->SetText(dataProvider->GetCellText(row, column)); auto structuredDataProvider = dynamic_cast(dataProvider); if (!structuredDataProvider) return; auto bindableDataProvider = structuredDataProvider->GetStructuredDataProvider().Cast(); if (!bindableDataProvider) return; auto columnProvider = bindableDataProvider->GetBindableColumn(column); if (!columnProvider) return; editorTemplate->SetRowValue(bindableDataProvider->GetRowValue(row)); editorTemplate->SetCellValue(columnProvider->GetCellValue(row)); } description::Value GuiBindableDataEditor::GetEditedCellValue() { if (editorTemplate) { return editorTemplate->GetCellValue(); } else { return description::Value(); } } /*********************************************************************** Helper Functions ***********************************************************************/ void SplitBySemicolon(const WString& input, collections::List& fragments) { const wchar_t* attValue = input.Buffer(); while(*attValue) { // split the value by ';' const wchar_t* attSemicolon = wcschr(attValue, L';'); WString pattern; if(attSemicolon) { pattern = WString(attValue, vint(attSemicolon - attValue)); attValue = attSemicolon + 1; } else { vint len = wcslen(attValue); pattern = WString(attValue, len); attValue += len; } fragments.Add(pattern); } } Ptr CreateTemplateFactory(const WString& typeValues) { List types; List typeNames; SplitBySemicolon(typeValues, typeNames); CopyFrom( types, From(typeNames) .Select(&description::GetTypeDescriptor) .Where([](ITypeDescriptor* type){return type != 0; }) ); return GuiTemplate::IFactory::CreateTemplateFactory(types); } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTVIEWER.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace elements; using namespace compositions; /*********************************************************************** GuiDocumentItem ***********************************************************************/ GuiDocumentItem::GuiDocumentItem(const WString& _name) :name(_name) { container = new GuiBoundsComposition; container->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); container->SetAssociatedCursor(GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::Arrow)); } GuiDocumentItem::~GuiDocumentItem() { if (!owned) { SafeDeleteComposition(container); } } compositions::GuiGraphicsComposition* GuiDocumentItem::GetContainer() { return container; } WString GuiDocumentItem::GetName() { return name; } /*********************************************************************** GuiDocumentCommonInterface ***********************************************************************/ void GuiDocumentCommonInterface::UpdateCaretPoint() { GuiGraphicsHost* host=documentComposition->GetRelatedGraphicsHost(); if(host) { Rect caret=documentElement->GetCaretBounds(documentElement->GetCaretEnd(), documentElement->IsCaretEndPreferFrontSide()); Point view=GetDocumentViewPosition(); vint x=caret.x1-view.x; vint y=caret.y2-view.y; host->SetCaretPoint(Point(x, y), documentComposition); } } void GuiDocumentCommonInterface::Move(TextPos caret, bool shift, bool frontSide) { TextPos begin=documentElement->GetCaretBegin(); TextPos end=documentElement->GetCaretEnd(); TextPos newBegin=shift?begin:caret; TextPos newEnd=caret; documentElement->SetCaret(newBegin, newEnd, frontSide); documentElement->SetCaretVisible(true); Rect bounds=documentElement->GetCaretBounds(newEnd, frontSide); if(bounds!=Rect()) { bounds.x1-=15; bounds.y1-=15; bounds.x2+=15; bounds.y2+=15; EnsureRectVisible(bounds); } UpdateCaretPoint(); SelectionChanged.Execute(documentControl->GetNotifyEventArguments()); } bool GuiDocumentCommonInterface::ProcessKey(vint code, bool shift, bool ctrl) { if(IGuiShortcutKeyItem* item=internalShortcutKeyManager->TryGetShortcut(ctrl, shift, false, code)) { GuiEventArgs arguments; item->Executed.Execute(arguments); return true; } TextPos currentCaret=documentElement->GetCaretEnd(); bool frontSide=documentElement->IsCaretEndPreferFrontSide(); TextPos begin=documentElement->GetCaretBegin(); TextPos end=documentElement->GetCaretEnd(); switch(code) { case VKEY_UP: { TextPos newCaret=documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretMoveUp, frontSide); Move(newCaret, shift, frontSide); } break; case VKEY_DOWN: { TextPos newCaret=documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretMoveDown, frontSide); Move(newCaret, shift, frontSide); } break; case VKEY_LEFT: { TextPos newCaret=documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretMoveLeft, frontSide); Move(newCaret, shift, frontSide); } break; case VKEY_RIGHT: { TextPos newCaret=documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretMoveRight, frontSide); Move(newCaret, shift, frontSide); } break; case VKEY_HOME: { TextPos newCaret=documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretLineFirst, frontSide); if(newCaret==currentCaret) { newCaret=documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretFirst, frontSide); } Move(newCaret, shift, frontSide); } break; case VKEY_END: { TextPos newCaret=documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretLineLast, frontSide); if(newCaret==currentCaret) { newCaret=documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretLast, frontSide); } Move(newCaret, shift, frontSide); } break; case VKEY_PRIOR: { } break; case VKEY_NEXT: { } break; case VKEY_BACK: if(editMode==Editable) { if(begin==end) { ProcessKey(VKEY_LEFT, true, false); } Array text; EditText(documentElement->GetCaretBegin(), documentElement->GetCaretEnd(), documentElement->IsCaretEndPreferFrontSide(), text); return true; } break; case VKEY_DELETE: if(editMode==Editable) { if(begin==end) { ProcessKey(VKEY_RIGHT, true, false); } Array text; EditText(documentElement->GetCaretBegin(), documentElement->GetCaretEnd(), documentElement->IsCaretEndPreferFrontSide(), text); return true; } break; case VKEY_RETURN: if(editMode==Editable) { if(ctrl) { Array text(1); text[0]=L"\r\n"; EditText(documentElement->GetCaretBegin(), documentElement->GetCaretEnd(), documentElement->IsCaretEndPreferFrontSide(), text); } else { Array text(2); EditText(documentElement->GetCaretBegin(), documentElement->GetCaretEnd(), documentElement->IsCaretEndPreferFrontSide(), text); } return true; } break; } return false; } void GuiDocumentCommonInterface::InstallDocumentViewer(GuiControl* _sender, compositions::GuiGraphicsComposition* _container) { documentControl=_sender; documentElement=GuiDocumentElement::Create(); documentElement->SetCallback(this); documentComposition=new GuiBoundsComposition; documentComposition->SetOwnedElement(documentElement); documentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); documentComposition->SetAlignmentToParent(Margin(5, 5, 5, 5)); _container->AddChild(documentComposition); documentComposition->GetEventReceiver()->mouseMove.AttachMethod(this, &GuiDocumentCommonInterface::OnMouseMove); documentComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiDocumentCommonInterface::OnMouseDown); documentComposition->GetEventReceiver()->leftButtonUp.AttachMethod(this, &GuiDocumentCommonInterface::OnMouseUp); documentComposition->GetEventReceiver()->mouseLeave.AttachMethod(this, &GuiDocumentCommonInterface::OnMouseLeave); _sender->FontChanged.AttachMethod(this, &GuiDocumentCommonInterface::OnFontChanged); _sender->GetFocusableComposition()->GetEventReceiver()->caretNotify.AttachMethod(this, &GuiDocumentCommonInterface::OnCaretNotify); _sender->GetFocusableComposition()->GetEventReceiver()->gotFocus.AttachMethod(this, &GuiDocumentCommonInterface::OnGotFocus); _sender->GetFocusableComposition()->GetEventReceiver()->lostFocus.AttachMethod(this, &GuiDocumentCommonInterface::OnLostFocus); _sender->GetFocusableComposition()->GetEventReceiver()->keyDown.AttachMethod(this, &GuiDocumentCommonInterface::OnKeyDown); _sender->GetFocusableComposition()->GetEventReceiver()->charInput.AttachMethod(this, &GuiDocumentCommonInterface::OnCharInput); undoRedoProcessor->Setup(documentElement, documentComposition); ActiveHyperlinkChanged.SetAssociatedComposition(_sender->GetBoundsComposition()); ActiveHyperlinkExecuted.SetAssociatedComposition(_sender->GetBoundsComposition()); SelectionChanged.SetAssociatedComposition(_sender->GetBoundsComposition()); } void GuiDocumentCommonInterface::SetActiveHyperlink(Ptr hyperlink, vint paragraphIndex) { if(activeHyperlink!=hyperlink) { ActivateActiveHyperlink(false); activeHyperlink=hyperlink; activeHyperlinkParagraph=paragraphIndex; ActivateActiveHyperlink(true); ActiveHyperlinkChanged.Execute(documentControl->GetNotifyEventArguments()); } } void GuiDocumentCommonInterface::ActivateActiveHyperlink(bool activate) { if(activeHyperlink) { activeHyperlink->styleName=activate?activeHyperlink->activeStyleName:activeHyperlink->normalStyleName; documentElement->NotifyParagraphUpdated(activeHyperlinkParagraph, 1, 1, false); } } void GuiDocumentCommonInterface::AddShortcutCommand(vint key, const Func& eventHandler) { IGuiShortcutKeyItem* item=internalShortcutKeyManager->CreateShortcut(true, false, false, key); item->Executed.AttachLambda([=](GuiGraphicsComposition* sender, GuiEventArgs& arguments) { eventHandler(); }); } void GuiDocumentCommonInterface::EditTextInternal(TextPos begin, TextPos end, const Func& editor) { // save run before editing if(begin>end) { TextPos temp=begin; begin=end; end=temp; } Ptr originalModel=documentElement->GetDocument()->CopyDocument(begin, end, true); if(originalModel) { // edit vint paragraphCount=0; vint lastParagraphLength=0; editor(begin, end, paragraphCount, lastParagraphLength); // calculate new caret TextPos caret; if(paragraphCount==0) { caret=begin; } else if(paragraphCount==1) { caret=TextPos(begin.row, begin.column+lastParagraphLength); } else { caret=TextPos(begin.row+paragraphCount-1, lastParagraphLength); } documentElement->SetCaret(caret, caret, true); documentControl->TextChanged.Execute(documentControl->GetNotifyEventArguments()); // save run after editing Ptr inputModel=documentElement->GetDocument()->CopyDocument(begin, caret, true); // submit redo-undo GuiDocumentUndoRedoProcessor::ReplaceModelStruct arguments; arguments.originalStart=begin; arguments.originalEnd=end; arguments.originalModel=originalModel; arguments.inputStart=begin; arguments.inputEnd=caret; arguments.inputModel=inputModel; undoRedoProcessor->OnReplaceModel(arguments); } } void GuiDocumentCommonInterface::EditStyleInternal(TextPos begin, TextPos end, const Func& editor) { // save run before editing if(begin>end) { TextPos temp=begin; begin=end; end=temp; } Ptr originalModel=documentElement->GetDocument()->CopyDocument(begin, end, true); if(originalModel) { // edit editor(begin, end); // save run after editing Ptr inputModel=documentElement->GetDocument()->CopyDocument(begin, end, true); // submit redo-undo GuiDocumentUndoRedoProcessor::ReplaceModelStruct arguments; arguments.originalStart=begin; arguments.originalEnd=end; arguments.originalModel=originalModel; arguments.inputStart=begin; arguments.inputEnd=end; arguments.inputModel=inputModel; undoRedoProcessor->OnReplaceModel(arguments); } } void GuiDocumentCommonInterface::MergeBaselineAndDefaultFont(Ptr document) { document->MergeDefaultFont(documentControl->GetFont()); if (baselineDocument) { document->MergeBaselineStyles(baselineDocument); } } void GuiDocumentCommonInterface::OnFontChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { auto document = documentElement->GetDocument(); MergeBaselineAndDefaultFont(document); documentElement->SetDocument(document); } void GuiDocumentCommonInterface::OnCaretNotify(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(documentControl->GetVisuallyEnabled()) { if(editMode!=ViewOnly) { documentElement->SetCaretVisible(!documentElement->GetCaretVisible()); } } } void GuiDocumentCommonInterface::OnGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(documentControl->GetVisuallyEnabled()) { if(editMode!=ViewOnly) { documentElement->SetCaretVisible(true); UpdateCaretPoint(); } } } void GuiDocumentCommonInterface::OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(documentControl->GetVisuallyEnabled()) { documentElement->SetCaretVisible(false); } } void GuiDocumentCommonInterface::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) { if(documentControl->GetVisuallyEnabled()) { if(editMode!=ViewOnly) { if(ProcessKey(arguments.code, arguments.shift, arguments.ctrl)) { arguments.handled=true; } } } } void GuiDocumentCommonInterface::OnCharInput(compositions::GuiGraphicsComposition* sender, compositions::GuiCharEventArgs& arguments) { if(documentControl->GetVisuallyEnabled()) { if(editMode==Editable && arguments.code!=VKEY_ESCAPE && arguments.code!=VKEY_BACK && arguments.code!=VKEY_RETURN && !arguments.ctrl) { Array text(1); text[0]=WString(arguments.code); EditText(documentElement->GetCaretBegin(), documentElement->GetCaretEnd(), documentElement->IsCaretEndPreferFrontSide(), text); } } } void GuiDocumentCommonInterface::OnMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(documentControl->GetVisuallyEnabled()) { switch(editMode) { case ViewOnly: { Point point(arguments.x, arguments.y); Ptr hyperlink=documentElement->GetHyperlinkFromPoint(point); vint hyperlinkParagraph=hyperlink?documentElement->CalculateCaretFromPoint(point).row:-1; if(dragging) { if(activeHyperlink) { ActivateActiveHyperlink(activeHyperlink==hyperlink); } } else { SetActiveHyperlink(hyperlink, hyperlinkParagraph); } if(activeHyperlink && activeHyperlink==hyperlink) { INativeCursor* cursor=GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::Hand); documentComposition->SetAssociatedCursor(cursor); } else { documentComposition->SetAssociatedCursor(0); } } break; case Selectable: case Editable: if(dragging) { TextPos caret=documentElement->CalculateCaretFromPoint(Point(arguments.x, arguments.y)); TextPos oldCaret=documentElement->GetCaretBegin(); Move(caret, true, (oldCaret==caret?documentElement->IsCaretEndPreferFrontSide():caretGetVisuallyEnabled()) { documentControl->SetFocus(); switch(editMode) { case ViewOnly: { Point point(arguments.x, arguments.y); Ptr hyperlink=documentElement->GetHyperlinkFromPoint(point); vint hyperlinkParagraph=hyperlink?documentElement->CalculateCaretFromPoint(point).row:-1; SetActiveHyperlink(hyperlink, hyperlinkParagraph); } break; case Selectable: case Editable: { TextPos caret=documentElement->CalculateCaretFromPoint(Point(arguments.x, arguments.y)); TextPos oldCaret=documentElement->GetCaretEnd(); if(caret!=oldCaret) { Move(caret, arguments.shift, caretGetVisuallyEnabled()) { dragging=false; switch(editMode) { case ViewOnly: { Point point(arguments.x, arguments.y); Ptr hyperlink=documentElement->GetHyperlinkFromPoint(point); if(activeHyperlink!=hyperlink) { SetActiveHyperlink(0); } if(activeHyperlink) { ActiveHyperlinkExecuted.Execute(documentControl->GetNotifyEventArguments()); } } break; default:; } } } void GuiDocumentCommonInterface::OnMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { SetActiveHyperlink(0); } Point GuiDocumentCommonInterface::GetDocumentViewPosition() { return Point(0, 0); } void GuiDocumentCommonInterface::EnsureRectVisible(Rect bounds) { } //================ callback void GuiDocumentCommonInterface::OnStartRender() { FOREACH(Ptr, item, documentItems.Values()) { item->visible = false; } } void GuiDocumentCommonInterface::OnFinishRender() { FOREACH(Ptr, item, documentItems.Values()) { if (item->container->GetVisible() != item->visible) { item->container->SetVisible(item->visible); } } } Size GuiDocumentCommonInterface::OnRenderEmbeddedObject(const WString& name, const Rect& location) { vint index = documentItems.Keys().IndexOf(name); if (index != -1) { auto item = documentItems.Values()[index]; auto size = item->container->GetBounds().GetSize(); item->container->SetBounds(Rect(location.LeftTop(), Size(0, 0))); item->visible = true; return size; } return Size(); } //================ basic GuiDocumentCommonInterface::GuiDocumentCommonInterface(Ptr _baselineDocument) :baselineDocument(_baselineDocument) ,documentElement(0) ,documentComposition(0) ,activeHyperlinkParagraph(-1) ,dragging(false) ,editMode(ViewOnly) ,documentControl(0) { undoRedoProcessor=new GuiDocumentUndoRedoProcessor; internalShortcutKeyManager=new GuiShortcutKeyManager; AddShortcutCommand('Z', Func(this, &GuiDocumentCommonInterface::Undo)); AddShortcutCommand('Y', Func(this, &GuiDocumentCommonInterface::Redo)); AddShortcutCommand('A', Func(this, &GuiDocumentCommonInterface::SelectAll)); AddShortcutCommand('X', Func(this, &GuiDocumentCommonInterface::Cut)); AddShortcutCommand('C', Func(this, &GuiDocumentCommonInterface::Copy)); AddShortcutCommand('V', Func(this, &GuiDocumentCommonInterface::Paste)); } GuiDocumentCommonInterface::~GuiDocumentCommonInterface() { } Ptr GuiDocumentCommonInterface::GetDocument() { return documentElement->GetDocument(); } void GuiDocumentCommonInterface::SetDocument(Ptr value) { SetActiveHyperlink(0); ClearUndoRedo(); NotifyModificationSaved(); if(value->paragraphs.Count()==0) { value->paragraphs.Add(new DocumentParagraphRun); } MergeBaselineAndDefaultFont(value); documentElement->SetDocument(value); } //================ document items bool GuiDocumentCommonInterface::AddDocumentItem(Ptr value) { if (documentItems.Keys().Contains(value->GetName())) { return false; } documentItems.Add(value->GetName(), value); documentComposition->AddChild(value->container); value->visible = false; value->owned = true; value->container->SetVisible(false); return true; } bool GuiDocumentCommonInterface::RemoveDocumentItem(Ptr value) { vint index = documentItems.Keys().IndexOf(value->GetName()); if (index == -1) { return false; } if (documentItems.Values()[index] != value) { return false; } value->owned = false; documentComposition->RemoveChild(value->container); documentItems.Remove(value->GetName()); return true; } const GuiDocumentCommonInterface::DocumentItemMap& GuiDocumentCommonInterface::GetDocumentItems() { return documentItems; } //================ caret operations TextPos GuiDocumentCommonInterface::GetCaretBegin() { return documentElement->GetCaretBegin(); } TextPos GuiDocumentCommonInterface::GetCaretEnd() { return documentElement->GetCaretEnd(); } void GuiDocumentCommonInterface::SetCaret(TextPos begin, TextPos end) { documentElement->SetCaret(begin, end, end>=begin); } TextPos GuiDocumentCommonInterface::CalculateCaretFromPoint(Point point) { return documentElement->CalculateCaretFromPoint(point); } Rect GuiDocumentCommonInterface::GetCaretBounds(TextPos caret, bool frontSide) { return documentElement->GetCaretBounds(caret, frontSide); } //================ editing operations void GuiDocumentCommonInterface::NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText) { documentElement->NotifyParagraphUpdated(index, oldCount, newCount, updatedText); } void GuiDocumentCommonInterface::EditRun(TextPos begin, TextPos end, Ptr model) { EditTextInternal(begin, end, [=](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength) { documentElement->EditRun(begin, end, model); paragraphCount=model->paragraphs.Count(); lastParagraphLength=paragraphCount==0?0:model->paragraphs[paragraphCount-1]->GetText(false).Length(); }); } void GuiDocumentCommonInterface::EditText(TextPos begin, TextPos end, bool frontSide, const collections::Array& text) { EditTextInternal(begin, end, [=, &text](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength) { documentElement->EditText(begin, end, frontSide, text); paragraphCount=text.Count(); lastParagraphLength=paragraphCount==0?0:text[paragraphCount-1].Length(); }); } void GuiDocumentCommonInterface::EditStyle(TextPos begin, TextPos end, Ptr style) { EditStyleInternal(begin, end, [=](TextPos begin, TextPos end) { documentElement->EditStyle(begin, end, style); }); } void GuiDocumentCommonInterface::EditImage(TextPos begin, TextPos end, Ptr image) { EditTextInternal(begin, end, [=](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength) { documentElement->EditImage(begin, end, image); paragraphCount=1; lastParagraphLength=wcslen(DocumentImageRun::RepresentationText); }); } void GuiDocumentCommonInterface::EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName, const WString& activeStyleName) { EditStyleInternal(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), [=](TextPos begin, TextPos end) { documentElement->EditHyperlink(begin.row, begin.column, end.column, reference, normalStyleName, activeStyleName); }); } void GuiDocumentCommonInterface::RemoveHyperlink(vint paragraphIndex, vint begin, vint end) { EditStyleInternal(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), [=](TextPos begin, TextPos end) { documentElement->RemoveHyperlink(begin.row, begin.column, end.column); }); } void GuiDocumentCommonInterface::EditStyleName(TextPos begin, TextPos end, const WString& styleName) { EditStyleInternal(begin, end, [=](TextPos begin, TextPos end) { documentElement->EditStyleName(begin, end, styleName); }); } void GuiDocumentCommonInterface::RemoveStyleName(TextPos begin, TextPos end) { EditStyleInternal(begin, end, [=](TextPos begin, TextPos end) { documentElement->RemoveStyleName(begin, end); }); } void GuiDocumentCommonInterface::RenameStyle(const WString& oldStyleName, const WString& newStyleName) { documentElement->RenameStyle(oldStyleName, newStyleName); // submit redo-undo GuiDocumentUndoRedoProcessor::RenameStyleStruct arguments; arguments.oldStyleName=oldStyleName; arguments.newStyleName=newStyleName; undoRedoProcessor->OnRenameStyle(arguments); } void GuiDocumentCommonInterface::ClearStyle(TextPos begin, TextPos end) { EditStyleInternal(begin, end, [=](TextPos begin, TextPos end) { documentElement->ClearStyle(begin, end); }); } Ptr GuiDocumentCommonInterface::SummarizeStyle(TextPos begin, TextPos end) { return documentElement->SummarizeStyle(begin, end); } void GuiDocumentCommonInterface::SetParagraphAlignment(TextPos begin, TextPos end, const collections::Array>& alignments) { vint first=begin.row; vint last=end.row; if(first>last) { vint temp=first; first=last; last=temp; } Ptr document=documentElement->GetDocument(); if(0<=first && firstparagraphs.Count() && 0<=last && lastparagraphs.Count() && last-first+1==alignments.Count()) { Ptr arguments=new GuiDocumentUndoRedoProcessor::SetAlignmentStruct; arguments->start=first; arguments->end=last; arguments->originalAlignments.Resize(alignments.Count()); arguments->inputAlignments.Resize(alignments.Count()); for(vint i=first;i<=last;i++) { arguments->originalAlignments[i-first]=document->paragraphs[i]->alignment; arguments->inputAlignments[i-first]=alignments[i-first]; } documentElement->SetParagraphAlignment(begin, end, alignments); undoRedoProcessor->OnSetAlignment(arguments); } } //================ editing control WString GuiDocumentCommonInterface::GetActiveHyperlinkReference() { return activeHyperlink?activeHyperlink->reference:L""; } GuiDocumentCommonInterface::EditMode GuiDocumentCommonInterface::GetEditMode() { return editMode; } void GuiDocumentCommonInterface::SetEditMode(EditMode value) { if(activeHyperlink) { SetActiveHyperlink(0); activeHyperlink=0; activeHyperlinkParagraph=-1; } editMode=value; if(editMode==ViewOnly) { documentComposition->SetAssociatedCursor(0); } else { INativeCursor* cursor=GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::IBeam); documentComposition->SetAssociatedCursor(cursor); } } //================ selection operations void GuiDocumentCommonInterface::SelectAll() { vint lastIndex=documentElement->GetDocument()->paragraphs.Count()-1; Ptr lastParagraph=documentElement->GetDocument()->paragraphs[lastIndex]; TextPos begin(0, 0); TextPos end(lastIndex, lastParagraph->GetText(false).Length()); SetCaret(begin, end); } WString GuiDocumentCommonInterface::GetSelectionText() { TextPos begin=documentElement->GetCaretBegin(); TextPos end=documentElement->GetCaretEnd(); if(begin>end) { TextPos temp=begin; begin=end; end=temp; } Ptr model=documentElement->GetDocument()->CopyDocument(begin, end, false); return model->GetText(true); } void GuiDocumentCommonInterface::SetSelectionText(const WString& value) { List paragraphs; { stream::StringReader reader(value); WString paragraph; bool empty=true; while(!reader.IsEnd()) { WString line=reader.ReadLine(); if(empty) { paragraph+=line; empty=false; } else if(line!=L"") { paragraph+=L"\r\n"+line; } else { paragraphs.Add(paragraph); paragraph=L""; empty=true; } } if(!empty) { paragraphs.Add(paragraph); } } TextPos begin=documentElement->GetCaretBegin(); TextPos end=documentElement->GetCaretEnd(); if(begin>end) { TextPos temp=begin; begin=end; end=temp; } Array text; CopyFrom(text, paragraphs); EditText(begin, end, documentElement->IsCaretEndPreferFrontSide(), text); } Ptr GuiDocumentCommonInterface::GetSelectionModel() { TextPos begin=documentElement->GetCaretBegin(); TextPos end=documentElement->GetCaretEnd(); if(begin>end) { TextPos temp=begin; begin=end; end=temp; } Ptr model=documentElement->GetDocument()->CopyDocument(begin, end, true); return model; } void GuiDocumentCommonInterface::SetSelectionModel(Ptr value) { TextPos begin=documentElement->GetCaretBegin(); TextPos end=documentElement->GetCaretEnd(); if(begin>end) { TextPos temp=begin; begin=end; end=temp; } EditRun(begin, end, value); } //================ clipboard operations bool GuiDocumentCommonInterface::CanCut() { return editMode==Editable && documentElement->GetCaretBegin()!=documentElement->GetCaretEnd(); } bool GuiDocumentCommonInterface::CanCopy() { return documentElement->GetCaretBegin()!=documentElement->GetCaretEnd(); } bool GuiDocumentCommonInterface::CanPaste() { return editMode==Editable && GetCurrentController()->ClipboardService()->ContainsText(); } bool GuiDocumentCommonInterface::Cut() { if(CanCut()) { GetCurrentController()->ClipboardService()->SetText(GetSelectionText()); SetSelectionText(L""); return true; } else { return false; } } bool GuiDocumentCommonInterface::Copy() { if(CanCopy()) { GetCurrentController()->ClipboardService()->SetText(GetSelectionText()); return true; } else { return false; } } bool GuiDocumentCommonInterface::Paste() { if(CanPaste()) { SetSelectionText(GetCurrentController()->ClipboardService()->GetText()); return true; } else { return false; } } //================ undo redo control bool GuiDocumentCommonInterface::CanUndo() { return editMode==Editable && undoRedoProcessor->CanUndo(); } bool GuiDocumentCommonInterface::CanRedo() { return editMode==Editable && undoRedoProcessor->CanRedo(); } void GuiDocumentCommonInterface::ClearUndoRedo() { undoRedoProcessor->ClearUndoRedo(); } bool GuiDocumentCommonInterface::GetModified() { return undoRedoProcessor->GetModified(); } void GuiDocumentCommonInterface::NotifyModificationSaved() { undoRedoProcessor->NotifyModificationSaved(); } bool GuiDocumentCommonInterface::Undo() { if(CanUndo()) { return undoRedoProcessor->Undo(); } else { return false; } } bool GuiDocumentCommonInterface::Redo() { if(CanRedo()) { return undoRedoProcessor->Redo(); } else { return false; } } /*********************************************************************** GuiDocumentViewer ***********************************************************************/ Point GuiDocumentViewer::GetDocumentViewPosition() { return GetViewBounds().LeftTop(); } void GuiDocumentViewer::EnsureRectVisible(Rect bounds) { Rect viewBounds=GetViewBounds(); vint offset=0; if(bounds.y1viewBounds.y2) { offset=bounds.y2-viewBounds.y2; } GetVerticalScroll()->SetPosition(viewBounds.y1+offset); } GuiDocumentViewer::GuiDocumentViewer(GuiDocumentViewer::IStyleProvider* styleProvider) :GuiScrollContainer(styleProvider) , GuiDocumentCommonInterface(styleProvider->GetBaselineDocument()) { SetExtendToFullWidth(true); SetHorizontalAlwaysVisible(false); SetFocusableComposition(GetBoundsComposition()); InstallDocumentViewer(this, GetContainerComposition()); SetDocument(new DocumentModel); } GuiDocumentViewer::~GuiDocumentViewer() { } const WString& GuiDocumentViewer::GetText() { text=documentElement->GetDocument()->GetText(true); return text; } void GuiDocumentViewer::SetText(const WString& value) { SelectAll(); SetSelectionText(value); } /*********************************************************************** GuiDocumentLabel ***********************************************************************/ GuiDocumentLabel::GuiDocumentLabel(GuiDocumentLabel::IStyleController* styleController) :GuiControl(styleController) , GuiDocumentCommonInterface(styleController->GetBaselineDocument()) { GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); SetFocusableComposition(GetBoundsComposition()); InstallDocumentViewer(this, GetContainerComposition()); SetDocument(new DocumentModel); } GuiDocumentLabel::~GuiDocumentLabel() { } const WString& GuiDocumentLabel::GetText() { text=documentElement->GetDocument()->GetText(true); return text; } void GuiDocumentLabel::SetText(const WString& value) { SelectAll(); SetSelectionText(value); } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\GUITEXTCOMMONINTERFACE.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace elements::text; using namespace compositions; /*********************************************************************** GuiTextBoxCommonInterface::DefaultCallback ***********************************************************************/ GuiTextBoxCommonInterface::DefaultCallback::DefaultCallback(elements::GuiColorizedTextElement* _textElement, compositions::GuiGraphicsComposition* _textComposition) :textElement(_textElement) ,textComposition(_textComposition) { } GuiTextBoxCommonInterface::DefaultCallback::~DefaultCallback() { } TextPos GuiTextBoxCommonInterface::DefaultCallback::GetLeftWord(TextPos pos) { return pos; } TextPos GuiTextBoxCommonInterface::DefaultCallback::GetRightWord(TextPos pos) { return pos; } void GuiTextBoxCommonInterface::DefaultCallback::GetWord(TextPos pos, TextPos& begin, TextPos& end) { begin=pos; end=pos; } vint GuiTextBoxCommonInterface::DefaultCallback::GetPageRows() { return textComposition->GetBounds().Height()/textElement->GetLines().GetRowHeight(); } bool GuiTextBoxCommonInterface::DefaultCallback::BeforeModify(TextPos start, TextPos end, const WString& originalText, WString& inputText) { return true; } /*********************************************************************** GuiTextBoxCommonInterface ***********************************************************************/ void GuiTextBoxCommonInterface::UpdateCaretPoint() { GuiGraphicsHost* host=textComposition->GetRelatedGraphicsHost(); if(host) { Rect caret=textElement->GetLines().GetRectFromTextPos(textElement->GetCaretEnd()); Point view=textElement->GetViewPosition(); vint x=caret.x1-view.x; vint y=caret.y2-view.y; host->SetCaretPoint(Point(x, y), textComposition); } } void GuiTextBoxCommonInterface::Move(TextPos pos, bool shift) { TextPos oldBegin=textElement->GetCaretBegin(); TextPos oldEnd=textElement->GetCaretEnd(); pos=textElement->GetLines().Normalize(pos); if(!shift) { textElement->SetCaretBegin(pos); } textElement->SetCaretEnd(pos); if(textControl) { GuiGraphicsHost* host=textComposition->GetRelatedGraphicsHost(); if(host) { if(host->GetFocusedComposition()==textControl->GetFocusableComposition()) { textElement->SetCaretVisible(true); } } } Rect bounds=textElement->GetLines().GetRectFromTextPos(pos); Rect view=Rect(textElement->GetViewPosition(), textComposition->GetBounds().GetSize()); Point viewPoint=view.LeftTop(); if(view.x2>view.x1 && view.y2>view.y1) { if(bounds.x1view.x2) { viewPoint.x=bounds.x2-view.Width(); } if(bounds.y1view.y2) { viewPoint.y=bounds.y2-view.Height(); } } callback->ScrollToView(viewPoint); UpdateCaretPoint(); TextPos newBegin=textElement->GetCaretBegin(); TextPos newEnd=textElement->GetCaretEnd(); if(oldBegin!=newBegin || oldEnd!=newEnd) { ICommonTextEditCallback::TextCaretChangedStruct arguments; arguments.oldBegin=oldBegin; arguments.oldEnd=oldEnd; arguments.newBegin=newBegin; arguments.newEnd=newEnd; arguments.editVersion=editVersion; for(vint i=0;iTextCaretChanged(arguments); } SelectionChanged.Execute(textControl->GetNotifyEventArguments()); } } void GuiTextBoxCommonInterface::Modify(TextPos start, TextPos end, const WString& input, bool asKeyInput) { if(start>end) { TextPos temp=start; start=end; end=temp; } TextPos originalStart=start; TextPos originalEnd=end; WString originalText=textElement->GetLines().GetText(start, end); WString inputText=input; if(callback->BeforeModify(start, end, originalText, inputText)) { { ICommonTextEditCallback::TextEditPreviewStruct arguments; arguments.originalStart=originalStart; arguments.originalEnd=originalEnd; arguments.originalText=originalText; arguments.inputText=inputText; arguments.editVersion=editVersion; arguments.keyInput=asKeyInput; for(vint i=0;iTextEditPreview(arguments); } inputText=arguments.inputText; if(originalStart!=arguments.originalStart || originalEnd!=arguments.originalEnd) { originalStart=arguments.originalStart; originalEnd=arguments.originalEnd; originalText=textElement->GetLines().GetText(originalStart, originalEnd); start=originalStart; end=originalEnd; } } SPIN_LOCK(elementModifyLock) { end=textElement->GetLines().Modify(start, end, inputText); } callback->AfterModify(originalStart, originalEnd, originalText, start, end, inputText); editVersion++; { ICommonTextEditCallback::TextEditNotifyStruct arguments; arguments.originalStart=originalStart; arguments.originalEnd=originalEnd; arguments.originalText=originalText; arguments.inputStart=start; arguments.inputEnd=end; arguments.inputText=inputText; arguments.editVersion=editVersion; arguments.keyInput=asKeyInput; for(vint i=0;iTextEditNotify(arguments); } } Move(end, false); for(vint i=0;iTextEditFinished(editVersion); } textControl->TextChanged.Execute(textControl->GetNotifyEventArguments()); } } bool GuiTextBoxCommonInterface::ProcessKey(vint code, bool shift, bool ctrl) { if(IGuiShortcutKeyItem* item=internalShortcutKeyManager->TryGetShortcut(ctrl, shift, false, code)) { GuiEventArgs arguments; item->Executed.Execute(arguments); return true; } TextPos begin=textElement->GetCaretBegin(); TextPos end=textElement->GetCaretEnd(); switch(code) { case VKEY_ESCAPE: if(autoComplete && autoComplete->IsListOpening() && !shift && !ctrl) { autoComplete->CloseList(); } return true; case VKEY_RETURN: if(autoComplete && autoComplete->IsListOpening() && !shift && !ctrl) { if(autoComplete->ApplySelectedListItem()) { preventEnterDueToAutoComplete=true; return true; } } break; case VKEY_UP: if(autoComplete && autoComplete->IsListOpening() && !shift && !ctrl) { autoComplete->SelectPreviousListItem(); } else { end.row--; Move(end, shift); } return true; case VKEY_DOWN: if(autoComplete && autoComplete->IsListOpening() && !shift && !ctrl) { autoComplete->SelectNextListItem(); } else { end.row++; Move(end, shift); } return true; case VKEY_LEFT: { if(ctrl) { Move(callback->GetLeftWord(end), shift); } else { if(end.column==0) { if(end.row>0) { end.row--; end=textElement->GetLines().Normalize(end); end.column=textElement->GetLines().GetLine(end.row).dataLength; } } else { end.column--; } Move(end, shift); } } return true; case VKEY_RIGHT: { if(ctrl) { Move(callback->GetRightWord(end), shift); } else { if(end.column==textElement->GetLines().GetLine(end.row).dataLength) { if(end.rowGetLines().GetCount()-1) { end.row++; end.column=0; } } else { end.column++; } Move(end, shift); } } return true; case VKEY_HOME: { if(ctrl) { Move(TextPos(0, 0), shift); } else { end.column=0; Move(end, shift); } } return true; case VKEY_END: { if(ctrl) { end.row=textElement->GetLines().GetCount()-1; } end.column=textElement->GetLines().GetLine(end.row).dataLength; Move(end, shift); } return true; case VKEY_PRIOR: { end.row-=callback->GetPageRows(); Move(end, shift); } return true; case VKEY_NEXT: { end.row+=callback->GetPageRows(); Move(end, shift); } return true; case VKEY_BACK: if(!readonly) { if(ctrl && !shift) { ProcessKey(VKEY_LEFT, true, true); ProcessKey(VKEY_BACK, false, false); } else if(!ctrl && shift) { ProcessKey(VKEY_UP, true, false); ProcessKey(VKEY_BACK, false, false); } else { if(begin==end) { ProcessKey(VKEY_LEFT, true, false); } SetSelectionTextAsKeyInput(L""); } return true; } break; case VKEY_DELETE: if(!readonly) { if(ctrl && !shift) { ProcessKey(VKEY_RIGHT, true, true); ProcessKey(VKEY_DELETE, false, false); } else if(!ctrl && shift) { ProcessKey(VKEY_DOWN, true, false); ProcessKey(VKEY_DELETE, false, false); } else { if(begin==end) { ProcessKey(VKEY_RIGHT, true, false); } SetSelectionTextAsKeyInput(L""); } return true; } break; } return false; } void GuiTextBoxCommonInterface::OnGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { textElement->SetFocused(true); textElement->SetCaretVisible(true); UpdateCaretPoint(); } void GuiTextBoxCommonInterface::OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { textElement->SetFocused(false); textElement->SetCaretVisible(false); } void GuiTextBoxCommonInterface::OnCaretNotify(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { textElement->SetCaretVisible(!textElement->GetCaretVisible()); } void GuiTextBoxCommonInterface::OnLeftButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) { dragging=true; TextPos pos=GetNearestTextPos(Point(arguments.x, arguments.y)); Move(pos, arguments.shift); } } void GuiTextBoxCommonInterface::OnLeftButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) { dragging=false; } } void GuiTextBoxCommonInterface::OnMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) { if(dragging) { TextPos pos=GetNearestTextPos(Point(arguments.x, arguments.y)); Move(pos, true); } } } void GuiTextBoxCommonInterface::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) { if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) { if(ProcessKey(arguments.code, arguments.shift, arguments.ctrl)) { arguments.handled=true; } } } void GuiTextBoxCommonInterface::OnCharInput(compositions::GuiGraphicsComposition* sender, compositions::GuiCharEventArgs& arguments) { if(preventEnterDueToAutoComplete) { preventEnterDueToAutoComplete=false; if(arguments.code==VKEY_RETURN) { return; } } if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) { if(!readonly && arguments.code!=VKEY_ESCAPE && arguments.code!=VKEY_BACK && !arguments.ctrl) { SetSelectionTextAsKeyInput(WString(arguments.code)); } } } void GuiTextBoxCommonInterface::Install(elements::GuiColorizedTextElement* _textElement, compositions::GuiGraphicsComposition* _textComposition, GuiControl* _textControl) { textElement=_textElement; textComposition=_textComposition; textControl=_textControl; textComposition->SetAssociatedCursor(GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::IBeam)); SelectionChanged.SetAssociatedComposition(textControl->GetBoundsComposition()); GuiGraphicsComposition* focusableComposition=textControl->GetFocusableComposition(); focusableComposition->GetEventReceiver()->gotFocus.AttachMethod(this, &GuiTextBoxCommonInterface::OnGotFocus); focusableComposition->GetEventReceiver()->lostFocus.AttachMethod(this, &GuiTextBoxCommonInterface::OnLostFocus); focusableComposition->GetEventReceiver()->caretNotify.AttachMethod(this, &GuiTextBoxCommonInterface::OnCaretNotify); textComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiTextBoxCommonInterface::OnLeftButtonDown); textComposition->GetEventReceiver()->leftButtonUp.AttachMethod(this, &GuiTextBoxCommonInterface::OnLeftButtonUp); textComposition->GetEventReceiver()->mouseMove.AttachMethod(this, &GuiTextBoxCommonInterface::OnMouseMove); focusableComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiTextBoxCommonInterface::OnKeyDown); focusableComposition->GetEventReceiver()->charInput.AttachMethod(this, &GuiTextBoxCommonInterface::OnCharInput); for(vint i=0;iAttach(textElement, elementModifyLock, textComposition ,editVersion); } } GuiTextBoxCommonInterface::ICallback* GuiTextBoxCommonInterface::GetCallback() { return callback; } void GuiTextBoxCommonInterface::SetCallback(ICallback* value) { callback=value; } bool GuiTextBoxCommonInterface::AttachTextEditCallback(Ptr value) { if(textEditCallbacks.Contains(value.Obj())) { return false; } else { textEditCallbacks.Add(value); if(textElement) { value->Attach(textElement, elementModifyLock, textComposition, editVersion); } return true; } } bool GuiTextBoxCommonInterface::DetachTextEditCallback(Ptr value) { if(textEditCallbacks.Remove(value.Obj())) { value->Detach(); return true; } else { return false; } } void GuiTextBoxCommonInterface::AddShortcutCommand(vint key, const Func& eventHandler) { IGuiShortcutKeyItem* item=internalShortcutKeyManager->CreateShortcut(true, false, false, key); item->Executed.AttachLambda([=](GuiGraphicsComposition* sender, GuiEventArgs& arguments) { eventHandler(); }); } elements::GuiColorizedTextElement* GuiTextBoxCommonInterface::GetTextElement() { return textElement; } void GuiTextBoxCommonInterface::UnsafeSetText(const WString& value) { if(textElement) { TextPos end; if(textElement->GetLines().GetCount()>0) { end.row=textElement->GetLines().GetCount()-1; end.column=textElement->GetLines().GetLine(end.row).dataLength; } Modify(TextPos(), end, value, false); } } GuiTextBoxCommonInterface::GuiTextBoxCommonInterface() :textElement(0) ,textComposition(0) ,editVersion(0) ,textControl(0) ,callback(0) ,dragging(false) ,readonly(false) ,preventEnterDueToAutoComplete(false) { undoRedoProcessor=new GuiTextBoxUndoRedoProcessor; AttachTextEditCallback(undoRedoProcessor); internalShortcutKeyManager=new GuiShortcutKeyManager; AddShortcutCommand('Z', Func(this, &GuiTextBoxCommonInterface::Undo)); AddShortcutCommand('Y', Func(this, &GuiTextBoxCommonInterface::Redo)); AddShortcutCommand('A', Func(this, &GuiTextBoxCommonInterface::SelectAll)); AddShortcutCommand('X', Func(this, &GuiTextBoxCommonInterface::Cut)); AddShortcutCommand('C', Func(this, &GuiTextBoxCommonInterface::Copy)); AddShortcutCommand('V', Func(this, &GuiTextBoxCommonInterface::Paste)); } GuiTextBoxCommonInterface::~GuiTextBoxCommonInterface() { if(colorizer) { DetachTextEditCallback(colorizer); colorizer=0; } if(undoRedoProcessor) { DetachTextEditCallback(undoRedoProcessor); undoRedoProcessor=0; } for(vint i=0;iDetach(); } textEditCallbacks.Clear(); } //================ clipboard operations bool GuiTextBoxCommonInterface::CanCut() { return !readonly && textElement->GetCaretBegin()!=textElement->GetCaretEnd() && textElement->GetPasswordChar()==L'\0'; } bool GuiTextBoxCommonInterface::CanCopy() { return textElement->GetCaretBegin()!=textElement->GetCaretEnd() && textElement->GetPasswordChar()==L'\0'; } bool GuiTextBoxCommonInterface::CanPaste() { return !readonly && GetCurrentController()->ClipboardService()->ContainsText() && textElement->GetPasswordChar()==L'\0'; } bool GuiTextBoxCommonInterface::Cut() { if(CanCut()) { GetCurrentController()->ClipboardService()->SetText(GetSelectionText()); SetSelectionText(L""); return true; } else { return false; } } bool GuiTextBoxCommonInterface::Copy() { if(CanCopy()) { GetCurrentController()->ClipboardService()->SetText(GetSelectionText()); return true; } else { return false; } } bool GuiTextBoxCommonInterface::Paste() { if(CanPaste()) { SetSelectionText(GetCurrentController()->ClipboardService()->GetText()); return true; } else { return false; } } //================ editing control bool GuiTextBoxCommonInterface::GetReadonly() { return readonly; } void GuiTextBoxCommonInterface::SetReadonly(bool value) { readonly=value; } //================ text operations void GuiTextBoxCommonInterface::Select(TextPos begin, TextPos end) { Move(begin, false); Move(end, true); } void GuiTextBoxCommonInterface::SelectAll() { vint row=textElement->GetLines().GetCount()-1; Move(TextPos(0, 0), false); Move(TextPos(row, textElement->GetLines().GetLine(row).dataLength), true); } WString GuiTextBoxCommonInterface::GetSelectionText() { TextPos selectionBegin=textElement->GetCaretBegin()GetCaretEnd()?textElement->GetCaretBegin():textElement->GetCaretEnd(); TextPos selectionEnd=textElement->GetCaretBegin()>textElement->GetCaretEnd()?textElement->GetCaretBegin():textElement->GetCaretEnd(); return textElement->GetLines().GetText(selectionBegin, selectionEnd); } void GuiTextBoxCommonInterface::SetSelectionText(const WString& value) { Modify(textElement->GetCaretBegin(), textElement->GetCaretEnd(), value, false); } void GuiTextBoxCommonInterface::SetSelectionTextAsKeyInput(const WString& value) { Modify(textElement->GetCaretBegin(), textElement->GetCaretEnd(), value, true); } WString GuiTextBoxCommonInterface::GetRowText(vint row) { TextPos start=textElement->GetLines().Normalize(TextPos(row, 0)); TextPos end=TextPos(start.row, textElement->GetLines().GetLine(start.row).dataLength); return GetFragmentText(start, end); } vint GuiTextBoxCommonInterface::GetRowCount() { return textElement->GetLines().GetCount(); } WString GuiTextBoxCommonInterface::GetFragmentText(TextPos start, TextPos end) { start=textElement->GetLines().Normalize(start); end=textElement->GetLines().Normalize(end); return textElement->GetLines().GetText(start, end); } TextPos GuiTextBoxCommonInterface::GetCaretBegin() { return textElement->GetCaretBegin(); } TextPos GuiTextBoxCommonInterface::GetCaretEnd() { return textElement->GetCaretEnd(); } TextPos GuiTextBoxCommonInterface::GetCaretSmall() { TextPos c1=GetCaretBegin(); TextPos c2=GetCaretEnd(); return c1c2?c1:c2; } //================ position query vint GuiTextBoxCommonInterface::GetRowWidth(vint row) { return textElement->GetLines().GetRowWidth(row); } vint GuiTextBoxCommonInterface::GetRowHeight() { return textElement->GetLines().GetRowHeight(); } vint GuiTextBoxCommonInterface::GetMaxWidth() { return textElement->GetLines().GetMaxWidth(); } vint GuiTextBoxCommonInterface::GetMaxHeight() { return textElement->GetLines().GetMaxHeight(); } TextPos GuiTextBoxCommonInterface::GetTextPosFromPoint(Point point) { Point view=textElement->GetViewPosition(); return textElement->GetLines().GetTextPosFromPoint(Point(point.x+view.x, point.y+view.y)); } Point GuiTextBoxCommonInterface::GetPointFromTextPos(TextPos pos) { Point view=textElement->GetViewPosition(); Point result=textElement->GetLines().GetPointFromTextPos(pos); return Point(result.x-view.x, result.y-view.y); } Rect GuiTextBoxCommonInterface::GetRectFromTextPos(TextPos pos) { Point view=textElement->GetViewPosition(); Rect result=textElement->GetLines().GetRectFromTextPos(pos); return Rect(Point(result.x1-view.x, result.y1-view.y), result.GetSize()); } TextPos GuiTextBoxCommonInterface::GetNearestTextPos(Point point) { Point viewPosition=textElement->GetViewPosition(); Point mousePosition=Point(point.x+viewPosition.x, point.y+viewPosition.y); TextPos pos=textElement->GetLines().GetTextPosFromPoint(mousePosition); if(pos.columnGetLines().GetLine(pos.row).dataLength) { Rect rect=textElement->GetLines().GetRectFromTextPos(pos); if(abs((int)(rect.x1-mousePosition.x))>=abs((int)(rect.x2-1-mousePosition.x))) { pos.column++; } } return pos; } //================ colorizing Ptr GuiTextBoxCommonInterface::GetColorizer() { return colorizer; } void GuiTextBoxCommonInterface::SetColorizer(Ptr value) { if (!filledDefaultColors) { filledDefaultColors = true; CopyFrom(defaultColors, GetTextElement()->GetColors()); } if(colorizer) { DetachTextEditCallback(colorizer); } colorizer=value; if(colorizer) { AttachTextEditCallback(colorizer); GetTextElement()->SetColors(colorizer->GetColors()); } else { GetTextElement()->SetColors(defaultColors); GetTextElement()->ResetTextColorIndex(0); } } //================ auto complete Ptr GuiTextBoxCommonInterface::GetAutoComplete() { return autoComplete; } void GuiTextBoxCommonInterface::SetAutoComplete(Ptr value) { if(autoComplete) { DetachTextEditCallback(autoComplete); } autoComplete=value; if(autoComplete) { AttachTextEditCallback(autoComplete); } } //================ undo redo control vuint GuiTextBoxCommonInterface::GetEditVersion() { return editVersion; } bool GuiTextBoxCommonInterface::CanUndo() { return !readonly && undoRedoProcessor->CanUndo(); } bool GuiTextBoxCommonInterface::CanRedo() { return !readonly && undoRedoProcessor->CanRedo(); } void GuiTextBoxCommonInterface::ClearUndoRedo() { undoRedoProcessor->ClearUndoRedo(); } bool GuiTextBoxCommonInterface::GetModified() { return undoRedoProcessor->GetModified(); } void GuiTextBoxCommonInterface::NotifyModificationSaved() { undoRedoProcessor->NotifyModificationSaved(); } bool GuiTextBoxCommonInterface::Undo() { if(CanUndo()) { return undoRedoProcessor->Undo(); } else { return false; } } bool GuiTextBoxCommonInterface::Redo() { if(CanRedo()) { return undoRedoProcessor->Redo(); } else { return false; } } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\GUITEXTCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace elements::text; using namespace compositions; /*********************************************************************** GuiMultilineTextBox::StyleController ***********************************************************************/ GuiMultilineTextBox::StyleController::StyleController(GuiScrollView::IStyleProvider* styleProvider) :GuiScrollView::StyleController(styleProvider) ,textElement(0) ,textComposition(0) ,textBox(0) { textElement=GuiColorizedTextElement::Create(); textComposition=new GuiBoundsComposition; textComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); textComposition->SetOwnedElement(textElement); GetInternalContainerComposition()->AddChild(textComposition); } GuiMultilineTextBox::StyleController::~StyleController() { } void GuiMultilineTextBox::StyleController::Initialize(GuiMultilineTextBox* control) { textBox=control; } elements::GuiColorizedTextElement* GuiMultilineTextBox::StyleController::GetTextElement() { return textElement; } compositions::GuiGraphicsComposition* GuiMultilineTextBox::StyleController::GetTextComposition() { return textComposition; } void GuiMultilineTextBox::StyleController::SetViewPosition(Point value) { textElement->SetViewPosition(value); } void GuiMultilineTextBox::StyleController::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { GuiScrollView::StyleController::SetFocusableComposition(value); textBox->Install(textElement, textComposition, scrollView); if(!textBox->GetCallback()) { if(!defaultCallback) { defaultCallback=new TextElementOperatorCallback(dynamic_cast(scrollView)); } textBox->SetCallback(defaultCallback.Obj()); } } WString GuiMultilineTextBox::StyleController::GetText() { return textElement->GetLines().GetText(); } void GuiMultilineTextBox::StyleController::SetText(const WString& value) { if(textBox) { textBox->UnsafeSetText(value); } textElement->SetCaretBegin(TextPos(0, 0)); textElement->SetCaretEnd(TextPos(0, 0)); GuiScrollView::StyleController::SetText(value); } void GuiMultilineTextBox::StyleController::SetFont(const FontProperties& value) { textElement->SetFont(value); GuiScrollView::StyleController::SetFont(value); } void GuiMultilineTextBox::StyleController::SetVisuallyEnabled(bool value) { textElement->SetVisuallyEnabled(value); GuiScrollView::StyleController::SetVisuallyEnabled(value); } /*********************************************************************** GuiMultilineTextBox::DefaultTextElementOperatorCallback ***********************************************************************/ GuiMultilineTextBox::TextElementOperatorCallback::TextElementOperatorCallback(GuiMultilineTextBox* _textControl) :GuiTextBoxCommonInterface::DefaultCallback( dynamic_cast(_textControl->GetStyleController())->GetTextElement(), dynamic_cast(_textControl->GetStyleController())->GetTextComposition() ) ,textControl(_textControl) ,textController(dynamic_cast(_textControl->GetStyleController())) { } void GuiMultilineTextBox::TextElementOperatorCallback::AfterModify(TextPos originalStart, TextPos originalEnd, const WString& originalText, TextPos inputStart, TextPos inputEnd, const WString& inputText) { textControl->CalculateView(); } void GuiMultilineTextBox::TextElementOperatorCallback::ScrollToView(Point point) { point.x+=TextMargin; point.y+=TextMargin; Point oldPoint(textControl->GetHorizontalScroll()->GetPosition(), textControl->GetVerticalScroll()->GetPosition()); vint marginX=0; vint marginY=0; if(oldPoint.xpoint.x) { marginX=-TextMargin; } if(oldPoint.ypoint.y) { marginY=-TextMargin; } textControl->GetHorizontalScroll()->SetPosition(point.x+marginX); textControl->GetVerticalScroll()->SetPosition(point.y+marginY); } vint GuiMultilineTextBox::TextElementOperatorCallback::GetTextMargin() { return TextMargin; } /*********************************************************************** GuiMultilineTextBox ***********************************************************************/ void GuiMultilineTextBox::CalculateViewAndSetScroll() { CalculateView(); vint smallMove=styleController->GetTextElement()->GetLines().GetRowHeight(); vint bigMove=smallMove*5; styleController->GetHorizontalScroll()->SetSmallMove(smallMove); styleController->GetHorizontalScroll()->SetBigMove(bigMove); styleController->GetVerticalScroll()->SetSmallMove(smallMove); styleController->GetVerticalScroll()->SetBigMove(bigMove); } void GuiMultilineTextBox::OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget) { CalculateViewAndSetScroll(); GuiScrollView::OnRenderTargetChanged(renderTarget); } Size GuiMultilineTextBox::QueryFullSize() { text::TextLines& lines=styleController->GetTextElement()->GetLines(); return Size(lines.GetMaxWidth()+TextMargin*2, lines.GetMaxHeight()+TextMargin*2); } void GuiMultilineTextBox::UpdateView(Rect viewBounds) { styleController->SetViewPosition(viewBounds.LeftTop()-Size(TextMargin, TextMargin)); } void GuiMultilineTextBox::OnBoundsMouseButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(GetVisuallyEnabled()) { boundsComposition->GetRelatedGraphicsHost()->SetFocus(boundsComposition); } } GuiMultilineTextBox::GuiMultilineTextBox(GuiMultilineTextBox::IStyleProvider* styleProvider) :GuiScrollView(new StyleController(styleProvider)) { styleController=dynamic_cast(GetStyleController()); styleController->Initialize(this); SetFocusableComposition(boundsComposition); boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiMultilineTextBox::OnBoundsMouseButtonDown); boundsComposition->GetEventReceiver()->middleButtonDown.AttachMethod(this, &GuiMultilineTextBox::OnBoundsMouseButtonDown); boundsComposition->GetEventReceiver()->rightButtonDown.AttachMethod(this, &GuiMultilineTextBox::OnBoundsMouseButtonDown); } GuiMultilineTextBox::~GuiMultilineTextBox() { } const WString& GuiMultilineTextBox::GetText() { text=styleController->GetText(); return text; } void GuiMultilineTextBox::SetText(const WString& value) { text=styleController->GetText(); GuiScrollView::SetText(value); CalculateView(); } void GuiMultilineTextBox::SetFont(const FontProperties& value) { GuiScrollView::SetFont(value); CalculateViewAndSetScroll(); } /*********************************************************************** GuiSinglelineTextBox::StyleController ***********************************************************************/ GuiSinglelineTextBox::StyleController::StyleController(IStyleProvider* _styleProvider) :styleProvider(_styleProvider) ,boundsComposition(0) ,containerComposition(0) ,textBox(0) ,textElement(0) ,textComposition(0) { boundsComposition=new GuiBoundsComposition; boundsComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); containerComposition=styleProvider->InstallBackground(boundsComposition); textElement=GuiColorizedTextElement::Create(); textElement->SetViewPosition(Point(-TextMargin, -TextMargin)); textCompositionTable=new GuiTableComposition; textCompositionTable->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); textCompositionTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); textCompositionTable->SetRowsAndColumns(3, 1); textCompositionTable->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); textCompositionTable->SetRowOption(1, GuiCellOption::AbsoluteOption(0)); textCompositionTable->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); textCompositionTable->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); containerComposition->AddChild(textCompositionTable); textComposition=new GuiCellComposition; textComposition->SetOwnedElement(textElement); textCompositionTable->AddChild(textComposition); textComposition->SetSite(1, 0, 1, 1); styleProvider->AssociateStyleController(this); } GuiSinglelineTextBox::StyleController::~StyleController() { } void GuiSinglelineTextBox::StyleController::SetTextBox(GuiSinglelineTextBox* control) { textBox=control; } void GuiSinglelineTextBox::StyleController::RearrangeTextElement() { textCompositionTable->SetRowOption(1, GuiCellOption::AbsoluteOption(textElement->GetLines().GetRowHeight()+2*TextMargin)); } compositions::GuiBoundsComposition* GuiSinglelineTextBox::StyleController::GetBoundsComposition() { return boundsComposition; } compositions::GuiGraphicsComposition* GuiSinglelineTextBox::StyleController::GetContainerComposition() { return containerComposition; } void GuiSinglelineTextBox::StyleController::SetFocusableComposition(compositions::GuiGraphicsComposition* value) { styleProvider->SetFocusableComposition(value); textBox->Install(textElement, textComposition, textBox); if(!textBox->GetCallback()) { if(!defaultCallback) { defaultCallback=new TextElementOperatorCallback(textBox); } textBox->SetCallback(defaultCallback.Obj()); } } WString GuiSinglelineTextBox::StyleController::GetText() { return textElement->GetLines().GetText(); } void GuiSinglelineTextBox::StyleController::SetText(const WString& value) { if(textBox) { textBox->UnsafeSetText(value); } textElement->SetCaretBegin(TextPos(0, 0)); textElement->SetCaretEnd(TextPos(0, 0)); styleProvider->SetText(value); } void GuiSinglelineTextBox::StyleController::SetFont(const FontProperties& value) { textElement->SetFont(value); styleProvider->SetFont(value); textComposition->SetPreferredMinSize(Size(0, textElement->GetLines().GetRowHeight())); } void GuiSinglelineTextBox::StyleController::SetVisuallyEnabled(bool value) { textElement->SetVisuallyEnabled(value); styleProvider->SetVisuallyEnabled(value); } elements::GuiColorizedTextElement* GuiSinglelineTextBox::StyleController::GetTextElement() { return textElement; } compositions::GuiGraphicsComposition* GuiSinglelineTextBox::StyleController::GetTextComposition() { return textComposition; } void GuiSinglelineTextBox::StyleController::SetViewPosition(Point value) { textElement->SetViewPosition(value); } /*********************************************************************** GuiSinglelineTextBox::DefaultTextElementOperatorCallback ***********************************************************************/ GuiSinglelineTextBox::TextElementOperatorCallback::TextElementOperatorCallback(GuiSinglelineTextBox* _textControl) :GuiTextBoxCommonInterface::DefaultCallback( dynamic_cast(_textControl->GetStyleController())->GetTextElement(), dynamic_cast(_textControl->GetStyleController())->GetTextComposition() ) ,textControl(_textControl) ,textController(dynamic_cast(_textControl->GetStyleController())) { } bool GuiSinglelineTextBox::TextElementOperatorCallback::BeforeModify(TextPos start, TextPos end, const WString& originalText, WString& inputText) { vint length=inputText.Length(); const wchar_t* input=inputText.Buffer(); for(vint i=0;iGetViewPosition().x; vint marginX=0; if(oldXnewX) { marginX=-TextMargin; } newX+=marginX; vint minX=-TextMargin; vint maxX=textElement->GetLines().GetMaxWidth()+TextMargin-textComposition->GetBounds().Width(); if(newX>=maxX) { newX=maxX-1; } if(newXSetViewPosition(Point(newX, -TextMargin)); } vint GuiSinglelineTextBox::TextElementOperatorCallback::GetTextMargin() { return TextMargin; } /*********************************************************************** GuiSinglelineTextBox ***********************************************************************/ void GuiSinglelineTextBox::OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget) { styleController->RearrangeTextElement(); GuiControl::OnRenderTargetChanged(renderTarget); } void GuiSinglelineTextBox::OnBoundsMouseButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) { if(GetVisuallyEnabled()) { boundsComposition->GetRelatedGraphicsHost()->SetFocus(boundsComposition); } } GuiSinglelineTextBox::GuiSinglelineTextBox(GuiSinglelineTextBox::IStyleProvider* styleProvider) :GuiControl(new StyleController(styleProvider)) { styleController=dynamic_cast(GetStyleController()); styleController->SetTextBox(this); SetFocusableComposition(boundsComposition); boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiSinglelineTextBox::OnBoundsMouseButtonDown); boundsComposition->GetEventReceiver()->middleButtonDown.AttachMethod(this, &GuiSinglelineTextBox::OnBoundsMouseButtonDown); boundsComposition->GetEventReceiver()->rightButtonDown.AttachMethod(this, &GuiSinglelineTextBox::OnBoundsMouseButtonDown); } GuiSinglelineTextBox::~GuiSinglelineTextBox() { } const WString& GuiSinglelineTextBox::GetText() { text=styleController->GetText(); return text; } void GuiSinglelineTextBox::SetText(const WString& value) { GuiControl::SetText(value); } void GuiSinglelineTextBox::SetFont(const FontProperties& value) { GuiControl::SetFont(value); styleController->RearrangeTextElement(); } wchar_t GuiSinglelineTextBox::GetPasswordChar() { return styleController->GetTextElement()->GetPasswordChar(); } void GuiSinglelineTextBox::SetPasswordChar(wchar_t value) { styleController->GetTextElement()->SetPasswordChar(value); } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTAUTOCOMPLETE.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; /*********************************************************************** GuiTextBoxAutoCompleteBase::TextListControlProvider ***********************************************************************/ GuiTextBoxAutoCompleteBase::TextListControlProvider::TextListControlProvider(GuiTextList::IStyleProvider* styleProvider) { autoCompleteList = new GuiTextList(styleProvider ? styleProvider : theme::GetCurrentTheme()->CreateTextListStyle(), theme::GetCurrentTheme()->CreateTextListItemStyle()); autoCompleteList->SetHorizontalAlwaysVisible(false); autoCompleteList->SetVerticalAlwaysVisible(false); } GuiTextBoxAutoCompleteBase::TextListControlProvider::~TextListControlProvider() { } GuiControl* GuiTextBoxAutoCompleteBase::TextListControlProvider::GetAutoCompleteControl() { return autoCompleteList; } GuiSelectableListControl* GuiTextBoxAutoCompleteBase::TextListControlProvider::GetListControl() { return autoCompleteList; } void GuiTextBoxAutoCompleteBase::TextListControlProvider::SetSortedContent(const collections::List& items) { autoCompleteList->GetItems().Clear(); FOREACH(AutoCompleteItem, item, items) { autoCompleteList->GetItems().Add(new list::TextItem(item.text)); } } vint GuiTextBoxAutoCompleteBase::TextListControlProvider::GetItemCount() { return autoCompleteList->GetItems().Count(); } WString GuiTextBoxAutoCompleteBase::TextListControlProvider::GetItemText(vint index) { return autoCompleteList->GetItems()[index]->GetText(); } /*********************************************************************** GuiTextBoxAutoCompleteBase ***********************************************************************/ bool GuiTextBoxAutoCompleteBase::IsPrefix(const WString& prefix, const WString& candidate) { if(candidate.Length()>=prefix.Length()) { if(INVLOC.Compare(prefix, candidate.Sub(0, prefix.Length()), Locale::IgnoreCase)==0) { return true; } } return false; } GuiTextBoxAutoCompleteBase::GuiTextBoxAutoCompleteBase(Ptr _autoCompleteControlProvider) :element(0) ,elementModifyLock(0) ,ownerComposition(0) ,autoCompleteControlProvider(_autoCompleteControlProvider) { if (!autoCompleteControlProvider) { autoCompleteControlProvider = new TextListControlProvider; } autoCompleteControlProvider->GetAutoCompleteControl()->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); autoCompletePopup = new GuiPopup(theme::GetCurrentTheme()->CreateMenuStyle()); autoCompletePopup->AddChild(autoCompleteControlProvider->GetAutoCompleteControl()); } GuiTextBoxAutoCompleteBase::~GuiTextBoxAutoCompleteBase() { delete autoCompletePopup; } void GuiTextBoxAutoCompleteBase::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) { if(_element) { SPIN_LOCK(_elementModifyLock) { element=_element; elementModifyLock=&_elementModifyLock; ownerComposition=_ownerComposition; } } } void GuiTextBoxAutoCompleteBase::Detach() { if(element && elementModifyLock) { SPIN_LOCK(*elementModifyLock) { element=0; elementModifyLock=0; } } } void GuiTextBoxAutoCompleteBase::TextEditPreview(TextEditPreviewStruct& arguments) { } void GuiTextBoxAutoCompleteBase::TextEditNotify(const TextEditNotifyStruct& arguments) { if(element && elementModifyLock) { if(IsListOpening()) { TextPos begin=GetListStartPosition(); TextPos end=arguments.inputEnd; WString editingText=element->GetLines().GetText(begin, end); HighlightList(editingText); } } } void GuiTextBoxAutoCompleteBase::TextCaretChanged(const TextCaretChangedStruct& arguments) { } void GuiTextBoxAutoCompleteBase::TextEditFinished(vuint editVersion) { } bool GuiTextBoxAutoCompleteBase::IsListOpening() { return autoCompletePopup->GetOpening(); } void GuiTextBoxAutoCompleteBase::OpenList(TextPos startPosition) { if(element && elementModifyLock) { autoCompleteStartPosition=startPosition; Rect bounds=element->GetLines().GetRectFromTextPos(startPosition); Point viewPosition=element->GetViewPosition(); GuiControl* ownerControl=ownerComposition->GetRelatedControl(); Rect compositionBounds=ownerComposition->GetGlobalBounds(); Rect controlBounds=ownerControl->GetBoundsComposition()->GetGlobalBounds(); vint px=compositionBounds.x1-controlBounds.x1-viewPosition.x; vint py=compositionBounds.y1-controlBounds.y1-viewPosition.y; bounds.x1+=px; bounds.x2+=px; bounds.y1+=py+5; bounds.y2+=py+5; autoCompletePopup->ShowPopup(ownerControl, bounds, true); } } void GuiTextBoxAutoCompleteBase::CloseList() { autoCompletePopup->Close(); } void GuiTextBoxAutoCompleteBase::SetListContent(const collections::List& items) { if(items.Count()==0) { CloseList(); } List sortedItems; CopyFrom( sortedItems, From(items) .OrderBy([](const AutoCompleteItem& a, const AutoCompleteItem& b) { return INVLOC.Compare(a.text, b.text, Locale::IgnoreCase); }) ); autoCompleteControlProvider->SetSortedContent(sortedItems); autoCompleteControlProvider->GetAutoCompleteControl()->GetBoundsComposition()->SetPreferredMinSize(Size(200, 200)); } TextPos GuiTextBoxAutoCompleteBase::GetListStartPosition() { return autoCompleteStartPosition; } bool GuiTextBoxAutoCompleteBase::SelectPreviousListItem() { if(!IsListOpening()) return false; if(autoCompleteControlProvider->GetListControl()->GetSelectedItems().Count()==0) { autoCompleteControlProvider->GetListControl()->SetSelected(0, true); } else { vint index=autoCompleteControlProvider->GetListControl()->GetSelectedItems()[0]; if (index > 0) index--; autoCompleteControlProvider->GetListControl()->SetSelected(index, true); autoCompleteControlProvider->GetListControl()->EnsureItemVisible(index); } return true; } bool GuiTextBoxAutoCompleteBase::SelectNextListItem() { if(!IsListOpening()) return false; if (autoCompleteControlProvider->GetListControl()->GetSelectedItems().Count() == 0) { autoCompleteControlProvider->GetListControl()->SetSelected(0, true); } else { vint index = autoCompleteControlProvider->GetListControl()->GetSelectedItems()[0]; if (index < autoCompleteControlProvider->GetItemCount() - 1) index++; autoCompleteControlProvider->GetListControl()->SetSelected(index, true); autoCompleteControlProvider->GetListControl()->EnsureItemVisible(index); } return true; } bool GuiTextBoxAutoCompleteBase::ApplySelectedListItem() { if(!IsListOpening()) return false; if(!ownerComposition) return false; const auto& selectedItems = autoCompleteControlProvider->GetListControl()->GetSelectedItems(); if (selectedItems.Count() == 0) return false; GuiTextBoxCommonInterface* ci=dynamic_cast(ownerComposition->GetRelatedControl()); if(!ci) return false; vint index = selectedItems[0]; WString selectedItem = autoCompleteControlProvider->GetItemText(index); TextPos begin = autoCompleteStartPosition; TextPos end = ci->GetCaretEnd(); ci->Select(begin, end); ci->SetSelectionText(selectedItem); CloseList(); return true; } WString GuiTextBoxAutoCompleteBase::GetSelectedListItem() { if(!IsListOpening()) return L""; const auto& selectedItems = autoCompleteControlProvider->GetListControl()->GetSelectedItems(); if (selectedItems.Count() == 0) return L""; vint index = selectedItems[0]; return autoCompleteControlProvider->GetItemText(index); } void GuiTextBoxAutoCompleteBase::HighlightList(const WString& editingText) { if(IsListOpening()) { vint first=0; vint last = autoCompleteControlProvider->GetItemCount() - 1; vint selected=-1; while (first <= last) { vint middle = (first + last) / 2; WString text = autoCompleteControlProvider->GetItemText(middle); if (IsPrefix(editingText, text)) { selected = middle; break; } vint result = INVLOC.Compare(editingText, text, Locale::IgnoreCase); if (result <= 0) { last = middle - 1; } else { first = middle + 1; } } while(selected>0) { WString text = autoCompleteControlProvider->GetItemText(selected - 1); if (IsPrefix(editingText, text)) { selected--; } else { break; } } if(selected!=-1) { autoCompleteControlProvider->GetListControl()->SetSelected(selected, true); autoCompleteControlProvider->GetListControl()->EnsureItemVisible(selected); } } } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTCOLORIZER.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace elements::text; /*********************************************************************** GuiTextBoxColorizerBase ***********************************************************************/ void GuiTextBoxColorizerBase::ColorizerThreadProc(void* argument) { GuiTextBoxColorizerBase* colorizer=(GuiTextBoxColorizerBase*)argument; while(!colorizer->isFinalizing) { vint lineIndex=-1; wchar_t* text=0; vuint32_t* colors=0; vint length=0; vint lexerState=-1; vint contextState=-1; SPIN_LOCK(*colorizer->elementModifyLock) { if(colorizer->colorizedLineCount>=colorizer->element->GetLines().GetCount()) { colorizer->isColorizerRunning=false; goto CANCEL_COLORIZING; } lineIndex=colorizer->colorizedLineCount++; TextLine& line=colorizer->element->GetLines().GetLine(lineIndex); length=line.dataLength; text=new wchar_t[length+2]; colors=new vuint32_t[length+2]; memcpy(text, line.text, sizeof(wchar_t)*length); text[length]=L'\r'; text[length+1]=L'\n'; lexerState=lineIndex==0?colorizer->GetLexerStartState():colorizer->element->GetLines().GetLine(lineIndex-1).lexerFinalState; contextState=lineIndex==0?colorizer->GetContextStartState():colorizer->element->GetLines().GetLine(lineIndex-1).contextFinalState; } colorizer->ColorizeLineWithCRLF(lineIndex, text, colors, length+2, lexerState, contextState); SPIN_LOCK(*colorizer->elementModifyLock) { if(lineIndexcolorizedLineCount && lineIndexelement->GetLines().GetCount()) { TextLine& line=colorizer->element->GetLines().GetLine(lineIndex); line.lexerFinalState=lexerState; line.contextFinalState=contextState; for(vint i=0;icolorizerRunningEvent.Leave(); } void GuiTextBoxColorizerBase::StartColorizer() { if(!isColorizerRunning) { isColorizerRunning=true; colorizerRunningEvent.Enter(); ThreadPoolLite::Queue(&GuiTextBoxColorizerBase::ColorizerThreadProc, this); } } void GuiTextBoxColorizerBase::StopColorizer(bool forever) { isFinalizing=true; colorizerRunningEvent.Enter(); colorizerRunningEvent.Leave(); colorizedLineCount=0; if(!forever) { isFinalizing=false; } } void GuiTextBoxColorizerBase::StopColorizerForever() { StopColorizer(true); } GuiTextBoxColorizerBase::GuiTextBoxColorizerBase() :element(0) ,elementModifyLock(0) ,colorizedLineCount(0) ,isColorizerRunning(false) ,isFinalizing(false) { } GuiTextBoxColorizerBase::~GuiTextBoxColorizerBase() { StopColorizerForever(); } void GuiTextBoxColorizerBase::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) { if(_element) { SPIN_LOCK(_elementModifyLock) { element=_element; elementModifyLock=&_elementModifyLock; StartColorizer(); } } } void GuiTextBoxColorizerBase::Detach() { if(element && elementModifyLock) { StopColorizer(false); SPIN_LOCK(*elementModifyLock) { element=0; elementModifyLock=0; } } } void GuiTextBoxColorizerBase::TextEditPreview(TextEditPreviewStruct& arguments) { } void GuiTextBoxColorizerBase::TextEditNotify(const TextEditNotifyStruct& arguments) { if(element && elementModifyLock) { SPIN_LOCK(*elementModifyLock) { vint line =arguments.originalStart.rowline) { colorizedLineCount=line; } StartColorizer(); } } } void GuiTextBoxColorizerBase::TextCaretChanged(const TextCaretChangedStruct& arguments) { } void GuiTextBoxColorizerBase::TextEditFinished(vuint editVersion) { } void GuiTextBoxColorizerBase::RestartColorizer() { if(element && elementModifyLock) { SPIN_LOCK(*elementModifyLock) { colorizedLineCount=0; StartColorizer(); } } } /*********************************************************************** GuiTextBoxRegexColorizer ***********************************************************************/ struct GuiTextBoxRegexColorizerProcData { GuiTextBoxRegexColorizer* colorizer; vint lineIndex; const wchar_t* text; vuint32_t* colors; vint contextState; }; void GuiTextBoxRegexColorizer::ColorizerProc(void* argument, vint start, vint length, vint token) { GuiTextBoxRegexColorizerProcData& data=*(GuiTextBoxRegexColorizerProcData*)argument; data.colorizer->ColorizeTokenContextSensitive(data.lineIndex, data.text, start, length, token, data.contextState); for(vint i=0;i& GuiTextBoxRegexColorizer::GetTokenRegexes() { return tokenRegexes; } collections::List& GuiTextBoxRegexColorizer::GetTokenColors() { return tokenColors; } collections::List& GuiTextBoxRegexColorizer::GetExtraTokenColors() { return extraTokenColors; } vint GuiTextBoxRegexColorizer::GetExtraTokenIndexStart() { if(lexer) { return tokenColors.Count(); } else { return -1; } } bool GuiTextBoxRegexColorizer::SetDefaultColor(elements::text::ColorEntry value) { if(lexer) { return false; } else { defaultColor=value; return true; } } vint GuiTextBoxRegexColorizer::AddToken(const WString& regex, elements::text::ColorEntry color) { if(lexer) { return -1; } else { tokenRegexes.Add(regex); tokenColors.Add(color); return tokenColors.Count()-1; } } vint GuiTextBoxRegexColorizer::AddExtraToken(elements::text::ColorEntry color) { if(lexer) { return -1; } else { extraTokenColors.Add(color); return extraTokenColors.Count()-1; } } void GuiTextBoxRegexColorizer::ClearTokens() { tokenRegexes.Clear(); tokenColors.Clear(); extraTokenColors.Clear(); lexer=0; } void GuiTextBoxRegexColorizer::Setup() { if(lexer || tokenRegexes.Count()==0) { colors.Resize(1); colors[0]=defaultColor; } else { lexer=new regex::RegexLexer(tokenRegexes); colors.Resize(1+tokenRegexes.Count()+extraTokenColors.Count()); colors[0]=defaultColor; for(vint i=0;iColorize()); } } void GuiTextBoxRegexColorizer::ColorizeTokenContextSensitive(vint lineIndex, const wchar_t* text, vint start, vint length, vint& token, vint& contextState) { } vint GuiTextBoxRegexColorizer::GetLexerStartState() { return lexer?colorizer->GetStartState():-1; } vint GuiTextBoxRegexColorizer::GetContextStartState() { return 0; } void GuiTextBoxRegexColorizer::ColorizeLineWithCRLF(vint lineIndex, const wchar_t* text, vuint32_t* colors, vint length, vint& lexerState, vint& contextState) { memset(colors, 0, sizeof(*colors)*length); if(lexer) { GuiTextBoxRegexColorizerProcData data; data.colorizer=this; data.lineIndex=lineIndex; data.text=text; data.colors=colors; data.contextState=contextState; colorizer->Reset(lexerState); colorizer->Colorize(text, length, &GuiTextBoxRegexColorizer::ColorizerProc, &data); lexerState=colorizer->GetCurrentState(); contextState=data.contextState; } else { lexerState=-1; contextState=-1; } } const GuiTextBoxRegexColorizer::ColorArray& GuiTextBoxRegexColorizer::GetColors() { return colors; } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTGENERALOPERATIONS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTUNDOREDO.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace elements::text; using namespace compositions; /*********************************************************************** GuiGeneralUndoRedoProcessor ***********************************************************************/ GuiGeneralUndoRedoProcessor::GuiGeneralUndoRedoProcessor() :firstFutureStep(0) ,savedStep(0) ,performingUndoRedo(false) { } GuiGeneralUndoRedoProcessor::~GuiGeneralUndoRedoProcessor() { } void GuiGeneralUndoRedoProcessor::PushStep(Ptr step) { if(!performingUndoRedo) { if(firstFutureStep0) { steps.RemoveRange(firstFutureStep, count); } steps.Add(step); firstFutureStep=steps.Count(); } } bool GuiGeneralUndoRedoProcessor::CanUndo() { return firstFutureStep>0; } bool GuiGeneralUndoRedoProcessor::CanRedo() { return steps.Count()>firstFutureStep; } void GuiGeneralUndoRedoProcessor::ClearUndoRedo() { if(!performingUndoRedo) { steps.Clear(); firstFutureStep=0; savedStep=-1; } } bool GuiGeneralUndoRedoProcessor::GetModified() { return firstFutureStep!=savedStep; } void GuiGeneralUndoRedoProcessor::NotifyModificationSaved() { if(!performingUndoRedo) { savedStep=firstFutureStep; } } bool GuiGeneralUndoRedoProcessor::Undo() { if(!CanUndo()) return false; performingUndoRedo=true; firstFutureStep--; steps[firstFutureStep]->Undo(); performingUndoRedo=false; return true; } bool GuiGeneralUndoRedoProcessor::Redo() { if(!CanRedo()) return false; performingUndoRedo=true; firstFutureStep++; steps[firstFutureStep-1]->Redo(); performingUndoRedo=false; return true; } /*********************************************************************** GuiTextBoxUndoRedoProcessor::EditStep ***********************************************************************/ void GuiTextBoxUndoRedoProcessor::EditStep::Undo() { GuiTextBoxCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); if(ci) { ci->Select(arguments.inputStart, arguments.inputEnd); ci->SetSelectionText(arguments.originalText); ci->Select(arguments.originalStart, arguments.originalEnd); } } void GuiTextBoxUndoRedoProcessor::EditStep::Redo() { GuiTextBoxCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); if(ci) { ci->Select(arguments.originalStart, arguments.originalEnd); ci->SetSelectionText(arguments.inputText); ci->Select(arguments.inputStart, arguments.inputEnd); } } /*********************************************************************** GuiTextBoxUndoRedoProcessor ***********************************************************************/ GuiTextBoxUndoRedoProcessor::GuiTextBoxUndoRedoProcessor() :ownerComposition(0) { } GuiTextBoxUndoRedoProcessor::~GuiTextBoxUndoRedoProcessor() { } void GuiTextBoxUndoRedoProcessor::Attach(elements::GuiColorizedTextElement* element, SpinLock& elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) { ownerComposition=_ownerComposition; } void GuiTextBoxUndoRedoProcessor::Detach() { ClearUndoRedo(); } void GuiTextBoxUndoRedoProcessor::TextEditPreview(TextEditPreviewStruct& arguments) { } void GuiTextBoxUndoRedoProcessor::TextEditNotify(const TextEditNotifyStruct& arguments) { Ptr step=new EditStep; step->processor=this; step->arguments=arguments; PushStep(step); } void GuiTextBoxUndoRedoProcessor::TextCaretChanged(const TextCaretChangedStruct& arguments) { } void GuiTextBoxUndoRedoProcessor::TextEditFinished(vuint editVersion) { } /*********************************************************************** GuiDocumentUndoRedoProcessor::ReplaceModelStep ***********************************************************************/ void GuiDocumentUndoRedoProcessor::ReplaceModelStep::Undo() { GuiDocumentCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); if(ci) { ci->EditRun(arguments.inputStart, arguments.inputEnd, arguments.originalModel); ci->SetCaret(arguments.originalStart, arguments.originalEnd); } } void GuiDocumentUndoRedoProcessor::ReplaceModelStep::Redo() { GuiDocumentCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); if(ci) { ci->EditRun(arguments.originalStart, arguments.originalEnd, arguments.inputModel); ci->SetCaret(arguments.inputStart, arguments.inputEnd); } } /*********************************************************************** GuiDocumentUndoRedoProcessor::RenameStyleStep ***********************************************************************/ void GuiDocumentUndoRedoProcessor::RenameStyleStep::Undo() { GuiDocumentCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); if(ci) { ci->RenameStyle(arguments.newStyleName, arguments.oldStyleName); } } void GuiDocumentUndoRedoProcessor::RenameStyleStep::Redo() { GuiDocumentCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); if(ci) { ci->RenameStyle(arguments.oldStyleName, arguments.newStyleName); } } /*********************************************************************** GuiDocumentUndoRedoProcessor::SetAlignmentStep ***********************************************************************/ void GuiDocumentUndoRedoProcessor::SetAlignmentStep::Undo() { GuiDocumentCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); if(ci) { ci->SetParagraphAlignment(TextPos(arguments->start, 0), TextPos(arguments->end, 0), arguments->originalAlignments); } } void GuiDocumentUndoRedoProcessor::SetAlignmentStep::Redo() { GuiDocumentCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); if(ci) { ci->SetParagraphAlignment(TextPos(arguments->start, 0), TextPos(arguments->end, 0), arguments->inputAlignments); } } /*********************************************************************** GuiDocumentUndoRedoProcessor ***********************************************************************/ GuiDocumentUndoRedoProcessor::GuiDocumentUndoRedoProcessor() :element(0) ,ownerComposition(0) { } GuiDocumentUndoRedoProcessor::~GuiDocumentUndoRedoProcessor() { } void GuiDocumentUndoRedoProcessor::Setup(elements::GuiDocumentElement* _element, compositions::GuiGraphicsComposition* _ownerComposition) { element=_element; ownerComposition=_ownerComposition; } void GuiDocumentUndoRedoProcessor::OnReplaceModel(const ReplaceModelStruct& arguments) { Ptr step=new ReplaceModelStep; step->processor=this; step->arguments=arguments; PushStep(step); } void GuiDocumentUndoRedoProcessor::OnRenameStyle(const RenameStyleStruct& arguments) { Ptr step=new RenameStyleStep; step->processor=this; step->arguments=arguments; PushStep(step); } void GuiDocumentUndoRedoProcessor::OnSetAlignment(Ptr arguments) { Ptr step=new SetAlignmentStep; step->processor=this; step->arguments=arguments; PushStep(step); } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGEAUTOCOMPLETE.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace regex; using namespace parsing; using namespace parsing::tabling; using namespace collections; /*********************************************************************** GuiGrammarAutoComplete ***********************************************************************/ void GuiGrammarAutoComplete::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) { GuiTextBoxAutoCompleteBase::Attach(_element, _elementModifyLock, _ownerComposition, editVersion); RepeatingParsingExecutor::CallbackBase::Attach(_element, _elementModifyLock, _ownerComposition, editVersion); } void GuiGrammarAutoComplete::Detach() { GuiTextBoxAutoCompleteBase::Detach(); RepeatingParsingExecutor::CallbackBase::Detach(); if(element && elementModifyLock) { EnsureAutoCompleteFinished(); } } void GuiGrammarAutoComplete::TextEditPreview(TextEditPreviewStruct& arguments) { GuiTextBoxAutoCompleteBase::TextEditPreview(arguments); RepeatingParsingExecutor::CallbackBase::TextEditPreview(arguments); if(element && elementModifyLock) { if(IsListOpening() && arguments.keyInput && arguments.originalText==L"" && arguments.inputText!=L"") { WString selectedItem=GetSelectedListItem(); if(selectedItem!=L"") { TextPos begin=GetListStartPosition(); TextPos end=arguments.originalStart; WString editingText=element->GetLines().GetText(begin, end); editingText+=arguments.inputText; if(grammarParser->GetTable()->GetLexer().Walk().IsClosedToken(editingText)) { arguments.originalStart=begin; arguments.inputText=selectedItem+arguments.inputText; CloseList(); } } } } } void GuiGrammarAutoComplete::TextEditNotify(const TextEditNotifyStruct& arguments) { GuiTextBoxAutoCompleteBase::TextEditNotify(arguments); RepeatingParsingExecutor::CallbackBase::TextEditNotify(arguments); if(element && elementModifyLock) { editing=true; SPIN_LOCK(editTraceLock) { editTrace.Add(arguments); } } } void GuiGrammarAutoComplete::TextCaretChanged(const TextCaretChangedStruct& arguments) { GuiTextBoxAutoCompleteBase::TextCaretChanged(arguments); RepeatingParsingExecutor::CallbackBase::TextCaretChanged(arguments); if(element && elementModifyLock) { SPIN_LOCK(editTraceLock) { // queue a fake TextEditNotifyStruct // a fake struct can be detected by (trace.originalText==L"" && trace.inputText==L"") TextEditNotifyStruct trace; trace.editVersion=arguments.editVersion; trace.originalStart=arguments.oldBegin; trace.originalEnd=arguments.oldEnd; trace.inputStart=arguments.newBegin; trace.inputEnd=arguments.newEnd; // ensure trace.originalStart<=trace.originalEnd if(trace.originalStart>trace.originalEnd) { TextPos temp=trace.originalStart; trace.originalStart=trace.originalEnd; trace.originalEnd=temp; } // ensure trace.inputStart<=trace.inputEnd if(trace.inputStart>trace.inputEnd) { TextPos temp=trace.inputStart; trace.inputStart=trace.inputEnd; trace.inputEnd=temp; } editTrace.Add(trace); } SPIN_LOCK(contextLock) { if(context.input.node) { if(editing) { // if the current caret changing is caused by editing // submit a task with valid editVersion and invalid node and code RepeatingParsingOutput input; input.editVersion=context.input.editVersion; SubmitTask(input); } else if(context.input.editVersion == arguments.editVersion) { // if the current caret changing is not caused by editing // submit a task with the previous input SubmitTask(context.input); } } } } } void GuiGrammarAutoComplete::TextEditFinished(vuint editVersion) { GuiTextBoxAutoCompleteBase::TextEditFinished(editVersion); RepeatingParsingExecutor::CallbackBase::TextEditFinished(editVersion); if(element && elementModifyLock) { editing=false; } } void GuiGrammarAutoComplete::OnParsingFinishedAsync(const RepeatingParsingOutput& arguments) { if(element && elementModifyLock) { GetApplication()->InvokeInMainThread([=]() { // submit a task if the RepeatingParsingExecutor notices a new parsing result SubmitTask(arguments); }); } } void GuiGrammarAutoComplete::CollectLeftRecursiveRules() { leftRecursiveRules.Clear(); Ptr parser=parsingExecutor->GetParser(); Ptr table=parser->GetTable(); vint stateCount=table->GetStateCount(); vint tokenCount=table->GetTokenCount(); for(vint i=0;i bag=table->GetTransitionBag(i, j); if(bag) { FOREACH(Ptr, item, bag->transitionItems) { FOREACH(ParsingTable::Instruction, ins, item->instructions) { if(ins.instructionType==ParsingTable::Instruction::LeftRecursiveReduce) { if(!leftRecursiveRules.Contains(ins.creatorRule)) { leftRecursiveRules.Add(ins.creatorRule); } } } } } } } } vint GuiGrammarAutoComplete::UnsafeGetEditTraceIndex(vuint editVersion) { // get the index of the latest TextEditNotifyStruct of a specified edit version // this function should be called inside SPIN_LOCK(editTraceLock) // perform a binary search vint start = 0; vint end = editTrace.Count() - 1; while (start <= end) { vint middle = (start + end) / 2; TextEditNotifyStruct& trace = editTrace[middle]; if (editVersiontrace.editVersion) { start = middle + 1; } else { // if multiple TextEditNotifyStruct is found, choose the latest one while (middle < editTrace.Count() - 1) { if (editTrace[middle + 1].editVersion == editTrace[middle].editVersion) { middle++; } else { break; } } return middle; } } return -1; } TextPos GuiGrammarAutoComplete::ChooseCorrectTextPos(TextPos pos, const regex::RegexTokens& tokens) { Ptr table=grammarParser->GetTable(); RegexToken lastToken; lastToken.reading=0; FOREACH(RegexToken, token, tokens) { // we treat "class| Name" as editing the first token if(TextPos(token.rowEnd, token.columnEnd+1)>=pos) { if(table->GetTableTokenIndex(token.token)!=-1 && lastToken.reading) { pos=TextPos(lastToken.rowStart, lastToken.columnStart); } break; } lastToken=token; } return pos; } void GuiGrammarAutoComplete::ExecuteRefresh(AutoCompleteContext& newContext) { // process the input of a task is submitted not by text editing // find the text selection by the edit version of the input TextPos startPos, endPos; { SPIN_LOCK(editTraceLock) { vint traceIndex = UnsafeGetEditTraceIndex(newContext.input.editVersion); if (traceIndex == -1) return; TextEditNotifyStruct& trace = editTrace[traceIndex]; startPos = trace.inputStart; endPos = trace.inputEnd; } const RegexLexer& lexer = grammarParser->GetTable()->GetLexer(); RegexTokens tokens = lexer.Parse(newContext.input.code); startPos = ChooseCorrectTextPos(startPos, tokens); } // locate the deepest node using the text selection ParsingTextPos start(startPos.row, startPos.column); ParsingTextPos end(endPos.row, endPos.column); ParsingTextRange range(start, end); ParsingTreeNode* found = newContext.input.node->FindDeepestNode(range); ParsingTreeObject* selectedNode = 0; // if the location failed, choose the root node if (!found || startPos == TextPos(0, 0)) { found = newContext.input.node.Obj(); } if (!selectedNode) { // from the deepest node, traverse towards the root node // find the deepest node whose created rule is a left recursive rule and whose parent is not ParsingTreeObject* lrec = 0; ParsingTreeNode* current = found; while (current) { ParsingTreeObject* obj = dynamic_cast(current); if (obj) { FOREACH(WString, rule, obj->GetCreatorRules()) { if (leftRecursiveRules.Contains(rule)) { lrec = obj; break; } } if (obj && lrec && lrec != obj) { selectedNode = lrec; break; } } current = current->GetParent(); } } if (!selectedNode) { // if there is no left recursive rule that creates the deepest node and all indirect parents // choose the deepest ParsingTreeObject ParsingTreeNode* current = found; while (current) { ParsingTreeObject* obj = dynamic_cast(current); if (obj) { selectedNode = obj; break; } current = current->GetParent(); } } if (selectedNode) { // get the code range of the selected node start = selectedNode->GetCodeRange().start; end = selectedNode->GetCodeRange().end; // get all properties from the selected node newContext.rule = selectedNode->GetCreatorRules()[selectedNode->GetCreatorRules().Count() - 1]; newContext.originalRange = selectedNode->GetCodeRange(); newContext.originalNode = dynamic_cast(selectedNode); newContext.modifiedNode = newContext.originalNode; newContext.modifiedEditVersion = newContext.input.editVersion; // get the corresponding code of the selected node if (start.index >= 0 && end.index >= 0) { newContext.modifiedCode = newContext.input.code.Sub(start.index, end.index - start.index + 1).Buffer(); } } } bool GuiGrammarAutoComplete::NormalizeTextPos(AutoCompleteContext& newContext, elements::text::TextLines& lines, TextPos& pos) { // get the start position TextPos start(newContext.originalRange.start.row, newContext.originalRange.start.column); // get the end position of the end of lines TextPos end = lines.GetCount() <= 1 ? TextPos(start.row, start.column + lines.GetLine(0).dataLength) : TextPos(start.row + lines.GetCount() - 1, lines.GetLine(lines.GetCount() - 1).dataLength) ; if (start <= pos && pos <= end) { // if the pos is inside the range // normalize the pos to a new coordinate that the beginning position of lines is (row=0, column=0) pos.row -= start.row; if (pos.row == 0) { pos.column -= start.column; } return true; } else { return false; } } void GuiGrammarAutoComplete::ExecuteEdit(AutoCompleteContext& newContext) { // process the input of a task that is submitted by text editing // this function make an approximiation to the context if the RepeatingParsingExecutor is not fast enough // copy all TextEditNotifyStruct that is caused by a text editing before (and including) the edit version of the input List usedTrace; { SPIN_LOCK(editTraceLock) { CopyFrom( usedTrace, From(editTrace) .Where([&newContext](const TextEditNotifyStruct& value) { return (value.originalText != L"" || value.inputText != L"") && value.editVersion > newContext.modifiedEditVersion; }) ); } } // apply all modification to get the new modifiedCode bool failed = false; if (usedTrace.Count() > 0) { if (usedTrace[0].editVersion != newContext.modifiedEditVersion + 1) { // failed if any TextEditNotifyStruct is missing failed = true; } else { // initialize a TextLines with the latest modifiedCode text::TextLines lines; lines.SetText(newContext.modifiedCode); FOREACH(TextEditNotifyStruct, trace, usedTrace) { // apply a modification to lines TextPos start = trace.originalStart; TextPos end = trace.originalEnd; // only if the modification is meaningful if (NormalizeTextPos(newContext, lines, start) && NormalizeTextPos(newContext, lines, end)) { lines.Modify(start, end, trace.inputText); } else { // otherwise, failed failed = true; break; } } if (!failed) { newContext.modifiedCode = lines.GetText(); } } } if (failed) { // clear originalNode to notify that the current context goes wrong newContext.originalNode = 0; } if (usedTrace.Count() > 0) { // update the edit version newContext.modifiedEditVersion = usedTrace[usedTrace.Count() - 1].editVersion; } } void GuiGrammarAutoComplete::DeleteFutures(collections::List& futures) { // delete all futures and clear the list FOREACH(ParsingState::Future*, future, futures) { delete future; } futures.Clear(); } regex::RegexToken* GuiGrammarAutoComplete::TraverseTransitions( parsing::tabling::ParsingState& state, parsing::tabling::ParsingTransitionCollector& transitionCollector, TextPos stopPosition, collections::List& nonRecoveryFutures, collections::List& recoveryFutures ) { const List& transitions = transitionCollector.GetTransitions(); for (vint index = 0; index < transitions.Count(); index++) { const ParsingState::TransitionResult& transition = transitions[index]; switch (transition.transitionType) { case ParsingState::TransitionResult::AmbiguityBegin: break; case ParsingState::TransitionResult::AmbiguityBranch: // ambiguity branches are not nested // tokens in different braches are the same // so we only need to run one branch, and skip the others index = transitionCollector.GetAmbiguityEndFromBegin(transitionCollector.GetAmbiguityBeginFromBranch(index)); break; case ParsingState::TransitionResult::AmbiguityEnd: break; case ParsingState::TransitionResult::ExecuteInstructions: { // test does the token reach the stop position if (transition.token) { // we treat "A|B" as editing A if token A is endless, otherwise treated as editing B TextPos tokenEnd(transition.token->rowEnd, transition.token->columnEnd + 1); // if the caret is not at the end of the token if (tokenEnd > stopPosition) { // stop the traversing and return the editing token return transition.token; } else if (tokenEnd == stopPosition) { // if the caret is at the end of the token, and it is a closed token // e.g. identifier is not a closed token, string is a closed token if (!grammarParser->GetTable()->GetLexer().Walk().IsClosedToken(transition.token->reading, transition.token->length)) { // stop the traversing and return the editing token return transition.token; } } } // traverse the PDA using the token specified in the current transition vint tableTokenIndex = transition.tableTokenIndex; List possibilities; if (recoveryFutures.Count() > 0) { FOREACH(ParsingState::Future*, future, recoveryFutures) { state.Explore(tableTokenIndex, future, possibilities); } } else { FOREACH(ParsingState::Future*, future, nonRecoveryFutures) { state.Explore(tableTokenIndex, future, possibilities); } } // delete duplicated futures List selectedPossibilities; for (vint i = 0; i < possibilities.Count(); i++) { ParsingState::Future* candidateFuture = possibilities[i]; bool duplicated = false; FOREACH(ParsingState::Future*, future, selectedPossibilities) { if ( candidateFuture->currentState == future->currentState && candidateFuture->reduceStateCount == future->reduceStateCount && candidateFuture->shiftStates.Count() == future->shiftStates.Count() ) { bool same = true; for (vint j = 0; j < future->shiftStates.Count(); j++) { if (candidateFuture->shiftStates[i] != future->shiftStates[i]) { same = false; break; } } if ((duplicated = same)) { break; } } } if (duplicated) { delete candidateFuture; } else { selectedPossibilities.Add(candidateFuture); } } // step forward if (transition.token || transition.tableTokenIndex == ParsingTable::TokenBegin) { DeleteFutures(nonRecoveryFutures); DeleteFutures(recoveryFutures); CopyFrom(nonRecoveryFutures, selectedPossibilities); } else { DeleteFutures(recoveryFutures); CopyFrom(recoveryFutures, selectedPossibilities); } } break; default:; } } return 0; } regex::RegexToken* GuiGrammarAutoComplete::SearchValidInputToken( parsing::tabling::ParsingState& state, parsing::tabling::ParsingTransitionCollector& transitionCollector, TextPos stopPosition, AutoCompleteContext& newContext, collections::SortedList& tableTokenIndices ) { // initialize the PDA state state.Reset(newContext.rule); List nonRecoveryFutures, recoveryFutures; nonRecoveryFutures.Add(state.ExploreCreateRootFuture()); // traverse the PDA until it reach the stop position // nonRecoveryFutures store the state when the last token (existing) is reached // recoveryFutures store the state when the last token (inserted by error recovery) is reached RegexToken* token = TraverseTransitions(state, transitionCollector, stopPosition, nonRecoveryFutures, recoveryFutures); // explore all possibilities from the last token before the stop position List possibilities; for (vint i = 0; i < nonRecoveryFutures.Count(); i++) { state.Explore(ParsingTable::NormalReduce, nonRecoveryFutures[i], nonRecoveryFutures); state.Explore(ParsingTable::LeftRecursiveReduce, nonRecoveryFutures[i], nonRecoveryFutures); } FOREACH(ParsingState::Future*, future, nonRecoveryFutures) { vint count = state.GetTable()->GetTokenCount(); for (vint i = ParsingTable::UserTokenStart; i < count; i++) { state.Explore(i, future, possibilities); } } // get all possible tokens that marked using @AutoCompleteCandidate FOREACH(ParsingState::Future*, future, possibilities) { if (!tableTokenIndices.Contains(future->selectedToken)) { tableTokenIndices.Add(future->selectedToken); } } // release all data DeleteFutures(possibilities); DeleteFutures(nonRecoveryFutures); DeleteFutures(recoveryFutures); // return the editing token return token; } TextPos GuiGrammarAutoComplete::GlobalTextPosToModifiedTextPos(AutoCompleteContext& newContext, TextPos pos) { pos.row-=newContext.originalRange.start.row; if(pos.row==0) { pos.column-=newContext.originalRange.start.column; } return pos; } TextPos GuiGrammarAutoComplete::ModifiedTextPosToGlobalTextPos(AutoCompleteContext& newContext, TextPos pos) { if(pos.row==0) { pos.column+=newContext.originalRange.start.column; } pos.row+=newContext.originalRange.start.row; return pos; } void GuiGrammarAutoComplete::ExecuteCalculateList(AutoCompleteContext& newContext) { // calcuate the content of the auto complete list // it is sad that, because the parser's algorithm is too complex // we need to reparse and track the internal state of the PDA(push-down automaton) here. // initialize the PDA ParsingState state(newContext.modifiedCode, grammarParser->GetTable()); state.Reset(newContext.rule); // prepare to get all transitions ParsingTransitionCollector collector; List> errors; // reparse and get all transitions during parsing if (grammarParser->Parse(state, collector, errors)) { // if modifiedNode is not prepared (the task is submitted because of text editing) // use the transition to build the syntax tree if (!newContext.modifiedNode) { ParsingTreeBuilder builder; builder.Reset(); bool succeeded = true; FOREACH(ParsingState::TransitionResult, transition, collector.GetTransitions()) { if (!(succeeded = builder.Run(transition))) { break; } } if (succeeded) { Ptr parsedNode = builder.GetNode(); newContext.modifiedNode = parsedNode.Cast(); newContext.modifiedNode->InitializeQueryCache(); } } if (newContext.modifiedNode) { // get the latest text editing trace TextEditNotifyStruct trace; SPIN_LOCK(editTraceLock) { vint index = UnsafeGetEditTraceIndex(newContext.modifiedEditVersion); if (index == -1) { return; } else { trace = editTrace[index]; } } // calculate the stop position for PDA traversing TextPos stopPosition = GlobalTextPosToModifiedTextPos(newContext, trace.inputStart); // find all possible token before the current caret using the PDA Ptr autoComplete = new AutoCompleteData; SortedList tableTokenIndices; RegexToken* editingToken = SearchValidInputToken(state, collector, stopPosition, newContext, tableTokenIndices); // collect all auto complete types { // collect all keywords that can be put into the auto complete list FOREACH(vint, token, tableTokenIndices) { vint regexToken = token - ParsingTable::UserTokenStart; if (regexToken >= 0) { autoComplete->candidates.Add(regexToken); if (parsingExecutor->GetTokenMetaData(regexToken).isCandidate) { autoComplete->shownCandidates.Add(regexToken); } } } // calculate the arranged stopPosition if (editingToken) { TextPos tokenPos(editingToken->rowStart, editingToken->columnStart); if (tokenPos < stopPosition) { stopPosition = tokenPos; } } // calculate the start/end position for PDA traversing TextPos startPos, endPos; { startPos = ModifiedTextPosToGlobalTextPos(newContext, stopPosition); autoComplete->startPosition = startPos; endPos = trace.inputEnd; if (newContext.modifiedNode != newContext.originalNode) { startPos = GlobalTextPosToModifiedTextPos(newContext, startPos); endPos = GlobalTextPosToModifiedTextPos(newContext, endPos); } if (startPos0) { endPos.column--; } } // calculate the auto complete type if (editingToken && parsingExecutor->GetTokenMetaData(editingToken->token).hasAutoComplete) { ParsingTextRange range(ParsingTextPos(startPos.row, startPos.column), ParsingTextPos(endPos.row, endPos.column)); AutoCompleteData::RetriveContext(*autoComplete.Obj(), range, newContext.modifiedNode.Obj(), parsingExecutor.Obj()); } } newContext.autoComplete = autoComplete; } } } void GuiGrammarAutoComplete::Execute(const RepeatingParsingOutput& input) { SPIN_LOCK(contextLock) { if(input.editVersionInvokeInMainThread([=]() { PostList(newContext, byGlobalCorrection); }); } } void GuiGrammarAutoComplete::PostList(const AutoCompleteContext& newContext, bool byGlobalCorrection) { bool openList = true; // true: make the list visible bool keepListState = false; // true: don't change the list visibility Ptr autoComplete = newContext.autoComplete; // if failed to get the auto complete list, close if (!autoComplete) { openList = false; } if (openList) { if (autoComplete->shownCandidates.Count() + autoComplete->candidateItems.Count() == 0) { openList = false; } } TextPos startPosition, endPosition; WString editingText; if (openList) { SPIN_LOCK(editTraceLock) { // if the edit version is invalid, cancel vint traceIndex = UnsafeGetEditTraceIndex(newContext.modifiedEditVersion); if (traceIndex == -1) { return; } // an edit version has two trace at most, for text change and caret change, here we peak the text change if (traceIndex > 0 && editTrace[traceIndex - 1].editVersion == context.modifiedEditVersion) { traceIndex--; } // if the edit version is not created by keyboard input, close if (traceIndex >= 0) { TextEditNotifyStruct& trace = editTrace[traceIndex]; if (!trace.keyInput) { openList = false; } } // scan all traces from the calculation's edit version until now if (openList) { keepListState = true; startPosition = autoComplete->startPosition; endPosition = editTrace[editTrace.Count() - 1].inputEnd; for (vint i = traceIndex; i < editTrace.Count(); i++) { TextEditNotifyStruct& trace = editTrace[i]; // if there are no text change trace until now, don't change the list if (trace.originalText != L"" || trace.inputText != L"") { keepListState = false; } // if the edit position goes before the start position of the auto complete, refresh if (trace.inputEnd <= startPosition) { openList = false; break; } } } if (traceIndex > 0) { editTrace.RemoveRange(0, traceIndex); } } } // if there is a global correction send to the UI thread but the list is not opening, cancel if (byGlobalCorrection && !IsListOpening()) { return; } // if the input text from the start position to the current position crosses a token, close if (openList && element) { editingText = element->GetLines().GetText(startPosition, endPosition); if (grammarParser->GetTable()->GetLexer().Walk().IsClosedToken(editingText)) { openList = false; } } // calculate the content of the list if (autoComplete && ((!keepListState && openList) || IsListOpening())) { SortedList itemKeys; List itemValues; // copy all candidate keywords FOREACH(vint, token, autoComplete->shownCandidates) { WString literal = parsingExecutor->GetTokenMetaData(token).unescapedRegexText; if (literal != L"" && !itemKeys.Contains(literal)) { ParsingCandidateItem item; item.name = literal; item.semanticId = -1; itemValues.Insert(itemKeys.Add(literal), item); } } // copy all candidate symbols if (autoComplete->acceptableSemanticIds) { FOREACH(ParsingCandidateItem, item, autoComplete->candidateItems) { if (autoComplete->acceptableSemanticIds->Contains(item.semanticId)) { // add all acceptable display of a symbol // because a symbol can has multiple representation in different places if (item.name != L"" && !itemKeys.Contains(item.name)) { itemValues.Insert(itemKeys.Add(item.name), item); } } } } // fill the list List candidateItems; for (vint i = 0; i < itemValues.Count(); i++) { auto& item = itemValues[i]; if (item.tag.IsNull()) { if (auto analyzer = parsingExecutor->GetAnalyzer()) { item.tag = analyzer->CreateTagForCandidateItem(item); } } GuiTextBoxAutoCompleteBase::AutoCompleteItem candidateItem; candidateItem.text = item.name; candidateItem.tag = item.tag; candidateItems.Add(candidateItem); } SetListContent(candidateItems); } // set the list state if (!keepListState) { if (openList) { OpenList(startPosition); } else { CloseList(); } } if (IsListOpening()) { HighlightList(editingText); } } void GuiGrammarAutoComplete::Initialize() { grammarParser=CreateAutoRecoverParser(parsingExecutor->GetParser()->GetTable()); CollectLeftRecursiveRules(); parsingExecutor->AttachCallback(this); } void GuiGrammarAutoComplete::OnContextFinishedAsync(AutoCompleteContext& context) { if (auto analyzer = parsingExecutor->GetAnalyzer()) { if (context.autoComplete && context.autoComplete->acceptableSemanticIds) { analyzer->GetCandidateItemsAsync(*context.autoComplete.Obj(), context, context.autoComplete->candidateItems); } } } void GuiGrammarAutoComplete::EnsureAutoCompleteFinished() { parsingExecutor->EnsureTaskFinished(); SPIN_LOCK(contextLock) { context = AutoCompleteContext(); } } GuiGrammarAutoComplete::GuiGrammarAutoComplete(Ptr _parsingExecutor) :RepeatingParsingExecutor::CallbackBase(_parsingExecutor) ,editing(false) { Initialize(); } GuiGrammarAutoComplete::GuiGrammarAutoComplete(Ptr _grammarParser, const WString& _grammarRule) :RepeatingParsingExecutor::CallbackBase(new RepeatingParsingExecutor(_grammarParser, _grammarRule)) ,editing(false) { Initialize(); } GuiGrammarAutoComplete::~GuiGrammarAutoComplete() { EnsureAutoCompleteFinished(); parsingExecutor->DetachCallback(this); } Ptr GuiGrammarAutoComplete::GetParsingExecutor() { return parsingExecutor; } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGECOLORIZER.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace elements; using namespace parsing; using namespace parsing::tabling; using namespace collections; using namespace theme; /*********************************************************************** GuiGrammarColorizer ***********************************************************************/ void GuiGrammarColorizer::OnParsingFinishedAsync(const RepeatingParsingOutput& output) { SPIN_LOCK(contextLock) { context=output; OnContextFinishedAsync(context); } RestartColorizer(); } void GuiGrammarColorizer::OnContextFinishedAsync(const RepeatingParsingOutput& context) { } void GuiGrammarColorizer::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) { GuiTextBoxRegexColorizer::Attach(_element, _elementModifyLock, _ownerComposition, editVersion); RepeatingParsingExecutor::CallbackBase::Attach(_element, _elementModifyLock, _ownerComposition, editVersion); } void GuiGrammarColorizer::Detach() { GuiTextBoxRegexColorizer::Detach(); RepeatingParsingExecutor::CallbackBase::Detach(); if(element && elementModifyLock) { parsingExecutor->EnsureTaskFinished(); StopColorizer(false); } } void GuiGrammarColorizer::TextEditPreview(TextEditPreviewStruct& arguments) { GuiTextBoxRegexColorizer::TextEditPreview(arguments); RepeatingParsingExecutor::CallbackBase::TextEditPreview(arguments); } void GuiGrammarColorizer::TextEditNotify(const TextEditNotifyStruct& arguments) { GuiTextBoxRegexColorizer::TextEditNotify(arguments); RepeatingParsingExecutor::CallbackBase::TextEditNotify(arguments); } void GuiGrammarColorizer::TextCaretChanged(const TextCaretChangedStruct& arguments) { GuiTextBoxRegexColorizer::TextCaretChanged(arguments); RepeatingParsingExecutor::CallbackBase::TextCaretChanged(arguments); } void GuiGrammarColorizer::TextEditFinished(vuint editVersion) { GuiTextBoxRegexColorizer::TextEditFinished(editVersion); RepeatingParsingExecutor::CallbackBase::TextEditFinished(editVersion); } void GuiGrammarColorizer::OnSemanticColorize(SemanticColorizeContext& context, const RepeatingParsingOutput& input) { if (auto analyzer = parsingExecutor->GetAnalyzer()) { auto semanticId = analyzer->GetSemanticIdForTokenAsync(context, input); if(semanticId!=-1) { context.semanticId=semanticId; } } } void GuiGrammarColorizer::EnsureColorizerFinished() { parsingExecutor->EnsureTaskFinished(); StopColorizerForever(); SPIN_LOCK(contextLock) { context=RepeatingParsingOutput(); } } GuiGrammarColorizer::GuiGrammarColorizer(Ptr _parsingExecutor) :RepeatingParsingExecutor::CallbackBase(_parsingExecutor) { parsingExecutor->AttachCallback(this); BeginSetColors(); } GuiGrammarColorizer::GuiGrammarColorizer(Ptr _grammarParser, const WString& _grammarRule) :RepeatingParsingExecutor::CallbackBase(new RepeatingParsingExecutor(_grammarParser, _grammarRule)) { parsingExecutor->AttachCallback(this); BeginSetColors(); } GuiGrammarColorizer::~GuiGrammarColorizer() { EnsureColorizerFinished(); parsingExecutor->DetachCallback(this); } void GuiGrammarColorizer::BeginSetColors() { ClearTokens(); colorSettings.Clear(); text::ColorEntry entry=GetCurrentTheme()->GetDefaultTextBoxColorEntry(); SetDefaultColor(entry); colorSettings.Add(L"Default", entry); } const collections::SortedList& GuiGrammarColorizer::GetColorNames() { return colorSettings.Keys(); } GuiGrammarColorizer::ColorEntry GuiGrammarColorizer::GetColor(const WString& name) { vint index=colorSettings.Keys().IndexOf(name); return index==-1?GetDefaultColor():colorSettings.Values().Get(index); } void GuiGrammarColorizer::SetColor(const WString& name, const ColorEntry& entry) { colorSettings.Set(name, entry); } void GuiGrammarColorizer::SetColor(const WString& name, const Color& color) { text::ColorEntry entry=GetDefaultColor(); entry.normal.text=color; SetColor(name, entry); } void GuiGrammarColorizer::EndSetColors() { SortedList tokenColors; Ptr table=parsingExecutor->GetParser()->GetTable(); semanticColorMap.Clear(); vint tokenCount=table->GetTokenCount(); for(vint token=ParsingTable::UserTokenStart;tokenGetTokenInfo(token); const RepeatingParsingExecutor::TokenMetaData& md=parsingExecutor->GetTokenMetaData(token-ParsingTable::UserTokenStart); if(md.defaultColorIndex==-1) { AddToken(tokenInfo.regex, GetDefaultColor()); } else { WString name=parsingExecutor->GetSemanticName(md.defaultColorIndex); vint color=AddToken(tokenInfo.regex, GetColor(name)); semanticColorMap.Set(md.defaultColorIndex, color); tokenColors.Add(name); } } FOREACH_INDEXER(WString, color, index, colorSettings.Keys()) { if(!tokenColors.Contains(color)) { vint semanticId=parsingExecutor->GetSemanticId(color); if(semanticId!=-1) { vint tokenId=AddExtraToken(colorSettings.Values().Get(index)); vint color=tokenId+tokenCount-ParsingTable::UserTokenStart; semanticColorMap.Set(semanticId, color); } } } Setup(); } void GuiGrammarColorizer::ColorizeTokenContextSensitive(vint lineIndex, const wchar_t* text, vint start, vint length, vint& token, vint& contextState) { SPIN_LOCK(contextLock) { ParsingTreeObject* node=context.node.Obj(); if(node && token!=-1 && parsingExecutor->GetTokenMetaData(token).hasContextColor) { ParsingTextPos pos(lineIndex, start); SemanticColorizeContext scContext; if(SemanticColorizeContext::RetriveContext(scContext, pos, node, parsingExecutor.Obj())) { const RepeatingParsingExecutor::FieldMetaData& md=parsingExecutor->GetFieldMetaData(scContext.type, scContext.field); vint semantic=md.colorIndex; scContext.semanticId=-1; if(scContext.acceptableSemanticIds) { OnSemanticColorize(scContext, context); if(md.semantics->Contains(scContext.semanticId)) { semantic=scContext.semanticId; } } if(semantic!=-1) { vint index=semanticColorMap.Keys().IndexOf(semantic); if(index!=-1) { token=semanticColorMap.Values()[index]; } } } } } } Ptr GuiGrammarColorizer::GetParsingExecutor() { return parsingExecutor; } } } } /*********************************************************************** CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGEOPERATIONS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace parsing; using namespace parsing::tabling; using namespace regex_internal; /*********************************************************************** ParsingContext ***********************************************************************/ bool ParsingTokenContext::RetriveContext(ParsingTokenContext& output, parsing::ParsingTreeNode* foundNode, RepeatingParsingExecutor* executor) { ParsingTreeToken* foundToken=dynamic_cast(foundNode); if(!foundToken) return false; ParsingTreeObject* tokenParent=dynamic_cast(foundNode->GetParent()); if(!tokenParent) return false; vint index=tokenParent->GetMembers().Values().IndexOf(foundNode); if(index==-1) return false; WString type=tokenParent->GetType(); WString field=tokenParent->GetMembers().Keys().Get(index); const RepeatingParsingExecutor::FieldMetaData& md=executor->GetFieldMetaData(type, field); output.foundToken=foundToken; output.tokenParent=tokenParent; output.type=type; output.field=field; output.acceptableSemanticIds=md.semantics; return true; } bool ParsingTokenContext::RetriveContext(ParsingTokenContext& output, parsing::ParsingTextPos pos, parsing::ParsingTreeObject* rootNode, RepeatingParsingExecutor* executor) { ParsingTreeNode* foundNode=rootNode->FindDeepestNode(pos); if(!foundNode) return false; return RetriveContext(output, foundNode, executor); } bool ParsingTokenContext::RetriveContext(ParsingTokenContext& output, parsing::ParsingTextRange range, ParsingTreeObject* rootNode, RepeatingParsingExecutor* executor) { ParsingTreeNode* foundNode=rootNode->FindDeepestNode(range); if(!foundNode) return false; return RetriveContext(output, foundNode, executor); } /*********************************************************************** RepeatingParsingExecutor::IParsingAnalyzer ***********************************************************************/ parsing::ParsingTreeNode* RepeatingParsingExecutor::IParsingAnalyzer::ToParent(parsing::ParsingTreeNode* node, const RepeatingPartialParsingOutput* output) { if (!output || !output->modifiedNode) return node; return node == output->modifiedNode.Obj() ? output->originalNode.Obj() : node; } parsing::ParsingTreeObject* RepeatingParsingExecutor::IParsingAnalyzer::ToChild(parsing::ParsingTreeObject* node, const RepeatingPartialParsingOutput* output) { if (!output || !output->modifiedNode) return node; return node == output->originalNode.Obj() ? output->modifiedNode.Obj() : node; } Ptr RepeatingParsingExecutor::IParsingAnalyzer::ToChild(Ptr node, const RepeatingPartialParsingOutput* output) { if (!output) return node; return node == output->originalNode ? output->modifiedNode.Cast() : node; } parsing::ParsingTreeNode* RepeatingParsingExecutor::IParsingAnalyzer::GetParent(parsing::ParsingTreeNode* node, const RepeatingPartialParsingOutput* output) { return ToParent(node, output)->GetParent(); } Ptr RepeatingParsingExecutor::IParsingAnalyzer::GetMember(parsing::ParsingTreeObject* node, const WString& name, const RepeatingPartialParsingOutput* output) { return ToChild(ToChild(node, output)->GetMember(name), output); } Ptr RepeatingParsingExecutor::IParsingAnalyzer::GetItem(parsing::ParsingTreeArray* node, vint index, const RepeatingPartialParsingOutput* output) { return ToChild(node->GetItem(index), output); } /*********************************************************************** RepeatingParsingExecutor::CallbackBase ***********************************************************************/ RepeatingParsingExecutor::CallbackBase::CallbackBase(Ptr _parsingExecutor) :parsingExecutor(_parsingExecutor) ,callbackAutoPushing(false) ,callbackElement(0) ,callbackElementModifyLock(0) { } RepeatingParsingExecutor::CallbackBase::~CallbackBase() { } void RepeatingParsingExecutor::CallbackBase::RequireAutoSubmitTask(bool enabled) { callbackAutoPushing=enabled; } void RepeatingParsingExecutor::CallbackBase::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) { if(_element) { SPIN_LOCK(_elementModifyLock) { callbackElement=_element; callbackElementModifyLock=&_elementModifyLock; } } parsingExecutor->ActivateCallback(this); if(callbackElement && callbackElementModifyLock && callbackAutoPushing) { SPIN_LOCK(*callbackElementModifyLock) { RepeatingParsingInput input; input.editVersion=editVersion; input.code=callbackElement->GetLines().GetText(); parsingExecutor->SubmitTask(input); } } } void RepeatingParsingExecutor::CallbackBase::Detach() { if(callbackElement && callbackElementModifyLock) { SPIN_LOCK(*callbackElementModifyLock) { callbackElement=0; callbackElementModifyLock=0; } } parsingExecutor->DeactivateCallback(this); } void RepeatingParsingExecutor::CallbackBase::TextEditPreview(TextEditPreviewStruct& arguments) { } void RepeatingParsingExecutor::CallbackBase::TextEditNotify(const TextEditNotifyStruct& arguments) { } void RepeatingParsingExecutor::CallbackBase::TextCaretChanged(const TextCaretChangedStruct& arguments) { } void RepeatingParsingExecutor::CallbackBase::TextEditFinished(vuint editVersion) { if(callbackElement && callbackElementModifyLock && callbackAutoPushing) { SPIN_LOCK(*callbackElementModifyLock) { RepeatingParsingInput input; input.editVersion=editVersion; input.code=callbackElement->GetLines().GetText(); parsingExecutor->SubmitTask(input); } } } /*********************************************************************** RepeatingParsingExecutor ***********************************************************************/ void RepeatingParsingExecutor::Execute(const RepeatingParsingInput& input) { List> errors; Ptr node=grammarParser->Parse(input.code, grammarRule, errors).Cast(); if(node) { node->InitializeQueryCache(); } RepeatingParsingOutput result; result.node=node; result.editVersion=input.editVersion; result.code=input.code; if(node) { OnContextFinishedAsync(result); FOREACH(ICallback*, callback, callbacks) { callback->OnParsingFinishedAsync(result); } } } void RepeatingParsingExecutor::PrepareMetaData() { Ptr table=grammarParser->GetTable(); tokenIndexMap.Clear(); semanticIndexMap.Clear(); tokenMetaDatas.Clear(); fieldMetaDatas.Clear(); Dictionary> tokenColorAtts, tokenContextColorAtts, tokenCandidateAtts, tokenAutoCompleteAtts; Dictionary> fieldColorAtts, fieldSemanticAtts; { vint tokenCount=table->GetTokenCount(); for(vint token=ParsingTable::UserTokenStart;tokenGetTokenInfo(token); vint tokenIndex=token-ParsingTable::UserTokenStart; tokenIndexMap.Add(tokenInfo.name, tokenIndex); if(Ptr att=GetColorAttribute(tokenInfo.attributeIndex)) { tokenColorAtts.Add(tokenIndex, att); } if(Ptr att=GetContextColorAttribute(tokenInfo.attributeIndex)) { tokenContextColorAtts.Add(tokenIndex, att); } if(Ptr att=GetCandidateAttribute(tokenInfo.attributeIndex)) { tokenCandidateAtts.Add(tokenIndex, att); } if(Ptr att=GetAutoCompleteAttribute(tokenInfo.attributeIndex)) { tokenAutoCompleteAtts.Add(tokenIndex, att); } } } { vint fieldCount=table->GetTreeFieldInfoCount(); for(vint field=0;fieldGetTreeFieldInfo(field); FieldDesc fieldDesc(fieldInfo.type, fieldInfo.field); if(Ptr att=GetColorAttribute(fieldInfo.attributeIndex)) { fieldColorAtts.Add(fieldDesc, att); } if(Ptr att=GetSemanticAttribute(fieldInfo.attributeIndex)) { fieldSemanticAtts.Add(fieldDesc, att); } } } FOREACH(Ptr, att, From(tokenColorAtts.Values()) .Concat(tokenContextColorAtts.Values()) .Concat(fieldColorAtts.Values()) .Concat(fieldSemanticAtts.Values()) ) { FOREACH(WString, argument, att->arguments) { if(!semanticIndexMap.Contains(argument)) { semanticIndexMap.Add(argument); } } } vint index=0; FOREACH(vint, tokenIndex, tokenIndexMap.Values()) { TokenMetaData md; md.tableTokenIndex=tokenIndex+ParsingTable::UserTokenStart; md.lexerTokenIndex=tokenIndex; md.defaultColorIndex=-1; md.hasContextColor=false; md.hasAutoComplete=false; md.isCandidate=false; if((index=tokenColorAtts.Keys().IndexOf(tokenIndex))!=-1) { md.defaultColorIndex=semanticIndexMap.IndexOf(tokenColorAtts.Values()[index]->arguments[0]); } md.hasContextColor=tokenContextColorAtts.Keys().Contains(tokenIndex); md.hasAutoComplete=tokenAutoCompleteAtts.Keys().Contains(tokenIndex); if((md.isCandidate=tokenCandidateAtts.Keys().Contains(tokenIndex))) { const ParsingTable::TokenInfo& tokenInfo=table->GetTokenInfo(md.tableTokenIndex); if(IsRegexEscapedLiteralString(tokenInfo.regex)) { md.unescapedRegexText=UnescapeTextForRegex(tokenInfo.regex); } else { md.isCandidate=false; } } tokenMetaDatas.Add(tokenIndex, md); } { vint fieldCount=table->GetTreeFieldInfoCount(); for(vint field=0;fieldGetTreeFieldInfo(field); FieldDesc fieldDesc(fieldInfo.type, fieldInfo.field); FieldMetaData md; md.colorIndex=-1; if((index=fieldColorAtts.Keys().IndexOf(fieldDesc))!=-1) { md.colorIndex=semanticIndexMap.IndexOf(fieldColorAtts.Values()[index]->arguments[0]); } if((index=fieldSemanticAtts.Keys().IndexOf(fieldDesc))!=-1) { md.semantics=new List; FOREACH(WString, argument, fieldSemanticAtts.Values()[index]->arguments) { md.semantics->Add(semanticIndexMap.IndexOf(argument)); } } fieldMetaDatas.Add(fieldDesc, md); } } } void RepeatingParsingExecutor::OnContextFinishedAsync(RepeatingParsingOutput& context) { if(analyzer) { context.cache = analyzer->CreateCacheAsync(context); } } RepeatingParsingExecutor::RepeatingParsingExecutor(Ptr _grammarParser, const WString& _grammarRule, Ptr _analyzer) :grammarParser(_grammarParser) ,grammarRule(_grammarRule) ,analyzer(_analyzer) ,autoPushingCallback(0) { PrepareMetaData(); if (analyzer) { analyzer->Attach(this); } } RepeatingParsingExecutor::~RepeatingParsingExecutor() { EnsureTaskFinished(); if (analyzer) { analyzer->Detach(this); } } Ptr RepeatingParsingExecutor::GetParser() { return grammarParser; } bool RepeatingParsingExecutor::AttachCallback(ICallback* value) { if(!value) return false; if(callbacks.Contains(value)) return false; callbacks.Add(value); return true; } bool RepeatingParsingExecutor::DetachCallback(ICallback* value) { if(!value) return false; if(!callbacks.Contains(value)) return false; DeactivateCallback(value); callbacks.Remove(value); return true; } bool RepeatingParsingExecutor::ActivateCallback(ICallback* value) { if(!value) return false; if(!callbacks.Contains(value)) return false; if(activatedCallbacks.Contains(value)) return false; activatedCallbacks.Add(value); if(!autoPushingCallback) { autoPushingCallback=value; autoPushingCallback->RequireAutoSubmitTask(true); } return true; } bool RepeatingParsingExecutor::DeactivateCallback(ICallback* value) { if(!value) return false; if(!callbacks.Contains(value)) return false; if(!activatedCallbacks.Contains(value)) return false; if(autoPushingCallback==value) { autoPushingCallback->RequireAutoSubmitTask(false); autoPushingCallback=0; } activatedCallbacks.Remove(value); if(!autoPushingCallback && activatedCallbacks.Count()>0) { autoPushingCallback=activatedCallbacks[0]; autoPushingCallback->RequireAutoSubmitTask(true); } return true; } Ptr RepeatingParsingExecutor::GetAnalyzer() { return analyzer; } vint RepeatingParsingExecutor::GetTokenIndex(const WString& tokenName) { vint index=tokenIndexMap.Keys().IndexOf(tokenName); return index==-1?-1:tokenIndexMap.Values()[index]; } vint RepeatingParsingExecutor::GetSemanticId(const WString& name) { return semanticIndexMap.IndexOf(name); } WString RepeatingParsingExecutor::GetSemanticName(vint id) { return 0<=id&&id RepeatingParsingExecutor::GetAttribute(vint index, const WString& name, vint argumentCount) { if(index!=-1) { Ptr att=grammarParser->GetTable()->GetAttributeInfo(index)->FindFirst(name); if(att && (argumentCount==-1 || att->arguments.Count()==argumentCount)) { return att; } } return 0; } Ptr RepeatingParsingExecutor::GetColorAttribute(vint index) { return GetAttribute(index, L"Color", 1); } Ptr RepeatingParsingExecutor::GetContextColorAttribute(vint index) { return GetAttribute(index, L"ContextColor", 0); } Ptr RepeatingParsingExecutor::GetSemanticAttribute(vint index) { return GetAttribute(index, L"Semantic", -1); } Ptr RepeatingParsingExecutor::GetCandidateAttribute(vint index) { return GetAttribute(index, L"Candidate", 0); } Ptr RepeatingParsingExecutor::GetAutoCompleteAttribute(vint index) { return GetAttribute(index, L"AutoComplete", 0); } } } } /*********************************************************************** CONTROLS\TOOLSTRIPPACKAGE\GUIMENUCONTROLS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace compositions; /*********************************************************************** IGuiMenuService ***********************************************************************/ const wchar_t* const IGuiMenuService::Identifier = L"vl::presentation::controls::IGuiMenuService"; IGuiMenuService::IGuiMenuService() :openingMenu(0) { } void IGuiMenuService::MenuItemExecuted() { if(openingMenu) { openingMenu->Hide(); } if(GetParentMenuService()) { GetParentMenuService()->MenuItemExecuted(); } } GuiMenu* IGuiMenuService::GetOpeningMenu() { return openingMenu; } void IGuiMenuService::MenuOpened(GuiMenu* menu) { if(openingMenu!=menu && openingMenu) { openingMenu->Hide(); } openingMenu=menu; } void IGuiMenuService::MenuClosed(GuiMenu* menu) { if(openingMenu==menu) { openingMenu=0; } } /*********************************************************************** GuiMenu ***********************************************************************/ IGuiMenuService* GuiMenu::GetParentMenuService() { return parentMenuService; } IGuiMenuService::Direction GuiMenu::GetPreferredDirection() { return IGuiMenuService::Vertical; } bool GuiMenu::IsActiveState() { return true; } bool GuiMenu::IsSubMenuActivatedByMouseDown() { return false; } void GuiMenu::MenuItemExecuted() { IGuiMenuService::MenuItemExecuted(); Hide(); } void GuiMenu::OnWindowOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(parentMenuService) { parentMenuService->MenuOpened(this); } } void GuiMenu::OnDeactivatedAltHost() { Hide(); } void GuiMenu::MouseClickedOnOtherWindow(GuiWindow* window) { GuiMenu* targetMenu=dynamic_cast(window); if(!targetMenu) { Hide(); } } void GuiMenu::OnWindowClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(parentMenuService) { parentMenuService->MenuClosed(this); GuiMenu* openingSubMenu=GetOpeningMenu(); if(openingSubMenu) { openingSubMenu->Hide(); } } } GuiMenu::GuiMenu(IStyleController* _styleController, GuiControl* _owner) :GuiPopup(_styleController) ,owner(_owner) ,parentMenuService(0) { GetNativeWindow()->SetAlwaysPassFocusToParent(true); UpdateMenuService(); WindowOpened.AttachMethod(this, &GuiMenu::OnWindowOpened); WindowClosed.AttachMethod(this, &GuiMenu::OnWindowClosed); } GuiMenu::~GuiMenu() { } void GuiMenu::UpdateMenuService() { if(owner) { parentMenuService=owner->QueryTypedService(); } } IDescriptable* GuiMenu::QueryService(const WString& identifier) { if(identifier==IGuiMenuService::Identifier) { return (IGuiMenuService*)this; } else { return GuiPopup::QueryService(identifier); } } /*********************************************************************** GuiMenuBar ***********************************************************************/ IGuiMenuService* GuiMenuBar::GetParentMenuService() { return 0; } IGuiMenuService::Direction GuiMenuBar::GetPreferredDirection() { return IGuiMenuService::Horizontal; } bool GuiMenuBar::IsActiveState() { return GetOpeningMenu()!=0; } bool GuiMenuBar::IsSubMenuActivatedByMouseDown() { return true; } GuiMenuBar::GuiMenuBar(GuiControl::IStyleController* _styleController) :GuiControl(_styleController) { } GuiMenuBar::~GuiMenuBar() { } IDescriptable* GuiMenuBar::QueryService(const WString& identifier) { if(identifier==IGuiMenuService::Identifier) { return (IGuiMenuService*)this; } else { return GuiControl::QueryService(identifier); } } /*********************************************************************** GuiMenuButton ***********************************************************************/ GuiButton* GuiMenuButton::GetSubMenuHost() { GuiButton* button=styleController->GetSubMenuHost(); return button?button:this; } void GuiMenuButton::OpenSubMenuInternal() { if(!GetSubMenuOpening()) { if(ownerMenuService) { GuiMenu* openingSiblingMenu=ownerMenuService->GetOpeningMenu(); if(openingSiblingMenu) { openingSiblingMenu->Hide(); } } SetSubMenuOpening(true); } } void GuiMenuButton::OnParentLineChanged() { GuiButton::OnParentLineChanged(); ownerMenuService=QueryTypedService(); if(ownerMenuService) { SetClickOnMouseUp(!ownerMenuService->IsSubMenuActivatedByMouseDown()); } if(subMenu) { subMenu->UpdateMenuService(); } } bool GuiMenuButton::IsAltAvailable() { return true; } compositions::IGuiAltActionHost* GuiMenuButton::GetActivatingAltHost() { if (subMenu) { return subMenu->QueryTypedService(); } return 0; } void GuiMenuButton::OnSubMenuWindowOpened(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { SubMenuOpeningChanged.Execute(GetNotifyEventArguments()); styleController->SetSubMenuOpening(true); } void GuiMenuButton::OnSubMenuWindowClosed(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { SubMenuOpeningChanged.Execute(GetNotifyEventArguments()); styleController->SetSubMenuOpening(false); } void GuiMenuButton::OnMouseEnter(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(GetVisuallyEnabled()) { if(cascadeAction && ownerMenuService && ownerMenuService->IsActiveState()) { OpenSubMenuInternal(); } } } void GuiMenuButton::OnClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(GetVisuallyEnabled()) { if(GetSubMenu()) { OpenSubMenuInternal(); } else if(ownerMenuService) { ownerMenuService->MenuItemExecuted(); } } } IGuiMenuService::Direction GuiMenuButton::GetSubMenuDirection() { return ownerMenuService?ownerMenuService->GetPreferredDirection():IGuiMenuService::Horizontal; } GuiMenuButton::GuiMenuButton(IStyleController* _styleController) :GuiSelectableButton(_styleController) ,styleController(_styleController) ,subMenu(0) ,ownedSubMenu(false) ,ownerMenuService(0) ,cascadeAction(true) { SetAutoSelection(false); SubMenuOpeningChanged.SetAssociatedComposition(boundsComposition); ImageChanged.SetAssociatedComposition(boundsComposition); ShortcutTextChanged.SetAssociatedComposition(boundsComposition); GetSubMenuHost()->Clicked.AttachMethod(this, &GuiMenuButton::OnClicked); GetSubMenuHost()->GetEventReceiver()->mouseEnter.AttachMethod(this, &GuiMenuButton::OnMouseEnter); } GuiMenuButton::~GuiMenuButton() { if(subMenu && ownedSubMenu) { delete subMenu; } } Ptr GuiMenuButton::GetImage() { return image; } void GuiMenuButton::SetImage(Ptr value) { if(image!=value) { image=value; styleController->SetImage(image); ImageChanged.Execute(GetNotifyEventArguments()); } } const WString& GuiMenuButton::GetShortcutText() { return shortcutText; } void GuiMenuButton::SetShortcutText(const WString& value) { if(shortcutText!=value) { shortcutText=value; styleController->SetShortcutText(shortcutText); ShortcutTextChanged.Execute(GetNotifyEventArguments()); } } bool GuiMenuButton::IsSubMenuExists() { return subMenu!=0; } GuiMenu* GuiMenuButton::GetSubMenu() { return subMenu; } GuiMenu* GuiMenuButton::CreateSubMenu(GuiMenu::IStyleController* subMenuStyleController) { if(!subMenu) { GuiMenu* newSubMenu=new GuiMenu(subMenuStyleController?subMenuStyleController:styleController->CreateSubMenuStyleController(), this); SetSubMenu(newSubMenu, true); } return subMenu; } void GuiMenuButton::SetSubMenu(GuiMenu* value, bool owned) { if(subMenu) { if(ownedSubMenu) { delete subMenu; } } subMenu=value; ownedSubMenu=owned; if(subMenu) { subMenu->WindowOpened.AttachMethod(this, &GuiMenuButton::OnSubMenuWindowOpened); subMenu->WindowClosed.AttachMethod(this, &GuiMenuButton::OnSubMenuWindowClosed); } styleController->SetSubMenuExisting(subMenu!=0); } void GuiMenuButton::DestroySubMenu() { if(subMenu) { if(ownedSubMenu) { delete subMenu; } subMenu=0; ownedSubMenu=false; styleController->SetSubMenuExisting(false); } } bool GuiMenuButton::GetOwnedSubMenu() { return subMenu && ownedSubMenu; } bool GuiMenuButton::GetSubMenuOpening() { if(subMenu) { return subMenu->GetOpening(); } else { return false; } } void GuiMenuButton::SetSubMenuOpening(bool value) { if(subMenu) { if(value) { subMenu->SetClientSize(preferredMenuClientSize); IGuiMenuService::Direction direction=GetSubMenuDirection(); subMenu->ShowPopup(GetSubMenuHost(), direction==IGuiMenuService::Horizontal); } else { subMenu->Close(); } } } Size GuiMenuButton::GetPreferredMenuClientSize() { return preferredMenuClientSize; } void GuiMenuButton::SetPreferredMenuClientSize(Size value) { preferredMenuClientSize=value; } bool GuiMenuButton::GetCascadeAction() { return cascadeAction; } void GuiMenuButton::SetCascadeAction(bool value) { cascadeAction=value; } } } } /*********************************************************************** CONTROLS\TOOLSTRIPPACKAGE\GUITOOLSTRIPCOMMAND.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace compositions; using namespace regex; /*********************************************************************** GuiToolstripCommand ***********************************************************************/ void GuiToolstripCommand::OnShortcutKeyItemExecuted(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { Executed.ExecuteWithNewSender(arguments, sender); } void GuiToolstripCommand::InvokeDescriptionChanged() { GuiEventArgs arguments; DescriptionChanged.Execute(arguments); } void GuiToolstripCommand::ReplaceShortcut(compositions::IGuiShortcutKeyItem* value, Ptr builder) { if(shortcutKeyItem!=value) { if(shortcutKeyItem) { shortcutKeyItem->Executed.Detach(shortcutKeyItemExecutedHandler); if (shortcutBuilder) { auto manager = dynamic_cast(shortcutOwner->GetShortcutKeyManager()); if (manager) { manager->DestroyShortcut(shortcutBuilder->ctrl, shortcutBuilder->shift, shortcutBuilder->alt, shortcutBuilder->key); } } } shortcutKeyItem=0; shortcutKeyItemExecutedHandler=0; shortcutBuilder = value ? builder : nullptr; if(value) { shortcutKeyItem=value; shortcutKeyItemExecutedHandler=shortcutKeyItem->Executed.AttachMethod(this, &GuiToolstripCommand::OnShortcutKeyItemExecuted); } InvokeDescriptionChanged(); } } void GuiToolstripCommand::BuildShortcut(const WString& builderText) { List errors; if (auto parser = GetParserManager()->GetParser(L"SHORTCUT")) if (Ptr builder = parser->TypedParse(builderText, errors)) { if (shortcutOwner) { if (!shortcutOwner->GetShortcutKeyManager()) { shortcutOwner->SetShortcutKeyManager(new GuiShortcutKeyManager); } if (auto manager = dynamic_cast(shortcutOwner->GetShortcutKeyManager())) { IGuiShortcutKeyItem* item = manager->TryGetShortcut(builder->ctrl, builder->shift, builder->alt, builder->key); if (!item) { item = manager->CreateShortcut(builder->ctrl, builder->shift, builder->alt, builder->key); if (item) { ReplaceShortcut(item, builder); } } } } else { shortcutBuilder = builder; } } } GuiToolstripCommand::GuiToolstripCommand() :shortcutKeyItem(0) ,enabled(true) ,selected(false) ,shortcutOwner(0) { } GuiToolstripCommand::~GuiToolstripCommand() { } void GuiToolstripCommand::Attach(GuiInstanceRootObject* rootObject) { shortcutOwner = dynamic_cast(rootObject); if (shortcutBuilder && !shortcutKeyItem) { BuildShortcut(shortcutBuilder->text); } } void GuiToolstripCommand::Detach(GuiInstanceRootObject* rootObject) { ReplaceShortcut(0, nullptr); shortcutOwner = 0; } Ptr GuiToolstripCommand::GetImage() { return image; } void GuiToolstripCommand::SetImage(Ptr value) { if(image!=value) { image=value; InvokeDescriptionChanged(); } } const WString& GuiToolstripCommand::GetText() { return text; } void GuiToolstripCommand::SetText(const WString& value) { if(text!=value) { text=value; InvokeDescriptionChanged(); } } compositions::IGuiShortcutKeyItem* GuiToolstripCommand::GetShortcut() { return shortcutKeyItem; } void GuiToolstripCommand::SetShortcut(compositions::IGuiShortcutKeyItem* value) { ReplaceShortcut(value, 0); } WString GuiToolstripCommand::GetShortcutBuilder() { return shortcutBuilder ? shortcutBuilder->text : L""; } void GuiToolstripCommand::SetShortcutBuilder(const WString& value) { BuildShortcut(value); } bool GuiToolstripCommand::GetEnabled() { return enabled; } void GuiToolstripCommand::SetEnabled(bool value) { if(enabled!=value) { enabled=value; InvokeDescriptionChanged(); } } bool GuiToolstripCommand::GetSelected() { return selected; } void GuiToolstripCommand::SetSelected(bool value) { if(selected!=value) { selected=value; InvokeDescriptionChanged(); } } /*********************************************************************** GuiToolstripCommand::ShortcutBuilder Parser ***********************************************************************/ class GuiToolstripCommandShortcutParser : public Object, public IGuiParser { typedef GuiToolstripCommand::ShortcutBuilder ShortcutBuilder; public: Regex regexShortcut; GuiToolstripCommandShortcutParser() :regexShortcut(L"((Ctrl)/+|(Shift)/+|(Alt)/+)*(/.+)") { } Ptr TypedParse(const WString& text, collections::List& errors)override { Ptr match=regexShortcut.MatchHead(text); if (match && match->Result().Length() != text.Length()) { errors.Add(L"Failed to parse a shortcut \"" + text + L"\"."); return 0; } Ptr builder = new ShortcutBuilder; builder->text = text; builder->ctrl = match->Groups().Contains(L"ctrl"); builder->shift = match->Groups().Contains(L"shift"); builder->alt = match->Groups().Contains(L"alt"); WString name = match->Groups()[L"key"][0].Value(); builder->key = GetCurrentController()->InputService()->GetKey(name); return builder->key == -1 ? nullptr : builder; } }; /*********************************************************************** GuiToolstripCommandPlugin ***********************************************************************/ class GuiToolstripCommandPlugin : public Object, public IGuiPlugin { public: GuiToolstripCommandPlugin() { } void Load()override { } void AfterLoad()override { IGuiParserManager* manager=GetParserManager(); manager->SetParser(L"SHORTCUT", new GuiToolstripCommandShortcutParser); } void Unload()override { } }; GUI_REGISTER_PLUGIN(GuiToolstripCommandPlugin) } } } /*********************************************************************** CONTROLS\TOOLSTRIPPACKAGE\GUITOOLSTRIPMENU.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace controls { using namespace collections; using namespace compositions; /*********************************************************************** GuiToolstripCollection ***********************************************************************/ void GuiToolstripCollection::InvokeUpdateLayout() { if(contentCallback) { contentCallback->UpdateLayout(); } } void GuiToolstripCollection::OnInterestingMenuButtonPropertyChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { InvokeUpdateLayout(); } bool GuiToolstripCollection::QueryInsert(vint index, GuiControl* const& child) { return true; } bool GuiToolstripCollection::QueryRemove(vint index, GuiControl* const& child) { return true; } void GuiToolstripCollection::BeforeInsert(vint index, GuiControl* const& child) { } void GuiToolstripCollection::BeforeRemove(vint index, GuiControl* const& child) { GuiStackItemComposition* stackItem = stackComposition->GetStackItems().Get(index); stackComposition->RemoveChild(stackItem); stackItem->RemoveChild(child->GetBoundsComposition()); delete stackItem; delete child; InvokeUpdateLayout(); } void GuiToolstripCollection::AfterInsert(vint index, GuiControl* const& child) { GuiStackItemComposition* stackItem=new GuiStackItemComposition; child->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); stackItem->AddChild(child->GetBoundsComposition()); stackComposition->InsertChild(index, stackItem); GuiMenuButton* menuButton=dynamic_cast(child); if(menuButton) { menuButton->TextChanged.AttachMethod(this, &GuiToolstripCollection::OnInterestingMenuButtonPropertyChanged); menuButton->ShortcutTextChanged.AttachMethod(this, &GuiToolstripCollection::OnInterestingMenuButtonPropertyChanged); } InvokeUpdateLayout(); } void GuiToolstripCollection::AfterRemove(vint index, vint count) { InvokeUpdateLayout(); } GuiToolstripCollection::GuiToolstripCollection(IContentCallback* _contentCallback, compositions::GuiStackComposition* _stackComposition) :contentCallback(_contentCallback) ,stackComposition(_stackComposition) { } GuiToolstripCollection::~GuiToolstripCollection() { } /*********************************************************************** GuiToolstripBuilder ***********************************************************************/ GuiToolstripBuilder::GuiToolstripBuilder(Environment _environment, GuiToolstripCollection* _toolstripItems) :environment(_environment) ,toolstripItems(_toolstripItems) ,previousBuilder(0) ,theme(0) ,lastCreatedButton(0) { } GuiToolstripBuilder::~GuiToolstripBuilder() { } GuiToolstripBuilder* GuiToolstripBuilder::Button(Ptr image, const WString& text, GuiToolstripButton** result) { lastCreatedButton=0; switch(environment) { case Menu: lastCreatedButton=new GuiToolstripButton(theme->CreateMenuItemButtonStyle()); break; case MenuBar: lastCreatedButton=new GuiToolstripButton(theme->CreateMenuBarButtonStyle()); break; case ToolBar: lastCreatedButton=new GuiToolstripButton(theme->CreateToolBarButtonStyle()); break; } if(lastCreatedButton) { lastCreatedButton->SetImage(image); lastCreatedButton->SetText(text); if(result) { *result=lastCreatedButton; } toolstripItems->Add(lastCreatedButton); } return this; } GuiToolstripBuilder* GuiToolstripBuilder::Button(GuiToolstripCommand* command, GuiToolstripButton** result) { lastCreatedButton=0; switch(environment) { case Menu: lastCreatedButton=new GuiToolstripButton(theme->CreateMenuItemButtonStyle()); break; case MenuBar: lastCreatedButton=new GuiToolstripButton(theme->CreateMenuBarButtonStyle()); break; case ToolBar: lastCreatedButton=new GuiToolstripButton(theme->CreateToolBarButtonStyle()); break; } if(lastCreatedButton) { lastCreatedButton->SetCommand(command); if(result) { *result=lastCreatedButton; } toolstripItems->Add(lastCreatedButton); } return this; } GuiToolstripBuilder* GuiToolstripBuilder::DropdownButton(Ptr image, const WString& text, GuiToolstripButton** result) { lastCreatedButton=0; switch(environment) { case ToolBar: lastCreatedButton=new GuiToolstripButton(theme->CreateToolBarDropdownButtonStyle()); break; default:; } if(lastCreatedButton) { lastCreatedButton->SetImage(image); lastCreatedButton->SetText(text); if(result) { *result=lastCreatedButton; } toolstripItems->Add(lastCreatedButton); } return this; } GuiToolstripBuilder* GuiToolstripBuilder::DropdownButton(GuiToolstripCommand* command, GuiToolstripButton** result) { lastCreatedButton=0; switch(environment) { case ToolBar: lastCreatedButton=new GuiToolstripButton(theme->CreateToolBarDropdownButtonStyle()); break; default:; } if(lastCreatedButton) { lastCreatedButton->SetCommand(command); if(result) { *result=lastCreatedButton; } toolstripItems->Add(lastCreatedButton); } return this; } GuiToolstripBuilder* GuiToolstripBuilder::SplitButton(Ptr image, const WString& text, GuiToolstripButton** result) { lastCreatedButton=0; switch(environment) { case ToolBar: lastCreatedButton=new GuiToolstripButton(theme->CreateToolBarSplitButtonStyle()); break; default:; } if(lastCreatedButton) { lastCreatedButton->SetImage(image); lastCreatedButton->SetText(text); if(result) { *result=lastCreatedButton; } toolstripItems->Add(lastCreatedButton); } return this; } GuiToolstripBuilder* GuiToolstripBuilder::SplitButton(GuiToolstripCommand* command, GuiToolstripButton** result) { lastCreatedButton=0; switch(environment) { case ToolBar: lastCreatedButton=new GuiToolstripButton(theme->CreateToolBarSplitButtonStyle()); break; default:; } if(lastCreatedButton) { lastCreatedButton->SetCommand(command); if(result) { *result=lastCreatedButton; } toolstripItems->Add(lastCreatedButton); } return this; } GuiToolstripBuilder* GuiToolstripBuilder::Splitter() { lastCreatedButton=0; switch(environment) { case Menu: toolstripItems->Add(new GuiControl(theme->CreateMenuSplitterStyle())); break; case ToolBar: toolstripItems->Add(new GuiControl(theme->CreateToolBarSplitterStyle())); break; default:; } return this; } GuiToolstripBuilder* GuiToolstripBuilder::Control(GuiControl* control) { toolstripItems->Add(control); return this; } GuiToolstripBuilder* GuiToolstripBuilder::BeginSubMenu() { if(lastCreatedButton) { lastCreatedButton->CreateToolstripSubMenu(); GuiToolstripMenu* menu=lastCreatedButton->GetToolstripSubMenu(); if(menu) { menu->GetBuilder()->previousBuilder=this; return menu->GetBuilder(); } } return 0; } GuiToolstripBuilder* GuiToolstripBuilder::EndSubMenu() { return previousBuilder; } /*********************************************************************** GuiToolstripMenu ***********************************************************************/ void GuiToolstripMenu::UpdateLayout() { sharedSizeRootComposition->ForceCalculateSizeImmediately(); } GuiToolstripMenu::GuiToolstripMenu(IStyleController* _styleController, GuiControl* _owner) :GuiMenu(_styleController, _owner) { sharedSizeRootComposition = new GuiSharedSizeRootComposition(); sharedSizeRootComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); sharedSizeRootComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GetContainerComposition()->AddChild(sharedSizeRootComposition); stackComposition=new GuiStackComposition; stackComposition->SetDirection(GuiStackComposition::Vertical); stackComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); stackComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); sharedSizeRootComposition->AddChild(stackComposition); toolstripItems = new GuiToolstripCollection(this, stackComposition); builder = new GuiToolstripBuilder(GuiToolstripBuilder::Menu, toolstripItems.Obj()); } GuiToolstripMenu::~GuiToolstripMenu() { } GuiToolstripCollection& GuiToolstripMenu::GetToolstripItems() { return *toolstripItems.Obj(); } GuiToolstripBuilder* GuiToolstripMenu::GetBuilder(theme::ITheme* themeObject) { builder->theme=themeObject?themeObject:theme::GetCurrentTheme(); return builder.Obj(); } /*********************************************************************** GuiToolstripMenuBar ***********************************************************************/ GuiToolstripMenuBar::GuiToolstripMenuBar(IStyleController* _styleController) :GuiMenuBar(_styleController) { stackComposition=new GuiStackComposition; stackComposition->SetDirection(GuiStackComposition::Horizontal); stackComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); stackComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GetContainerComposition()->AddChild(stackComposition); toolstripItems=new GuiToolstripCollection(0, stackComposition); builder=new GuiToolstripBuilder(GuiToolstripBuilder::MenuBar, toolstripItems.Obj()); } GuiToolstripMenuBar::~GuiToolstripMenuBar() { } GuiToolstripCollection& GuiToolstripMenuBar::GetToolstripItems() { return *toolstripItems.Obj(); } GuiToolstripBuilder* GuiToolstripMenuBar::GetBuilder(theme::ITheme* themeObject) { builder->theme=themeObject?themeObject:theme::GetCurrentTheme(); return builder.Obj(); } /*********************************************************************** GuiToolstripToolBar ***********************************************************************/ GuiToolstripToolBar::GuiToolstripToolBar(IStyleController* _styleController) :GuiControl(_styleController) { stackComposition=new GuiStackComposition; stackComposition->SetDirection(GuiStackComposition::Horizontal); stackComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); stackComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); GetContainerComposition()->AddChild(stackComposition); toolstripItems=new GuiToolstripCollection(0, stackComposition); builder=new GuiToolstripBuilder(GuiToolstripBuilder::ToolBar, toolstripItems.Obj()); } GuiToolstripToolBar::~GuiToolstripToolBar() { } GuiToolstripCollection& GuiToolstripToolBar::GetToolstripItems() { return *toolstripItems.Obj(); } GuiToolstripBuilder* GuiToolstripToolBar::GetBuilder(theme::ITheme* themeObject) { builder->theme=themeObject?themeObject:theme::GetCurrentTheme(); return builder.Obj(); } /*********************************************************************** GuiToolstripButton ***********************************************************************/ void GuiToolstripButton::UpdateCommandContent() { if(command) { SetImage(command->GetImage()); SetText(command->GetText()); SetEnabled(command->GetEnabled()); SetSelected(command->GetSelected()); if(command->GetShortcut()) { SetShortcutText(command->GetShortcut()->GetName()); } else { SetShortcutText(L""); } } else { SetImage(0); SetText(L""); SetEnabled(true); SetSelected(false); SetShortcutText(L""); } } void GuiToolstripButton::OnClicked(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { if(command) { command->Executed.ExecuteWithNewSender(arguments, sender); } } void GuiToolstripButton::OnCommandDescriptionChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) { UpdateCommandContent(); } GuiToolstripButton::GuiToolstripButton(IStyleController* _styleController) :GuiMenuButton(_styleController) ,command(0) { Clicked.AttachMethod(this, &GuiToolstripButton::OnClicked); } GuiToolstripButton::~GuiToolstripButton() { } GuiToolstripCommand* GuiToolstripButton::GetCommand() { return command; } void GuiToolstripButton::SetCommand(GuiToolstripCommand* value) { if(command!=value) { if(command) { command->DescriptionChanged.Detach(descriptionChangedHandler); } command=0; descriptionChangedHandler=0; if(value) { command=value; descriptionChangedHandler=command->DescriptionChanged.AttachMethod(this, &GuiToolstripButton::OnCommandDescriptionChanged); } UpdateCommandContent(); } } GuiToolstripMenu* GuiToolstripButton::GetToolstripSubMenu() { return dynamic_cast(GetSubMenu()); } GuiToolstripMenu* GuiToolstripButton::EnsureToolstripSubMenu() { if (!GetSubMenu()) { CreateToolstripSubMenu(); } return dynamic_cast(GetSubMenu()); } void GuiToolstripButton::CreateToolstripSubMenu(GuiToolstripMenu::IStyleController* subMenuStyleController) { if(!subMenu) { GuiToolstripMenu* newSubMenu=new GuiToolstripMenu(subMenuStyleController?subMenuStyleController:styleController->CreateSubMenuStyleController(), this); SetSubMenu(newSubMenu, true); } } } } } /*********************************************************************** GRAPHICSCOMPOSITION\GUIGRAPHICSAXIS.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { /*********************************************************************** GuiDefaultAxis ***********************************************************************/ GuiDefaultAxis::GuiDefaultAxis() { } GuiDefaultAxis::~GuiDefaultAxis() { } Size GuiDefaultAxis::RealSizeToVirtualSize(Size size) { return size; } Size GuiDefaultAxis::VirtualSizeToRealSize(Size size) { return size; } Point GuiDefaultAxis::RealPointToVirtualPoint(Size realFullSize, Point point) { return point; } Point GuiDefaultAxis::VirtualPointToRealPoint(Size realFullSize, Point point) { return point; } Rect GuiDefaultAxis::RealRectToVirtualRect(Size realFullSize, Rect rect) { return rect; } Rect GuiDefaultAxis::VirtualRectToRealRect(Size realFullSize, Rect rect) { return rect; } Margin GuiDefaultAxis::RealMarginToVirtualMargin(Margin margin) { return margin; } Margin GuiDefaultAxis::VirtualMarginToRealMargin(Margin margin) { return margin; } KeyDirection GuiDefaultAxis::RealKeyDirectionToVirtualKeyDirection(KeyDirection key) { return key; } /*********************************************************************** GuiAxis ***********************************************************************/ GuiAxis::GuiAxis(AxisDirection _axisDirection) :axisDirection(_axisDirection) { } GuiAxis::~GuiAxis() { } AxisDirection GuiAxis::GetDirection() { return axisDirection; } Size GuiAxis::RealSizeToVirtualSize(Size size) { switch(axisDirection) { case AxisDirection::LeftDown: case AxisDirection::RightDown: case AxisDirection::LeftUp: case AxisDirection::RightUp: return Size(size.x, size.y); case AxisDirection::DownLeft: case AxisDirection::DownRight: case AxisDirection::UpLeft: case AxisDirection::UpRight: return Size(size.y, size.x); } return size; } Size GuiAxis::VirtualSizeToRealSize(Size size) { return RealSizeToVirtualSize(size); } Point GuiAxis::RealPointToVirtualPoint(Size realFullSize, Point point) { Rect rect(point, Size(0, 0)); return RealRectToVirtualRect(realFullSize, rect).LeftTop(); } Point GuiAxis::VirtualPointToRealPoint(Size realFullSize, Point point) { Rect rect(point, Size(0, 0)); return VirtualRectToRealRect(realFullSize, rect).LeftTop(); } Rect GuiAxis::RealRectToVirtualRect(Size realFullSize, Rect rect) { vint x1=rect.x1; vint x2=realFullSize.x-rect.x2; vint y1=rect.y1; vint y2=realFullSize.y-rect.y2; vint w=rect.Width(); vint h=rect.Height(); switch(axisDirection) { case AxisDirection::LeftDown: return Rect(Point(x2, y1), Size(w, h)); case AxisDirection::RightDown: return Rect(Point(x1, y1), Size(w, h)); case AxisDirection::LeftUp: return Rect(Point(x2, y2), Size(w, h)); case AxisDirection::RightUp: return Rect(Point(x1, y2), Size(w, h)); case AxisDirection::DownLeft: return Rect(Point(y1, x2), Size(h, w)); case AxisDirection::DownRight: return Rect(Point(y1, x1), Size(h, w)); case AxisDirection::UpLeft: return Rect(Point(y2, x2), Size(h, w)); case AxisDirection::UpRight: return Rect(Point(y2, x1), Size(h, w)); } return rect; } Rect GuiAxis::VirtualRectToRealRect(Size realFullSize, Rect rect) { realFullSize=RealSizeToVirtualSize(realFullSize); vint x1=rect.x1; vint x2=realFullSize.x-rect.x2; vint y1=rect.y1; vint y2=realFullSize.y-rect.y2; vint w=rect.Width(); vint h=rect.Height(); switch(axisDirection) { case AxisDirection::LeftDown: return Rect(Point(x2, y1), Size(w, h)); case AxisDirection::RightDown: return Rect(Point(x1, y1), Size(w, h)); case AxisDirection::LeftUp: return Rect(Point(x2, y2), Size(w, h)); case AxisDirection::RightUp: return Rect(Point(x1, y2), Size(w, h)); case AxisDirection::DownLeft: return Rect(Point(y2, x1), Size(h, w)); case AxisDirection::DownRight: return Rect(Point(y1, x1), Size(h, w)); case AxisDirection::UpLeft: return Rect(Point(y2, x2), Size(h, w)); case AxisDirection::UpRight: return Rect(Point(y1, x2), Size(h, w)); } return rect; } Margin GuiAxis::RealMarginToVirtualMargin(Margin margin) { vint x1=margin.left; vint x2=margin.right; vint y1=margin.top; vint y2=margin.bottom; switch(axisDirection) { case AxisDirection::LeftDown: return Margin(x2, y1, x1, y2); case AxisDirection::RightDown: return Margin(x1, y1, x2, y2); case AxisDirection::LeftUp: return Margin(x2, y2, x1, y1); case AxisDirection::RightUp: return Margin(x1, y2, x2, y1); case AxisDirection::DownLeft: return Margin(y1, x2, y2, x1); case AxisDirection::DownRight: return Margin(y1, x1, y2, x2); case AxisDirection::UpLeft: return Margin(y2, x2, y1, x1); case AxisDirection::UpRight: return Margin(y2, x1, y1, x2); } return margin; } Margin GuiAxis::VirtualMarginToRealMargin(Margin margin) { vint x1=margin.left; vint x2=margin.right; vint y1=margin.top; vint y2=margin.bottom; switch(axisDirection) { case AxisDirection::LeftDown: return Margin(x2, y1, x1, y2); case AxisDirection::RightDown: return Margin(x1, y1, x2, y2); case AxisDirection::LeftUp: return Margin(x2, y2, x1, y1); case AxisDirection::RightUp: return Margin(x1, y2, x2, y1); case AxisDirection::DownLeft: return Margin(y2, x1, y1, x2); case AxisDirection::DownRight: return Margin(y1, x1, y2, x2); case AxisDirection::UpLeft: return Margin(y2, x2, y1, x1); case AxisDirection::UpRight: return Margin(y1, x2, y2, x1); default:; } return margin; } KeyDirection GuiAxis::RealKeyDirectionToVirtualKeyDirection(KeyDirection key) { bool pageKey=false; switch(key) { case KeyDirection::PageUp: pageKey=true; key=KeyDirection::Up; break; case KeyDirection::PageDown: pageKey=true; key=KeyDirection::Down; break; case KeyDirection::PageLeft: pageKey=true; key=KeyDirection::Left; break; case KeyDirection::PageRight: pageKey=true; key=KeyDirection::Right; break; default:; } switch(key) { case KeyDirection::Up: switch(axisDirection) { case AxisDirection::LeftDown: key=KeyDirection::Up; break; case AxisDirection::RightDown: key=KeyDirection::Up; break; case AxisDirection::LeftUp: key=KeyDirection::Down; break; case AxisDirection::RightUp: key=KeyDirection::Down; break; case AxisDirection::DownLeft: key=KeyDirection::Left; break; case AxisDirection::DownRight: key=KeyDirection::Left; break; case AxisDirection::UpLeft: key=KeyDirection::Right; break; case AxisDirection::UpRight: key=KeyDirection::Right; break; } break; case KeyDirection::Down: switch(axisDirection) { case AxisDirection::LeftDown: key=KeyDirection::Down; break; case AxisDirection::RightDown: key=KeyDirection::Down; break; case AxisDirection::LeftUp: key=KeyDirection::Up; break; case AxisDirection::RightUp: key=KeyDirection::Up; break; case AxisDirection::DownLeft: key=KeyDirection::Right; break; case AxisDirection::DownRight: key=KeyDirection::Right; break; case AxisDirection::UpLeft: key=KeyDirection::Left; break; case AxisDirection::UpRight: key=KeyDirection::Left; break; } break; case KeyDirection::Left: switch(axisDirection) { case AxisDirection::LeftDown: key=KeyDirection::Right; break; case AxisDirection::RightDown: key=KeyDirection::Left; break; case AxisDirection::LeftUp: key=KeyDirection::Right; break; case AxisDirection::RightUp: key=KeyDirection::Left; break; case AxisDirection::DownLeft: key=KeyDirection::Down; break; case AxisDirection::DownRight: key=KeyDirection::Up; break; case AxisDirection::UpLeft: key=KeyDirection::Down; break; case AxisDirection::UpRight: key=KeyDirection::Up; break; } break; case KeyDirection::Right: switch(axisDirection) { case AxisDirection::LeftDown: key=KeyDirection::Left; break; case AxisDirection::RightDown: key=KeyDirection::Right; break; case AxisDirection::LeftUp: key=KeyDirection::Left; break; case AxisDirection::RightUp: key=KeyDirection::Right; break; case AxisDirection::DownLeft: key=KeyDirection::Up; break; case AxisDirection::DownRight: key=KeyDirection::Down; break; case AxisDirection::UpLeft: key=KeyDirection::Up; break; case AxisDirection::UpRight: key=KeyDirection::Down; break; } break; case KeyDirection::Home: switch(axisDirection) { case AxisDirection::LeftDown: key=KeyDirection::Home; break; case AxisDirection::RightDown: key=KeyDirection::Home; break; case AxisDirection::LeftUp: key=KeyDirection::End; break; case AxisDirection::RightUp: key=KeyDirection::End; break; case AxisDirection::DownLeft: key=KeyDirection::Home; break; case AxisDirection::DownRight: key=KeyDirection::Home; break; case AxisDirection::UpLeft: key=KeyDirection::End; break; case AxisDirection::UpRight: key=KeyDirection::End; break; } break; case KeyDirection::End: switch(axisDirection) { case AxisDirection::LeftDown: key=KeyDirection::End; break; case AxisDirection::RightDown: key=KeyDirection::End; break; case AxisDirection::LeftUp: key=KeyDirection::Home; break; case AxisDirection::RightUp: key=KeyDirection::Home; break; case AxisDirection::DownLeft: key=KeyDirection::End; break; case AxisDirection::DownRight: key=KeyDirection::End; break; case AxisDirection::UpLeft: key=KeyDirection::Home; break; case AxisDirection::UpRight: key=KeyDirection::Home; break; } break; default:; } if(pageKey) { switch(key) { case KeyDirection::Up: key=KeyDirection::PageUp; break; case KeyDirection::Down: key=KeyDirection::PageDown; break; case KeyDirection::Left: key=KeyDirection::PageLeft; break; case KeyDirection::Right: key=KeyDirection::PageRight; break; default:; } } return key; } } } } /*********************************************************************** GRAPHICSCOMPOSITION\GUIGRAPHICSBASICCOMPOSITION.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { using namespace collections; using namespace controls; using namespace elements; /*********************************************************************** GuiWindowComposition ***********************************************************************/ GuiWindowComposition::GuiWindowComposition() :attachedWindow(0) { } GuiWindowComposition::~GuiWindowComposition() { } INativeWindow* GuiWindowComposition::GetAttachedWindow() { return attachedWindow; } void GuiWindowComposition::SetAttachedWindow(INativeWindow* window) { attachedWindow=window; SetRenderTarget(attachedWindow?GetGuiGraphicsResourceManager()->GetRenderTarget(attachedWindow):0); } Rect GuiWindowComposition::GetBounds() { return attachedWindow?Rect(Point(0, 0), attachedWindow->GetClientSize()):Rect(); } void GuiWindowComposition::SetMargin(Margin value) { } /*********************************************************************** GuiBoundsComposition ***********************************************************************/ GuiBoundsComposition::GuiBoundsComposition() { ClearAlignmentToParent(); } GuiBoundsComposition::~GuiBoundsComposition() { } 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; } void GuiBoundsComposition::ClearAlignmentToParent() { alignmentToParent=Margin(-1, -1, -1, -1); } Margin GuiBoundsComposition::GetAlignmentToParent() { return alignmentToParent; } void GuiBoundsComposition::SetAlignmentToParent(Margin value) { alignmentToParent=value; } bool GuiBoundsComposition::IsAlignedToParent() { return alignmentToParent!=Margin(-1, -1, -1, -1); } } } } /*********************************************************************** GRAPHICSCOMPOSITION\GUIGRAPHICSCOMPOSITION.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { using namespace collections; using namespace controls; using namespace elements; /*********************************************************************** GuiSharedSizeItemComposition ***********************************************************************/ void GuiSharedSizeItemComposition::Update() { if (parentRoot) { parentRoot->ForceCalculateSizeImmediately(); } } void GuiSharedSizeItemComposition::OnParentLineChanged() { GuiBoundsComposition::OnParentLineChanged(); if (parentRoot) { parentRoot->childItems.Remove(this); parentRoot = 0; } auto current = GetParent(); while (current) { if (auto item = dynamic_cast(current)) { break; } else if (auto root = dynamic_cast(current)) { parentRoot = root; break; } current = current->GetParent(); } if (parentRoot) { parentRoot->childItems.Add(this); } } GuiSharedSizeItemComposition::GuiSharedSizeItemComposition() :parentRoot(0) , sharedWidth(false) , sharedHeight(false) { SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } GuiSharedSizeItemComposition::~GuiSharedSizeItemComposition() { } const WString& GuiSharedSizeItemComposition::GetGroup() { return group; } void GuiSharedSizeItemComposition::SetGroup(const WString& value) { if (group != value) { group = value; Update(); } } bool GuiSharedSizeItemComposition::GetSharedWidth() { return sharedWidth; } void GuiSharedSizeItemComposition::SetSharedWidth(bool value) { if (sharedWidth != value) { sharedWidth = value; Update(); } } bool GuiSharedSizeItemComposition::GetSharedHeight() { return sharedHeight; } void GuiSharedSizeItemComposition::SetSharedHeight(bool value) { if (sharedHeight != value) { sharedHeight = value; Update(); } } /*********************************************************************** GuiSharedSizeRootComposition ***********************************************************************/ GuiSharedSizeRootComposition::GuiSharedSizeRootComposition() { } GuiSharedSizeRootComposition::~GuiSharedSizeRootComposition() { } void AddSizeComponent(Dictionary& sizes, const WString& group, vint sizeComponent) { vint index = sizes.Keys().IndexOf(group); if (index == -1) { sizes.Add(group, sizeComponent); } else if (sizes.Values().Get(index) < sizeComponent) { sizes.Set(group, sizeComponent); } } void GuiSharedSizeRootComposition::ForceCalculateSizeImmediately() { Dictionary widths, heights; FOREACH(GuiSharedSizeItemComposition*, item, childItems) { auto group = item->GetGroup(); auto minSize = item->GetPreferredMinSize(); item->SetPreferredMinSize(Size(0, 0)); auto size = item->GetPreferredBounds().GetSize(); if (item->GetSharedWidth()) { AddSizeComponent(widths, group, size.x); } if (item->GetSharedHeight()) { AddSizeComponent(heights, group, size.y); } item->SetPreferredMinSize(minSize); } FOREACH(GuiSharedSizeItemComposition*, item, childItems) { auto group = item->GetGroup(); auto size = item->GetPreferredMinSize(); if (item->GetSharedWidth()) { size.x = widths[group]; } if (item->GetSharedHeight()) { size.y = heights[group]; } item->SetPreferredMinSize(size); } GuiBoundsComposition::ForceCalculateSizeImmediately(); } } } } /*********************************************************************** GRAPHICSCOMPOSITION\GUIGRAPHICSCOMPOSITIONBASE.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { using namespace collections; using namespace controls; using namespace elements; /*********************************************************************** 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::OnRenderTargetChanged() { if(associatedControl) { associatedControl->OnRenderTargetChanged(renderTarget); } } 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() :parent(0) ,visible(true) ,minSizeLimitation(NoLimit) ,renderTarget(0) ,associatedControl(0) ,associatedHost(0) ,associatedCursor(0) ,associatedHitTestResult(INativeWindowListener::NoDecision) { sharedPtrDestructorProc = &GuiGraphicsComposition::SharedPtrDestructorProc; } GuiGraphicsComposition::~GuiGraphicsComposition() { for(vint i=0;iGetParent()) return false; children.Insert(index, child); child->parent=this; child->SetRenderTarget(renderTarget); OnChildInserted(child); child->OnParentChanged(0, child->parent); return true; } bool GuiGraphicsComposition::RemoveChild(GuiGraphicsComposition* child) { if(!child) return false; vint index=children.IndexOf(child); if(index==-1) return false; child->OnParentChanged(child->parent, 0); OnChildRemoved(child); child->SetRenderTarget(0); child->parent=0; GuiGraphicsHost* host=GetRelatedGraphicsHost(); if(host) { host->DisconnectComposition(child); } children.RemoveAt(index); 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); return true; } Ptr GuiGraphicsComposition::GetOwnedElement() { return ownedElement; } void GuiGraphicsComposition::SetOwnedElement(Ptr element) { if(ownedElement) { IGuiGraphicsRenderer* renderer=ownedElement->GetRenderer(); if(renderer) { renderer->SetRenderTarget(0); } } ownedElement=element; if(ownedElement) { IGuiGraphicsRenderer* renderer=ownedElement->GetRenderer(); if(renderer) { renderer->SetRenderTarget(renderTarget); } } } bool GuiGraphicsComposition::GetVisible() { return visible; } void GuiGraphicsComposition::SetVisible(bool value) { visible=value; } GuiGraphicsComposition::MinSizeLimitation GuiGraphicsComposition::GetMinSizeLimitation() { return minSizeLimitation; } void GuiGraphicsComposition::SetMinSizeLimitation(MinSizeLimitation value) { minSizeLimitation=value; } IGuiGraphicsRenderTarget* GuiGraphicsComposition::GetRenderTarget() { return renderTarget; } void GuiGraphicsComposition::SetRenderTarget(IGuiGraphicsRenderTarget* value) { renderTarget=value; if(ownedElement) { IGuiGraphicsRenderer* renderer=ownedElement->GetRenderer(); if(renderer) { renderer->SetRenderTarget(renderTarget); } } for(vint i=0;iSetRenderTarget(renderTarget); } OnRenderTargetChanged(); } void GuiGraphicsComposition::Render(Size offset) { 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; 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;iRender(Size(bounds.x1, bounds.y1)); } } renderTarget->PopClipper(); } } } } } GuiGraphicsEventReceiver* GuiGraphicsComposition::GetEventReceiver() { if(!eventReceiver) { eventReceiver=new GuiGraphicsEventReceiver(this); } return eventReceiver.Obj(); } bool GuiGraphicsComposition::HasEventReceiver() { return eventReceiver; } GuiGraphicsComposition* GuiGraphicsComposition::FindComposition(Point location) { 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); if(childResult) { return childResult; } } return this; } else { return 0; } } 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; } void GuiGraphicsComposition::SetAssociatedControl(controls::GuiControl* control) { if(associatedControl) { for(vint i=0;iOnControlParentChanged(0); } } associatedControl=control; if(associatedControl) { for(vint i=0;iOnControlParentChanged(associatedControl); } } } GuiGraphicsHost* GuiGraphicsComposition::GetAssociatedHost() { return associatedHost; } void GuiGraphicsComposition::SetAssociatedHost(GuiGraphicsHost* host) { associatedHost=host; } 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 0; } GuiGraphicsHost* GuiGraphicsComposition::GetRelatedGraphicsHost() { GuiGraphicsComposition* composition=this; while(composition) { if(composition->GetAssociatedHost()) { return composition->GetAssociatedHost(); } else { composition=composition->GetParent(); } } return 0; } controls::GuiControlHost* GuiGraphicsComposition::GetRelatedControlHost() { GuiGraphicsComposition* composition=this; while(composition) { if(composition->GetAssociatedControl()) { GuiControlHost* controlHost=dynamic_cast(composition->GetAssociatedControl()); if(controlHost) { return controlHost; } } composition=composition->GetParent(); } return 0; } INativeCursor* GuiGraphicsComposition::GetRelatedCursor() { GuiGraphicsComposition* composition=this; while(composition) { if(composition->GetAssociatedCursor()) { return composition->GetAssociatedCursor(); } else { composition=composition->GetParent(); } } return 0; } Margin GuiGraphicsComposition::GetMargin() { return margin; } void GuiGraphicsComposition::SetMargin(Margin value) { margin=value; } Margin GuiGraphicsComposition::GetInternalMargin() { return internalMargin; } void GuiGraphicsComposition::SetInternalMargin(Margin value) { internalMargin=value; } Size GuiGraphicsComposition::GetPreferredMinSize() { return preferredMinSize; } void GuiGraphicsComposition::SetPreferredMinSize(Size value) { preferredMinSize=value; } 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() { for(vint i=0;iForceCalculateSizeImmediately(); } } /*********************************************************************** GuiGraphicsSite ***********************************************************************/ Rect GuiGraphicsSite::GetBoundsInternal(Rect expectedBounds) { Size minSize=GetMinPreferredClientSize(); if(minSize.xGetRenderer(); if(renderer) { minSize=renderer->GetMinSize(); } } } if(minSizeLimitation==GuiGraphicsComposition::LimitToElementAndChildren) { vint childCount=Children().Count(); for(vint i=0;iIsSizeAffectParent()) { Rect childBounds=child->GetPreferredBounds(); if(minSize.xGetBoundsComposition(); if(bounds->GetParent()) { bounds->GetParent()->RemoveChild(bounds); } delete value; } } void SafeDeleteComposition(GuiGraphicsComposition* value) { if(value) { if(value->GetParent()) { value->GetParent()->RemoveChild(value); } if(value->GetAssociatedControl()) { SafeDeleteControl(value->GetAssociatedControl()); } else { for(vint i=value->Children().Count()-1;i>=0;i--) { SafeDeleteComposition(value->Children().Get(i)); } delete 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 ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { using namespace collections; /*********************************************************************** GuiFlowComposition ***********************************************************************/ void GuiFlowComposition::UpdateFlowItemBounds(bool forceUpdate) { if (forceUpdate || needUpdate) { needUpdate = false; auto clientMargin = axis->RealMarginToVirtualMargin(extraMargin); if (clientMargin.left < 0) clientMargin.left = 0; if (clientMargin.top < 0) clientMargin.top = 0; if (clientMargin.right < 0) clientMargin.right = 0; if (clientMargin.bottom < 0) clientMargin.bottom = 0; auto realFullSize = previousBounds.GetSize(); auto clientSize = axis->RealSizeToVirtualSize(realFullSize); clientSize.x -= (clientMargin.left + clientMargin.right); clientSize.y -= (clientMargin.top + clientMargin.bottom); flowItemBounds.Resize(flowItems.Count()); for (vint i = 0; i < flowItems.Count(); i++) { flowItemBounds[i] = Rect(Point(0, 0), flowItems[i]->GetMinSize()); } vint currentIndex = 0; vint rowTop = 0; while (currentIndex < flowItems.Count()) { auto itemSize = axis->RealSizeToVirtualSize(flowItemBounds[currentIndex].GetSize()); vint rowWidth = itemSize.x; vint rowHeight = itemSize.y; vint rowItemCount = 1; for (vint i = currentIndex + 1; i < flowItems.Count(); i++) { itemSize = axis->RealSizeToVirtualSize(flowItemBounds[i].GetSize()); vint itemWidth = itemSize.x + columnPadding; if (rowWidth + itemWidth > clientSize.x) { break; } rowWidth += itemWidth; if (rowHeight < itemSize.y) { rowHeight = itemSize.y; } rowItemCount++; } vint baseLine = 0; Array itemBaseLines(rowItemCount); for (vint i = 0; i < rowItemCount; i++) { vint index = currentIndex + i; vint itemBaseLine = 0; itemSize = axis->RealSizeToVirtualSize(flowItemBounds[index].GetSize()); auto option = flowItems[index]->GetFlowOption(); switch (option.baseline) { case GuiFlowOption::FromTop: itemBaseLine = option.distance; break; case GuiFlowOption::FromBottom: itemBaseLine = itemSize.y - option.distance; break; case GuiFlowOption::Percentage: itemBaseLine = (vint)(itemSize.y*option.percentage); break; } itemBaseLines[i] = itemBaseLine; if (baseLine < itemBaseLine) { baseLine = itemBaseLine; } } vint rowUsedWidth = 0; for (vint i = 0; i < rowItemCount; i++) { vint index = currentIndex + i; itemSize = axis->RealSizeToVirtualSize(flowItemBounds[index].GetSize()); vint itemLeft = 0; vint itemTop = rowTop + baseLine - itemBaseLines[i]; switch (alignment) { case FlowAlignment::Left: itemLeft = rowUsedWidth + i * columnPadding; break; case FlowAlignment::Center: itemLeft = rowUsedWidth + i * columnPadding + (clientSize.x - rowWidth) / 2; break; case FlowAlignment::Extend: if (i == 0) { itemLeft = rowUsedWidth; } else { itemLeft = rowUsedWidth + (vint)((double)(clientSize.x - rowWidth) * i / (rowItemCount - 1)) + i * columnPadding; } break; } flowItemBounds[index] = axis->VirtualRectToRealRect( realFullSize, Rect( Point( itemLeft + clientMargin.left, itemTop + clientMargin.top ), itemSize ) ); rowUsedWidth += itemSize.x; } rowTop += rowHeight + rowPadding; currentIndex += rowItemCount; } minHeight = rowTop == 0 ? 0 : rowTop - rowPadding; } } void GuiFlowComposition::OnBoundsChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) { UpdateFlowItemBounds(true); } void GuiFlowComposition::OnChildInserted(GuiGraphicsComposition* child) { GuiBoundsComposition::OnChildInserted(child); auto item = dynamic_cast(child); if (item && !flowItems.Contains(item)) { flowItems.Add(item); needUpdate = true; } } void GuiFlowComposition::OnChildRemoved(GuiGraphicsComposition* child) { GuiBoundsComposition::OnChildRemoved(child); auto item=dynamic_cast(child); if(item) { flowItems.Remove(item); needUpdate = true; } } GuiFlowComposition::GuiFlowComposition() :axis(new GuiDefaultAxis) { BoundsChanged.AttachMethod(this, &GuiFlowComposition::OnBoundsChanged); } GuiFlowComposition::~GuiFlowComposition() { } const GuiFlowComposition::ItemCompositionList& GuiFlowComposition::GetFlowItems() { return flowItems; } Margin GuiFlowComposition::GetExtraMargin() { return extraMargin; } void GuiFlowComposition::SetExtraMargin(Margin value) { extraMargin = value; needUpdate = true; } vint GuiFlowComposition::GetRowPadding() { return rowPadding; } void GuiFlowComposition::SetRowPadding(vint value) { rowPadding = value; needUpdate = true; } vint GuiFlowComposition::GetColumnPadding() { return columnPadding; } void GuiFlowComposition::SetColumnPadding(vint value) { columnPadding = value; needUpdate = true; } Ptr GuiFlowComposition::GetAxis() { return axis; } void GuiFlowComposition::SetAxis(Ptr value) { if (value) { axis = value; needUpdate = true; } } FlowAlignment GuiFlowComposition::GetAlignment() { return alignment; } void GuiFlowComposition::SetAlignment(FlowAlignment value) { alignment = value; needUpdate = true; } void GuiFlowComposition::ForceCalculateSizeImmediately() { GuiBoundsComposition::ForceCalculateSizeImmediately(); UpdateFlowItemBounds(true); } Size GuiFlowComposition::GetMinPreferredClientSize() { Size minSize = GuiBoundsComposition::GetMinPreferredClientSize(); if (GetMinSizeLimitation() == GuiGraphicsComposition::LimitToElementAndChildren) { auto clientMargin = extraMargin; if (clientMargin.left < 0) clientMargin.left = 0; if (clientMargin.top < 0) clientMargin.top = 0; if (clientMargin.right < 0) clientMargin.right = 0; if (clientMargin.bottom < 0) clientMargin.bottom = 0; auto clientSize = axis->VirtualSizeToRealSize(Size(0, minHeight)); clientSize.x += clientMargin.left + clientMargin.right; clientSize.y += clientMargin.top + clientMargin.bottom; if (minSize.x < clientSize.x) minSize.x = clientSize.x; if (minSize.y < clientSize.y) minSize.y = clientSize.y; } vint x = 0; vint y = 0; if (extraMargin.left > 0) x += extraMargin.left; if (extraMargin.right > 0) x += extraMargin.right; if (extraMargin.top > 0) y += extraMargin.top; if (extraMargin.bottom > 0) y += extraMargin.bottom; return minSize + Size(x, y); } Rect GuiFlowComposition::GetBounds() { if (!needUpdate) { for (vint i = 0; i < flowItems.Count(); i++) { if (flowItemBounds[i].GetSize() != flowItems[i]->GetMinSize()) { needUpdate = true; break; } } } if (needUpdate) { UpdateFlowItemBounds(true); } bounds = GuiBoundsComposition::GetBounds(); return bounds; } /*********************************************************************** GuiFlowItemComposition ***********************************************************************/ void GuiFlowItemComposition::OnParentChanged(GuiGraphicsComposition* oldParent, GuiGraphicsComposition* newParent) { GuiGraphicsSite::OnParentChanged(oldParent, newParent); flowParent = newParent == 0 ? 0 : dynamic_cast(newParent); } Size GuiFlowItemComposition::GetMinSize() { return GetBoundsInternal(bounds).GetSize(); } GuiFlowItemComposition::GuiFlowItemComposition() { SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } GuiFlowItemComposition::~GuiFlowItemComposition() { } bool GuiFlowItemComposition::IsSizeAffectParent() { return false; } Rect GuiFlowItemComposition::GetBounds() { Rect result = bounds; if(flowParent) { flowParent->UpdateFlowItemBounds(false); vint index = flowParent->flowItems.IndexOf(this); if (index != -1) { result = flowParent->flowItemBounds[index]; } result = Rect( result.Left() - extraMargin.left, result.Top() - extraMargin.top, result.Right() + extraMargin.right, result.Bottom() + extraMargin.bottom ); } UpdatePreviousBounds(result); return result; } void GuiFlowItemComposition::SetBounds(Rect value) { bounds = value; } Margin GuiFlowItemComposition::GetExtraMargin() { return extraMargin; } void GuiFlowItemComposition::SetExtraMargin(Margin value) { extraMargin = value; } GuiFlowOption GuiFlowItemComposition::GetFlowOption() { return option; } void GuiFlowItemComposition::SetFlowOption(GuiFlowOption value) { option = value; if (flowParent) { flowParent->needUpdate = true; } } } } } /*********************************************************************** GRAPHICSCOMPOSITION\GUIGRAPHICSSPECIALIZEDCOMPOSITION.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { /*********************************************************************** GuiSideAlignedComposition ***********************************************************************/ GuiSideAlignedComposition::GuiSideAlignedComposition() :direction(Top) ,maxLength(10) ,maxRatio(1.0) { } GuiSideAlignedComposition::~GuiSideAlignedComposition() { } GuiSideAlignedComposition::Direction GuiSideAlignedComposition::GetDirection() { return direction; } void GuiSideAlignedComposition::SetDirection(Direction value) { direction=value; } vint GuiSideAlignedComposition::GetMaxLength() { return maxLength; } void GuiSideAlignedComposition::SetMaxLength(vint value) { if(value<0) value=0; maxLength=value; } double GuiSideAlignedComposition::GetMaxRatio() { return maxRatio; } void GuiSideAlignedComposition::SetMaxRatio(double value) { maxRatio= value<0?0: value>1?1: value; } bool GuiSideAlignedComposition::IsSizeAffectParent() { return false; } Rect GuiSideAlignedComposition::GetBounds() { Rect result; GuiGraphicsComposition* parent=GetParent(); if(parent) { Rect bounds=parent->GetBounds(); vint w=(vint)(bounds.Width()*maxRatio); vint h=(vint)(bounds.Height()*maxRatio); if(w>maxLength) w=maxLength; if(h>maxLength) h=maxLength; switch(direction) { case Left: { bounds.x2=bounds.x1+w; } break; case Top: { bounds.y2=bounds.y1+h; } break; case Right: { bounds.x1=bounds.x2-w; } break; case Bottom: { bounds.y1=bounds.y2-h; } break; } result = bounds; } UpdatePreviousBounds(result); return result; } /*********************************************************************** GuiPartialViewComposition ***********************************************************************/ GuiPartialViewComposition::GuiPartialViewComposition() :wRatio(0.0) ,wPageSize(1.0) ,hRatio(0.0) ,hPageSize(1.0) { } GuiPartialViewComposition::~GuiPartialViewComposition() { } double GuiPartialViewComposition::GetWidthRatio() { return wRatio; } double GuiPartialViewComposition::GetWidthPageSize() { return wPageSize; } double GuiPartialViewComposition::GetHeightRatio() { return hRatio; } double GuiPartialViewComposition::GetHeightPageSize() { return hPageSize; } void GuiPartialViewComposition::SetWidthRatio(double value) { wRatio=value; } void GuiPartialViewComposition::SetWidthPageSize(double value) { wPageSize=value; } void GuiPartialViewComposition::SetHeightRatio(double value) { hRatio=value; } void GuiPartialViewComposition::SetHeightPageSize(double value) { hPageSize=value; } bool GuiPartialViewComposition::IsSizeAffectParent() { return false; } Rect GuiPartialViewComposition::GetBounds() { Rect result; GuiGraphicsComposition* parent=GetParent(); if(parent) { Rect bounds=parent->GetBounds(); vint w=bounds.Width(); vint h=bounds.Height(); vint pw=(vint)(wPageSize*w); vint ph=(vint)(hPageSize*h); vint ow=preferredMinSize.x-pw; if(ow<0) ow=0; vint oh=preferredMinSize.y-ph; if(oh<0) oh=0; w-=ow; h-=oh; pw+=ow; ph+=oh; result = Rect(Point((vint)(wRatio*w), (vint)(hRatio*h)), Size(pw, ph)); } UpdatePreviousBounds(result); return result; } } } } /*********************************************************************** GRAPHICSCOMPOSITION\GUIGRAPHICSSTACKCOMPOSITION.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { /*********************************************************************** GuiStackComposition ***********************************************************************/ void GuiStackComposition::UpdateStackItemBounds() { if (stackItemBounds.Count() != stackItems.Count()) { stackItemBounds.Resize(stackItems.Count()); } stackItemTotalSize = Size(0, 0); Point offset; for (vint i = 0; i < stackItems.Count(); i++) { vint offsetX = 0; vint offsetY = 0; Size itemSize = stackItems[i]->GetMinSize(); stackItemBounds[i] = Rect(offset, itemSize); #define ACCUMULATE(U, V) \ { \ if (stackItemTotalSize.V < itemSize.V) \ { \ stackItemTotalSize.V = itemSize.V; \ } \ if (i > 0) \ { \ stackItemTotalSize.U += padding; \ } \ stackItemTotalSize.U += itemSize.U; \ } \ switch (direction) { case GuiStackComposition::Horizontal: case GuiStackComposition::ReversedHorizontal: ACCUMULATE(x, y) break; case GuiStackComposition::Vertical: case GuiStackComposition::ReversedVertical: ACCUMULATE(y, x) break; } #undef ACCUMULATE offset.x += itemSize.x + padding; offset.y += itemSize.y + padding; } EnsureStackItemVisible(); } void GuiStackComposition::EnsureStackItemVisible() { #define ADJUSTMENT(U, V) \ if (itemBounds.U() <= 0) \ { \ adjustment -= itemBounds.U(); \ } \ else \ { \ vint overflow = itemBounds.V() - previousBounds.V(); \ if (overflow > 0) \ { \ adjustment -= overflow; \ } \ } \ if (ensuringVisibleStackItem) { Rect itemBounds = ensuringVisibleStackItem->GetBounds(); switch (direction) { case Horizontal: case ReversedHorizontal: ADJUSTMENT(Left, Right) break; case Vertical: case ReversedVertical: ADJUSTMENT(Top, Bottom) break; } } #undef ADJUSTMENT } void GuiStackComposition::OnBoundsChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) { EnsureStackItemVisible(); } void GuiStackComposition::OnChildInserted(GuiGraphicsComposition* child) { GuiBoundsComposition::OnChildInserted(child); GuiStackItemComposition* item = dynamic_cast(child); if (item) { if (!stackItems.Contains(item)) { stackItems.Add(item); } UpdateStackItemBounds(); } } void GuiStackComposition::OnChildRemoved(GuiGraphicsComposition* child) { GuiBoundsComposition::OnChildRemoved(child); GuiStackItemComposition* item=dynamic_cast(child); if(item) { stackItems.Remove(item); if (item == ensuringVisibleStackItem) { ensuringVisibleStackItem = 0; } UpdateStackItemBounds(); } } GuiStackComposition::GuiStackComposition() { BoundsChanged.AttachMethod(this, &GuiStackComposition::OnBoundsChanged); } GuiStackComposition::~GuiStackComposition() { } const GuiStackComposition::ItemCompositionList& GuiStackComposition::GetStackItems() { return stackItems; } bool GuiStackComposition::InsertStackItem(vint index, GuiStackItemComposition* item) { index=stackItems.Insert(index, item); if(!AddChild(item)) { stackItems.RemoveAt(index); return false; } else { return true; } } GuiStackComposition::Direction GuiStackComposition::GetDirection() { return direction; } void GuiStackComposition::SetDirection(Direction value) { direction = value; EnsureStackItemVisible(); } vint GuiStackComposition::GetPadding() { return padding; } void GuiStackComposition::SetPadding(vint value) { padding = value; EnsureStackItemVisible(); } void GuiStackComposition::ForceCalculateSizeImmediately() { GuiBoundsComposition::ForceCalculateSizeImmediately(); UpdateStackItemBounds(); } Size GuiStackComposition::GetMinPreferredClientSize() { Size minSize = GuiBoundsComposition::GetMinPreferredClientSize(); if (GetMinSizeLimitation() == GuiGraphicsComposition::LimitToElementAndChildren) { if (!ensuringVisibleStackItem || direction == Vertical || direction == ReversedVertical) { if (minSize.x < stackItemTotalSize.x) { minSize.x = stackItemTotalSize.x; } } if (!ensuringVisibleStackItem || direction == Horizontal || direction == ReversedHorizontal) { if (minSize.y < stackItemTotalSize.y) { minSize.y = stackItemTotalSize.y; } } } vint x = 0; vint y = 0; if (extraMargin.left > 0) x += extraMargin.left; if (extraMargin.right > 0) x += extraMargin.right; if (extraMargin.top > 0) y += extraMargin.top; if (extraMargin.bottom > 0) y += extraMargin.bottom; return minSize + Size(x, y); } Rect GuiStackComposition::GetBounds() { for (vint i = 0; i < stackItems.Count(); i++) { if (stackItemBounds[i].GetSize() != stackItems[i]->GetMinSize()) { UpdateStackItemBounds(); break; } } Rect bounds = GuiBoundsComposition::GetBounds(); previousBounds = bounds; UpdatePreviousBounds(previousBounds); return bounds; } Margin GuiStackComposition::GetExtraMargin() { return extraMargin; } void GuiStackComposition::SetExtraMargin(Margin value) { extraMargin=value; EnsureStackItemVisible(); } bool GuiStackComposition::IsStackItemClipped() { Rect clientArea = GetClientArea(); switch(direction) { case Horizontal: case ReversedHorizontal: { vint width = stackItemTotalSize.x + (extraMargin.left > 0 ? extraMargin.left : 0) + (extraMargin.right > 0 ? extraMargin.right : 0) ; return width > clientArea.Width(); } break; case Vertical: case ReversedVertical: { vint height = stackItemTotalSize.y + (extraMargin.top > 0 ? extraMargin.top : 0) + (extraMargin.bottom > 0 ? extraMargin.bottom : 0) ; return height > clientArea.Height(); } break; } return false; } bool GuiStackComposition::EnsureVisible(vint index) { if (0 <= index && index < stackItems.Count()) { ensuringVisibleStackItem = stackItems[index]; } else { ensuringVisibleStackItem = 0; } EnsureStackItemVisible(); return ensuringVisibleStackItem != 0; } /*********************************************************************** GuiStackItemComposition ***********************************************************************/ void GuiStackItemComposition::OnParentChanged(GuiGraphicsComposition* oldParent, GuiGraphicsComposition* newParent) { GuiGraphicsSite::OnParentChanged(oldParent, newParent); stackParent = newParent == 0 ? 0 : dynamic_cast(newParent); } Size GuiStackItemComposition::GetMinSize() { return GetBoundsInternal(bounds).GetSize(); } GuiStackItemComposition::GuiStackItemComposition() :stackParent(0) { SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } GuiStackItemComposition::~GuiStackItemComposition() { } bool GuiStackItemComposition::IsSizeAffectParent() { return false; } Rect GuiStackItemComposition::GetBounds() { Rect result = bounds; if(stackParent) { vint index = stackParent->stackItems.IndexOf(this); if (index != -1) { result = stackParent->stackItemBounds[index]; } Rect parentBounds = stackParent->previousBounds; Margin margin = stackParent->extraMargin; if (margin.left <= 0) margin.left = 0; if (margin.top <= 0) margin.top = 0; if (margin.right <= 0) margin.right = 0; if (margin.bottom <= 0) margin.bottom = 0; auto x = result.Left(); auto y = result.Top(); auto w = result.Width(); auto h = result.Height(); switch (stackParent->direction) { case GuiStackComposition::Horizontal: x += margin.left + stackParent->adjustment; y = margin.top; h = parentBounds.Height() - margin.top - margin.bottom; break; case GuiStackComposition::ReversedHorizontal: x = parentBounds.Width() - margin.right - x - w + stackParent->adjustment; y = margin.top; h = parentBounds.Height() - margin.top - margin.bottom; break; case GuiStackComposition::Vertical: x = margin.left; y += margin.top + stackParent->adjustment; w = parentBounds.Width() - margin.left - margin.right; break; case GuiStackComposition::ReversedVertical: x = margin.left; y = parentBounds.Height() - margin.bottom - y - h + stackParent->adjustment; w = parentBounds.Width() - margin.left - margin.right; break; } result = Rect( x - extraMargin.left, y - extraMargin.top, x + w + extraMargin.right, y + h + extraMargin.bottom ); } UpdatePreviousBounds(result); return result; } void GuiStackItemComposition::SetBounds(Rect value) { bounds = value; } Margin GuiStackItemComposition::GetExtraMargin() { return extraMargin; } void GuiStackItemComposition::SetExtraMargin(Margin value) { extraMargin = value; } } } } /*********************************************************************** GRAPHICSCOMPOSITION\GUIGRAPHICSTABLECOMPOSITION.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { using namespace collections; using namespace controls; using namespace elements; /*********************************************************************** GuiTableComposition ***********************************************************************/ namespace update_cell_bounds_helpers { vint First(vint a, vint b) { return a; } vint Second(vint a, vint b) { return b; } vint X(Size s) { return s.x; } vint Y(Size s) { return s.y; } vint RL(GuiCellComposition* cell) { return cell->GetRow(); } vint CL(GuiCellComposition* cell) { return cell->GetColumn(); } vint RS(GuiCellComposition* cell) { return cell->GetRowSpan(); } vint CS(GuiCellComposition* cell) { return cell->GetColumnSpan(); } } using namespace update_cell_bounds_helpers; vint GuiTableComposition::GetSiteIndex(vint _rows, vint _columns, vint _row, vint _column) { return _row*_columns+_column; } void GuiTableComposition::SetSitedCell(vint _row, vint _column, GuiCellComposition* cell) { cellCompositions[GetSiteIndex(rows, columns, _row, _column)]=cell; } void GuiTableComposition::UpdateCellBoundsInternal( collections::Array& dimSizes, vint& dimSize, vint& dimSizeWithPercentage, collections::Array& dimOptions, vint GuiTableComposition::* dim1, vint GuiTableComposition::* dim2, vint (*getSize)(Size), vint (*getLocation)(GuiCellComposition*), vint (*getSpan)(GuiCellComposition*), vint (*getRow)(vint, vint), vint (*getCol)(vint, vint), vint maxPass ) { for(vint pass=0;pass*dim1;i++) { GuiCellOption option=dimOptions[i]; if(pass==0) { dimSizes[i]=0; } switch(option.composeType) { case GuiCellOption::Absolute: { dimSizes[i]=option.absolute; } break; case GuiCellOption::MinSize: { for(vint j=0;j*dim2;j++) { GuiCellComposition* cell=GetSitedCell(getRow(i, j), getCol(i, j)); if(cell) { bool accept=false; if(pass==0) { accept=getSpan(cell)==1; } else { accept=getLocation(cell)+getSpan(cell)==i+1; } if(accept) { vint size=getSize(cell->GetPreferredBounds().GetSize()); vint span=getSpan(cell); for(vint k=1;k*dim1;i++) { GuiCellOption option=dimOptions[i]; if(option.composeType==GuiCellOption::Percentage) { if(0.001*dim1;i++) { GuiCellOption option=dimOptions[i]; if(option.composeType==GuiCellOption::Percentage) { if(0.001*dim2;j++) { GuiCellComposition* cell=GetSitedCell(getRow(i, j), getCol(i, j)); if(cell) { vint size=getSize(cell->GetPreferredBounds().GetSize()); vint start=getLocation(cell); vint span=getSpan(cell); size-=(span-1)*cellPadding; double totalPercentage=0; for(vint k=start;k*dim1;i++) { GuiCellOption option=dimOptions[i]; if(option.composeType==GuiCellOption::Percentage) { if(0.001*dim1;i++) { GuiCellOption option=dimOptions[i]; if(option.composeType==GuiCellOption::Percentage) { if(0.001*dim1;i++) { GuiCellOption option=dimOptions[i]; if(option.composeType==GuiCellOption::Percentage) { if(0.001*dim1;i++) { if(dimOptions[i].composeType!=GuiCellOption::Percentage) { dimSize+=dimSizes[i]; } dimSizeWithPercentage+=dimSizes[i]; } } void GuiTableComposition::UpdateCellBoundsPercentages( collections::Array& dimSizes, vint dimSize, vint maxDimSize, collections::Array& dimOptions ) { if(maxDimSize>dimSize) { double totalPercentage=0; vint percentageCount=0; for(vint i=0;i0 && totalPercentage>0.001) { for(vint i=0;i& offsets, collections::Array& sizes, vint max ) { offsets[0]=0; for(vint i=1;i rowSizes, columnSizes; rowSizes.Resize(rows); columnSizes.Resize(columns); { vint rowTotal = (rows - 1) * cellPadding; vint columnTotal = (columns - 1) * cellPadding; vint rowTotalWithPercentage=rowTotal; vint columnTotalWithPercentage=columnTotal; UpdateCellBoundsInternal( rowSizes, rowTotal, rowTotalWithPercentage, rowOptions, &GuiTableComposition::rows, &GuiTableComposition::columns, &Y, &RL, &RS, &First, &Second, 2 ); UpdateCellBoundsInternal( columnSizes, columnTotal, columnTotalWithPercentage, columnOptions, &GuiTableComposition::columns, &GuiTableComposition::rows, &X, &CL, &CS, &Second, &First, 2 ); tableContentMinSize=Size(columnTotalWithPercentage, rowTotalWithPercentage); } if(previousContentMinSize!=tableContentMinSize) { previousContentMinSize=tableContentMinSize; UpdateCellBoundsInternal(); } } void GuiTableComposition::OnRenderTargetChanged() { if(GetRenderTarget()) { UpdateTableContentMinSize(); } } GuiTableComposition::GuiTableComposition() :rows(0) , columns(0) , cellPadding(0) , borderVisible(true) , rowExtending(0) , columnExtending(0) { ConfigChanged.SetAssociatedComposition(this); SetRowsAndColumns(1, 1); } GuiTableComposition::~GuiTableComposition() { } vint GuiTableComposition::GetRows() { return rows; } vint GuiTableComposition::GetColumns() { return columns; } bool GuiTableComposition::SetRowsAndColumns(vint _rows, vint _columns) { if(_rows<=0 || _columns<=0) return false; rowOptions.Resize(_rows); columnOptions.Resize(_columns); cellCompositions.Resize(_rows*_columns); cellBounds.Resize(_rows*_columns); for(vint i=0;i<_rows*_columns;i++) { cellCompositions[i]=0; cellBounds[i]=Rect(); } rows=_rows; columns=_columns; vint childCount=Children().Count(); for(vint i=0;i(Children().Get(i)); if(cell) { cell->OnTableRowsAndColumnsChanged(); } } ConfigChanged.Execute(GuiEventArgs(this)); UpdateCellBounds(); return true; } GuiCellComposition* GuiTableComposition::GetSitedCell(vint _row, vint _column) { return cellCompositions[GetSiteIndex(rows, columns, _row, _column)]; } GuiCellOption GuiTableComposition::GetRowOption(vint _row) { return rowOptions[_row]; } void GuiTableComposition::SetRowOption(vint _row, GuiCellOption option) { rowOptions[_row]=option; ConfigChanged.Execute(GuiEventArgs(this)); } GuiCellOption GuiTableComposition::GetColumnOption(vint _column) { return columnOptions[_column]; } void GuiTableComposition::SetColumnOption(vint _column, GuiCellOption option) { columnOptions[_column]=option; ConfigChanged.Execute(GuiEventArgs(this)); } vint GuiTableComposition::GetCellPadding() { return cellPadding; } void GuiTableComposition::SetCellPadding(vint value) { if(value<0) value=0; cellPadding=value; } bool GuiTableComposition::GetBorderVisible() { return borderVisible; } void GuiTableComposition::SetBorderVisible(bool value) { if (borderVisible != value) { borderVisible = value; UpdateCellBounds(); } } Rect GuiTableComposition::GetCellArea() { Rect bounds(Point(0, 0), GuiBoundsComposition::GetBounds().GetSize()); vint borderThickness = borderVisible ? cellPadding : 0; bounds.x1 += margin.left + internalMargin.left + borderThickness; bounds.y1 += margin.top + internalMargin.top + borderThickness; bounds.x2 -= margin.right + internalMargin.right + borderThickness; bounds.y2 -= margin.bottom + internalMargin.bottom + borderThickness; if (bounds.x2 < bounds.x1) bounds.x2 = bounds.x1; if (bounds.y2 < bounds.y1) bounds.y2 = bounds.y1; return bounds; } void GuiTableComposition::UpdateCellBounds() { UpdateCellBoundsInternal(); UpdateTableContentMinSize(); } void GuiTableComposition::ForceCalculateSizeImmediately() { GuiBoundsComposition::ForceCalculateSizeImmediately(); UpdateCellBounds(); UpdateCellBounds(); } Size GuiTableComposition::GetMinPreferredClientSize() { vint offset = (borderVisible ? 2 * cellPadding : 0); return Size(tableContentMinSize.x + offset, tableContentMinSize.y + offset); } Rect GuiTableComposition::GetBounds() { Rect result; if(!IsAlignedToParent() && GetMinSizeLimitation()!=GuiGraphicsComposition::NoLimit) { result=Rect(compositionBounds.LeftTop(), compositionBounds.GetSize()-Size(columnExtending, rowExtending)); } else { result=GuiBoundsComposition::GetBounds(); } bool cellMinSizeModified=false; SortedList cells; FOREACH(GuiCellComposition*, cell, cellCompositions) { if(cell && !cells.Contains(cell)) { cells.Add(cell); Size newSize=cell->GetPreferredBounds().GetSize(); if(cell->lastPreferredSize!=newSize) { cell->lastPreferredSize=newSize; cellMinSizeModified=true; } } } if(previousBounds!=result || cellMinSizeModified) { previousBounds=result; UpdateCellBounds(); } return result; } /*********************************************************************** GuiCellComposition ***********************************************************************/ void GuiCellComposition::ClearSitedCells(GuiTableComposition* table) { if(row!=-1 && column!=-1) { for(vint r=0;rSetSitedCell(row+r, column+c, 0); } } } } void GuiCellComposition::SetSitedCells(GuiTableComposition* table) { for(vint r=0;rSetSitedCell(row+r, column+c, this); } } } void GuiCellComposition::ResetSiteInternal() { row=-1; column=-1; rowSpan=1; columnSpan=1; } bool GuiCellComposition::SetSiteInternal(vint _row, vint _column, vint _rowSpan, vint _columnSpan) { if (tableParent) { if(_row<0 || _row>=tableParent->rows || _column<0 || _column>=tableParent->columns) return false; if(_rowSpan<1 || _row+_rowSpan>tableParent->rows || _columnSpan<1 || _column+_columnSpan>tableParent->columns) return false; for(vint r=0;r<_rowSpan;r++) { for(vint c=0;c<_columnSpan;c++) { GuiCellComposition* cell=tableParent->GetSitedCell(_row+r, _column+c); if(cell && cell!=this) { return false; } } } ClearSitedCells(tableParent); } row=_row; column=_column; rowSpan=_rowSpan; columnSpan=_columnSpan; if (tableParent) { SetSitedCells(tableParent); } return true; } void GuiCellComposition::OnParentChanged(GuiGraphicsComposition* oldParent, GuiGraphicsComposition* newParent) { GuiGraphicsSite::OnParentChanged(oldParent, newParent); if(tableParent) { ClearSitedCells(tableParent); } tableParent=dynamic_cast(newParent); if(!tableParent || !SetSiteInternal(row, column, rowSpan, columnSpan)) { ResetSiteInternal(); } if(tableParent) { if (row != -1 && column != -1) { SetSiteInternal(row, column, rowSpan, columnSpan); } tableParent->UpdateCellBounds(); } } void GuiCellComposition::OnTableRowsAndColumnsChanged() { if(!SetSiteInternal(row, column, rowSpan, columnSpan)) { ResetSiteInternal(); } } GuiCellComposition::GuiCellComposition() :row(-1) ,column(-1) ,rowSpan(1) ,columnSpan(1) ,tableParent(0) { SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } GuiCellComposition::~GuiCellComposition() { } GuiTableComposition* GuiCellComposition::GetTableParent() { return tableParent; } vint GuiCellComposition::GetRow() { return row; } vint GuiCellComposition::GetRowSpan() { return rowSpan; } vint GuiCellComposition::GetColumn() { return column; } vint GuiCellComposition::GetColumnSpan() { return columnSpan; } bool GuiCellComposition::SetSite(vint _row, vint _column, vint _rowSpan, vint _columnSpan) { if(SetSiteInternal(_row, _column, _rowSpan, _columnSpan)) { if (tableParent) { tableParent->UpdateCellBounds(); } return true; } else { return false; } } Rect GuiCellComposition::GetBounds() { Rect result; if(tableParent && row!=-1 && column!=-1) { Rect bounds1, bounds2; { vint index=tableParent->GetSiteIndex(tableParent->rows, tableParent->columns, row, column); bounds1=tableParent->cellBounds[index]; } { vint index=tableParent->GetSiteIndex(tableParent->rows, tableParent->columns, row+rowSpan-1, column+columnSpan-1); bounds2=tableParent->cellBounds[index]; if(tableParent->GetMinSizeLimitation()==GuiGraphicsComposition::NoLimit) { if(row+rowSpan==tableParent->rows) { bounds2.y2+=tableParent->rowExtending; } if(column+columnSpan==tableParent->columns) { bounds2.x2+=tableParent->columnExtending; } } } vint offset = tableParent->borderVisible ? tableParent->cellPadding : 0; result = Rect(bounds1.x1 + offset, bounds1.y1 + offset, bounds2.x2 + offset, bounds2.y2 + offset); } else { result = Rect(); } UpdatePreviousBounds(result); return result; } /*********************************************************************** GuiTableSplitterCompositionBase ***********************************************************************/ void GuiTableSplitterCompositionBase::OnParentChanged(GuiGraphicsComposition* oldParent, GuiGraphicsComposition* newParent) { GuiGraphicsSite::OnParentChanged(oldParent, newParent); tableParent = dynamic_cast(newParent); } void GuiTableSplitterCompositionBase::OnLeftButtonDown(GuiGraphicsComposition* sender, GuiMouseEventArgs& arguments) { dragging = true; draggingPoint = Point(arguments.x, arguments.y); } void GuiTableSplitterCompositionBase::OnLeftButtonUp(GuiGraphicsComposition* sender, GuiMouseEventArgs& arguments) { dragging = false; } void GuiTableSplitterCompositionBase::OnMouseMoveHelper( vint cellsBefore, vint GuiTableComposition::* cells, collections::Array& cellSizes, vint offset, GuiCellOption(GuiTableComposition::*getOption)(vint), void(GuiTableComposition::*setOption)(vint, GuiCellOption) ) { if (dragging) { if (tableParent) { if (0 < cellsBefore && cellsBefore < tableParent->*cells) { auto o1 = (tableParent->*getOption)(cellsBefore - 1); auto o2 = (tableParent->*getOption)(cellsBefore); vint indexStart = -1; vint indexEnd = -1; vint indexStep = -1; vint max = 0; if (offset < 0) { indexStart = cellsBefore - 1; indexEnd = -1; indexStep = -1; } else if (offset > 0) { indexStart = cellsBefore; indexEnd = tableParent->*cells; indexStep = 1; } else { return; } { auto o = (tableParent->*getOption)(indexStart); if (o.composeType == GuiCellOption::Absolute) { max = o.absolute - 1; } else { for (vint i = indexStart; i != indexEnd; i += indexStep) { o = (tableParent->*getOption)(i); if (o.composeType == GuiCellOption::Absolute) { break; } else if (o.composeType == GuiCellOption::Percentage) { max += cellSizes[i] - 1; } } } if (max <= 0) { return; } } if (offset < 0) { if (max < -offset) { offset = -max; } } else { if (max < offset) { offset = max; } } if (o1.composeType == GuiCellOption::Absolute) { o1.absolute += offset; (tableParent->*setOption)(cellsBefore - 1, o1); } if (o2.composeType == GuiCellOption::Absolute) { o2.absolute -= offset; (tableParent->*setOption)(cellsBefore, o2); } tableParent->ForceCalculateSizeImmediately(); } } } } Rect GuiTableSplitterCompositionBase::GetBoundsHelper( vint cellsBefore, vint GuiTableComposition::* cells, vint(Rect::* dimSize)()const, collections::Array& cellOffsets, vint Rect::* dimU1, vint Rect::* dimU2, vint Rect::* dimV1, vint Rect::* dimV2 ) { Rect result(0, 0, 0, 0); if (tableParent) { if (0 < cellsBefore && cellsBefore < tableParent->*cells) { vint offset = tableParent->borderVisible ? tableParent->cellPadding : 0; result.*dimU1 = offset; result.*dimU2 = offset + (tableParent->GetCellArea().*dimSize)(); result.*dimV1 = offset + cellOffsets[cellsBefore] - tableParent->cellPadding; result.*dimV2 = (result.*dimV1) + tableParent->cellPadding; } } UpdatePreviousBounds(result); return result; } GuiTableSplitterCompositionBase::GuiTableSplitterCompositionBase() :tableParent(0) , dragging(false) { SetAssociatedCursor(GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::SizeNS)); GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiTableSplitterCompositionBase::OnLeftButtonDown); GetEventReceiver()->leftButtonUp.AttachMethod(this, &GuiTableSplitterCompositionBase::OnLeftButtonUp); } GuiTableSplitterCompositionBase::~GuiTableSplitterCompositionBase() { } GuiTableComposition* GuiTableSplitterCompositionBase::GetTableParent() { return tableParent; } /*********************************************************************** GuiRowSplitterComposition ***********************************************************************/ void GuiRowSplitterComposition::OnMouseMove(GuiGraphicsComposition* sender, GuiMouseEventArgs& arguments) { OnMouseMoveHelper( rowsToTheTop, &GuiTableComposition::rows, tableParent->rowSizes, arguments.y - draggingPoint.y, &GuiTableComposition::GetRowOption, &GuiTableComposition::SetRowOption ); } GuiRowSplitterComposition::GuiRowSplitterComposition() :rowsToTheTop(0) { SetAssociatedCursor(GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::SizeNS)); GetEventReceiver()->mouseMove.AttachMethod(this, &GuiRowSplitterComposition::OnMouseMove); } GuiRowSplitterComposition::~GuiRowSplitterComposition() { } vint GuiRowSplitterComposition::GetRowsToTheTop() { return rowsToTheTop; } void GuiRowSplitterComposition::SetRowsToTheTop(vint value) { rowsToTheTop = value; } Rect GuiRowSplitterComposition::GetBounds() { return GetBoundsHelper( rowsToTheTop, &GuiTableComposition::rows, &Rect::Width, tableParent->rowOffsets, &Rect::x1, &Rect::x2, &Rect::y1, &Rect::y2 ); } /*********************************************************************** GuiColumnSplitterComposition ***********************************************************************/ void GuiColumnSplitterComposition::OnMouseMove(GuiGraphicsComposition* sender, GuiMouseEventArgs& arguments) { OnMouseMoveHelper( columnsToTheLeft, &GuiTableComposition::columns, tableParent->columnSizes, arguments.x - draggingPoint.x, &GuiTableComposition::GetColumnOption, &GuiTableComposition::SetColumnOption ); } GuiColumnSplitterComposition::GuiColumnSplitterComposition() :columnsToTheLeft(0) { SetAssociatedCursor(GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::SizeWE)); GetEventReceiver()->mouseMove.AttachMethod(this, &GuiColumnSplitterComposition::OnMouseMove); } GuiColumnSplitterComposition::~GuiColumnSplitterComposition() { } vint GuiColumnSplitterComposition::GetColumnsToTheLeft() { return columnsToTheLeft; } void GuiColumnSplitterComposition::SetColumnsToTheLeft(vint value) { columnsToTheLeft = value; } Rect GuiColumnSplitterComposition::GetBounds() { return GetBoundsHelper( columnsToTheLeft, &GuiTableComposition::columns, &Rect::Height, tableParent->columnOffsets, &Rect::y1, &Rect::y2, &Rect::x1, &Rect::x2 ); } } } } /*********************************************************************** GRAPHICSELEMENT\GUIGRAPHICSDOCUMENTELEMENT.CPP ***********************************************************************/ namespace vl { using namespace collections; namespace presentation { namespace elements { /*********************************************************************** SetPropertiesVisitor ***********************************************************************/ namespace visitors { class SetPropertiesVisitor : public Object, public DocumentRun::IVisitor { typedef GuiDocumentElement::GuiDocumentElementRenderer Renderer; typedef DocumentModel::ResolvedStyle ResolvedStyle; public: vint start; vint length; vint selectionBegin; vint selectionEnd; List styles; DocumentModel* model; Renderer* renderer; Ptr cache; IGuiGraphicsParagraph* paragraph; SetPropertiesVisitor(DocumentModel* _model, Renderer* _renderer, Ptr _cache, vint _selectionBegin, vint _selectionEnd) :start(0) ,length(0) ,model(_model) ,renderer(_renderer) ,cache(_cache) ,paragraph(_cache->graphicsParagraph.Obj()) ,selectionBegin(_selectionBegin) ,selectionEnd(_selectionEnd) { ResolvedStyle style; style=model->GetStyle(DocumentModel::DefaultStyleName, style); styles.Add(style); } void VisitContainer(DocumentContainerRun* run) { FOREACH(Ptr, subRun, run->runs) { subRun->Accept(this); } } void ApplyStyle(vint start, vint length, const ResolvedStyle& style) { paragraph->SetFont(start, length, style.style.fontFamily); paragraph->SetSize(start, length, style.style.size); paragraph->SetStyle(start, length, (IGuiGraphicsParagraph::TextStyle) ( (style.style.bold?IGuiGraphicsParagraph::Bold:0) | (style.style.italic?IGuiGraphicsParagraph::Italic:0) | (style.style.underline?IGuiGraphicsParagraph::Underline:0) | (style.style.strikeline?IGuiGraphicsParagraph::Strikeline:0) )); } void ApplyColor(vint start, vint length, const ResolvedStyle& style) { paragraph->SetColor(start, length, style.color); paragraph->SetBackgroundColor(start, length, style.backgroundColor); } void Visit(DocumentTextRun* run)override { length=run->GetRepresentationText().Length(); if(length>0) { ResolvedStyle style=styles[styles.Count()-1]; ApplyStyle(start, length, style); ApplyColor(start, length, style); vint styleStart=start; vint styleEnd=styleStart+length; if(styleStartselectionBegin?styleStart:selectionBegin; vint s3=selectionEndGetStyle(DocumentModel::SelectionStyleName, style); ApplyColor(s2, s3-s2, selectionStyle); } } } start+=length; } void Visit(DocumentStylePropertiesRun* run)override { ResolvedStyle style=styles[styles.Count()-1]; style=model->GetStyle(run->style, style); styles.Add(style); VisitContainer(run); styles.RemoveAt(styles.Count()-1); } void Visit(DocumentStyleApplicationRun* run)override { ResolvedStyle style=styles[styles.Count()-1]; style=model->GetStyle(run->styleName, style); styles.Add(style); VisitContainer(run); styles.RemoveAt(styles.Count()-1); } void Visit(DocumentHyperlinkRun* run)override { ResolvedStyle style=styles[styles.Count()-1]; style=model->GetStyle(run->styleName, style); styles.Add(style); VisitContainer(run); styles.RemoveAt(styles.Count()-1); } void Visit(DocumentImageRun* run)override { length=run->GetRepresentationText().Length(); Ptr element=GuiImageFrameElement::Create(); element->SetImage(run->image, run->frameIndex); element->SetStretch(true); IGuiGraphicsParagraph::InlineObjectProperties properties; properties.size=run->size; properties.baseline=run->baseline; properties.breakCondition=IGuiGraphicsParagraph::Alone; properties.backgroundImage = element; paragraph->SetInlineObject(start, length, properties); if(startGetStyle(DocumentModel::SelectionStyleName, style); ApplyColor(start, length, selectionStyle); } start+=length; } void Visit(DocumentEmbeddedObjectRun* run)override { length=run->GetRepresentationText().Length(); IGuiGraphicsParagraph::InlineObjectProperties properties; properties.breakCondition=IGuiGraphicsParagraph::Alone; if (run->name != L"") { vint index = renderer->nameCallbackIdMap.Keys().IndexOf(run->name); if (index != -1) { auto id = renderer->nameCallbackIdMap.Values()[index]; index = cache->embeddedObjects.Keys().IndexOf(id); if (index != -1) { auto eo = cache->embeddedObjects.Values()[index]; if (eo->start == start) { properties.size = eo->size; properties.callbackId = id; } } } else { auto eo = MakePtr(); eo->name = run->name; eo->size = Size(0, 0); eo->start = start; vint id = -1; vint count = renderer->freeCallbackIds.Count(); if (count > 0) { id = renderer->freeCallbackIds[count - 1]; renderer->freeCallbackIds.RemoveAt(count - 1); } else { id = renderer->usedCallbackIds++; } renderer->nameCallbackIdMap.Add(eo->name, id); cache->embeddedObjects.Add(id, eo); properties.callbackId = id; } } paragraph->SetInlineObject(start, length, properties); if(startGetStyle(DocumentModel::SelectionStyleName, style); ApplyColor(start, length, selectionStyle); } start+=length; } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static vint SetProperty(DocumentModel* model, Renderer* renderer, Ptr cache, Ptr run, vint selectionBegin, vint selectionEnd) { SetPropertiesVisitor visitor(model, renderer, cache, selectionBegin, selectionEnd); run->Accept(&visitor); return visitor.length; } }; } using namespace visitors; /*********************************************************************** GuiDocumentElement::GuiDocumentElementRenderer ***********************************************************************/ Size GuiDocumentElement::GuiDocumentElementRenderer::OnRenderInlineObject(vint callbackId, Rect location) { if (element->callback) { auto cache = paragraphCaches[renderingParagraph]; auto relativeLocation = Rect(Point(location.x1 + renderingParagraphOffset.x, location.y1 + renderingParagraphOffset.y), location.GetSize()); auto eo = cache->embeddedObjects[callbackId]; auto size = element->callback->OnRenderEmbeddedObject(eo->name, relativeLocation); eo->resized = eo->size != size; eo->size = size; return eo->size; } else { return Size(); } } void GuiDocumentElement::GuiDocumentElementRenderer::InitializeInternal() { } void GuiDocumentElement::GuiDocumentElementRenderer::FinalizeInternal() { } void GuiDocumentElement::GuiDocumentElementRenderer::RenderTargetChangedInternal(IGuiGraphicsRenderTarget* oldRenderTarget, IGuiGraphicsRenderTarget* newRenderTarget) { for(vint i=0;igraphicsParagraph=0; } } } Ptr GuiDocumentElement::GuiDocumentElementRenderer::EnsureAndGetCache(vint paragraphIndex, bool createParagraph) { if(paragraphIndex<0 || paragraphIndex>=paragraphCaches.Count()) return 0; Ptr paragraph=element->document->paragraphs[paragraphIndex]; Ptr cache=paragraphCaches[paragraphIndex]; if(!cache) { cache=new ParagraphCache; cache->fullText=paragraph->GetText(false); paragraphCaches[paragraphIndex]=cache; } if(createParagraph) { if(!cache->graphicsParagraph) { cache->graphicsParagraph=layoutProvider->CreateParagraph(cache->fullText, renderTarget, this); cache->graphicsParagraph->SetParagraphAlignment(paragraph->alignment ? paragraph->alignment.Value() : Alignment::Left); SetPropertiesVisitor::SetProperty(element->document.Obj(), this, cache, paragraph, cache->selectionBegin, cache->selectionEnd); } if(cache->graphicsParagraph->GetMaxWidth()!=lastMaxWidth) { cache->graphicsParagraph->SetMaxWidth(lastMaxWidth); } vint paragraphHeight=paragraphHeights[paragraphIndex]; vint height=cache->graphicsParagraph->GetHeight(); if(paragraphHeight!=height) { cachedTotalHeight+=height-paragraphHeight; paragraphHeight=height; paragraphHeights[paragraphIndex]=paragraphHeight; minSize=Size(0, cachedTotalHeight); } } return cache; } bool GuiDocumentElement::GuiDocumentElementRenderer::GetParagraphIndexFromPoint(Point point, vint& top, vint& index) { vint y=0; for(vint i=0;iGetLayoutProvider()) ,lastCaret(-1, -1) ,lastCaretFrontSide(false) { } void GuiDocumentElement::GuiDocumentElementRenderer::Render(Rect bounds) { if (element->callback) { element->callback->OnStartRender(); } renderTarget->PushClipper(bounds); if(!renderTarget->IsClipperCoverWholeTarget()) { vint maxWidth=bounds.Width(); Rect clipper=renderTarget->GetClipper(); vint cx=bounds.Left(); vint cy=bounds.Top(); vint y1=clipper.Top()-bounds.Top(); vint y2=y1+clipper.Height(); vint y=0; lastMaxWidth=maxWidth; for(vint i=0;i=y2) { break; } else { Ptr paragraph=element->document->paragraphs[i]; Ptr cache=paragraphCaches[i]; bool created=cache && cache->graphicsParagraph; cache=EnsureAndGetCache(i, true); if(!created && i==lastCaret.row && element->caretVisible) { cache->graphicsParagraph->OpenCaret(lastCaret.column, lastCaretColor, lastCaretFrontSide); } paragraphHeight=cache->graphicsParagraph->GetHeight(); renderingParagraph = i; renderingParagraphOffset = Point(cx - bounds.x1, cy + y - bounds.y1); cache->graphicsParagraph->Render(Rect(Point(cx, cy+y), Size(maxWidth, paragraphHeight))); renderingParagraph = -1; bool resized = false; for (vint j = 0; j < cache->embeddedObjects.Count(); j++) { auto eo = cache->embeddedObjects.Values()[j]; if (eo->resized) { eo->resized = false; resized = true; } } if (resized) { cache->graphicsParagraph = 0; } } y+=paragraphHeight+paragraphDistance; } } renderTarget->PopClipper(); if (element->callback) { element->callback->OnFinishRender(); } } void GuiDocumentElement::GuiDocumentElementRenderer::OnElementStateChanged() { if (element->document && element->document->paragraphs.Count() > 0) { vint defaultSize = GetCurrentController()->ResourceService()->GetDefaultFont().size; paragraphDistance = defaultSize; vint defaultHeight = defaultSize; paragraphCaches.Resize(element->document->paragraphs.Count()); paragraphHeights.Resize(element->document->paragraphs.Count()); for (vint i = 0; i < paragraphCaches.Count(); i++) { paragraphCaches[i] = 0; } for (vint i = 0; i < paragraphHeights.Count(); i++) { paragraphHeights[i] = defaultHeight; } cachedTotalHeight = paragraphHeights.Count() * (defaultHeight + paragraphDistance); if (paragraphHeights.Count()>0) { cachedTotalHeight -= paragraphDistance; } minSize = Size(0, cachedTotalHeight); } else { paragraphCaches.Resize(0); paragraphHeights.Resize(0); cachedTotalHeight = 0; minSize = Size(0, 0); } nameCallbackIdMap.Clear(); freeCallbackIds.Clear(); usedCallbackIds = 0; } void GuiDocumentElement::GuiDocumentElementRenderer::NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText) { if (0 <= index && index < paragraphCaches.Count() && 0 <= oldCount && index + oldCount <= paragraphCaches.Count() && 0 <= newCount) { vint paragraphCount = element->document->paragraphs.Count(); CHECK_ERROR(updatedText || oldCount == newCount, L"GuiDocumentlement::GuiDocumentElementRenderer::NotifyParagraphUpdated(vint, vint, vint, bool)#Illegal values of oldCount and newCount."); CHECK_ERROR(paragraphCount - paragraphCaches.Count() == newCount - oldCount, L"GuiDocumentElement::GuiDocumentElementRenderer::NotifyParagraphUpdated(vint, vint, vint, bool)#Illegal values of oldCount and newCount."); ParagraphCacheArray oldCaches; CopyFrom(oldCaches, paragraphCaches); paragraphCaches.Resize(paragraphCount); ParagraphHeightArray oldHeights; CopyFrom(oldHeights, paragraphHeights); paragraphHeights.Resize(paragraphCount); vint defaultHeight = GetCurrentController()->ResourceService()->GetDefaultFont().size; cachedTotalHeight = 0; for (vint i = 0; i < paragraphCount; i++) { if (i < index) { paragraphCaches[i] = oldCaches[i]; paragraphHeights[i] = oldHeights[i]; } else if (i < index + newCount) { paragraphCaches[i] = 0; paragraphHeights[i] = defaultHeight; if (!updatedText && i < index + oldCount) { auto cache = oldCaches[i]; if(cache) { cache->graphicsParagraph = 0; } paragraphCaches[i] = cache; } } else { paragraphCaches[i] = oldCaches[i - (newCount - oldCount)]; paragraphHeights[i] = oldHeights[i - (newCount - oldCount)]; } cachedTotalHeight += paragraphHeights[i] + paragraphDistance; } if (paragraphCount > 0) { cachedTotalHeight -= paragraphDistance; } if (updatedText) { vint count = oldCount < newCount ? oldCount : newCount; for (vint i = 0; i < count; i++) { if (auto cache = oldCaches[index + i]) { for (vint j = 0; j < cache->embeddedObjects.Count(); j++) { auto id = cache->embeddedObjects.Keys()[j]; auto name = cache->embeddedObjects.Values()[j]->name; nameCallbackIdMap.Remove(name); freeCallbackIds.Add(id); } } } } } } Ptr GuiDocumentElement::GuiDocumentElementRenderer::GetHyperlinkFromPoint(Point point) { vint top=0; vint index=-1; if(GetParagraphIndexFromPoint(point, top, index)) { Ptr cache=EnsureAndGetCache(index, true); Point paragraphPoint(point.x, point.y-top); vint start=-1; vint length=0; if(cache->graphicsParagraph->GetInlineObjectFromPoint(paragraphPoint, start, length)) { return element->document->GetHyperlink(index, start, start+length); } vint caret=cache->graphicsParagraph->GetCaretFromPoint(paragraphPoint); return element->document->GetHyperlink(index, caret, caret); } return 0; } void GuiDocumentElement::GuiDocumentElementRenderer::OpenCaret(TextPos caret, Color color, bool frontSide) { CloseCaret(caret); lastCaret=caret; lastCaretColor=color; lastCaretFrontSide=frontSide; Ptr cache=paragraphCaches[lastCaret.row]; if(cache && cache->graphicsParagraph) { cache->graphicsParagraph->OpenCaret(lastCaret.column, lastCaretColor, lastCaretFrontSide); } } void GuiDocumentElement::GuiDocumentElementRenderer::CloseCaret(TextPos caret) { if(lastCaret!=TextPos(-1, -1)) { if(0<=lastCaret.row && lastCaret.row cache=paragraphCaches[lastCaret.row]; if(cache && cache->graphicsParagraph) { cache->graphicsParagraph->CloseCaret(); } } } lastCaret=caret; } void GuiDocumentElement::GuiDocumentElementRenderer::SetSelection(TextPos begin, TextPos end) { if(begin>end) { TextPos t=begin; begin=end; end=t; } if(begin==end) { begin=TextPos(-1, -1); end=TextPos(-1, -1); } for(vint i=0;i cache=EnsureAndGetCache(i, false); vint newBegin=i==begin.row?begin.column:0; vint newEnd=i==end.row?end.column:cache->fullText.Length(); if(cache->selectionBegin!=newBegin || cache->selectionEnd!=newEnd) { cache->selectionBegin=newBegin; cache->selectionEnd=newEnd; NotifyParagraphUpdated(i, 1, 1, false); } } else { Ptr cache=paragraphCaches[i]; if(cache) { if(cache->selectionBegin!=-1 || cache->selectionEnd!=-1) { cache->selectionBegin=-1; cache->selectionEnd=-1; NotifyParagraphUpdated(i, 1, 1, false); } } } } } TextPos GuiDocumentElement::GuiDocumentElementRenderer::CalculateCaret(TextPos comparingCaret, IGuiGraphicsParagraph::CaretRelativePosition position, bool& preferFrontSide) { Ptr cache=EnsureAndGetCache(comparingCaret.row, true); if(cache) { switch(position) { case IGuiGraphicsParagraph::CaretFirst: { preferFrontSide=false; vint caret=cache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretFirst, preferFrontSide); return TextPos(comparingCaret.row, caret); } case IGuiGraphicsParagraph::CaretLast: { preferFrontSide=true; vint caret=cache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretLast, preferFrontSide); return TextPos(comparingCaret.row, caret); } case IGuiGraphicsParagraph::CaretLineFirst: { preferFrontSide=false; vint caret=cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretLineFirst, preferFrontSide); return TextPos(comparingCaret.row, caret); } case IGuiGraphicsParagraph::CaretLineLast: { preferFrontSide=true; vint caret=cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretLineLast, preferFrontSide); return TextPos(comparingCaret.row, caret); } case IGuiGraphicsParagraph::CaretMoveUp: { vint caret=cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveUp, preferFrontSide); if(caret==comparingCaret.column && comparingCaret.row>0) { Rect caretBounds=cache->graphicsParagraph->GetCaretBounds(comparingCaret.column, preferFrontSide); Ptr anotherCache=EnsureAndGetCache(comparingCaret.row-1, true); vint height=anotherCache->graphicsParagraph->GetHeight(); caret=anotherCache->graphicsParagraph->GetCaretFromPoint(Point(caretBounds.x1, height)); return TextPos(comparingCaret.row-1, caret); } else { return TextPos(comparingCaret.row, caret); } } case IGuiGraphicsParagraph::CaretMoveDown: { vint caret=cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveDown, preferFrontSide); if(caret==comparingCaret.column && comparingCaret.rowgraphicsParagraph->GetCaretBounds(comparingCaret.column, preferFrontSide); Ptr anotherCache=EnsureAndGetCache(comparingCaret.row+1, true); caret=anotherCache->graphicsParagraph->GetCaretFromPoint(Point(caretBounds.x1, 0)); return TextPos(comparingCaret.row+1, caret); } else { return TextPos(comparingCaret.row, caret); } } case IGuiGraphicsParagraph::CaretMoveLeft: { preferFrontSide=false; vint caret=cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveLeft, preferFrontSide); if(caret==comparingCaret.column && comparingCaret.row>0) { Ptr anotherCache=EnsureAndGetCache(comparingCaret.row-1, true); caret=anotherCache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretLast, preferFrontSide); return TextPos(comparingCaret.row-1, caret); } else { return TextPos(comparingCaret.row, caret); } } case IGuiGraphicsParagraph::CaretMoveRight: { preferFrontSide=true; vint caret=cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveRight, preferFrontSide); if(caret==comparingCaret.column && comparingCaret.row anotherCache=EnsureAndGetCache(comparingCaret.row+1, true); caret=anotherCache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretFirst, preferFrontSide); return TextPos(comparingCaret.row+1, caret); } else { return TextPos(comparingCaret.row, caret); } } } } return comparingCaret; } TextPos GuiDocumentElement::GuiDocumentElementRenderer::CalculateCaretFromPoint(Point point) { vint top=0; vint index=-1; if(GetParagraphIndexFromPoint(point, top, index)) { Ptr cache=EnsureAndGetCache(index, true); Point paragraphPoint(point.x, point.y-top); vint caret=cache->graphicsParagraph->GetCaretFromPoint(paragraphPoint); return TextPos(index, caret); } return TextPos(-1, -1); } Rect GuiDocumentElement::GuiDocumentElementRenderer::GetCaretBounds(TextPos caret, bool frontSide) { Ptr cache=EnsureAndGetCache(caret.row, true); if(cache) { Rect bounds=cache->graphicsParagraph->GetCaretBounds(caret.column, frontSide); if(bounds!=Rect()) { vint y=0; for(vint i=0;i elementRenderer=renderer.Cast(); if(elementRenderer) { elementRenderer->SetSelection(caretBegin, caretEnd); if(caretVisible) { elementRenderer->OpenCaret(caretEnd, caretColor, caretFrontSide); } else { elementRenderer->CloseCaret(caretEnd); } } } GuiDocumentElement::GuiDocumentElement() :caretVisible(false) ,caretFrontSide(false) { } GuiDocumentElement::~GuiDocumentElement() { } GuiDocumentElement::ICallback* GuiDocumentElement::GetCallback() { return callback; } void GuiDocumentElement::SetCallback(ICallback* value) { callback = value; } Ptr GuiDocumentElement::GetDocument() { return document; } void GuiDocumentElement::SetDocument(Ptr value) { document=value; if(renderer) { renderer->OnElementStateChanged(); SetCaret(TextPos(), TextPos(), false); } } TextPos GuiDocumentElement::GetCaretBegin() { return caretBegin; } TextPos GuiDocumentElement::GetCaretEnd() { return caretEnd; } bool GuiDocumentElement::IsCaretEndPreferFrontSide() { return caretFrontSide; } void GuiDocumentElement::SetCaret(TextPos begin, TextPos end, bool frontSide) { caretBegin=begin; caretEnd=end; if(caretBegincaretEnd) { caretFrontSide=false; } else { caretFrontSide=frontSide; } UpdateCaret(); } bool GuiDocumentElement::GetCaretVisible() { return caretVisible; } void GuiDocumentElement::SetCaretVisible(bool value) { caretVisible=value; UpdateCaret(); } Color GuiDocumentElement::GetCaretColor() { return caretColor; } void GuiDocumentElement::SetCaretColor(Color value) { caretColor=value; UpdateCaret(); } TextPos GuiDocumentElement::CalculateCaret(TextPos comparingCaret, IGuiGraphicsParagraph::CaretRelativePosition position, bool& preferFrontSide) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { TextPos caret=elementRenderer->CalculateCaret(comparingCaret, position, preferFrontSide); return caret.column==-1?comparingCaret:caret; } else { return comparingCaret; } } TextPos GuiDocumentElement::CalculateCaretFromPoint(Point point) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { return elementRenderer->CalculateCaretFromPoint(point); } else { return TextPos(0, 0); } } Rect GuiDocumentElement::GetCaretBounds(TextPos caret, bool frontSide) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { return elementRenderer->GetCaretBounds(caret, frontSide); } else { return Rect(); } } void GuiDocumentElement::NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { elementRenderer->NotifyParagraphUpdated(index, oldCount, newCount, updatedText); } } void GuiDocumentElement::EditRun(TextPos begin, TextPos end, Ptr model) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { TextPos temp=begin; begin=end; end=temp; } vint newRows=document->EditRun(begin, end, model); if(newRows!=-1) { elementRenderer->NotifyParagraphUpdated(begin.row, end.row-begin.row+1, newRows, true); } } } void GuiDocumentElement::EditText(TextPos begin, TextPos end, bool frontSide, const collections::Array& text) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { TextPos temp=begin; begin=end; end=temp; } vint newRows=document->EditText(begin, end, frontSide, text); if(newRows!=-1) { elementRenderer->NotifyParagraphUpdated(begin.row, end.row-begin.row+1, newRows, true); } } } void GuiDocumentElement::EditStyle(TextPos begin, TextPos end, Ptr style) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { TextPos temp=begin; begin=end; end=temp; } if(document->EditStyle(begin, end, style)) { elementRenderer->NotifyParagraphUpdated(begin.row, end.row-begin.row+1, end.row-begin.row+1, false); } } } void GuiDocumentElement::EditImage(TextPos begin, TextPos end, Ptr image) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { TextPos temp=begin; begin=end; end=temp; } if(document->EditImage(begin, end, image)) { elementRenderer->NotifyParagraphUpdated(begin.row, end.row-begin.row+1, 1, true); } } } void GuiDocumentElement::EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName, const WString& activeStyleName) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { vint temp=begin; begin=end; end=temp; } if(document->EditHyperlink(paragraphIndex, begin, end, reference, normalStyleName, activeStyleName)) { elementRenderer->NotifyParagraphUpdated(paragraphIndex, 1, 1, false); } } } void GuiDocumentElement::RemoveHyperlink(vint paragraphIndex, vint begin, vint end) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { vint temp=begin; begin=end; end=temp; } if(document->RemoveHyperlink(paragraphIndex, begin, end)) { elementRenderer->NotifyParagraphUpdated(paragraphIndex, 1, 1, false); } } } void GuiDocumentElement::EditStyleName(TextPos begin, TextPos end, const WString& styleName) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { TextPos temp=begin; begin=end; end=temp; } if(document->EditStyleName(begin, end, styleName)) { elementRenderer->NotifyParagraphUpdated(begin.row, end.row-begin.row+1, end.row-begin.row+1, false); } } } void GuiDocumentElement::RemoveStyleName(TextPos begin, TextPos end) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { TextPos temp=begin; begin=end; end=temp; } if(document->RemoveStyleName(begin, end)) { elementRenderer->NotifyParagraphUpdated(begin.row, end.row-begin.row+1, end.row-begin.row+1, false); } } } void GuiDocumentElement::RenameStyle(const WString& oldStyleName, const WString& newStyleName) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { document->RenameStyle(oldStyleName, newStyleName); } } void GuiDocumentElement::ClearStyle(TextPos begin, TextPos end) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { TextPos temp=begin; begin=end; end=temp; } if(document->ClearStyle(begin, end)) { elementRenderer->NotifyParagraphUpdated(begin.row, end.row-begin.row+1, end.row-begin.row+1, false); } } } Ptr GuiDocumentElement::SummarizeStyle(TextPos begin, TextPos end) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { if(begin>end) { TextPos temp=begin; begin=end; end=temp; } return document->SummarizeStyle(begin, end); } return 0; } void GuiDocumentElement::SetParagraphAlignment(TextPos begin, TextPos end, const collections::Array>& alignments) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { vint first=begin.row; vint last=end.row; if(first>last) { vint temp=first; first=last; last=temp; } if(0<=first && firstparagraphs.Count() && 0<=last && lastparagraphs.Count() && last-first+1==alignments.Count()) { for(vint i=first;i<=last;i++) { document->paragraphs[i]->alignment=alignments[i-first]; } elementRenderer->NotifyParagraphUpdated(first, alignments.Count(), alignments.Count(), false); } } } Ptr GuiDocumentElement::GetHyperlinkFromPoint(Point point) { Ptr elementRenderer=renderer.Cast(); if(elementRenderer) { return elementRenderer->GetHyperlinkFromPoint(point); } else { return 0; } } } } } /*********************************************************************** GRAPHICSELEMENT\GUIGRAPHICSELEMENT.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace elements { using namespace collections; /*********************************************************************** GuiSolidBorderElement ***********************************************************************/ GuiSolidBorderElement::GuiSolidBorderElement() :color(0, 0, 0) ,shape(ElementShape::Rectangle) { } GuiSolidBorderElement::~GuiSolidBorderElement() { renderer->Finalize(); } Color GuiSolidBorderElement::GetColor() { return color; } void GuiSolidBorderElement::SetColor(Color value) { if(color!=value) { color=value; if(renderer) { renderer->OnElementStateChanged(); } } } ElementShape GuiSolidBorderElement::GetShape() { return shape; } void GuiSolidBorderElement::SetShape(ElementShape value) { shape=value; } /*********************************************************************** GuiRoundBorderElement ***********************************************************************/ GuiRoundBorderElement::GuiRoundBorderElement() :color(0, 0, 0) ,radius(10) { } GuiRoundBorderElement::~GuiRoundBorderElement() { renderer->Finalize(); } Color GuiRoundBorderElement::GetColor() { return color; } void GuiRoundBorderElement::SetColor(Color value) { if(color!=value) { color=value; if(renderer) { renderer->OnElementStateChanged(); } } } vint GuiRoundBorderElement::GetRadius() { return radius; } void GuiRoundBorderElement::SetRadius(vint value) { if(radius!=value) { radius=value; if(renderer) { renderer->OnElementStateChanged(); } } } /*********************************************************************** Gui3DBorderElement ***********************************************************************/ Gui3DBorderElement::Gui3DBorderElement() { } Gui3DBorderElement::~Gui3DBorderElement() { renderer->Finalize(); } Color Gui3DBorderElement::GetColor1() { return color1; } void Gui3DBorderElement::SetColor1(Color value) { SetColors(value, color2); } Color Gui3DBorderElement::GetColor2() { return color2; } void Gui3DBorderElement::SetColor2(Color value) { SetColors(color1, value); } void Gui3DBorderElement::SetColors(Color value1, Color value2) { if(color1!=value1 || color2!=value2) { color1=value1; color2=value2; if(renderer) { renderer->OnElementStateChanged(); } } } /*********************************************************************** Gui3DSplitterElement ***********************************************************************/ Gui3DSplitterElement::Gui3DSplitterElement() :direction(Horizontal) { } Gui3DSplitterElement::~Gui3DSplitterElement() { renderer->Finalize(); } Color Gui3DSplitterElement::GetColor1() { return color1; } void Gui3DSplitterElement::SetColor1(Color value) { SetColors(value, color2); } Color Gui3DSplitterElement::GetColor2() { return color2; } void Gui3DSplitterElement::SetColor2(Color value) { SetColors(color1, value); } void Gui3DSplitterElement::SetColors(Color value1, Color value2) { if(color1!=value1 || color2!=value2) { color1=value1; color2=value2; if(renderer) { renderer->OnElementStateChanged(); } } } Gui3DSplitterElement::Direction Gui3DSplitterElement::GetDirection() { return direction; } void Gui3DSplitterElement::SetDirection(Direction value) { if(direction!=value) { direction=value; if(renderer) { renderer->OnElementStateChanged(); } } } /*********************************************************************** GuiSolidBackgroundElement ***********************************************************************/ GuiSolidBackgroundElement::GuiSolidBackgroundElement() :color(255, 255, 255) ,shape(ElementShape::Rectangle) { } GuiSolidBackgroundElement::~GuiSolidBackgroundElement() { renderer->Finalize(); } Color GuiSolidBackgroundElement::GetColor() { return color; } void GuiSolidBackgroundElement::SetColor(Color value) { if(color!=value) { color=value; if(renderer) { renderer->OnElementStateChanged(); } } } ElementShape GuiSolidBackgroundElement::GetShape() { return shape; } void GuiSolidBackgroundElement::SetShape(ElementShape value) { shape=value; } /*********************************************************************** GuiGradientBackgroundElement ***********************************************************************/ GuiGradientBackgroundElement::GuiGradientBackgroundElement() :direction(Horizontal) ,shape(ElementShape::Rectangle) { } GuiGradientBackgroundElement::~GuiGradientBackgroundElement() { renderer->Finalize(); } Color GuiGradientBackgroundElement::GetColor1() { return color1; } void GuiGradientBackgroundElement::SetColor1(Color value) { SetColors(value, color2); } Color GuiGradientBackgroundElement::GetColor2() { return color2; } void GuiGradientBackgroundElement::SetColor2(Color value) { SetColors(color1, value); } void GuiGradientBackgroundElement::SetColors(Color value1, Color value2) { if(color1!=value1 || color2!=value2) { color1=value1; color2=value2; if(renderer) { renderer->OnElementStateChanged(); } } } GuiGradientBackgroundElement::Direction GuiGradientBackgroundElement::GetDirection() { return direction; } void GuiGradientBackgroundElement::SetDirection(Direction value) { if(direction!=value) { direction=value; if(renderer) { renderer->OnElementStateChanged(); } } } ElementShape GuiGradientBackgroundElement::GetShape() { return shape; } void GuiGradientBackgroundElement::SetShape(ElementShape value) { shape=value; } /*********************************************************************** GuiSolidLabelElement ***********************************************************************/ GuiSolidLabelElement::GuiSolidLabelElement() :color(0, 0, 0) ,hAlignment(Alignment::Left) ,vAlignment(Alignment::Top) ,wrapLine(false) ,ellipse(false) ,multiline(false) ,wrapLineHeightCalculation(false) { fontProperties.fontFamily=L"Lucida Console"; fontProperties.size=12; } GuiSolidLabelElement::~GuiSolidLabelElement() { renderer->Finalize(); } Color GuiSolidLabelElement::GetColor() { return color; } void GuiSolidLabelElement::SetColor(Color value) { if(color!=value) { color=value; if(renderer) { renderer->OnElementStateChanged(); } } } const FontProperties& GuiSolidLabelElement::GetFont() { return fontProperties; } void GuiSolidLabelElement::SetFont(const FontProperties& value) { if(fontProperties!=value) { fontProperties=value; if(renderer) { renderer->OnElementStateChanged(); } } } const WString& GuiSolidLabelElement::GetText() { return text; } void GuiSolidLabelElement::SetText(const WString& value) { if(text!=value) { text=value; if(renderer) { renderer->OnElementStateChanged(); } } } Alignment GuiSolidLabelElement::GetHorizontalAlignment() { return hAlignment; } Alignment GuiSolidLabelElement::GetVerticalAlignment() { return vAlignment; } void GuiSolidLabelElement::SetHorizontalAlignment(Alignment value) { SetAlignments(value, vAlignment); } void GuiSolidLabelElement::SetVerticalAlignment(Alignment value) { SetAlignments(hAlignment, value); } void GuiSolidLabelElement::SetAlignments(Alignment horizontal, Alignment vertical) { if(hAlignment!=horizontal || vAlignment!=vertical) { hAlignment=horizontal; vAlignment=vertical; if(renderer) { renderer->OnElementStateChanged(); } } } bool GuiSolidLabelElement::GetWrapLine() { return wrapLine; } void GuiSolidLabelElement::SetWrapLine(bool value) { if(wrapLine!=value) { wrapLine=value; if(renderer) { renderer->OnElementStateChanged(); } } } bool GuiSolidLabelElement::GetEllipse() { return ellipse; } void GuiSolidLabelElement::SetEllipse(bool value) { if(ellipse!=value) { ellipse=value; if(renderer) { renderer->OnElementStateChanged(); } } } bool GuiSolidLabelElement::GetMultiline() { return multiline; } void GuiSolidLabelElement::SetMultiline(bool value) { if(multiline!=value) { multiline=value; if(renderer) { renderer->OnElementStateChanged(); } } } bool GuiSolidLabelElement::GetWrapLineHeightCalculation() { return wrapLineHeightCalculation; } void GuiSolidLabelElement::SetWrapLineHeightCalculation(bool value) { if(wrapLineHeightCalculation!=value) { wrapLineHeightCalculation=value; if(renderer) { renderer->OnElementStateChanged(); } } } /*********************************************************************** GuiImageFrameElement ***********************************************************************/ GuiImageFrameElement::GuiImageFrameElement() :frameIndex(0) ,hAlignment(Alignment::Left) ,vAlignment(Alignment::Top) ,stretch(false) ,enabled(true) { } GuiImageFrameElement::~GuiImageFrameElement() { renderer->Finalize(); } Ptr GuiImageFrameElement::GetImage() { return image; } vint GuiImageFrameElement::GetFrameIndex() { return frameIndex; } void GuiImageFrameElement::SetImage(Ptr value) { SetImage(value, frameIndex); } void GuiImageFrameElement::SetFrameIndex(vint value) { SetImage(image, value); } void GuiImageFrameElement::SetImage(Ptr _image, vint _frameIndex) { if(image!=_image || frameIndex!=_frameIndex) { if(!_image) { image=0; frameIndex=0; } else if(0<=_frameIndex && _frameIndex<_image->GetFrameCount()) { image=_image; frameIndex=_frameIndex; } if(renderer) { renderer->OnElementStateChanged(); } } } Alignment GuiImageFrameElement::GetHorizontalAlignment() { return hAlignment; } Alignment GuiImageFrameElement::GetVerticalAlignment() { return vAlignment; } void GuiImageFrameElement::SetHorizontalAlignment(Alignment value) { SetAlignments(value, vAlignment); } void GuiImageFrameElement::SetVerticalAlignment(Alignment value) { SetAlignments(hAlignment, value); } void GuiImageFrameElement::SetAlignments(Alignment horizontal, Alignment vertical) { if(hAlignment!=horizontal || vAlignment!=vertical) { hAlignment=horizontal; vAlignment=vertical; if(renderer) { renderer->OnElementStateChanged(); } } } bool GuiImageFrameElement::GetStretch() { return stretch; } void GuiImageFrameElement::SetStretch(bool value) { if(stretch!=value) { stretch=value; if(renderer) { renderer->OnElementStateChanged(); } } } bool GuiImageFrameElement::GetEnabled() { return enabled; } void GuiImageFrameElement::SetEnabled(bool value) { if(enabled!=value) { enabled=value; if(renderer) { renderer->OnElementStateChanged(); } } } /*********************************************************************** GuiPolygonElement ***********************************************************************/ GuiPolygonElement::GuiPolygonElement() { } GuiPolygonElement::~GuiPolygonElement() { } Size GuiPolygonElement::GetSize() { return size; } void GuiPolygonElement::SetSize(Size value) { if(size!=value) { size=value; if(renderer) { renderer->OnElementStateChanged(); } } } const Point& GuiPolygonElement::GetPoint(vint index) { return points[index]; } vint GuiPolygonElement::GetPointCount() { return points.Count(); } void GuiPolygonElement::SetPoints(const Point* p, vint count) { points.Resize(count); if(count>0) { memcpy(&points[0], p, sizeof(*p)*count); } if(renderer) { renderer->OnElementStateChanged(); } } const GuiPolygonElement::PointArray& GuiPolygonElement::GetPointsArray() { return points; } void GuiPolygonElement::SetPointsArray(const PointArray& value) { CopyFrom(points, value); } Color GuiPolygonElement::GetBorderColor() { return borderColor; } void GuiPolygonElement::SetBorderColor(Color value) { if(borderColor!=value) { borderColor=value; if(renderer) { renderer->OnElementStateChanged(); } } } Color GuiPolygonElement::GetBackgroundColor() { return backgroundColor; } void GuiPolygonElement::SetBackgroundColor(Color value) { if(backgroundColor!=value) { backgroundColor=value; if(renderer) { renderer->OnElementStateChanged(); } } } } } } /*********************************************************************** GRAPHICSELEMENT\GUIGRAPHICSHOST.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace compositions { using namespace collections; using namespace controls; using namespace elements; using namespace theme; /*********************************************************************** GuiGraphicsAnimationManager ***********************************************************************/ GuiGraphicsAnimationManager::GuiGraphicsAnimationManager() { } GuiGraphicsAnimationManager::~GuiGraphicsAnimationManager() { } void GuiGraphicsAnimationManager::AddAnimation(Ptr animation) { playingAnimations.Add(animation); } bool GuiGraphicsAnimationManager::HasAnimation() { return playingAnimations.Count()>0; } void GuiGraphicsAnimationManager::Play() { for(vint i=playingAnimations.Count()-1;i>=0;i--) { Ptr animation=playingAnimations[i]; vint totalLength=animation->GetTotalLength(); vint currentPosition=animation->GetCurrentPosition(); animation->Play(currentPosition, totalLength); if(currentPosition>=totalLength) { playingAnimations.RemoveAt(i); animation->Stop(); } } } /*********************************************************************** IGuiAltAction ***********************************************************************/ const wchar_t* const IGuiAltAction::Identifier = L"vl::presentation::compositions::IGuiAltAction"; const wchar_t* const IGuiAltActionContainer::Identifier = L"vl::presentation::compositions::IGuiAltAction"; const wchar_t* const IGuiAltActionHost::Identifier = L"vl::presentation::compositions::IGuiAltAction"; bool IGuiAltAction::IsLegalAlt(const WString& alt) { for (vint i = 0; i < alt.Length(); i++) { if (alt[i] < L'A' || L'Z' < alt[i]) { return false; } } return true; } void IGuiAltActionHost::CollectAltActionsFromControl(controls::GuiControl* control, collections::Group& actions) { List controls; controls.Add(control); vint current = 0; while (current < controls.Count()) { GuiControl* control = controls[current++]; if (auto container = control->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 = control->QueryTypedService()) { if (action->IsAltAvailable()) { if (action->IsAltEnabled()) { actions.Add(action->GetAlt(), action); continue; } } } vint count = control->GetChildrenCount(); for (vint i = 0; i < count; i++) { controls.Add(control->GetChild(i)); } } } /*********************************************************************** GuiGraphicsHost ***********************************************************************/ void GuiGraphicsHost::EnterAltHost(IGuiAltActionHost* host) { ClearAltHost(); Group actions; host->CollectAltActions(actions); if (actions.Count() == 0) { CloseAltHost(); return; } host->OnActivatedAltHost(currentAltHost); currentAltHost = host; CreateAltTitles(actions); } void GuiGraphicsHost::LeaveAltHost() { if (currentAltHost) { ClearAltHost(); auto previousHost = currentAltHost->GetPreviousAltHost(); currentAltHost->OnDeactivatedAltHost(); currentAltHost = previousHost; if (currentAltHost) { Group actions; currentAltHost->CollectAltActions(actions); CreateAltTitles(actions); } } } bool GuiGraphicsHost::EnterAltKey(wchar_t key) { currentAltPrefix += 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 GuiGraphicsHost::LeaveAltKey() { if (currentAltPrefix.Length() >= 1) { currentAltPrefix = currentAltPrefix.Left(currentAltPrefix.Length() - 1); } FilterTitles(); } void GuiGraphicsHost::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; } FOREACH_INDEXER(IGuiAltAction*, action, index, 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()); auto windowStyle = dynamic_cast(window->GetStyleController()); for (vint i = 0; i < count; i++) { auto key = currentActiveAltActions.Keys()[i]; auto composition = currentActiveAltActions.Values()[i]->GetAltComposition(); auto labelStyle = windowStyle->CreateShortcutKeyStyle(); if (!labelStyle)labelStyle = GetCurrentTheme()->CreateShortcutKeyStyle(); auto label = new GuiLabel(labelStyle); label->SetText(key); composition->AddChild(label->GetBoundsComposition()); currentActiveAltTitles.Add(key, label); } FilterTitles(); } } vint GuiGraphicsHost::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 GuiGraphicsHost::ClearAltHost() { FOREACH(GuiControl*, title, currentActiveAltTitles.Values()) { SafeDeleteControl(title); } currentActiveAltActions.Clear(); currentActiveAltTitles.Clear(); currentAltPrefix = L""; } void GuiGraphicsHost::CloseAltHost() { ClearAltHost(); while (currentAltHost) { currentAltHost->OnDeactivatedAltHost(); currentAltHost = currentAltHost->GetPreviousAltHost(); } } void GuiGraphicsHost::DisconnectCompositionInternal(GuiGraphicsComposition* composition) { for(vint i=0;iChildren().Count();i++) { DisconnectCompositionInternal(composition->Children().Get(i)); } if(mouseCaptureComposition==composition) { if(nativeWindow) { nativeWindow->ReleaseCapture(); } mouseCaptureComposition=0; } if(focusedComposition==composition) { focusedComposition=0; } mouseEnterCompositions.Remove(composition); } void GuiGraphicsHost::MouseCapture(const NativeWindowMouseInfo& info) { if(nativeWindow && (info.left || info.middle || info.right)) { if(!nativeWindow->IsCapturing() && !info.nonClient) { nativeWindow->RequireCapture(); mouseCaptureComposition=windowComposition->FindComposition(Point(info.x, info.y)); } } } void GuiGraphicsHost::MouseUncapture(const NativeWindowMouseInfo& info) { if(nativeWindow && !(info.left || info.middle || info.right)) { 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; while(composition) { if(composition->HasEventReceiver()) { compositions.Add(composition); } composition=composition->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;iGetEventReceiver()->*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 { composition=windowComposition->FindComposition(Point(info.x, info.y)); } if(composition) { Rect bounds=composition->GetGlobalBounds(); GuiMouseEventArgs arguments; (NativeWindowMouseInfo&)arguments=info; arguments.x-=bounds.x1; arguments.y-=bounds.y1; RaiseMouseEvent(arguments, composition, eventReceiverEvent); } } INativeWindowListener::HitTestResult GuiGraphicsHost::HitTest(Point location) { Rect bounds=nativeWindow->GetBounds(); Rect clientBounds=nativeWindow->GetClientBoundsInScreen(); Point clientLocation(location.x+bounds.x1-clientBounds.x1, location.y+bounds.y1-clientBounds.y1); GuiGraphicsComposition* hitComposition=windowComposition->FindComposition(clientLocation); while(hitComposition) { INativeWindowListener::HitTestResult result=hitComposition->GetAssociatedHitTestResult(); if(result==INativeWindowListener::NoDecision) { hitComposition=hitComposition->GetParent(); } else { return result; } } return INativeWindowListener::NoDecision; } void GuiGraphicsHost::Moving(Rect& bounds, bool fixSizeOnly) { Rect oldBounds=nativeWindow->GetBounds(); minSize=windowComposition->GetPreferredBounds().GetSize(); Size minWindowSize=minSize+(oldBounds.GetSize()-nativeWindow->GetClientSize()); if(bounds.Width()GetClientSize(); if(previousClientSize!=size) { previousClientSize=size; minSize=windowComposition->GetPreferredBounds().GetSize(); Render(); } } void GuiGraphicsHost::LeftButtonDown(const NativeWindowMouseInfo& info) { 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) { 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) { 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; { GuiGraphicsComposition* composition=windowComposition->FindComposition(Point(info.x, info.y)); while(composition) { newCompositions.Insert(0, composition); composition=composition->GetParent(); } } vint firstDifferentIndex=mouseEnterCompositions.Count(); for(vint i=0;i=firstDifferentIndex;i--) { GuiGraphicsComposition* composition=mouseEnterCompositions[i]; if(composition->HasEventReceiver()) { composition->GetEventReceiver()->mouseLeave.Execute(GuiEventArgs(composition)); } } CopyFrom(mouseEnterCompositions, newCompositions); for(vint i=firstDifferentIndex;iHasEventReceiver()) { composition->GetEventReceiver()->mouseEnter.Execute(GuiEventArgs(composition)); } } INativeCursor* cursor=0; if(newCompositions.Count()>0) { cursor=newCompositions[newCompositions.Count()-1]->GetRelatedCursor(); } if(cursor) { nativeWindow->SetWindowCursor(cursor); } else { 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 (!info.ctrl && !info.shift && currentAltHost) { if (info.code == VKEY_ESCAPE) { LeaveAltHost(); return; } else if (info.code == VKEY_BACK) { LeaveAltKey(); } else if (VKEY_NUMPAD0 <= info.code && info.code <= VKEY_NUMPAD9) { if (EnterAltKey((wchar_t)(L'0' + (info.code - VKEY_NUMPAD0)))) { supressAltKey = info.code; return; } } else if (('0' <= info.code && info.code <= '9') || ('A' <= info.code && info.code <= 'Z')) { if (EnterAltKey((wchar_t)info.code)) { supressAltKey = info.code; return; } } } if (currentAltHost) { return; } if(shortcutKeyManager && shortcutKeyManager->Execute(info)) { return; } if(focusedComposition && focusedComposition->HasEventReceiver()) { OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::keyDown); } } void GuiGraphicsHost::KeyUp(const NativeWindowKeyInfo& info) { if (!info.ctrl && !info.shift && info.code == supressAltKey) { supressAltKey = 0; return; } if(focusedComposition && focusedComposition->HasEventReceiver()) { OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::keyUp); } } void GuiGraphicsHost::SysKeyDown(const NativeWindowKeyInfo& info) { if (!info.ctrl && !info.shift && info.code == VKEY_MENU && !currentAltHost) { if (auto window = dynamic_cast(windowComposition->Children()[0]->GetRelatedControlHost())) { if (auto altHost = window->QueryTypedService()) { if (!altHost->GetPreviousAltHost()) { EnterAltHost(altHost); } } } } if (currentAltHost) { return; } if(focusedComposition && focusedComposition->HasEventReceiver()) { OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::systemKeyDown); } } void GuiGraphicsHost::SysKeyUp(const NativeWindowKeyInfo& info) { if (!info.ctrl && !info.shift && info.code == VKEY_MENU && nativeWindow) { if (nativeWindow) { nativeWindow->SupressAlt(); } } if(focusedComposition && focusedComposition->HasEventReceiver()) { OnKeyInput(info, focusedComposition, &GuiGraphicsEventReceiver::systemKeyUp); } } void GuiGraphicsHost::Char(const NativeWindowCharInfo& info) { if (!currentAltHost && !supressAltKey) { if(focusedComposition && focusedComposition->HasEventReceiver()) { OnCharInput(info, focusedComposition, &GuiGraphicsEventReceiver::charInput); } } } void GuiGraphicsHost::GlobalTimer() { if(animationManager.HasAnimation()) { animationManager.Play(); } DateTime now=DateTime::UtcTime(); if(now.totalMilliseconds-lastCaretTime>=CaretInterval) { lastCaretTime=now.totalMilliseconds; if(focusedComposition && focusedComposition->HasEventReceiver()) { focusedComposition->GetEventReceiver()->caretNotify.Execute(GuiEventArgs(focusedComposition)); } } Render(); } GuiGraphicsHost::GuiGraphicsHost() :nativeWindow(0) ,shortcutKeyManager(0) ,windowComposition(0) ,focusedComposition(0) ,mouseCaptureComposition(0) ,lastCaretTime(0) ,currentAltHost(0) ,supressAltKey(0) { windowComposition=new GuiWindowComposition; windowComposition->SetAssociatedHost(this); windowComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); } GuiGraphicsHost::~GuiGraphicsHost() { if(shortcutKeyManager) { delete shortcutKeyManager; shortcutKeyManager=0; } delete windowComposition; } INativeWindow* GuiGraphicsHost::GetNativeWindow() { return nativeWindow; } void GuiGraphicsHost::SetNativeWindow(INativeWindow* _nativeWindow) { if(nativeWindow!=_nativeWindow) { if(nativeWindow) { GetCurrentController()->CallbackService()->UninstallListener(this); nativeWindow->UninstallListener(this); } nativeWindow=_nativeWindow; windowComposition->SetAttachedWindow(nativeWindow); if(nativeWindow) { nativeWindow->InstallListener(this); GetCurrentController()->CallbackService()->InstallListener(this); previousClientSize=nativeWindow->GetClientSize(); minSize=windowComposition->GetPreferredBounds().GetSize(); nativeWindow->SetCaretPoint(caretPoint); } } } GuiGraphicsComposition* GuiGraphicsHost::GetMainComposition() { return windowComposition; } void GuiGraphicsHost::Render() { if(nativeWindow && nativeWindow->IsVisible()) { windowComposition->GetRenderTarget()->StartRendering(); windowComposition->Render(Size()); bool success = windowComposition->GetRenderTarget()->StopRendering(); nativeWindow->RedrawContent(); if (!success) { windowComposition->SetAttachedWindow(0); GetGuiGraphicsResourceManager()->RecreateRenderTarget(nativeWindow); windowComposition->SetAttachedWindow(nativeWindow); } } } 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(nativeWindow) { nativeWindow->SetCaretPoint(caretPoint); } } GuiGraphicsAnimationManager* GuiGraphicsHost::GetAnimationManager() { return &animationManager; } void GuiGraphicsHost::DisconnectComposition(GuiGraphicsComposition* composition) { DisconnectCompositionInternal(composition); } /*********************************************************************** GuiTimeBasedAnimation ***********************************************************************/ GuiTimeBasedAnimation::GuiTimeBasedAnimation(vint totalMilliseconds) :startTime(0) ,length(totalMilliseconds) { Restart(); } GuiTimeBasedAnimation::~GuiTimeBasedAnimation() { } void GuiTimeBasedAnimation::Restart(vint totalMilliseconds) { startTime=DateTime::LocalTime().totalMilliseconds; if(totalMilliseconds>-1) { length=totalMilliseconds; } } vint GuiTimeBasedAnimation::GetTotalLength() { return length; } vint GuiTimeBasedAnimation::GetCurrentPosition() { return (vint)(DateTime::LocalTime().totalMilliseconds-startTime); } /*********************************************************************** GuiShortcutKeyItem ***********************************************************************/ GuiShortcutKeyItem::GuiShortcutKeyItem(GuiShortcutKeyManager* _shortcutKeyManager, bool _ctrl, bool _shift, bool _alt, vint _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, vint _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; FOREACH(Ptr, 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, vint key) { FOREACH(Ptr, item, shortcutKeyItems) { if(item->CanActivate(ctrl, shift, alt, key)) { return item.Obj(); } } Ptr item=new GuiShortcutKeyItem(this, ctrl, shift, alt, key); shortcutKeyItems.Add(item); return item.Obj(); } bool GuiShortcutKeyManager::DestroyShortcut(bool ctrl, bool shift, bool alt, vint key) { FOREACH(Ptr, 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, vint key) { FOREACH(Ptr, item, shortcutKeyItems) { if(item->CanActivate(ctrl, shift, alt, key)) { return item.Obj(); } } return 0; } } } } /*********************************************************************** GRAPHICSELEMENT\GUIGRAPHICSRESOURCEMANAGER.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace elements { using namespace collections; /*********************************************************************** GuiGraphicsResourceManager ***********************************************************************/ GuiGraphicsResourceManager::GuiGraphicsResourceManager() { } GuiGraphicsResourceManager::~GuiGraphicsResourceManager() { } bool GuiGraphicsResourceManager::RegisterElementFactory(IGuiGraphicsElementFactory* factory) { if(elementFactories.Keys().Contains(factory->GetElementTypeName())) { return false; } else { elementFactories.Add(factory->GetElementTypeName(), factory); return true; } } bool GuiGraphicsResourceManager::RegisterRendererFactory(const WString& elementTypeName, IGuiGraphicsRendererFactory* factory) { if(rendererFactories.Keys().Contains(elementTypeName)) { return false; } else { rendererFactories.Add(elementTypeName, factory); return true; } } IGuiGraphicsElementFactory* GuiGraphicsResourceManager::GetElementFactory(const WString& elementTypeName) { vint index=elementFactories.Keys().IndexOf(elementTypeName); return index==-1?0:elementFactories.Values().Get(index).Obj(); } IGuiGraphicsRendererFactory* GuiGraphicsResourceManager::GetRendererFactory(const WString& elementTypeName) { vint index=rendererFactories.Keys().IndexOf(elementTypeName); return index==-1?0:rendererFactories.Values().Get(index).Obj(); } GuiGraphicsResourceManager* guiGraphicsResourceManager=0; GuiGraphicsResourceManager* GetGuiGraphicsResourceManager() { return guiGraphicsResourceManager; } void SetGuiGraphicsResourceManager(GuiGraphicsResourceManager* resourceManager) { guiGraphicsResourceManager=resourceManager; } bool RegisterFactories(IGuiGraphicsElementFactory* elementFactory, IGuiGraphicsRendererFactory* rendererFactory) { if(guiGraphicsResourceManager && elementFactory && rendererFactory) { if(guiGraphicsResourceManager->RegisterElementFactory(elementFactory)) { if(guiGraphicsResourceManager->RegisterRendererFactory(elementFactory->GetElementTypeName(), rendererFactory)) { return true; } } } return false; } } } } /*********************************************************************** GRAPHICSELEMENT\GUIGRAPHICSTEXTELEMENT.CPP ***********************************************************************/ namespace vl { using namespace collections; namespace presentation { namespace elements { namespace text { /*********************************************************************** text::TextLine ***********************************************************************/ TextLine::TextLine() :text(0) ,att(0) ,availableOffsetCount(0) ,bufferLength(0) ,dataLength(0) ,lexerFinalState(-1) ,contextFinalState(-1) { } TextLine::~TextLine() { } vint TextLine::CalculateBufferLength(vint dataLength) { if(dataLength<1)dataLength=1; vint bufferLength=dataLength-dataLength%BlockSize; if(bufferLengthdataLength || inputCount<0) return false; vint newDataLength=dataLength-count+inputCount; vint newBufferLength=CalculateBufferLength(newDataLength); if(newBufferLength!=bufferLength) { wchar_t* newText=new wchar_t[newBufferLength]; memcpy(newText, text, start*sizeof(wchar_t)); memcpy(newText+start, input, inputCount*sizeof(wchar_t)); memcpy(newText+start+inputCount, text+start+count, (dataLength-start-count)*sizeof(wchar_t)); CharAtt* newAtt=new CharAtt[newBufferLength]; memcpy(newAtt, att, start*sizeof(CharAtt)); memset(newAtt+start, 0, inputCount*sizeof(CharAtt)); memcpy(newAtt+start+inputCount, att+start+count, (dataLength-start-count)*sizeof(CharAtt)); delete[] text; delete[] att; text=newText; att=newAtt; } else { memmove(text+start+inputCount, text+start+count, (dataLength-start-count)*sizeof(wchar_t)); memmove(att+start+inputCount, att+start+count, (dataLength-start-count)*sizeof(CharAtt)); memcpy(text+start, input, inputCount*sizeof(wchar_t)); memset(att+start, 0, inputCount*sizeof(CharAtt)); } dataLength=newDataLength; bufferLength=newBufferLength; if(availableOffsetCount>start) { availableOffsetCount=start; } return true; } TextLine TextLine::Split(vint index) { if(index<0 || index>dataLength) return TextLine(); vint count=dataLength-index; TextLine line; line.Initialize(); line.Modify(0, 0, text+index, count); memcpy(line.att, att+index, count*sizeof(CharAtt)); Modify(index, count, L"", 0); return line; } void TextLine::AppendAndFinalize(TextLine& line) { vint oldDataLength=dataLength; Modify(oldDataLength, 0, line.text, line.dataLength); memcpy(att+oldDataLength, line.att, line.dataLength*sizeof(CharAtt)); line.Finalize(); } /*********************************************************************** text::CharMeasurer ***********************************************************************/ CharMeasurer::CharMeasurer(vint _rowHeight) :oldRenderTarget(0) ,rowHeight(_rowHeight) { memset(widths, 0, sizeof(widths)); } CharMeasurer::~CharMeasurer() { } void CharMeasurer::SetRenderTarget(IGuiGraphicsRenderTarget* value) { if(oldRenderTarget!=value) { oldRenderTarget=value; rowHeight=GetRowHeightInternal(oldRenderTarget); memset(widths, 0, sizeof(widths)); } } vint CharMeasurer::MeasureWidth(wchar_t character) { vint w=widths[character]; if(w==0) { widths[character]=w=MeasureWidthInternal(character, oldRenderTarget); } return w; } vint CharMeasurer::GetRowHeight() { return rowHeight; } /*********************************************************************** text::TextLines ***********************************************************************/ TextLines::TextLines() :charMeasurer(0) ,renderTarget(0) ,tabWidth(1) ,tabSpaceCount(4) ,passwordChar(L'\0') { TextLine line; line.Initialize(); lines.Add(line); } TextLines::~TextLines() { RemoveLines(0, lines.Count()); } //-------------------------------------------------------- vint TextLines::GetCount() { return lines.Count(); } TextLine& TextLines::GetLine(vint row) { return lines[row]; } CharMeasurer* TextLines::GetCharMeasurer() { return charMeasurer; } void TextLines::SetCharMeasurer(CharMeasurer* value) { charMeasurer=value; if(charMeasurer) charMeasurer->SetRenderTarget(renderTarget); ClearMeasurement(); } IGuiGraphicsRenderTarget* TextLines::GetRenderTarget() { return renderTarget; } void TextLines::SetRenderTarget(IGuiGraphicsRenderTarget* value) { renderTarget=value; if(charMeasurer) charMeasurer->SetRenderTarget(renderTarget); ClearMeasurement(); } WString TextLines::GetText(TextPos start, TextPos end) { if(!IsAvailable(start) || !IsAvailable(end) || start>end) return L""; if(start.row==end.row) { return WString(lines[start.row].text+start.column, end.column-start.column); } vint count=0; for(vint i=start.row+1;i buffer; buffer.Resize(count+(end.row-start.row)*2); wchar_t* writing=&buffer[0]; for(vint i=start.row;i<=end.row;i++) { wchar_t* text=lines[i].text; vint chars=0; if(i==start.row) { text+=start.column; chars=lines[i].dataLength-start.column; } else if(i==end.row) { chars=end.column; } else { chars=lines[i].dataLength; } if(i!=start.row) { *writing++=L'\r'; *writing++=L'\n'; } memcpy(writing, text, chars*sizeof(wchar_t)); writing+=chars; } return WString(&buffer[0], buffer.Count()); } WString TextLines::GetText() { return GetText(TextPos(0, 0), TextPos(lines.Count()-1, lines[lines.Count()-1].dataLength)); } void TextLines::SetText(const WString& value) { Modify(TextPos(0, 0), TextPos(lines.Count()-1, lines[lines.Count()-1].dataLength), value); } //-------------------------------------------------------- bool TextLines::RemoveLines(vint start, vint count) { if(start<0 || count<0 || start+count>lines.Count()) return false; for(vint i=start+count-1;i>=start;i--) { lines[i].Finalize(); } lines.RemoveRange(start, count); return true; } bool TextLines::IsAvailable(TextPos pos) { return 0<=pos.row && pos.row=lines.Count()) { return TextPos(lines.Count()-1, lines[lines.Count()-1].dataLength); } else { TextLine& line=lines[pos.row]; if(pos.column<0) { return TextPos(pos.row, 0); } else if(pos.column>line.dataLength) { return TextPos(pos.row, line.dataLength); } else { return pos; } } } TextPos TextLines::Modify(TextPos start, TextPos end, const wchar_t** inputs, vint* inputCounts, vint rows) { if(!IsAvailable(start) || !IsAvailable(end) || start>end) return TextPos(-1, -1); if(rows==1) { if(start.row==end.row) { lines[start.row].Modify(start.column, end.column-start.column, inputs[0], inputCounts[0]); } else { if(end.row-start.row>1) { RemoveLines(start.row+1, end.row-start.row-1); } vint modifyCount=lines[start.row].dataLength-start.column+end.column; lines[start.row].AppendAndFinalize(lines[start.row+1]); lines.RemoveAt(start.row+1); lines[start.row].Modify(start.column, modifyCount, inputs[0], inputCounts[0]); } return TextPos(start.row, start.column+inputCounts[0]); } if(start.row==end.row) { TextLine newLine=lines[start.row].Split(end.column); lines.Insert(start.row+1, newLine); end=TextPos(start.row+1, 0); } vint oldMiddleLines=end.row-start.row-1; vint newMiddleLines=rows-2; if(oldMiddleLinesnewMiddleLines) { RemoveLines(start.row+newMiddleLines+1, oldMiddleLines-newMiddleLines); } end.row+=newMiddleLines-oldMiddleLines; lines[start.row].Modify(start.column, lines[start.row].dataLength-start.column, inputs[0], inputCounts[0]); lines[end.row].Modify(0, end.column, inputs[rows-1], inputCounts[rows-1]); for(vint i=1;i inputs; List inputCounts; const wchar_t* previous=input; const wchar_t* current=input; while(true) { if(current==input+inputCount) { inputs.Add(previous); inputCounts.Add(current-previous); break; } else if(*current==L'\r' || *current==L'\n') { inputs.Add(previous); inputCounts.Add(current-previous); previous=current+(current[1]==L'\n'?2:1); current=previous; } else { current++; } } return Modify(start, end, &inputs[0], &inputCounts[0], inputs.Count()); } TextPos TextLines::Modify(TextPos start, TextPos end, const wchar_t* input) { return Modify(start, end, input, wcslen(input)); } TextPos TextLines::Modify(TextPos start, TextPos end, const WString& input) { return Modify(start, end, input.Buffer(), input.Length()); } void TextLines::Clear() { RemoveLines(0, lines.Count()); TextLine line; line.Initialize(); lines.Add(line); } //-------------------------------------------------------- void TextLines::ClearMeasurement() { for(vint i=0;iMeasureWidth(L' '); } if(tabWidth==0) { tabWidth=1; } } vint TextLines::GetTabSpaceCount() { return tabSpaceCount; } void TextLines::SetTabSpaceCount(vint value) { if(value<1) value=1; if(tabSpaceCount!=value) { tabSpaceCount=value; ClearMeasurement(); } } void TextLines::MeasureRow(vint row) { TextLine& line=lines[row]; vint offset=0; if(line.availableOffsetCount) { offset=line.att[line.availableOffsetCount-1].rightOffset; } for(vint i=line.availableOffsetCount;iMeasureWidth(passwordChar); } else if(c==L'\t') { width=tabWidth-offset%tabWidth; } else { width=charMeasurer->MeasureWidth(line.text[i]); } offset+=width; att.rightOffset=(int)offset; } line.availableOffsetCount=line.dataLength; } vint TextLines::GetRowWidth(vint row) { if(row<0 || row>=lines.Count()) return -1; TextLine& line=lines[row]; if(line.dataLength==0) { return 0; } else { MeasureRow(row); return line.att[line.dataLength-1].rightOffset; } } vint TextLines::GetRowHeight() { return charMeasurer->GetRowHeight(); } vint TextLines::GetMaxWidth() { vint width=0; for(vint i=0;iGetRowHeight(); } TextPos TextLines::GetTextPosFromPoint(Point point) { vint h=charMeasurer->GetRowHeight(); if(point.y<0) { point.y=0; } else if(point.y>=h*lines.Count()) { point.y=h*lines.Count()-1; } vint row=point.y/h; if(point.x<0) { return TextPos(row, 0); } else if(point.x>=GetRowWidth(row)) { return TextPos(row, lines[row].dataLength); } TextLine& line=lines[row]; vint i1=0, i2=line.dataLength; vint p1=0, p2=line.att[line.dataLength-1].rightOffset; while(i2-i1>1) { vint i=(i1+i2)/2; vint p=i==0?0:line.att[i-1].rightOffset; if(point.xGetRowHeight(); if(pos.column==0) { return Point(0, y); } else { MeasureRow(pos.row); TextLine& line=lines[pos.row]; return Point(line.att[pos.column-1].rightOffset, y); } } else { return Point(-1, -1); } } Rect TextLines::GetRectFromTextPos(TextPos pos) { Point point=GetPointFromTextPos(pos); if(point==Point(-1, -1)) { return Rect(-1, -1, -1, -1); } else { vint h=charMeasurer->GetRowHeight(); TextLine& line=lines[pos.row]; if(pos.column==line.dataLength) { return Rect(point, Size(h/2, h)); } else { return Rect(point, Size(line.att[pos.column].rightOffset-point.x, h)); } } } //-------------------------------------------------------- wchar_t TextLines::GetPasswordChar() { return passwordChar; } void TextLines::SetPasswordChar(wchar_t value) { passwordChar=value; ClearMeasurement(); } } using namespace text; /*********************************************************************** GuiColorizedTextElement ***********************************************************************/ GuiColorizedTextElement::GuiColorizedTextElement() :callback(0) ,isVisuallyEnabled(true) ,isFocused(false) ,caretVisible(false) { } GuiColorizedTextElement::~GuiColorizedTextElement() { renderer->Finalize(); } text::TextLines& GuiColorizedTextElement::GetLines() { return lines; } GuiColorizedTextElement::ICallback* GuiColorizedTextElement::GetCallback() { return callback; } void GuiColorizedTextElement::SetCallback(ICallback* value) { callback=value; if(!callback) { lines.SetCharMeasurer(0); } } const GuiColorizedTextElement::ColorArray& GuiColorizedTextElement::GetColors() { return colors; } void GuiColorizedTextElement::SetColors(const ColorArray& value) { CopyFrom(colors, value); if(callback) callback->ColorChanged(); if(renderer) { renderer->OnElementStateChanged(); } } void GuiColorizedTextElement::ResetTextColorIndex(vint index) { vint lineCount = lines.GetCount(); for (vint i = 0; i < lineCount; i++) { auto& line = lines.GetLine(i); line.lexerFinalState = -1; line.contextFinalState = -1; for (vint j = 0; j < line.dataLength; j++) { line.att[j].colorIndex = (vuint32_t)index; } } } const FontProperties& GuiColorizedTextElement::GetFont() { return font; } void GuiColorizedTextElement::SetFont(const FontProperties& value) { if(font!=value) { font=value; if(callback) { callback->FontChanged(); } if(renderer) { renderer->OnElementStateChanged(); } } } wchar_t GuiColorizedTextElement::GetPasswordChar() { return lines.GetPasswordChar(); } void GuiColorizedTextElement::SetPasswordChar(wchar_t value) { if(lines.GetPasswordChar()!=value) { lines.SetPasswordChar(value); if(renderer) { renderer->OnElementStateChanged(); } } } Point GuiColorizedTextElement::GetViewPosition() { return viewPosition; } void GuiColorizedTextElement::SetViewPosition(Point value) { if(viewPosition!=value) { viewPosition=value; if(renderer) { renderer->OnElementStateChanged(); } } } bool GuiColorizedTextElement::GetVisuallyEnabled() { return isVisuallyEnabled; } void GuiColorizedTextElement::SetVisuallyEnabled(bool value) { if(isVisuallyEnabled!=value) { isVisuallyEnabled=value; if(renderer) { renderer->OnElementStateChanged(); } } } bool GuiColorizedTextElement::GetFocused() { return isFocused; } void GuiColorizedTextElement::SetFocused(bool value) { if(isFocused!=value) { isFocused=value; if(renderer) { renderer->OnElementStateChanged(); } } } TextPos GuiColorizedTextElement::GetCaretBegin() { return caretBegin; } void GuiColorizedTextElement::SetCaretBegin(TextPos value) { caretBegin=value; } TextPos GuiColorizedTextElement::GetCaretEnd() { return caretEnd; } void GuiColorizedTextElement::SetCaretEnd(TextPos value) { caretEnd=value; } bool GuiColorizedTextElement::GetCaretVisible() { return caretVisible; } void GuiColorizedTextElement::SetCaretVisible(bool value) { caretVisible=value; } Color GuiColorizedTextElement::GetCaretColor() { return caretColor; } void GuiColorizedTextElement::SetCaretColor(Color value) { if(caretColor!=value) { caretColor=value; if(renderer) { renderer->OnElementStateChanged(); } } } } } } /*********************************************************************** NATIVEWINDOW\GUINATIVEWINDOW.CPP ***********************************************************************/ namespace vl { namespace presentation { /*********************************************************************** INativeWindowListener ***********************************************************************/ INativeWindowListener::HitTestResult INativeWindowListener::HitTest(Point location) { return INativeWindowListener::NoDecision; } void INativeWindowListener::Moving(Rect& bounds, bool fixSizeOnly) { } void INativeWindowListener::Moved() { } void INativeWindowListener::Enabled() { } void INativeWindowListener::Disabled() { } void INativeWindowListener::GotFocus() { } void INativeWindowListener::LostFocus() { } void INativeWindowListener::Activated() { } void INativeWindowListener::Deactivated() { } void INativeWindowListener::Opened() { } void INativeWindowListener::Closing(bool& cancel) { } void INativeWindowListener::Closed() { } void INativeWindowListener::Paint() { } void INativeWindowListener::Destroying() { } void INativeWindowListener::Destroyed() { } void INativeWindowListener::LeftButtonDown(const NativeWindowMouseInfo& info) { } void INativeWindowListener::LeftButtonUp(const NativeWindowMouseInfo& info) { } void INativeWindowListener::LeftButtonDoubleClick(const NativeWindowMouseInfo& info) { } void INativeWindowListener::RightButtonDown(const NativeWindowMouseInfo& info) { } void INativeWindowListener::RightButtonUp(const NativeWindowMouseInfo& info) { } void INativeWindowListener::RightButtonDoubleClick(const NativeWindowMouseInfo& info) { } void INativeWindowListener::MiddleButtonDown(const NativeWindowMouseInfo& info) { } void INativeWindowListener::MiddleButtonUp(const NativeWindowMouseInfo& info) { } void INativeWindowListener::MiddleButtonDoubleClick(const NativeWindowMouseInfo& info) { } void INativeWindowListener::HorizontalWheel(const NativeWindowMouseInfo& info) { } void INativeWindowListener::VerticalWheel(const NativeWindowMouseInfo& info) { } void INativeWindowListener::MouseMoving(const NativeWindowMouseInfo& info) { } void INativeWindowListener::MouseEntered() { } void INativeWindowListener::MouseLeaved() { } void INativeWindowListener::KeyDown(const NativeWindowKeyInfo& info) { } void INativeWindowListener::KeyUp(const NativeWindowKeyInfo& info) { } void INativeWindowListener::SysKeyDown(const NativeWindowKeyInfo& info) { } void INativeWindowListener::SysKeyUp(const NativeWindowKeyInfo& info) { } void INativeWindowListener::Char(const NativeWindowCharInfo& info) { } /*********************************************************************** INativeControllerListener ***********************************************************************/ void INativeControllerListener::LeftButtonDown(Point position) { } void INativeControllerListener::LeftButtonUp(Point position) { } void INativeControllerListener::RightButtonDown(Point position) { } void INativeControllerListener::RightButtonUp(Point position) { } void INativeControllerListener::MouseMoving(Point position) { } void INativeControllerListener::GlobalTimer() { } void INativeControllerListener::ClipboardUpdated() { } void INativeControllerListener::NativeWindowCreated(INativeWindow* window) { } void INativeControllerListener::NativeWindowDestroying(INativeWindow* window) { } /*********************************************************************** Native Window Provider ***********************************************************************/ INativeController* currentController=0; INativeController* GetCurrentController() { return currentController; } void SetCurrentController(INativeController* controller) { currentController=controller; } } } /*********************************************************************** RESOURCES\GUIDOCUMENT.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace parsing::tabling; using namespace parsing::xml; using namespace regex; /*********************************************************************** DocumentFontSize ***********************************************************************/ DocumentFontSize DocumentFontSize::Parse(const WString& value) { if (value.Length() > 0 && value[value.Length() - 1] == L'x') { return DocumentFontSize(wtof(value.Left(value.Length() - 1)), true); } else { return DocumentFontSize(wtof(value), false); } } WString DocumentFontSize::ToString()const { return ftow(size) + (relative ? L"x" : L""); } /*********************************************************************** DocumentImageRun ***********************************************************************/ const wchar_t* DocumentImageRun::RepresentationText=L"[Image]"; const wchar_t* DocumentEmbeddedObjectRun::RepresentationText=L"[EmbeddedObject]"; /*********************************************************************** ExtractTextVisitor ***********************************************************************/ namespace document_operation_visitors { class ExtractTextVisitor : public Object, public DocumentRun::IVisitor { public: stream::TextWriter& writer; bool skipNonTextContent; ExtractTextVisitor(stream::TextWriter& _writer, bool _skipNonTextContent) :writer(_writer) ,skipNonTextContent(_skipNonTextContent) { } void VisitContainer(DocumentContainerRun* run) { FOREACH(Ptr, subRun, run->runs) { subRun->Accept(this); } } void VisitContent(DocumentContentRun* run) { writer.WriteString(run->GetRepresentationText()); } void Visit(DocumentTextRun* run)override { VisitContent(run); } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { if(!skipNonTextContent) { VisitContent(run); } } void Visit(DocumentEmbeddedObjectRun* run)override { if(!skipNonTextContent) { VisitContent(run); } } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } }; } using namespace document_operation_visitors; /*********************************************************************** DocumentParagraphRun ***********************************************************************/ WString DocumentParagraphRun::GetText(bool skipNonTextContent) { stream::MemoryStream memoryStream; { stream::StreamWriter writer(memoryStream); GetText(writer, skipNonTextContent); } memoryStream.SeekFromBegin(0); stream::StreamReader reader(memoryStream); return reader.ReadToEnd(); } void DocumentParagraphRun::GetText(stream::TextWriter& writer, bool skipNonTextContent) { ExtractTextVisitor visitor(writer, skipNonTextContent); Accept(&visitor); } /*********************************************************************** DocumentModel ***********************************************************************/ const wchar_t* DocumentModel::DefaultStyleName = L"#Default"; const wchar_t* DocumentModel::SelectionStyleName = L"#Selection"; const wchar_t* DocumentModel::ContextStyleName = L"#Context"; const wchar_t* DocumentModel::NormalLinkStyleName = L"#NormalLink"; const wchar_t* DocumentModel::ActiveLinkStyleName = L"#ActiveLink"; DocumentModel::DocumentModel() { { FontProperties font=GetCurrentController()->ResourceService()->GetDefaultFont(); Ptr sp=new DocumentStyleProperties; sp->face=font.fontFamily; sp->size=DocumentFontSize(font.size, false); sp->color=Color(); sp->backgroundColor=Color(0, 0, 0, 0); sp->bold=font.bold; sp->italic=font.italic; sp->underline=font.underline; sp->strikeline=font.strikeline; sp->antialias=font.antialias; sp->verticalAntialias=font.verticalAntialias; Ptr style=new DocumentStyle; style->styles=sp; styles.Add(L"#Default", style); } { Ptr sp=new DocumentStyleProperties; sp->color=Color(255, 255, 255); sp->backgroundColor=Color(51, 153, 255); Ptr style=new DocumentStyle; style->styles=sp; styles.Add(L"#Selection", style); } { Ptr sp=new DocumentStyleProperties; Ptr style=new DocumentStyle; style->styles=sp; styles.Add(L"#Context", style); } { Ptr sp=new DocumentStyleProperties; sp->color=Color(0, 0, 255); sp->underline=true; Ptr style=new DocumentStyle; style->parentStyleName=L"#Context"; style->styles=sp; styles.Add(L"#NormalLink", style); } { Ptr sp=new DocumentStyleProperties; sp->color=Color(0, 0, 255); sp->underline=true; Ptr style=new DocumentStyle; style->parentStyleName=L"#Context"; style->styles=sp; styles.Add(L"#ActiveLink", style); } } void DocumentModel::MergeStyle(Ptr style, Ptr parent) { if(!style->face && parent->face) style->face =parent->face; if(!style->size && parent->size) style->size =parent->size; if(!style->color && parent->color) style->color =parent->color; if(!style->backgroundColor && parent->backgroundColor) style->backgroundColor =parent->backgroundColor; if(!style->bold && parent->bold) style->bold =parent->bold; if(!style->italic && parent->italic) style->italic =parent->italic; if(!style->underline && parent->underline) style->underline =parent->underline; if(!style->strikeline && parent->strikeline) style->strikeline =parent->strikeline; if(!style->antialias && parent->antialias) style->antialias =parent->antialias; if(!style->verticalAntialias && parent->verticalAntialias) style->verticalAntialias =parent->verticalAntialias; } void DocumentModel::MergeBaselineStyle(Ptr style, const WString& styleName) { auto indexDst = styles.Keys().IndexOf(styleName); Ptr sp = new DocumentStyleProperties; MergeStyle(sp, style); if (indexDst != -1) { MergeStyle(sp, styles.Values()[indexDst]->styles); } if (indexDst == -1) { auto style = new DocumentStyle; style->styles = sp; styles.Add(styleName, style); } else { styles.Values()[indexDst]->styles = sp; } FOREACH(Ptr, style, styles.Values()) { style->resolvedStyles = nullptr; } } void DocumentModel::MergeBaselineStyle(Ptr baselineDocument, const WString& styleName) { auto indexSrc = baselineDocument->styles.Keys().IndexOf(styleName); if (indexSrc == -1) { return; } auto csp = baselineDocument->styles.Values()[indexSrc]->styles; MergeBaselineStyle(csp, styleName); } void DocumentModel::MergeBaselineStyles(Ptr baselineDocument) { MergeBaselineStyle(baselineDocument, DefaultStyleName); MergeBaselineStyle(baselineDocument, SelectionStyleName); MergeBaselineStyle(baselineDocument, ContextStyleName); MergeBaselineStyle(baselineDocument, NormalLinkStyleName); MergeBaselineStyle(baselineDocument, ActiveLinkStyleName); } void DocumentModel::MergeDefaultFont(const FontProperties& defaultFont) { Ptr style = new DocumentStyleProperties; style->face =defaultFont.fontFamily; style->size =DocumentFontSize(defaultFont.size, false); style->bold =defaultFont.bold; style->italic =defaultFont.italic; style->underline =defaultFont.underline; style->strikeline =defaultFont.strikeline; style->antialias =defaultFont.antialias; style->verticalAntialias =defaultFont.verticalAntialias; MergeBaselineStyle(style, DefaultStyleName); } DocumentModel::ResolvedStyle DocumentModel::GetStyle(Ptr sp, const ResolvedStyle& context) { FontProperties font; font.fontFamily =sp->face ?sp->face.Value() :context.style.fontFamily; font.bold =sp->bold ?sp->bold.Value() :context.style.bold; font.italic =sp->italic ?sp->italic.Value() :context.style.italic; font.underline =sp->underline ?sp->underline.Value() :context.style.underline; font.strikeline =sp->strikeline ?sp->strikeline.Value() :context.style.strikeline; font.antialias =sp->antialias ?sp->antialias.Value() :context.style.antialias; font.verticalAntialias =sp->verticalAntialias ?sp->verticalAntialias.Value() :context.style.verticalAntialias; Color color =sp->color ?sp->color.Value() :context.color; Color backgroundColor =sp->backgroundColor ?sp->backgroundColor.Value() :context.backgroundColor; if (sp->size) { font.size = (vint)(sp->size.Value().relative ? context.style.size * sp->size.Value().size : sp->size.Value().size); } else { font.size = context.style.size; } return ResolvedStyle(font, color, backgroundColor); } DocumentModel::ResolvedStyle DocumentModel::GetStyle(const WString& styleName, const ResolvedStyle& context) { Ptr selectedStyle; { vint index=styles.Keys().IndexOf(styleName); if(index!=-1) { selectedStyle=styles.Values()[index]; } else { selectedStyle=styles[L"#Default"]; } } if(!selectedStyle->resolvedStyles) { Ptr sp = new DocumentStyleProperties; selectedStyle->resolvedStyles = sp; Ptr currentStyle; WString currentName = styleName; while(true) { vint index = styles.Keys().IndexOf(currentName); if (index == -1) break; currentStyle = styles.Values().Get(index); currentName = currentStyle->parentStyleName; MergeStyle(sp, currentStyle->styles); } } Ptr sp=selectedStyle->resolvedStyles; return GetStyle(sp, context); } WString DocumentModel::GetText(bool skipNonTextContent) { stream::MemoryStream memoryStream; { stream::StreamWriter writer(memoryStream); GetText(writer, skipNonTextContent); } memoryStream.SeekFromBegin(0); stream::StreamReader reader(memoryStream); return reader.ReadToEnd(); } void DocumentModel::GetText(stream::TextWriter& writer, bool skipNonTextContent) { for(vint i=0;i paragraph=paragraphs[i]; paragraph->GetText(writer, skipNonTextContent); if(i, subRun, run->runs) { subRun->Accept(this); } range.end=start; runRanges.Add(run, range); } void VisitContent(DocumentContentRun* run) { RunRange range; range.start=start; start+=run->GetRepresentationText().Length(); range.end=start; runRanges.Add(run, range); } void Visit(DocumentTextRun* run)override { VisitContent(run); } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { VisitContent(run); } void Visit(DocumentEmbeddedObjectRun* run)override { VisitContent(run); } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static void GetRunRange(DocumentParagraphRun* run, RunRangeMap& runRanges) { GetRunRangeVisitor visitor(runRanges); run->Accept(&visitor); } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::LocateStyleVisitor ***********************************************************************/ namespace document_operation_visitors { class LocateStyleVisitor : public Object, public DocumentRun::IVisitor { public: List& locatedRuns; RunRangeMap& runRanges; vint position; bool frontSide; LocateStyleVisitor(List& _locatedRuns, RunRangeMap& _runRanges, vint _position, bool _frontSide) :locatedRuns(_locatedRuns) ,runRanges(_runRanges) ,position(_position) ,frontSide(_frontSide) { } void VisitContainer(DocumentContainerRun* run) { locatedRuns.Add(run); Ptr selectedRun; FOREACH(Ptr, subRun, run->runs) { RunRange range=runRanges[subRun.Obj()]; if(position==range.start) { if(!frontSide) { selectedRun=subRun; break; } } else if(position==range.end) { if(frontSide) { selectedRun=subRun; break; } } else if(range.startAccept(this); } } void Visit(DocumentTextRun* run)override { } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { } void Visit(DocumentEmbeddedObjectRun* run)override { } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static void LocateStyle(DocumentParagraphRun* run, RunRangeMap& runRanges, vint position, bool frontSide, List& locatedRuns) { LocateStyleVisitor visitor(locatedRuns, runRanges, position, frontSide); run->Accept(&visitor); } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::LocateHyperlinkVisitor ***********************************************************************/ namespace document_operation_visitors { class LocateHyperlinkVisitor : public Object, public DocumentRun::IVisitor { public: Ptr hyperlink; RunRangeMap& runRanges; vint start; vint end; LocateHyperlinkVisitor(RunRangeMap& _runRanges, vint _start, vint _end) :runRanges(_runRanges) ,start(_start) ,end(_end) { } void VisitContainer(DocumentContainerRun* run) { Ptr selectedRun; FOREACH(Ptr, subRun, run->runs) { RunRange range=runRanges[subRun.Obj()]; if(range.start<=start && end<=range.end) { selectedRun=subRun; break; } } if(selectedRun) { selectedRun->Accept(this); } } void Visit(DocumentTextRun* run)override { } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { hyperlink=run; } void Visit(DocumentImageRun* run)override { } void Visit(DocumentEmbeddedObjectRun* run)override { } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static Ptr LocateHyperlink(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end) { LocateHyperlinkVisitor visitor(runRanges, start, end); run->Accept(&visitor); return visitor.hyperlink; } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::CloneRunVisitor ***********************************************************************/ namespace document_operation_visitors { class CloneRunVisitor : public Object, public DocumentRun::IVisitor { public: Ptr clonedRun; CloneRunVisitor(Ptr subRun) :clonedRun(subRun) { } void VisitContainer(Ptr cloned) { if(clonedRun) { cloned->runs.Add(clonedRun); } clonedRun=cloned; } void Visit(DocumentTextRun* run)override { Ptr cloned=new DocumentTextRun; cloned->text=run->text; clonedRun=cloned; } void Visit(DocumentStylePropertiesRun* run)override { Ptr cloned=new DocumentStylePropertiesRun; cloned->style=CopyStyle(run->style); VisitContainer(cloned); } void Visit(DocumentStyleApplicationRun* run)override { Ptr cloned=new DocumentStyleApplicationRun; cloned->styleName=run->styleName; VisitContainer(cloned); } void Visit(DocumentHyperlinkRun* run)override { Ptr cloned=new DocumentHyperlinkRun; cloned->styleName=run->styleName; cloned->normalStyleName=run->normalStyleName; cloned->activeStyleName=run->activeStyleName; cloned->reference=run->reference; VisitContainer(cloned); } void Visit(DocumentImageRun* run)override { Ptr cloned=new DocumentImageRun; cloned->size=run->size; cloned->baseline=run->baseline; cloned->image=run->image; cloned->frameIndex=run->frameIndex; cloned->source=run->source; clonedRun=cloned; } void Visit(DocumentEmbeddedObjectRun* run)override { Ptr cloned=new DocumentEmbeddedObjectRun; cloned->name=run->name; clonedRun=cloned; } void Visit(DocumentParagraphRun* run)override { Ptr cloned=new DocumentParagraphRun; cloned->alignment=run->alignment; VisitContainer(cloned); } static Ptr CopyStyle(Ptr style) { Ptr newStyle=new DocumentStyleProperties; newStyle->face =style->face; newStyle->size =style->size; newStyle->color =style->color; newStyle->backgroundColor =style->backgroundColor; newStyle->bold =style->bold; newStyle->italic =style->italic; newStyle->underline =style->underline; newStyle->strikeline =style->strikeline; newStyle->antialias =style->antialias; newStyle->verticalAntialias =style->verticalAntialias; return newStyle; } static Ptr CopyRun(DocumentRun* run) { CloneRunVisitor visitor(0); run->Accept(&visitor); return visitor.clonedRun; } static Ptr CopyStyledText(List& styleRuns, const WString& text) { Ptr textRun=new DocumentTextRun; textRun->text=text; CloneRunVisitor visitor(textRun); for(vint i=styleRuns.Count()-1;i>=0;i--) { styleRuns[i]->Accept(&visitor); } return visitor.clonedRun; } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::CloneRunRecursivelyVisitor ***********************************************************************/ namespace document_operation_visitors { class CloneRunRecursivelyVisitor : public Object, public DocumentRun::IVisitor { public: Ptr clonedRun; RunRangeMap& runRanges; vint start; vint end; bool deepCopy; CloneRunRecursivelyVisitor(RunRangeMap& _runRanges, vint _start, vint _end, bool _deepCopy) :runRanges(_runRanges) ,start(_start) ,end(_end) ,deepCopy(_deepCopy) { } void VisitContainer(DocumentContainerRun* run) { clonedRun=0; RunRange range=runRanges[run]; if(range.start<=end && start<=range.end) { if(start<=range.start && range.end<=end && !deepCopy) { clonedRun=run; } else { Ptr containerRun=CloneRunVisitor::CopyRun(run).Cast(); FOREACH(Ptr, subRun, run->runs) { subRun->Accept(this); if(clonedRun) { containerRun->runs.Add(clonedRun); } } clonedRun=containerRun; } } } void Visit(DocumentTextRun* run)override { clonedRun=0; RunRange range=runRanges[run]; if(range.start textRun=new DocumentTextRun; vint copyStart=start>range.start?start:range.start; vint copyEnd=endtext=run->text.Sub(copyStart-range.start, copyEnd-copyStart); } clonedRun=textRun; } } } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { clonedRun=0; RunRange range=runRanges[run]; if(range.start CopyRun(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end, bool deepCopy) { CloneRunRecursivelyVisitor visitor(runRanges, start, end, deepCopy); run->Accept(&visitor); return visitor.clonedRun; } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::CollectStyleNameVisitor ***********************************************************************/ namespace document_operation_visitors { class CollectStyleNameVisitor : public Object, public DocumentRun::IVisitor { public: List& styleNames; CollectStyleNameVisitor(List& _styleNames) :styleNames(_styleNames) { } void VisitContainer(DocumentContainerRun* run) { FOREACH(Ptr, subRun, run->runs) { subRun->Accept(this); } } void Visit(DocumentTextRun* run)override { } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { if(!styleNames.Contains(run->styleName)) { styleNames.Add(run->styleName); } VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { if(!styleNames.Contains(run->normalStyleName)) { styleNames.Add(run->normalStyleName); } if(!styleNames.Contains(run->activeStyleName)) { styleNames.Add(run->activeStyleName); } VisitContainer(run); } void Visit(DocumentImageRun* run)override { } void Visit(DocumentEmbeddedObjectRun* run)override { } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static void CollectStyleName(DocumentParagraphRun* run, List& styleNames) { CollectStyleNameVisitor visitor(styleNames); run->Accept(&visitor); } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::ReplaceStyleNameVisitor ***********************************************************************/ namespace document_operation_visitors { class ReplaceStyleNameVisitor : public Object, public DocumentRun::IVisitor { public: WString oldStyleName; WString newStyleName; ReplaceStyleNameVisitor(const WString& _oldStyleName, const WString& _newStyleName) :oldStyleName(_oldStyleName) ,newStyleName(_newStyleName) { } void VisitContainer(DocumentContainerRun* run) { FOREACH(Ptr, subRun, run->runs) { subRun->Accept(this); } } void Visit(DocumentTextRun* run)override { } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { if(run->styleName==oldStyleName) run->styleName=newStyleName; VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { if(run->styleName==oldStyleName) run->styleName=newStyleName; if(run->normalStyleName==oldStyleName) run->normalStyleName=newStyleName; if(run->activeStyleName==oldStyleName) run->activeStyleName=newStyleName; VisitContainer(run); } void Visit(DocumentImageRun* run)override { } void Visit(DocumentEmbeddedObjectRun* run)override { } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static void ReplaceStyleName(DocumentParagraphRun* run, const WString& oldStyleName, const WString& newStyleName) { ReplaceStyleNameVisitor visitor(oldStyleName, newStyleName); run->Accept(&visitor); } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::RemoveRunVisitor ***********************************************************************/ namespace document_operation_visitors { class RemoveRunVisitor : public Object, public DocumentRun::IVisitor { public: RunRangeMap& runRanges; vint start; vint end; List> replacedRuns; RemoveRunVisitor(RunRangeMap& _runRanges, vint _start, vint _end) :runRanges(_runRanges) ,start(_start) ,end(_end) { } void VisitContainer(DocumentContainerRun* run) { if(start==end) return; for(vint i=run->runs.Count()-1;i>=0;i--) { Ptr subRun=run->runs[i]; RunRange range=runRanges[subRun.Obj()]; if(range.start<=end && start<=range.end) { subRun->Accept(this); if(replacedRuns.Count()==0 || subRun!=replacedRuns[0]) { run->runs.RemoveAt(i); for(vint j=0;jruns.Insert(i+j, replacedRuns[j]); } } } } replacedRuns.Clear(); replacedRuns.Add(run); } void Visit(DocumentTextRun* run)override { replacedRuns.Clear(); RunRange range=runRanges[run]; if(start<=range.start) { if(endtext=run->text.Sub(end-range.start, range.end-end); replacedRuns.Add(run); } } else { if(endtext=run->text.Sub(0, start-range.start); secondRun->text=run->text.Sub(end-range.start, range.end-end); replacedRuns.Add(firstRun); replacedRuns.Add(secondRun); } else { run->text=run->text.Sub(0, start-range.start); replacedRuns.Add(run); } } } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { replacedRuns.Clear(); } void Visit(DocumentEmbeddedObjectRun* run)override { replacedRuns.Clear(); } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static void RemoveRun(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end) { RemoveRunVisitor visitor(runRanges, start, end); run->Accept(&visitor); } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::CutRunVisitor ***********************************************************************/ namespace document_operation_visitors { class CutRunVisitor : public Object, public DocumentRun::IVisitor { public: RunRangeMap& runRanges; vint position; Ptr leftRun; Ptr rightRun; CutRunVisitor(RunRangeMap& _runRanges, vint _position) :runRanges(_runRanges) ,position(_position) { } void VisitContainer(DocumentContainerRun* run) { vint leftCount=0; Ptr selectedRun; FOREACH(Ptr, subRun, run->runs) { RunRange range=runRanges[subRun.Obj()]; if(range.startAccept(this); if(leftRun && rightRun) { run->runs.RemoveAt(leftCount-1); run->runs.Insert(leftCount-1, leftRun); run->runs.Insert(leftCount, rightRun); } } Ptr leftContainer=CloneRunVisitor::CopyRun(run).Cast(); Ptr rightContainer=CloneRunVisitor::CopyRun(run).Cast(); for(vint i=0;iruns.Count();i++) { (iruns.Add(run->runs[i]); } leftRun=leftContainer; rightRun=rightContainer; } void Visit(DocumentTextRun* run)override { RunRange range=runRanges[run]; Ptr leftText=new DocumentTextRun; leftText->text=run->text.Sub(0, position-range.start); Ptr rightText=new DocumentTextRun; rightText->text=run->text.Sub(position-range.start, range.end-position); leftRun=leftText; rightRun=rightText; } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { leftRun=0; rightRun=0; } void Visit(DocumentEmbeddedObjectRun* run)override { leftRun=0; rightRun=0; } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static void CutRun(DocumentParagraphRun* run, RunRangeMap& runRanges, vint position, Ptr& leftRun, Ptr& rightRun) { CutRunVisitor visitor(runRanges, position); run->Accept(&visitor); leftRun=visitor.leftRun; rightRun=visitor.rightRun; } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::ClearRunVisitor ***********************************************************************/ namespace document_operation_visitors { class ClearRunVisitor : public Object, public DocumentRun::IVisitor { public: vint start; ClearRunVisitor() :start(0) { } void VisitContainer(DocumentContainerRun* run) { for(vint i=run->runs.Count()-1;i>=0;i--) { vint oldStart=start; run->runs[i]->Accept(this); if(oldStart==start) { run->runs.RemoveAt(i); } } } void VisitContent(DocumentContentRun* run) { start+=run->GetRepresentationText().Length(); } void Visit(DocumentTextRun* run)override { VisitContent(run); } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { VisitContent(run); } void Visit(DocumentEmbeddedObjectRun* run)override { VisitContent(run); } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static void ClearRun(DocumentParagraphRun* run) { ClearRunVisitor visitor; run->Accept(&visitor); } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::AddContainerVisitor ***********************************************************************/ namespace document_operation_visitors { class AddContainerVisitor : public Object, public DocumentRun::IVisitor { public: RunRangeMap& runRanges; vint start; vint end; bool insertStyle; virtual Ptr CreateContainer()=0; AddContainerVisitor(RunRangeMap& _runRanges, vint _start, vint _end) :runRanges(_runRanges) ,start(_start) ,end(_end) ,insertStyle(false) { } void VisitContainer(DocumentContainerRun* run) { for(vint i=run->runs.Count()-1;i>=0;i--) { Ptr subRun=run->runs[i]; RunRange range=runRanges[subRun.Obj()]; if(range.startAccept(this); if(insertStyle) { Ptr containerRun=CreateContainer(); run->runs.RemoveAt(i); containerRun->runs.Add(subRun); run->runs.Insert(i, containerRun); } } } insertStyle=false; } void Visit(DocumentTextRun* run)override { insertStyle=true; } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { insertStyle=false; } void Visit(DocumentEmbeddedObjectRun* run)override { insertStyle=false; } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } }; class AddStyleVisitor : public AddContainerVisitor { public: Ptr style; Ptr CreateContainer()override { Ptr containerRun=new DocumentStylePropertiesRun; containerRun->style=CloneRunVisitor::CopyStyle(style); return containerRun; } AddStyleVisitor(RunRangeMap& _runRanges, vint _start, vint _end, Ptr _style) :AddContainerVisitor(_runRanges, _start, _end) ,style(_style) { } static void AddStyle(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end, Ptr style) { AddStyleVisitor visitor(runRanges, start, end, style); run->Accept(&visitor); } }; class AddHyperlinkVisitor : public AddContainerVisitor { public: WString reference; WString normalStyleName; WString activeStyleName; Ptr CreateContainer()override { Ptr containerRun=new DocumentHyperlinkRun; containerRun->reference=reference; containerRun->normalStyleName=normalStyleName; containerRun->activeStyleName=activeStyleName; containerRun->styleName=normalStyleName; return containerRun; } AddHyperlinkVisitor(RunRangeMap& _runRanges, vint _start, vint _end, const WString& _reference, const WString& _normalStyleName, const WString& _activeStyleName) :AddContainerVisitor(_runRanges, _start, _end) ,reference(_reference) ,normalStyleName(_normalStyleName) ,activeStyleName(_activeStyleName) { } static void AddHyperlink(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end, const WString& reference, const WString& normalStyleName, const WString& activeStyleName) { AddHyperlinkVisitor visitor(runRanges, start, end, reference, normalStyleName, activeStyleName); run->Accept(&visitor); } }; class AddStyleNameVisitor : public AddContainerVisitor { public: WString styleName; Ptr CreateContainer()override { Ptr containerRun=new DocumentStyleApplicationRun; containerRun->styleName=styleName; return containerRun; } AddStyleNameVisitor(RunRangeMap& _runRanges, vint _start, vint _end, const WString& _styleName) :AddContainerVisitor(_runRanges, _start, _end) ,styleName(_styleName) { } static void AddStyleName(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end, const WString& styleName) { AddStyleNameVisitor visitor(runRanges, start, end, styleName); run->Accept(&visitor); } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::RemoveContainerVisitor ***********************************************************************/ namespace document_operation_visitors { class RemoveContainerVisitor : public Object, public DocumentRun::IVisitor { public: RunRangeMap& runRanges; vint start; vint end; List> replacedRuns; RemoveContainerVisitor(RunRangeMap& _runRanges, vint _start, vint _end) :runRanges(_runRanges) ,start(_start) ,end(_end) { } void VisitContainer(DocumentContainerRun* run) { for(vint i=run->runs.Count()-1;i>=0;i--) { Ptr subRun=run->runs[i]; RunRange range=runRanges[subRun.Obj()]; if(range.startAccept(this); if(replacedRuns.Count()!=1 || replacedRuns[0]!=subRun) { run->runs.RemoveAt(i); for(vint j=0;jruns.Insert(i+j, replacedRuns[j]); } i+=replacedRuns.Count(); } } } replacedRuns.Clear(); replacedRuns.Add(run); } void VisitContent(DocumentContentRun* run) { replacedRuns.Add(run); } void RemoveContainer(DocumentContainerRun* run) { CopyFrom(replacedRuns, run->runs); } void Visit(DocumentTextRun* run)override { VisitContent(run); } void Visit(DocumentStylePropertiesRun* run)override { VisitContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { VisitContainer(run); } void Visit(DocumentHyperlinkRun* run)override { VisitContainer(run); } void Visit(DocumentImageRun* run)override { VisitContent(run); } void Visit(DocumentEmbeddedObjectRun* run)override { VisitContent(run); } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } }; class RemoveHyperlinkVisitor : public RemoveContainerVisitor { public: RemoveHyperlinkVisitor(RunRangeMap& _runRanges, vint _start, vint _end) :RemoveContainerVisitor(_runRanges, _start, _end) { } void Visit(DocumentHyperlinkRun* run)override { RemoveContainer(run); } static void RemoveHyperlink(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end) { RemoveHyperlinkVisitor visitor(runRanges, start, end); run->Accept(&visitor); } }; class RemoveStyleNameVisitor : public RemoveContainerVisitor { public: RemoveStyleNameVisitor(RunRangeMap& _runRanges, vint _start, vint _end) :RemoveContainerVisitor(_runRanges, _start, _end) { } void Visit(DocumentStyleApplicationRun* run)override { RemoveContainer(run); } static void RemoveStyleName(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end) { RemoveStyleNameVisitor visitor(runRanges, start, end); run->Accept(&visitor); } }; class ClearStyleVisitor : public RemoveContainerVisitor { public: ClearStyleVisitor(RunRangeMap& _runRanges, vint _start, vint _end) :RemoveContainerVisitor(_runRanges, _start, _end) { } void Visit(DocumentStylePropertiesRun* run)override { RemoveContainer(run); } void Visit(DocumentStyleApplicationRun* run)override { RemoveContainer(run); } static void ClearStyle(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end) { ClearStyleVisitor visitor(runRanges, start, end); run->Accept(&visitor); } }; } using namespace document_operation_visitors; /*********************************************************************** document_operation_visitors::SummerizeStyleVisitor ***********************************************************************/ namespace document_operation_visitors { class SummerizeStyleVisitor : public Object, public DocumentRun::IVisitor { public: RunRangeMap& runRanges; DocumentModel* model; vint start; vint end; Ptr style; List resolvedStyles; SummerizeStyleVisitor(RunRangeMap& _runRanges, DocumentModel* _model, vint _start, vint _end) :runRanges(_runRanges) ,model(_model) ,start(_start) ,end(_end) { DocumentModel::ResolvedStyle resolvedStyle; resolvedStyle = model->GetStyle(DocumentModel::DefaultStyleName, resolvedStyle); resolvedStyles.Add(resolvedStyle); } const DocumentModel::ResolvedStyle& GetCurrentResolvedStyle() { return resolvedStyles[resolvedStyles.Count()-1]; } // --------------------------------------------------------- template void SetStyleItem(Nullable DocumentStyleProperties::* dstField, T FontProperties::* srcField) { const DocumentModel::ResolvedStyle& src = GetCurrentResolvedStyle(); if (style.Obj()->*dstField && (style.Obj()->*dstField).Value() != src.style.*srcField) { style.Obj()->*dstField = Nullable(); } } template void SetStyleItem(Nullable DocumentStyleProperties::* dstField, T DocumentModel::ResolvedStyle::* srcField) { const DocumentModel::ResolvedStyle& src = GetCurrentResolvedStyle(); if (style.Obj()->*dstField && (style.Obj()->*dstField).Value() != src.*srcField) { style.Obj()->*dstField = Nullable(); } } void SetStyleItem(Nullable DocumentStyleProperties::* dstField, vint FontProperties::* srcField) { const DocumentModel::ResolvedStyle& src = GetCurrentResolvedStyle(); if (style.Obj()->*dstField) { auto dfs = (style.Obj()->*dstField).Value(); if (dfs.relative || dfs.size != src.style.*srcField) { style.Obj()->*dstField = Nullable(); } } } // --------------------------------------------------------- template void OverrideStyleItem(Nullable DocumentStyleProperties::* dstField, T FontProperties::* srcField) { const DocumentModel::ResolvedStyle& src = GetCurrentResolvedStyle(); style.Obj()->*dstField = src.style.*srcField; } template void OverrideStyleItem(Nullable DocumentStyleProperties::* dstField, T DocumentModel::ResolvedStyle::* srcField) { const DocumentModel::ResolvedStyle& src = GetCurrentResolvedStyle(); style.Obj()->*dstField = src.*srcField; } void OverrideStyleItem(Nullable DocumentStyleProperties::* dstField, vint FontProperties::* srcField) { const DocumentModel::ResolvedStyle& src = GetCurrentResolvedStyle(); style.Obj()->*dstField = DocumentFontSize(src.style.*srcField, false); } // --------------------------------------------------------- void VisitContainer(DocumentContainerRun* run) { for(vint i=run->runs.Count()-1;i>=0;i--) { Ptr subRun=run->runs[i]; RunRange range=runRanges[subRun.Obj()]; if(range.startAccept(this); } } } void Visit(DocumentTextRun* run)override { const DocumentModel::ResolvedStyle& currentResolvedStyle=GetCurrentResolvedStyle(); if (style) { SetStyleItem(&DocumentStyleProperties::face, &FontProperties::fontFamily); SetStyleItem(&DocumentStyleProperties::size, &FontProperties::size); SetStyleItem(&DocumentStyleProperties::color, &DocumentModel::ResolvedStyle::color); SetStyleItem(&DocumentStyleProperties::backgroundColor, &DocumentModel::ResolvedStyle::backgroundColor); SetStyleItem(&DocumentStyleProperties::bold, &FontProperties::bold); SetStyleItem(&DocumentStyleProperties::italic, &FontProperties::italic); SetStyleItem(&DocumentStyleProperties::underline, &FontProperties::underline); SetStyleItem(&DocumentStyleProperties::strikeline, &FontProperties::strikeline); SetStyleItem(&DocumentStyleProperties::antialias, &FontProperties::antialias); SetStyleItem(&DocumentStyleProperties::verticalAntialias, &FontProperties::verticalAntialias); } else { style=new DocumentStyleProperties; OverrideStyleItem(&DocumentStyleProperties::face, &FontProperties::fontFamily); OverrideStyleItem(&DocumentStyleProperties::size, &FontProperties::size); OverrideStyleItem(&DocumentStyleProperties::color, &DocumentModel::ResolvedStyle::color); OverrideStyleItem(&DocumentStyleProperties::backgroundColor, &DocumentModel::ResolvedStyle::backgroundColor); OverrideStyleItem(&DocumentStyleProperties::bold, &FontProperties::bold); OverrideStyleItem(&DocumentStyleProperties::italic, &FontProperties::italic); OverrideStyleItem(&DocumentStyleProperties::underline, &FontProperties::underline); OverrideStyleItem(&DocumentStyleProperties::strikeline, &FontProperties::strikeline); OverrideStyleItem(&DocumentStyleProperties::antialias, &FontProperties::antialias); OverrideStyleItem(&DocumentStyleProperties::verticalAntialias, &FontProperties::verticalAntialias); } } void Visit(DocumentStylePropertiesRun* run)override { const DocumentModel::ResolvedStyle& currentResolvedStyle=GetCurrentResolvedStyle(); DocumentModel::ResolvedStyle resolvedStyle=model->GetStyle(run->style, currentResolvedStyle); resolvedStyles.Add(resolvedStyle); VisitContainer(run); resolvedStyles.RemoveAt(resolvedStyles.Count()-1); } void Visit(DocumentStyleApplicationRun* run)override { const DocumentModel::ResolvedStyle& currentResolvedStyle=GetCurrentResolvedStyle(); DocumentModel::ResolvedStyle resolvedStyle=model->GetStyle(run->styleName, currentResolvedStyle); resolvedStyles.Add(resolvedStyle); VisitContainer(run); resolvedStyles.RemoveAt(resolvedStyles.Count()-1); } void Visit(DocumentHyperlinkRun* run)override { const DocumentModel::ResolvedStyle& currentResolvedStyle=GetCurrentResolvedStyle(); DocumentModel::ResolvedStyle resolvedStyle=model->GetStyle(run->styleName, currentResolvedStyle); resolvedStyles.Add(resolvedStyle); VisitContainer(run); resolvedStyles.RemoveAt(resolvedStyles.Count()-1); } void Visit(DocumentImageRun* run)override { } void Visit(DocumentEmbeddedObjectRun* run)override { } void Visit(DocumentParagraphRun* run)override { VisitContainer(run); } static Ptr SummerizeStyle(DocumentParagraphRun* run, RunRangeMap& runRanges, DocumentModel* model, vint start, vint end) { SummerizeStyleVisitor visitor(runRanges, model, start, end); run->Accept(&visitor); return visitor.style; } template static void AggregateStyleItem(Ptr& dst, Ptr src, Nullable DocumentStyleProperties::* field) { if(dst.Obj()->*field && (!(src.Obj()->*field) || (dst.Obj()->*field).Value()!=(src.Obj()->*field).Value())) { dst.Obj()->*field=Nullable(); } } static void AggregateStyle(Ptr& dst, Ptr src) { AggregateStyleItem(dst, src, &DocumentStyleProperties::face); AggregateStyleItem(dst, src, &DocumentStyleProperties::size); AggregateStyleItem(dst, src, &DocumentStyleProperties::color); AggregateStyleItem(dst, src, &DocumentStyleProperties::backgroundColor); AggregateStyleItem(dst, src, &DocumentStyleProperties::bold); AggregateStyleItem(dst, src, &DocumentStyleProperties::italic); AggregateStyleItem(dst, src, &DocumentStyleProperties::underline); AggregateStyleItem(dst, src, &DocumentStyleProperties::strikeline); AggregateStyleItem(dst, src, &DocumentStyleProperties::antialias); AggregateStyleItem(dst, src, &DocumentStyleProperties::verticalAntialias); } }; } using namespace document_operation_visitors; /*********************************************************************** DocumentModel::EditRangeOperations ***********************************************************************/ bool DocumentModel::CheckEditRange(TextPos begin, TextPos end, RunRangeMap& relatedRanges) { // check caret range if(begin>end) return false; if(begin.row<0 || begin.row>=paragraphs.Count()) return false; if(end.row<0 || end.row>=paragraphs.Count()) return false; // determine run ranges GetRunRangeVisitor::GetRunRange(paragraphs[begin.row].Obj(), relatedRanges); if(begin.row!=end.row) { GetRunRangeVisitor::GetRunRange(paragraphs[end.row].Obj(), relatedRanges); } // check caret range RunRange beginRange=relatedRanges[paragraphs[begin.row].Obj()]; RunRange endRange=relatedRanges[paragraphs[end.row].Obj()]; if(begin.column<0 || begin.column>beginRange.end) return false; if(end.column<0 || end.column>endRange.end) return false; return true; } Ptr DocumentModel::CopyDocument(TextPos begin, TextPos end, bool deepCopy) { // check caret range RunRangeMap runRanges; if(!CheckEditRange(begin, end, runRanges)) return 0; // get ranges for(vint i=begin.row+1;i newDocument=new DocumentModel; // copy paragraphs if(begin.row==end.row) { newDocument->paragraphs.Add(CloneRunRecursivelyVisitor::CopyRun(paragraphs[begin.row].Obj(), runRanges, begin.column, end.column, deepCopy).Cast()); } else { for(vint i=begin.row;i<=end.row;i++) { Ptr paragraph=paragraphs[i]; RunRange range=runRanges[paragraph.Obj()]; if(i==begin.row) { newDocument->paragraphs.Add(CloneRunRecursivelyVisitor::CopyRun(paragraph.Obj(), runRanges, begin.column, range.end, deepCopy).Cast()); } else if(i==end.row) { newDocument->paragraphs.Add(CloneRunRecursivelyVisitor::CopyRun(paragraph.Obj(), runRanges, range.start, end.column, deepCopy).Cast()); } else if(deepCopy) { newDocument->paragraphs.Add(CloneRunRecursivelyVisitor::CopyRun(paragraph.Obj(), runRanges, range.start, range.end, deepCopy).Cast()); } else { newDocument->paragraphs.Add(paragraph); } } } // copy styles List styleNames; FOREACH(Ptr, paragraph, newDocument->paragraphs) { CollectStyleNameVisitor::CollectStyleName(paragraph.Obj(), styleNames); } for(vint i=0;istyles.Keys().Contains(styleName)) { Ptr style=styles[styleName]; if(deepCopy) { Ptr newStyle=new DocumentStyle; newStyle->parentStyleName=style->parentStyleName; newStyle->styles=CloneRunVisitor::CopyStyle(style->styles); newStyle->resolvedStyles=CloneRunVisitor::CopyStyle(style->resolvedStyles); newDocument->styles.Add(styleName, newStyle); } else { newDocument->styles.Add(styleName, style); } if(!styleNames.Contains(style->parentStyleName)) { styleNames.Add(style->parentStyleName); } } } return newDocument; } bool DocumentModel::CutParagraph(TextPos position) { if(position.row<0 || position.row>=paragraphs.Count()) return false; Ptr paragraph=paragraphs[position.row]; RunRangeMap runRanges; Ptr leftRun, rightRun; GetRunRangeVisitor::GetRunRange(paragraph.Obj(), runRanges); CutRunVisitor::CutRun(paragraph.Obj(), runRanges, position.column, leftRun, rightRun); CopyFrom(paragraph->runs, leftRun.Cast()->runs); CopyFrom(paragraph->runs, rightRun.Cast()->runs, true); return true; } bool DocumentModel::CutEditRange(TextPos begin, TextPos end) { // check caret range if(begin>end) return false; if(begin.row<0 || begin.row>=paragraphs.Count()) return false; if(end.row<0 || end.row>=paragraphs.Count()) return false; // cut paragraphs CutParagraph(begin); if(begin!=end) { CutParagraph(end); } return true; } bool DocumentModel::EditContainer(TextPos begin, TextPos end, const Func& editor) { if(begin==end) return false; // cut paragraphs if(!CutEditRange(begin, end)) return false; // check caret range RunRangeMap runRanges; if(!CheckEditRange(begin, end, runRanges)) return false; // edit container if(begin.row==end.row) { editor(paragraphs[begin.row].Obj(), runRanges, begin.column, end.column); } else { for(vint i=begin.row;i<=end.row;i++) { Ptr paragraph=paragraphs[i]; if(begin.row model) { // check caret range RunRangeMap runRanges; if(!CheckEditRange(begin, end, runRanges)) return -1; // calculate new names for the model's styles to prevent conflicting List oldNames, newNames; CopyFrom(oldNames, model->styles.Keys()); CopyFrom(newNames, model->styles.Keys()); for(vint i=0;istyles.Keys().Contains(newName)) { newNames[i]=newName; break; } } } } // rename model's styles typedef Pair NamePair; FOREACH(NamePair, name, From(oldNames).Pairwise(newNames)) { model->RenameStyle(name.key, name.value); } FOREACH(WString, name, newNames) { if((name.Length()==0 || name[0]!=L'#') && !styles.Keys().Contains(name)) { styles.Add(name, model->styles[name]); } } // edit runs Array> runs; CopyFrom(runs, model->paragraphs); return EditRun(begin, end, runs); } vint DocumentModel::EditRun(TextPos begin, TextPos end, const collections::Array>& runs) { // check caret range RunRangeMap runRanges; if(!CheckEditRange(begin, end, runRanges)) return -1; // remove unnecessary paragraphs if(begin.row!=end.row) { for(vint i=end.row-1;i>begin.row;i--) { paragraphs.RemoveAt(i); } end.row=begin.row+1; } // remove unnecessary runs and ensure begin.row!=end.row if(begin.row==end.row) { RemoveRunVisitor::RemoveRun(paragraphs[begin.row].Obj(), runRanges, begin.column, end.column); Ptr leftRun, rightRun; runRanges.Clear(); GetRunRangeVisitor::GetRunRange(paragraphs[begin.row].Obj(), runRanges); CutRunVisitor::CutRun(paragraphs[begin.row].Obj(), runRanges, begin.column, leftRun, rightRun); paragraphs.RemoveAt(begin.row); paragraphs.Insert(begin.row, leftRun.Cast()); paragraphs.Insert(begin.row+1, rightRun.Cast()); end.row=begin.row+1; } else { RemoveRunVisitor::RemoveRun(paragraphs[begin.row].Obj(), runRanges, begin.column, runRanges[paragraphs[begin.row].Obj()].end); RemoveRunVisitor::RemoveRun(paragraphs[end.row].Obj(), runRanges, 0, end.column); } // insert new paragraphs Ptr beginParagraph=paragraphs[begin.row]; Ptr endParagraph=paragraphs[end.row]; if(runs.Count()==0) { CopyFrom(beginParagraph->runs, endParagraph->runs, true); paragraphs.RemoveAt(end.row); } else if(runs.Count()==1) { CopyFrom(beginParagraph->runs, runs[0]->runs, true); CopyFrom(beginParagraph->runs, endParagraph->runs, true); paragraphs.RemoveAt(end.row); } else { Ptr newBeginRuns=runs[0]; CopyFrom(beginParagraph->runs, newBeginRuns->runs, true); Ptr newEndRuns=runs[runs.Count()-1]; if (newEndRuns->alignment) { endParagraph->alignment = newEndRuns->alignment; } for(vint i=0;iruns.Count();i++) { endParagraph->runs.Insert(i, newEndRuns->runs[i]); } for(vint i=1;i& text) { // check caret range RunRangeMap runRanges; if(!CheckEditRange(begin, end, runRanges)) return -1; // calcuate the position to get the text style TextPos stylePosition; if(frontSide) { stylePosition=begin; if(stylePosition.column==0) { frontSide=false; } } else { stylePosition=end; if(stylePosition.column==runRanges[paragraphs[end.row].Obj()].end) { frontSide=true; } } // copy runs that contains the target style for new text List styleRuns; LocateStyleVisitor::LocateStyle(paragraphs[stylePosition.row].Obj(), runRanges, stylePosition.column, frontSide, styleRuns); // create paragraphs Array> runs(text.Count()); for(vint i=0;i paragraph=CloneRunVisitor::CopyStyledText(styleRuns, text[i]); runs[i]=paragraph.Cast(); } // replace the paragraphs return EditRun(begin, end, runs); } /*********************************************************************** DocumentModel::EditStyle ***********************************************************************/ bool DocumentModel::EditStyle(TextPos begin, TextPos end, Ptr style) { return EditContainer(begin, end, [=](DocumentParagraphRun* paragraph, RunRangeMap& runRanges, vint start, vint end) { AddStyleVisitor::AddStyle(paragraph, runRanges, start, end, style); }); } /*********************************************************************** DocumentModel::EditImage ***********************************************************************/ Ptr DocumentModel::EditImage(TextPos begin, TextPos end, Ptr image) { Ptr imageRun=new DocumentImageRun; imageRun->size=image->GetImage()->GetFrame(image->GetFrameIndex())->GetSize(); imageRun->baseline=imageRun->size.y; imageRun->image=image->GetImage(); imageRun->frameIndex=image->GetFrameIndex(); Ptr paragraph=new DocumentParagraphRun; paragraph->runs.Add(imageRun); Array> runs(1); runs[0]=paragraph; if(EditRun(begin, end, runs)) { return imageRun; } else { return 0; } } /*********************************************************************** DocumentModel::EditHyperlink ***********************************************************************/ bool DocumentModel::EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName, const WString& activeStyleName) { Ptr run=GetHyperlink(paragraphIndex, begin, end); if(run) { run->reference=reference; run->normalStyleName=normalStyleName; run->activeStyleName=activeStyleName; run->styleName=normalStyleName; return true; } else if(RemoveHyperlink(paragraphIndex, begin, end)) { CutEditRange(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end)); RunRangeMap runRanges; Ptr paragraph=paragraphs[paragraphIndex]; GetRunRangeVisitor::GetRunRange(paragraph.Obj(), runRanges); AddHyperlinkVisitor::AddHyperlink(paragraph.Obj(), runRanges, begin, end, reference, normalStyleName, activeStyleName); ClearRunVisitor::ClearRun(paragraph.Obj()); return true; } return false; } bool DocumentModel::RemoveHyperlink(vint paragraphIndex, vint begin, vint end) { RunRangeMap runRanges; if(!CheckEditRange(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), runRanges)) return false; Ptr paragraph=paragraphs[paragraphIndex]; RemoveHyperlinkVisitor::RemoveHyperlink(paragraph.Obj(), runRanges, begin, end); ClearRunVisitor::ClearRun(paragraph.Obj()); return true; } Ptr DocumentModel::GetHyperlink(vint paragraphIndex, vint begin, vint end) { RunRangeMap runRanges; if(!CheckEditRange(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), runRanges)) return 0; Ptr paragraph=paragraphs[paragraphIndex]; return LocateHyperlinkVisitor::LocateHyperlink(paragraph.Obj(), runRanges, begin, end); } /*********************************************************************** DocumentModel::EditStyleName ***********************************************************************/ bool DocumentModel::EditStyleName(TextPos begin, TextPos end, const WString& styleName) { return EditContainer(begin, end, [=](DocumentParagraphRun* paragraph, RunRangeMap& runRanges, vint start, vint end) { AddStyleNameVisitor::AddStyleName(paragraph, runRanges, start, end, styleName); }); } bool DocumentModel::RemoveStyleName(TextPos begin, TextPos end) { return EditContainer(begin, end, [=](DocumentParagraphRun* paragraph, RunRangeMap& runRanges, vint start, vint end) { RemoveStyleNameVisitor::RemoveStyleName(paragraph, runRanges, start, end); }); } bool DocumentModel::RenameStyle(const WString& oldStyleName, const WString& newStyleName) { vint index=styles.Keys().IndexOf(oldStyleName); if(index==-1) return false; if(styles.Keys().Contains(newStyleName)) return false; Ptr style=styles.Values()[index]; styles.Remove(oldStyleName); styles.Add(newStyleName, style); FOREACH(Ptr, subStyle, styles.Values()) { if(subStyle->parentStyleName==oldStyleName) { subStyle->parentStyleName=newStyleName; } } FOREACH(Ptr, paragraph, paragraphs) { ReplaceStyleNameVisitor::ReplaceStyleName(paragraph.Obj(), oldStyleName, newStyleName); } return true; } /*********************************************************************** DocumentModel::ClearStyle ***********************************************************************/ bool DocumentModel::ClearStyle(TextPos begin, TextPos end) { return EditContainer(begin, end, [=](DocumentParagraphRun* paragraph, RunRangeMap& runRanges, vint start, vint end) { ClearStyleVisitor::ClearStyle(paragraph, runRanges, start, end); }); } /*********************************************************************** DocumentModel::ClearStyle ***********************************************************************/ Ptr DocumentModel::SummarizeStyle(TextPos begin, TextPos end) { Ptr style; RunRangeMap runRanges; if(begin==end) goto END_OF_SUMMERIZING; // check caret range if(!CheckEditRange(begin, end, runRanges)) return nullptr; // summerize container if(begin.row==end.row) { style=SummerizeStyleVisitor::SummerizeStyle(paragraphs[begin.row].Obj(), runRanges, this, begin.column, end.column); } else { for(vint i=begin.row;i<=end.row;i++) { Ptr paragraph=paragraphs[i]; if(begin.row paragraphStyle; if(i==begin.row) { paragraphStyle=SummerizeStyleVisitor::SummerizeStyle(paragraph.Obj(), runRanges, this, begin.column, range.end); } else if(i==end.row) { paragraphStyle=SummerizeStyleVisitor::SummerizeStyle(paragraph.Obj(), runRanges, this, range.start, end.column); } else { paragraphStyle=SummerizeStyleVisitor::SummerizeStyle(paragraph.Obj(), runRanges, this, range.start, range.end); } if(!style) { style=paragraphStyle; } else if(paragraphStyle) { SummerizeStyleVisitor::AggregateStyle(style, paragraphStyle); } } } END_OF_SUMMERIZING: if(!style) { style=new DocumentStyleProperties; } return style; } } } /*********************************************************************** RESOURCES\GUIDOCUMENT_LOAD.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace parsing::tabling; using namespace parsing::xml; using namespace regex; /*********************************************************************** document_operation_visitors::DeserializeNodeVisitor ***********************************************************************/ namespace document_operation_visitors { class DeserializeNodeVisitor : public XmlNode::IVisitor { public: Ptr model; Ptr container; vint paragraphIndex; Ptr resolver; Regex regexAttributeApply; List& errors; DeserializeNodeVisitor(Ptr _model, Ptr _paragraph, vint _paragraphIndex, Ptr _resolver, List& _errors) :model(_model) , container(_paragraph) , paragraphIndex(_paragraphIndex) , resolver(_resolver) , regexAttributeApply(L"/{@([^{}]+)/}") , errors(_errors) { } void PrintText(const WString& text) { Ptr run=new DocumentTextRun; run->text=text; container->runs.Add(run); } void Visit(XmlText* node)override { PrintText(node->content.value); } void Visit(XmlCData* node)override { PrintText(node->content.value); } void Visit(XmlAttribute* node)override { } void Visit(XmlComment* node)override { } void Visit(XmlElement* node)override { Ptr createdContainer; bool useTemplateInfo=false; XmlElement* subNodeContainer=node; if(node->name.value==L"br") { PrintText(L"\r\n"); } else if(node->name.value==L"sp") { PrintText(L" "); } else if(node->name.value==L"tab") { PrintText(L"\t"); } else if(node->name.value==L"img") { Ptr run=new DocumentImageRun; run->baseline = -1; if(Ptr source=XmlGetAttribute(node, L"source")) { run->source=source->value.value; WString protocol, path; if(IsResourceUrl(run->source, protocol, path)) { Ptr imageData=resolver->ResolveResource(protocol, path).Cast(); if(imageData) { run->image=imageData->GetImage(); } if(run->image && run->image->GetFrameCount()>0) { run->size=run->image->GetFrame(0)->GetSize(); run->frameIndex=0; } } FOREACH(Ptr, att, node->attributes) { if(att->name.value==L"width") { run->size.x=wtoi(att->value.value); } else if(att->name.value==L"height") { run->size.y=wtoi(att->value.value); } else if(att->name.value==L"baseline") { run->baseline=wtoi(att->value.value); } else if(att->name.value==L"frameIndex") { run->frameIndex=wtoi(att->value.value); } else if (att->name.value != L"source") { errors.Add(L"Unknown attribute in \"" + att->name.value + L"\"."); } } container->runs.Add(run); } } else if(node->name.value==L"object") { Ptr run=new DocumentEmbeddedObjectRun; run->baseline = -1; if(Ptr name=XmlGetAttribute(node, L"name")) { run->name = name->value.value; container->runs.Add(run); } else { errors.Add(L"The \"name\" attribute in is missing."); } } else if(node->name.value==L"font") { Ptr run=new DocumentStylePropertiesRun(); Ptr sp=new DocumentStyleProperties; run->style=sp; FOREACH(Ptr, att, node->attributes) { if(att->name.value==L"face") { sp->face=att->value.value; } else if(att->name.value==L"size") { sp->size=DocumentFontSize::Parse(att->value.value); } else if(att->name.value==L"color") { sp->color=Color::Parse(att->value.value); } else if(att->name.value==L"bkcolor") { sp->backgroundColor=Color::Parse(att->value.value); } else { errors.Add(L"Unknown attribute in \"" + att->name.value + L"\"."); } } container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"b" || node->name.value==L"b-") { Ptr run=new DocumentStylePropertiesRun(); run->style=new DocumentStyleProperties; run->style->bold=node->name.value==L"b"; container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"i" || node->name.value==L"i-") { Ptr run=new DocumentStylePropertiesRun(); run->style=new DocumentStyleProperties; run->style->italic=node->name.value==L"i"; container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"u" || node->name.value==L"u-") { Ptr run=new DocumentStylePropertiesRun(); run->style=new DocumentStyleProperties; run->style->underline=node->name.value==L"u"; container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"s" || node->name.value==L"s-") { Ptr run=new DocumentStylePropertiesRun(); run->style=new DocumentStyleProperties; run->style->strikeline=node->name.value==L"s"; container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"ha") { Ptr run=new DocumentStylePropertiesRun(); run->style=new DocumentStyleProperties; run->style->antialias=true; run->style->verticalAntialias=false; container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"va") { Ptr run=new DocumentStylePropertiesRun(); run->style=new DocumentStyleProperties; run->style->antialias=true; run->style->verticalAntialias=true; container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"na") { Ptr run=new DocumentStylePropertiesRun(); run->style=new DocumentStyleProperties; run->style->antialias=false; run->style->verticalAntialias=false; container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"div") { if(Ptr att=XmlGetAttribute(node, L"style")) { WString styleName=att->value.value; Ptr run=new DocumentStyleApplicationRun; run->styleName=styleName; container->runs.Add(run); createdContainer=run; } else { createdContainer=container; } } else if(node->name.value==L"a") { Ptr run=new DocumentHyperlinkRun; run->normalStyleName=L"#NormalLink"; run->activeStyleName=L"#ActiveLink"; if(Ptr att=XmlGetAttribute(node, L"normal")) { run->normalStyleName=att->value.value; } if(Ptr att=XmlGetAttribute(node, L"active")) { run->activeStyleName=att->value.value; } if(Ptr att=XmlGetAttribute(node, L"href")) { run->reference=att->value.value; } run->styleName=run->normalStyleName; container->runs.Add(run); createdContainer=run; } else if(node->name.value==L"p") { FOREACH(Ptr, sub, node->subNodes) { sub->Accept(this); } } else { if (node->name.value != L"nop") { errors.Add(L"Unknown tag in document resource \"" + node->name.value + L"\"."); } FOREACH(Ptr, sub, node->subNodes) { sub->Accept(this); } } if(createdContainer) { Ptr oldContainer=container; container=createdContainer; FOREACH(Ptr, subNode, subNodeContainer->subNodes) { subNode->Accept(this); } container=oldContainer; } } void Visit(XmlInstruction* node)override { } void Visit(XmlDocument* node)override { } }; Ptr ParseDocumentStyle(Ptr styleElement) { Ptr style=new DocumentStyle; if(Ptr parent=XmlGetAttribute(styleElement, L"parent")) { style->parentStyleName=parent->value.value; } Ptr sp=new DocumentStyleProperties; style->styles=sp; FOREACH(Ptr, att, XmlGetElements(styleElement)) { if(att->name.value==L"face") { sp->face=XmlGetValue(att); } else if(att->name.value==L"size") { sp->size=DocumentFontSize::Parse(XmlGetValue(att)); } else if(att->name.value==L"color") { sp->color=Color::Parse(XmlGetValue(att)); } else if(att->name.value==L"bkcolor") { sp->backgroundColor=Color::Parse(XmlGetValue(att)); } else if(att->name.value==L"b") { sp->bold=XmlGetValue(att)==L"true"; } else if(att->name.value==L"i") { sp->italic=XmlGetValue(att)==L"true"; } else if(att->name.value==L"u") { sp->underline=XmlGetValue(att)==L"true"; } else if(att->name.value==L"s") { sp->strikeline=XmlGetValue(att)==L"true"; } else if(att->name.value==L"antialias") { WString value=XmlGetValue(att); if(value==L"horizontal" || value==L"default") { sp->antialias=true; sp->verticalAntialias=false; } else if(value==L"no") { sp->antialias=false; sp->verticalAntialias=false; } else if(value==L"vertical") { sp->antialias=true; sp->verticalAntialias=true; } } } return style; } } using namespace document_operation_visitors; /*********************************************************************** DocumentModel ***********************************************************************/ Ptr DocumentModel::LoadFromXml(Ptr xml, Ptr resolver, collections::List& errors) { Ptr model=new DocumentModel; if(xml->rootElement->name.value==L"Doc") { if(Ptr styles=XmlGetElement(xml->rootElement, L"Styles")) { FOREACH(Ptr, styleElement, XmlGetElements(styles, L"Style")) if (Ptr name = XmlGetAttribute(styleElement, L"name")) { auto style = ParseDocumentStyle(styleElement); auto styleName = name->value.value; if(!model->styles.Keys().Contains(styleName)) { model->styles.Add(styleName, style); if (styleName.Length() > 9 && styleName.Right(9) == L"-Override") { auto overridedStyle = MakePtr(); overridedStyle->styles = new DocumentStyleProperties; MergeStyle(overridedStyle->styles, style->styles); styleName = styleName.Left(styleName.Length() - 9); auto index = model->styles.Keys().IndexOf(styleName); if (index == -1) { model->styles.Add(styleName, overridedStyle); } else { auto originalStyle = model->styles.Values()[index]; MergeStyle(overridedStyle->styles, originalStyle->styles); originalStyle->styles = overridedStyle->styles; } } } } } if(Ptr content=XmlGetElement(xml->rootElement, L"Content")) { FOREACH_INDEXER(Ptr, p, i, XmlGetElements(content, L"p")) { Ptr paragraph=new DocumentParagraphRun; if(Ptr att=XmlGetAttribute(p, L"align")) { if(att->value.value==L"Left") { paragraph->alignment=Alignment::Left; } else if(att->value.value==L"Center") { paragraph->alignment=Alignment::Center; } else if(att->value.value==L"Right") { paragraph->alignment=Alignment::Right; } } model->paragraphs.Add(paragraph); DeserializeNodeVisitor visitor(model, paragraph, i, resolver, errors); p->Accept(&visitor); } } } return model; } Ptr DocumentModel::LoadFromXml(Ptr xml, const WString& workingDirectory, collections::List& errors) { Ptr resolver=new GuiResourcePathResolver(0, workingDirectory); return LoadFromXml(xml, resolver, errors); } Ptr DocumentModel::LoadFromXml(const WString& filePath, collections::List& errors) { Ptr xml; Ptr document; if(auto parser=GetParserManager()->GetParser(L"XML")) { WString text; if(LoadTextFile(filePath, text)) { xml = parser->TypedParse(text, errors); } else { errors.Add(L"Failed to load file \"" + filePath + L"\"."); } } if(xml) { document = DocumentModel::LoadFromXml(xml, GetFolderPath(filePath), errors); } return document; } } } /*********************************************************************** RESOURCES\GUIDOCUMENT_SAVE.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace parsing::xml; /*********************************************************************** document_operation_visitors::SerializeRunVisitor ***********************************************************************/ namespace document_operation_visitors { class SerializeRunVisitor : public Object, public DocumentRun::IVisitor { protected: DocumentModel* model; Ptr parent; public: SerializeRunVisitor(DocumentModel* _model, Ptr _parent) :model(_model) ,parent(_parent) { } void VisitContainer(Ptr replacedParent, DocumentContainerRun* run) { if(replacedParent) { parent->subNodes.Add(replacedParent); Ptr oldParent=parent; parent=replacedParent; FOREACH(Ptr, subRun, run->runs) { subRun->Accept(this); } parent=oldParent; } else { FOREACH(Ptr, subRun, run->runs) { subRun->Accept(this); } } } void Visit(DocumentTextRun* run)override { if(run->text!=L"") { auto writer = XmlElementWriter(parent).Element(L"nop"); auto begin = run->text.Buffer(); auto reading = begin; auto last = reading; while (true) { const wchar_t* tag = nullptr; auto c = *reading; switch (c) { case L'\n': tag = L"br"; break; case L' ': tag = L"sp"; break; case L'\t': tag = L"tab"; break; } if (tag || c == 0) { if (reading > last) { auto end = reading[-1] == L'\r' ? reading - 1 : reading; if (end > last) { writer.Text(run->text.Sub(last - begin, end - last)); } last = reading; } } if (tag) { writer.Element(tag); } else if (c == 0) { break; } reading++; } } } void Visit(DocumentStylePropertiesRun* run)override { Ptr sp=run->style; Ptr oldParent=parent; if(sp->face || sp->size || sp->color) { Ptr element=new XmlElement; element->name.value=L"font"; parent->subNodes.Add(element); XmlElementWriter writer(element); if(sp->face) { writer.Attribute(L"face", sp->face.Value()); } if(sp->size) { writer.Attribute(L"size", sp->size.Value().ToString()); } if(sp->color) { writer.Attribute(L"color", sp->color.Value().ToString()); } if(sp->backgroundColor) { writer.Attribute(L"bkcolor", sp->backgroundColor.Value().ToString()); } parent=element; } if(sp->bold) { Ptr element=new XmlElement; element->name.value=sp->bold.Value()?L"b":L"b-"; parent->subNodes.Add(element); parent=element; } if(sp->italic) { Ptr element=new XmlElement; element->name.value=sp->italic.Value()?L"i":L"i-"; parent->subNodes.Add(element); parent=element; } if(sp->underline) { Ptr element=new XmlElement; element->name.value=sp->underline.Value()?L"u":L"u-"; parent->subNodes.Add(element); parent=element; } if(sp->strikeline) { Ptr element=new XmlElement; element->name.value=sp->strikeline.Value()?L"s":L"s-"; parent->subNodes.Add(element); parent=element; } if(sp->antialias || sp->verticalAntialias) { bool ha=sp->antialias?sp->antialias.Value():true; bool va=sp->verticalAntialias?sp->verticalAntialias.Value():false; if(!ha) { Ptr element=new XmlElement; element->name.value=L"ha"; parent->subNodes.Add(element); parent=element; } else if(!va) { Ptr element=new XmlElement; element->name.value=L"va"; parent->subNodes.Add(element); parent=element; } else { Ptr element=new XmlElement; element->name.value=L"na"; parent->subNodes.Add(element); parent=element; } } VisitContainer(0, run); parent=oldParent; } void Visit(DocumentStyleApplicationRun* run)override { Ptr element=new XmlElement; element->name.value=L"div"; XmlElementWriter(element).Attribute(L"style", run->styleName); VisitContainer(element, run); } void Visit(DocumentHyperlinkRun* run)override { Ptr element=new XmlElement; element->name.value=L"a"; XmlElementWriter writer(element); if(run->normalStyleName!=L"#NormalLink") { writer.Attribute(L"normal", run->normalStyleName); } if(run->activeStyleName!=L"#ActiveLink") { writer.Attribute(L"active", run->activeStyleName); } if(run->reference!=L"") { writer.Attribute(L"href", run->reference); } VisitContainer(element, run); } void Visit(DocumentImageRun* run)override { XmlElementWriter writer(parent); writer .Element(L"img") .Attribute(L"width", itow(run->size.x)) .Attribute(L"height", itow(run->size.y)) .Attribute(L"baseline", itow(run->baseline)) .Attribute(L"frameIndex", itow(run->frameIndex)) .Attribute(L"source", run->source) ; } void Visit(DocumentEmbeddedObjectRun* run)override { XmlElementWriter writer(parent); writer .Element(L"object") .Attribute(L"name", run->name) ; } void Visit(DocumentParagraphRun* run)override { Ptr element=new XmlElement; element->name.value=L"p"; XmlElementWriter writer(element); if (run->alignment) { switch(run->alignment.Value()) { case Alignment::Left: writer.Attribute(L"align", L"Left"); break; case Alignment::Center: writer.Attribute(L"align", L"Center"); break; case Alignment::Right: writer.Attribute(L"align", L"Right"); break; } } VisitContainer(element, run); } }; } using namespace document_operation_visitors; /*********************************************************************** DocumentModel ***********************************************************************/ Ptr DocumentModel::SaveToXml() { Ptr xml=new XmlDocument; Ptr doc=new XmlElement; doc->name.value=L"Doc"; xml->rootElement=doc; { Ptr content=new XmlElement; content->name.value=L"Content"; doc->subNodes.Add(content); FOREACH(Ptr, p, paragraphs) { SerializeRunVisitor visitor(this, content); p->Accept(&visitor); } } { Ptr stylesElement=new XmlElement; stylesElement->name.value=L"Styles"; doc->subNodes.Add(stylesElement); for(vint i=0;i0 && name[0] == L'#' && (name.Length() <= 9 || name.Right(9) != L"-Override")) continue; Ptr style=styles.Values().Get(i); Ptr sp=style->styles; Ptr styleElement=new XmlElement; styleElement->name.value=L"Style"; stylesElement->subNodes.Add(styleElement); XmlElementWriter(styleElement).Attribute(L"name", name); if(style->parentStyleName!=L"") { XmlElementWriter(styleElement).Attribute(L"parent", style->parentStyleName); } if(sp->face) XmlElementWriter(styleElement).Element(L"face").Text( sp->face.Value() ); if(sp->size) XmlElementWriter(styleElement).Element(L"size").Text( sp->size.Value().ToString() ); if(sp->color) XmlElementWriter(styleElement).Element(L"color").Text( sp->color.Value().ToString() ); if(sp->backgroundColor) XmlElementWriter(styleElement).Element(L"bkcolor").Text( sp->color.Value().ToString() ); if(sp->bold) XmlElementWriter(styleElement).Element(L"b").Text( sp->bold.Value()?L"true":L"false" ); if(sp->italic) XmlElementWriter(styleElement).Element(L"i").Text( sp->italic.Value()?L"true":L"false" ); if(sp->underline) XmlElementWriter(styleElement).Element(L"u").Text( sp->underline.Value()?L"true":L"false" ); if(sp->strikeline) XmlElementWriter(styleElement).Element(L"s").Text( sp->strikeline.Value()?L"true":L"false" ); if(sp->antialias && sp->verticalAntialias) { bool h=sp->antialias; bool v=sp->verticalAntialias; if(!h) { XmlElementWriter(styleElement).Element(L"antialias").Text(L"no"); } else if(!v) { XmlElementWriter(styleElement).Element(L"antialias").Text(L"horizontal"); } else { XmlElementWriter(styleElement).Element(L"antialias").Text(L"vertical"); } } } } return xml; } bool DocumentModel::SaveToXml(const WString& filePath) { Ptr xml=SaveToXml(); if(xml) { stream::FileStream fileStream(filePath, stream::FileStream::WriteOnly); stream::BomEncoder encoder(stream::BomEncoder::Utf16); stream::EncoderStream encoderStream(fileStream, encoder); stream::StreamWriter writer(encoderStream); XmlPrint(xml, writer); return true; } return false; } } } /*********************************************************************** RESOURCES\GUIPARSERMANAGER.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace controls; using namespace parsing::tabling; using namespace parsing::xml; using namespace parsing::json; using namespace regex; /*********************************************************************** IGuiParserManager ***********************************************************************/ IGuiParserManager* parserManager=0; IGuiParserManager* GetParserManager() { return parserManager; } class GuiParserManager : public Object, public IGuiParserManager, public IGuiPlugin { protected: Dictionary> tables; Dictionary()>> loaders; SpinLock lock; Dictionary> parsers; public: GuiParserManager() { } ~GuiParserManager() { } void Load()override { parserManager=this; SetParsingTable(L"XML", &XmlLoadTable); SetParsingTable(L"JSON", &JsonLoadTable); SetTableParser(L"XML", L"XML", &XmlParseDocument); SetTableParser(L"JSON", L"JSON", &JsonParse); } void AfterLoad()override { } void Unload()override { parserManager=0; } Ptr GetParsingTable(const WString& name)override { SPIN_LOCK(lock) { vint index=tables.Keys().IndexOf(name); if(index!=-1) { return tables.Values()[index]; } index=loaders.Keys().IndexOf(name); if(index!=-1) { Ptr
table=loaders.Values()[index](); tables.Add(name, table); return table; } } return 0; } bool SetParsingTable(const WString& name, Func()> loader)override { if(loaders.Keys().Contains(name)) return false; loaders.Add(name, loader); return true; } Ptr GetParser(const WString& name)override { vint index=parsers.Keys().IndexOf(name); return index == -1 ? nullptr : parsers.Values()[index]; } bool SetParser(const WString& name, Ptr parser)override { if(parsers.Keys().Contains(name)) return false; parsers.Add(name, parser); return true; } }; GUI_REGISTER_PLUGIN(GuiParserManager) } } /*********************************************************************** RESOURCES\GUIRESOURCE.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace controls; using namespace collections; using namespace parsing::tabling; using namespace parsing::xml; using namespace parsing::json; using namespace regex; using namespace stream; WString GetFolderPath(const WString& filePath) { for(vint i=filePath.Length()-1;i>=0;i--) { if(filePath[i]==L'\\' || filePath[i]==L'/') { return filePath.Sub(0, i+1); } } return L""; } WString GetFileName(const WString& filePath) { for(vint i=filePath.Length()-1;i>=0;i--) { if(filePath[i]==L'\\' || filePath[i]==L'/') { return filePath.Sub(i+1, filePath.Length()-i-1); } } return filePath; } bool LoadTextFile(const WString& filePath, WString& text) { stream::FileStream fileStream(filePath, stream::FileStream::ReadOnly); return LoadTextFromStream(fileStream, text); } bool LoadTextFromStream(stream::IStream& stream, WString& text) { if(stream.IsAvailable()) { stream::BomDecoder decoder; stream::DecoderStream decoderStream(stream, decoder); stream::StreamReader reader(decoderStream); text=reader.ReadToEnd(); return true; } return false; } bool IsResourceUrl(const WString& text, WString& protocol, WString& path) { Pair index=INVLOC.FindFirst(text, L"://", Locale::None); if(index.key!=-1) { protocol=INVLOC.ToLower(text.Sub(0, index.key)); path=text.Sub(index.key+index.value, text.Length()-index.key-index.value); return true; } else { return false; } } vint HexToInt(wchar_t c) { if (L'0' <= c && c <= L'9') { return c - L'0'; } else if (L'A' <= c && c <= L'F') { return c - L'A' + 10; } else { return 0; } } void HexToBinary(stream::IStream& stream, const WString& hexText) { const wchar_t* buffer = hexText.Buffer(); vint count = hexText.Length() / 2; for (vint i = 0; i < count; i++) { vuint8_t byte = (vuint8_t)(HexToInt(buffer[0]) * 16 + HexToInt(buffer[1])); buffer += 2; stream.Write(&byte, 1); } } WString BinaryToHex(stream::IStream& stream) { stream::MemoryStream memoryStream; { stream::StreamWriter writer(memoryStream); vuint8_t byte; while (stream.Read(&byte, 1) == 1) { writer.WriteChar(L"0123456789ABCDEF"[byte / 16]); writer.WriteChar(L"0123456789ABCDEF"[byte % 16]); } } memoryStream.SeekFromBegin(0); { stream::StreamReader reader(memoryStream); return reader.ReadToEnd(); } } /*********************************************************************** GlobalStringKey ***********************************************************************/ GlobalStringKey GlobalStringKey::Empty; GlobalStringKey GlobalStringKey::_Set; GlobalStringKey GlobalStringKey::_Ref; GlobalStringKey GlobalStringKey::_Bind; GlobalStringKey GlobalStringKey::_Format; GlobalStringKey GlobalStringKey::_Eval; GlobalStringKey GlobalStringKey::_Uri; GlobalStringKey GlobalStringKey::_ControlTemplate; GlobalStringKey GlobalStringKey::_ItemTemplate; class GlobalStringKeyManager { public: Dictionary stoi; List itos; void InitializeConstants() { GlobalStringKey::_Set = GlobalStringKey::Get(L"set"); GlobalStringKey::_Ref = GlobalStringKey::Get(L"ref"); GlobalStringKey::_Bind = GlobalStringKey::Get(L"bind"); GlobalStringKey::_Format = GlobalStringKey::Get(L"format"); GlobalStringKey::_Eval = GlobalStringKey::Get(L"eval"); GlobalStringKey::_Uri = GlobalStringKey::Get(L"uri"); GlobalStringKey::_ControlTemplate = GlobalStringKey::Get(L"ControlTemplate"); GlobalStringKey::_ItemTemplate = GlobalStringKey::Get(L"ItemTemplate"); } }* globalStringKeyManager = 0; GlobalStringKey GlobalStringKey::Get(const WString& string) { GlobalStringKey key; if (string != L"") { vint index = globalStringKeyManager->stoi.Keys().IndexOf(string); if (index == -1) { key.key = globalStringKeyManager->itos.Add(string); globalStringKeyManager->stoi.Add(string, key.key); } else { key.key = globalStringKeyManager->stoi.Values()[index]; } } return key; } vint GlobalStringKey::ToKey()const { return key; } WString GlobalStringKey::ToString()const { return *this == GlobalStringKey::Empty ? L"" : globalStringKeyManager->itos[key]; } /*********************************************************************** GuiImageData ***********************************************************************/ GuiImageData::GuiImageData() :frameIndex(-1) { } GuiImageData::GuiImageData(Ptr _image, vint _frameIndex, const WString& _filePath) :image(_image) , frameIndex(_frameIndex) , filePath(_filePath) { } GuiImageData::~GuiImageData() { } Ptr GuiImageData::GetImage() { return image; } vint GuiImageData::GetFrameIndex() { return frameIndex; } const WString& GuiImageData::GetFilePath() { return filePath; } /*********************************************************************** GuiTextData ***********************************************************************/ GuiTextData::GuiTextData() { } GuiTextData::GuiTextData(const WString& _text) :text(_text) { } WString GuiTextData::GetText() { return text; } /*********************************************************************** GuiResourceNodeBase ***********************************************************************/ GuiResourceNodeBase::GuiResourceNodeBase() :parent(0) { } GuiResourceNodeBase::~GuiResourceNodeBase() { } const WString& GuiResourceNodeBase::GetName() { return name; } WString GuiResourceNodeBase::GetResourcePath() { auto resourcePath = name; auto current = parent; while (current && current->GetParent()) { resourcePath = current->GetName() + L"/" + resourcePath; current = current->GetParent(); } return resourcePath; } const WString& GuiResourceNodeBase::GetFileContentPath() { return fileContentPath; } void GuiResourceNodeBase::SetFileContentPath(const WString& value) { fileContentPath = value; } GuiResourceFolder* GuiResourceNodeBase::GetParent() { return parent; } /*********************************************************************** GuiResourceItem ***********************************************************************/ GuiResourceItem::GuiResourceItem() { } GuiResourceItem::~GuiResourceItem() { } const WString& GuiResourceItem::GetTypeName() { return typeName; } Ptr GuiResourceItem::GetContent() { return content; } void GuiResourceItem::SetContent(const WString& _typeName, Ptr value) { typeName = _typeName; content = value; } Ptr GuiResourceItem::AsImage() { return content.Cast(); } Ptr GuiResourceItem::AsXml() { return content.Cast(); } Ptr GuiResourceItem::AsString() { return content.Cast(); } Ptr GuiResourceItem::AsDocument() { return content.Cast(); } /*********************************************************************** GuiResourceFolder ***********************************************************************/ void GuiResourceFolder::LoadResourceFolderFromXml(DelayLoadingList& delayLoadings, const WString& containingFolder, Ptr folderXml, collections::List& errors) { ClearItems(); ClearFolders(); FOREACH(Ptr, element, XmlGetElements(folderXml)) { WString name; if(Ptr nameAtt=XmlGetAttribute(element, L"name")) { name=nameAtt->value.value; } if(element->name.value==L"Folder") { if (name == L"") { errors.Add(L"A resource folder should have a name."); errors.Add( L"Format: RESOURCE, Row: " + itow(element->codeRange.start.row + 1) + L", Column: " + itow(element->codeRange.start.column + 1) + L", Message: A resource folder should have a name."); } else { Ptr folder=new GuiResourceFolder; if(AddFolder(name, folder)) { WString newContainingFolder=containingFolder; Ptr newFolderXml=element; if(Ptr contentAtt=XmlGetAttribute(element, L"content")) { if(contentAtt->value.value==L"Link") { folder->SetFileContentPath(XmlGetValue(element)); WString filePath = containingFolder + folder->GetFileContentPath(); WString text; if(LoadTextFile(filePath, text)) { if(auto parser=GetParserManager()->GetParser(L"XML")) { if(auto xml=parser->TypedParse(text, errors)) { newContainingFolder=GetFolderPath(filePath); newFolderXml=xml->rootElement; } } } else { errors.Add(L"Failed to load file \"" + filePath + L"\"."); } } } folder->LoadResourceFolderFromXml(delayLoadings, newContainingFolder, newFolderXml, errors); } else { errors.Add(L"Duplicated resource folder name \"" + name + L"\"."); } } } else if(element->name.value.Length() <= 3 || element->name.value.Sub(0, 4) != L"ref.") { WString relativeFilePath; WString filePath; if(Ptr contentAtt=XmlGetAttribute(element, L"content")) { if(contentAtt->value.value==L"File") { relativeFilePath = XmlGetValue(element); filePath = containingFolder + relativeFilePath; if(name==L"") { name=GetFileName(filePath); } } } Ptr item = new GuiResourceItem; if(AddItem(name, item)) { WString type = element->name.value; IGuiResourceTypeResolver* typeResolver = GetResourceResolverManager()->GetTypeResolver(type); IGuiResourceTypeResolver* preloadResolver = typeResolver; if(typeResolver) { if (!typeResolver->DirectLoadXml()) { WString preloadType = typeResolver->IndirectLoad()->GetPreloadType(); if (preloadType != L"") { preloadResolver = GetResourceResolverManager()->GetTypeResolver(preloadType); if (!preloadResolver) { errors.Add(L"Unknown resource resolver \"" + preloadType + L"\" of resource type \"" + type + L"\"."); } } } } else { errors.Add(L"Unknown resource type \"" + type + L"\"."); } if(typeResolver && preloadResolver) { if (auto directLoad = preloadResolver->DirectLoadXml()) { Ptr resource; WString itemType = preloadResolver->GetType(); if (filePath == L"") { resource = directLoad->ResolveResource(element, errors); } else { item->SetFileContentPath(relativeFilePath); resource = directLoad->ResolveResource(filePath, errors); } if (typeResolver != preloadResolver) { if (auto indirectLoad = typeResolver->IndirectLoad()) { if(indirectLoad->IsDelayLoad()) { DelayLoading delayLoading; delayLoading.type = type; delayLoading.workingDirectory = containingFolder; delayLoading.preloadResource = item; delayLoadings.Add(delayLoading); } else if(resource) { resource = indirectLoad->ResolveResource(resource, 0, errors); itemType = typeResolver->GetType(); } } else { resource = 0; errors.Add(L"Resource type \"" + typeResolver->GetType() + L"\" is not a indirect load resource type."); } } item->SetContent(itemType, resource); } else { errors.Add(L"Resource type \"" + preloadResolver->GetType() + L"\" is not a direct load resource type."); } } if(!item->GetContent()) { RemoveItem(name); } } else { errors.Add(L"Duplicated resource item name \"" + name + L"\"."); } } } } void GuiResourceFolder::SaveResourceFolderToXml(Ptr xmlParent) { FOREACH(Ptr, item, items.Values()) { auto resolver = GetResourceResolverManager()->GetTypeResolver(item->GetTypeName()); if (resolver->XmlSerializable()) { auto attName = MakePtr(); attName->name.value = L"name"; attName->value.value = item->GetName(); if (item->GetFileContentPath() == L"") { Ptr xmlElement; if (auto directLoad = resolver->DirectLoadXml()) { xmlElement = directLoad->Serialize(item->GetContent()); } else if (auto indirectLoad = resolver->IndirectLoad()) { if (auto preloadResolver = GetResourceResolverManager()->GetTypeResolver(indirectLoad->GetPreloadType())) { if (auto directLoad = preloadResolver->DirectLoadXml()) { if (auto resource = indirectLoad->Serialize(item->GetContent())) { xmlElement = directLoad->Serialize(resource); xmlElement->name.value = resolver->GetType(); } } } } if (xmlElement) { xmlElement->attributes.Add(attName); xmlParent->subNodes.Add(xmlElement); } } else { auto xmlElement = MakePtr(); xmlElement->name.value = item->GetTypeName(); xmlParent->subNodes.Add(xmlElement); auto attContent = MakePtr(); attContent->name.value = L"content"; attContent->value.value = L"File"; xmlElement->attributes.Add(attContent); auto xmlText = MakePtr(); xmlText->content.value = item->GetFileContentPath(); xmlElement->subNodes.Add(xmlText); } } } FOREACH(Ptr, folder, folders.Values()) { auto attName = MakePtr(); attName->name.value = L"name"; attName->value.value = folder->GetName(); auto xmlFolder = MakePtr(); xmlFolder->name.value = L"Folder"; xmlFolder->attributes.Add(attName); xmlParent->subNodes.Add(xmlFolder); if (folder->GetFileContentPath() == L"") { folder->SaveResourceFolderToXml(xmlFolder); } else { auto attContent = MakePtr(); attContent->name.value = L"content"; attContent->value.value = L"Link"; xmlFolder->attributes.Add(attContent); auto xmlText = MakePtr(); xmlText->content.value = folder->GetFileContentPath(); xmlFolder->subNodes.Add(xmlText); } } } void GuiResourceFolder::CollectTypeNames(collections::List& typeNames) { FOREACH(Ptr, item, items.Values()) { if (!typeNames.Contains(item->GetTypeName())) { typeNames.Add(item->GetTypeName()); } } FOREACH(Ptr, folder, folders.Values()) { folder->CollectTypeNames(typeNames); } } void GuiResourceFolder::LoadResourceFolderFromBinary(DelayLoadingList& delayLoadings, stream::internal::ContextFreeReader& reader, collections::List& typeNames, collections::List& errors) { vint count = 0; reader << count; for (vint i = 0; i < count; i++) { vint typeName = 0; WString name; reader << typeName << name; auto resolver = GetResourceResolverManager()->GetTypeResolver(typeNames[typeName]); Ptr item = new GuiResourceItem; if(AddItem(name, item)) { WString type = typeNames[typeName]; IGuiResourceTypeResolver* typeResolver = GetResourceResolverManager()->GetTypeResolver(type); IGuiResourceTypeResolver* preloadResolver = typeResolver; if(typeResolver) { if (!typeResolver->DirectLoadStream()) { WString preloadType = typeResolver->IndirectLoad()->GetPreloadType(); if (preloadType != L"") { preloadResolver = GetResourceResolverManager()->GetTypeResolver(preloadType); if (!preloadResolver) { errors.Add(L"Unknown resource resolver \"" + preloadType + L"\" of resource type \"" + type + L"\"."); } } } } else { errors.Add(L"Unknown resource type \"" + type + L"\"."); } if(typeResolver && preloadResolver) { if (auto directLoad = preloadResolver->DirectLoadStream()) { WString itemType = preloadResolver->GetType(); auto resource = directLoad->ResolveResourcePrecompiled(reader.input, errors); if (typeResolver != preloadResolver) { if (auto indirectLoad = typeResolver->IndirectLoad()) { if(indirectLoad->IsDelayLoad()) { DelayLoading delayLoading; delayLoading.type = type; delayLoading.preloadResource = item; delayLoadings.Add(delayLoading); } else if(resource) { resource = indirectLoad->ResolveResource(resource, 0, errors); itemType = typeResolver->GetType(); } } else { resource = 0; errors.Add(L"Resource type \"" + typeResolver->GetType() + L"\" is not a indirect load resource type."); } } item->SetContent(itemType, resource); } else { errors.Add(L"Resource type \"" + preloadResolver->GetType() + L"\" is not a direct load resource type."); } } if(!item->GetContent()) { RemoveItem(name); } } else { errors.Add(L"Duplicated resource item name \"" + name + L"\"."); } } reader << count; for (vint i = 0; i < count; i++) { WString name; reader << name; auto folder = MakePtr(); folder->LoadResourceFolderFromBinary(delayLoadings, reader, typeNames, errors); AddFolder(name, folder); } } void GuiResourceFolder::SaveResourceFolderToBinary(stream::internal::ContextFreeWriter& writer, collections::List& typeNames) { typedef Tuple> ItemTuple; List itemTuples; FOREACH(Ptr, item, items.Values()) { auto resolver = GetResourceResolverManager()->GetTypeResolver(item->GetTypeName()); if (resolver->StreamSerializable()) { vint typeName = typeNames.IndexOf(item->GetTypeName()); WString name = item->GetName(); if (auto directLoad = resolver->DirectLoadStream()) { itemTuples.Add(ItemTuple(typeName, name, directLoad, item->GetContent())); } else if (auto indirectLoad = resolver->IndirectLoad()) { if (auto preloadResolver = GetResourceResolverManager()->GetTypeResolver(indirectLoad->GetPreloadType())) { if (auto directLoad = preloadResolver->DirectLoadStream()) { if (auto resource = indirectLoad->Serialize(item->GetContent())) { itemTuples.Add(ItemTuple(typeName, name, directLoad, resource)); } } } } } } vint count = itemTuples.Count(); writer << count; FOREACH(ItemTuple, item, itemTuples) { vint typeName = item.f0; WString name = item.f1; writer << typeName << name; auto directLoad = item.f2; auto resource = item.f3; directLoad->SerializePrecompiled(resource, writer.output); } count = folders.Count(); writer << count; FOREACH(Ptr, folder, folders.Values()) { WString name = folder->GetName(); writer << name; folder->SaveResourceFolderToBinary(writer, typeNames); } } void GuiResourceFolder::PrecompileResourceFolder(GuiResourcePrecompileContext& context, IGuiResourcePrecompileCallback* callback, collections::List& errors) { FOREACH(Ptr, item, items.Values()) { auto typeResolver = GetResourceResolverManager()->GetTypeResolver(item->GetTypeName()); if (auto precompile = typeResolver->Precompile()) { if (precompile->GetPassSupport(context.passIndex) == IGuiResourceTypeResolver_Precompile::PerResource) { if (callback) { callback->OnPerResource(context.passIndex, item); } precompile->PerResourcePrecompile(item, context, errors); } } } FOREACH(Ptr, folder, folders.Values()) { folder->PrecompileResourceFolder(context, callback, errors); } } void GuiResourceFolder::InitializeResourceFolder(GuiResourceInitializeContext& context) { FOREACH(Ptr, item, items.Values()) { auto typeResolver = GetResourceResolverManager()->GetTypeResolver(item->GetTypeName()); if (auto initialize = typeResolver->Initialize()) { initialize->Initialize(item, context); } } FOREACH(Ptr, folder, folders.Values()) { folder->InitializeResourceFolder(context); } } GuiResourceFolder::GuiResourceFolder() { } GuiResourceFolder::~GuiResourceFolder() { } const GuiResourceFolder::ItemList& GuiResourceFolder::GetItems() { return items.Values(); } Ptr GuiResourceFolder::GetItem(const WString& name) { vint index=items.Keys().IndexOf(name); return index == -1 ? nullptr : items.Values().Get(index); } bool GuiResourceFolder::AddItem(const WString& name, Ptr item) { if(item->GetParent()!=0 || items.Keys().Contains(name)) return false; items.Add(name, item); item->parent=this; item->name=name; return true; } Ptr GuiResourceFolder::RemoveItem(const WString& name) { Ptr item=GetItem(name); if(!item) return 0; items.Remove(name); return item; } void GuiResourceFolder::ClearItems() { items.Clear(); } const GuiResourceFolder::FolderList& GuiResourceFolder::GetFolders() { return folders.Values(); } Ptr GuiResourceFolder::GetFolder(const WString& name) { vint index=folders.Keys().IndexOf(name); return index == -1 ? nullptr : folders.Values().Get(index); } bool GuiResourceFolder::AddFolder(const WString& name, Ptr folder) { if(folder->GetParent()!=0 || folders.Keys().Contains(name)) return false; folders.Add(name, folder); folder->parent=this; folder->name=name; return true; } Ptr GuiResourceFolder::RemoveFolder(const WString& name) { Ptr folder=GetFolder(name); if(!folder) return 0; folders.Remove(name); return folder; } void GuiResourceFolder::ClearFolders() { folders.Clear(); } Ptr GuiResourceFolder::GetValueByPath(const WString& path) { const wchar_t* buffer=path.Buffer(); const wchar_t* index=wcschr(buffer, L'\\'); if(!index) index=wcschr(buffer, '/'); if(index) { WString name=path.Sub(0, index-buffer); Ptr folder=GetFolder(name); if(folder) { vint start=index-buffer+1; return folder->GetValueByPath(path.Sub(start, path.Length()-start)); } } else { Ptr item=GetItem(path); if(item) { return item->GetContent(); } } return 0; } Ptr GuiResourceFolder::GetFolderByPath(const WString& path) { const wchar_t* buffer=path.Buffer(); const wchar_t* index=wcschr(buffer, L'\\'); if(!index) index=wcschr(buffer, '/'); if(!index) return 0; WString name=path.Sub(0, index-buffer); Ptr folder=GetFolder(name); if(index-buffer==path.Length()-1) { return folder; } if(folder) { vint start=index-buffer+1; return folder->GetFolderByPath(path.Sub(start, path.Length()-start)); } return 0; } bool GuiResourceFolder::CreateValueByPath(const WString& path, const WString& typeName, Ptr value) { const wchar_t* buffer = path.Buffer(); const wchar_t* index = wcschr(buffer, L'\\'); if (!index) index = wcschr(buffer, '/'); if(index) { WString name = path.Sub(0, index - buffer); Ptr folder = GetFolder(name); if (!folder) { folder = new GuiResourceFolder; AddFolder(name, folder); } vint start = index - buffer + 1; return folder->CreateValueByPath(path.Sub(start, path.Length() - start), typeName, value); } else { if(GetItem(path)) { return false; } auto item = new GuiResourceItem; item->SetContent(typeName, value); return AddItem(path, item); } } /*********************************************************************** GuiResource ***********************************************************************/ void GuiResource::ProcessDelayLoading(Ptr resource, DelayLoadingList& delayLoadings, collections::List& errors) { FOREACH(DelayLoading, delay, delayLoadings) { WString type = delay.type; WString folder = delay.workingDirectory; Ptr item = delay.preloadResource; auto typeResolver = GetResourceResolverManager()->GetTypeResolver(type); auto indirectLoad = typeResolver->IndirectLoad(); if (!indirectLoad) { errors.Add(L"Unknown resource type \"" + type + L"\"."); } else if (item->GetContent()) { Ptr pathResolver = new GuiResourcePathResolver(resource, folder); Ptr resource = indirectLoad->ResolveResource(item->GetContent(), pathResolver, errors); if(resource) { item->SetContent(typeResolver->GetType(), resource); } } } } GuiResource::GuiResource() { } GuiResource::~GuiResource() { } WString GuiResource::GetWorkingDirectory() { return workingDirectory; } Ptr GuiResource::LoadFromXml(Ptr xml, const WString& workingDirectory, collections::List& errors) { Ptr resource = new GuiResource; resource->workingDirectory = workingDirectory; DelayLoadingList delayLoadings; resource->LoadResourceFolderFromXml(delayLoadings, resource->workingDirectory, xml->rootElement, errors); ProcessDelayLoading(resource, delayLoadings, errors); return resource; } Ptr GuiResource::LoadFromXml(const WString& filePath, collections::List& errors) { Ptr xml; if(auto parser=GetParserManager()->GetParser(L"XML")) { WString text; if(LoadTextFile(filePath, text)) { xml = parser->TypedParse(text, errors); } else { errors.Add(L"Failed to load file \"" + filePath + L"\"."); } } if(xml) { return LoadFromXml(xml, GetFolderPath(filePath), errors); } return 0; } Ptr GuiResource::SaveToXml() { auto xmlRoot = MakePtr(); xmlRoot->name.value = L"Resource"; SaveResourceFolderToXml(xmlRoot); auto doc = MakePtr(); doc->rootElement = xmlRoot; return doc; } Ptr GuiResource::LoadPrecompiledBinary(stream::IStream& stream, collections::List& errors) { stream::internal::ContextFreeReader reader(stream); auto resource = MakePtr(); List typeNames; reader << typeNames; DelayLoadingList delayLoadings; resource->LoadResourceFolderFromBinary(delayLoadings, reader, typeNames, errors); ProcessDelayLoading(resource, delayLoadings, errors); return resource; } void GuiResource::SavePrecompiledBinary(stream::IStream& stream) { stream::internal::ContextFreeWriter writer(stream); List typeNames; CollectTypeNames(typeNames); writer << typeNames; SaveResourceFolderToBinary(writer, typeNames); } void GuiResource::Precompile(IGuiResourcePrecompileCallback* callback, collections::List& errors) { if (GetFolder(L"Precompiled")) { errors.Add(L"A precompiled resource cannot be compiled again."); return; } GuiResourcePrecompileContext context; context.rootResource = this; context.resolver = new GuiResourcePathResolver(this, workingDirectory); context.targetFolder = new GuiResourceFolder; auto manager = GetResourceResolverManager(); vint maxPass = manager->GetMaxPrecompilePassIndex(); List resolvers; for (vint i = 0; i <= maxPass; i++) { context.passIndex = i; { manager->GetPerResourceResolverNames(i, resolvers); if (resolvers.Count() > 0) { PrecompileResourceFolder(context, callback, errors); } } { manager->GetPerPassResolverNames(i, resolvers); if (resolvers.Count() > 0) { if (callback) { callback->OnPerPass(i); } FOREACH(WString, name, resolvers) { auto resolver = manager->GetTypeResolver(name); resolver->Precompile()->PerPassPrecompile(context, errors); } } } } if (errors.Count() == 0) { AddFolder(L"Precompiled", context.targetFolder); } } void GuiResource::Initialize(GuiResourceUsage usage) { auto precompiledFolder = GetFolder(L"Precompiled"); if (!precompiledFolder) { CHECK_FAIL(L"GuiResource::Initialize()#Cannot initialize a non-precompiled resource."); return; } GuiResourceInitializeContext context; context.rootResource = this; context.resolver = new GuiResourcePathResolver(this, workingDirectory); context.targetFolder = precompiledFolder; context.usage = usage; vint maxPass = GetResourceResolverManager()->GetMaxInitializePassIndex(); for (vint i = 0; i <= maxPass; i++) { context.passIndex = i; InitializeResourceFolder(context); } } Ptr GuiResource::GetDocumentByPath(const WString& path) { Ptr result=GetValueByPath(path).Cast(); if(!result) throw ArgumentException(L"Path not exists.", L"GuiResource::GetDocumentByPath", L"path"); return result; } Ptr GuiResource::GetImageByPath(const WString& path) { Ptr result=GetValueByPath(path).Cast(); if(!result) throw ArgumentException(L"Path not exists.", L"GuiResource::GetImageByPath", L"path"); return result; } Ptr GuiResource::GetXmlByPath(const WString& path) { Ptr result=GetValueByPath(path).Cast(); if(!result) throw ArgumentException(L"Path not exists.", L"GuiResource::GetXmlByPath", L"path"); return result; } WString GuiResource::GetStringByPath(const WString& path) { Ptr> result=GetValueByPath(path).Cast>(); if(!result) throw ArgumentException(L"Path not exists.", L"GuiResource::GetStringByPath", L"path"); return result->Unbox(); } /*********************************************************************** GuiResourcePathResolver ***********************************************************************/ GuiResourcePathResolver::GuiResourcePathResolver(Ptr _resource, const WString& _workingDirectory) :resource(_resource) ,workingDirectory(_workingDirectory) { } GuiResourcePathResolver::~GuiResourcePathResolver() { } Ptr GuiResourcePathResolver::ResolveResource(const WString& protocol, const WString& path) { Ptr resolver; vint index=resolvers.Keys().IndexOf(protocol); if(index==-1) { IGuiResourcePathResolverFactory* factory=GetResourceResolverManager()->GetPathResolverFactory(protocol); if(factory) { resolver=factory->CreateResolver(resource, workingDirectory); } resolvers.Add(protocol, resolver); } else { resolver=resolvers.Values()[index]; } if(resolver) { return resolver->ResolveResource(path); } else { return 0; } } /*********************************************************************** GuiResourcePathFileResolver ***********************************************************************/ class GuiResourcePathFileResolver : public Object, public IGuiResourcePathResolver { protected: WString workingDirectory; public: GuiResourcePathFileResolver(const WString& _workingDirectory) :workingDirectory(_workingDirectory) { } Ptr ResolveResource(const WString& path) { WString filename=path; if(filename.Length()>=2 && filename[1]!=L':') { filename=workingDirectory+filename; } Ptr image=GetCurrentController()->ImageService()->CreateImageFromFile(filename); return new GuiImageData(image, 0); } class Factory : public Object, public IGuiResourcePathResolverFactory { public: WString GetProtocol()override { return L"file"; } Ptr CreateResolver(Ptr resource, const WString& workingDirectory)override { return new GuiResourcePathFileResolver(workingDirectory); } }; }; /*********************************************************************** GuiResourcePathResResolver ***********************************************************************/ class GuiResourcePathResResolver : public Object, public IGuiResourcePathResolver { protected: Ptr resource; public: GuiResourcePathResResolver(Ptr _resource) :resource(_resource) { } Ptr ResolveResource(const WString& path) { if(resource) { if(path.Length()>0) { switch(path[path.Length()-1]) { case L'\\':case L'/': return resource->GetFolderByPath(path); default: return resource->GetValueByPath(path); } } } return 0; } class Factory : public Object, public IGuiResourcePathResolverFactory { public: WString GetProtocol()override { return L"res"; } Ptr CreateResolver(Ptr resource, const WString& workingDirectory)override { return new GuiResourcePathResResolver(resource); } }; }; /*********************************************************************** IGuiResourceResolverManager ***********************************************************************/ IGuiResourceResolverManager* resourceResolverManager=0; IGuiResourceResolverManager* GetResourceResolverManager() { return resourceResolverManager; } class GuiResourceResolverManager : public Object, public IGuiResourceResolverManager, public IGuiPlugin { typedef Dictionary> PathFactoryMap; typedef Dictionary> TypeResolverMap; typedef Group ResolverGroup; protected: PathFactoryMap pathFactories; TypeResolverMap typeResolvers; ResolverGroup perResourceResolvers; ResolverGroup perPassResolvers; public: GuiResourceResolverManager() { } ~GuiResourceResolverManager() { } void Load()override { globalStringKeyManager = new GlobalStringKeyManager(); globalStringKeyManager->InitializeConstants(); resourceResolverManager = this; SetPathResolverFactory(new GuiResourcePathFileResolver::Factory); SetPathResolverFactory(new GuiResourcePathResResolver::Factory); } void AfterLoad()override { } void Unload()override { delete globalStringKeyManager; globalStringKeyManager = 0; resourceResolverManager = 0; } IGuiResourcePathResolverFactory* GetPathResolverFactory(const WString& protocol)override { vint index=pathFactories.Keys().IndexOf(protocol); return index==-1?0:pathFactories.Values()[index].Obj(); } bool SetPathResolverFactory(Ptr factory)override { if(pathFactories.Keys().Contains(factory->GetProtocol())) return false; pathFactories.Add(factory->GetProtocol(), factory); return true; } IGuiResourceTypeResolver* GetTypeResolver(const WString& type)override { vint index=typeResolvers.Keys().IndexOf(type); return index==-1?0:typeResolvers.Values()[index].Obj(); } bool SetTypeResolver(Ptr resolver)override { if(typeResolvers.Keys().Contains(resolver->GetType())) return false; typeResolvers.Add(resolver->GetType(), resolver); if (auto precompile = resolver->Precompile()) { vint maxPassIndex = precompile->GetMaxPassIndex(); for (vint i = 0; i <= maxPassIndex; i++) { switch (precompile->GetPassSupport(i)) { case IGuiResourceTypeResolver_Precompile::PerResource: perResourceResolvers.Add(i, resolver->GetType()); break; case IGuiResourceTypeResolver_Precompile::PerPass: perPassResolvers.Add(i, resolver->GetType()); break; default:; } } } return true; } vint GetMaxPrecompilePassIndex()override { vint maxPass = -1; FOREACH(Ptr, resolver, typeResolvers.Values()) { if (auto precompile = resolver->Precompile()) { vint pass = precompile->GetMaxPassIndex(); if (maxPass < pass) { maxPass = pass; } } } return maxPass; } vint GetMaxInitializePassIndex()override { vint maxPass = -1; FOREACH(Ptr, resolver, typeResolvers.Values()) { if (auto initialize = resolver->Initialize()) { vint pass = initialize->GetMaxPassIndex(); if (maxPass < pass) { maxPass = pass; } } } return maxPass; } void GetPerResourceResolverNames(vint passIndex, collections::List& names)override { names.Clear(); vint index = perResourceResolvers.Keys().IndexOf(passIndex); if (index != -1) { CopyFrom(names, perResourceResolvers.GetByIndex(index)); } } void GetPerPassResolverNames(vint passIndex, collections::List& names)override { names.Clear(); vint index = perPassResolvers.Keys().IndexOf(passIndex); if (index != -1) { CopyFrom(names, perPassResolvers.GetByIndex(index)); } } }; GUI_REGISTER_PLUGIN(GuiResourceResolverManager) } } /*********************************************************************** RESOURCES\GUIRESOURCEMANAGER.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace stream; using namespace reflection::description; using namespace controls; /*********************************************************************** Class Name Record (ClassNameRecord) ***********************************************************************/ class GuiResourceClassNameRecordTypeResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_DirectLoadStream { public: WString GetType()override { return L"ClassNameRecord"; } bool XmlSerializable()override { return false; } bool StreamSerializable()override { return true; } IGuiResourceTypeResolver_DirectLoadStream* DirectLoadStream()override { return this; } void SerializePrecompiled(Ptr resource, stream::IStream& stream)override { if (auto obj = resource.Cast()) { internal::ContextFreeWriter writer(stream); writer << obj->classNames; } } Ptr ResolveResourcePrecompiled(stream::IStream& stream, collections::List& errors)override { internal::ContextFreeReader reader(stream); auto obj = MakePtr(); reader << obj->classNames; return obj; } }; /*********************************************************************** IGuiInstanceResourceManager ***********************************************************************/ IGuiResourceManager* resourceManager = 0; IGuiResourceManager* GetResourceManager() { return resourceManager; } class GuiResourceManager : public Object, public IGuiResourceManager, public IGuiPlugin { protected: typedef Dictionary> ResourceMap; ResourceMap resources; ResourceMap instanceResources; public: GuiResourceManager() { } void Load()override { resourceManager = this; } void AfterLoad()override { IGuiResourceResolverManager* manager = GetResourceResolverManager(); manager->SetTypeResolver(new GuiResourceClassNameRecordTypeResolver); } void Unload()override { resourceManager = nullptr; } bool SetResource(const WString& name, Ptr resource, GuiResourceUsage usage)override { vint index = resources.Keys().IndexOf(name); if (index != -1) return false; resource->Initialize(usage); resources.Add(name, resource); auto record = resource->GetValueByPath(L"Precompiled/ClassNameRecord").Cast(); FOREACH(WString, className, record->classNames) { instanceResources.Add(className, resource); } return true; } Ptr GetResource(const WString& name)override { vint index = resources.Keys().IndexOf(name); return index == -1 ? nullptr : resources.Values()[index]; } Ptr GetResourceFromClassName(const WString& classFullName)override { vint index = instanceResources.Keys().IndexOf(classFullName); if (index == -1) return nullptr; return instanceResources.Values()[index]; } }; GUI_REGISTER_PLUGIN(GuiResourceManager) } } /*********************************************************************** RESOURCES\GUIRESOURCETYPERESOLVERS.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace controls; using namespace parsing; using namespace parsing::tabling; using namespace parsing::xml; using namespace stream; /*********************************************************************** Image Type Resolver (Image) ***********************************************************************/ class GuiResourceImageTypeResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_DirectLoadXml , private IGuiResourceTypeResolver_DirectLoadStream { public: WString GetType()override { return L"Image"; } bool XmlSerializable()override { return true; } bool StreamSerializable()override { return true; } IGuiResourceTypeResolver_DirectLoadXml* DirectLoadXml()override { return this; } IGuiResourceTypeResolver_DirectLoadStream* DirectLoadStream()override { return this; } Ptr Serialize(Ptr resource)override { if (auto obj = resource.Cast()) { FileStream fileStream(obj->GetFilePath(), FileStream::ReadOnly); if (fileStream.IsAvailable()) { auto xmlContent = MakePtr(); xmlContent->content.value = BinaryToHex(fileStream); auto xmlImage = MakePtr(); xmlImage->name.value = L"Image"; xmlImage->subNodes.Add(xmlContent); return xmlImage; } } return 0; } void SerializePrecompiled(Ptr resource, stream::IStream& stream)override { auto obj = resource.Cast(); stream::internal::ContextFreeWriter writer(stream); FileStream fileStream(obj->GetFilePath(), FileStream::ReadOnly); writer << (stream::IStream&)fileStream; } Ptr ResolveResource(Ptr element, collections::List& errors)override { MemoryStream stream; HexToBinary(stream, XmlGetValue(element)); stream.SeekFromBegin(0); auto image = GetCurrentController()->ImageService()->CreateImageFromStream(stream); if (image) { return new GuiImageData(image, 0); } else { errors.Add(L"Failed to load an image from binary data in xml."); return 0; } } Ptr ResolveResource(const WString& path, collections::List& errors)override { Ptr image = GetCurrentController()->ImageService()->CreateImageFromFile(path); if(image) { return new GuiImageData(image, 0, path); } else { errors.Add(L"Failed to load file \"" + path + L"\"."); return 0; } } Ptr ResolveResourcePrecompiled(stream::IStream& stream, collections::List& errors)override { stream::internal::ContextFreeReader reader(stream); MemoryStream memoryStream; reader << (stream::IStream&)memoryStream; auto image = GetCurrentController()->ImageService()->CreateImageFromStream(memoryStream); if (image) { return new GuiImageData(image, 0); } else { errors.Add(L"Failed to load an image from binary data in a stream."); return 0; } } }; /*********************************************************************** Text Type Resolver (Text) ***********************************************************************/ class GuiResourceTextTypeResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_DirectLoadXml , private IGuiResourceTypeResolver_DirectLoadStream { public: WString GetType()override { return L"Text"; } bool XmlSerializable()override { return true; } bool StreamSerializable()override { return true; } IGuiResourceTypeResolver_DirectLoadXml* DirectLoadXml()override { return this; } IGuiResourceTypeResolver_DirectLoadStream* DirectLoadStream()override { return this; } Ptr Serialize(Ptr resource)override { if (auto obj = resource.Cast()) { auto xmlContent = MakePtr(); xmlContent->content.value = obj->GetText(); auto xmlText = MakePtr(); xmlText->name.value = L"Text"; xmlText->subNodes.Add(xmlContent); return xmlText; } return 0; } void SerializePrecompiled(Ptr resource, stream::IStream& stream)override { auto obj = resource.Cast(); stream::internal::ContextFreeWriter writer(stream); WString text = obj->GetText(); writer << text; } Ptr ResolveResource(Ptr element, collections::List& errors)override { return new GuiTextData(XmlGetValue(element)); } Ptr ResolveResource(const WString& path, collections::List& errors)override { WString text; if(LoadTextFile(path, text)) { return new GuiTextData(text); } else { errors.Add(L"Failed to load file \"" + path + L"\"."); return 0; } } Ptr ResolveResourcePrecompiled(stream::IStream& stream, collections::List& errors)override { stream::internal::ContextFreeReader reader(stream); WString text; reader << text; return new GuiTextData(text); } }; /*********************************************************************** Xml Type Resolver (Xml) ***********************************************************************/ class GuiResourceXmlTypeResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_DirectLoadXml , private IGuiResourceTypeResolver_DirectLoadStream { public: WString GetType()override { return L"Xml"; } bool XmlSerializable()override { return true; } bool StreamSerializable()override { return true; } IGuiResourceTypeResolver_DirectLoadXml* DirectLoadXml()override { return this; } IGuiResourceTypeResolver_DirectLoadStream* DirectLoadStream()override { return this; } Ptr Serialize(Ptr resource)override { if (auto obj = resource.Cast()) { auto xmlXml = MakePtr(); xmlXml->name.value = L"Xml"; xmlXml->subNodes.Add(obj->rootElement); return xmlXml; } return 0; } void SerializePrecompiled(Ptr resource, stream::IStream& stream)override { auto obj = resource.Cast(); MemoryStream buffer; { StreamWriter writer(buffer); XmlPrint(obj, writer); } { buffer.SeekFromBegin(0); StreamReader reader(buffer); WString text = reader.ReadToEnd(); stream::internal::ContextFreeWriter writer(stream); writer << text; } } Ptr ResolveResource(Ptr element, collections::List& errors)override { Ptr root = XmlGetElements(element).First(0); if(root) { Ptr xml=new XmlDocument; xml->rootElement=root; return xml; } return 0; } Ptr ResolveResource(const WString& path, collections::List& errors)override { if(auto parser=GetParserManager()->GetParser(L"XML")) { WString text; if(LoadTextFile(path, text)) { return parser->TypedParse(text, errors); } else { errors.Add(L"Failed to load file \"" + path + L"\"."); } } return 0; } Ptr ResolveResourcePrecompiled(stream::IStream& stream, collections::List& errors)override { stream::internal::ContextFreeReader reader(stream); WString text; reader << text; auto parser = GetParserManager()->GetParser(L"XML"); return parser->TypedParse(text, errors); } }; /*********************************************************************** Doc Type Resolver (Doc) ***********************************************************************/ class GuiResourceDocTypeResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_IndirectLoad { public: WString GetType()override { return L"Doc"; } bool XmlSerializable()override { return true; } bool StreamSerializable()override { return true; } WString GetPreloadType()override { return L"Xml"; } bool IsDelayLoad()override { return true; } IGuiResourceTypeResolver_IndirectLoad* IndirectLoad()override { return this; } Ptr Serialize(Ptr resource)override { if (auto obj = resource.Cast()) { return obj->SaveToXml(); } return 0; } Ptr ResolveResource(Ptr resource, Ptr resolver, collections::List& errors)override { Ptr xml = resource.Cast(); if(xml) { Ptr model=DocumentModel::LoadFromXml(xml, resolver, errors); return model; } return 0; } }; /*********************************************************************** Type Resolver Plugin ***********************************************************************/ class GuiResourceTypeResolverPlugin : public Object, public IGuiPlugin { public: void Load()override { } void AfterLoad()override { IGuiResourceResolverManager* manager=GetResourceResolverManager(); manager->SetTypeResolver(new GuiResourceImageTypeResolver); manager->SetTypeResolver(new GuiResourceTextTypeResolver); manager->SetTypeResolver(new GuiResourceXmlTypeResolver); manager->SetTypeResolver(new GuiResourceDocTypeResolver); } void Unload()override { } }; GUI_REGISTER_PLUGIN(GuiResourceTypeResolverPlugin) } }