mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-02-06 03:42:11 +08:00
46057 lines
1.2 MiB
46057 lines
1.2 MiB
/***********************************************************************
|
|
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<Color>::GetDefaultValue()
|
|
{
|
|
return Color();
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<Color>::Serialize(const Color& input, WString& output)
|
|
{
|
|
output = input.ToString();
|
|
return true;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<Color>::Deserialize(const WString& input, Color& output)
|
|
{
|
|
output = Color::Parse(input);
|
|
return true;
|
|
}
|
|
|
|
IValueType::CompareResult TypedValueSerializerProvider<Color>::Compare(const presentation::Color& a, const presentation::Color& b)
|
|
{
|
|
return TypedValueSerializerProvider<vuint32_t>::Compare(a.value, b.value);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Serialization (DocumentFontSize)
|
|
***********************************************************************/
|
|
|
|
DocumentFontSize TypedValueSerializerProvider<DocumentFontSize>::GetDefaultValue()
|
|
{
|
|
return DocumentFontSize();
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<DocumentFontSize>::Serialize(const DocumentFontSize& input, WString& output)
|
|
{
|
|
output = input.ToString();
|
|
return true;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<DocumentFontSize>::Deserialize(const WString& input, DocumentFontSize& output)
|
|
{
|
|
output = DocumentFontSize::Parse(input);
|
|
return true;
|
|
}
|
|
|
|
IValueType::CompareResult TypedValueSerializerProvider<DocumentFontSize>::Compare(const presentation::DocumentFontSize& a, const presentation::DocumentFontSize& b)
|
|
{
|
|
return TypedValueSerializerProvider<WString>::Compare(a.ToString(), b.ToString());
|
|
}
|
|
|
|
/***********************************************************************
|
|
Serialization (GlobalStringKey)
|
|
***********************************************************************/
|
|
|
|
GlobalStringKey TypedValueSerializerProvider<GlobalStringKey>::GetDefaultValue()
|
|
{
|
|
return GlobalStringKey();
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<GlobalStringKey>::Serialize(const GlobalStringKey& input, WString& output)
|
|
{
|
|
output = input.ToString();
|
|
return true;
|
|
}
|
|
|
|
bool TypedValueSerializerProvider<GlobalStringKey>::Deserialize(const WString& input, GlobalStringKey& output)
|
|
{
|
|
output = GlobalStringKey::Get(input);
|
|
return true;
|
|
}
|
|
|
|
IValueType::CompareResult TypedValueSerializerProvider<GlobalStringKey>::Compare(const presentation::GlobalStringKey& a, const presentation::GlobalStringKey& b)
|
|
{
|
|
return TypedValueSerializerProvider<WString>::Compare(a.ToString(), b.ToString());
|
|
}
|
|
|
|
/***********************************************************************
|
|
External Functions (Basic)
|
|
***********************************************************************/
|
|
|
|
GuiGraphicsAnimationManager* GuiControlHost_GetAnimationManager(GuiControlHost* thisObject)
|
|
{
|
|
return thisObject->GetGraphicsHost()->GetAnimationManager();
|
|
}
|
|
|
|
Ptr<INativeImage> 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> 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<ParsingTable> table = XmlLoadTable();
|
|
Ptr<XmlDocument> xml = XmlParseDocument(xmlText, table);
|
|
if (!xml) return 0;
|
|
|
|
List<WString> 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<IGuiAltAction*>& actions)
|
|
{
|
|
Group<WString, IGuiAltAction*> group;
|
|
host->CollectAltActions(group);
|
|
for (vint i = 0; i < group.Count(); i++)
|
|
{
|
|
CopyFrom(actions, group.GetByIndex(i), true);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
External Functions (Controls)
|
|
***********************************************************************/
|
|
|
|
Ptr<ITheme> CreateWin7Theme()
|
|
{
|
|
return new win7::Win7Theme();
|
|
}
|
|
|
|
Ptr<ITheme> CreateWin8Theme()
|
|
{
|
|
return new win8::Win8Theme();
|
|
}
|
|
|
|
list::ListViewItemStyleProvider::IListViewItemContent* ListViewItemStyleProvider_GetItemContent(list::ListViewItemStyleProvider* thisObject, GuiListControl::IItemStyleController* itemStyleController)
|
|
{
|
|
return thisObject->GetItemContent<list::ListViewItemStyleProvider::IListViewItemContent>(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;i<windows.Count();i++)
|
|
{
|
|
GuiEventArgs arguments=windows[i]->GetNotifyEventArguments();
|
|
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;i<windows.Count();i++)
|
|
{
|
|
if(windows[i]!=window)
|
|
{
|
|
windows[i]->MouseClickedOnOtherWindow(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<GuiWindow*>& GuiApplication::GetWindows()
|
|
{
|
|
return windows;
|
|
}
|
|
|
|
GuiWindow* GuiApplication::GetWindow(Point location)
|
|
{
|
|
INativeWindow* nativeWindow=GetCurrentController()->WindowService()->GetWindow(location);
|
|
if(nativeWindow)
|
|
{
|
|
for(vint i=0;i<windows.Count();i++)
|
|
{
|
|
GuiWindow* window=windows[i];
|
|
if(window->GetNativeWindow()==nativeWindow)
|
|
{
|
|
return window;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void GuiApplication::ShowTooltip(GuiControl* owner, GuiControl* tooltip, vint preferredContentWidth, Point location)
|
|
{
|
|
GuiWindow* ownerWindow = dynamic_cast<GuiWindow*>(owner->GetRelatedControlHost());
|
|
if (sharedTooltipOwnerWindow != ownerWindow)
|
|
{
|
|
delete sharedTooltipControl;
|
|
sharedTooltipControl = 0;
|
|
}
|
|
|
|
if(!sharedTooltipControl)
|
|
{
|
|
GuiWindow::IStyleController* tooltipStyle = 0;
|
|
if (ownerWindow)
|
|
{
|
|
tooltipStyle = dynamic_cast<GuiWindow::IStyleController*>(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<void()>& proc)
|
|
{
|
|
GetCurrentController()->AsyncService()->InvokeAsync(proc);
|
|
}
|
|
|
|
void GuiApplication::InvokeInMainThread(const Func<void()>& proc)
|
|
{
|
|
GetCurrentController()->AsyncService()->InvokeInMainThread(proc);
|
|
}
|
|
|
|
bool GuiApplication::InvokeInMainThreadAndWait(const Func<void()>& proc, vint milliseconds)
|
|
{
|
|
return GetCurrentController()->AsyncService()->InvokeInMainThreadAndWait(proc, milliseconds);
|
|
}
|
|
|
|
Ptr<INativeDelay> GuiApplication::DelayExecute(const Func<void()>& proc, vint milliseconds)
|
|
{
|
|
return GetCurrentController()->AsyncService()->DelayExecute(proc, milliseconds);
|
|
}
|
|
|
|
Ptr<INativeDelay> GuiApplication::DelayExecuteInMainThread(const Func<void()>& proc, vint milliseconds)
|
|
{
|
|
return GetCurrentController()->AsyncService()->DelayExecuteInMainThread(proc, milliseconds);
|
|
}
|
|
|
|
void GuiApplication::RunGuiTask(const Func<void()>& proc)
|
|
{
|
|
if(IsInMainThread())
|
|
{
|
|
return proc();
|
|
}
|
|
else
|
|
{
|
|
InvokeInMainThreadAndWait([&proc]()
|
|
{
|
|
proc();
|
|
});
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiPluginManager
|
|
***********************************************************************/
|
|
|
|
class GuiPluginManager : public Object, public IGuiPluginManager
|
|
{
|
|
protected:
|
|
List<Ptr<IGuiPlugin>> plugins;
|
|
bool loaded;
|
|
public:
|
|
GuiPluginManager()
|
|
:loaded(false)
|
|
{
|
|
}
|
|
|
|
~GuiPluginManager()
|
|
{
|
|
Unload();
|
|
}
|
|
|
|
void AddPlugin(Ptr<IGuiPlugin> plugin)override
|
|
{
|
|
plugins.Add(plugin);
|
|
if(loaded)
|
|
{
|
|
plugin->Load();
|
|
}
|
|
}
|
|
|
|
void Load()override
|
|
{
|
|
if(!loaded)
|
|
{
|
|
loaded=true;
|
|
FOREACH(Ptr<IGuiPlugin>, plugin, plugins)
|
|
{
|
|
plugin->Load();
|
|
}
|
|
FOREACH(Ptr<IGuiPlugin>, plugin, plugins)
|
|
{
|
|
plugin->AfterLoad();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Unload()override
|
|
{
|
|
if(loaded)
|
|
{
|
|
loaded=false;
|
|
FOREACH(Ptr<IGuiPlugin>, 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::ITheme> 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;i<children.Count();i++)
|
|
{
|
|
children[i]->OnParentLineChanged();
|
|
}
|
|
}
|
|
|
|
void GuiControl::OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget)
|
|
{
|
|
}
|
|
|
|
void GuiControl::OnBeforeReleaseGraphicsHost()
|
|
{
|
|
for(vint i=0;i<children.Count();i++)
|
|
{
|
|
children[i]->OnBeforeReleaseGraphicsHost();
|
|
}
|
|
}
|
|
|
|
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;i<children.Count();i++)
|
|
{
|
|
children[i]->UpdateVisuallyEnabled();
|
|
}
|
|
}
|
|
}
|
|
|
|
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<GuiControl*>(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<children.Count();i++)
|
|
{
|
|
delete children[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(vint i=children.Count()-1;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<description::IValueSubscription> GuiInstanceRootObject::AddSubscription(Ptr<description::IValueSubscription> subscription)
|
|
{
|
|
if (subscriptions.Contains(subscription.Obj()))
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
subscriptions.Add(subscription);
|
|
return subscription;
|
|
}
|
|
}
|
|
|
|
bool GuiInstanceRootObject::RemoveSubscription(Ptr<description::IValueSubscription> subscription)
|
|
{
|
|
return subscriptions.Remove(subscription.Obj());
|
|
}
|
|
|
|
bool GuiInstanceRootObject::ContainsSubscription(Ptr<description::IValueSubscription> subscription)
|
|
{
|
|
return subscriptions.Contains(subscription.Obj());
|
|
}
|
|
|
|
void GuiInstanceRootObject::ClearSubscriptions()
|
|
{
|
|
FOREACH(Ptr<IValueSubscription>, 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<GuiControlHost>(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;i<components.Count();i++)
|
|
{
|
|
components[i]->Detach(this);
|
|
}
|
|
for(vint i=0;i<components.Count();i++)
|
|
{
|
|
delete components[i];
|
|
}
|
|
components.Clear();
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiCustomControl
|
|
***********************************************************************/
|
|
|
|
GuiCustomControl::GuiCustomControl(IStyleController* _styleController)
|
|
:GuiControl(_styleController)
|
|
{
|
|
}
|
|
|
|
GuiCustomControl::~GuiCustomControl()
|
|
{
|
|
FinalizeAggregation();
|
|
FinalizeInstance();
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiLabel
|
|
***********************************************************************/
|
|
|
|
GuiLabel::GuiLabel(IStyleController* _styleController)
|
|
:GuiControl(_styleController)
|
|
,styleController(_styleController)
|
|
{
|
|
textColor=styleController->GetDefaultTextColor();
|
|
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;i<buttons.Count();i++)
|
|
{
|
|
buttons[i]->SetSelected(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 && 0<value)
|
|
{
|
|
totalSize=value;
|
|
if(pageSize>totalSize)
|
|
{
|
|
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=
|
|
value<min?min:
|
|
value>max?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<GuiControl*>(rootObject))
|
|
{
|
|
if (auto host = control->GetRelatedControlHost())
|
|
{
|
|
return dynamic_cast<GuiWindow*>(host);
|
|
}
|
|
}
|
|
else if (auto composition = dynamic_cast<GuiGraphicsComposition*>(rootObject))
|
|
{
|
|
if (auto host = composition->GetRelatedControlHost())
|
|
{
|
|
return dynamic_cast<GuiWindow*>(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<Color>& GuiColorDialog::GetCustomColors()
|
|
{
|
|
return customColors;
|
|
}
|
|
|
|
bool GuiColorDialog::ShowDialog()
|
|
{
|
|
Array<Color> 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<WString>& 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<WString> 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<WString, compositions::IGuiAltAction*>& 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<tabPages.Count();i++)
|
|
{
|
|
delete tabPages[i];
|
|
}
|
|
}
|
|
|
|
IDescriptable* GuiTab::QueryService(const WString& identifier)
|
|
{
|
|
if (identifier == IGuiAltActionContainer::Identifier)
|
|
{
|
|
return (IGuiAltActionContainer*)this;
|
|
}
|
|
else
|
|
{
|
|
return GuiControl::QueryService(identifier);
|
|
}
|
|
}
|
|
|
|
GuiTabPage* GuiTab::CreatePage(vint index)
|
|
{
|
|
GuiTabPage* page=new GuiTabPage();
|
|
if(CreatePage(page, index))
|
|
{
|
|
return page;
|
|
}
|
|
else
|
|
{
|
|
delete page;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool GuiTab::CreatePage(GuiTabPage* page, vint index)
|
|
{
|
|
if(index>=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<GuiTabPage*>& 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;i<tabPages.Count();i++)
|
|
{
|
|
bool selected=tabPages[i]==value;
|
|
tabPages[i]->GetContainerComposition()->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<StyleController*>(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<StyleController*>(GetStyleController());
|
|
GuiBoundsComposition* composition=dynamic_cast<GuiBoundsComposition*>(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<GuiSelectableButton*>(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;i<showPrev;i++)
|
|
{
|
|
DateTime day=DateTime::FromDateTime(yearPrev, monthPrev, countPrev-(showPrev-i-1));
|
|
SetDay(day, index, false);
|
|
}
|
|
for(vint i=0;i<show;i++)
|
|
{
|
|
DateTime day=DateTime::FromDateTime(year, month, i+1);
|
|
SetDay(day, index, true);
|
|
}
|
|
for(vint i=0;i<showNext;i++)
|
|
{
|
|
DateTime day=DateTime::FromDateTime(yearNext, monthNext, i+1);
|
|
SetDay(day, index, false);
|
|
}
|
|
}
|
|
|
|
void GuiDatePicker::StyleController::SelectDay(vint day)
|
|
{
|
|
for(vint i=0;i<dateDays.Count();i++)
|
|
{
|
|
const DateTime& dt=dateDays[i];
|
|
if(dt.year==currentDate.year && dt.month==currentDate.month && dt.day==day)
|
|
{
|
|
preventButtonEvent=true;
|
|
buttonDays[i]->SetSelected(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;i<DayRowStart;i++)
|
|
{
|
|
dayTable->SetRowOption(i, GuiCellOption::MinSizeOption());
|
|
}
|
|
for(vint i=0;i<DayRows;i++)
|
|
{
|
|
dayTable->SetRowOption(i+DayRowStart, GuiCellOption::PercentageOption(1.0));
|
|
}
|
|
for(vint i=0;i<DaysOfWeek;i++)
|
|
{
|
|
dayTable->SetColumnOption(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;i<DaysOfWeek;i++)
|
|
{
|
|
GuiCellComposition* cell=new GuiCellComposition;
|
|
dayTable->AddChild(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;i<DaysOfWeek;i++)
|
|
{
|
|
for(vint j=0;j<DayRows;j++)
|
|
{
|
|
GuiCellComposition* cell=new GuiCellComposition;
|
|
dayTable->AddChild(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;i<DaysOfWeek;i++)
|
|
{
|
|
labelDaysOfWeek[i]->SetText(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<StyleController*>(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<WString> 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<WString, IGuiAltAction*>& 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<void()>& callback)
|
|
{
|
|
owner->SetEnabled(false);
|
|
GetNativeWindow()->SetParent(owner->GetNativeWindow());
|
|
auto container = CreateEventHandlerContainer<GuiEventArgs>();
|
|
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<void()>& 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.x<screenBounds.x1)
|
|
{
|
|
location.x=screenBounds.x1;
|
|
}
|
|
else if(location.x+size.x>screenBounds.x2)
|
|
{
|
|
location.x=screenBounds.x2-size.x;
|
|
}
|
|
|
|
if(location.y<screenBounds.y1)
|
|
{
|
|
location.y=screenBounds.y1;
|
|
}
|
|
else if(location.y+size.y>screenBounds.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<description::IValueEnumerable> GuiBindableTextList::ItemSource::GetItemSource()
|
|
{
|
|
return itemSource;
|
|
}
|
|
|
|
void GuiBindableTextList::ItemSource::SetItemSource(Ptr<description::IValueEnumerable> _itemSource)
|
|
{
|
|
vint oldCount = 0;
|
|
if (itemSource)
|
|
{
|
|
oldCount = itemSource->GetCount();
|
|
}
|
|
if (itemChangedEventHandler)
|
|
{
|
|
auto ol = itemSource.Cast<IValueObservableList>();
|
|
ol->ItemChanged.Remove(itemChangedEventHandler);
|
|
}
|
|
|
|
itemSource = nullptr;
|
|
itemChangedEventHandler = nullptr;
|
|
|
|
if (_itemSource)
|
|
{
|
|
if (auto ol = _itemSource.Cast<IValueObservableList>())
|
|
{
|
|
itemSource = ol;
|
|
itemChangedEventHandler = ol->ItemChanged.Add([this](vint start, vint oldCount, vint newCount)
|
|
{
|
|
InvokeOnItemModified(start, oldCount, newCount);
|
|
});
|
|
}
|
|
else if (auto rl = _itemSource.Cast<IValueReadonlyList>())
|
|
{
|
|
itemSource = rl;
|
|
}
|
|
else
|
|
{
|
|
itemSource = IValueList::Create(GetLazyList<Value>(_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<bool>())
|
|
{
|
|
return UnboxValue<bool>(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<ItemSource*>(GetItemProvider());
|
|
|
|
TextPropertyChanged.SetAssociatedComposition(boundsComposition);
|
|
TextPropertyChanged.SetAssociatedComposition(boundsComposition);
|
|
}
|
|
|
|
GuiBindableTextList::~GuiBindableTextList()
|
|
{
|
|
}
|
|
|
|
Ptr<description::IValueEnumerable> GuiBindableTextList::GetItemSource()
|
|
{
|
|
return itemSource->GetItemSource();
|
|
}
|
|
|
|
void GuiBindableTextList::SetItemSource(Ptr<description::IValueEnumerable> _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<description::IValueEnumerable> GuiBindableListView::ItemSource::GetItemSource()
|
|
{
|
|
return itemSource;
|
|
}
|
|
|
|
void GuiBindableListView::ItemSource::SetItemSource(Ptr<description::IValueEnumerable> _itemSource)
|
|
{
|
|
vint oldCount = 0;
|
|
if (itemSource)
|
|
{
|
|
oldCount = itemSource->GetCount();
|
|
}
|
|
if (itemChangedEventHandler)
|
|
{
|
|
auto ol = itemSource.Cast<IValueObservableList>();
|
|
ol->ItemChanged.Remove(itemChangedEventHandler);
|
|
}
|
|
|
|
itemSource = nullptr;
|
|
itemChangedEventHandler = nullptr;
|
|
|
|
if (_itemSource)
|
|
{
|
|
if (auto ol = _itemSource.Cast<IValueObservableList>())
|
|
{
|
|
itemSource = ol;
|
|
itemChangedEventHandler = ol->ItemChanged.Add([this](vint start, vint oldCount, vint newCount)
|
|
{
|
|
InvokeOnItemModified(start, oldCount, newCount);
|
|
});
|
|
}
|
|
else if (auto rl = _itemSource.Cast<IValueReadonlyList>())
|
|
{
|
|
itemSource = rl;
|
|
}
|
|
else
|
|
{
|
|
itemSource = IValueList::Create(GetLazyList<Value>(_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<GuiImageData> GuiBindableListView::ItemSource::GetSmallImage(vint itemIndex)
|
|
{
|
|
if (itemSource)
|
|
{
|
|
if (0 <= itemIndex && itemIndex < itemSource->GetCount())
|
|
{
|
|
auto value = ReadProperty(itemSource->Get(itemIndex), smallImageProperty);
|
|
return value.GetSharedPtr().Cast<GuiImageData>();
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<GuiImageData> GuiBindableListView::ItemSource::GetLargeImage(vint itemIndex)
|
|
{
|
|
if (itemSource)
|
|
{
|
|
if (0 <= itemIndex && itemIndex < itemSource->GetCount())
|
|
{
|
|
auto value = ReadProperty(itemSource->Get(itemIndex), largeImageProperty);
|
|
return value.GetSharedPtr().Cast<GuiImageData>();
|
|
}
|
|
}
|
|
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<ItemSource*>(GetItemProvider());
|
|
|
|
LargeImagePropertyChanged.SetAssociatedComposition(boundsComposition);
|
|
SmallImagePropertyChanged.SetAssociatedComposition(boundsComposition);
|
|
}
|
|
|
|
GuiBindableListView::~GuiBindableListView()
|
|
{
|
|
}
|
|
|
|
list::ListViewDataColumns& GuiBindableListView::GetDataColumns()
|
|
{
|
|
return itemSource->GetDataColumns();
|
|
}
|
|
|
|
list::ListViewColumns& GuiBindableListView::GetColumns()
|
|
{
|
|
return itemSource->GetColumns();
|
|
}
|
|
|
|
Ptr<description::IValueEnumerable> GuiBindableListView::GetItemSource()
|
|
{
|
|
return itemSource->GetItemSource();
|
|
}
|
|
|
|
void GuiBindableListView::SetItemSource(Ptr<description::IValueEnumerable> _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<IValueObservableList>()))
|
|
{
|
|
auto ol = UnboxValue<Ptr<IValueObservableList>>(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<IValueReadonlyList>()))
|
|
{
|
|
childrenVirtualList = UnboxValue<Ptr<IValueReadonlyList>>(value);
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<IValueEnumerable>()))
|
|
{
|
|
auto e = UnboxValue<Ptr<IValueEnumerable>>(value);
|
|
childrenVirtualList = IValueList::Create(GetLazyList<Value>(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<IValueObservableList>();
|
|
ol->ItemChanged.Remove(itemChangedEventHandler);
|
|
itemChangedEventHandler = nullptr;
|
|
}
|
|
childrenVirtualList = nullptr;
|
|
FOREACH(Ptr<ItemSourceNode>, 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<ItemSourceNode>, 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<ItemSourceNode*>(node))
|
|
{
|
|
return itemSourceNode->GetItemSource();
|
|
}
|
|
return Value();
|
|
}
|
|
|
|
// ===================== tree::INodeItemPrimaryTextView =====================
|
|
|
|
WString GuiBindableTreeView::ItemSource::GetPrimaryTextViewText(tree::INodeProvider* node)
|
|
{
|
|
return GetNodeText(node);
|
|
}
|
|
|
|
// ===================== tree::ITreeViewItemView =====================
|
|
|
|
Ptr<GuiImageData> GuiBindableTreeView::ItemSource::GetNodeImage(tree::INodeProvider* node)
|
|
{
|
|
if (auto itemSourceNode = dynamic_cast<ItemSourceNode*>(node))
|
|
{
|
|
auto value = ReadProperty(itemSourceNode->GetItemSource(), imageProperty);
|
|
return value.GetSharedPtr().Cast<GuiImageData>();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
WString GuiBindableTreeView::ItemSource::GetNodeText(tree::INodeProvider* node)
|
|
{
|
|
if (auto itemSourceNode = dynamic_cast<ItemSourceNode*>(node))
|
|
{
|
|
return GetValueText(ReadProperty(itemSourceNode->GetItemSource(), textProperty));
|
|
}
|
|
return L"";
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiBindableTreeView
|
|
***********************************************************************/
|
|
|
|
GuiBindableTreeView::GuiBindableTreeView(IStyleProvider* _styleProvider)
|
|
:GuiVirtualTreeView(_styleProvider, new ItemSource)
|
|
{
|
|
itemSource = dynamic_cast<ItemSource*>(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<ItemSourceNode*>(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<GuiBindableDataEditor*>(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<description::IValueEnumerable> BindableDataProvider::GetItemSource()
|
|
{
|
|
return itemSource;
|
|
}
|
|
|
|
void BindableDataProvider::SetItemSource(Ptr<description::IValueEnumerable> _itemSource)
|
|
{
|
|
vint oldCount = 0;
|
|
if (itemSource)
|
|
{
|
|
oldCount = itemSource->GetCount();
|
|
}
|
|
if (itemChangedEventHandler)
|
|
{
|
|
auto ol = itemSource.Cast<IValueObservableList>();
|
|
ol->ItemChanged.Remove(itemChangedEventHandler);
|
|
}
|
|
|
|
itemSource = nullptr;
|
|
itemChangedEventHandler = nullptr;
|
|
|
|
if (_itemSource)
|
|
{
|
|
if (auto ol = _itemSource.Cast<IValueObservableList>())
|
|
{
|
|
itemSource = ol;
|
|
itemChangedEventHandler = ol->ItemChanged.Add([this](vint start, vint oldCount, vint newCount)
|
|
{
|
|
commandExecutor->OnDataProviderItemModified(start, oldCount, newCount);
|
|
});
|
|
}
|
|
else if (auto rl = _itemSource.Cast<IValueReadonlyList>())
|
|
{
|
|
itemSource = rl;
|
|
}
|
|
else
|
|
{
|
|
itemSource = IValueList::Create(GetLazyList<Value>(_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<BindableDataColumn> column)
|
|
{
|
|
if (InsertColumnInternal(index, column, true))
|
|
{
|
|
column->dataProvider = this;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool BindableDataProvider::AddBindableColumn(Ptr<BindableDataColumn> column)
|
|
{
|
|
if (AddColumnInternal(column, true))
|
|
{
|
|
column->dataProvider = this;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool BindableDataProvider::RemoveBindableColumn(Ptr<BindableDataColumn> column)
|
|
{
|
|
if (RemoveColumnInternal(column, true))
|
|
{
|
|
column->dataProvider = nullptr;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool BindableDataProvider::ClearBindableColumns()
|
|
{
|
|
FOREACH(Ptr<StructuredColummProviderBase>, column, columns)
|
|
{
|
|
column.Cast<BindableDataColumn>()->dataProvider = nullptr;
|
|
}
|
|
return ClearColumnsInternal(true);
|
|
}
|
|
|
|
Ptr<BindableDataColumn> BindableDataProvider::GetBindableColumn(vint index)
|
|
{
|
|
if (0 <= index && index < GetColumnCount())
|
|
{
|
|
return columns[index].Cast<BindableDataColumn>();
|
|
}
|
|
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<BindableDataProvider>();
|
|
}
|
|
|
|
GuiBindableDataGrid::~GuiBindableDataGrid()
|
|
{
|
|
}
|
|
|
|
Ptr<description::IValueEnumerable> GuiBindableDataGrid::GetItemSource()
|
|
{
|
|
return bindableDataProvider->GetItemSource();
|
|
}
|
|
|
|
void GuiBindableDataGrid::SetItemSource(Ptr<description::IValueEnumerable> _itemSource)
|
|
{
|
|
bindableDataProvider->SetItemSource(_itemSource);
|
|
}
|
|
|
|
bool GuiBindableDataGrid::InsertBindableColumn(vint index, Ptr<list::BindableDataColumn> column)
|
|
{
|
|
return bindableDataProvider->InsertBindableColumn(index, column);
|
|
}
|
|
|
|
bool GuiBindableDataGrid::AddBindableColumn(Ptr<list::BindableDataColumn> column)
|
|
{
|
|
return bindableDataProvider->AddBindableColumn(column);
|
|
}
|
|
|
|
bool GuiBindableDataGrid::RemoveBindableColumn(Ptr<list::BindableDataColumn> column)
|
|
{
|
|
return bindableDataProvider->RemoveBindableColumn(column);
|
|
}
|
|
|
|
bool GuiBindableDataGrid::ClearBindableColumns()
|
|
{
|
|
return bindableDataProvider->ClearBindableColumns();
|
|
}
|
|
|
|
Ptr<list::BindableDataColumn> 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<IStyleController*>(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<GuiListControl::IItemPrimaryTextView*>(itemProvider->RequestView(GuiListControl::IItemPrimaryTextView::Identifier));
|
|
itemBindingView = dynamic_cast<GuiListControl::IItemBindingView*>(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::IItemStyleProvider> GuiComboBoxListControl::SetStyleProvider(Ptr<IItemStyleProvider> 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;i<itemProviderCallbacks.Count();i++)
|
|
{
|
|
itemProviderCallbacks[i]->OnItemModified(start, count, newCount);
|
|
}
|
|
}
|
|
|
|
void DataGridItemProvider::InvokeOnColumnChanged()
|
|
{
|
|
for(vint i=0;i<columnItemViewCallbacks.Count();i++)
|
|
{
|
|
columnItemViewCallbacks[i]->OnColumnChanged();
|
|
}
|
|
}
|
|
|
|
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<GuiImageData> DataGridItemProvider::GetSmallImage(vint itemIndex)
|
|
{
|
|
return dataProvider->GetRowSmallImage(itemIndex);
|
|
}
|
|
|
|
Ptr<GuiImageData> 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;i<columnItemViewCallbacks.Count();i++)
|
|
{
|
|
columnItemViewCallbacks[i]->OnColumnChanged();
|
|
}
|
|
}
|
|
|
|
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;i<dataVisualizers.Count();i++)
|
|
{
|
|
IDataVisualizer* visualizer=dataVisualizers[i].Obj();
|
|
GuiGraphicsComposition* composition=visualizer->GetBoundsComposition();
|
|
if(composition->GetParent())
|
|
{
|
|
composition->GetParent()->RemoveChild(composition);
|
|
}
|
|
dataVisualizers[i]=0;
|
|
}
|
|
dataVisualizers.Resize(0);
|
|
|
|
for(vint i=0;i<textTable->GetColumns();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;i<textTable->GetColumns();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<GuiCellComposition*>(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;i<columnCount;i++)
|
|
{
|
|
textTable->SetColumnOption(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;i<dataVisualizers.Count();i++)
|
|
{
|
|
dataVisualizers[i]->SetSelected(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;i<dataVisualizers.Count();i++)
|
|
{
|
|
IDataVisualizerFactory* factory=dataVisualizers[i]->GetFactory();
|
|
if(factory!=GetDataVisualizerFactory(itemIndex, i))
|
|
{
|
|
refresh=true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(refresh)
|
|
{
|
|
RemoveCellsAndDataVisualizers();
|
|
vint columnCount=contentProvider->columnItemView->GetColumnCount();
|
|
|
|
dataVisualizers.Resize(columnCount);
|
|
for(vint i=0;i<dataVisualizers.Count();i++)
|
|
{
|
|
IDataVisualizerFactory* factory=GetDataVisualizerFactory(itemIndex, i);
|
|
dataVisualizers[i]=factory->CreateVisualizer(font, styleProvider);
|
|
}
|
|
|
|
textTable->SetRowsAndColumns(1, columnCount);
|
|
for(vint i=0;i<columnCount;i++)
|
|
{
|
|
GuiCellComposition* cell=new GuiCellComposition;
|
|
textTable->AddChild(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;i<dataVisualizers.Count();i++)
|
|
{
|
|
IDataVisualizer* dataVisualizer=dataVisualizers[i].Obj();
|
|
dataVisualizer->BeforeVisualizeCell(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;i<count;i++)
|
|
{
|
|
GuiListControl::IItemStyleController* itemStyleController=listViewItemStyleProvider->GetCreatedItemStyles().Get(i);
|
|
ItemContent* itemContent=listViewItemStyleProvider->GetItemContent<ItemContent>(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;i<count;i++)
|
|
{
|
|
GuiListControl::IItemStyleController* itemStyleController=listViewItemStyleProvider->GetCreatedItemStyles().Get(i);
|
|
ItemContent* itemContent=listViewItemStyleProvider->GetItemContent<ItemContent>(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;i<count;i++)
|
|
{
|
|
GuiListControl::IItemStyleController* itemStyleController=listViewItemStyleProvider->GetCreatedItemStyles().Get(i);
|
|
ItemContent* itemContent=listViewItemStyleProvider->GetItemContent<ItemContent>(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<ItemContent>(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<GuiVirtualDataGrid*>(value);
|
|
listViewItemStyleProvider=dynamic_cast<ListViewItemStyleProvider*>(value->GetStyleProvider());
|
|
itemProvider=value->GetItemProvider();
|
|
itemProvider->AttachCallback(this);
|
|
columnItemView=dynamic_cast<ListViewColumnItemArranger::IColumnItemView*>(itemProvider->RequestView(ListViewColumnItemArranger::IColumnItemView::Identifier));
|
|
if(columnItemView)
|
|
{
|
|
columnItemView->AttachCallback(this);
|
|
}
|
|
dataProvider=dynamic_cast<IDataProvider*>(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.row<dataProvider->GetRowCount() && 0<=value.column && value.column<dataProvider->GetColumnCount())
|
|
{
|
|
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<DataGridItemProvider*>(GetItemProvider());
|
|
dataProvider=itemProvider->GetDataProvider();
|
|
structuredDataProvider=dataProvider.Cast<StructuredDataProvider>();
|
|
|
|
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.row<dataProvider->GetRowCount())
|
|
{
|
|
EnsureItemVisible(value.row);
|
|
ClearSelection();
|
|
SetSelected(value.row, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ptr<GuiListControl::IItemStyleProvider> GuiVirtualDataGrid::SetStyleProvider(Ptr<GuiListControl::IItemStyleProvider> value)
|
|
{
|
|
Ptr<list::ListViewItemStyleProvider> styleProvider=value.Cast<list::ListViewItemStyleProvider>();
|
|
if(styleProvider)
|
|
{
|
|
list::DataGridContentProvider* dataGridContentProvider=dynamic_cast<list::DataGridContentProvider*>(styleProvider->GetItemContentProvider());
|
|
if(dataGridContentProvider)
|
|
{
|
|
Ptr<GuiListControl::IItemStyleProvider> result=GuiVirtualListView::SetStyleProvider(value);
|
|
if(result)
|
|
{
|
|
contentProvider=dataGridContentProvider;
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool GuiVirtualDataGrid::ChangeItemStyle(Ptr<list::ListViewItemStyleProvider::IListViewItemContentProvider> contentProvider)
|
|
{
|
|
if(contentProvider.Cast<list::DataGridContentProvider>())
|
|
{
|
|
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<StringGridItem>& rowData, WString& cellData)
|
|
{
|
|
vint index=provider->columns.IndexOf(this);
|
|
if(0<=index && index<rowData->strings.Count())
|
|
{
|
|
cellData=rowData->strings[index];
|
|
}
|
|
else
|
|
{
|
|
cellData=L"";
|
|
}
|
|
}
|
|
|
|
void StringGridColumn::SetCellData(const Ptr<StringGridItem>& rowData, const WString& cellData)
|
|
{
|
|
vint index=provider->columns.IndexOf(this);
|
|
if(0<=index && index<rowData->strings.Count())
|
|
{
|
|
rowData->strings[index]=cellData;
|
|
}
|
|
}
|
|
|
|
WString StringGridColumn::GetCellDataText(const WString& cellData)
|
|
{
|
|
return cellData;
|
|
}
|
|
|
|
void StringGridColumn::BeforeEditCell(vint row, IDataEditor* dataEditor)
|
|
{
|
|
TextBoxDataEditor* editor=dynamic_cast<TextBoxDataEditor*>(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<TextBoxDataEditor*>(dataEditor);
|
|
if(editor)
|
|
{
|
|
vint column=provider->columns.IndexOf(this);
|
|
provider->SetGridString(row, column, editor->GetTextBox()->GetText());
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
StringGridProvider
|
|
***********************************************************************/
|
|
|
|
void StringGridProvider::GetRowData(vint row, Ptr<StringGridItem>& rowData)
|
|
{
|
|
rowData=items[row];
|
|
}
|
|
|
|
bool StringGridProvider::GetReadonly()
|
|
{
|
|
return readonly;
|
|
}
|
|
|
|
void StringGridProvider::SetReadonly(bool value)
|
|
{
|
|
if(readonly!=value)
|
|
{
|
|
readonly=value;
|
|
FOREACH(Ptr<StructuredColummProviderBase>, 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()<row) return false;
|
|
Ptr<StringGridItem> item=new StringGridItem;
|
|
for(vint i=0;i<columns.Count();i++)
|
|
{
|
|
item->strings.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<StringGridItem> 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<StringGridColumn> 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<StringGridItem>, 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<StringGridColumn> columnProvider=columns[source].Cast<StringGridColumn>();
|
|
columns.RemoveAt(source);
|
|
columns.Insert(target, columnProvider);
|
|
|
|
FOREACH(Ptr<StringGridItem>, 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<StringGridColumn> columnProvider=columns[column].Cast<StringGridColumn>();
|
|
if(!RemoveColumnInternal(columnProvider, false)) return false;
|
|
|
|
FOREACH(Ptr<StringGridItem>, item, items)
|
|
{
|
|
item->strings.RemoveAt(column);
|
|
}
|
|
if(commandExecutor)
|
|
{
|
|
commandExecutor->OnDataProviderColumnChanged();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool StringGridProvider::ClearColumns()
|
|
{
|
|
if(!ClearColumnsInternal(false)) return false;
|
|
|
|
FOREACH(Ptr<StringGridItem>, 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<IDataVisualizer> _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<GuiImageData> 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<IDataVisualizer> 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<IDataVisualizer> 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<IStructuredDataFilter> 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<IStructuredDataFilter> 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;i<filters.Count();i++)
|
|
{
|
|
filters[i]->SetCommandExecutor(value);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
StructuredDataAndFilter
|
|
***********************************************************************/
|
|
|
|
StructuredDataAndFilter::StructuredDataAndFilter()
|
|
{
|
|
}
|
|
|
|
bool StructuredDataAndFilter::Filter(vint row)
|
|
{
|
|
return From(filters)
|
|
.All([row](Ptr<IStructuredDataFilter> filter)
|
|
{
|
|
return filter->Filter(row);
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
StructuredDataOrFilter
|
|
***********************************************************************/
|
|
|
|
StructuredDataOrFilter::StructuredDataOrFilter()
|
|
{
|
|
}
|
|
|
|
bool StructuredDataOrFilter::Filter(vint row)
|
|
{
|
|
return From(filters)
|
|
.Any([row](Ptr<IStructuredDataFilter> filter)
|
|
{
|
|
return filter->Filter(row);
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
StructuredDataNotFilter
|
|
***********************************************************************/
|
|
|
|
StructuredDataNotFilter::StructuredDataNotFilter()
|
|
{
|
|
}
|
|
|
|
bool StructuredDataNotFilter::SetSubFilter(Ptr<IStructuredDataFilter> 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<IStructuredDataSorter> value)
|
|
{
|
|
if(leftSorter==value) return false;
|
|
leftSorter=value;
|
|
return true;
|
|
}
|
|
|
|
bool StructuredDataMultipleSorter::SetRightSorter(Ptr<IStructuredDataSorter> 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<IStructuredDataSorter> 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<Ptr<IStructuredDataFilter>> selectedFilters;
|
|
CopyFrom(
|
|
selectedFilters,
|
|
Range<vint>(0, GetColumnCount())
|
|
.Select([this](vint column){return structuredDataProvider->GetColumn(column)->GetInherentFilter();})
|
|
.Where([](Ptr<IStructuredDataFilter> filter){return (bool)filter;})
|
|
);
|
|
if(additionalFilter)
|
|
{
|
|
selectedFilters.Add(additionalFilter);
|
|
}
|
|
if(selectedFilters.Count()>0)
|
|
{
|
|
Ptr<StructuredDataAndFilter> andFilter=new StructuredDataAndFilter;
|
|
FOREACH(Ptr<IStructuredDataFilter>, 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;i<rowCount;i++)
|
|
{
|
|
if(currentFilter->Filter(i))
|
|
{
|
|
reorderedRows.Add(i);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(vint i=0;i<rowCount;i++)
|
|
{
|
|
reorderedRows.Add(i);
|
|
}
|
|
}
|
|
|
|
if(currentSorter && reorderedRows.Count()>0)
|
|
{
|
|
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<IStructuredDataProvider> StructuredDataProvider::GetStructuredDataProvider()
|
|
{
|
|
return structuredDataProvider;
|
|
}
|
|
|
|
Ptr<IStructuredDataFilter> StructuredDataProvider::GetAdditionalFilter()
|
|
{
|
|
return additionalFilter;
|
|
}
|
|
|
|
void StructuredDataProvider::SetAdditionalFilter(Ptr<IStructuredDataFilter> value)
|
|
{
|
|
additionalFilter=value;
|
|
RebuildFilter(true);
|
|
ReorderRows(true);
|
|
}
|
|
|
|
StructuredDataProvider::StructuredDataProvider(Ptr<IStructuredDataProvider> 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 && column<structuredDataProvider->GetColumnCount())
|
|
{
|
|
Ptr<IStructuredDataSorter> sorter=structuredDataProvider->GetColumn(column)->GetInherentSorter();
|
|
if(!sorter)
|
|
{
|
|
currentSorter=0;
|
|
}
|
|
else if(ascending)
|
|
{
|
|
currentSorter=sorter;
|
|
}
|
|
else
|
|
{
|
|
Ptr<StructuredDataReverseSorter> reverseSorter=new StructuredDataReverseSorter();
|
|
reverseSorter->SetSubSorter(sorter);
|
|
currentSorter=reverseSorter;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
currentSorter=0;
|
|
}
|
|
for(vint i=0;i<structuredDataProvider->GetColumnCount();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;i<structuredDataProvider->GetColumnCount();i++)
|
|
{
|
|
GuiListViewColumnHeader::ColumnSortingState state=structuredDataProvider->GetColumn(i)->GetSortingState();
|
|
if(state!=GuiListViewColumnHeader::NotSorted)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
bool StructuredDataProvider::IsSortOrderAscending()
|
|
{
|
|
for(vint i=0;i<structuredDataProvider->GetColumnCount();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<GuiImageData> StructuredDataProvider::GetRowLargeImage(vint row)
|
|
{
|
|
return structuredDataProvider->GetRowLargeImage(TranslateRowNumber(row));
|
|
}
|
|
|
|
Ptr<GuiImageData> 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<IStructuredDataFilter> value)
|
|
{
|
|
inherentFilter=value;
|
|
if(commandExecutor)
|
|
{
|
|
commandExecutor->OnDataProviderColumnChanged();
|
|
}
|
|
return this;
|
|
}
|
|
|
|
StructuredColummProviderBase* StructuredColummProviderBase::SetInherentSorter(Ptr<IStructuredDataSorter> value)
|
|
{
|
|
inherentSorter=value;
|
|
if(commandExecutor)
|
|
{
|
|
commandExecutor->OnDataProviderColumnChanged();
|
|
}
|
|
return this;
|
|
}
|
|
|
|
Ptr<IDataVisualizerFactory> StructuredColummProviderBase::GetVisualizerFactory()
|
|
{
|
|
return visualizerFactory;
|
|
}
|
|
|
|
StructuredColummProviderBase* StructuredColummProviderBase::SetVisualizerFactory(Ptr<IDataVisualizerFactory> value)
|
|
{
|
|
visualizerFactory=value;
|
|
return this;
|
|
}
|
|
|
|
Ptr<IDataEditorFactory> StructuredColummProviderBase::GetEditorFactory()
|
|
{
|
|
return editorFactory;
|
|
}
|
|
|
|
StructuredColummProviderBase* StructuredColummProviderBase::SetEditorFactory(Ptr<IDataEditorFactory> 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<IStructuredDataFilter> StructuredColummProviderBase::GetInherentFilter()
|
|
{
|
|
return inherentFilter;
|
|
}
|
|
|
|
Ptr<IStructuredDataSorter> 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<StructuredColummProviderBase> value, bool callback)
|
|
{
|
|
if(column<0 || columns.Count()<column) return false;
|
|
if(columns.Contains(value.Obj())) return false;
|
|
columns.Insert(column, value);
|
|
value->SetCommandExecutor(commandExecutor);
|
|
if(callback && commandExecutor)
|
|
{
|
|
commandExecutor->OnDataProviderColumnChanged();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool StructuredDataProviderBase::AddColumnInternal(Ptr<StructuredColummProviderBase> value, bool callback)
|
|
{
|
|
return InsertColumnInternal(columns.Count(), value, callback);
|
|
}
|
|
|
|
bool StructuredDataProviderBase::RemoveColumnInternal(Ptr<StructuredColummProviderBase> 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<StructuredColummProviderBase>, 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<StructuredColummProviderBase>, column, columns)
|
|
{
|
|
column->SetCommandExecutor(commandExecutor);
|
|
}
|
|
}
|
|
|
|
vint StructuredDataProviderBase::GetColumnCount()
|
|
{
|
|
return columns.Count();
|
|
}
|
|
|
|
IStructuredColumnProvider* StructuredDataProviderBase::GetColumn(vint column)
|
|
{
|
|
return columns[column].Obj();
|
|
}
|
|
|
|
Ptr<GuiImageData> StructuredDataProviderBase::GetRowLargeImage(vint row)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Ptr<GuiImageData> 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;i<cachedStyles.Count();i++)
|
|
{
|
|
listControl->itemStyleProvider->DestroyItemStyle(cachedStyles[i]);
|
|
}
|
|
for(vint i=0;i<installedStyles.Count();i++)
|
|
{
|
|
listControl->itemStyleProvider->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;i<cachedStyles.Count();i++)
|
|
{
|
|
IItemStyleController* cachedStyle=cachedStyles[i];
|
|
if(cachedStyle->GetItemStyleId()==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<IItemStyleProvider> styleProvider, Ptr<IItemArranger> 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<void(GuiItemMouseEvent&, IItemStyleController*, GuiGraphicsComposition*, GuiMouseEventArgs&)> 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<void(GuiItemNotifyEvent&, IItemStyleController*, GuiGraphicsComposition*, GuiEventArgs&)> 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<VisibleStyleHelper> 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<VisibleStyleHelper> 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::IItemStyleProvider> GuiListControl::SetStyleProvider(Ptr<IItemStyleProvider> value)
|
|
{
|
|
Ptr<IItemStyleProvider> old=itemStyleProvider;
|
|
SetStyleProviderAndArranger(value, itemArranger);
|
|
StyleProviderChanged.Execute(GetNotifyEventArguments());
|
|
return old;
|
|
}
|
|
|
|
GuiListControl::IItemArranger* GuiListControl::GetArranger()
|
|
{
|
|
return itemArranger.Obj();
|
|
}
|
|
|
|
Ptr<GuiListControl::IItemArranger> GuiListControl::SetArranger(Ptr<IItemArranger> value)
|
|
{
|
|
Ptr<IItemArranger> old=itemArranger;
|
|
SetStyleProviderAndArranger(itemStyleProvider, value);
|
|
ArrangerChanged.Execute(GetNotifyEventArguments());
|
|
return old;
|
|
}
|
|
|
|
compositions::IGuiAxis* GuiListControl::GetAxis()
|
|
{
|
|
return axis.Obj();
|
|
}
|
|
|
|
Ptr<compositions::IGuiAxis> GuiListControl::SetAxis(Ptr<compositions::IGuiAxis> value)
|
|
{
|
|
Ptr<IGuiAxis> 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;i<visibleStyles.Count();i++)
|
|
{
|
|
selectableStyleProvider->SetStyleSelected(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<GuiListControl::IItemStyleProvider> GuiSelectableListControl::SetStyleProvider(Ptr<GuiListControl::IItemStyleProvider> value)
|
|
{
|
|
selectableStyleProvider = value ? value.Cast<IItemStyleProvider>() : nullptr;
|
|
return GuiListControl::SetStyleProvider(value);
|
|
}
|
|
|
|
bool GuiSelectableListControl::GetMultiSelect()
|
|
{
|
|
return multiSelect;
|
|
}
|
|
|
|
void GuiSelectableListControl::SetMultiSelect(bool value)
|
|
{
|
|
if(multiSelect!=value)
|
|
{
|
|
multiSelect=value;
|
|
ClearSelection();
|
|
}
|
|
}
|
|
|
|
const collections::SortedList<vint>& 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<IItemPrimaryTextView*>(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 && itemIndex<itemProvider->Count())
|
|
{
|
|
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;i<visibleStyles.Count();i++)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i];
|
|
callback->ReleaseItem(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<GuiListControl::IItemStyleController*> reusedStyles;
|
|
for(vint i=0;i<visibleCount;i++)
|
|
{
|
|
vint index=startIndex+i;
|
|
if(index>=itemCount)
|
|
{
|
|
break;
|
|
}
|
|
|
|
vint oldIndex=-1;
|
|
if(index<start)
|
|
{
|
|
oldIndex=index;
|
|
}
|
|
else if(index>=start+newCount)
|
|
{
|
|
oldIndex=index-newCount+count;
|
|
}
|
|
|
|
if(oldIndex!=-1)
|
|
{
|
|
if(oldIndex>=startIndex && oldIndex<startIndex+visibleCount)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[oldIndex-startIndex];
|
|
reusedStyles.Add(style);
|
|
visibleStyles.Add(style);
|
|
}
|
|
else
|
|
{
|
|
oldIndex=-1;
|
|
}
|
|
}
|
|
if(oldIndex==-1)
|
|
{
|
|
GuiListControl::IItemStyleController* style=callback->RequestItem(index);
|
|
visibleStyles.Add(style);
|
|
}
|
|
}
|
|
|
|
for(vint i=0;i<visibleCount;i++)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i];
|
|
if(!reusedStyles.Contains(style))
|
|
{
|
|
callback->ReleaseItem(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 && itemIndex<startIndex+visibleStyles.Count())
|
|
{
|
|
return visibleStyles[itemIndex-startIndex];
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
vint RangedItemArrangerBase::GetVisibleIndex(GuiListControl::IItemStyleController* style)
|
|
{
|
|
vint index=visibleStyles.IndexOf(style);
|
|
return index==-1?-1:index+startIndex;
|
|
}
|
|
|
|
void RangedItemArrangerBase::OnViewChanged(Rect bounds)
|
|
{
|
|
Rect oldBounds=viewBounds;
|
|
viewBounds=bounds;
|
|
if(callback)
|
|
{
|
|
OnViewChangedInternal(oldBounds, viewBounds);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
FixedHeightItemArranger
|
|
***********************************************************************/
|
|
|
|
void FixedHeightItemArranger::RearrangeItemBounds()
|
|
{
|
|
vint x0=-viewBounds.Left();
|
|
vint y0=-viewBounds.Top()+GetYOffset();
|
|
vint width=GetWidth();
|
|
for(vint i=0;i<visibleStyles.Count();i++)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i];
|
|
vint top=y0+(startIndex+i)*rowHeight;
|
|
if(width==-1)
|
|
{
|
|
callback->SetStyleAlignmentToParent(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 && i<itemCount;i++)
|
|
{
|
|
if(startIndex<=i && i<=endIndex)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i-startIndex];
|
|
visibleStyles.Add(style);
|
|
}
|
|
else
|
|
{
|
|
GuiListControl::IItemStyleController* style=callback->RequestItem(i);
|
|
visibleStyles.Add(style);
|
|
vint styleHeight=callback->GetStylePreferredSize(style).y;
|
|
if(newRowHeight<styleHeight)
|
|
{
|
|
newRowHeight=styleHeight;
|
|
newEndIndex = newStartIndex + (newBounds.Height() - 1) / newRowHeight + 1;
|
|
if (newEndIndex < i)
|
|
{
|
|
newEndIndex = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for(vint i=0;i<oldVisibleCount;i++)
|
|
{
|
|
vint index=startIndex+i;
|
|
if(index<newStartIndex || newEndIndex<index)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i];
|
|
callback->ReleaseItem(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()<rowHeight)
|
|
{
|
|
if(viewBounds.Top()<bottom && top<viewBounds.Bottom())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
Point location=viewBounds.LeftTop();
|
|
if(top<viewBounds.Top())
|
|
{
|
|
location.y=top;
|
|
}
|
|
else if(viewBounds.Bottom()<bottom)
|
|
{
|
|
location.y=bottom-viewBounds.Height();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
callback->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;i<visibleStyles.Count();i++)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i];
|
|
vint row=(startIndex+i)/rowItems;
|
|
vint col=(startIndex+i)%rowItems;
|
|
callback->SetStyleBounds(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) && newStartIndex<newEndIndex)
|
|
{
|
|
newEndIndex=newStartIndex;
|
|
}
|
|
|
|
vint previousStartIndex=-1;
|
|
vint previousEndIndex=-1;
|
|
|
|
while(true)
|
|
{
|
|
for(vint i=newStartIndex;i<=newEndIndex;i++)
|
|
{
|
|
if(startIndex<=i && i<=endIndex)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i-startIndex];
|
|
visibleStyles.Add(style);
|
|
}
|
|
else if(i<previousStartIndex || i>previousEndIndex)
|
|
{
|
|
GuiListControl::IItemStyleController* style=callback->RequestItem(i);
|
|
|
|
if(i<previousStartIndex)
|
|
{
|
|
visibleStyles.Insert(oldVisibleCount+(i-newStartIndex), style);
|
|
}
|
|
else
|
|
{
|
|
visibleStyles.Add(style);
|
|
}
|
|
|
|
Size styleSize=callback->GetStylePreferredSize(style);
|
|
if(newItemSize.x<styleSize.x) newItemSize.x=styleSize.x;
|
|
if(newItemSize.y<styleSize.y) newItemSize.y=styleSize.y;
|
|
}
|
|
}
|
|
|
|
vint updatedStartIndex=0;
|
|
vint updatedEndIndex=0;
|
|
CalculateRange(newItemSize, newBounds, itemCount, updatedStartIndex, updatedEndIndex);
|
|
bool again=updatedStartIndex<newStartIndex || updatedEndIndex>newEndIndex;
|
|
previousStartIndex=newStartIndex;
|
|
previousEndIndex=newEndIndex;
|
|
if(updatedStartIndex<newStartIndex) newStartIndex=updatedStartIndex;
|
|
if(updatedEndIndex>newEndIndex) newEndIndex=updatedEndIndex;
|
|
if(!again) break;
|
|
}
|
|
|
|
for(vint i=0;i<oldVisibleCount;i++)
|
|
{
|
|
vint index=startIndex+i;
|
|
if(index<newStartIndex || newEndIndex<index)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i];
|
|
callback->ReleaseItem(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()<rowHeight)
|
|
{
|
|
if(viewBounds.Top()<bottom && top<viewBounds.Bottom())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
Point location=viewBounds.LeftTop();
|
|
if(top<viewBounds.Top())
|
|
{
|
|
location.y=top;
|
|
}
|
|
else if(viewBounds.Bottom()<bottom)
|
|
{
|
|
location.y=bottom-viewBounds.Height();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
callback->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;i<visibleStyles.Count();i++)
|
|
{
|
|
vint column=i%rows;
|
|
if(column==0)
|
|
{
|
|
totalWidth+=currentWidth;
|
|
currentWidth=0;
|
|
}
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i];
|
|
vint itemWidth=callback->GetStylePreferredSize(style).x;
|
|
if(currentWidth<itemWidth) currentWidth=itemWidth;
|
|
callback->SetStyleBounds(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<itemCount;i++)
|
|
{
|
|
if(i%newRows==0)
|
|
{
|
|
totalWidth+=currentWidth;
|
|
currentWidth=0;
|
|
if(totalWidth>=newBounds.Width())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
newEndIndex=i;
|
|
|
|
if(startIndex<=i && i<=endIndex)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i-startIndex];
|
|
visibleStyles.Add(style);
|
|
}
|
|
else if(i<previousStartIndex || i>previousEndIndex)
|
|
{
|
|
GuiListControl::IItemStyleController* style=callback->RequestItem(i);
|
|
|
|
if(i<previousStartIndex)
|
|
{
|
|
visibleStyles.Insert(oldVisibleCount+(i-newStartIndex), style);
|
|
}
|
|
else
|
|
{
|
|
visibleStyles.Add(style);
|
|
}
|
|
|
|
Size styleSize=callback->GetStylePreferredSize(style);
|
|
if(currentWidth<styleSize.x) currentWidth=styleSize.x;
|
|
if(newItemHeight<styleSize.y) newItemHeight=styleSize.y;
|
|
if(currentItemHeight!=newItemHeight) break;
|
|
}
|
|
}
|
|
|
|
if(previousStartIndex==-1 || previousStartIndex<newStartIndex) previousStartIndex=newStartIndex;
|
|
if(previousEndIndex==-1 || previousEndIndex>newEndIndex) previousEndIndex=newEndIndex;
|
|
if(currentItemHeight==newItemHeight)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
newStartIndex=previousStartIndex;
|
|
newEndIndex=previousEndIndex;
|
|
|
|
for(vint i=0;i<oldVisibleCount;i++)
|
|
{
|
|
vint index=startIndex+i;
|
|
if(index<newStartIndex || newEndIndex<index)
|
|
{
|
|
GuiListControl::IItemStyleController* style=visibleStyles[i];
|
|
callback->ReleaseItem(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(0<bounds.Bottom() && bounds.Top()<viewBounds.Width() && bounds.Width()>viewBounds.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<minIndex/rowCount)
|
|
{
|
|
location.x-=viewBounds.Width();
|
|
}
|
|
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;i<callbacks.Count();i++)
|
|
{
|
|
callbacks[i]->OnItemModified(start, count, newCount);
|
|
}
|
|
}
|
|
|
|
ItemProviderBase::ItemProviderBase()
|
|
{
|
|
}
|
|
|
|
ItemProviderBase::~ItemProviderBase()
|
|
{
|
|
for(vint i=0;i<callbacks.Count();i++)
|
|
{
|
|
callbacks[i]->OnAttached(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<GuiListViewBase*>(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<ListViewItemStyleController*>(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<IStyleProvider*>(styleController->GetStyleProvider());
|
|
ColumnClicked.SetAssociatedComposition(boundsComposition);
|
|
}
|
|
|
|
GuiListViewBase::~GuiListViewBase()
|
|
{
|
|
}
|
|
|
|
GuiListViewBase::IStyleProvider* GuiListViewBase::GetListViewStyleProvider()
|
|
{
|
|
return styleProvider;
|
|
}
|
|
|
|
Ptr<GuiListControl::IItemStyleProvider> GuiListViewBase::SetStyleProvider(Ptr<GuiListControl::IItemStyleProvider> value)
|
|
{
|
|
if(value.Cast<list::ListViewItemStyleProvider>())
|
|
{
|
|
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<IListViewItemContentProvider> itemContentProvider)
|
|
:listViewItemView(0)
|
|
,listViewItemContentProvider(itemContentProvider)
|
|
{
|
|
}
|
|
|
|
ListViewItemStyleProvider::~ListViewItemStyleProvider()
|
|
{
|
|
}
|
|
|
|
void ListViewItemStyleProvider::AttachListControl(GuiListControl* value)
|
|
{
|
|
ListViewItemStyleProviderBase::AttachListControl(value);
|
|
listViewItemView=dynamic_cast<IListViewItemView*>(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<ListViewContentItemStyleController*>(style);
|
|
if(itemStyle)
|
|
{
|
|
itemStyles.Remove(itemStyle);
|
|
delete itemStyle;
|
|
}
|
|
}
|
|
|
|
void ListViewItemStyleProvider::Install(GuiListControl::IItemStyleController* style, vint itemIndex)
|
|
{
|
|
ListViewContentItemStyleController* itemStyle=dynamic_cast<ListViewContentItemStyleController*>(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<ListViewContentItemStyleController*>(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<GuiImageData> 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<GuiImageData> 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<GuiImageData> 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;i<textRows;i++)
|
|
{
|
|
textTable->SetRowOption(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<GuiImageData> 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;i<dataTexts.Count();i++)
|
|
{
|
|
RemoveTextElement(i+1);
|
|
}
|
|
vint dataColumnCount=view->GetDataColumnCount();
|
|
ResetTextTable(dataColumnCount+1);
|
|
dataTexts.Resize(dataColumnCount);
|
|
for(vint i=0;i<dataColumnCount;i++)
|
|
{
|
|
dataTexts[i]=CreateTextElement(i+1, text->GetFont());
|
|
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<GuiImageData> 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<GuiBoundsComposition*>(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(width<SplitterWidth)
|
|
{
|
|
width=SplitterWidth;
|
|
}
|
|
return width;
|
|
}
|
|
|
|
vint ListViewColumnItemArranger::GetYOffset()
|
|
{
|
|
return columnHeaders->GetBounds().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;i<columnItemView->GetColumnCount();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;i<columnItemView->GetColumnCount();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;i<columnItemView->GetColumnCount();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<void(vint, GuiGraphicsComposition*, GuiEventArgs&)>(this, &ListViewColumnItemArranger::ColumnClicked))(i));
|
|
button->GetBoundsComposition()->BoundsChanged.AttachLambda(Curry(Func<void(vint, GuiGraphicsComposition*, GuiEventArgs&)>(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<GuiListViewBase*>(value);
|
|
if(listView)
|
|
{
|
|
styleProvider=listView->GetListViewStyleProvider();
|
|
listView->GetContainerComposition()->AddChild(columnHeaders);
|
|
columnItemView=dynamic_cast<IColumnItemView*>(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<ListViewColumnItemArranger::IColumnItemView*>(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;i<columnCount;i++)
|
|
{
|
|
textTable->SetColumnOption(i, GuiCellOption::AbsoluteOption(columnItemView->GetColumnSize(i)));
|
|
}
|
|
textTable->UpdateCellBounds();
|
|
}
|
|
|
|
void ListViewDetailContentProvider::ItemContent::Install(GuiListViewBase::IStyleProvider* styleProvider, ListViewItemStyleProvider::IListViewItemView* view, vint itemIndex)
|
|
{
|
|
for(vint i=1;i<textTable->GetColumns();i++)
|
|
{
|
|
GuiCellComposition* cell=textTable->GetSitedCell(0, i);
|
|
textTable->RemoveChild(cell);
|
|
delete cell;
|
|
}
|
|
|
|
Ptr<GuiImageData> 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;i<columnCount;i++)
|
|
{
|
|
GuiCellComposition* cell=new GuiCellComposition;
|
|
textTable->AddChild(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;i<count;i++)
|
|
{
|
|
GuiListControl::IItemStyleController* itemStyleController=listViewItemStyleProvider->GetCreatedItemStyles().Get(i);
|
|
ItemContent* itemContent=listViewItemStyleProvider->GetItemContent<ItemContent>(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<ListViewItemStyleProvider*>(value->GetStyleProvider());
|
|
itemProvider=value->GetItemProvider();
|
|
columnItemView=dynamic_cast<ListViewColumnItemArranger::IColumnItemView*>(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<GuiImageData> ListViewItem::GetSmallImage()
|
|
{
|
|
return smallImage;
|
|
}
|
|
|
|
void ListViewItem::SetSmallImage(Ptr<GuiImageData> value)
|
|
{
|
|
smallImage = value;
|
|
NotifyUpdate();
|
|
}
|
|
|
|
Ptr<GuiImageData> ListViewItem::GetLargeImage()
|
|
{
|
|
return largeImage;
|
|
}
|
|
|
|
void ListViewItem::SetLargeImage(Ptr<GuiImageData> 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<ListViewColumn>& value)
|
|
{
|
|
ItemsBase<Ptr<ListViewColumn>>::AfterInsert(index, value);
|
|
value->owner = this;
|
|
}
|
|
|
|
void ListViewColumns::BeforeRemove(vint index, const Ptr<ListViewColumn>& value)
|
|
{
|
|
value->owner = 0;
|
|
ItemsBase<Ptr<ListViewColumn>>::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<ListViewItem>& value)
|
|
{
|
|
ListProvider<Ptr<ListViewItem>>::AfterInsert(index, value);
|
|
value->owner = this;
|
|
}
|
|
|
|
void ListViewItemProvider::BeforeRemove(vint index, const Ptr<ListViewItem>& value)
|
|
{
|
|
value->owner = 0;
|
|
ListProvider<Ptr<ListViewItem>>::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<GuiImageData> ListViewItemProvider::GetSmallImage(vint itemIndex)
|
|
{
|
|
return Get(itemIndex)->smallImage;
|
|
}
|
|
|
|
Ptr<GuiImageData> 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<ListViewItem> 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 && index<columns.Count())
|
|
{
|
|
columns[index]->SetSize(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<list::ListViewItemStyleProvider::IListViewItemContentProvider> 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<list::ListViewItemProvider*>(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<list::ListViewItem> 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<GuiVirtualTextList*>(value);
|
|
textItemView=dynamic_cast<ITextItemView*>(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<TextItemStyleController*>(style);
|
|
}
|
|
|
|
void TextItemStyleProvider::Install(GuiListControl::IItemStyleController* style, vint itemIndex)
|
|
{
|
|
TextItemStyleController* textStyle=dynamic_cast<TextItemStyleController*>(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<TextItemStyleController*>(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<TextItem>& value)
|
|
{
|
|
ListProvider<Ptr<TextItem>>::AfterInsert(item, value);
|
|
value->owner = this;
|
|
}
|
|
|
|
void TextItemProvider::BeforeRemove(vint item, const Ptr<TextItem>& value)
|
|
{
|
|
value->owner = 0;
|
|
ListProvider<Ptr<TextItem>>::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<IStyleProvider*>(styleController->GetStyleProvider());
|
|
ChangeItemStyle(_bulletFactory);
|
|
SetArranger(new list::FixedHeightItemArranger);
|
|
}
|
|
|
|
GuiVirtualTextList::~GuiVirtualTextList()
|
|
{
|
|
}
|
|
|
|
GuiVirtualTextList::IStyleProvider* GuiVirtualTextList::GetTextListStyleProvider()
|
|
{
|
|
return styleProvider;
|
|
}
|
|
|
|
Ptr<GuiListControl::IItemStyleProvider> 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<list::TextItemProvider*>(itemProvider.Obj());
|
|
items->listControl=this;
|
|
}
|
|
|
|
GuiTextList::~GuiTextList()
|
|
{
|
|
}
|
|
|
|
list::TextItemProvider& GuiTextList::GetItems()
|
|
{
|
|
return *items;
|
|
}
|
|
|
|
Ptr<list::TextItem> 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 && i<count);i++)
|
|
{
|
|
INodeProvider* child=provider->GetChild(i);
|
|
vint visibleCount=child->CalculateTotalVisibleNodes();
|
|
if(offset<visibleCount)
|
|
{
|
|
result=GetNodeByOffset(child, offset);
|
|
}
|
|
else
|
|
{
|
|
offset-=visibleCount;
|
|
}
|
|
}
|
|
}
|
|
ReleaseNode(provider);
|
|
return result;
|
|
}
|
|
|
|
void NodeItemProvider::OnAttached(INodeRootProvider* provider)
|
|
{
|
|
}
|
|
|
|
void NodeItemProvider::OnBeforeItemModified(INodeProvider* parentNode, vint start, vint count, vint newCount)
|
|
{
|
|
vint offset = 0;
|
|
vint base=CalculateNodeVisibilityIndexInternal(parentNode);
|
|
if(base!=-2 && parentNode->GetExpanding())
|
|
{
|
|
for(vint i=0;i<count;i++)
|
|
{
|
|
INodeProvider* child=parentNode->GetChild(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;i<newCount;i++)
|
|
{
|
|
INodeProvider* child=parentNode->GetChild(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(start<childCount)
|
|
{
|
|
INodeProvider* child=parentNode->GetChild(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;i<count;i++)
|
|
{
|
|
INodeProvider* child=node->GetChild(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;i<count;i++)
|
|
{
|
|
INodeProvider* child=parent->GetChild(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<INodeRootProvider> _root)
|
|
:root(_root)
|
|
{
|
|
root->AttachCallback(this);
|
|
nodeItemPrimaryTextView=dynamic_cast<INodeItemPrimaryTextView*>(root->RequestView(INodeItemPrimaryTextView::Identifier));
|
|
}
|
|
|
|
NodeItemProvider::~NodeItemProvider()
|
|
{
|
|
if(nodeItemPrimaryTextView)
|
|
{
|
|
root->ReleaseView(nodeItemPrimaryTextView);
|
|
}
|
|
root->DetachCallback(this);
|
|
}
|
|
|
|
Ptr<INodeRootProvider> 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<INodeItemView*>(view)==0)
|
|
{
|
|
root->ReleaseView(view);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
NodeItemProvider
|
|
***********************************************************************/
|
|
|
|
NodeItemStyleProvider::NodeItemStyleProvider(Ptr<INodeItemStyleProvider> provider)
|
|
:nodeItemStyleProvider(provider)
|
|
,listControl(0)
|
|
,nodeItemView(0)
|
|
{
|
|
nodeItemStyleProvider->BindItemStyleProvider(this);
|
|
}
|
|
|
|
NodeItemStyleProvider::~NodeItemStyleProvider()
|
|
{
|
|
}
|
|
|
|
void NodeItemStyleProvider::AttachListControl(GuiListControl* value)
|
|
{
|
|
listControl=value;
|
|
nodeItemView=dynamic_cast<INodeItemView*>(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<INodeItemStyleController*>(style);
|
|
if(nodeStyle)
|
|
{
|
|
nodeItemStyleProvider->DestroyItemStyle(nodeStyle);
|
|
}
|
|
}
|
|
|
|
void NodeItemStyleProvider::Install(GuiListControl::IItemStyleController* style, vint itemIndex)
|
|
{
|
|
if(nodeItemView)
|
|
{
|
|
INodeItemStyleController* nodeStyle=dynamic_cast<INodeItemStyleController*>(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<INodeItemStyleController*>(style);
|
|
if(nodeStyle)
|
|
{
|
|
nodeItemStyleProvider->SetStyleIndex(nodeStyle, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NodeItemStyleProvider::SetStyleSelected(GuiListControl::IItemStyleController* style, bool value)
|
|
{
|
|
if(nodeItemView)
|
|
{
|
|
INodeItemStyleController* nodeStyle=dynamic_cast<INodeItemStyleController*>(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;i<count;i++)
|
|
{
|
|
ownerProvider->offsetBeforeChildModified+=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;i<newCount;i++)
|
|
{
|
|
offset+=items[start+i]->totalVisibleNodeCount;
|
|
}
|
|
ownerProvider->OnChildTotalVisibleNodesChanged(offset-ownerProvider->offsetBeforeChildModified);
|
|
}
|
|
INodeProviderCallback* proxy=ownerProvider->GetCallbackProxyInternal();
|
|
if(proxy)
|
|
{
|
|
proxy->OnAfterItemModified(ownerProvider, start, count, newCount);
|
|
}
|
|
}
|
|
|
|
bool MemoryNodeProvider::NodeCollection::QueryInsert(vint index, Ptr<MemoryNodeProvider> const& child)
|
|
{
|
|
return child->parent == 0;
|
|
}
|
|
|
|
bool MemoryNodeProvider::NodeCollection::QueryRemove(vint index, Ptr<MemoryNodeProvider> const& child)
|
|
{
|
|
return child->parent == ownerProvider;
|
|
}
|
|
|
|
void MemoryNodeProvider::NodeCollection::BeforeInsert(vint index, Ptr<MemoryNodeProvider> const& child)
|
|
{
|
|
OnBeforeChildModified(index, 0, 1);
|
|
child->parent = ownerProvider;
|
|
}
|
|
|
|
void MemoryNodeProvider::NodeCollection::BeforeRemove(vint index, Ptr<MemoryNodeProvider> const& child)
|
|
{
|
|
OnBeforeChildModified(index, 1, 0);
|
|
child->parent = 0;
|
|
}
|
|
|
|
void MemoryNodeProvider::NodeCollection::AfterInsert(vint index, Ptr<MemoryNodeProvider> 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<IMemoryNodeData>& _data)
|
|
:parent(0)
|
|
,expanding(false)
|
|
,childCount(0)
|
|
,totalVisibleNodeCount(1)
|
|
,offsetBeforeChildModified(0)
|
|
,data(_data)
|
|
{
|
|
children.ownerProvider=this;
|
|
}
|
|
|
|
MemoryNodeProvider::~MemoryNodeProvider()
|
|
{
|
|
}
|
|
|
|
Ptr<IMemoryNodeData> MemoryNodeProvider::GetData()
|
|
{
|
|
return data;
|
|
}
|
|
|
|
void MemoryNodeProvider::SetData(const Ptr<IMemoryNodeData>& 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;i<childCount;i++)
|
|
{
|
|
offset+=children[i]->totalVisibleNodeCount;
|
|
}
|
|
|
|
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 && index<childCount)
|
|
{
|
|
return children[index].Obj();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void MemoryNodeProvider::Increase()
|
|
{
|
|
}
|
|
|
|
void MemoryNodeProvider::Release()
|
|
{
|
|
}
|
|
|
|
/***********************************************************************
|
|
NodeRootProviderBase
|
|
***********************************************************************/
|
|
|
|
void NodeRootProviderBase::OnAttached(INodeRootProvider* provider)
|
|
{
|
|
}
|
|
|
|
void NodeRootProviderBase::OnBeforeItemModified(INodeProvider* parentNode, vint start, vint count, vint newCount)
|
|
{
|
|
for(vint i=0;i<callbacks.Count();i++)
|
|
{
|
|
callbacks[i]->OnBeforeItemModified(parentNode, start, count, newCount);
|
|
}
|
|
}
|
|
|
|
void NodeRootProviderBase::OnAfterItemModified(INodeProvider* parentNode, vint start, vint count, vint newCount)
|
|
{
|
|
for(vint i=0;i<callbacks.Count();i++)
|
|
{
|
|
callbacks[i]->OnAfterItemModified(parentNode, start, count, newCount);
|
|
}
|
|
}
|
|
|
|
void NodeRootProviderBase::OnItemExpanded(INodeProvider* node)
|
|
{
|
|
for(vint i=0;i<callbacks.Count();i++)
|
|
{
|
|
callbacks[i]->OnItemExpanded(node);
|
|
}
|
|
}
|
|
|
|
void NodeRootProviderBase::OnItemCollapsed(INodeProvider* node)
|
|
{
|
|
for(vint i=0;i<callbacks.Count();i++)
|
|
{
|
|
callbacks[i]->OnItemCollapsed(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<MemoryNodeProvider*>(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<void(GuiNodeMouseEvent&, GuiGraphicsComposition*, GuiItemMouseEventArgs&)> func(this, &GuiVirtualTreeListControl::OnItemMouseEvent);\
|
|
ITEMEVENTNAME.AttachFunction(Curry(func)(NODEEVENTNAME));\
|
|
}\
|
|
|
|
#define ATTACH_ITEM_NOTIFY_EVENT(NODEEVENTNAME, ITEMEVENTNAME)\
|
|
{\
|
|
Func<void(GuiNodeNotifyEvent&, GuiGraphicsComposition*, GuiItemEventArgs&)> func(this, &GuiVirtualTreeListControl::OnItemNotifyEvent);\
|
|
ITEMEVENTNAME.AttachFunction(Curry(func)(NODEEVENTNAME));\
|
|
}\
|
|
|
|
GuiVirtualTreeListControl::GuiVirtualTreeListControl(IStyleProvider* _styleProvider, Ptr<tree::INodeRootProvider> _nodeRootProvider)
|
|
:GuiSelectableListControl(_styleProvider, new tree::NodeItemProvider(_nodeRootProvider))
|
|
{
|
|
nodeItemProvider=dynamic_cast<tree::NodeItemProvider*>(GetItemProvider());
|
|
nodeItemView=dynamic_cast<tree::INodeItemView*>(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<tree::INodeItemStyleProvider> GuiVirtualTreeListControl::SetNodeStyleProvider(Ptr<tree::INodeItemStyleProvider> styleProvider)
|
|
{
|
|
Ptr<tree::INodeItemStyleProvider> 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<GuiImageData>& _image, const WString& _text)
|
|
:image(_image)
|
|
,text(_text)
|
|
{
|
|
}
|
|
|
|
/***********************************************************************
|
|
TreeViewItemRootProvider
|
|
***********************************************************************/
|
|
|
|
WString TreeViewItemRootProvider::GetPrimaryTextViewText(INodeProvider* node)
|
|
{
|
|
return GetNodeText(node);
|
|
}
|
|
|
|
Ptr<GuiImageData> TreeViewItemRootProvider::GetNodeImage(INodeProvider* node)
|
|
{
|
|
MemoryNodeProvider* memoryNode=dynamic_cast<MemoryNodeProvider*>(node);
|
|
if(memoryNode)
|
|
{
|
|
Ptr<TreeViewItem> data=memoryNode->GetData().Cast<TreeViewItem>();
|
|
if(data)
|
|
{
|
|
return data->image;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
WString TreeViewItemRootProvider::GetNodeText(INodeProvider* node)
|
|
{
|
|
MemoryNodeProvider* memoryNode=dynamic_cast<MemoryNodeProvider*>(node);
|
|
if(memoryNode)
|
|
{
|
|
Ptr<TreeViewItem> data=memoryNode->GetData().Cast<TreeViewItem>();
|
|
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<TreeViewItem> TreeViewItemRootProvider::GetTreeViewData(INodeProvider* node)
|
|
{
|
|
MemoryNodeProvider* memoryNode=GetMemoryNode(node);
|
|
if(memoryNode)
|
|
{
|
|
return memoryNode->GetData().Cast<TreeViewItem>();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void TreeViewItemRootProvider::SetTreeViewData(INodeProvider* node, Ptr<TreeViewItem> 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<tree::INodeRootProvider> _nodeRootProvider)
|
|
:GuiVirtualTreeListControl(_styleProvider, _nodeRootProvider)
|
|
{
|
|
styleProvider=dynamic_cast<IStyleProvider*>(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<tree::TreeViewItemRootProvider>();
|
|
}
|
|
|
|
GuiTreeView::~GuiTreeView()
|
|
{
|
|
}
|
|
|
|
Ptr<tree::TreeViewItemRootProvider> GuiTreeView::Nodes()
|
|
{
|
|
return nodes;
|
|
}
|
|
|
|
Ptr<tree::TreeViewItem> GuiTreeView::GetSelectedItem()
|
|
{
|
|
Ptr<tree::TreeViewItem> result;
|
|
vint index = GetSelectedItemIndex();
|
|
if (index != -1)
|
|
{
|
|
if (auto node = nodeItemView->RequestNode(index))
|
|
{
|
|
if (auto memoryNode = dynamic_cast<tree::MemoryNodeProvider*>(node))
|
|
{
|
|
result = memoryNode->GetData().Cast<tree::TreeViewItem>();
|
|
}
|
|
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<GuiImageData> 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<ItemController*>(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<GuiVirtualTreeView*>(value);
|
|
if(treeControl)
|
|
{
|
|
treeViewItemView=dynamic_cast<ITreeViewItemView*>(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<ItemController*>(style);
|
|
if(itemController)
|
|
{
|
|
delete itemController;
|
|
}
|
|
}
|
|
|
|
void TreeViewNodeItemStyleProvider::Install(INodeItemStyleController* style, INodeProvider* node, vint itemIndex)
|
|
{
|
|
ItemController* itemController=dynamic_cast<ItemController*>(style);
|
|
if(itemController)
|
|
{
|
|
itemController->Install(node);
|
|
}
|
|
}
|
|
|
|
void TreeViewNodeItemStyleProvider::SetStyleIndex(INodeItemStyleController* style, vint value)
|
|
{
|
|
}
|
|
|
|
void TreeViewNodeItemStyleProvider::SetStyleSelected(INodeItemStyleController* style, bool value)
|
|
{
|
|
ItemController* itemController=dynamic_cast<ItemController*>(style);
|
|
if(itemController)
|
|
{
|
|
itemController->SetSelected(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
CONTROLS\STYLES\GUICOMMONSTYLES.CPP
|
|
***********************************************************************/
|
|
#include <math.h>
|
|
|
|
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(delta1<delta2)
|
|
{
|
|
commandExecutor->SetPosition(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.x<handleBounds.x1)
|
|
{
|
|
commandExecutor->BigDecrease();
|
|
}
|
|
else if(arguments.x>=handleBounds.x2)
|
|
{
|
|
commandExecutor->BigIncrease();
|
|
}
|
|
break;
|
|
case Vertical:
|
|
if(arguments.y<handleBounds.y1)
|
|
{
|
|
commandExecutor->BigDecrease();
|
|
}
|
|
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(delta1<delta2)
|
|
{
|
|
commandExecutor->SetPosition(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<GuiImageData> 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<IGuiGraphicsElement> 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<GuiImageData> 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<GuiImageData> 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<GuiImageData> 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<text::ColorEntry> 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<GuiMultilineTextBox::StyleController*>(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<GuiSinglelineTextBox::StyleController*>(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<DocumentModel> Win7DocumentViewerStyle::GetBaselineDocument()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Win7DocumentlabelStyle
|
|
***********************************************************************/
|
|
|
|
Win7DocumentLabelStyle::Win7DocumentLabelStyle()
|
|
{
|
|
}
|
|
|
|
Win7DocumentLabelStyle::~Win7DocumentLabelStyle()
|
|
{
|
|
}
|
|
|
|
Ptr<DocumentModel> 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<DocumentModel> 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<GuiSelectableButton*>(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;i<itemCount;i++)
|
|
{
|
|
GuiStackItemComposition* item=tabHeaderComposition->GetStackItems().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;i<itemCount;i++)
|
|
{
|
|
if(headerButtons[i]->GetSelected())
|
|
{
|
|
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<IGuiAltAction>();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
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<GuiImageData> 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<IGuiGraphicsElement> 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<GuiImageData> 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<GuiImageData> 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<GuiImageData> 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<text::ColorEntry> 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<GuiMultilineTextBox::StyleController*>(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<GuiSinglelineTextBox::StyleController*>(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<DocumentModel> Win8DocumentViewerStyle::GetBaselineDocument()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Win8DocumentlabelStyle
|
|
***********************************************************************/
|
|
|
|
Win8DocumentLabelStyle::Win8DocumentLabelStyle()
|
|
{
|
|
}
|
|
|
|
Win8DocumentLabelStyle::~Win8DocumentLabelStyle()
|
|
{
|
|
}
|
|
|
|
Ptr<DocumentModel> 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<DocumentModel> 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<GuiImageData> 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<ITypeDescriptor*> types;
|
|
|
|
public:
|
|
GuiTemplateReflectableFactory(const List<ITypeDescriptor*>& _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<Value> arguments(ctor->GetParameterCount());
|
|
if (ctor->GetParameterCount() == 1)
|
|
{
|
|
if (!viewModel.CanConvertTo(ctor->GetParameter(0)->GetType()))
|
|
{
|
|
continue;
|
|
}
|
|
arguments[0] = viewModel;
|
|
}
|
|
return dynamic_cast<GuiTemplate*>(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> GuiTemplate::IFactory::CreateTemplateFactory(const collections::List<description::ITypeDescriptor*>& 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<GuiTemplate::IFactory> factory, description::Value viewModel)
|
|
:associatedStyleController(0)
|
|
, controlTemplate(0)
|
|
{
|
|
GuiTemplate* itemTemplate = factory->CreateTemplate(viewModel);
|
|
if (!(controlTemplate = dynamic_cast<GuiControlTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiLabelTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiSinglelineTextBoxTemplate*>(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<GuiSinglelineTextBox::StyleController*>(associatedStyleController))
|
|
{
|
|
auto element = style->GetTextElement();
|
|
Array<text::ColorEntry> 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<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiDocumentLabelTemplate*>(GetBoundsComposition())))
|
|
{
|
|
CHECK_FAIL(L"GuiDocumentLabelTemplate_StyleProvider::GuiDocumentLabelTemplate_StyleProvider()#An instance of GuiDocumentLabelTemplate is expected.");
|
|
}
|
|
}
|
|
|
|
GuiDocumentLabelTemplate_StyleProvider::~GuiDocumentLabelTemplate_StyleProvider()
|
|
{
|
|
}
|
|
|
|
Ptr<DocumentModel> GuiDocumentLabelTemplate_StyleProvider::GetBaselineDocument()
|
|
{
|
|
return controlTemplate->GetBaselineDocument();
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiMenuTemplate_StyleProvider
|
|
***********************************************************************/
|
|
|
|
GuiMenuTemplate_StyleProvider::GuiMenuTemplate_StyleProvider(Ptr<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
}
|
|
|
|
GuiMenuTemplate_StyleProvider::~GuiMenuTemplate_StyleProvider()
|
|
{
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiWindowTemplate_StyleProvider
|
|
***********************************************************************/
|
|
|
|
GuiWindowTemplate_StyleProvider::GuiWindowTemplate_StyleProvider(Ptr<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
, window(0)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiWindowTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiButtonTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiButtonTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiSelectableButtonTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiSelectableButtonTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiToolstripButtonTemplate*>(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<GuiImageData> value)
|
|
{
|
|
controlTemplate->SetImage(value);
|
|
}
|
|
|
|
void GuiToolstripButtonTemplate_StyleProvider::SetShortcutText(const WString& value)
|
|
{
|
|
controlTemplate->SetShortcutText(value);
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiListViewColumnHeaderTemplate_StyleProvider
|
|
***********************************************************************/
|
|
|
|
GuiListViewColumnHeaderTemplate_StyleProvider::GuiListViewColumnHeaderTemplate_StyleProvider(Ptr<GuiTemplate::IFactory> factory)
|
|
:GuiToolstripButtonTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiListViewColumnHeaderTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiToolstripButtonTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiComboBoxTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiDatePickerTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiComboBoxTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiDateComboBoxTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiScrollTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiScrollViewTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiScrollViewTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiMultilineTextBoxTemplate*>(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<GuiMultilineTextBox::StyleController*>(associatedStyleController))
|
|
{
|
|
auto element = style->GetTextElement();
|
|
Array<text::ColorEntry> colors(1);
|
|
colors[0] = controlTemplate->GetTextColor();
|
|
element->SetColors(colors);
|
|
element->SetCaretColor(controlTemplate->GetCaretColor());
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiDocumentViewerTemplate_StyleProvider
|
|
***********************************************************************/
|
|
|
|
GuiDocumentViewerTemplate_StyleProvider::GuiDocumentViewerTemplate_StyleProvider(Ptr<GuiTemplate::IFactory> factory)
|
|
:GuiScrollViewTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiDocumentViewerTemplate*>(GetBoundsComposition())))
|
|
{
|
|
CHECK_FAIL(L"GuiDocumentViewerTemplate_StyleProvider::GuiDocumentViewerTemplate_StyleProvider()#An instance of GuiDocumentViewerTemplate is expected.");
|
|
}
|
|
}
|
|
|
|
GuiDocumentViewerTemplate_StyleProvider::~GuiDocumentViewerTemplate_StyleProvider()
|
|
{
|
|
}
|
|
|
|
Ptr<DocumentModel> 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<GuiTemplate::IFactory> factory)
|
|
:GuiScrollViewTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiTextListTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiScrollViewTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiListViewTemplate*>(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<GuiTemplate::IFactory> factory)
|
|
:GuiScrollViewTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiTreeViewTemplate*>(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<GuiSelectableButton*>(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;i<itemCount;i++)
|
|
{
|
|
GuiStackItemComposition* item=tabHeaderComposition->GetStackItems().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;i<itemCount;i++)
|
|
{
|
|
if(headerButtons[i]->GetSelected())
|
|
{
|
|
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<GuiTemplate::IFactory> factory)
|
|
:GuiControlTemplate_StyleProvider(factory)
|
|
{
|
|
if (!(controlTemplate = dynamic_cast<GuiTabTemplate*>(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<IGuiAltAction>();
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiControlTemplate_ItemStyleProvider
|
|
***********************************************************************/
|
|
|
|
GuiControlTemplate_ItemStyleProvider::GuiControlTemplate_ItemStyleProvider(Ptr<GuiTemplate::IFactory> _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<GuiTemplate::IFactory> _factory)
|
|
:factory(_factory)
|
|
, listControl(0)
|
|
, bindingView(0)
|
|
{
|
|
}
|
|
|
|
GuiTextListItemTemplate_ItemStyleProvider::~GuiTextListItemTemplate_ItemStyleProvider()
|
|
{
|
|
}
|
|
|
|
void GuiTextListItemTemplate_ItemStyleProvider::AttachListControl(controls::GuiListControl* value)
|
|
{
|
|
listControl = dynamic_cast<GuiVirtualTextList*>(value);
|
|
bindingView = dynamic_cast<GuiListControl::IItemBindingView*>(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<GuiTextListItemTemplate_ItemStyleController*>(style))
|
|
{
|
|
Value viewModel;
|
|
if (bindingView)
|
|
{
|
|
viewModel = bindingView->GetBindingValue(itemIndex);
|
|
}
|
|
|
|
GuiTemplate* itemTemplate = factory->CreateTemplate(viewModel);
|
|
if (auto listItemTemplate = dynamic_cast<GuiTextListItemTemplate*>(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<GuiTextListItemTemplate_ItemStyleController*>(style))
|
|
{
|
|
if (auto itemTemplate = controller->GetTemplate())
|
|
{
|
|
itemTemplate->SetIndex(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiTextListItemTemplate_ItemStyleProvider::SetStyleSelected(controls::GuiListControl::IItemStyleController* style, bool value)
|
|
{
|
|
if (auto controller = dynamic_cast<GuiTextListItemTemplate_ItemStyleController*>(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<GuiTreeItemTemplate_ItemStyleController*>(style))
|
|
{
|
|
if (auto itemTemplate = dynamic_cast<GuiTreeItemTemplate*>(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<GuiTemplate::IFactory> _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<GuiVirtualTreeListControl*>(value);
|
|
if (treeListControl)
|
|
{
|
|
treeListControl->GetNodeRootProvider()->AttachCallback(this);
|
|
bindingView = dynamic_cast<tree::INodeItemBindingView*>(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<GuiTreeItemTemplate_ItemStyleController*>(style))
|
|
{
|
|
Value viewModel;
|
|
if (bindingView)
|
|
{
|
|
viewModel = bindingView->GetBindingValue(node);
|
|
}
|
|
|
|
GuiTemplate* itemTemplate = factory->CreateTemplate(viewModel);
|
|
if (auto treeItemTemplate = dynamic_cast<GuiTreeItemTemplate*>(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<GuiTreeItemTemplate_ItemStyleController*>(style))
|
|
{
|
|
if (auto itemTemplate = controller->GetTemplate())
|
|
{
|
|
itemTemplate->SetIndex(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiTreeItemTemplate_ItemStyleProvider::SetStyleSelected(controls::tree::INodeItemStyleController* style, bool value)
|
|
{
|
|
if (auto controller = dynamic_cast<GuiTreeItemTemplate_ItemStyleController*>(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<GuiTemplate::IFactory> _templateFactory, controls::list::BindableDataColumn* _ownerColumn)
|
|
:templateFactory(_templateFactory)
|
|
, ownerColumn(_ownerColumn)
|
|
{
|
|
}
|
|
|
|
GuiBindableDataVisualizer::Factory::~Factory()
|
|
{
|
|
}
|
|
|
|
Ptr<controls::list::IDataVisualizer> GuiBindableDataVisualizer::Factory::CreateVisualizer(const FontProperties& font, controls::GuiListViewBase::IStyleProvider* styleProvider)
|
|
{
|
|
auto visualizer = DataVisualizerFactory<GuiBindableDataVisualizer>::CreateVisualizer(font, styleProvider).Cast<GuiBindableDataVisualizer>();
|
|
if (visualizer)
|
|
{
|
|
visualizer->templateFactory = templateFactory;
|
|
visualizer->ownerColumn = ownerColumn;
|
|
}
|
|
return visualizer;
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiBindableDataVisualizer::DecoratedFactory
|
|
***********************************************************************/
|
|
|
|
GuiBindableDataVisualizer::DecoratedFactory::DecoratedFactory(Ptr<GuiTemplate::IFactory> _templateFactory, controls::list::BindableDataColumn* _ownerColumn, Ptr<controls::list::IDataVisualizerFactory> _decoratedFactory)
|
|
:DataDecoratableVisualizerFactory<GuiBindableDataVisualizer>(_decoratedFactory)
|
|
, templateFactory(_templateFactory)
|
|
, ownerColumn(_ownerColumn)
|
|
{
|
|
}
|
|
|
|
GuiBindableDataVisualizer::DecoratedFactory::~DecoratedFactory()
|
|
{
|
|
}
|
|
|
|
Ptr<controls::list::IDataVisualizer> GuiBindableDataVisualizer::DecoratedFactory::CreateVisualizer(const FontProperties& font, controls::GuiListViewBase::IStyleProvider* styleProvider)
|
|
{
|
|
auto visualizer = DataDecoratableVisualizerFactory<GuiBindableDataVisualizer>::CreateVisualizer(font, styleProvider).Cast<GuiBindableDataVisualizer>();
|
|
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<GuiGridVisualizerTemplate*>(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<controls::list::IDataVisualizer> _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<list::StructuredDataProvider*>(dataProvider);
|
|
if (!structuredDataProvider) return;
|
|
|
|
auto bindableDataProvider = structuredDataProvider->GetStructuredDataProvider().Cast<list::BindableDataProvider>();
|
|
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<GuiTemplate::IFactory> _templateFactory, controls::list::BindableDataColumn* _ownerColumn)
|
|
:templateFactory(_templateFactory)
|
|
, ownerColumn(_ownerColumn)
|
|
{
|
|
}
|
|
|
|
GuiBindableDataEditor::Factory::~Factory()
|
|
{
|
|
}
|
|
|
|
Ptr<controls::list::IDataEditor> GuiBindableDataEditor::Factory::CreateEditor(controls::list::IDataEditorCallback* callback)
|
|
{
|
|
auto editor = DataEditorFactory<GuiBindableDataEditor>::CreateEditor(callback).Cast<GuiBindableDataEditor>();
|
|
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<GuiGridEditorTemplate*>(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<list::StructuredDataProvider*>(dataProvider);
|
|
if (!structuredDataProvider) return;
|
|
|
|
auto bindableDataProvider = structuredDataProvider->GetStructuredDataProvider().Cast<list::BindableDataProvider>();
|
|
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<WString>& 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<GuiTemplate::IFactory> CreateTemplateFactory(const WString& typeValues)
|
|
{
|
|
List<ITypeDescriptor*> types;
|
|
List<WString> typeNames;
|
|
SplitBySemicolon(typeValues, typeNames);
|
|
CopyFrom(
|
|
types,
|
|
From(typeNames)
|
|
.Select<ITypeDescriptor*(*)(const WString&)>(&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<WString> 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<WString> text;
|
|
EditText(documentElement->GetCaretBegin(), documentElement->GetCaretEnd(), documentElement->IsCaretEndPreferFrontSide(), text);
|
|
return true;
|
|
}
|
|
break;
|
|
case VKEY_RETURN:
|
|
if(editMode==Editable)
|
|
{
|
|
if(ctrl)
|
|
{
|
|
Array<WString> text(1);
|
|
text[0]=L"\r\n";
|
|
EditText(documentElement->GetCaretBegin(), documentElement->GetCaretEnd(), documentElement->IsCaretEndPreferFrontSide(), text);
|
|
}
|
|
else
|
|
{
|
|
Array<WString> 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<DocumentHyperlinkRun> 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<void()>& 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<void(TextPos, TextPos, vint&, vint&)>& editor)
|
|
{
|
|
// save run before editing
|
|
if(begin>end)
|
|
{
|
|
TextPos temp=begin;
|
|
begin=end;
|
|
end=temp;
|
|
}
|
|
Ptr<DocumentModel> 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<DocumentModel> 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<void(TextPos, TextPos)>& editor)
|
|
{
|
|
// save run before editing
|
|
if(begin>end)
|
|
{
|
|
TextPos temp=begin;
|
|
begin=end;
|
|
end=temp;
|
|
}
|
|
Ptr<DocumentModel> originalModel=documentElement->GetDocument()->CopyDocument(begin, end, true);
|
|
if(originalModel)
|
|
{
|
|
// edit
|
|
editor(begin, end);
|
|
|
|
// save run after editing
|
|
Ptr<DocumentModel> 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<DocumentModel> 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<WString> 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<DocumentHyperlinkRun> 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():caret<oldCaret));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiDocumentCommonInterface::OnMouseDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments)
|
|
{
|
|
if(documentControl->GetVisuallyEnabled())
|
|
{
|
|
documentControl->SetFocus();
|
|
switch(editMode)
|
|
{
|
|
case ViewOnly:
|
|
{
|
|
Point point(arguments.x, arguments.y);
|
|
Ptr<DocumentHyperlinkRun> 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, caret<oldCaret);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
dragging=true;
|
|
}
|
|
}
|
|
|
|
void GuiDocumentCommonInterface::OnMouseUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments)
|
|
{
|
|
if(documentControl->GetVisuallyEnabled())
|
|
{
|
|
dragging=false;
|
|
switch(editMode)
|
|
{
|
|
case ViewOnly:
|
|
{
|
|
Point point(arguments.x, arguments.y);
|
|
Ptr<DocumentHyperlinkRun> 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<GuiDocumentItem>, item, documentItems.Values())
|
|
{
|
|
item->visible = false;
|
|
}
|
|
}
|
|
|
|
void GuiDocumentCommonInterface::OnFinishRender()
|
|
{
|
|
FOREACH(Ptr<GuiDocumentItem>, 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<DocumentModel> _baselineDocument)
|
|
:baselineDocument(_baselineDocument)
|
|
,documentElement(0)
|
|
,documentComposition(0)
|
|
,activeHyperlinkParagraph(-1)
|
|
,dragging(false)
|
|
,editMode(ViewOnly)
|
|
,documentControl(0)
|
|
{
|
|
undoRedoProcessor=new GuiDocumentUndoRedoProcessor;
|
|
|
|
internalShortcutKeyManager=new GuiShortcutKeyManager;
|
|
AddShortcutCommand('Z', Func<bool()>(this, &GuiDocumentCommonInterface::Undo));
|
|
AddShortcutCommand('Y', Func<bool()>(this, &GuiDocumentCommonInterface::Redo));
|
|
AddShortcutCommand('A', Func<void()>(this, &GuiDocumentCommonInterface::SelectAll));
|
|
AddShortcutCommand('X', Func<bool()>(this, &GuiDocumentCommonInterface::Cut));
|
|
AddShortcutCommand('C', Func<bool()>(this, &GuiDocumentCommonInterface::Copy));
|
|
AddShortcutCommand('V', Func<bool()>(this, &GuiDocumentCommonInterface::Paste));
|
|
}
|
|
|
|
GuiDocumentCommonInterface::~GuiDocumentCommonInterface()
|
|
{
|
|
}
|
|
|
|
Ptr<DocumentModel> GuiDocumentCommonInterface::GetDocument()
|
|
{
|
|
return documentElement->GetDocument();
|
|
}
|
|
|
|
void GuiDocumentCommonInterface::SetDocument(Ptr<DocumentModel> 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<GuiDocumentItem> 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<GuiDocumentItem> 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<DocumentModel> 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<WString>& 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<DocumentStyleProperties> style)
|
|
{
|
|
EditStyleInternal(begin, end, [=](TextPos begin, TextPos end)
|
|
{
|
|
documentElement->EditStyle(begin, end, style);
|
|
});
|
|
}
|
|
|
|
void GuiDocumentCommonInterface::EditImage(TextPos begin, TextPos end, Ptr<GuiImageData> 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<DocumentStyleProperties> GuiDocumentCommonInterface::SummarizeStyle(TextPos begin, TextPos end)
|
|
{
|
|
return documentElement->SummarizeStyle(begin, end);
|
|
}
|
|
|
|
void GuiDocumentCommonInterface::SetParagraphAlignment(TextPos begin, TextPos end, const collections::Array<Nullable<Alignment>>& alignments)
|
|
{
|
|
vint first=begin.row;
|
|
vint last=end.row;
|
|
if(first>last)
|
|
{
|
|
vint temp=first;
|
|
first=last;
|
|
last=temp;
|
|
}
|
|
|
|
Ptr<DocumentModel> document=documentElement->GetDocument();
|
|
if(0<=first && first<document->paragraphs.Count() && 0<=last && last<document->paragraphs.Count() && last-first+1==alignments.Count())
|
|
{
|
|
Ptr<GuiDocumentUndoRedoProcessor::SetAlignmentStruct> 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<DocumentParagraphRun> 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<DocumentModel> model=documentElement->GetDocument()->CopyDocument(begin, end, false);
|
|
return model->GetText(true);
|
|
}
|
|
|
|
void GuiDocumentCommonInterface::SetSelectionText(const WString& value)
|
|
{
|
|
List<WString> 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<WString> text;
|
|
CopyFrom(text, paragraphs);
|
|
EditText(begin, end, documentElement->IsCaretEndPreferFrontSide(), text);
|
|
}
|
|
|
|
Ptr<DocumentModel> GuiDocumentCommonInterface::GetSelectionModel()
|
|
{
|
|
TextPos begin=documentElement->GetCaretBegin();
|
|
TextPos end=documentElement->GetCaretEnd();
|
|
if(begin>end)
|
|
{
|
|
TextPos temp=begin;
|
|
begin=end;
|
|
end=temp;
|
|
}
|
|
|
|
Ptr<DocumentModel> model=documentElement->GetDocument()->CopyDocument(begin, end, true);
|
|
return model;
|
|
}
|
|
|
|
void GuiDocumentCommonInterface::SetSelectionModel(Ptr<DocumentModel> 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.y1<viewBounds.y1)
|
|
{
|
|
offset=bounds.y1-viewBounds.y1;
|
|
}
|
|
else if(bounds.y2>viewBounds.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.x1<view.x1)
|
|
{
|
|
viewPoint.x=bounds.x1;
|
|
}
|
|
else if(bounds.x2>view.x2)
|
|
{
|
|
viewPoint.x=bounds.x2-view.Width();
|
|
}
|
|
if(bounds.y1<view.y1)
|
|
{
|
|
viewPoint.y=bounds.y1;
|
|
}
|
|
else if(bounds.y2>view.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;i<textEditCallbacks.Count();i++)
|
|
{
|
|
textEditCallbacks[i]->TextCaretChanged(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;i<textEditCallbacks.Count();i++)
|
|
{
|
|
textEditCallbacks[i]->TextEditPreview(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;i<textEditCallbacks.Count();i++)
|
|
{
|
|
textEditCallbacks[i]->TextEditNotify(arguments);
|
|
}
|
|
}
|
|
|
|
Move(end, false);
|
|
|
|
for(vint i=0;i<textEditCallbacks.Count();i++)
|
|
{
|
|
textEditCallbacks[i]->TextEditFinished(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.row<textElement->GetLines().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;i<textEditCallbacks.Count();i++)
|
|
{
|
|
textEditCallbacks[i]->Attach(textElement, elementModifyLock, textComposition ,editVersion);
|
|
}
|
|
}
|
|
|
|
GuiTextBoxCommonInterface::ICallback* GuiTextBoxCommonInterface::GetCallback()
|
|
{
|
|
return callback;
|
|
}
|
|
|
|
void GuiTextBoxCommonInterface::SetCallback(ICallback* value)
|
|
{
|
|
callback=value;
|
|
}
|
|
|
|
bool GuiTextBoxCommonInterface::AttachTextEditCallback(Ptr<ICommonTextEditCallback> 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<ICommonTextEditCallback> value)
|
|
{
|
|
if(textEditCallbacks.Remove(value.Obj()))
|
|
{
|
|
value->Detach();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void GuiTextBoxCommonInterface::AddShortcutCommand(vint key, const Func<void()>& 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<bool()>(this, &GuiTextBoxCommonInterface::Undo));
|
|
AddShortcutCommand('Y', Func<bool()>(this, &GuiTextBoxCommonInterface::Redo));
|
|
AddShortcutCommand('A', Func<void()>(this, &GuiTextBoxCommonInterface::SelectAll));
|
|
AddShortcutCommand('X', Func<bool()>(this, &GuiTextBoxCommonInterface::Cut));
|
|
AddShortcutCommand('C', Func<bool()>(this, &GuiTextBoxCommonInterface::Copy));
|
|
AddShortcutCommand('V', Func<bool()>(this, &GuiTextBoxCommonInterface::Paste));
|
|
}
|
|
|
|
GuiTextBoxCommonInterface::~GuiTextBoxCommonInterface()
|
|
{
|
|
if(colorizer)
|
|
{
|
|
DetachTextEditCallback(colorizer);
|
|
colorizer=0;
|
|
}
|
|
if(undoRedoProcessor)
|
|
{
|
|
DetachTextEditCallback(undoRedoProcessor);
|
|
undoRedoProcessor=0;
|
|
}
|
|
|
|
for(vint i=0;i<textEditCallbacks.Count();i++)
|
|
{
|
|
textEditCallbacks[i]->Detach();
|
|
}
|
|
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()<textElement->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 c1<c2?c1:c2;
|
|
}
|
|
|
|
TextPos GuiTextBoxCommonInterface::GetCaretLarge()
|
|
{
|
|
TextPos c1=GetCaretBegin();
|
|
TextPos c2=GetCaretEnd();
|
|
return c1>c2?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.column<textElement->GetLines().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<GuiTextBoxColorizerBase> GuiTextBoxCommonInterface::GetColorizer()
|
|
{
|
|
return colorizer;
|
|
}
|
|
|
|
void GuiTextBoxCommonInterface::SetColorizer(Ptr<GuiTextBoxColorizerBase> 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<GuiTextBoxAutoCompleteBase> GuiTextBoxCommonInterface::GetAutoComplete()
|
|
{
|
|
return autoComplete;
|
|
}
|
|
|
|
void GuiTextBoxCommonInterface::SetAutoComplete(Ptr<GuiTextBoxAutoCompleteBase> 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<GuiMultilineTextBox*>(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<StyleController*>(_textControl->GetStyleController())->GetTextElement(),
|
|
dynamic_cast<StyleController*>(_textControl->GetStyleController())->GetTextComposition()
|
|
)
|
|
,textControl(_textControl)
|
|
,textController(dynamic_cast<StyleController*>(_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.x<point.x)
|
|
{
|
|
marginX=TextMargin;
|
|
}
|
|
else if(oldPoint.x>point.x)
|
|
{
|
|
marginX=-TextMargin;
|
|
}
|
|
if(oldPoint.y<point.y)
|
|
{
|
|
marginY=TextMargin;
|
|
}
|
|
else if(oldPoint.y>point.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<StyleController*>(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<StyleController*>(_textControl->GetStyleController())->GetTextElement(),
|
|
dynamic_cast<StyleController*>(_textControl->GetStyleController())->GetTextComposition()
|
|
)
|
|
,textControl(_textControl)
|
|
,textController(dynamic_cast<StyleController*>(_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;i<length;i++)
|
|
{
|
|
if(*input==0 || *input==L'\r' || *input==L'\n')
|
|
{
|
|
length=i;
|
|
break;
|
|
}
|
|
}
|
|
if(length!=inputText.Length())
|
|
{
|
|
inputText=inputText.Left(length);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void GuiSinglelineTextBox::TextElementOperatorCallback::AfterModify(TextPos originalStart, TextPos originalEnd, const WString& originalText, TextPos inputStart, TextPos inputEnd, const WString& inputText)
|
|
{
|
|
}
|
|
|
|
void GuiSinglelineTextBox::TextElementOperatorCallback::ScrollToView(Point point)
|
|
{
|
|
vint newX=point.x;
|
|
vint oldX=textElement->GetViewPosition().x;
|
|
vint marginX=0;
|
|
if(oldX<newX)
|
|
{
|
|
marginX=TextMargin;
|
|
}
|
|
else if(oldX>newX)
|
|
{
|
|
marginX=-TextMargin;
|
|
}
|
|
|
|
newX+=marginX;
|
|
vint minX=-TextMargin;
|
|
vint maxX=textElement->GetLines().GetMaxWidth()+TextMargin-textComposition->GetBounds().Width();
|
|
if(newX>=maxX)
|
|
{
|
|
newX=maxX-1;
|
|
}
|
|
if(newX<minX)
|
|
{
|
|
newX=minX;
|
|
}
|
|
textElement->SetViewPosition(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<StyleController*>(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<AutoCompleteItem>& 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<IAutoCompleteControlProvider> _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<AutoCompleteItem>& items)
|
|
{
|
|
if(items.Count()==0)
|
|
{
|
|
CloseList();
|
|
}
|
|
|
|
List<AutoCompleteItem> 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<GuiTextBoxCommonInterface*>(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(lineIndex<colorizer->colorizedLineCount && lineIndex<colorizer->element->GetLines().GetCount())
|
|
{
|
|
TextLine& line=colorizer->element->GetLines().GetLine(lineIndex);
|
|
line.lexerFinalState=lexerState;
|
|
line.contextFinalState=contextState;
|
|
for(vint i=0;i<length;i++)
|
|
{
|
|
line.att[i].colorIndex=colors[i];
|
|
}
|
|
}
|
|
delete[] text;
|
|
delete[] colors;
|
|
}
|
|
}
|
|
CANCEL_COLORIZING:
|
|
colorizer->colorizerRunningEvent.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.row<arguments.originalEnd.row
|
|
?arguments.originalStart.row
|
|
:arguments.originalEnd.row;
|
|
if(colorizedLineCount>line)
|
|
{
|
|
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<length;i++)
|
|
{
|
|
data.colors[start+i]=(int)token+1;
|
|
}
|
|
}
|
|
|
|
GuiTextBoxRegexColorizer::GuiTextBoxRegexColorizer()
|
|
{
|
|
colors.Resize(1);
|
|
}
|
|
|
|
GuiTextBoxRegexColorizer::~GuiTextBoxRegexColorizer()
|
|
{
|
|
StopColorizerForever();
|
|
}
|
|
|
|
elements::text::ColorEntry GuiTextBoxRegexColorizer::GetDefaultColor()
|
|
{
|
|
return defaultColor;
|
|
}
|
|
|
|
collections::List<WString>& GuiTextBoxRegexColorizer::GetTokenRegexes()
|
|
{
|
|
return tokenRegexes;
|
|
}
|
|
|
|
collections::List<elements::text::ColorEntry>& GuiTextBoxRegexColorizer::GetTokenColors()
|
|
{
|
|
return tokenColors;
|
|
}
|
|
|
|
collections::List<elements::text::ColorEntry>& 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;i<tokenColors.Count();i++)
|
|
{
|
|
colors[i+1]=tokenColors[i];
|
|
}
|
|
for(vint i=0;i<extraTokenColors.Count();i++)
|
|
{
|
|
colors[i+1+tokenColors.Count()]=extraTokenColors[i];
|
|
}
|
|
colorizer=new regex::RegexLexerColorizer(lexer->Colorize());
|
|
}
|
|
}
|
|
|
|
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<IEditStep> step)
|
|
{
|
|
if(!performingUndoRedo)
|
|
{
|
|
if(firstFutureStep<savedStep)
|
|
{
|
|
savedStep=-1;
|
|
}
|
|
|
|
vint count=steps.Count()-firstFutureStep;
|
|
if(count>0)
|
|
{
|
|
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<GuiTextBoxCommonInterface*>(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<GuiTextBoxCommonInterface*>(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<EditStep> 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<GuiDocumentCommonInterface*>(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<GuiDocumentCommonInterface*>(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<GuiDocumentCommonInterface*>(processor->ownerComposition->GetRelatedControl());
|
|
if(ci)
|
|
{
|
|
ci->RenameStyle(arguments.newStyleName, arguments.oldStyleName);
|
|
}
|
|
}
|
|
|
|
void GuiDocumentUndoRedoProcessor::RenameStyleStep::Redo()
|
|
{
|
|
GuiDocumentCommonInterface* ci=dynamic_cast<GuiDocumentCommonInterface*>(processor->ownerComposition->GetRelatedControl());
|
|
if(ci)
|
|
{
|
|
ci->RenameStyle(arguments.oldStyleName, arguments.newStyleName);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiDocumentUndoRedoProcessor::SetAlignmentStep
|
|
***********************************************************************/
|
|
|
|
void GuiDocumentUndoRedoProcessor::SetAlignmentStep::Undo()
|
|
{
|
|
GuiDocumentCommonInterface* ci=dynamic_cast<GuiDocumentCommonInterface*>(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<GuiDocumentCommonInterface*>(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<ReplaceModelStep> step=new ReplaceModelStep;
|
|
step->processor=this;
|
|
step->arguments=arguments;
|
|
PushStep(step);
|
|
}
|
|
|
|
void GuiDocumentUndoRedoProcessor::OnRenameStyle(const RenameStyleStruct& arguments)
|
|
{
|
|
Ptr<RenameStyleStep> step=new RenameStyleStep;
|
|
step->processor=this;
|
|
step->arguments=arguments;
|
|
PushStep(step);
|
|
}
|
|
|
|
void GuiDocumentUndoRedoProcessor::OnSetAlignment(Ptr<SetAlignmentStruct> arguments)
|
|
{
|
|
Ptr<SetAlignmentStep> 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<ParsingGeneralParser> parser=parsingExecutor->GetParser();
|
|
Ptr<ParsingTable> table=parser->GetTable();
|
|
vint stateCount=table->GetStateCount();
|
|
vint tokenCount=table->GetTokenCount();
|
|
for(vint i=0;i<stateCount;i++)
|
|
{
|
|
for(vint j=0;j<tokenCount;j++)
|
|
{
|
|
Ptr<ParsingTable::TransitionBag> bag=table->GetTransitionBag(i, j);
|
|
if(bag)
|
|
{
|
|
FOREACH(Ptr<ParsingTable::TransitionItem>, 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 (editVersion<trace.editVersion)
|
|
{
|
|
end = middle - 1;
|
|
}
|
|
else if (editVersion>trace.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<ParsingTable> 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<ParsingTreeObject*>(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<ParsingTreeObject*>(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<ParsingTreeObject*>(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<TextEditNotifyStruct> 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<parsing::tabling::ParsingState::Future*>& 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<parsing::tabling::ParsingState::Future*>& nonRecoveryFutures,
|
|
collections::List<parsing::tabling::ParsingState::Future*>& recoveryFutures
|
|
)
|
|
{
|
|
const List<ParsingState::TransitionResult>& 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<ParsingState::Future*> 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<ParsingState::Future*> 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<vint>& tableTokenIndices
|
|
)
|
|
{
|
|
// initialize the PDA state
|
|
state.Reset(newContext.rule);
|
|
List<ParsingState::Future*> 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<ParsingState::Future*> 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<Ptr<ParsingError>> 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<ParsingTreeNode> parsedNode = builder.GetNode();
|
|
newContext.modifiedNode = parsedNode.Cast<ParsingTreeObject>();
|
|
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<AutoCompleteData> autoComplete = new AutoCompleteData;
|
|
SortedList<vint> 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 (startPos<endPos && endPos.column>0)
|
|
{
|
|
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.editVersion<context.input.editVersion)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
AutoCompleteContext newContext;
|
|
bool byGlobalCorrection=false;
|
|
|
|
if(input.node)
|
|
{
|
|
newContext.input=input;
|
|
ExecuteRefresh(newContext);
|
|
byGlobalCorrection=true;
|
|
}
|
|
else
|
|
{
|
|
SPIN_LOCK(contextLock)
|
|
{
|
|
newContext=context;
|
|
newContext.modifiedNode=0;
|
|
newContext.autoComplete=0;
|
|
}
|
|
if(newContext.originalNode)
|
|
{
|
|
ExecuteEdit(newContext);
|
|
}
|
|
}
|
|
|
|
if(newContext.originalNode)
|
|
{
|
|
ExecuteCalculateList(newContext);
|
|
}
|
|
|
|
SPIN_LOCK(contextLock)
|
|
{
|
|
context=newContext;
|
|
}
|
|
if(newContext.modifiedNode)
|
|
{
|
|
OnContextFinishedAsync(context);
|
|
GetApplication()->InvokeInMainThread([=]()
|
|
{
|
|
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<AutoCompleteData> 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<WString> itemKeys;
|
|
List<ParsingCandidateItem> 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<GuiTextBoxAutoCompleteBase::AutoCompleteItem> 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<RepeatingParsingExecutor> _parsingExecutor)
|
|
:RepeatingParsingExecutor::CallbackBase(_parsingExecutor)
|
|
,editing(false)
|
|
{
|
|
Initialize();
|
|
}
|
|
|
|
GuiGrammarAutoComplete::GuiGrammarAutoComplete(Ptr<parsing::tabling::ParsingGeneralParser> _grammarParser, const WString& _grammarRule)
|
|
:RepeatingParsingExecutor::CallbackBase(new RepeatingParsingExecutor(_grammarParser, _grammarRule))
|
|
,editing(false)
|
|
{
|
|
Initialize();
|
|
}
|
|
|
|
GuiGrammarAutoComplete::~GuiGrammarAutoComplete()
|
|
{
|
|
EnsureAutoCompleteFinished();
|
|
parsingExecutor->DetachCallback(this);
|
|
}
|
|
|
|
Ptr<RepeatingParsingExecutor> 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<RepeatingParsingExecutor> _parsingExecutor)
|
|
:RepeatingParsingExecutor::CallbackBase(_parsingExecutor)
|
|
{
|
|
parsingExecutor->AttachCallback(this);
|
|
BeginSetColors();
|
|
}
|
|
|
|
GuiGrammarColorizer::GuiGrammarColorizer(Ptr<parsing::tabling::ParsingGeneralParser> _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<WString>& 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<WString> tokenColors;
|
|
Ptr<ParsingTable> table=parsingExecutor->GetParser()->GetTable();
|
|
semanticColorMap.Clear();
|
|
|
|
vint tokenCount=table->GetTokenCount();
|
|
for(vint token=ParsingTable::UserTokenStart;token<tokenCount;token++)
|
|
{
|
|
const ParsingTable::TokenInfo& tokenInfo=table->GetTokenInfo(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<RepeatingParsingExecutor> 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<ParsingTreeToken*>(foundNode);
|
|
if(!foundToken) return false;
|
|
ParsingTreeObject* tokenParent=dynamic_cast<ParsingTreeObject*>(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<parsing::ParsingTreeNode> RepeatingParsingExecutor::IParsingAnalyzer::ToChild(Ptr<parsing::ParsingTreeNode> node, const RepeatingPartialParsingOutput* output)
|
|
{
|
|
if (!output) return node;
|
|
return node == output->originalNode
|
|
? output->modifiedNode.Cast<ParsingTreeNode>()
|
|
: node;
|
|
}
|
|
|
|
parsing::ParsingTreeNode* RepeatingParsingExecutor::IParsingAnalyzer::GetParent(parsing::ParsingTreeNode* node, const RepeatingPartialParsingOutput* output)
|
|
{
|
|
return ToParent(node, output)->GetParent();
|
|
}
|
|
|
|
Ptr<parsing::ParsingTreeNode> RepeatingParsingExecutor::IParsingAnalyzer::GetMember(parsing::ParsingTreeObject* node, const WString& name, const RepeatingPartialParsingOutput* output)
|
|
{
|
|
return ToChild(ToChild(node, output)->GetMember(name), output);
|
|
}
|
|
|
|
Ptr<parsing::ParsingTreeNode> RepeatingParsingExecutor::IParsingAnalyzer::GetItem(parsing::ParsingTreeArray* node, vint index, const RepeatingPartialParsingOutput* output)
|
|
{
|
|
return ToChild(node->GetItem(index), output);
|
|
}
|
|
|
|
/***********************************************************************
|
|
RepeatingParsingExecutor::CallbackBase
|
|
***********************************************************************/
|
|
|
|
RepeatingParsingExecutor::CallbackBase::CallbackBase(Ptr<RepeatingParsingExecutor> _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<Ptr<ParsingError>> errors;
|
|
Ptr<ParsingTreeObject> node=grammarParser->Parse(input.code, grammarRule, errors).Cast<ParsingTreeObject>();
|
|
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<ParsingTable> table=grammarParser->GetTable();
|
|
tokenIndexMap.Clear();
|
|
semanticIndexMap.Clear();
|
|
tokenMetaDatas.Clear();
|
|
fieldMetaDatas.Clear();
|
|
|
|
Dictionary<vint, Ptr<ParsingTable::AttributeInfo>> tokenColorAtts, tokenContextColorAtts, tokenCandidateAtts, tokenAutoCompleteAtts;
|
|
Dictionary<FieldDesc, Ptr<ParsingTable::AttributeInfo>> fieldColorAtts, fieldSemanticAtts;
|
|
|
|
{
|
|
vint tokenCount=table->GetTokenCount();
|
|
for(vint token=ParsingTable::UserTokenStart;token<tokenCount;token++)
|
|
{
|
|
const ParsingTable::TokenInfo& tokenInfo=table->GetTokenInfo(token);
|
|
vint tokenIndex=token-ParsingTable::UserTokenStart;
|
|
tokenIndexMap.Add(tokenInfo.name, tokenIndex);
|
|
|
|
if(Ptr<ParsingTable::AttributeInfo> att=GetColorAttribute(tokenInfo.attributeIndex))
|
|
{
|
|
tokenColorAtts.Add(tokenIndex, att);
|
|
}
|
|
if(Ptr<ParsingTable::AttributeInfo> att=GetContextColorAttribute(tokenInfo.attributeIndex))
|
|
{
|
|
tokenContextColorAtts.Add(tokenIndex, att);
|
|
}
|
|
if(Ptr<ParsingTable::AttributeInfo> att=GetCandidateAttribute(tokenInfo.attributeIndex))
|
|
{
|
|
tokenCandidateAtts.Add(tokenIndex, att);
|
|
}
|
|
if(Ptr<ParsingTable::AttributeInfo> att=GetAutoCompleteAttribute(tokenInfo.attributeIndex))
|
|
{
|
|
tokenAutoCompleteAtts.Add(tokenIndex, att);
|
|
}
|
|
}
|
|
}
|
|
{
|
|
vint fieldCount=table->GetTreeFieldInfoCount();
|
|
for(vint field=0;field<fieldCount;field++)
|
|
{
|
|
const ParsingTable::TreeFieldInfo& fieldInfo=table->GetTreeFieldInfo(field);
|
|
FieldDesc fieldDesc(fieldInfo.type, fieldInfo.field);
|
|
|
|
if(Ptr<ParsingTable::AttributeInfo> att=GetColorAttribute(fieldInfo.attributeIndex))
|
|
{
|
|
fieldColorAtts.Add(fieldDesc, att);
|
|
}
|
|
if(Ptr<ParsingTable::AttributeInfo> att=GetSemanticAttribute(fieldInfo.attributeIndex))
|
|
{
|
|
fieldSemanticAtts.Add(fieldDesc, att);
|
|
}
|
|
}
|
|
}
|
|
|
|
FOREACH(Ptr<ParsingTable::AttributeInfo>, 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;field<fieldCount;field++)
|
|
{
|
|
const ParsingTable::TreeFieldInfo& fieldInfo=table->GetTreeFieldInfo(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<vint>;
|
|
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<parsing::tabling::ParsingGeneralParser> _grammarParser, const WString& _grammarRule, Ptr<IParsingAnalyzer> _analyzer)
|
|
:grammarParser(_grammarParser)
|
|
,grammarRule(_grammarRule)
|
|
,analyzer(_analyzer)
|
|
,autoPushingCallback(0)
|
|
{
|
|
PrepareMetaData();
|
|
if (analyzer)
|
|
{
|
|
analyzer->Attach(this);
|
|
}
|
|
}
|
|
|
|
RepeatingParsingExecutor::~RepeatingParsingExecutor()
|
|
{
|
|
EnsureTaskFinished();
|
|
if (analyzer)
|
|
{
|
|
analyzer->Detach(this);
|
|
}
|
|
}
|
|
|
|
Ptr<parsing::tabling::ParsingGeneralParser> 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::IParsingAnalyzer> 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<semanticIndexMap.Count()?semanticIndexMap[id]:L"";
|
|
}
|
|
|
|
const RepeatingParsingExecutor::TokenMetaData& RepeatingParsingExecutor::GetTokenMetaData(vint regexTokenIndex)
|
|
{
|
|
return tokenMetaDatas[regexTokenIndex];
|
|
}
|
|
|
|
const RepeatingParsingExecutor::FieldMetaData& RepeatingParsingExecutor::GetFieldMetaData(const WString& type, const WString& field)
|
|
{
|
|
return fieldMetaDatas[FieldDesc(type, field)];
|
|
}
|
|
|
|
Ptr<parsing::tabling::ParsingTable::AttributeInfo> RepeatingParsingExecutor::GetAttribute(vint index, const WString& name, vint argumentCount)
|
|
{
|
|
if(index!=-1)
|
|
{
|
|
Ptr<ParsingTable::AttributeInfo> att=grammarParser->GetTable()->GetAttributeInfo(index)->FindFirst(name);
|
|
if(att && (argumentCount==-1 || att->arguments.Count()==argumentCount))
|
|
{
|
|
return att;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Ptr<parsing::tabling::ParsingTable::AttributeInfo> RepeatingParsingExecutor::GetColorAttribute(vint index)
|
|
{
|
|
return GetAttribute(index, L"Color", 1);
|
|
}
|
|
|
|
Ptr<parsing::tabling::ParsingTable::AttributeInfo> RepeatingParsingExecutor::GetContextColorAttribute(vint index)
|
|
{
|
|
return GetAttribute(index, L"ContextColor", 0);
|
|
}
|
|
|
|
Ptr<parsing::tabling::ParsingTable::AttributeInfo> RepeatingParsingExecutor::GetSemanticAttribute(vint index)
|
|
{
|
|
return GetAttribute(index, L"Semantic", -1);
|
|
}
|
|
|
|
Ptr<parsing::tabling::ParsingTable::AttributeInfo> RepeatingParsingExecutor::GetCandidateAttribute(vint index)
|
|
{
|
|
return GetAttribute(index, L"Candidate", 0);
|
|
}
|
|
|
|
Ptr<parsing::tabling::ParsingTable::AttributeInfo> 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<GuiMenu*>(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<IGuiMenuService>();
|
|
}
|
|
}
|
|
|
|
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<IGuiMenuService>();
|
|
if(ownerMenuService)
|
|
{
|
|
SetClickOnMouseUp(!ownerMenuService->IsSubMenuActivatedByMouseDown());
|
|
}
|
|
if(subMenu)
|
|
{
|
|
subMenu->UpdateMenuService();
|
|
}
|
|
}
|
|
|
|
bool GuiMenuButton::IsAltAvailable()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
compositions::IGuiAltActionHost* GuiMenuButton::GetActivatingAltHost()
|
|
{
|
|
if (subMenu)
|
|
{
|
|
return subMenu->QueryTypedService<IGuiAltActionHost>();
|
|
}
|
|
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<GuiImageData> GuiMenuButton::GetImage()
|
|
{
|
|
return image;
|
|
}
|
|
|
|
void GuiMenuButton::SetImage(Ptr<GuiImageData> 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<ShortcutBuilder> builder)
|
|
{
|
|
if(shortcutKeyItem!=value)
|
|
{
|
|
if(shortcutKeyItem)
|
|
{
|
|
shortcutKeyItem->Executed.Detach(shortcutKeyItemExecutedHandler);
|
|
if (shortcutBuilder)
|
|
{
|
|
auto manager = dynamic_cast<GuiShortcutKeyManager*>(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<WString> errors;
|
|
if (auto parser = GetParserManager()->GetParser<ShortcutBuilder>(L"SHORTCUT"))
|
|
if (Ptr<ShortcutBuilder> builder = parser->TypedParse(builderText, errors))
|
|
{
|
|
if (shortcutOwner)
|
|
{
|
|
if (!shortcutOwner->GetShortcutKeyManager())
|
|
{
|
|
shortcutOwner->SetShortcutKeyManager(new GuiShortcutKeyManager);
|
|
}
|
|
if (auto manager = dynamic_cast<GuiShortcutKeyManager*>(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<GuiControlHost*>(rootObject);
|
|
if (shortcutBuilder && !shortcutKeyItem)
|
|
{
|
|
BuildShortcut(shortcutBuilder->text);
|
|
}
|
|
}
|
|
|
|
void GuiToolstripCommand::Detach(GuiInstanceRootObject* rootObject)
|
|
{
|
|
ReplaceShortcut(0, nullptr);
|
|
shortcutOwner = 0;
|
|
}
|
|
|
|
Ptr<GuiImageData> GuiToolstripCommand::GetImage()
|
|
{
|
|
return image;
|
|
}
|
|
|
|
void GuiToolstripCommand::SetImage(Ptr<GuiImageData> 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<GuiToolstripCommand::ShortcutBuilder>
|
|
{
|
|
typedef GuiToolstripCommand::ShortcutBuilder ShortcutBuilder;
|
|
public:
|
|
Regex regexShortcut;
|
|
|
|
GuiToolstripCommandShortcutParser()
|
|
:regexShortcut(L"((<ctrl>Ctrl)/+|(<shift>Shift)/+|(<alt>Alt)/+)*(<key>/.+)")
|
|
{
|
|
}
|
|
|
|
Ptr<ShortcutBuilder> TypedParse(const WString& text, collections::List<WString>& errors)override
|
|
{
|
|
Ptr<RegexMatch> match=regexShortcut.MatchHead(text);
|
|
if (match && match->Result().Length() != text.Length())
|
|
{
|
|
errors.Add(L"Failed to parse a shortcut \"" + text + L"\".");
|
|
return 0;
|
|
}
|
|
|
|
Ptr<ShortcutBuilder> 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<GuiMenuButton*>(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<GuiImageData> 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<GuiImageData> 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<GuiImageData> 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<GuiToolstripMenu*>(GetSubMenu());
|
|
}
|
|
|
|
GuiToolstripMenu* GuiToolstripButton::EnsureToolstripSubMenu()
|
|
{
|
|
if (!GetSubMenu())
|
|
{
|
|
CreateToolstripSubMenu();
|
|
}
|
|
return dynamic_cast<GuiToolstripMenu*>(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<GuiSharedSizeItemComposition*>(current))
|
|
{
|
|
break;
|
|
}
|
|
else if (auto root = dynamic_cast<GuiSharedSizeRootComposition*>(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<WString, vint>& 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<WString, vint> 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;i<children.Count();i++)
|
|
{
|
|
children[i]->OnControlParentChanged(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<GuiGraphicsComposition*>(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;i<children.Count();i++)
|
|
{
|
|
delete children[i];
|
|
}
|
|
}
|
|
|
|
GuiGraphicsComposition* GuiGraphicsComposition::GetParent()
|
|
{
|
|
return parent;
|
|
}
|
|
|
|
const GuiGraphicsComposition::CompositionList& GuiGraphicsComposition::Children()
|
|
{
|
|
return children;
|
|
}
|
|
|
|
bool GuiGraphicsComposition::AddChild(GuiGraphicsComposition* child)
|
|
{
|
|
return InsertChild(children.Count(), child);
|
|
}
|
|
|
|
bool GuiGraphicsComposition::InsertChild(vint index, GuiGraphicsComposition* child)
|
|
{
|
|
if(!child) return false;
|
|
if(child->GetParent()) 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<IGuiGraphicsElement> GuiGraphicsComposition::GetOwnedElement()
|
|
{
|
|
return ownedElement;
|
|
}
|
|
|
|
void GuiGraphicsComposition::SetOwnedElement(Ptr<IGuiGraphicsElement> 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;i<children.Count();i++)
|
|
{
|
|
children[i]->SetRenderTarget(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;i<children.Count();i++)
|
|
{
|
|
children[i]->Render(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;i<children.Count();i++)
|
|
{
|
|
children[i]->OnControlParentChanged(0);
|
|
}
|
|
}
|
|
associatedControl=control;
|
|
if(associatedControl)
|
|
{
|
|
for(vint i=0;i<children.Count();i++)
|
|
{
|
|
children[i]->OnControlParentChanged(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<GuiControlHost*>(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;i<children.Count();i++)
|
|
{
|
|
children[i]->ForceCalculateSizeImmediately();
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiGraphicsSite
|
|
***********************************************************************/
|
|
|
|
Rect GuiGraphicsSite::GetBoundsInternal(Rect expectedBounds)
|
|
{
|
|
Size minSize=GetMinPreferredClientSize();
|
|
if(minSize.x<preferredMinSize.x) minSize.x=preferredMinSize.x;
|
|
if(minSize.y<preferredMinSize.y) minSize.y=preferredMinSize.y;
|
|
|
|
minSize.x+=margin.left+margin.right+internalMargin.left+internalMargin.right;
|
|
minSize.y+=margin.top+margin.bottom+internalMargin.top+internalMargin.bottom;
|
|
vint w=expectedBounds.Width();
|
|
vint h=expectedBounds.Height();
|
|
if(minSize.x<w) minSize.x=w;
|
|
if(minSize.y<h) minSize.y=h;
|
|
return Rect(expectedBounds.LeftTop(), minSize);
|
|
}
|
|
|
|
void GuiGraphicsSite::UpdatePreviousBounds(Rect bounds)
|
|
{
|
|
if(previousBounds!=bounds)
|
|
{
|
|
previousBounds=bounds;
|
|
BoundsChanged.Execute(GuiEventArgs(this));
|
|
}
|
|
}
|
|
|
|
GuiGraphicsSite::GuiGraphicsSite()
|
|
{
|
|
BoundsChanged.SetAssociatedComposition(this);
|
|
}
|
|
|
|
GuiGraphicsSite::~GuiGraphicsSite()
|
|
{
|
|
}
|
|
|
|
bool GuiGraphicsSite::IsSizeAffectParent()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
Size GuiGraphicsSite::GetMinPreferredClientSize()
|
|
{
|
|
Size minSize;
|
|
if(minSizeLimitation!=GuiGraphicsComposition::NoLimit)
|
|
{
|
|
if(ownedElement)
|
|
{
|
|
IGuiGraphicsRenderer* renderer=ownedElement->GetRenderer();
|
|
if(renderer)
|
|
{
|
|
minSize=renderer->GetMinSize();
|
|
}
|
|
}
|
|
}
|
|
if(minSizeLimitation==GuiGraphicsComposition::LimitToElementAndChildren)
|
|
{
|
|
vint childCount=Children().Count();
|
|
for(vint i=0;i<childCount;i++)
|
|
{
|
|
GuiGraphicsComposition* child=children[i];
|
|
if(child->IsSizeAffectParent())
|
|
{
|
|
Rect childBounds=child->GetPreferredBounds();
|
|
if(minSize.x<childBounds.x2) minSize.x=childBounds.x2;
|
|
if(minSize.y<childBounds.y2) minSize.y=childBounds.y2;
|
|
}
|
|
}
|
|
}
|
|
return minSize;
|
|
}
|
|
|
|
Rect GuiGraphicsSite::GetPreferredBounds()
|
|
{
|
|
return GetBoundsInternal(Rect(Point(0, 0), GetMinPreferredClientSize()));
|
|
}
|
|
|
|
/***********************************************************************
|
|
Helper Functions
|
|
***********************************************************************/
|
|
|
|
void SafeDeleteControl(controls::GuiControl* value)
|
|
{
|
|
if(value)
|
|
{
|
|
GuiGraphicsComposition* bounds=value->GetBoundsComposition();
|
|
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<vint> 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<GuiFlowItemComposition*>(child);
|
|
if (item && !flowItems.Contains(item))
|
|
{
|
|
flowItems.Add(item);
|
|
needUpdate = true;
|
|
}
|
|
}
|
|
|
|
void GuiFlowComposition::OnChildRemoved(GuiGraphicsComposition* child)
|
|
{
|
|
GuiBoundsComposition::OnChildRemoved(child);
|
|
auto item=dynamic_cast<GuiFlowItemComposition*>(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<IGuiAxis> GuiFlowComposition::GetAxis()
|
|
{
|
|
return axis;
|
|
}
|
|
|
|
void GuiFlowComposition::SetAxis(Ptr<IGuiAxis> 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<GuiFlowComposition*>(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<GuiStackItemComposition*>(child);
|
|
if (item)
|
|
{
|
|
if (!stackItems.Contains(item))
|
|
{
|
|
stackItems.Add(item);
|
|
}
|
|
UpdateStackItemBounds();
|
|
}
|
|
}
|
|
|
|
void GuiStackComposition::OnChildRemoved(GuiGraphicsComposition* child)
|
|
{
|
|
GuiBoundsComposition::OnChildRemoved(child);
|
|
GuiStackItemComposition* item=dynamic_cast<GuiStackItemComposition*>(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<GuiStackComposition*>(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<vint>& dimSizes,
|
|
vint& dimSize,
|
|
vint& dimSizeWithPercentage,
|
|
collections::Array<GuiCellOption>& 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<maxPass;pass++)
|
|
{
|
|
for(vint i=0;i<this->*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<this->*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<span;k++)
|
|
{
|
|
size-=dimSizes[i-k]+cellPadding;
|
|
}
|
|
if(dimSizes[i]<size)
|
|
{
|
|
dimSizes[i]=size;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool percentageExists=false;
|
|
for(vint i=0;i<this->*dim1;i++)
|
|
{
|
|
GuiCellOption option=dimOptions[i];
|
|
if(option.composeType==GuiCellOption::Percentage)
|
|
{
|
|
if(0.001<option.percentage)
|
|
{
|
|
percentageExists=true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(percentageExists)
|
|
{
|
|
for(vint i=0;i<this->*dim1;i++)
|
|
{
|
|
GuiCellOption option=dimOptions[i];
|
|
if(option.composeType==GuiCellOption::Percentage)
|
|
{
|
|
if(0.001<option.percentage)
|
|
{
|
|
for(vint j=0;j<this->*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<start+span;k++)
|
|
{
|
|
if(dimOptions[k].composeType==GuiCellOption::Percentage)
|
|
{
|
|
if(0.001<dimOptions[k].percentage)
|
|
{
|
|
totalPercentage+=dimOptions[k].percentage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
size-=dimSizes[k];
|
|
}
|
|
}
|
|
|
|
size=(vint)ceil(size*option.percentage/totalPercentage);
|
|
if(dimSizes[i]<size)
|
|
{
|
|
dimSizes[i]=size;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
vint percentageTotalSize=0;
|
|
for(vint i=0;i<this->*dim1;i++)
|
|
{
|
|
GuiCellOption option=dimOptions[i];
|
|
if(option.composeType==GuiCellOption::Percentage)
|
|
{
|
|
if(0.001<option.percentage)
|
|
{
|
|
vint size=(vint)ceil(dimSizes[i]/option.percentage);
|
|
if(percentageTotalSize<size)
|
|
{
|
|
percentageTotalSize=size;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
double totalPercentage=0;
|
|
for(vint i=0;i<this->*dim1;i++)
|
|
{
|
|
GuiCellOption option=dimOptions[i];
|
|
if(option.composeType==GuiCellOption::Percentage)
|
|
{
|
|
if(0.001<option.percentage)
|
|
{
|
|
totalPercentage+=option.percentage;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(vint i=0;i<this->*dim1;i++)
|
|
{
|
|
GuiCellOption option=dimOptions[i];
|
|
if(option.composeType==GuiCellOption::Percentage)
|
|
{
|
|
if(0.001<option.percentage)
|
|
{
|
|
vint size=(vint)ceil(percentageTotalSize*option.percentage/totalPercentage);
|
|
if(dimSizes[i]<size)
|
|
{
|
|
dimSizes[i]=size;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for(vint i=0;i<this->*dim1;i++)
|
|
{
|
|
if(dimOptions[i].composeType!=GuiCellOption::Percentage)
|
|
{
|
|
dimSize+=dimSizes[i];
|
|
}
|
|
dimSizeWithPercentage+=dimSizes[i];
|
|
}
|
|
}
|
|
|
|
void GuiTableComposition::UpdateCellBoundsPercentages(
|
|
collections::Array<vint>& dimSizes,
|
|
vint dimSize,
|
|
vint maxDimSize,
|
|
collections::Array<GuiCellOption>& dimOptions
|
|
)
|
|
{
|
|
if(maxDimSize>dimSize)
|
|
{
|
|
double totalPercentage=0;
|
|
vint percentageCount=0;
|
|
for(vint i=0;i<dimOptions.Count();i++)
|
|
{
|
|
GuiCellOption option=dimOptions[i];
|
|
if(option.composeType==GuiCellOption::Percentage)
|
|
{
|
|
totalPercentage+=option.percentage;
|
|
percentageCount++;
|
|
}
|
|
}
|
|
if(percentageCount>0 && totalPercentage>0.001)
|
|
{
|
|
for(vint i=0;i<dimOptions.Count();i++)
|
|
{
|
|
GuiCellOption option=dimOptions[i];
|
|
if(option.composeType==GuiCellOption::Percentage)
|
|
{
|
|
dimSizes[i]=(vint)((maxDimSize-dimSize)*option.percentage/totalPercentage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
vint GuiTableComposition::UpdateCellBoundsOffsets(
|
|
collections::Array<vint>& offsets,
|
|
collections::Array<vint>& sizes,
|
|
vint max
|
|
)
|
|
{
|
|
offsets[0]=0;
|
|
for(vint i=1;i<offsets.Count();i++)
|
|
{
|
|
offsets[i] = offsets[i - 1] + cellPadding + sizes[i - 1];
|
|
}
|
|
|
|
vint last=offsets.Count()-1;
|
|
vint right=offsets[last]+sizes[last];
|
|
return max-right;
|
|
}
|
|
|
|
void GuiTableComposition::UpdateCellBoundsInternal()
|
|
{
|
|
rowOffsets.Resize(rows);
|
|
rowSizes.Resize(rows);
|
|
columnOffsets.Resize(columns);
|
|
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,
|
|
1
|
|
);
|
|
UpdateCellBoundsInternal(
|
|
columnSizes,
|
|
columnTotal,
|
|
columnTotalWithPercentage,
|
|
columnOptions,
|
|
&GuiTableComposition::columns,
|
|
&GuiTableComposition::rows,
|
|
&X,
|
|
&CL,
|
|
&CS,
|
|
&Second,
|
|
&First,
|
|
1
|
|
);
|
|
|
|
Rect area=GetCellArea();
|
|
UpdateCellBoundsPercentages(rowSizes, rowTotal, area.Height(), rowOptions);
|
|
UpdateCellBoundsPercentages(columnSizes, columnTotal, area.Width(), columnOptions);
|
|
rowExtending=UpdateCellBoundsOffsets(rowOffsets, rowSizes, area.Height());
|
|
columnExtending=UpdateCellBoundsOffsets(columnOffsets, columnSizes, area.Width());
|
|
|
|
for(vint i=0;i<rows;i++)
|
|
{
|
|
for(vint j=0;j<columns;j++)
|
|
{
|
|
vint index=GetSiteIndex(rows, columns, i, j);
|
|
cellBounds[index]=Rect(Point(columnOffsets[j], rowOffsets[i]), Size(columnSizes[j], rowSizes[i]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiTableComposition::UpdateTableContentMinSize()
|
|
{
|
|
Array<vint> 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<childCount;i++)
|
|
{
|
|
GuiCellComposition* cell=dynamic_cast<GuiCellComposition*>(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<GuiCellComposition*> 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;r<rowSpan;r++)
|
|
{
|
|
for(vint c=0;c<columnSpan;c++)
|
|
{
|
|
table->SetSitedCell(row+r, column+c, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiCellComposition::SetSitedCells(GuiTableComposition* table)
|
|
{
|
|
for(vint r=0;r<rowSpan;r++)
|
|
{
|
|
for(vint c=0;c<columnSpan;c++)
|
|
{
|
|
table->SetSitedCell(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<GuiTableComposition*>(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<GuiTableComposition*>(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<vint>& 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<vint>& 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<ResolvedStyle> styles;
|
|
|
|
DocumentModel* model;
|
|
Renderer* renderer;
|
|
Ptr<Renderer::ParagraphCache> cache;
|
|
IGuiGraphicsParagraph* paragraph;
|
|
|
|
SetPropertiesVisitor(DocumentModel* _model, Renderer* _renderer, Ptr<Renderer::ParagraphCache> _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<DocumentRun>, 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(styleStart<selectionEnd && selectionBegin<styleEnd)
|
|
{
|
|
vint s2=styleStart>selectionBegin?styleStart:selectionBegin;
|
|
vint s3=selectionEnd<styleEnd?selectionEnd:styleEnd;
|
|
|
|
if(s2<s3)
|
|
{
|
|
ResolvedStyle selectionStyle=model->GetStyle(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<GuiImageFrameElement> 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(start<selectionEnd && selectionBegin<start+length)
|
|
{
|
|
ResolvedStyle style=styles[styles.Count()-1];
|
|
ResolvedStyle selectionStyle=model->GetStyle(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<Renderer::EmbeddedObject>();
|
|
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(start<selectionEnd && selectionBegin<start+length)
|
|
{
|
|
ResolvedStyle style=styles[styles.Count()-1];
|
|
ResolvedStyle selectionStyle=model->GetStyle(DocumentModel::SelectionStyleName, style);
|
|
ApplyColor(start, length, selectionStyle);
|
|
}
|
|
start+=length;
|
|
}
|
|
|
|
void Visit(DocumentParagraphRun* run)override
|
|
{
|
|
VisitContainer(run);
|
|
}
|
|
|
|
static vint SetProperty(DocumentModel* model, Renderer* renderer, Ptr<Renderer::ParagraphCache> cache, Ptr<DocumentParagraphRun> 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;i<paragraphCaches.Count();i++)
|
|
{
|
|
ParagraphCache* cache=paragraphCaches[i].Obj();
|
|
if(cache)
|
|
{
|
|
cache->graphicsParagraph=0;
|
|
}
|
|
}
|
|
}
|
|
|
|
Ptr<GuiDocumentElement::GuiDocumentElementRenderer::ParagraphCache> GuiDocumentElement::GuiDocumentElementRenderer::EnsureAndGetCache(vint paragraphIndex, bool createParagraph)
|
|
{
|
|
if(paragraphIndex<0 || paragraphIndex>=paragraphCaches.Count()) return 0;
|
|
Ptr<DocumentParagraphRun> paragraph=element->document->paragraphs[paragraphIndex];
|
|
Ptr<ParagraphCache> 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;i<paragraphHeights.Count();i++)
|
|
{
|
|
vint paragraphHeight=paragraphHeights[i];
|
|
vint nextY=y+paragraphHeight+paragraphDistance;
|
|
top=y;
|
|
index=i;
|
|
|
|
if(nextY<=point.y)
|
|
{
|
|
y=nextY;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
GuiDocumentElement::GuiDocumentElementRenderer::GuiDocumentElementRenderer()
|
|
:paragraphDistance(0)
|
|
,lastMaxWidth(-1)
|
|
,cachedTotalHeight(0)
|
|
,layoutProvider(GetGuiGraphicsResourceManager()->GetLayoutProvider())
|
|
,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<paragraphHeights.Count();i++)
|
|
{
|
|
vint paragraphHeight=paragraphHeights[i];
|
|
if(y+paragraphHeight<=y1)
|
|
{
|
|
y+=paragraphHeight+paragraphDistance;
|
|
continue;
|
|
}
|
|
else if(y>=y2)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
Ptr<DocumentParagraphRun> paragraph=element->document->paragraphs[i];
|
|
Ptr<ParagraphCache> 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<DocumentHyperlinkRun> GuiDocumentElement::GuiDocumentElementRenderer::GetHyperlinkFromPoint(Point point)
|
|
{
|
|
vint top=0;
|
|
vint index=-1;
|
|
if(GetParagraphIndexFromPoint(point, top, index))
|
|
{
|
|
Ptr<ParagraphCache> 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<ParagraphCache> 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<paragraphCaches.Count())
|
|
{
|
|
Ptr<ParagraphCache> 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<paragraphCaches.Count();i++)
|
|
{
|
|
if(begin.row<=i && i<=end.row)
|
|
{
|
|
Ptr<ParagraphCache> 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<ParagraphCache> 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<ParagraphCache> 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<ParagraphCache> 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.row<paragraphCaches.Count()-1)
|
|
{
|
|
Rect caretBounds=cache->graphicsParagraph->GetCaretBounds(comparingCaret.column, preferFrontSide);
|
|
Ptr<ParagraphCache> 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<ParagraphCache> 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<paragraphCaches.Count()-1)
|
|
{
|
|
Ptr<ParagraphCache> 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<ParagraphCache> 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<ParagraphCache> 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<caret.row;i++)
|
|
{
|
|
EnsureAndGetCache(i, true);
|
|
y+=paragraphHeights[i]+paragraphDistance;
|
|
}
|
|
|
|
bounds.y1+=y;
|
|
bounds.y2+=y;
|
|
return bounds;
|
|
}
|
|
}
|
|
return Rect();
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiDocumentElement
|
|
***********************************************************************/
|
|
|
|
void GuiDocumentElement::UpdateCaret()
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<DocumentModel> GuiDocumentElement::GetDocument()
|
|
{
|
|
return document;
|
|
}
|
|
|
|
void GuiDocumentElement::SetDocument(Ptr<DocumentModel> 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(caretBegin<caretEnd)
|
|
{
|
|
caretFrontSide=true;
|
|
}
|
|
else if(caretBegin>caretEnd)
|
|
{
|
|
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<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
if(elementRenderer)
|
|
{
|
|
TextPos caret=elementRenderer->CalculateCaret(comparingCaret, position, preferFrontSide);
|
|
return caret.column==-1?comparingCaret:caret;
|
|
}
|
|
else
|
|
{
|
|
return comparingCaret;
|
|
}
|
|
}
|
|
|
|
TextPos GuiDocumentElement::CalculateCaretFromPoint(Point point)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
if(elementRenderer)
|
|
{
|
|
return elementRenderer->CalculateCaretFromPoint(point);
|
|
}
|
|
else
|
|
{
|
|
return TextPos(0, 0);
|
|
}
|
|
}
|
|
|
|
Rect GuiDocumentElement::GetCaretBounds(TextPos caret, bool frontSide)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
if(elementRenderer)
|
|
{
|
|
return elementRenderer->GetCaretBounds(caret, frontSide);
|
|
}
|
|
else
|
|
{
|
|
return Rect();
|
|
}
|
|
}
|
|
|
|
void GuiDocumentElement::NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
if(elementRenderer)
|
|
{
|
|
elementRenderer->NotifyParagraphUpdated(index, oldCount, newCount, updatedText);
|
|
}
|
|
}
|
|
|
|
void GuiDocumentElement::EditRun(TextPos begin, TextPos end, Ptr<DocumentModel> model)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<WString>& text)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<DocumentStyleProperties> style)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<GuiImageData> image)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
if(elementRenderer)
|
|
{
|
|
document->RenameStyle(oldStyleName, newStyleName);
|
|
}
|
|
}
|
|
|
|
void GuiDocumentElement::ClearStyle(TextPos begin, TextPos end)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<DocumentStyleProperties> GuiDocumentElement::SummarizeStyle(TextPos begin, TextPos end)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<Nullable<Alignment>>& alignments)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
if(elementRenderer)
|
|
{
|
|
vint first=begin.row;
|
|
vint last=end.row;
|
|
if(first>last)
|
|
{
|
|
vint temp=first;
|
|
first=last;
|
|
last=temp;
|
|
}
|
|
|
|
if(0<=first && first<document->paragraphs.Count() && 0<=last && last<document->paragraphs.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<DocumentHyperlinkRun> GuiDocumentElement::GetHyperlinkFromPoint(Point point)
|
|
{
|
|
Ptr<GuiDocumentElementRenderer> elementRenderer=renderer.Cast<GuiDocumentElementRenderer>();
|
|
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<INativeImage> GuiImageFrameElement::GetImage()
|
|
{
|
|
return image;
|
|
}
|
|
|
|
vint GuiImageFrameElement::GetFrameIndex()
|
|
{
|
|
return frameIndex;
|
|
}
|
|
|
|
void GuiImageFrameElement::SetImage(Ptr<INativeImage> value)
|
|
{
|
|
SetImage(value, frameIndex);
|
|
}
|
|
|
|
void GuiImageFrameElement::SetFrameIndex(vint value)
|
|
{
|
|
SetImage(image, value);
|
|
}
|
|
|
|
void GuiImageFrameElement::SetImage(Ptr<INativeImage> _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<IGuiGraphicsAnimation> animation)
|
|
{
|
|
playingAnimations.Add(animation);
|
|
}
|
|
|
|
bool GuiGraphicsAnimationManager::HasAnimation()
|
|
{
|
|
return playingAnimations.Count()>0;
|
|
}
|
|
|
|
void GuiGraphicsAnimationManager::Play()
|
|
{
|
|
for(vint i=playingAnimations.Count()-1;i>=0;i--)
|
|
{
|
|
Ptr<IGuiGraphicsAnimation> 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<WString, IGuiAltAction*>& actions)
|
|
{
|
|
List<GuiControl*> controls;
|
|
controls.Add(control);
|
|
vint current = 0;
|
|
|
|
while (current < controls.Count())
|
|
{
|
|
GuiControl* control = controls[current++];
|
|
|
|
if (auto container = control->QueryTypedService<IGuiAltActionContainer>())
|
|
{
|
|
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<IGuiAltAction>())
|
|
{
|
|
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<WString, IGuiAltAction*> 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<WString, IGuiAltAction*> 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<WString, IGuiAltAction*>& 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<GuiWindow*>(currentAltHost->GetAltComposition()->GetRelatedControlHost());
|
|
auto windowStyle = dynamic_cast<GuiWindow::IStyleController*>(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;i<composition->Children().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<GuiGraphicsComposition*> 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;i<compositions.Count();i++)
|
|
{
|
|
(compositions[i]->GetEventReceiver()->*eventReceiverEvent).Execute(arguments);
|
|
if(arguments.handled)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiGraphicsHost::OnKeyInput(const NativeWindowKeyInfo& info, GuiGraphicsComposition* composition, GuiKeyEvent GuiGraphicsEventReceiver::* eventReceiverEvent)
|
|
{
|
|
List<GuiGraphicsComposition*> 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;i<compositions.Count();i++)
|
|
{
|
|
(compositions[i]->GetEventReceiver()->*eventReceiverEvent).Execute(arguments);
|
|
if(arguments.handled)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiGraphicsHost::RaiseMouseEvent(GuiMouseEventArgs& arguments, GuiGraphicsComposition* composition, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent)
|
|
{
|
|
arguments.compositionSource=composition;
|
|
arguments.eventSource=0;
|
|
vint x=arguments.x;
|
|
vint y=arguments.y;
|
|
|
|
while(composition)
|
|
{
|
|
if(composition->HasEventReceiver())
|
|
{
|
|
if(!arguments.eventSource)
|
|
{
|
|
arguments.eventSource=composition;
|
|
}
|
|
GuiGraphicsEventReceiver* eventReceiver=composition->GetEventReceiver();
|
|
(eventReceiver->*eventReceiverEvent).Execute(arguments);
|
|
if(arguments.handled)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
GuiGraphicsComposition* parent=composition->GetParent();
|
|
if(parent)
|
|
{
|
|
Rect parentBounds=parent->GetBounds();
|
|
Rect clientArea=parent->GetClientArea();
|
|
Rect childBounds=composition->GetBounds();
|
|
|
|
x+=childBounds.x1+(clientArea.x1-parentBounds.x1);
|
|
y+=childBounds.y1+(clientArea.y1-parentBounds.y1);
|
|
arguments.x=x;
|
|
arguments.y=y;
|
|
}
|
|
composition=parent;
|
|
}
|
|
}
|
|
|
|
void GuiGraphicsHost::OnMouseInput(const NativeWindowMouseInfo& info, GuiMouseEvent GuiGraphicsEventReceiver::* eventReceiverEvent)
|
|
{
|
|
GuiGraphicsComposition* composition=0;
|
|
if(mouseCaptureComposition)
|
|
{
|
|
composition=mouseCaptureComposition;
|
|
}
|
|
else
|
|
{
|
|
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()<minWindowSize.x)
|
|
{
|
|
if(fixSizeOnly)
|
|
{
|
|
if(bounds.Width()<minWindowSize.x)
|
|
{
|
|
bounds.x2=bounds.x1+minWindowSize.x;
|
|
}
|
|
}
|
|
else if(oldBounds.x1!=bounds.x1)
|
|
{
|
|
bounds.x1=oldBounds.x2-minWindowSize.x;
|
|
}
|
|
else if(oldBounds.x2!=bounds.x2)
|
|
{
|
|
bounds.x2=oldBounds.x1+minWindowSize.x;
|
|
}
|
|
}
|
|
if(bounds.Height()<minWindowSize.y)
|
|
{
|
|
if(fixSizeOnly)
|
|
{
|
|
if(bounds.Height()<minWindowSize.y)
|
|
{
|
|
bounds.y2=bounds.y1+minWindowSize.y;
|
|
}
|
|
}
|
|
else if(oldBounds.y1!=bounds.y1)
|
|
{
|
|
bounds.y1=oldBounds.y2-minWindowSize.y;
|
|
}
|
|
else if(oldBounds.y2!=bounds.y2)
|
|
{
|
|
bounds.y2=oldBounds.y1+minWindowSize.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiGraphicsHost::Moved()
|
|
{
|
|
Size size=nativeWindow->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<mouseEnterCompositions.Count();i++)
|
|
{
|
|
if(i==newCompositions.Count())
|
|
{
|
|
firstDifferentIndex=newCompositions.Count();
|
|
break;
|
|
}
|
|
if(mouseEnterCompositions[i]!=newCompositions[i])
|
|
{
|
|
firstDifferentIndex=i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for(vint i=mouseEnterCompositions.Count()-1;i>=firstDifferentIndex;i--)
|
|
{
|
|
GuiGraphicsComposition* composition=mouseEnterCompositions[i];
|
|
if(composition->HasEventReceiver())
|
|
{
|
|
composition->GetEventReceiver()->mouseLeave.Execute(GuiEventArgs(composition));
|
|
}
|
|
}
|
|
|
|
CopyFrom(mouseEnterCompositions, newCompositions);
|
|
for(vint i=firstDifferentIndex;i<mouseEnterCompositions.Count();i++)
|
|
{
|
|
GuiGraphicsComposition* composition=mouseEnterCompositions[i];
|
|
if(composition->HasEventReceiver())
|
|
{
|
|
composition->GetEventReceiver()->mouseEnter.Execute(GuiEventArgs(composition));
|
|
}
|
|
}
|
|
|
|
INativeCursor* cursor=0;
|
|
if(newCompositions.Count()>0)
|
|
{
|
|
cursor=newCompositions[newCompositions.Count()-1]->GetRelatedCursor();
|
|
}
|
|
if(cursor)
|
|
{
|
|
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<GuiWindow*>(windowComposition->Children()[0]->GetRelatedControlHost()))
|
|
{
|
|
if (auto altHost = window->QueryTypedService<IGuiAltActionHost>())
|
|
{
|
|
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<GuiShortcutKeyItem>, 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<GuiShortcutKeyItem>, item, shortcutKeyItems)
|
|
{
|
|
if(item->CanActivate(ctrl, shift, alt, key))
|
|
{
|
|
return item.Obj();
|
|
}
|
|
}
|
|
Ptr<GuiShortcutKeyItem> 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<GuiShortcutKeyItem>, 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<GuiShortcutKeyItem>, 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(bufferLength<dataLength)
|
|
{
|
|
bufferLength+=BlockSize;
|
|
}
|
|
return bufferLength;
|
|
}
|
|
|
|
void TextLine::Initialize()
|
|
{
|
|
Finalize();
|
|
text=new wchar_t[BlockSize];
|
|
att=new CharAtt[BlockSize];
|
|
bufferLength=BlockSize;
|
|
|
|
memset(text, 0, sizeof(wchar_t)*bufferLength);
|
|
memset(att, 0, sizeof(CharAtt)*bufferLength);
|
|
}
|
|
|
|
void TextLine::Finalize()
|
|
{
|
|
if(text)
|
|
{
|
|
delete[] text;
|
|
text=0;
|
|
}
|
|
if(att)
|
|
{
|
|
delete[] att;
|
|
att=0;
|
|
}
|
|
availableOffsetCount=0;
|
|
bufferLength=0;
|
|
dataLength=0;
|
|
}
|
|
|
|
bool TextLine::IsReady()
|
|
{
|
|
return text && att;
|
|
}
|
|
|
|
bool TextLine::Modify(vint start, vint count, const wchar_t* input, vint inputCount)
|
|
{
|
|
if(!text || !att || start<0 || count<0 || start+count>dataLength || 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<end.row;i++)
|
|
{
|
|
count+=lines[i].dataLength;
|
|
}
|
|
count+=lines[start.row].dataLength-start.column;
|
|
count+=end.column;
|
|
|
|
Array<wchar_t> 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() && 0<=pos.column && pos.column<=lines[pos.row].dataLength;
|
|
}
|
|
|
|
TextPos TextLines::Normalize(TextPos pos)
|
|
{
|
|
if(pos.row<0)
|
|
{
|
|
return TextPos(0, 0);
|
|
}
|
|
else if(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(oldMiddleLines<newMiddleLines)
|
|
{
|
|
for(vint i=oldMiddleLines;i<newMiddleLines;i++)
|
|
{
|
|
TextLine line;
|
|
line.Initialize();
|
|
lines.Insert(end.row, line);
|
|
}
|
|
}
|
|
else if(oldMiddleLines>newMiddleLines)
|
|
{
|
|
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<rows-1;i++)
|
|
{
|
|
lines[start.row+i].Modify(0, lines[start.row+i].dataLength, inputs[i], inputCounts[i]);
|
|
}
|
|
return TextPos(end.row, inputCounts[rows-1]);
|
|
}
|
|
|
|
TextPos TextLines::Modify(TextPos start, TextPos end, const wchar_t* input, vint inputCount)
|
|
{
|
|
List<const wchar_t*> inputs;
|
|
List<vint> 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;i<lines.Count();i++)
|
|
{
|
|
lines[i].availableOffsetCount=0;
|
|
}
|
|
if(charMeasurer)
|
|
{
|
|
tabWidth=tabSpaceCount*charMeasurer->MeasureWidth(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;i<line.dataLength;i++)
|
|
{
|
|
CharAtt& att=line.att[i];
|
|
wchar_t c=line.text[i];
|
|
vint width=0;
|
|
if(passwordChar)
|
|
{
|
|
width=charMeasurer->MeasureWidth(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;i<lines.Count();i++)
|
|
{
|
|
vint rowWidth=GetRowWidth(i);
|
|
if(width<rowWidth)
|
|
{
|
|
width=rowWidth;
|
|
}
|
|
}
|
|
return width;
|
|
}
|
|
|
|
vint TextLines::GetMaxHeight()
|
|
{
|
|
return lines.Count()*charMeasurer->GetRowHeight();
|
|
}
|
|
|
|
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.x<p)
|
|
{
|
|
i2=i;
|
|
p2=p;
|
|
}
|
|
else
|
|
{
|
|
i1=i;
|
|
p1=p;
|
|
}
|
|
}
|
|
return TextPos(row, i1);
|
|
}
|
|
|
|
Point TextLines::GetPointFromTextPos(TextPos pos)
|
|
{
|
|
if(IsAvailable(pos))
|
|
{
|
|
vint y=pos.row*charMeasurer->GetRowHeight();
|
|
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<DocumentRun>, 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<DocumentStyleProperties> 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<DocumentStyle> style=new DocumentStyle;
|
|
style->styles=sp;
|
|
styles.Add(L"#Default", style);
|
|
}
|
|
{
|
|
Ptr<DocumentStyleProperties> sp=new DocumentStyleProperties;
|
|
sp->color=Color(255, 255, 255);
|
|
sp->backgroundColor=Color(51, 153, 255);
|
|
|
|
Ptr<DocumentStyle> style=new DocumentStyle;
|
|
style->styles=sp;
|
|
styles.Add(L"#Selection", style);
|
|
}
|
|
{
|
|
Ptr<DocumentStyleProperties> sp=new DocumentStyleProperties;
|
|
|
|
Ptr<DocumentStyle> style=new DocumentStyle;
|
|
style->styles=sp;
|
|
styles.Add(L"#Context", style);
|
|
}
|
|
{
|
|
Ptr<DocumentStyleProperties> sp=new DocumentStyleProperties;
|
|
sp->color=Color(0, 0, 255);
|
|
sp->underline=true;
|
|
|
|
Ptr<DocumentStyle> style=new DocumentStyle;
|
|
style->parentStyleName=L"#Context";
|
|
style->styles=sp;
|
|
styles.Add(L"#NormalLink", style);
|
|
}
|
|
{
|
|
Ptr<DocumentStyleProperties> sp=new DocumentStyleProperties;
|
|
sp->color=Color(0, 0, 255);
|
|
sp->underline=true;
|
|
|
|
Ptr<DocumentStyle> style=new DocumentStyle;
|
|
style->parentStyleName=L"#Context";
|
|
style->styles=sp;
|
|
styles.Add(L"#ActiveLink", style);
|
|
}
|
|
}
|
|
|
|
void DocumentModel::MergeStyle(Ptr<DocumentStyleProperties> style, Ptr<DocumentStyleProperties> 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<DocumentStyleProperties> style, const WString& styleName)
|
|
{
|
|
auto indexDst = styles.Keys().IndexOf(styleName);
|
|
Ptr<DocumentStyleProperties> 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<DocumentStyle>, style, styles.Values())
|
|
{
|
|
style->resolvedStyles = nullptr;
|
|
}
|
|
}
|
|
|
|
void DocumentModel::MergeBaselineStyle(Ptr<DocumentModel> 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<DocumentModel> baselineDocument)
|
|
{
|
|
MergeBaselineStyle(baselineDocument, DefaultStyleName);
|
|
MergeBaselineStyle(baselineDocument, SelectionStyleName);
|
|
MergeBaselineStyle(baselineDocument, ContextStyleName);
|
|
MergeBaselineStyle(baselineDocument, NormalLinkStyleName);
|
|
MergeBaselineStyle(baselineDocument, ActiveLinkStyleName);
|
|
}
|
|
|
|
void DocumentModel::MergeDefaultFont(const FontProperties& defaultFont)
|
|
{
|
|
Ptr<DocumentStyleProperties> 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<DocumentStyleProperties> 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<DocumentStyle> selectedStyle;
|
|
{
|
|
vint index=styles.Keys().IndexOf(styleName);
|
|
if(index!=-1)
|
|
{
|
|
selectedStyle=styles.Values()[index];
|
|
}
|
|
else
|
|
{
|
|
selectedStyle=styles[L"#Default"];
|
|
}
|
|
}
|
|
|
|
if(!selectedStyle->resolvedStyles)
|
|
{
|
|
Ptr<DocumentStyleProperties> sp = new DocumentStyleProperties;
|
|
selectedStyle->resolvedStyles = sp;
|
|
|
|
Ptr<DocumentStyle> 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<DocumentStyleProperties> 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<paragraphs.Count();i++)
|
|
{
|
|
Ptr<DocumentParagraphRun> paragraph=paragraphs[i];
|
|
paragraph->GetText(writer, skipNonTextContent);
|
|
if(i<paragraphs.Count()-1)
|
|
{
|
|
writer.WriteString(L"\r\n\r\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
RESOURCES\GUIDOCUMENT_EDIT.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
|
|
typedef DocumentModel::RunRange RunRange;
|
|
typedef DocumentModel::RunRangeMap RunRangeMap;
|
|
|
|
/***********************************************************************
|
|
document_operation_visitors::GetRunRangeVisitor
|
|
***********************************************************************/
|
|
|
|
namespace document_operation_visitors
|
|
{
|
|
class GetRunRangeVisitor : public Object, public DocumentRun::IVisitor
|
|
{
|
|
public:
|
|
RunRangeMap& runRanges;
|
|
vint start;
|
|
|
|
GetRunRangeVisitor(RunRangeMap& _runRanges)
|
|
:runRanges(_runRanges)
|
|
,start(0)
|
|
{
|
|
}
|
|
|
|
void VisitContainer(DocumentContainerRun* run)
|
|
{
|
|
RunRange range;
|
|
range.start=start;
|
|
FOREACH(Ptr<DocumentRun>, 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<DocumentContainerRun*>& locatedRuns;
|
|
RunRangeMap& runRanges;
|
|
vint position;
|
|
bool frontSide;
|
|
|
|
LocateStyleVisitor(List<DocumentContainerRun*>& _locatedRuns, RunRangeMap& _runRanges, vint _position, bool _frontSide)
|
|
:locatedRuns(_locatedRuns)
|
|
,runRanges(_runRanges)
|
|
,position(_position)
|
|
,frontSide(_frontSide)
|
|
{
|
|
}
|
|
|
|
void VisitContainer(DocumentContainerRun* run)
|
|
{
|
|
locatedRuns.Add(run);
|
|
Ptr<DocumentRun> selectedRun;
|
|
FOREACH(Ptr<DocumentRun>, 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.start<position && position<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
|
|
{
|
|
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<DocumentContainerRun*>& 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<DocumentHyperlinkRun> 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<DocumentRun> selectedRun;
|
|
FOREACH(Ptr<DocumentRun>, 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<DocumentHyperlinkRun> 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<DocumentRun> clonedRun;
|
|
|
|
CloneRunVisitor(Ptr<DocumentRun> subRun)
|
|
:clonedRun(subRun)
|
|
{
|
|
}
|
|
|
|
void VisitContainer(Ptr<DocumentContainerRun> cloned)
|
|
{
|
|
if(clonedRun)
|
|
{
|
|
cloned->runs.Add(clonedRun);
|
|
}
|
|
clonedRun=cloned;
|
|
}
|
|
|
|
void Visit(DocumentTextRun* run)override
|
|
{
|
|
Ptr<DocumentTextRun> cloned=new DocumentTextRun;
|
|
cloned->text=run->text;
|
|
clonedRun=cloned;
|
|
}
|
|
|
|
void Visit(DocumentStylePropertiesRun* run)override
|
|
{
|
|
Ptr<DocumentStylePropertiesRun> cloned=new DocumentStylePropertiesRun;
|
|
cloned->style=CopyStyle(run->style);
|
|
VisitContainer(cloned);
|
|
}
|
|
|
|
void Visit(DocumentStyleApplicationRun* run)override
|
|
{
|
|
Ptr<DocumentStyleApplicationRun> cloned=new DocumentStyleApplicationRun;
|
|
cloned->styleName=run->styleName;
|
|
|
|
VisitContainer(cloned);
|
|
}
|
|
|
|
void Visit(DocumentHyperlinkRun* run)override
|
|
{
|
|
Ptr<DocumentHyperlinkRun> 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<DocumentImageRun> 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<DocumentEmbeddedObjectRun> cloned=new DocumentEmbeddedObjectRun;
|
|
cloned->name=run->name;
|
|
clonedRun=cloned;
|
|
}
|
|
|
|
void Visit(DocumentParagraphRun* run)override
|
|
{
|
|
Ptr<DocumentParagraphRun> cloned=new DocumentParagraphRun;
|
|
cloned->alignment=run->alignment;
|
|
|
|
VisitContainer(cloned);
|
|
}
|
|
|
|
static Ptr<DocumentStyleProperties> CopyStyle(Ptr<DocumentStyleProperties> style)
|
|
{
|
|
Ptr<DocumentStyleProperties> 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<DocumentRun> CopyRun(DocumentRun* run)
|
|
{
|
|
CloneRunVisitor visitor(0);
|
|
run->Accept(&visitor);
|
|
return visitor.clonedRun;
|
|
}
|
|
|
|
static Ptr<DocumentRun> CopyStyledText(List<DocumentContainerRun*>& styleRuns, const WString& text)
|
|
{
|
|
Ptr<DocumentTextRun> 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<DocumentRun> 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<DocumentContainerRun> containerRun=CloneRunVisitor::CopyRun(run).Cast<DocumentContainerRun>();
|
|
FOREACH(Ptr<DocumentRun>, 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<end && start<range.end)
|
|
{
|
|
if(start<=range.start && range.end<=end)
|
|
{
|
|
if(deepCopy)
|
|
{
|
|
clonedRun=CloneRunVisitor::CopyRun(run);
|
|
}
|
|
else
|
|
{
|
|
clonedRun=run;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Ptr<DocumentTextRun> textRun=new DocumentTextRun;
|
|
vint copyStart=start>range.start?start:range.start;
|
|
vint copyEnd=end<range.end?end:range.end;
|
|
if(copyStart<copyEnd)
|
|
{
|
|
textRun->text=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<end && start<range.end)
|
|
{
|
|
if(deepCopy)
|
|
{
|
|
clonedRun=CloneRunVisitor::CopyRun(run);
|
|
}
|
|
else
|
|
{
|
|
clonedRun=run;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Visit(DocumentEmbeddedObjectRun* run)override
|
|
{
|
|
clonedRun=0;
|
|
RunRange range=runRanges[run];
|
|
if(range.start<end && start<range.end)
|
|
{
|
|
if(deepCopy)
|
|
{
|
|
clonedRun=CloneRunVisitor::CopyRun(run);
|
|
}
|
|
else
|
|
{
|
|
clonedRun=run;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Visit(DocumentParagraphRun* run)override
|
|
{
|
|
VisitContainer(run);
|
|
}
|
|
|
|
static Ptr<DocumentRun> 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<WString>& styleNames;
|
|
|
|
CollectStyleNameVisitor(List<WString>& _styleNames)
|
|
:styleNames(_styleNames)
|
|
{
|
|
}
|
|
|
|
void VisitContainer(DocumentContainerRun* run)
|
|
{
|
|
FOREACH(Ptr<DocumentRun>, 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<WString>& 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<DocumentRun>, 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<Ptr<DocumentRun>> 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<DocumentRun> 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;j<replacedRuns.Count();j++)
|
|
{
|
|
run->runs.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(end<range.end)
|
|
{
|
|
run->text=run->text.Sub(end-range.start, range.end-end);
|
|
replacedRuns.Add(run);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(end<range.end)
|
|
{
|
|
DocumentTextRun* firstRun=new DocumentTextRun;
|
|
DocumentTextRun* secondRun=new DocumentTextRun;
|
|
|
|
firstRun->text=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<DocumentRun> leftRun;
|
|
Ptr<DocumentRun> rightRun;
|
|
|
|
CutRunVisitor(RunRangeMap& _runRanges, vint _position)
|
|
:runRanges(_runRanges)
|
|
,position(_position)
|
|
{
|
|
}
|
|
|
|
void VisitContainer(DocumentContainerRun* run)
|
|
{
|
|
vint leftCount=0;
|
|
Ptr<DocumentRun> selectedRun;
|
|
|
|
FOREACH(Ptr<DocumentRun>, subRun, run->runs)
|
|
{
|
|
RunRange range=runRanges[subRun.Obj()];
|
|
if(range.start<position)
|
|
{
|
|
leftCount++;
|
|
if (position<range.end)
|
|
{
|
|
selectedRun=subRun;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(selectedRun)
|
|
{
|
|
selectedRun->Accept(this);
|
|
if(leftRun && rightRun)
|
|
{
|
|
run->runs.RemoveAt(leftCount-1);
|
|
run->runs.Insert(leftCount-1, leftRun);
|
|
run->runs.Insert(leftCount, rightRun);
|
|
}
|
|
}
|
|
|
|
Ptr<DocumentContainerRun> leftContainer=CloneRunVisitor::CopyRun(run).Cast<DocumentContainerRun>();
|
|
Ptr<DocumentContainerRun> rightContainer=CloneRunVisitor::CopyRun(run).Cast<DocumentContainerRun>();
|
|
for(vint i=0;i<run->runs.Count();i++)
|
|
{
|
|
(i<leftCount?leftContainer:rightContainer)->runs.Add(run->runs[i]);
|
|
}
|
|
leftRun=leftContainer;
|
|
rightRun=rightContainer;
|
|
}
|
|
|
|
void Visit(DocumentTextRun* run)override
|
|
{
|
|
RunRange range=runRanges[run];
|
|
|
|
Ptr<DocumentTextRun> leftText=new DocumentTextRun;
|
|
leftText->text=run->text.Sub(0, position-range.start);
|
|
|
|
Ptr<DocumentTextRun> 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<DocumentRun>& leftRun, Ptr<DocumentRun>& 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<DocumentContainerRun> 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<DocumentRun> subRun=run->runs[i];
|
|
RunRange range=runRanges[subRun.Obj()];
|
|
if(range.start<end && start<range.end)
|
|
{
|
|
insertStyle=false;
|
|
subRun->Accept(this);
|
|
if(insertStyle)
|
|
{
|
|
Ptr<DocumentContainerRun> 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<DocumentStyleProperties> style;
|
|
|
|
Ptr<DocumentContainerRun> CreateContainer()override
|
|
{
|
|
Ptr<DocumentStylePropertiesRun> containerRun=new DocumentStylePropertiesRun;
|
|
containerRun->style=CloneRunVisitor::CopyStyle(style);
|
|
return containerRun;
|
|
}
|
|
|
|
AddStyleVisitor(RunRangeMap& _runRanges, vint _start, vint _end, Ptr<DocumentStyleProperties> _style)
|
|
:AddContainerVisitor(_runRanges, _start, _end)
|
|
,style(_style)
|
|
{
|
|
}
|
|
|
|
static void AddStyle(DocumentParagraphRun* run, RunRangeMap& runRanges, vint start, vint end, Ptr<DocumentStyleProperties> style)
|
|
{
|
|
AddStyleVisitor visitor(runRanges, start, end, style);
|
|
run->Accept(&visitor);
|
|
}
|
|
};
|
|
|
|
class AddHyperlinkVisitor : public AddContainerVisitor
|
|
{
|
|
public:
|
|
WString reference;
|
|
WString normalStyleName;
|
|
WString activeStyleName;
|
|
|
|
Ptr<DocumentContainerRun> CreateContainer()override
|
|
{
|
|
Ptr<DocumentHyperlinkRun> 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<DocumentContainerRun> CreateContainer()override
|
|
{
|
|
Ptr<DocumentStyleApplicationRun> 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<Ptr<DocumentRun>> 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<DocumentRun> subRun=run->runs[i];
|
|
RunRange range=runRanges[subRun.Obj()];
|
|
if(range.start<end && start<range.end)
|
|
{
|
|
replacedRuns.Clear();
|
|
subRun->Accept(this);
|
|
if(replacedRuns.Count()!=1 || replacedRuns[0]!=subRun)
|
|
{
|
|
run->runs.RemoveAt(i);
|
|
for(vint j=0;j<replacedRuns.Count();j++)
|
|
{
|
|
run->runs.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<DocumentStyleProperties> style;
|
|
List<DocumentModel::ResolvedStyle> 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<typename T>
|
|
void SetStyleItem(Nullable<T> 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<T>();
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
void SetStyleItem(Nullable<T> 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<T>();
|
|
}
|
|
}
|
|
|
|
void SetStyleItem(Nullable<DocumentFontSize> 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<DocumentFontSize>();
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
|
|
template<typename T>
|
|
void OverrideStyleItem(Nullable<T> DocumentStyleProperties::* dstField, T FontProperties::* srcField)
|
|
{
|
|
const DocumentModel::ResolvedStyle& src = GetCurrentResolvedStyle();
|
|
style.Obj()->*dstField = src.style.*srcField;
|
|
}
|
|
|
|
template<typename T>
|
|
void OverrideStyleItem(Nullable<T> DocumentStyleProperties::* dstField, T DocumentModel::ResolvedStyle::* srcField)
|
|
{
|
|
const DocumentModel::ResolvedStyle& src = GetCurrentResolvedStyle();
|
|
style.Obj()->*dstField = src.*srcField;
|
|
}
|
|
|
|
void OverrideStyleItem(Nullable<DocumentFontSize> 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<DocumentRun> subRun=run->runs[i];
|
|
RunRange range=runRanges[subRun.Obj()];
|
|
if(range.start<end && start<range.end)
|
|
{
|
|
subRun->Accept(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<DocumentStyleProperties> SummerizeStyle(DocumentParagraphRun* run, RunRangeMap& runRanges, DocumentModel* model, vint start, vint end)
|
|
{
|
|
SummerizeStyleVisitor visitor(runRanges, model, start, end);
|
|
run->Accept(&visitor);
|
|
return visitor.style;
|
|
}
|
|
|
|
template<typename T>
|
|
static void AggregateStyleItem(Ptr<DocumentStyleProperties>& dst, Ptr<DocumentStyleProperties> src, Nullable<T> DocumentStyleProperties::* field)
|
|
{
|
|
if(dst.Obj()->*field && (!(src.Obj()->*field) || (dst.Obj()->*field).Value()!=(src.Obj()->*field).Value()))
|
|
{
|
|
dst.Obj()->*field=Nullable<T>();
|
|
}
|
|
}
|
|
|
|
static void AggregateStyle(Ptr<DocumentStyleProperties>& dst, Ptr<DocumentStyleProperties> 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> 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<end.row;i++)
|
|
{
|
|
GetRunRangeVisitor::GetRunRange(paragraphs[i].Obj(), runRanges);
|
|
}
|
|
|
|
Ptr<DocumentModel> 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<DocumentParagraphRun>());
|
|
}
|
|
else
|
|
{
|
|
for(vint i=begin.row;i<=end.row;i++)
|
|
{
|
|
Ptr<DocumentParagraphRun> 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<DocumentParagraphRun>());
|
|
}
|
|
else if(i==end.row)
|
|
{
|
|
newDocument->paragraphs.Add(CloneRunRecursivelyVisitor::CopyRun(paragraph.Obj(), runRanges, range.start, end.column, deepCopy).Cast<DocumentParagraphRun>());
|
|
}
|
|
else if(deepCopy)
|
|
{
|
|
newDocument->paragraphs.Add(CloneRunRecursivelyVisitor::CopyRun(paragraph.Obj(), runRanges, range.start, range.end, deepCopy).Cast<DocumentParagraphRun>());
|
|
}
|
|
else
|
|
{
|
|
newDocument->paragraphs.Add(paragraph);
|
|
}
|
|
}
|
|
}
|
|
|
|
// copy styles
|
|
List<WString> styleNames;
|
|
FOREACH(Ptr<DocumentParagraphRun>, paragraph, newDocument->paragraphs)
|
|
{
|
|
CollectStyleNameVisitor::CollectStyleName(paragraph.Obj(), styleNames);
|
|
}
|
|
|
|
for(vint i=0;i<styleNames.Count();i++)
|
|
{
|
|
WString styleName=styleNames[i];
|
|
if(!newDocument->styles.Keys().Contains(styleName))
|
|
{
|
|
Ptr<DocumentStyle> style=styles[styleName];
|
|
if(deepCopy)
|
|
{
|
|
Ptr<DocumentStyle> 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<DocumentParagraphRun> paragraph=paragraphs[position.row];
|
|
RunRangeMap runRanges;
|
|
Ptr<DocumentRun> leftRun, rightRun;
|
|
|
|
GetRunRangeVisitor::GetRunRange(paragraph.Obj(), runRanges);
|
|
CutRunVisitor::CutRun(paragraph.Obj(), runRanges, position.column, leftRun, rightRun);
|
|
|
|
CopyFrom(paragraph->runs, leftRun.Cast<DocumentParagraphRun>()->runs);
|
|
CopyFrom(paragraph->runs, rightRun.Cast<DocumentParagraphRun>()->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<void(DocumentParagraphRun*, RunRangeMap&, vint, vint)>& 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<DocumentParagraphRun> paragraph=paragraphs[i];
|
|
if(begin.row<i && i<end.row)
|
|
{
|
|
GetRunRangeVisitor::GetRunRange(paragraph.Obj(), runRanges);
|
|
}
|
|
RunRange range=runRanges[paragraph.Obj()];
|
|
if(i==begin.row)
|
|
{
|
|
editor(paragraph.Obj(), runRanges, begin.column, range.end);
|
|
}
|
|
else if(i==end.row)
|
|
{
|
|
editor(paragraph.Obj(), runRanges, range.start, end.column);
|
|
}
|
|
else
|
|
{
|
|
editor(paragraph.Obj(), runRanges, range.start, range.end);
|
|
}
|
|
}
|
|
}
|
|
|
|
// clear paragraphs
|
|
for(vint i=begin.row;i<=end.row;i++)
|
|
{
|
|
ClearRunVisitor::ClearRun(paragraphs[i].Obj());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
DocumentModel::EditRun
|
|
***********************************************************************/
|
|
|
|
vint DocumentModel::EditRun(TextPos begin, TextPos end, Ptr<DocumentModel> 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<WString> oldNames, newNames;
|
|
CopyFrom(oldNames, model->styles.Keys());
|
|
CopyFrom(newNames, model->styles.Keys());
|
|
for(vint i=0;i<newNames.Count();i++)
|
|
{
|
|
WString name=newNames[i];
|
|
if((name.Length()==0 || name[0]!=L'#') && styles.Keys().Contains(name))
|
|
{
|
|
vint index=2;
|
|
while(true)
|
|
{
|
|
WString newName=name+L"_"+itow(index++);
|
|
if(!styles.Keys().Contains(newName) && !model->styles.Keys().Contains(newName))
|
|
{
|
|
newNames[i]=newName;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// rename model's styles
|
|
typedef Pair<WString, WString> 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<Ptr<DocumentParagraphRun>> runs;
|
|
CopyFrom(runs, model->paragraphs);
|
|
return EditRun(begin, end, runs);
|
|
}
|
|
|
|
vint DocumentModel::EditRun(TextPos begin, TextPos end, const collections::Array<Ptr<DocumentParagraphRun>>& 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<DocumentRun> 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<DocumentParagraphRun>());
|
|
paragraphs.Insert(begin.row+1, rightRun.Cast<DocumentParagraphRun>());
|
|
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<DocumentParagraphRun> beginParagraph=paragraphs[begin.row];
|
|
Ptr<DocumentParagraphRun> 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<DocumentParagraphRun> newBeginRuns=runs[0];
|
|
CopyFrom(beginParagraph->runs, newBeginRuns->runs, true);
|
|
|
|
Ptr<DocumentParagraphRun> newEndRuns=runs[runs.Count()-1];
|
|
if (newEndRuns->alignment)
|
|
{
|
|
endParagraph->alignment = newEndRuns->alignment;
|
|
}
|
|
for(vint i=0;i<newEndRuns->runs.Count();i++)
|
|
{
|
|
endParagraph->runs.Insert(i, newEndRuns->runs[i]);
|
|
}
|
|
|
|
for(vint i=1;i<runs.Count()-1;i++)
|
|
{
|
|
paragraphs.Insert(begin.row+i, runs[i]);
|
|
}
|
|
}
|
|
|
|
// clear unnecessary runs
|
|
vint rows=runs.Count()==0?1:runs.Count();
|
|
for(vint i=0;i<rows;i++)
|
|
{
|
|
ClearRunVisitor::ClearRun(paragraphs[begin.row+i].Obj());
|
|
}
|
|
return rows;
|
|
}
|
|
|
|
/***********************************************************************
|
|
DocumentModel::EditText
|
|
***********************************************************************/
|
|
|
|
vint DocumentModel::EditText(TextPos begin, TextPos end, bool frontSide, const collections::Array<WString>& 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<DocumentContainerRun*> styleRuns;
|
|
LocateStyleVisitor::LocateStyle(paragraphs[stylePosition.row].Obj(), runRanges, stylePosition.column, frontSide, styleRuns);
|
|
|
|
// create paragraphs
|
|
Array<Ptr<DocumentParagraphRun>> runs(text.Count());
|
|
for(vint i=0;i<text.Count();i++)
|
|
{
|
|
Ptr<DocumentRun> paragraph=CloneRunVisitor::CopyStyledText(styleRuns, text[i]);
|
|
runs[i]=paragraph.Cast<DocumentParagraphRun>();
|
|
}
|
|
|
|
// replace the paragraphs
|
|
return EditRun(begin, end, runs);
|
|
}
|
|
|
|
/***********************************************************************
|
|
DocumentModel::EditStyle
|
|
***********************************************************************/
|
|
|
|
bool DocumentModel::EditStyle(TextPos begin, TextPos end, Ptr<DocumentStyleProperties> style)
|
|
{
|
|
return EditContainer(begin, end, [=](DocumentParagraphRun* paragraph, RunRangeMap& runRanges, vint start, vint end)
|
|
{
|
|
AddStyleVisitor::AddStyle(paragraph, runRanges, start, end, style);
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
DocumentModel::EditImage
|
|
***********************************************************************/
|
|
|
|
Ptr<DocumentImageRun> DocumentModel::EditImage(TextPos begin, TextPos end, Ptr<GuiImageData> image)
|
|
{
|
|
Ptr<DocumentImageRun> 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<DocumentParagraphRun> paragraph=new DocumentParagraphRun;
|
|
paragraph->runs.Add(imageRun);
|
|
|
|
Array<Ptr<DocumentParagraphRun>> 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<DocumentHyperlinkRun> 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<DocumentParagraphRun> 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<DocumentParagraphRun> paragraph=paragraphs[paragraphIndex];
|
|
RemoveHyperlinkVisitor::RemoveHyperlink(paragraph.Obj(), runRanges, begin, end);
|
|
ClearRunVisitor::ClearRun(paragraph.Obj());
|
|
return true;
|
|
}
|
|
|
|
Ptr<DocumentHyperlinkRun> DocumentModel::GetHyperlink(vint paragraphIndex, vint begin, vint end)
|
|
{
|
|
RunRangeMap runRanges;
|
|
if(!CheckEditRange(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), runRanges)) return 0;
|
|
|
|
Ptr<DocumentParagraphRun> 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<DocumentStyle> style=styles.Values()[index];
|
|
styles.Remove(oldStyleName);
|
|
styles.Add(newStyleName, style);
|
|
|
|
FOREACH(Ptr<DocumentStyle>, subStyle, styles.Values())
|
|
{
|
|
if(subStyle->parentStyleName==oldStyleName)
|
|
{
|
|
subStyle->parentStyleName=newStyleName;
|
|
}
|
|
}
|
|
|
|
FOREACH(Ptr<DocumentParagraphRun>, 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<DocumentStyleProperties> DocumentModel::SummarizeStyle(TextPos begin, TextPos end)
|
|
{
|
|
Ptr<DocumentStyleProperties> 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<DocumentParagraphRun> paragraph=paragraphs[i];
|
|
if(begin.row<i && i<end.row)
|
|
{
|
|
GetRunRangeVisitor::GetRunRange(paragraph.Obj(), runRanges);
|
|
}
|
|
RunRange range=runRanges[paragraph.Obj()];
|
|
Ptr<DocumentStyleProperties> 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<DocumentModel> model;
|
|
Ptr<DocumentContainerRun> container;
|
|
vint paragraphIndex;
|
|
Ptr<GuiResourcePathResolver> resolver;
|
|
Regex regexAttributeApply;
|
|
List<WString>& errors;
|
|
|
|
DeserializeNodeVisitor(Ptr<DocumentModel> _model, Ptr<DocumentParagraphRun> _paragraph, vint _paragraphIndex, Ptr<GuiResourcePathResolver> _resolver, List<WString>& _errors)
|
|
:model(_model)
|
|
, container(_paragraph)
|
|
, paragraphIndex(_paragraphIndex)
|
|
, resolver(_resolver)
|
|
, regexAttributeApply(L"/{@(<value>[^{}]+)/}")
|
|
, errors(_errors)
|
|
{
|
|
}
|
|
|
|
void PrintText(const WString& text)
|
|
{
|
|
Ptr<DocumentTextRun> 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<DocumentContainerRun> 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<DocumentImageRun> run=new DocumentImageRun;
|
|
run->baseline = -1;
|
|
|
|
if(Ptr<XmlAttribute> source=XmlGetAttribute(node, L"source"))
|
|
{
|
|
run->source=source->value.value;
|
|
WString protocol, path;
|
|
if(IsResourceUrl(run->source, protocol, path))
|
|
{
|
|
Ptr<GuiImageData> imageData=resolver->ResolveResource(protocol, path).Cast<GuiImageData>();
|
|
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<XmlAttribute>, 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 <img> \"" + att->name.value + L"\".");
|
|
}
|
|
}
|
|
|
|
container->runs.Add(run);
|
|
}
|
|
}
|
|
else if(node->name.value==L"object")
|
|
{
|
|
Ptr<DocumentEmbeddedObjectRun> run=new DocumentEmbeddedObjectRun;
|
|
run->baseline = -1;
|
|
|
|
if(Ptr<XmlAttribute> name=XmlGetAttribute(node, L"name"))
|
|
{
|
|
run->name = name->value.value;
|
|
container->runs.Add(run);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(L"The \"name\" attribute in <object> is missing.");
|
|
}
|
|
}
|
|
else if(node->name.value==L"font")
|
|
{
|
|
Ptr<DocumentStylePropertiesRun> run=new DocumentStylePropertiesRun();
|
|
Ptr<DocumentStyleProperties> sp=new DocumentStyleProperties;
|
|
run->style=sp;
|
|
|
|
FOREACH(Ptr<XmlAttribute>, 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 <font> \"" + att->name.value + L"\".");
|
|
}
|
|
}
|
|
container->runs.Add(run);
|
|
createdContainer=run;
|
|
}
|
|
else if(node->name.value==L"b" || node->name.value==L"b-")
|
|
{
|
|
Ptr<DocumentStylePropertiesRun> 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<DocumentStylePropertiesRun> 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<DocumentStylePropertiesRun> 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<DocumentStylePropertiesRun> 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<DocumentStylePropertiesRun> 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<DocumentStylePropertiesRun> 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<DocumentStylePropertiesRun> 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<XmlAttribute> att=XmlGetAttribute(node, L"style"))
|
|
{
|
|
WString styleName=att->value.value;
|
|
|
|
Ptr<DocumentStyleApplicationRun> run=new DocumentStyleApplicationRun;
|
|
run->styleName=styleName;
|
|
container->runs.Add(run);
|
|
createdContainer=run;
|
|
}
|
|
else
|
|
{
|
|
createdContainer=container;
|
|
}
|
|
}
|
|
else if(node->name.value==L"a")
|
|
{
|
|
Ptr<DocumentHyperlinkRun> run=new DocumentHyperlinkRun;
|
|
run->normalStyleName=L"#NormalLink";
|
|
run->activeStyleName=L"#ActiveLink";
|
|
if(Ptr<XmlAttribute> att=XmlGetAttribute(node, L"normal"))
|
|
{
|
|
run->normalStyleName=att->value.value;
|
|
}
|
|
if(Ptr<XmlAttribute> att=XmlGetAttribute(node, L"active"))
|
|
{
|
|
run->activeStyleName=att->value.value;
|
|
}
|
|
if(Ptr<XmlAttribute> 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<XmlNode>, 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<XmlNode>, sub, node->subNodes)
|
|
{
|
|
sub->Accept(this);
|
|
}
|
|
}
|
|
|
|
if(createdContainer)
|
|
{
|
|
Ptr<DocumentContainerRun> oldContainer=container;
|
|
container=createdContainer;
|
|
FOREACH(Ptr<XmlNode>, subNode, subNodeContainer->subNodes)
|
|
{
|
|
subNode->Accept(this);
|
|
}
|
|
container=oldContainer;
|
|
}
|
|
}
|
|
|
|
void Visit(XmlInstruction* node)override
|
|
{
|
|
}
|
|
|
|
void Visit(XmlDocument* node)override
|
|
{
|
|
}
|
|
};
|
|
|
|
Ptr<DocumentStyle> ParseDocumentStyle(Ptr<XmlElement> styleElement)
|
|
{
|
|
Ptr<DocumentStyle> style=new DocumentStyle;
|
|
|
|
if(Ptr<XmlAttribute> parent=XmlGetAttribute(styleElement, L"parent"))
|
|
{
|
|
style->parentStyleName=parent->value.value;
|
|
}
|
|
|
|
Ptr<DocumentStyleProperties> sp=new DocumentStyleProperties;
|
|
style->styles=sp;
|
|
|
|
FOREACH(Ptr<XmlElement>, 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> DocumentModel::LoadFromXml(Ptr<parsing::xml::XmlDocument> xml, Ptr<GuiResourcePathResolver> resolver, collections::List<WString>& errors)
|
|
{
|
|
Ptr<DocumentModel> model=new DocumentModel;
|
|
if(xml->rootElement->name.value==L"Doc")
|
|
{
|
|
if(Ptr<XmlElement> styles=XmlGetElement(xml->rootElement, L"Styles"))
|
|
{
|
|
FOREACH(Ptr<XmlElement>, styleElement, XmlGetElements(styles, L"Style"))
|
|
if (Ptr<XmlAttribute> 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<DocumentStyle>();
|
|
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<XmlElement> content=XmlGetElement(xml->rootElement, L"Content"))
|
|
{
|
|
FOREACH_INDEXER(Ptr<XmlElement>, p, i, XmlGetElements(content, L"p"))
|
|
{
|
|
Ptr<DocumentParagraphRun> paragraph=new DocumentParagraphRun;
|
|
if(Ptr<XmlAttribute> 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> DocumentModel::LoadFromXml(Ptr<parsing::xml::XmlDocument> xml, const WString& workingDirectory, collections::List<WString>& errors)
|
|
{
|
|
Ptr<GuiResourcePathResolver> resolver=new GuiResourcePathResolver(0, workingDirectory);
|
|
return LoadFromXml(xml, resolver, errors);
|
|
}
|
|
|
|
Ptr<DocumentModel> DocumentModel::LoadFromXml(const WString& filePath, collections::List<WString>& errors)
|
|
{
|
|
Ptr<XmlDocument> xml;
|
|
Ptr<DocumentModel> document;
|
|
if(auto parser=GetParserManager()->GetParser<XmlDocument>(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<XmlElement> parent;
|
|
|
|
public:
|
|
SerializeRunVisitor(DocumentModel* _model, Ptr<XmlElement> _parent)
|
|
:model(_model)
|
|
,parent(_parent)
|
|
{
|
|
}
|
|
|
|
void VisitContainer(Ptr<XmlElement> replacedParent, DocumentContainerRun* run)
|
|
{
|
|
if(replacedParent)
|
|
{
|
|
parent->subNodes.Add(replacedParent);
|
|
Ptr<XmlElement> oldParent=parent;
|
|
parent=replacedParent;
|
|
FOREACH(Ptr<DocumentRun>, subRun, run->runs)
|
|
{
|
|
subRun->Accept(this);
|
|
}
|
|
parent=oldParent;
|
|
}
|
|
else
|
|
{
|
|
FOREACH(Ptr<DocumentRun>, 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<DocumentStyleProperties> sp=run->style;
|
|
Ptr<XmlElement> oldParent=parent;
|
|
if(sp->face || sp->size || sp->color)
|
|
{
|
|
Ptr<XmlElement> 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<XmlElement> element=new XmlElement;
|
|
element->name.value=sp->bold.Value()?L"b":L"b-";
|
|
parent->subNodes.Add(element);
|
|
parent=element;
|
|
}
|
|
if(sp->italic)
|
|
{
|
|
Ptr<XmlElement> element=new XmlElement;
|
|
element->name.value=sp->italic.Value()?L"i":L"i-";
|
|
parent->subNodes.Add(element);
|
|
parent=element;
|
|
}
|
|
if(sp->underline)
|
|
{
|
|
Ptr<XmlElement> element=new XmlElement;
|
|
element->name.value=sp->underline.Value()?L"u":L"u-";
|
|
parent->subNodes.Add(element);
|
|
parent=element;
|
|
}
|
|
if(sp->strikeline)
|
|
{
|
|
Ptr<XmlElement> 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<XmlElement> element=new XmlElement;
|
|
element->name.value=L"ha";
|
|
parent->subNodes.Add(element);
|
|
parent=element;
|
|
}
|
|
else if(!va)
|
|
{
|
|
Ptr<XmlElement> element=new XmlElement;
|
|
element->name.value=L"va";
|
|
parent->subNodes.Add(element);
|
|
parent=element;
|
|
}
|
|
else
|
|
{
|
|
Ptr<XmlElement> 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<XmlElement> element=new XmlElement;
|
|
element->name.value=L"div";
|
|
XmlElementWriter(element).Attribute(L"style", run->styleName);
|
|
VisitContainer(element, run);
|
|
}
|
|
|
|
void Visit(DocumentHyperlinkRun* run)override
|
|
{
|
|
Ptr<XmlElement> 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<XmlElement> 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<parsing::xml::XmlDocument> DocumentModel::SaveToXml()
|
|
{
|
|
Ptr<XmlDocument> xml=new XmlDocument;
|
|
Ptr<XmlElement> doc=new XmlElement;
|
|
doc->name.value=L"Doc";
|
|
xml->rootElement=doc;
|
|
{
|
|
Ptr<XmlElement> content=new XmlElement;
|
|
content->name.value=L"Content";
|
|
doc->subNodes.Add(content);
|
|
|
|
FOREACH(Ptr<DocumentParagraphRun>, p, paragraphs)
|
|
{
|
|
SerializeRunVisitor visitor(this, content);
|
|
p->Accept(&visitor);
|
|
}
|
|
}
|
|
{
|
|
Ptr<XmlElement> stylesElement=new XmlElement;
|
|
stylesElement->name.value=L"Styles";
|
|
doc->subNodes.Add(stylesElement);
|
|
|
|
for(vint i=0;i<styles.Count();i++)
|
|
{
|
|
WString name=styles.Keys()[i];
|
|
if (name.Length()>0 && name[0] == L'#' && (name.Length() <= 9 || name.Right(9) != L"-Override")) continue;
|
|
|
|
Ptr<DocumentStyle> style=styles.Values().Get(i);
|
|
Ptr<DocumentStyleProperties> sp=style->styles;
|
|
Ptr<XmlElement> 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<XmlDocument> 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<WString, Ptr<Table>> tables;
|
|
Dictionary<WString, Func<Ptr<Table>()>> loaders;
|
|
SpinLock lock;
|
|
|
|
Dictionary<WString, Ptr<IGuiGeneralParser>> 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<Table> 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> table=loaders.Values()[index]();
|
|
tables.Add(name, table);
|
|
return table;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool SetParsingTable(const WString& name, Func<Ptr<Table>()> loader)override
|
|
{
|
|
if(loaders.Keys().Contains(name)) return false;
|
|
loaders.Add(name, loader);
|
|
return true;
|
|
}
|
|
|
|
Ptr<IGuiGeneralParser> GetParser(const WString& name)override
|
|
{
|
|
vint index=parsers.Keys().IndexOf(name);
|
|
return index == -1 ? nullptr : parsers.Values()[index];
|
|
}
|
|
|
|
bool SetParser(const WString& name, Ptr<IGuiGeneralParser> 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<vint, vint> 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<WString, vint> stoi;
|
|
List<WString> 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<INativeImage> _image, vint _frameIndex, const WString& _filePath)
|
|
:image(_image)
|
|
, frameIndex(_frameIndex)
|
|
, filePath(_filePath)
|
|
{
|
|
}
|
|
|
|
GuiImageData::~GuiImageData()
|
|
{
|
|
}
|
|
|
|
Ptr<INativeImage> 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<DescriptableObject> GuiResourceItem::GetContent()
|
|
{
|
|
return content;
|
|
}
|
|
|
|
void GuiResourceItem::SetContent(const WString& _typeName, Ptr<DescriptableObject> value)
|
|
{
|
|
typeName = _typeName;
|
|
content = value;
|
|
}
|
|
|
|
Ptr<GuiImageData> GuiResourceItem::AsImage()
|
|
{
|
|
return content.Cast<GuiImageData>();
|
|
}
|
|
|
|
Ptr<parsing::xml::XmlDocument> GuiResourceItem::AsXml()
|
|
{
|
|
return content.Cast<XmlDocument>();
|
|
}
|
|
|
|
Ptr<GuiTextData> GuiResourceItem::AsString()
|
|
{
|
|
return content.Cast<GuiTextData>();
|
|
}
|
|
|
|
Ptr<DocumentModel> GuiResourceItem::AsDocument()
|
|
{
|
|
return content.Cast<DocumentModel>();
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiResourceFolder
|
|
***********************************************************************/
|
|
|
|
void GuiResourceFolder::LoadResourceFolderFromXml(DelayLoadingList& delayLoadings, const WString& containingFolder, Ptr<parsing::xml::XmlElement> folderXml, collections::List<WString>& errors)
|
|
{
|
|
ClearItems();
|
|
ClearFolders();
|
|
FOREACH(Ptr<XmlElement>, element, XmlGetElements(folderXml))
|
|
{
|
|
WString name;
|
|
if(Ptr<XmlAttribute> 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<GuiResourceFolder> folder=new GuiResourceFolder;
|
|
if(AddFolder(name, folder))
|
|
{
|
|
WString newContainingFolder=containingFolder;
|
|
Ptr<XmlElement> newFolderXml=element;
|
|
if(Ptr<XmlAttribute> 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<XmlDocument>(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<XmlAttribute> contentAtt=XmlGetAttribute(element, L"content"))
|
|
{
|
|
if(contentAtt->value.value==L"File")
|
|
{
|
|
relativeFilePath = XmlGetValue(element);
|
|
filePath = containingFolder + relativeFilePath;
|
|
if(name==L"")
|
|
{
|
|
name=GetFileName(filePath);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ptr<GuiResourceItem> 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<DescriptableObject> 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<parsing::xml::XmlElement> xmlParent)
|
|
{
|
|
FOREACH(Ptr<GuiResourceItem>, item, items.Values())
|
|
{
|
|
auto resolver = GetResourceResolverManager()->GetTypeResolver(item->GetTypeName());
|
|
if (resolver->XmlSerializable())
|
|
{
|
|
auto attName = MakePtr<XmlAttribute>();
|
|
attName->name.value = L"name";
|
|
attName->value.value = item->GetName();
|
|
|
|
if (item->GetFileContentPath() == L"")
|
|
{
|
|
Ptr<XmlElement> 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>();
|
|
xmlElement->name.value = item->GetTypeName();
|
|
xmlParent->subNodes.Add(xmlElement);
|
|
|
|
auto attContent = MakePtr<XmlAttribute>();
|
|
attContent->name.value = L"content";
|
|
attContent->value.value = L"File";
|
|
xmlElement->attributes.Add(attContent);
|
|
|
|
auto xmlText = MakePtr<XmlText>();
|
|
xmlText->content.value = item->GetFileContentPath();
|
|
xmlElement->subNodes.Add(xmlText);
|
|
}
|
|
}
|
|
}
|
|
|
|
FOREACH(Ptr<GuiResourceFolder>, folder, folders.Values())
|
|
{
|
|
auto attName = MakePtr<XmlAttribute>();
|
|
attName->name.value = L"name";
|
|
attName->value.value = folder->GetName();
|
|
|
|
auto xmlFolder = MakePtr<XmlElement>();
|
|
xmlFolder->name.value = L"Folder";
|
|
xmlFolder->attributes.Add(attName);
|
|
xmlParent->subNodes.Add(xmlFolder);
|
|
|
|
|
|
if (folder->GetFileContentPath() == L"")
|
|
{
|
|
folder->SaveResourceFolderToXml(xmlFolder);
|
|
}
|
|
else
|
|
{
|
|
auto attContent = MakePtr<XmlAttribute>();
|
|
attContent->name.value = L"content";
|
|
attContent->value.value = L"Link";
|
|
xmlFolder->attributes.Add(attContent);
|
|
|
|
auto xmlText = MakePtr<XmlText>();
|
|
xmlText->content.value = folder->GetFileContentPath();
|
|
xmlFolder->subNodes.Add(xmlText);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiResourceFolder::CollectTypeNames(collections::List<WString>& typeNames)
|
|
{
|
|
FOREACH(Ptr<GuiResourceItem>, item, items.Values())
|
|
{
|
|
if (!typeNames.Contains(item->GetTypeName()))
|
|
{
|
|
typeNames.Add(item->GetTypeName());
|
|
}
|
|
}
|
|
FOREACH(Ptr<GuiResourceFolder>, folder, folders.Values())
|
|
{
|
|
folder->CollectTypeNames(typeNames);
|
|
}
|
|
}
|
|
|
|
void GuiResourceFolder::LoadResourceFolderFromBinary(DelayLoadingList& delayLoadings, stream::internal::ContextFreeReader& reader, collections::List<WString>& typeNames, collections::List<WString>& 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<GuiResourceItem> 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<GuiResourceFolder>();
|
|
folder->LoadResourceFolderFromBinary(delayLoadings, reader, typeNames, errors);
|
|
AddFolder(name, folder);
|
|
}
|
|
}
|
|
|
|
void GuiResourceFolder::SaveResourceFolderToBinary(stream::internal::ContextFreeWriter& writer, collections::List<WString>& typeNames)
|
|
{
|
|
typedef Tuple<vint, WString, IGuiResourceTypeResolver_DirectLoadStream*, Ptr<DescriptableObject>> ItemTuple;
|
|
List<ItemTuple> itemTuples;
|
|
|
|
FOREACH(Ptr<GuiResourceItem>, 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<GuiResourceFolder>, folder, folders.Values())
|
|
{
|
|
WString name = folder->GetName();
|
|
writer << name;
|
|
folder->SaveResourceFolderToBinary(writer, typeNames);
|
|
}
|
|
}
|
|
|
|
void GuiResourceFolder::PrecompileResourceFolder(GuiResourcePrecompileContext& context, IGuiResourcePrecompileCallback* callback, collections::List<WString>& errors)
|
|
{
|
|
FOREACH(Ptr<GuiResourceItem>, 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<GuiResourceFolder>, folder, folders.Values())
|
|
{
|
|
folder->PrecompileResourceFolder(context, callback, errors);
|
|
}
|
|
}
|
|
|
|
void GuiResourceFolder::InitializeResourceFolder(GuiResourceInitializeContext& context)
|
|
{
|
|
FOREACH(Ptr<GuiResourceItem>, item, items.Values())
|
|
{
|
|
auto typeResolver = GetResourceResolverManager()->GetTypeResolver(item->GetTypeName());
|
|
if (auto initialize = typeResolver->Initialize())
|
|
{
|
|
initialize->Initialize(item, context);
|
|
}
|
|
}
|
|
|
|
FOREACH(Ptr<GuiResourceFolder>, folder, folders.Values())
|
|
{
|
|
folder->InitializeResourceFolder(context);
|
|
}
|
|
}
|
|
|
|
GuiResourceFolder::GuiResourceFolder()
|
|
{
|
|
}
|
|
|
|
GuiResourceFolder::~GuiResourceFolder()
|
|
{
|
|
}
|
|
|
|
const GuiResourceFolder::ItemList& GuiResourceFolder::GetItems()
|
|
{
|
|
return items.Values();
|
|
}
|
|
|
|
Ptr<GuiResourceItem> 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<GuiResourceItem> item)
|
|
{
|
|
if(item->GetParent()!=0 || items.Keys().Contains(name)) return false;
|
|
items.Add(name, item);
|
|
item->parent=this;
|
|
item->name=name;
|
|
return true;
|
|
}
|
|
|
|
Ptr<GuiResourceItem> GuiResourceFolder::RemoveItem(const WString& name)
|
|
{
|
|
Ptr<GuiResourceItem> 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> 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<GuiResourceFolder> 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> GuiResourceFolder::RemoveFolder(const WString& name)
|
|
{
|
|
Ptr<GuiResourceFolder> folder=GetFolder(name);
|
|
if(!folder) return 0;
|
|
folders.Remove(name);
|
|
return folder;
|
|
}
|
|
|
|
void GuiResourceFolder::ClearFolders()
|
|
{
|
|
folders.Clear();
|
|
}
|
|
|
|
Ptr<DescriptableObject> 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<GuiResourceFolder> folder=GetFolder(name);
|
|
if(folder)
|
|
{
|
|
vint start=index-buffer+1;
|
|
return folder->GetValueByPath(path.Sub(start, path.Length()-start));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Ptr<GuiResourceItem> item=GetItem(path);
|
|
if(item)
|
|
{
|
|
return item->GetContent();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Ptr<GuiResourceFolder> 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<GuiResourceFolder> 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<DescriptableObject> 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<GuiResourceFolder> 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<GuiResource> resource, DelayLoadingList& delayLoadings, collections::List<WString>& errors)
|
|
{
|
|
FOREACH(DelayLoading, delay, delayLoadings)
|
|
{
|
|
WString type = delay.type;
|
|
WString folder = delay.workingDirectory;
|
|
Ptr<GuiResourceItem> 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<GuiResourcePathResolver> pathResolver = new GuiResourcePathResolver(resource, folder);
|
|
Ptr<DescriptableObject> 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> GuiResource::LoadFromXml(Ptr<parsing::xml::XmlDocument> xml, const WString& workingDirectory, collections::List<WString>& errors)
|
|
{
|
|
Ptr<GuiResource> resource = new GuiResource;
|
|
resource->workingDirectory = workingDirectory;
|
|
DelayLoadingList delayLoadings;
|
|
resource->LoadResourceFolderFromXml(delayLoadings, resource->workingDirectory, xml->rootElement, errors);
|
|
|
|
ProcessDelayLoading(resource, delayLoadings, errors);
|
|
return resource;
|
|
}
|
|
|
|
Ptr<GuiResource> GuiResource::LoadFromXml(const WString& filePath, collections::List<WString>& errors)
|
|
{
|
|
Ptr<XmlDocument> xml;
|
|
if(auto parser=GetParserManager()->GetParser<XmlDocument>(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<parsing::xml::XmlDocument> GuiResource::SaveToXml()
|
|
{
|
|
auto xmlRoot = MakePtr<XmlElement>();
|
|
xmlRoot->name.value = L"Resource";
|
|
SaveResourceFolderToXml(xmlRoot);
|
|
|
|
auto doc = MakePtr<XmlDocument>();
|
|
doc->rootElement = xmlRoot;
|
|
return doc;
|
|
}
|
|
|
|
Ptr<GuiResource> GuiResource::LoadPrecompiledBinary(stream::IStream& stream, collections::List<WString>& errors)
|
|
{
|
|
stream::internal::ContextFreeReader reader(stream);
|
|
auto resource = MakePtr<GuiResource>();
|
|
|
|
List<WString> 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<WString> typeNames;
|
|
CollectTypeNames(typeNames);
|
|
writer << typeNames;
|
|
SaveResourceFolderToBinary(writer, typeNames);
|
|
}
|
|
|
|
void GuiResource::Precompile(IGuiResourcePrecompileCallback* callback, collections::List<WString>& 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<WString> 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<DocumentModel> GuiResource::GetDocumentByPath(const WString& path)
|
|
{
|
|
Ptr<DocumentModel> result=GetValueByPath(path).Cast<DocumentModel>();
|
|
if(!result) throw ArgumentException(L"Path not exists.", L"GuiResource::GetDocumentByPath", L"path");
|
|
return result;
|
|
}
|
|
|
|
Ptr<GuiImageData> GuiResource::GetImageByPath(const WString& path)
|
|
{
|
|
Ptr<GuiImageData> result=GetValueByPath(path).Cast<GuiImageData>();
|
|
if(!result) throw ArgumentException(L"Path not exists.", L"GuiResource::GetImageByPath", L"path");
|
|
return result;
|
|
}
|
|
|
|
Ptr<parsing::xml::XmlDocument> GuiResource::GetXmlByPath(const WString& path)
|
|
{
|
|
Ptr<XmlDocument> result=GetValueByPath(path).Cast<XmlDocument>();
|
|
if(!result) throw ArgumentException(L"Path not exists.", L"GuiResource::GetXmlByPath", L"path");
|
|
return result;
|
|
}
|
|
|
|
WString GuiResource::GetStringByPath(const WString& path)
|
|
{
|
|
Ptr<ObjectBox<WString>> result=GetValueByPath(path).Cast<ObjectBox<WString>>();
|
|
if(!result) throw ArgumentException(L"Path not exists.", L"GuiResource::GetStringByPath", L"path");
|
|
return result->Unbox();
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiResourcePathResolver
|
|
***********************************************************************/
|
|
|
|
GuiResourcePathResolver::GuiResourcePathResolver(Ptr<GuiResource> _resource, const WString& _workingDirectory)
|
|
:resource(_resource)
|
|
,workingDirectory(_workingDirectory)
|
|
{
|
|
}
|
|
|
|
GuiResourcePathResolver::~GuiResourcePathResolver()
|
|
{
|
|
}
|
|
|
|
Ptr<DescriptableObject> GuiResourcePathResolver::ResolveResource(const WString& protocol, const WString& path)
|
|
{
|
|
Ptr<IGuiResourcePathResolver> 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<DescriptableObject> ResolveResource(const WString& path)
|
|
{
|
|
WString filename=path;
|
|
if(filename.Length()>=2 && filename[1]!=L':')
|
|
{
|
|
filename=workingDirectory+filename;
|
|
}
|
|
Ptr<INativeImage> image=GetCurrentController()->ImageService()->CreateImageFromFile(filename);
|
|
return new GuiImageData(image, 0);
|
|
}
|
|
|
|
class Factory : public Object, public IGuiResourcePathResolverFactory
|
|
{
|
|
public:
|
|
WString GetProtocol()override
|
|
{
|
|
return L"file";
|
|
}
|
|
|
|
Ptr<IGuiResourcePathResolver> CreateResolver(Ptr<GuiResource> resource, const WString& workingDirectory)override
|
|
{
|
|
return new GuiResourcePathFileResolver(workingDirectory);
|
|
}
|
|
};
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiResourcePathResResolver
|
|
***********************************************************************/
|
|
|
|
class GuiResourcePathResResolver : public Object, public IGuiResourcePathResolver
|
|
{
|
|
protected:
|
|
Ptr<GuiResource> resource;
|
|
|
|
public:
|
|
GuiResourcePathResResolver(Ptr<GuiResource> _resource)
|
|
:resource(_resource)
|
|
{
|
|
}
|
|
|
|
Ptr<DescriptableObject> 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<IGuiResourcePathResolver> CreateResolver(Ptr<GuiResource> 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<WString, Ptr<IGuiResourcePathResolverFactory>> PathFactoryMap;
|
|
typedef Dictionary<WString, Ptr<IGuiResourceTypeResolver>> TypeResolverMap;
|
|
typedef Group<vint, WString> 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<IGuiResourcePathResolverFactory> 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<IGuiResourceTypeResolver> 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<IGuiResourceTypeResolver>, 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<IGuiResourceTypeResolver>, 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<WString>& names)override
|
|
{
|
|
names.Clear();
|
|
vint index = perResourceResolvers.Keys().IndexOf(passIndex);
|
|
if (index != -1)
|
|
{
|
|
CopyFrom(names, perResourceResolvers.GetByIndex(index));
|
|
}
|
|
}
|
|
|
|
void GetPerPassResolverNames(vint passIndex, collections::List<WString>& 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<DescriptableObject> resource, stream::IStream& stream)override
|
|
{
|
|
if (auto obj = resource.Cast<GuiResourceClassNameRecord>())
|
|
{
|
|
internal::ContextFreeWriter writer(stream);
|
|
writer << obj->classNames;
|
|
}
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResourcePrecompiled(stream::IStream& stream, collections::List<WString>& errors)override
|
|
{
|
|
internal::ContextFreeReader reader(stream);
|
|
|
|
auto obj = MakePtr<GuiResourceClassNameRecord>();
|
|
reader << obj->classNames;
|
|
return obj;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
IGuiInstanceResourceManager
|
|
***********************************************************************/
|
|
|
|
IGuiResourceManager* resourceManager = 0;
|
|
|
|
IGuiResourceManager* GetResourceManager()
|
|
{
|
|
return resourceManager;
|
|
}
|
|
|
|
class GuiResourceManager : public Object, public IGuiResourceManager, public IGuiPlugin
|
|
{
|
|
protected:
|
|
typedef Dictionary<WString, Ptr<GuiResource>> 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<GuiResource> 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<GuiResourceClassNameRecord>();
|
|
FOREACH(WString, className, record->classNames)
|
|
{
|
|
instanceResources.Add(className, resource);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Ptr<GuiResource> GetResource(const WString& name)override
|
|
{
|
|
vint index = resources.Keys().IndexOf(name);
|
|
return index == -1 ? nullptr : resources.Values()[index];
|
|
}
|
|
|
|
Ptr<GuiResource> 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<parsing::xml::XmlElement> Serialize(Ptr<DescriptableObject> resource)override
|
|
{
|
|
if (auto obj = resource.Cast<GuiImageData>())
|
|
{
|
|
FileStream fileStream(obj->GetFilePath(), FileStream::ReadOnly);
|
|
if (fileStream.IsAvailable())
|
|
{
|
|
auto xmlContent = MakePtr<XmlCData>();
|
|
xmlContent->content.value = BinaryToHex(fileStream);
|
|
|
|
auto xmlImage = MakePtr<XmlElement>();
|
|
xmlImage->name.value = L"Image";
|
|
xmlImage->subNodes.Add(xmlContent);
|
|
return xmlImage;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void SerializePrecompiled(Ptr<DescriptableObject> resource, stream::IStream& stream)override
|
|
{
|
|
auto obj = resource.Cast<GuiImageData>();
|
|
stream::internal::ContextFreeWriter writer(stream);
|
|
FileStream fileStream(obj->GetFilePath(), FileStream::ReadOnly);
|
|
writer << (stream::IStream&)fileStream;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(Ptr<parsing::xml::XmlElement> element, collections::List<WString>& 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<DescriptableObject> ResolveResource(const WString& path, collections::List<WString>& errors)override
|
|
{
|
|
Ptr<INativeImage> 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<DescriptableObject> ResolveResourcePrecompiled(stream::IStream& stream, collections::List<WString>& 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<parsing::xml::XmlElement> Serialize(Ptr<DescriptableObject> resource)override
|
|
{
|
|
if (auto obj = resource.Cast<GuiTextData>())
|
|
{
|
|
auto xmlContent = MakePtr<XmlText>();
|
|
xmlContent->content.value = obj->GetText();
|
|
|
|
auto xmlText = MakePtr<XmlElement>();
|
|
xmlText->name.value = L"Text";
|
|
xmlText->subNodes.Add(xmlContent);
|
|
|
|
return xmlText;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void SerializePrecompiled(Ptr<DescriptableObject> resource, stream::IStream& stream)override
|
|
{
|
|
auto obj = resource.Cast<GuiTextData>();
|
|
stream::internal::ContextFreeWriter writer(stream);
|
|
WString text = obj->GetText();
|
|
writer << text;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(Ptr<parsing::xml::XmlElement> element, collections::List<WString>& errors)override
|
|
{
|
|
return new GuiTextData(XmlGetValue(element));
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(const WString& path, collections::List<WString>& 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<DescriptableObject> ResolveResourcePrecompiled(stream::IStream& stream, collections::List<WString>& 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<parsing::xml::XmlElement> Serialize(Ptr<DescriptableObject> resource)override
|
|
{
|
|
if (auto obj = resource.Cast<XmlDocument>())
|
|
{
|
|
auto xmlXml = MakePtr<XmlElement>();
|
|
xmlXml->name.value = L"Xml";
|
|
xmlXml->subNodes.Add(obj->rootElement);
|
|
return xmlXml;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void SerializePrecompiled(Ptr<DescriptableObject> resource, stream::IStream& stream)override
|
|
{
|
|
auto obj = resource.Cast<XmlDocument>();
|
|
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<DescriptableObject> ResolveResource(Ptr<parsing::xml::XmlElement> element, collections::List<WString>& errors)override
|
|
{
|
|
Ptr<XmlElement> root = XmlGetElements(element).First(0);
|
|
if(root)
|
|
{
|
|
Ptr<XmlDocument> xml=new XmlDocument;
|
|
xml->rootElement=root;
|
|
return xml;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(const WString& path, collections::List<WString>& errors)override
|
|
{
|
|
if(auto parser=GetParserManager()->GetParser<XmlDocument>(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<DescriptableObject> ResolveResourcePrecompiled(stream::IStream& stream, collections::List<WString>& errors)override
|
|
{
|
|
stream::internal::ContextFreeReader reader(stream);
|
|
WString text;
|
|
reader << text;
|
|
|
|
auto parser = GetParserManager()->GetParser<XmlDocument>(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<DescriptableObject> Serialize(Ptr<DescriptableObject> resource)override
|
|
{
|
|
if (auto obj = resource.Cast<DocumentModel>())
|
|
{
|
|
return obj->SaveToXml();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(Ptr<DescriptableObject> resource, Ptr<GuiResourcePathResolver> resolver, collections::List<WString>& errors)override
|
|
{
|
|
Ptr<XmlDocument> xml = resource.Cast<XmlDocument>();
|
|
if(xml)
|
|
{
|
|
Ptr<DocumentModel> 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)
|
|
}
|
|
}
|