Initial Actor Editor code
This was SVN commit r2025.
This commit is contained in:
parent
2091822e16
commit
d0146135c4
30
source/tools/atlas/Atlas.sln
Normal file
30
source/tools/atlas/Atlas.sln
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AtlasUI", "AtlasUI\AtlasUI.vcproj", "{E99BA969-D540-4F23-822E-37C499E8F704}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{228B468D-3C2E-45BF-9833-C626E1A35B04} = {228B468D-3C2E-45BF-9833-C626E1A35B04}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AtlasObject", "AtlasObject\AtlasObject.vcproj", "{228B468D-3C2E-45BF-9833-C626E1A35B04}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfiguration) = preSolution
|
||||||
|
Debug = Debug
|
||||||
|
Release = Release
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfiguration) = postSolution
|
||||||
|
{E99BA969-D540-4F23-822E-37C499E8F704}.Debug.ActiveCfg = Debug|Win32
|
||||||
|
{E99BA969-D540-4F23-822E-37C499E8F704}.Debug.Build.0 = Debug|Win32
|
||||||
|
{E99BA969-D540-4F23-822E-37C499E8F704}.Release.ActiveCfg = Release|Win32
|
||||||
|
{E99BA969-D540-4F23-822E-37C499E8F704}.Release.Build.0 = Release|Win32
|
||||||
|
{228B468D-3C2E-45BF-9833-C626E1A35B04}.Debug.ActiveCfg = Debug|Win32
|
||||||
|
{228B468D-3C2E-45BF-9833-C626E1A35B04}.Debug.Build.0 = Debug|Win32
|
||||||
|
{228B468D-3C2E-45BF-9833-C626E1A35B04}.Release.ActiveCfg = Release|Win32
|
||||||
|
{228B468D-3C2E-45BF-9833-C626E1A35B04}.Release.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
137
source/tools/atlas/AtlasObject/AtlasObject.h
Normal file
137
source/tools/atlas/AtlasObject/AtlasObject.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// Public interface to almost all of AtlasObject.
|
||||||
|
// (See AtlasObjectText for the rest of it).
|
||||||
|
//
|
||||||
|
// Tries to include as few headers as possible, to minimise its impact
|
||||||
|
// on compile times.
|
||||||
|
|
||||||
|
#ifndef ATLASOBJECT_H__
|
||||||
|
#define ATLASOBJECT_H__
|
||||||
|
|
||||||
|
#include <wchar.h> // for wchar_t
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Mostly-private bits:
|
||||||
|
|
||||||
|
// Simple reference-counted pointer. class T must contain a reference count,
|
||||||
|
// initialised to 0. An external implementation (in AtlasObjectImpl.cpp)
|
||||||
|
// provides the inc_ref and dec_ref methods, so that this header file doesn't
|
||||||
|
// need to know their implementations.
|
||||||
|
template<class T> class AtSmartPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
AtSmartPtr() : ptr(NULL) {}
|
||||||
|
explicit AtSmartPtr(T* p) : ptr(p) { inc_ref(); }
|
||||||
|
// Copy constructor
|
||||||
|
AtSmartPtr(const AtSmartPtr<T>& r) : ptr(r.ptr) { inc_ref(); }
|
||||||
|
// Assignment operators
|
||||||
|
AtSmartPtr<T>& operator=(T* p) { dec_ref(); ptr = p; inc_ref(); return *this; }
|
||||||
|
AtSmartPtr<T>& operator=(const AtSmartPtr<T>& r) { dec_ref(); ptr = r.ptr; inc_ref(); return *this; }
|
||||||
|
// Destructor
|
||||||
|
~AtSmartPtr() { dec_ref(); }
|
||||||
|
// Allow conversion from non-const T* to const T*
|
||||||
|
operator AtSmartPtr<const T> () { return AtSmartPtr<const T>(ptr); }
|
||||||
|
// Override ->
|
||||||
|
T* operator->() const { return ptr; }
|
||||||
|
// Test whether the pointer is pointing to anything
|
||||||
|
operator bool() const { return ptr!=NULL; }
|
||||||
|
bool operator!() const { return ptr==NULL; }
|
||||||
|
private:
|
||||||
|
void inc_ref();
|
||||||
|
void dec_ref();
|
||||||
|
T* ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A few required declarations
|
||||||
|
class AtObj;
|
||||||
|
class AtNode;
|
||||||
|
class AtIterImpl;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public bits:
|
||||||
|
|
||||||
|
|
||||||
|
// AtIter is an iterator over AtObjs - use it like:
|
||||||
|
//
|
||||||
|
// for (AtIter thing = whatever["thing"]; thing.defined(); ++thing)
|
||||||
|
// DoStuff(thing);
|
||||||
|
//
|
||||||
|
// to handle XML data like:
|
||||||
|
//
|
||||||
|
// <whatever>
|
||||||
|
// <thing>Stuff 1</thing>
|
||||||
|
// <thing>Stuff 2</thing>
|
||||||
|
// </whatever>
|
||||||
|
|
||||||
|
class AtIter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Increment the iterator; or make it undefined, if there weren't any
|
||||||
|
// AtObjs left to iterate over
|
||||||
|
AtIter& operator ++ ();
|
||||||
|
// Return whether this iterator has an AtObj to point to
|
||||||
|
bool defined() const;
|
||||||
|
|
||||||
|
// Return an iterator to the children matching 'key'. (That is, children
|
||||||
|
// of the AtObj currently pointed to by this iterator)
|
||||||
|
const AtIter operator [] (const char* key) const;
|
||||||
|
|
||||||
|
// Return the AtObj currently pointed to by this iterator
|
||||||
|
operator const AtObj () const;
|
||||||
|
|
||||||
|
// Return the string value of the AtObj currently pointed to by this iterator
|
||||||
|
operator const wchar_t* () const;
|
||||||
|
|
||||||
|
#ifdef __WXWINDOWS__
|
||||||
|
// Wrapper function around 'operator wchar_t*', for convenience in wx programs
|
||||||
|
operator const wxString () const { return (const wchar_t*)*this; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Private implementation. (But not 'private:', because it's a waste of time
|
||||||
|
// adding loads of friend functions)
|
||||||
|
AtSmartPtr<AtIterImpl> p;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class AtObj
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AtObj() {}
|
||||||
|
AtObj(const AtObj& r) : p(r.p) {}
|
||||||
|
|
||||||
|
// Return an iterator to the children matching 'key'
|
||||||
|
const AtIter operator [] (const char* key) const;
|
||||||
|
|
||||||
|
// Return the string value of this object
|
||||||
|
operator const wchar_t* () const;
|
||||||
|
|
||||||
|
// Check whether the object contains anything (even if those things are empty)
|
||||||
|
bool isNull() const { return !p; }
|
||||||
|
|
||||||
|
// Check recursively whether there's actually any non-empty data in the object
|
||||||
|
bool isContentless() const;
|
||||||
|
|
||||||
|
// Add or set a child. The wchar_t* versions create a new AtObj with
|
||||||
|
// the appropriate string value, then use that as the child.
|
||||||
|
//
|
||||||
|
// These alter the AtObj's internal pointer, and the pointed-to data is
|
||||||
|
// never actually altered. Copies of this AtObj (including copies stored
|
||||||
|
// inside other AtObjs) will not be affected.
|
||||||
|
void add(const char* key, const wchar_t* value);
|
||||||
|
void add(const char* key, AtObj& data);
|
||||||
|
void set(const char* key, const wchar_t* value);
|
||||||
|
void set(const char* key, AtObj& data);
|
||||||
|
|
||||||
|
AtSmartPtr<const AtNode> p;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Miscellaneous utility functions:
|
||||||
|
namespace AtlasObject
|
||||||
|
{
|
||||||
|
void LoadFromXML(AtObj& obj, const wchar_t* filename);
|
||||||
|
void SaveToXML(AtObj& obj, const wchar_t* filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ATLASOBJECT_H__
|
127
source/tools/atlas/AtlasObject/AtlasObject.vcproj
Normal file
127
source/tools/atlas/AtlasObject/AtlasObject.vcproj
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.10"
|
||||||
|
Name="AtlasObject"
|
||||||
|
ProjectGUID="{228B468D-3C2E-45BF-9833-C626E1A35B04}"
|
||||||
|
Keyword="Win32Proj">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="Debug"
|
||||||
|
IntermediateDirectory="Debug"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="../../../../libraries/xerces/include"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||||
|
MinimalRebuild="TRUE"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="4"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
OutputFile="$(OutDir)/AtlasObject.lib"
|
||||||
|
AdditionalLibraryDirectories="E:\0ad\svnc\trunk\libraries\xerces\lib"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="Release"
|
||||||
|
IntermediateDirectory="Release"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="1"
|
||||||
|
AdditionalIncludeDirectories="../../../../libraries/xerces/include"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="3"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
OutputFile="$(OutDir)/AtlasObject.lib"
|
||||||
|
AdditionalLibraryDirectories="E:\0ad\svnc\trunk\libraries\xerces\lib"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||||
|
<File
|
||||||
|
RelativePath=".\AtlasObject.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\AtlasObjectImpl.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\AtlasObjectImpl.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\AtlasObjectText.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\AtlasObjectText.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\AtlasObjectXML.cpp">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
190
source/tools/atlas/AtlasObject/AtlasObjectImpl.cpp
Normal file
190
source/tools/atlas/AtlasObject/AtlasObjectImpl.cpp
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
#include "AtlasObject.h"
|
||||||
|
#include "AtlasObjectImpl.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define ATSMARTPTR_IMPL(T) \
|
||||||
|
template<> void AtSmartPtr<T>::inc_ref() \
|
||||||
|
{ \
|
||||||
|
if (ptr) ++ptr->refcount; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template<> void AtSmartPtr<T>::dec_ref() \
|
||||||
|
{ \
|
||||||
|
if (ptr && --ptr->refcount == 0) \
|
||||||
|
delete ptr; \
|
||||||
|
} // (Don't set ptr=NULL, since it should never be possible for an
|
||||||
|
// unreferenced pointer to exist; I would rather see it die in debug
|
||||||
|
// mode if that ever happens, instead of just silently ignoring the error.)
|
||||||
|
|
||||||
|
|
||||||
|
ATSMARTPTR_IMPL(AtNode);
|
||||||
|
ATSMARTPTR_IMPL(const AtNode);
|
||||||
|
ATSMARTPTR_IMPL(AtIterImpl);
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const AtIter AtIter::operator [] (const char* key) const
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
return p->iter->second->getChild(key);
|
||||||
|
else
|
||||||
|
return AtIter();
|
||||||
|
}
|
||||||
|
|
||||||
|
AtIter::operator const wchar_t* () const
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
return p->iter->second->value.c_str();
|
||||||
|
else
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
AtIter::operator const AtObj () const
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
AtObj ret;
|
||||||
|
ret.p = p->iter->second;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return AtObj();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AtIter& AtIter::operator ++ ()
|
||||||
|
{
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
// Increment the internal iterator, and stop if we've run out children
|
||||||
|
// to iterate over.
|
||||||
|
if (p && ++p->iter == p->iter_upperbound)
|
||||||
|
p = NULL;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtIter::defined() const
|
||||||
|
{
|
||||||
|
return (p != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const AtIter AtObj::operator [] (const char* key) const
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
return p->getChild(key);
|
||||||
|
else
|
||||||
|
// This object doesn't exist, so return another object that doesn't exist
|
||||||
|
return AtIter();
|
||||||
|
}
|
||||||
|
|
||||||
|
AtObj::operator const wchar_t* () const
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
return p->value.c_str();
|
||||||
|
else
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtObj::add(const char* key, AtObj& data)
|
||||||
|
{
|
||||||
|
if (!p)
|
||||||
|
p = new AtNode();
|
||||||
|
|
||||||
|
p = p->addChild(key, data.p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtObj::add(const char* key, const wchar_t* value)
|
||||||
|
{
|
||||||
|
const AtNode* o = new AtNode(value);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
p = new AtNode();
|
||||||
|
|
||||||
|
p = p->addChild(key, AtNode::Ptr(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtObj::set(const char* key, AtObj& data)
|
||||||
|
{
|
||||||
|
if (!p)
|
||||||
|
p = new AtNode();
|
||||||
|
|
||||||
|
p = p->setChild(key, data.p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtObj::set(const char* key, const wchar_t* value)
|
||||||
|
{
|
||||||
|
const AtNode* o = new AtNode(value);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
p = new AtNode();
|
||||||
|
|
||||||
|
p = p->setChild(key, AtNode::Ptr(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtObj::isContentless() const
|
||||||
|
{
|
||||||
|
if (! p)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return ! p->hasContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const AtIter AtNode::getChild(const char* key) const
|
||||||
|
{
|
||||||
|
// Find the range of matching children
|
||||||
|
AtNode::child_maptype::const_iterator it = children.lower_bound(key);
|
||||||
|
AtNode::child_maptype::const_iterator it_upper = children.upper_bound(key);
|
||||||
|
|
||||||
|
if (it == it_upper) // No match found
|
||||||
|
return AtIter();
|
||||||
|
|
||||||
|
AtIter obj;
|
||||||
|
obj.p = new AtIterImpl(it, it_upper);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtNode::hasContent() const
|
||||||
|
{
|
||||||
|
if (value.length())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (child_maptype::const_iterator it = children.begin(); it != children.end(); ++it)
|
||||||
|
if (it->second->hasContent())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AtNode::Ptr AtNode::setValue(const wchar_t* value) const
|
||||||
|
{
|
||||||
|
AtNode* newNode = new AtNode();
|
||||||
|
newNode->children = children;
|
||||||
|
newNode->value = value;
|
||||||
|
return AtNode::Ptr(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
const AtNode::Ptr AtNode::setChild(const char* key, const AtNode::Ptr &data) const
|
||||||
|
{
|
||||||
|
AtNode* newNode = new AtNode(this);
|
||||||
|
newNode->children.erase(key);
|
||||||
|
newNode->children.insert(AtNode::child_pairtype(key, data));
|
||||||
|
return AtNode::Ptr(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
const AtNode::Ptr AtNode::addChild(const char* key, const AtNode::Ptr &data) const
|
||||||
|
{
|
||||||
|
AtNode* newNode = new AtNode(this);
|
||||||
|
newNode->children.insert(AtNode::child_pairtype(key, data));
|
||||||
|
return AtNode::Ptr(newNode);
|
||||||
|
}
|
58
source/tools/atlas/AtlasObject/AtlasObjectImpl.h
Normal file
58
source/tools/atlas/AtlasObject/AtlasObjectImpl.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "AtlasObject.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// AtNode is an immutable tree node, with a string and and multimap of children.
|
||||||
|
class AtNode
|
||||||
|
{
|
||||||
|
friend class AtSmartPtr<AtNode>;
|
||||||
|
friend class AtSmartPtr<const AtNode>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef AtSmartPtr<const AtNode> Ptr;
|
||||||
|
|
||||||
|
AtNode() : refcount(0) {}
|
||||||
|
explicit AtNode(const AtNode* n) { *this = *n; refcount = 0; }
|
||||||
|
explicit AtNode(const wchar_t* text) : refcount(0), value(text) {}
|
||||||
|
|
||||||
|
// Create a new AtNode (since AtNodes are immutable, so it's not possible
|
||||||
|
// to just change this one), with the relevant alterations to its content.
|
||||||
|
const AtNode::Ptr setValue(const wchar_t* value) const;
|
||||||
|
const AtNode::Ptr addChild(const char* key, const AtNode::Ptr &data) const;
|
||||||
|
const AtNode::Ptr setChild(const char* key, const AtNode::Ptr &data) const;
|
||||||
|
const AtIter getChild(const char* key) const;
|
||||||
|
|
||||||
|
// Check recursively for any 'value' data
|
||||||
|
bool hasContent() const;
|
||||||
|
|
||||||
|
//private: // (but not actually private, since I'm still too lazy to waste
|
||||||
|
// time with dozens of friends)
|
||||||
|
|
||||||
|
std::wstring value;
|
||||||
|
|
||||||
|
typedef std::multimap<const std::string, const AtNode::Ptr> child_maptype;
|
||||||
|
typedef std::pair<const std::string, const AtNode::Ptr> child_pairtype;
|
||||||
|
|
||||||
|
child_maptype children;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable unsigned int refcount;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of AtIter
|
||||||
|
class AtIterImpl
|
||||||
|
{
|
||||||
|
friend class AtSmartPtr<AtIterImpl>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AtIterImpl() : refcount(0) {}
|
||||||
|
|
||||||
|
AtIterImpl(AtNode::child_maptype::const_iterator it, AtNode::child_maptype::const_iterator up)
|
||||||
|
: refcount(0), iter(it), iter_upperbound(up) {}
|
||||||
|
|
||||||
|
AtNode::child_maptype::const_iterator iter, iter_upperbound;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable unsigned int refcount;
|
||||||
|
};
|
56
source/tools/atlas/AtlasObject/AtlasObjectText.cpp
Normal file
56
source/tools/atlas/AtlasObject/AtlasObjectText.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "AtlasObjectText.h"
|
||||||
|
#include "AtlasObjectImpl.h"
|
||||||
|
#include "AtlasObject.h"
|
||||||
|
|
||||||
|
static std::wstring ConvertRecursive(const AtNode::Ptr obj, bool use_brackets = true)
|
||||||
|
{
|
||||||
|
// Convert (1, ()) into "1"
|
||||||
|
// Convert (3, (d: (...), e: (...))) into "3 (conv(...), conv(...))"
|
||||||
|
// etc
|
||||||
|
// resulting in data-loss [because of the key names], and a rather arbitrary
|
||||||
|
// [alphabetical by key] ordering of children, but at least it's fairly readable
|
||||||
|
|
||||||
|
if (! obj)
|
||||||
|
return L"";
|
||||||
|
|
||||||
|
std::wstring result;
|
||||||
|
|
||||||
|
bool has_value = (obj->value.length() != 0);
|
||||||
|
bool has_children = (obj->children.size() != 0);
|
||||||
|
|
||||||
|
if (has_value && has_children)
|
||||||
|
result = obj->value + L" ";
|
||||||
|
else if (has_value)
|
||||||
|
result = obj->value;
|
||||||
|
// else no value; result = L""
|
||||||
|
|
||||||
|
if (has_children)
|
||||||
|
{
|
||||||
|
if (use_brackets)
|
||||||
|
result += L"(";
|
||||||
|
|
||||||
|
bool first_child = true; // so we can add ", " in appropriate places
|
||||||
|
|
||||||
|
for (AtNode::child_maptype::const_iterator it = obj->children.begin();
|
||||||
|
it != obj->children.end();
|
||||||
|
++it)
|
||||||
|
{
|
||||||
|
if (! first_child)
|
||||||
|
result += L", ";
|
||||||
|
else
|
||||||
|
first_child = false;
|
||||||
|
|
||||||
|
result += ConvertRecursive(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_brackets)
|
||||||
|
result += L")";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring AtlasObject::ConvertToString(const AtObj& obj)
|
||||||
|
{
|
||||||
|
return ConvertRecursive(obj.p, false);
|
||||||
|
}
|
22
source/tools/atlas/AtlasObject/AtlasObjectText.h
Normal file
22
source/tools/atlas/AtlasObject/AtlasObjectText.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Public interface to text-related functions that make use of std::wstring
|
||||||
|
//
|
||||||
|
// (This is done in order to avoid forcing inclusion of all the
|
||||||
|
// STL headers when they're not needed)
|
||||||
|
|
||||||
|
#ifdef new // HACK: to make the STL headers happy with a redefined 'new'
|
||||||
|
# undef new
|
||||||
|
# include <string>
|
||||||
|
# define new new(_NORMAL_BLOCK ,__FILE__, __LINE__)
|
||||||
|
#else
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class AtObj;
|
||||||
|
|
||||||
|
namespace AtlasObject
|
||||||
|
{
|
||||||
|
// Generate a human-readable string representation of the AtObj,
|
||||||
|
// as an easy way of visualising the data (without any horridly ugly
|
||||||
|
// XML junk)
|
||||||
|
std::wstring ConvertToString(const AtObj& obj);
|
||||||
|
}
|
177
source/tools/atlas/AtlasObject/AtlasObjectXML.cpp
Normal file
177
source/tools/atlas/AtlasObject/AtlasObjectXML.cpp
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#include "AtlasObject.h"
|
||||||
|
#include "AtlasObjectImpl.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# ifndef NDEBUG
|
||||||
|
# pragma comment(lib, "xerces-c_2D.lib")
|
||||||
|
# else
|
||||||
|
# pragma comment(lib, "xerces-c_2.lib")
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <xercesc/parsers/XercesDOMParser.hpp>
|
||||||
|
#include <xercesc/dom/DOM.hpp>
|
||||||
|
#include <xercesc/util/PlatformUtils.hpp>
|
||||||
|
#include <xercesc/util/XMLString.hpp>
|
||||||
|
#include <xercesc/framework/LocalFileFormatTarget.hpp>
|
||||||
|
|
||||||
|
XERCES_CPP_NAMESPACE_USE
|
||||||
|
|
||||||
|
static AtSmartPtr<AtNode> ConvertNode(DOMElement* element);
|
||||||
|
|
||||||
|
void AtlasObject::LoadFromXML(AtObj& obj, const wchar_t* filename)
|
||||||
|
{
|
||||||
|
// TODO: Convert wchar_t* to XMLCh* when running under GCC
|
||||||
|
assert(sizeof(wchar_t) == sizeof(XMLCh));
|
||||||
|
|
||||||
|
|
||||||
|
XMLPlatformUtils::Initialize();
|
||||||
|
|
||||||
|
XercesDOMParser* parser = new XercesDOMParser();
|
||||||
|
|
||||||
|
parser->setValidationScheme(XercesDOMParser::Val_Never);
|
||||||
|
parser->setCreateEntityReferenceNodes(false);
|
||||||
|
|
||||||
|
parser->parse((XMLCh*)filename);
|
||||||
|
|
||||||
|
if (parser->getErrorCount() != 0)
|
||||||
|
{
|
||||||
|
assert(! "Error while loading XML - invalid XML data?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMDocument* doc = parser->getDocument();
|
||||||
|
DOMElement* root = doc->getDocumentElement();
|
||||||
|
|
||||||
|
obj.p = ConvertNode(root);
|
||||||
|
|
||||||
|
// TODO: Initialise/terminate properly
|
||||||
|
// XMLPlatformUtils::Terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert from a DOMElement to an AtNode
|
||||||
|
static AtSmartPtr<AtNode> ConvertNode(DOMElement* element)
|
||||||
|
{
|
||||||
|
AtSmartPtr<AtNode> obj (new AtNode());
|
||||||
|
|
||||||
|
// Loop through all child elements
|
||||||
|
DOMNodeList* children = element->getChildNodes();
|
||||||
|
XMLSize_t len = children->getLength();
|
||||||
|
for (XMLSize_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
DOMNode* node = children->item(i);
|
||||||
|
short type = node->getNodeType();
|
||||||
|
|
||||||
|
if (type == DOMNode::ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
// Sub-element.
|
||||||
|
|
||||||
|
// Use its name for the AtNode key
|
||||||
|
char* name = XMLString::transcode(node->getNodeName());
|
||||||
|
const std::string namestr (name);
|
||||||
|
|
||||||
|
// Recursively convert the sub-element, and add it into this node
|
||||||
|
AtNode::child_pairtype n (
|
||||||
|
namestr, ConvertNode((DOMElement*)node)
|
||||||
|
);
|
||||||
|
obj->children.insert(n);
|
||||||
|
|
||||||
|
// Free memory
|
||||||
|
XMLString::release(&name);
|
||||||
|
}
|
||||||
|
else if (type == DOMNode::TEXT_NODE)
|
||||||
|
{
|
||||||
|
// Text inside the element. Append it to the current node's string.
|
||||||
|
|
||||||
|
// TODO: Make this work on GCC, where wchar_t != XMLCh
|
||||||
|
std::wstring value_wstr (node->getNodeValue());
|
||||||
|
obj->value += value_wstr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim whitespace surrounding the string value
|
||||||
|
const std::wstring whitespace = L" \t\r\n";
|
||||||
|
size_t first = obj->value.find_first_not_of(whitespace);
|
||||||
|
if (first == std::wstring::npos)
|
||||||
|
obj->value = L"";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t last = obj->value.find_last_not_of(whitespace);
|
||||||
|
obj->value = obj->value.substr(first, 1+last-first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Build a DOM node from a given AtNode
|
||||||
|
static DOMNode* BuildDOM(DOMDocument* doc, const XMLCh* name, AtNode::Ptr p)
|
||||||
|
{
|
||||||
|
DOMElement* node = doc->createElement(name);
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
// TODO: make this work on GCC
|
||||||
|
node->setTextContent(p->value.c_str());
|
||||||
|
|
||||||
|
XMLCh tempStr[256]; // urgh, nasty fixed-size buffer
|
||||||
|
for (AtNode::child_maptype::const_iterator it = p->children.begin(); it != p->children.end(); ++it)
|
||||||
|
{
|
||||||
|
XMLString::transcode(it->first.c_str(), tempStr, 255);
|
||||||
|
node->appendChild(BuildDOM(doc, tempStr, it->second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtlasObject::SaveToXML(AtObj& obj, const wchar_t* filename)
|
||||||
|
{
|
||||||
|
// TODO: Convert wchar_t* to XMLCh* when running under GCC
|
||||||
|
assert(sizeof(wchar_t) == sizeof(XMLCh));
|
||||||
|
|
||||||
|
|
||||||
|
XMLPlatformUtils::Initialize();
|
||||||
|
|
||||||
|
// Why does it take so much work just to create a DOMWriter? :-(
|
||||||
|
XMLCh tempStr[100];
|
||||||
|
XMLString::transcode("LS", tempStr, 99);
|
||||||
|
DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(tempStr);
|
||||||
|
DOMWriter* writer = ((DOMImplementationLS*)impl)->createDOMWriter();
|
||||||
|
|
||||||
|
if (writer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true))
|
||||||
|
writer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true);
|
||||||
|
|
||||||
|
if (writer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true))
|
||||||
|
writer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
|
||||||
|
|
||||||
|
DOMDocument* doc = impl->createDocument();
|
||||||
|
doc->appendChild(BuildDOM(doc, L"actor", obj.p)); // TODO: this is stupid
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XMLFormatTarget* FormatTarget = new LocalFileFormatTarget((XMLCh*)filename);
|
||||||
|
writer->writeNode(FormatTarget, *doc);
|
||||||
|
delete FormatTarget;
|
||||||
|
}
|
||||||
|
catch (const XMLException& e) {
|
||||||
|
char* message = XMLString::transcode(e.getMessage());
|
||||||
|
assert(! "XML exception - maybe failed while writing the file");
|
||||||
|
XMLString::release(&message);
|
||||||
|
XMLPlatformUtils::Terminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (const DOMException& e) {
|
||||||
|
char* message = XMLString::transcode(e.msg);
|
||||||
|
assert(! "DOM exception");
|
||||||
|
XMLString::release(&message);
|
||||||
|
XMLPlatformUtils::Terminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer->release();
|
||||||
|
|
||||||
|
// XMLPlatformUtils::Terminate();
|
||||||
|
}
|
88
source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.cpp
Normal file
88
source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "ActorEditor.h"
|
||||||
|
|
||||||
|
#include "ActorEditorListCtrl.h"
|
||||||
|
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
|
||||||
|
#include "wx/panel.h"
|
||||||
|
#include "wx/sizer.h"
|
||||||
|
|
||||||
|
ActorEditor::ActorEditor(wxWindow* parent)
|
||||||
|
: AtlasWindow(parent, _("Actor Editor"), wxSize(1024, 450))
|
||||||
|
{
|
||||||
|
wxPanel* mainPanel = new wxPanel(this);
|
||||||
|
|
||||||
|
m_ActorEditorListCtrl = new ActorEditorListCtrl(mainPanel);
|
||||||
|
|
||||||
|
wxBoxSizer* vertSizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
mainPanel->SetSizer(vertSizer);
|
||||||
|
|
||||||
|
wxBoxSizer* topSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
vertSizer->Add(topSizer,
|
||||||
|
wxSizerFlags().Border(wxLEFT|wxRIGHT, 5));
|
||||||
|
|
||||||
|
vertSizer->Add(
|
||||||
|
m_ActorEditorListCtrl,
|
||||||
|
wxSizerFlags().Proportion(1).Expand().Border(wxALL, 10));
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Properties panel:
|
||||||
|
|
||||||
|
wxPanel* propertiesPanel = new wxPanel(mainPanel);
|
||||||
|
topSizer->Add(propertiesPanel, wxSizerFlags().Expand().Border(wxLEFT|wxRIGHT, 5));
|
||||||
|
|
||||||
|
wxSizer* propertiesSizer = new wxStaticBoxSizer(
|
||||||
|
new wxStaticBox(propertiesPanel, wxID_ANY, _("Actor properties")),
|
||||||
|
wxHORIZONTAL);
|
||||||
|
|
||||||
|
propertiesPanel->SetSizer(propertiesSizer);
|
||||||
|
|
||||||
|
|
||||||
|
m_CastShadows = new wxCheckBox(propertiesPanel, wxID_ANY, _("Cast shadow"));
|
||||||
|
propertiesSizer->Add(m_CastShadows, wxSizerFlags().Border(wxALL, 5));
|
||||||
|
|
||||||
|
// TODO: Orientation property.
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Materials box:
|
||||||
|
|
||||||
|
wxPanel* materialsPanel = new wxPanel(mainPanel);
|
||||||
|
topSizer->Add(materialsPanel, wxSizerFlags().Expand().Border(wxLEFT|wxRIGHT, 5));
|
||||||
|
|
||||||
|
wxSizer* materialsSizer = new wxStaticBoxSizer(
|
||||||
|
new wxStaticBox(materialsPanel, wxID_ANY, _("Material")),
|
||||||
|
wxHORIZONTAL);
|
||||||
|
|
||||||
|
materialsPanel->SetSizer(materialsSizer);
|
||||||
|
|
||||||
|
m_Material = new wxTextCtrl(materialsPanel, wxID_ANY, _T(""));
|
||||||
|
materialsSizer->Add(m_Material, wxSizerFlags().Border(wxALL, 2));
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ActorEditor::Import(AtObj& in)
|
||||||
|
{
|
||||||
|
m_ActorEditorListCtrl->Import(in);
|
||||||
|
|
||||||
|
if (in["castshadow"].defined())
|
||||||
|
m_CastShadows->SetValue(true);
|
||||||
|
else
|
||||||
|
m_CastShadows->SetValue(false);
|
||||||
|
|
||||||
|
m_Material->SetValue(in["material"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActorEditor::Export(AtObj& out)
|
||||||
|
{
|
||||||
|
m_ActorEditorListCtrl->Export(out);
|
||||||
|
|
||||||
|
if (m_CastShadows->IsChecked())
|
||||||
|
out.set("castshadow", L"true");
|
||||||
|
|
||||||
|
out.set("material", m_Material->GetValue().c_str());
|
||||||
|
}
|
19
source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.h
Normal file
19
source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "AtlasWindow.h"
|
||||||
|
|
||||||
|
class ActorEditorListCtrl;
|
||||||
|
|
||||||
|
class ActorEditor : public AtlasWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActorEditor(wxWindow* parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Import(AtObj& in);
|
||||||
|
void Export(AtObj& out);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ActorEditorListCtrl* m_ActorEditorListCtrl;
|
||||||
|
|
||||||
|
wxCheckBox* m_CastShadows;
|
||||||
|
wxTextCtrl* m_Material;
|
||||||
|
};
|
@ -0,0 +1,57 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "ActorEditorListCtrl.h"
|
||||||
|
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
#include "FieldEditCtrl.h"
|
||||||
|
|
||||||
|
ActorEditorListCtrl::ActorEditorListCtrl(wxWindow* parent)
|
||||||
|
: DraggableListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxLC_REPORT | wxLC_HRULES | wxLC_VRULES | wxLC_SINGLE_SEL)
|
||||||
|
{
|
||||||
|
AddColumnType(_("Variant"), 100, "name", new FieldEditCtrl_Text());
|
||||||
|
AddColumnType(_("Freq"), 50, "frequency", new FieldEditCtrl_Text());
|
||||||
|
AddColumnType(_("Model"), 160, "mesh", new FieldEditCtrl_Text());
|
||||||
|
AddColumnType(_("Texture"), 160, "texture", new FieldEditCtrl_Text());
|
||||||
|
AddColumnType(_("Animations"), 250, "animations", new FieldEditCtrl_Dialog(_T("AnimListEditor")));
|
||||||
|
AddColumnType(_("Props"), 250, "props", new FieldEditCtrl_Dialog(_T("PropListEditor")));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActorEditorListCtrl::Import(AtObj& in)
|
||||||
|
{
|
||||||
|
DeleteData();
|
||||||
|
|
||||||
|
for (AtIter group = in["group"]; group.defined(); ++group)
|
||||||
|
{
|
||||||
|
for (AtIter variant = group["variant"]; variant.defined(); ++variant)
|
||||||
|
AddRow(variant);
|
||||||
|
|
||||||
|
AtObj blank;
|
||||||
|
AddRow(blank);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActorEditorListCtrl::Export(AtObj& out)
|
||||||
|
{
|
||||||
|
AtObj group;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_ListData.size(); ++i)
|
||||||
|
{
|
||||||
|
if (IsRowBlank((int)i))
|
||||||
|
{
|
||||||
|
if (! group.isNull())
|
||||||
|
out.add("group", group);
|
||||||
|
group = AtObj();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AtObj variant = m_ListData[i];
|
||||||
|
group.add("variant", variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! group.isNull())
|
||||||
|
out.add("group", group);
|
||||||
|
}
|
19
source/tools/atlas/AtlasUI/ActorEditor/ActorEditorListCtrl.h
Normal file
19
source/tools/atlas/AtlasUI/ActorEditor/ActorEditorListCtrl.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "DraggableListCtrl.h"
|
||||||
|
|
||||||
|
#include "IAtlasExporter.h"
|
||||||
|
|
||||||
|
class ActorEditor;
|
||||||
|
|
||||||
|
class ActorEditorListCtrl : public DraggableListCtrl, public IAtlasExporter
|
||||||
|
{
|
||||||
|
friend class ActorEditor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ActorEditorListCtrl(wxWindow* parent);
|
||||||
|
|
||||||
|
void OnUpdate(wxCommandEvent& event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Import(AtObj& in);
|
||||||
|
void Export(AtObj& out);
|
||||||
|
};
|
57
source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.cpp
Normal file
57
source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "AnimListEditor.h"
|
||||||
|
|
||||||
|
#include "FieldEditCtrl.h"
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
IMPLEMENT_DYNAMIC_CLASS(AnimListEditor, AtlasDialog);
|
||||||
|
|
||||||
|
AnimListEditor::AnimListEditor()
|
||||||
|
: AtlasDialog(NULL, _("Animation editor"))
|
||||||
|
{
|
||||||
|
m_MainListBox = new AnimListEditorListCtrl(m_MainPanel);
|
||||||
|
|
||||||
|
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
sizer->Add(m_MainListBox,
|
||||||
|
wxSizerFlags().Proportion(1).Expand().Border(wxALL, 5));
|
||||||
|
|
||||||
|
m_MainPanel->SetSizer(sizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimListEditor::Import(AtObj& in)
|
||||||
|
{
|
||||||
|
m_MainListBox->Import(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimListEditor::Export(AtObj& out)
|
||||||
|
{
|
||||||
|
m_MainListBox->Export(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
AnimListEditorListCtrl::AnimListEditorListCtrl(wxWindow* parent)
|
||||||
|
: DraggableListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxLC_REPORT | wxLC_HRULES | wxLC_VRULES | wxLC_SINGLE_SEL)
|
||||||
|
{
|
||||||
|
AddColumnType(_("Anim name"), 100, "name", new FieldEditCtrl_Text());
|
||||||
|
AddColumnType(_("File"), 200, "file", new FieldEditCtrl_Text());
|
||||||
|
AddColumnType(_("Speed"), 50, "speed", new FieldEditCtrl_Text());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimListEditorListCtrl::Import(AtObj& in)
|
||||||
|
{
|
||||||
|
for (AtIter prop = in["animation"]; prop.defined(); ++prop)
|
||||||
|
AddRow(prop);
|
||||||
|
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimListEditorListCtrl::Export(AtObj& out)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_ListData.size(); ++i)
|
||||||
|
out.add("animation", m_ListData[i]);
|
||||||
|
}
|
38
source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.h
Normal file
38
source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "AtlasDialog.h"
|
||||||
|
|
||||||
|
#include "DraggableListCtrl.h"
|
||||||
|
#include "IAtlasExporter.h"
|
||||||
|
|
||||||
|
class AnimListEditorListCtrl;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class AnimListEditor : public AtlasDialog
|
||||||
|
{
|
||||||
|
DECLARE_DYNAMIC_CLASS(AnimListEditor);
|
||||||
|
|
||||||
|
public:
|
||||||
|
AnimListEditor();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Import(AtObj& in);
|
||||||
|
void Export(AtObj& out);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AnimListEditorListCtrl* m_MainListBox;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class AnimListEditorListCtrl : public DraggableListCtrl, public IAtlasExporter
|
||||||
|
{
|
||||||
|
friend class AnimListEditor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AnimListEditorListCtrl(wxWindow* parent);
|
||||||
|
|
||||||
|
void OnUpdate(wxCommandEvent& event);
|
||||||
|
|
||||||
|
void Import(AtObj& in);
|
||||||
|
void Export(AtObj& out);
|
||||||
|
};
|
56
source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.cpp
Normal file
56
source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "PropListEditor.h"
|
||||||
|
|
||||||
|
#include "FieldEditCtrl.h"
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
IMPLEMENT_DYNAMIC_CLASS(PropListEditor, AtlasDialog);
|
||||||
|
|
||||||
|
PropListEditor::PropListEditor()
|
||||||
|
: AtlasDialog(NULL, _("Prop editor"))
|
||||||
|
{
|
||||||
|
m_MainListBox = new PropListEditorListCtrl(m_MainPanel);
|
||||||
|
|
||||||
|
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
sizer->Add(m_MainListBox,
|
||||||
|
wxSizerFlags().Proportion(1).Expand().Border(wxALL, 5));
|
||||||
|
|
||||||
|
m_MainPanel->SetSizer(sizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropListEditor::Import(AtObj& in)
|
||||||
|
{
|
||||||
|
m_MainListBox->Import(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropListEditor::Export(AtObj& out)
|
||||||
|
{
|
||||||
|
m_MainListBox->Export(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
PropListEditorListCtrl::PropListEditorListCtrl(wxWindow* parent)
|
||||||
|
: DraggableListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxLC_REPORT | wxLC_HRULES | wxLC_VRULES | wxLC_SINGLE_SEL)
|
||||||
|
{
|
||||||
|
AddColumnType(_("Attachment point"), 100, "attachpoint", new FieldEditCtrl_Text());
|
||||||
|
AddColumnType(_("Prop model"), 200, "model", new FieldEditCtrl_Text());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropListEditorListCtrl::Import(AtObj& in)
|
||||||
|
{
|
||||||
|
for (AtIter prop = in["prop"]; prop.defined(); ++prop)
|
||||||
|
AddRow(prop);
|
||||||
|
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropListEditorListCtrl::Export(AtObj& out)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_ListData.size(); ++i)
|
||||||
|
out.add("prop", m_ListData[i]);
|
||||||
|
}
|
38
source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.h
Normal file
38
source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "AtlasDialog.h"
|
||||||
|
|
||||||
|
#include "DraggableListCtrl.h"
|
||||||
|
#include "IAtlasExporter.h"
|
||||||
|
|
||||||
|
class PropListEditorListCtrl;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class PropListEditor : public AtlasDialog
|
||||||
|
{
|
||||||
|
DECLARE_DYNAMIC_CLASS(PropListEditor);
|
||||||
|
|
||||||
|
public:
|
||||||
|
PropListEditor();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Import(AtObj& in);
|
||||||
|
void Export(AtObj& out);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PropListEditorListCtrl* m_MainListBox;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class PropListEditorListCtrl : public DraggableListCtrl, public IAtlasExporter
|
||||||
|
{
|
||||||
|
friend class PropListEditor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PropListEditorListCtrl(wxWindow* parent);
|
||||||
|
|
||||||
|
void OnUpdate(wxCommandEvent& event);
|
||||||
|
|
||||||
|
void Import(AtObj& in);
|
||||||
|
void Export(AtObj& out);
|
||||||
|
};
|
270
source/tools/atlas/AtlasUI/AtlasUI.vcproj
Normal file
270
source/tools/atlas/AtlasUI/AtlasUI.vcproj
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.10"
|
||||||
|
Name="AtlasUI"
|
||||||
|
ProjectGUID="{E99BA969-D540-4F23-822E-37C499E8F704}"
|
||||||
|
Keyword="Win32Proj">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="Debug"
|
||||||
|
IntermediateDirectory="Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories=".;..;.\General;.\CustomControls\EditableListCtrl;.\CustomControls\DraggableListCtrl;.\CustomControls\Windows;.\Misc;E:\wx\wxWidgets\include;E:\wx\wxWidgets\include\msvc"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
|
||||||
|
MinimalRebuild="TRUE"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="3"
|
||||||
|
WarningLevel="4"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="4"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="comctl32.lib rpcrt4.lib"
|
||||||
|
OutputFile="$(OutDir)/actored.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
AdditionalLibraryDirectories="E:\wx\wxWidgets\lib\vc_lib;E:\0ad\svnc\trunk\libraries\xerces\lib"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile="$(OutDir)/actored.pdb"
|
||||||
|
SubSystem="2"
|
||||||
|
TargetMachine="1"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="Release"
|
||||||
|
IntermediateDirectory="Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="1"
|
||||||
|
AdditionalIncludeDirectories=".;..;.\General;.\CustomControls\EditableListCtrl;.\CustomControls\DraggableListCtrl;.\CustomControls\Windows;.\Misc;E:\wx\wxWidgets\include;E:\wx\wxWidgets\include\msvc"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
UsePrecompiledHeader="3"
|
||||||
|
WarningLevel="4"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="3"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="comctl32.lib rpcrt4.lib"
|
||||||
|
OutputFile="$(OutDir)/actored.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
AdditionalLibraryDirectories="E:\wx\wxWidgets\lib\vc_lib;E:\0ad\svnc\trunk\libraries\xerces\lib"
|
||||||
|
GenerateDebugInformation="FALSE"
|
||||||
|
SubSystem="2"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
OptimizeForWindows98="1"
|
||||||
|
TargetMachine="1"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||||
|
<Filter
|
||||||
|
Name="General"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath=".\General\AtlasWindowCommand.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\General\AtlasWindowCommand.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\General\AtlasWindowCommandProc.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\General\AtlasWindowCommandProc.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\General\IAtlasExporter.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="CustomControls"
|
||||||
|
Filter="">
|
||||||
|
<Filter
|
||||||
|
Name="EditableListCtrl"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\EditableListCtrl\EditableListCtrl.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\EditableListCtrl\EditableListCtrl.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\EditableListCtrl\FieldEditCtrl.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\EditableListCtrl\FieldEditCtrl.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\EditableListCtrl\ListCtrlValidator.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\EditableListCtrl\ListCtrlValidator.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\EditableListCtrl\QuickTextCtrl.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\EditableListCtrl\QuickTextCtrl.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="DraggableListCtrl"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\DraggableListCtrl\DraggableListCtrl.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\DraggableListCtrl\DraggableListCtrl.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\DraggableListCtrl\DraggableListCtrlCommands.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\DraggableListCtrl\DraggableListCtrlCommands.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Windows"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\Windows\AtlasDialog.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\Windows\AtlasDialog.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\Windows\AtlasWindow.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\CustomControls\Windows\AtlasWindow.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="ActorEditor"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath=".\ActorEditor\ActorEditor.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ActorEditor\ActorEditor.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ActorEditor\ActorEditorListCtrl.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ActorEditor\ActorEditorListCtrl.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ActorEditor\AnimListEditor.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ActorEditor\AnimListEditor.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ActorEditor\PropListEditor.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ActorEditor\PropListEditor.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Misc"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath=".\Misc\actored.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Misc\actored.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Misc\stdafx.cpp">
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Misc\stdafx.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath=".\TODO.txt">
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
@ -0,0 +1,143 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "DraggableListCtrl.h"
|
||||||
|
|
||||||
|
#include "AtlasWindowCommandProc.h"
|
||||||
|
#include "DraggableListCtrlCommands.h"
|
||||||
|
|
||||||
|
//DEFINE_EVENT_TYPE(wxEVT_LISTCTRL_UPDATED);
|
||||||
|
|
||||||
|
const int ScrollSpeed = 8; // when dragging off the top or bottom of the control
|
||||||
|
|
||||||
|
DraggableListCtrl::DraggableListCtrl(wxWindow *parent,
|
||||||
|
wxWindowID id,
|
||||||
|
const wxPoint& pos,
|
||||||
|
const wxSize& size,
|
||||||
|
long style,
|
||||||
|
const wxValidator& validator,
|
||||||
|
const wxString& name)
|
||||||
|
: EditableListCtrl(parent, id, pos, size, style, validator, name)
|
||||||
|
, m_DragSource(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// * Dragging of multiple selections?
|
||||||
|
|
||||||
|
void DraggableListCtrl::OnBeginDrag(wxListEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
CaptureMouse();
|
||||||
|
SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DraggableListCtrl::OnEndDrag()
|
||||||
|
{
|
||||||
|
AtlasWindowCommandProc* commandProc = AtlasWindowCommandProc::GetFromParentFrame(this);
|
||||||
|
commandProc->FinaliseLastCommand();
|
||||||
|
SetSelection(m_DragSource);
|
||||||
|
//commandProc->Store(new DragCommand(this, m_InitialDragSource, m_DragSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DraggableListCtrl::OnItemSelected(wxListEvent& event)
|
||||||
|
{
|
||||||
|
// Don't respond while in drag-mode - only the initial selection
|
||||||
|
// (when starting the drag operation) should be handled
|
||||||
|
if (! HasCapture())
|
||||||
|
{
|
||||||
|
// Remember which item is being dragged
|
||||||
|
m_DragSource = event.GetIndex();
|
||||||
|
|
||||||
|
// Make sure this listctrl is in focus
|
||||||
|
SetFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DraggableListCtrl::OnMouseCaptureChanged(wxMouseCaptureChangedEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
OnEndDrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DraggableListCtrl::OnMouseEvent(wxMouseEvent& event)
|
||||||
|
{
|
||||||
|
// Only care when in drag-mode
|
||||||
|
if (! HasCapture())
|
||||||
|
{
|
||||||
|
event.Skip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.LeftUp())
|
||||||
|
{
|
||||||
|
// Finished dragging; stop responding to mouse motion
|
||||||
|
ReleaseMouse();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (event.Dragging())
|
||||||
|
{
|
||||||
|
// Find which item the mouse is now over
|
||||||
|
int flags;
|
||||||
|
long dragTarget = HitTest(event.GetPosition(), flags);
|
||||||
|
|
||||||
|
if (dragTarget == wxNOT_FOUND)
|
||||||
|
{
|
||||||
|
// Not over an item. Scroll the view up/down if the mouse is
|
||||||
|
// outside the listctrl.
|
||||||
|
if (flags & wxLIST_HITTEST_ABOVE)
|
||||||
|
ScrollList(0, -ScrollSpeed);
|
||||||
|
else if (flags & wxLIST_HITTEST_BELOW)
|
||||||
|
ScrollList(0, ScrollSpeed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (flags & wxLIST_HITTEST_ONITEM && dragTarget != m_DragSource)
|
||||||
|
{
|
||||||
|
// Move the source item to the location under the mouse
|
||||||
|
|
||||||
|
AtlasWindowCommandProc* commandProc = AtlasWindowCommandProc::GetFromParentFrame(this);
|
||||||
|
commandProc->Submit(new DragCommand(this, m_DragSource, dragTarget));
|
||||||
|
|
||||||
|
// and remember that the source item is now in a different place
|
||||||
|
m_DragSource = dragTarget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
// Some other kind of event which we're not interested in - ignore it
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DraggableListCtrl::OnChar(wxKeyEvent& event)
|
||||||
|
{
|
||||||
|
// Don't respond to the keyboard if the user is dragging things (else
|
||||||
|
// the undo system might get slightly confused)
|
||||||
|
if (HasCapture())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.GetKeyCode() == WXK_DELETE)
|
||||||
|
{
|
||||||
|
long item = GetNextItem(-1,
|
||||||
|
wxLIST_NEXT_ALL,
|
||||||
|
wxLIST_STATE_SELECTED);
|
||||||
|
|
||||||
|
if (item != -1)
|
||||||
|
{
|
||||||
|
AtlasWindowCommandProc::GetFromParentFrame(this)->Submit(
|
||||||
|
new DeleteCommand(this, item)
|
||||||
|
);
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BEGIN_EVENT_TABLE(DraggableListCtrl, EditableListCtrl)
|
||||||
|
EVT_LIST_BEGIN_DRAG(wxID_ANY, DraggableListCtrl::OnBeginDrag)
|
||||||
|
EVT_LIST_ITEM_SELECTED(wxID_ANY, DraggableListCtrl::OnItemSelected)
|
||||||
|
EVT_MOTION(DraggableListCtrl::OnMouseEvent)
|
||||||
|
EVT_LEFT_UP(DraggableListCtrl::OnMouseEvent)
|
||||||
|
EVT_CHAR(DraggableListCtrl::OnChar)
|
||||||
|
EVT_MOUSE_CAPTURE_CHANGED(DraggableListCtrl::OnMouseCaptureChanged)
|
||||||
|
END_EVENT_TABLE()
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
DraggableListCtrl
|
||||||
|
|
||||||
|
Based on wxListCtrl, but items can be reordered by dragging them around.
|
||||||
|
Use just like a normal listctrl.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "EditableListCtrl.h"
|
||||||
|
|
||||||
|
class DragCommand;
|
||||||
|
|
||||||
|
class DraggableListCtrl : public EditableListCtrl
|
||||||
|
{
|
||||||
|
friend class DragCommand;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DraggableListCtrl(wxWindow *parent,
|
||||||
|
wxWindowID id = wxID_ANY,
|
||||||
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
|
const wxSize& size = wxDefaultSize,
|
||||||
|
long style = wxLC_ICON,
|
||||||
|
const wxValidator& validator = wxDefaultValidator,
|
||||||
|
const wxString& name = wxListCtrlNameStr);
|
||||||
|
|
||||||
|
void OnBeginDrag(wxListEvent& event);
|
||||||
|
void OnEndDrag();
|
||||||
|
|
||||||
|
void OnItemSelected(wxListEvent& event);
|
||||||
|
void OnMouseEvent(wxMouseEvent& event);
|
||||||
|
void OnChar(wxKeyEvent& event);
|
||||||
|
void OnMouseCaptureChanged(wxMouseCaptureChangedEvent& event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
long m_DragSource;
|
||||||
|
|
||||||
|
DECLARE_EVENT_TABLE();
|
||||||
|
};
|
@ -0,0 +1,109 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "DraggableListCtrlCommands.h"
|
||||||
|
|
||||||
|
#include "DraggableListCtrl.h"
|
||||||
|
#include "EditableListCtrl.h"
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS(DragCommand, AtlasWindowCommand);
|
||||||
|
|
||||||
|
DragCommand::DragCommand(DraggableListCtrl* ctrl, long src, long tgt)
|
||||||
|
: AtlasWindowCommand(true, _("Drag")), m_Ctrl(ctrl), m_Src(src), m_Tgt(tgt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DragCommand::Do()
|
||||||
|
{
|
||||||
|
wxASSERT(m_Tgt >= 0 && m_Src >= 0);
|
||||||
|
|
||||||
|
m_Ctrl->CloneListData(m_OldData);
|
||||||
|
|
||||||
|
m_Ctrl->MakeSizeAtLeast(m_Src+1);
|
||||||
|
m_Ctrl->MakeSizeAtLeast(m_Tgt+1);
|
||||||
|
|
||||||
|
// data[src] will be inserted just before data[tgt].
|
||||||
|
// If tgt>src, (src+1)..tgt will be shifted down by 1.
|
||||||
|
// If tgt<src, tgt..(src-1) will be shifted up by 1.
|
||||||
|
|
||||||
|
AtObj srcData = m_Ctrl->m_ListData.at(m_Src);
|
||||||
|
|
||||||
|
if (m_Tgt > m_Src)
|
||||||
|
std::copy(
|
||||||
|
m_Ctrl->m_ListData.begin()+m_Src+1,
|
||||||
|
m_Ctrl->m_ListData.begin()+m_Tgt+1,
|
||||||
|
m_Ctrl->m_ListData.begin()+m_Src);
|
||||||
|
else if (m_Tgt < m_Src)
|
||||||
|
std::copy_backward(
|
||||||
|
m_Ctrl->m_ListData.begin()+m_Tgt,
|
||||||
|
m_Ctrl->m_ListData.begin()+m_Src,
|
||||||
|
m_Ctrl->m_ListData.begin()+m_Src+1);
|
||||||
|
else // m_Tgt == m_Src
|
||||||
|
; // do nothing - this item was just dragged onto itself
|
||||||
|
|
||||||
|
m_Ctrl->m_ListData.at(m_Tgt) = srcData;
|
||||||
|
|
||||||
|
m_Ctrl->UpdateDisplay();
|
||||||
|
m_Ctrl->SetSelection(m_Tgt);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DragCommand::Undo()
|
||||||
|
{
|
||||||
|
m_Ctrl->SetListData(m_OldData);
|
||||||
|
|
||||||
|
m_Ctrl->UpdateDisplay();
|
||||||
|
m_Ctrl->SetSelection(m_Src);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DragCommand::Merge(AtlasWindowCommand* command)
|
||||||
|
{
|
||||||
|
DragCommand* nextCommand = wxDynamicCast(command, DragCommand);
|
||||||
|
|
||||||
|
if (! nextCommand)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (nextCommand->m_Src != m_Tgt)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Tgt = nextCommand->m_Tgt;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DeleteCommand::DeleteCommand(DraggableListCtrl* ctrl, long itemID)
|
||||||
|
: wxCommand(true, _("Delete")), m_Ctrl(ctrl), m_ItemID(itemID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeleteCommand::Do()
|
||||||
|
{
|
||||||
|
wxASSERT(m_ItemID >= 0);
|
||||||
|
|
||||||
|
// If we're asked to delete one of the blank rows off the end of the
|
||||||
|
// list, don't do anything
|
||||||
|
if (m_ItemID >= (long)m_Ctrl->m_ListData.size())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
m_Ctrl->CloneListData(m_OldData);
|
||||||
|
|
||||||
|
m_Ctrl->m_ListData.erase(m_Ctrl->m_ListData.begin()+m_ItemID);
|
||||||
|
|
||||||
|
m_Ctrl->UpdateDisplay();
|
||||||
|
m_Ctrl->SetSelection(m_ItemID);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeleteCommand::Undo()
|
||||||
|
{
|
||||||
|
m_Ctrl->SetListData(m_OldData);
|
||||||
|
|
||||||
|
m_Ctrl->UpdateDisplay();
|
||||||
|
m_Ctrl->SetSelection(m_ItemID);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
#include "AtlasWindowCommand.h"
|
||||||
|
|
||||||
|
#include "wx/arrstr.h"
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
//#include "RefcntPtr.h"
|
||||||
|
|
||||||
|
class DraggableListCtrl;
|
||||||
|
|
||||||
|
class DragCommand : public AtlasWindowCommand
|
||||||
|
{
|
||||||
|
DECLARE_CLASS(DragCommand)
|
||||||
|
|
||||||
|
public:
|
||||||
|
DragCommand(DraggableListCtrl* ctrl, long src, long tgt);
|
||||||
|
bool Do();
|
||||||
|
bool Undo();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Merge(AtlasWindowCommand* command);
|
||||||
|
|
||||||
|
DraggableListCtrl* m_Ctrl;
|
||||||
|
long m_Src, m_Tgt;
|
||||||
|
|
||||||
|
std::vector<AtObj> m_OldData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteCommand : public wxCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DeleteCommand(DraggableListCtrl* ctrl, long itemID);
|
||||||
|
bool Do();
|
||||||
|
bool Undo();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DraggableListCtrl* m_Ctrl;
|
||||||
|
//wxArrayString m_Texts;
|
||||||
|
long m_ItemID;
|
||||||
|
//RefcntPtr<AtObj> m_ItemData;
|
||||||
|
std::vector<AtObj> m_OldData;
|
||||||
|
};
|
@ -0,0 +1,238 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "EditableListCtrl.h"
|
||||||
|
|
||||||
|
#include "FieldEditCtrl.h"
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
#include "AtlasObject/AtlasObjectText.h"
|
||||||
|
|
||||||
|
const int BlanksAtEnd = 2;
|
||||||
|
|
||||||
|
EditableListCtrl::EditableListCtrl(wxWindow *parent,
|
||||||
|
wxWindowID id,
|
||||||
|
const wxPoint& pos,
|
||||||
|
const wxSize& size,
|
||||||
|
long style,
|
||||||
|
const wxValidator& validator,
|
||||||
|
const wxString& name)
|
||||||
|
: wxListCtrl(parent, id, pos, size, style | wxLC_VIRTUAL, validator, name)
|
||||||
|
{
|
||||||
|
wxASSERT_MSG(style & wxLC_REPORT, _T("EditableListCtrl must be LC_REPORT"));
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditableListCtrl::~EditableListCtrl()
|
||||||
|
{
|
||||||
|
size_t count = m_ColumnTypes.size();
|
||||||
|
for (size_t n = 0; n < count; ++n)
|
||||||
|
delete (FieldEditCtrl*)m_ColumnTypes[n].ctrl;
|
||||||
|
|
||||||
|
m_ColumnTypes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::AddColumnType(const wxString& title, int width, const char* objectkey, FieldEditCtrl* ctrl)
|
||||||
|
{
|
||||||
|
int n = GetColumnCount();
|
||||||
|
wxASSERT(m_ColumnTypes.size() == (size_t) n); // check internal consistency
|
||||||
|
|
||||||
|
InsertColumn(n, title, wxLIST_FORMAT_LEFT, width);
|
||||||
|
|
||||||
|
m_ColumnTypes.push_back(ColumnData(objectkey, ctrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EditableListCtrl::OnMouseEvent(wxMouseEvent& event)
|
||||||
|
{
|
||||||
|
// Double-clicking on a cell lets the user edit it. The editing method
|
||||||
|
// depends on what column the cell is in.
|
||||||
|
|
||||||
|
if (event.LeftDClick())
|
||||||
|
{
|
||||||
|
// Work out what cell was clicked on:
|
||||||
|
|
||||||
|
wxPoint pt = event.GetPosition();
|
||||||
|
int col = GetColumnAtPosition(pt);
|
||||||
|
|
||||||
|
wxCHECK2(col >= 0 && col < (int)m_ColumnTypes.size(), return);
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
long row = HitTest(pt, flags);
|
||||||
|
|
||||||
|
if (row != wxNOT_FOUND && (flags & wxLIST_HITTEST_ONITEM))
|
||||||
|
{
|
||||||
|
// Calculate the exact positioning of the clicked cell
|
||||||
|
wxRect rect;
|
||||||
|
GetCellRect(row, col, rect);
|
||||||
|
|
||||||
|
// Execute the appropriate FieldEditCtrl
|
||||||
|
FieldEditCtrl* editor = (FieldEditCtrl*)m_ColumnTypes[col].ctrl;
|
||||||
|
editor->StartEdit(this, rect, row, col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int EditableListCtrl::GetColumnAtPosition(wxPoint& pos)
|
||||||
|
{
|
||||||
|
// Find the column which pos is in.
|
||||||
|
|
||||||
|
// Get the origin of the table, in case it's scrolled horizontally
|
||||||
|
wxRect rect;
|
||||||
|
GetItemRect(0, rect);
|
||||||
|
int x = rect.GetX();
|
||||||
|
|
||||||
|
// Loop through each column
|
||||||
|
int numCols = GetColumnCount();
|
||||||
|
for (int i = 0; i < numCols; ++i)
|
||||||
|
{
|
||||||
|
// Calculate the position of this column's right-hand edge
|
||||||
|
x += GetColumnWidth(i);
|
||||||
|
|
||||||
|
// Test if pos was within this column (and assume it wasn't in an earlier one)
|
||||||
|
if (pos.x <= x)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Point is outside the table's right edge
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::GetCellRect(long row, int col, wxRect& rect)
|
||||||
|
{
|
||||||
|
wxASSERT(col >= 0 && col < GetColumnCount());
|
||||||
|
wxASSERT(row >= 0 && row < GetItemCount());
|
||||||
|
|
||||||
|
GetItemRect(row, rect);
|
||||||
|
|
||||||
|
for (int i = 0; i < col; ++i)
|
||||||
|
rect.x += GetColumnWidth(i);
|
||||||
|
|
||||||
|
rect.width = GetColumnWidth(col);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool EditableListCtrl::IsRowBlank(int n)
|
||||||
|
{
|
||||||
|
return m_ListData[n].isContentless();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::TrimBlankEnds()
|
||||||
|
{
|
||||||
|
while (m_ListData.size() && m_ListData.back().isNull())
|
||||||
|
m_ListData.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EditableListCtrl::SetSelection(long item)
|
||||||
|
{
|
||||||
|
SetItemState(item, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
long EditableListCtrl::GetSelection()
|
||||||
|
{
|
||||||
|
for (long item = 0; item < GetItemCount(); ++item)
|
||||||
|
if (GetItemState(item, wxLIST_STATE_SELECTED))
|
||||||
|
return item;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EditableListCtrl::MakeSizeAtLeast(int n)
|
||||||
|
{
|
||||||
|
if ((int)m_ListData.size() < n)
|
||||||
|
m_ListData.resize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::AddRow(AtObj& obj)
|
||||||
|
{
|
||||||
|
m_ListData.push_back(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::AddRow(AtIter& iter)
|
||||||
|
{
|
||||||
|
AtObj obj = iter;
|
||||||
|
AddRow(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::UpdateDisplay()
|
||||||
|
{
|
||||||
|
TrimBlankEnds();
|
||||||
|
SetItemCount((int)m_ListData.size() + BlanksAtEnd);
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EditableListCtrl::CloneListData(std::vector<AtObj>& out)
|
||||||
|
{
|
||||||
|
out = m_ListData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::SetListData(std::vector<AtObj>& in)
|
||||||
|
{
|
||||||
|
m_ListData = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::DeleteData()
|
||||||
|
{
|
||||||
|
m_ListData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString EditableListCtrl::GetCellString(long item, long column) const
|
||||||
|
{
|
||||||
|
wxCHECK(item >= 0 && column >= 0 && column < (int)m_ColumnTypes.size(), _T(""));
|
||||||
|
|
||||||
|
if (item >= (int)m_ListData.size())
|
||||||
|
return _T("");
|
||||||
|
|
||||||
|
AtObj cell = m_ListData[item][m_ColumnTypes[column].key];
|
||||||
|
return AtlasObject::ConvertToString(cell).c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
AtObj EditableListCtrl::GetCellObject(long item, long column) const
|
||||||
|
{
|
||||||
|
wxCHECK(item >= 0 && column >= 0 && column < (int)m_ColumnTypes.size(), AtObj());
|
||||||
|
|
||||||
|
if (item >= (int)m_ListData.size())
|
||||||
|
return AtObj();
|
||||||
|
|
||||||
|
return m_ListData[item][m_ColumnTypes[column].key];
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::SetCellString(long item, long column, wxString& str)
|
||||||
|
{
|
||||||
|
wxCHECK(item >= 0 && column >= 0 && column < (int)m_ColumnTypes.size(), );
|
||||||
|
MakeSizeAtLeast(item+1);
|
||||||
|
m_ListData[item].set(m_ColumnTypes[column].key, str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableListCtrl::SetCellObject(long item, long column, AtObj& obj)
|
||||||
|
{
|
||||||
|
wxCHECK(item >= 0 && column >= 0 && column < (int)m_ColumnTypes.size(), );
|
||||||
|
MakeSizeAtLeast(item+1);
|
||||||
|
m_ListData[item].set(m_ColumnTypes[column].key, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString EditableListCtrl::OnGetItemText(long item, long column) const
|
||||||
|
{
|
||||||
|
return GetCellString(item, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxListItemAttr* EditableListCtrl::OnGetItemAttr(long WXUNUSED(item)) const
|
||||||
|
{
|
||||||
|
// if (item > (int)m_ListData.size()-BlanksAtEnd)
|
||||||
|
// {
|
||||||
|
// static wxListItemAttr attr;
|
||||||
|
// static int attr_init = 0;
|
||||||
|
// if (attr_init++ == 0)
|
||||||
|
// attr.SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT));
|
||||||
|
//
|
||||||
|
// return &attr;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BEGIN_EVENT_TABLE(EditableListCtrl, wxListCtrl)
|
||||||
|
EVT_LEFT_DCLICK(EditableListCtrl::OnMouseEvent)
|
||||||
|
END_EVENT_TABLE()
|
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef EDITABLELISTCTRL_H__
|
||||||
|
#define EDITABLELISTCTRL_H__
|
||||||
|
|
||||||
|
#include "wx/listctrl.h"
|
||||||
|
#include "wx/arrstr.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class FieldEditCtrl;
|
||||||
|
class AtObj;
|
||||||
|
class AtIter;
|
||||||
|
|
||||||
|
class EditableListCtrl : public wxListCtrl
|
||||||
|
{
|
||||||
|
friend class DeleteCommand;
|
||||||
|
friend class DragCommand;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EditableListCtrl(wxWindow *parent,
|
||||||
|
wxWindowID id = wxID_ANY,
|
||||||
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
|
const wxSize& size = wxDefaultSize,
|
||||||
|
long style = wxLC_ICON,
|
||||||
|
const wxValidator& validator = wxDefaultValidator,
|
||||||
|
const wxString& name = wxListCtrlNameStr);
|
||||||
|
|
||||||
|
~EditableListCtrl();
|
||||||
|
|
||||||
|
void OnMouseEvent(wxMouseEvent& event);
|
||||||
|
|
||||||
|
void MakeSizeAtLeast(int n);
|
||||||
|
|
||||||
|
long GetSelection();
|
||||||
|
void SetSelection(long item);
|
||||||
|
|
||||||
|
void UpdateDisplay();
|
||||||
|
|
||||||
|
wxString GetCellString(long item, long column) const;
|
||||||
|
AtObj GetCellObject(long item, long column) const;
|
||||||
|
void SetCellString(long item, long column, wxString& str);
|
||||||
|
void SetCellObject(long item, long column, AtObj& obj);
|
||||||
|
|
||||||
|
struct ColumnData
|
||||||
|
{
|
||||||
|
ColumnData(const char* k, const FieldEditCtrl* c) : key(k), ctrl(c) {}
|
||||||
|
const char* key;
|
||||||
|
const FieldEditCtrl* ctrl;
|
||||||
|
};
|
||||||
|
std::vector<ColumnData> m_ColumnTypes;
|
||||||
|
|
||||||
|
void CloneListData(std::vector<AtObj>& out);
|
||||||
|
void SetListData(std::vector<AtObj>& in);
|
||||||
|
|
||||||
|
void DeleteData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int GetColumnAtPosition(wxPoint& pos);
|
||||||
|
void GetCellRect(long row, int col, wxRect& rect);
|
||||||
|
|
||||||
|
void TrimBlankEnds();
|
||||||
|
|
||||||
|
wxString OnGetItemText(long item, long column) const;
|
||||||
|
wxListItemAttr* OnGetItemAttr(long item) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::vector<AtObj> m_ListData;
|
||||||
|
|
||||||
|
// objectkey must remain in existence for as long as this list control
|
||||||
|
// exists (so you really don't want to be dynamically allocating it;
|
||||||
|
// just use static constant strings)
|
||||||
|
void AddColumnType(const wxString& title, int width, const char* objectkey, FieldEditCtrl* ctrl);
|
||||||
|
|
||||||
|
void AddRow(AtObj& obj);
|
||||||
|
void AddRow(AtIter& iter);
|
||||||
|
|
||||||
|
bool IsRowBlank(int n);
|
||||||
|
|
||||||
|
DECLARE_EVENT_TABLE();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EDITABLELISTCTRL_H__
|
@ -0,0 +1,92 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "FieldEditCtrl.h"
|
||||||
|
|
||||||
|
#include "ListCtrlValidator.h"
|
||||||
|
#include "QuickTextCtrl.h"
|
||||||
|
#include "AtlasDialog.h"
|
||||||
|
#include "EditableListCtrl.h"
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
#include "AtlasObject/AtlasObjectText.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
void FieldEditCtrl_Text::StartEdit(wxWindow* parent, wxRect rect, long row, int col)
|
||||||
|
{
|
||||||
|
new QuickTextCtrl(parent, rect, ListCtrlValidator((EditableListCtrl*)parent, row, col));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class EditCommand_Dialog : public wxCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EditCommand_Dialog(EditableListCtrl* ctrl, long row, int col, AtObj& newData)
|
||||||
|
: wxCommand(true, _("Edit")), m_Ctrl(ctrl), m_Row(row), m_Col(col), m_NewData(newData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Do()
|
||||||
|
{
|
||||||
|
m_Ctrl->CloneListData(m_OldData);
|
||||||
|
|
||||||
|
m_Ctrl->MakeSizeAtLeast(m_Row+1);
|
||||||
|
|
||||||
|
m_Ctrl->SetCellObject(m_Row, m_Col, m_NewData);
|
||||||
|
|
||||||
|
m_Ctrl->UpdateDisplay();
|
||||||
|
m_Ctrl->SetSelection(m_Row);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Undo()
|
||||||
|
{
|
||||||
|
m_Ctrl->SetListData(m_OldData);
|
||||||
|
|
||||||
|
m_Ctrl->UpdateDisplay();
|
||||||
|
m_Ctrl->SetSelection(m_Row);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EditableListCtrl* m_Ctrl;
|
||||||
|
long m_Row;
|
||||||
|
int m_Col;
|
||||||
|
AtObj m_NewData;
|
||||||
|
std::vector<AtObj> m_OldData;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
FieldEditCtrl_Dialog::FieldEditCtrl_Dialog(wxString dialogType)
|
||||||
|
: m_DialogType(dialogType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldEditCtrl_Dialog::StartEdit(wxWindow* parent, wxRect WXUNUSED(rect), long row, int col)
|
||||||
|
{
|
||||||
|
AtlasDialog* dialog = wxDynamicCast(wxCreateDynamicObject(m_DialogType), AtlasDialog);
|
||||||
|
wxCHECK2(dialog, return);
|
||||||
|
|
||||||
|
dialog->SetParent(parent);
|
||||||
|
|
||||||
|
EditableListCtrl* editCtrl = (EditableListCtrl*)parent;
|
||||||
|
|
||||||
|
AtObj in (editCtrl->GetCellObject(row, col));
|
||||||
|
dialog->Import(in);
|
||||||
|
|
||||||
|
int ret = dialog->ShowModal();
|
||||||
|
|
||||||
|
if (ret == wxID_OK)
|
||||||
|
{
|
||||||
|
AtObj out;
|
||||||
|
dialog->Export(out);
|
||||||
|
|
||||||
|
AtlasWindowCommandProc::GetFromParentFrame(parent)->Submit(
|
||||||
|
new EditCommand_Dialog(editCtrl, row, col, out)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete dialog;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
class EditableListCtrl;
|
||||||
|
|
||||||
|
class FieldEditCtrl
|
||||||
|
{
|
||||||
|
friend class EditableListCtrl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~FieldEditCtrl() {};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void StartEdit(wxWindow* parent, wxRect rect, long row, int col)=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FieldEditCtrl_Text : public FieldEditCtrl
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void StartEdit(wxWindow* parent, wxRect rect, long row, int col);
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FieldEditCtrl_Dialog : public FieldEditCtrl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FieldEditCtrl_Dialog(wxString dialogType);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void StartEdit(wxWindow* parent, wxRect rect, long row, int col);
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxString m_DialogType;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,94 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "ListCtrlValidator.h"
|
||||||
|
|
||||||
|
#include "AtlasWindowCommandProc.h"
|
||||||
|
#include "EditableListCtrl.h"
|
||||||
|
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
#include "AtlasObject/AtlasObjectText.h"
|
||||||
|
|
||||||
|
class EditCommand_Text : public wxCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EditCommand_Text(EditableListCtrl* ctrl, long row, int col, wxString newText)
|
||||||
|
: wxCommand(true, _("Edit")), m_Ctrl(ctrl), m_Row(row), m_Col(col), m_NewText(newText)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Do()
|
||||||
|
{
|
||||||
|
m_Ctrl->CloneListData(m_OldData);
|
||||||
|
|
||||||
|
m_Ctrl->MakeSizeAtLeast(m_Row+1);
|
||||||
|
|
||||||
|
m_Ctrl->SetCellString(m_Row, m_Col, m_NewText);
|
||||||
|
|
||||||
|
m_Ctrl->UpdateDisplay();
|
||||||
|
m_Ctrl->SetSelection(m_Row);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Undo()
|
||||||
|
{
|
||||||
|
m_Ctrl->SetListData(m_OldData);
|
||||||
|
|
||||||
|
m_Ctrl->UpdateDisplay();
|
||||||
|
m_Ctrl->SetSelection(m_Row);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EditableListCtrl* m_Ctrl;
|
||||||
|
long m_Row;
|
||||||
|
int m_Col;
|
||||||
|
wxString m_NewText;
|
||||||
|
std::vector<AtObj> m_OldData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ListCtrlValidator::ListCtrlValidator()
|
||||||
|
: m_listCtrl(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ListCtrlValidator::ListCtrlValidator(EditableListCtrl* listCtrl, long row, int col)
|
||||||
|
: m_listCtrl(listCtrl), m_Row(row), m_Col(col)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxObject* ListCtrlValidator::Clone() const
|
||||||
|
{
|
||||||
|
return new ListCtrlValidator(m_listCtrl, m_Row, m_Col);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ListCtrlValidator::TransferToWindow()
|
||||||
|
{
|
||||||
|
wxTextCtrl* textCtrl = wxDynamicCast(GetWindow(), wxTextCtrl);
|
||||||
|
|
||||||
|
wxString text (m_listCtrl->GetCellString(m_Row, m_Col));
|
||||||
|
|
||||||
|
textCtrl->SetValue(text);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ListCtrlValidator::TransferFromWindow()
|
||||||
|
{
|
||||||
|
wxTextCtrl* textCtrl = wxDynamicCast(GetWindow(), wxTextCtrl);
|
||||||
|
|
||||||
|
wxString newText = textCtrl->GetValue();
|
||||||
|
|
||||||
|
AtlasWindowCommandProc::GetFromParentFrame(m_listCtrl)->Submit(
|
||||||
|
new EditCommand_Text(m_listCtrl, m_Row, m_Col, newText)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ListCtrlValidator::Validate(wxWindow* WXUNUSED(parent))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
#include "wx/validate.h"
|
||||||
|
#include "wx/listctrl.h"
|
||||||
|
|
||||||
|
class EditableListCtrl;
|
||||||
|
|
||||||
|
class ListCtrlValidator : public wxValidator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ListCtrlValidator();
|
||||||
|
ListCtrlValidator(EditableListCtrl* listCtrl, long row, int col);
|
||||||
|
|
||||||
|
wxObject* Clone() const;
|
||||||
|
|
||||||
|
bool TransferToWindow();
|
||||||
|
bool TransferFromWindow();
|
||||||
|
bool Validate(wxWindow *parent);
|
||||||
|
|
||||||
|
private:
|
||||||
|
EditableListCtrl* m_listCtrl;
|
||||||
|
long m_Row;
|
||||||
|
int m_Col;
|
||||||
|
};
|
@ -0,0 +1,43 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "QuickTextCtrl.h"
|
||||||
|
|
||||||
|
const int verticalPadding = 2;
|
||||||
|
|
||||||
|
QuickTextCtrl::QuickTextCtrl(wxWindow* parent,
|
||||||
|
wxRect& location,
|
||||||
|
const wxValidator& validator)
|
||||||
|
|
||||||
|
: wxTextCtrl(parent, wxID_ANY, wxEmptyString,
|
||||||
|
location.GetPosition()-wxPoint(0,verticalPadding),
|
||||||
|
location.GetSize()+wxSize(0,verticalPadding*2),
|
||||||
|
wxSUNKEN_BORDER | wxTE_PROCESS_TAB | wxTE_PROCESS_ENTER,
|
||||||
|
validator)
|
||||||
|
{
|
||||||
|
GetValidator()->TransferToWindow();
|
||||||
|
|
||||||
|
SetFocus();
|
||||||
|
SetSelection(-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QuickTextCtrl::OnKillFocus(wxFocusEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
GetValidator()->TransferFromWindow();
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickTextCtrl::OnChar(wxKeyEvent& event)
|
||||||
|
{
|
||||||
|
if (event.GetKeyCode() == WXK_RETURN)
|
||||||
|
GetParent()->SetFocus();
|
||||||
|
else if (event.GetKeyCode() == WXK_ESCAPE)
|
||||||
|
Destroy();
|
||||||
|
else
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_EVENT_TABLE(QuickTextCtrl, wxTextCtrl)
|
||||||
|
EVT_KILL_FOCUS(QuickTextCtrl::OnKillFocus)
|
||||||
|
EVT_CHAR(QuickTextCtrl::OnChar)
|
||||||
|
END_EVENT_TABLE()
|
@ -0,0 +1,13 @@
|
|||||||
|
#include "wx/textctrl.h"
|
||||||
|
|
||||||
|
class QuickTextCtrl : public wxTextCtrl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuickTextCtrl(wxWindow* parent, wxRect& location, const wxValidator& validator = wxDefaultValidator);
|
||||||
|
|
||||||
|
void OnKillFocus(wxFocusEvent& event);
|
||||||
|
void OnChar(wxKeyEvent& event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DECLARE_EVENT_TABLE();
|
||||||
|
};
|
@ -0,0 +1,63 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "AtlasDialog.h"
|
||||||
|
|
||||||
|
#include "wx/statline.h"
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS(AtlasDialog, wxDialog);
|
||||||
|
|
||||||
|
BEGIN_EVENT_TABLE(AtlasDialog, wxDialog)
|
||||||
|
EVT_MENU(wxID_UNDO, AtlasDialog::OnUndo)
|
||||||
|
EVT_MENU(wxID_REDO, AtlasDialog::OnRedo)
|
||||||
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
AtlasDialog::AtlasDialog(wxWindow* parent, const wxString& title)
|
||||||
|
: wxDialog(parent, -1, title, wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxCAPTION | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCLOSE_BOX)
|
||||||
|
{
|
||||||
|
// Create generic dialog box, with OK/Cancel buttons, some horizontal
|
||||||
|
// dividing lines, and a wxPanel in the middle:
|
||||||
|
|
||||||
|
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
SetSizer(mainSizer);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
mainSizer->Add(new wxStaticLine(this, -1), wxSizerFlags().Expand().Border(wxALL, 5));
|
||||||
|
|
||||||
|
|
||||||
|
m_MainPanel = new wxPanel(this);
|
||||||
|
mainSizer->Add(m_MainPanel, wxSizerFlags().Proportion(1).Expand().Border(wxLEFT|wxRIGHT, 5));
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
mainSizer->Add(new wxStaticLine(this, -1), wxSizerFlags().Expand().Border(wxALL, 5));
|
||||||
|
|
||||||
|
|
||||||
|
wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
mainSizer->Add(buttonSizer, wxSizerFlags().Expand().Align(wxALIGN_RIGHT).Border(wxALL, 5));
|
||||||
|
|
||||||
|
buttonSizer->Add(new wxButton(this, wxID_OK, _("OK")), wxSizerFlags().Border(wxRIGHT, 25));
|
||||||
|
buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), wxSizerFlags().Border(wxRIGHT, 5));
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Set up handlers for Ctrl+Z, Ctrl+Y (undo/redo), since dialogs don't
|
||||||
|
// have any menu entries for them (since they don't have menus at all).
|
||||||
|
wxAcceleratorEntry entries[2];
|
||||||
|
entries[0].Set(wxACCEL_CTRL, 'Z', wxID_UNDO);
|
||||||
|
entries[1].Set(wxACCEL_CTRL, 'Y', wxID_REDO);
|
||||||
|
wxAcceleratorTable accel(2, entries);
|
||||||
|
SetAcceleratorTable(accel);
|
||||||
|
|
||||||
|
m_CommandProc.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtlasDialog::OnUndo(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
m_CommandProc.Undo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtlasDialog::OnRedo(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
m_CommandProc.Redo();
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
#include "wx/dialog.h"
|
||||||
|
|
||||||
|
#include "AtlasWindowCommandProc.h"
|
||||||
|
#include "IAtlasExporter.h"
|
||||||
|
|
||||||
|
class FieldEditCtrl_Dialog;
|
||||||
|
|
||||||
|
class AtlasDialog : public wxDialog, public IAtlasExporter
|
||||||
|
{
|
||||||
|
friend class FieldEditCtrl_Dialog;
|
||||||
|
friend class AtlasWindowCommandProc;
|
||||||
|
|
||||||
|
DECLARE_CLASS(AtlasDialog);
|
||||||
|
|
||||||
|
public:
|
||||||
|
AtlasDialog(wxWindow* parent, const wxString& title);
|
||||||
|
virtual ~AtlasDialog() {}
|
||||||
|
|
||||||
|
void OnUndo(wxCommandEvent& event);
|
||||||
|
void OnRedo(wxCommandEvent& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxPanel* m_MainPanel;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AtlasWindowCommandProc m_CommandProc;
|
||||||
|
|
||||||
|
DECLARE_EVENT_TABLE()
|
||||||
|
};
|
@ -0,0 +1,119 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "AtlasWindow.h"
|
||||||
|
|
||||||
|
#include "AtlasObject/AtlasObject.h"
|
||||||
|
|
||||||
|
#include "wx/intl.h"
|
||||||
|
#include "wx/menu.h"
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS(AtlasWindow, wxFrame);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ID_Quit = 1,
|
||||||
|
ID_Import,
|
||||||
|
ID_Export
|
||||||
|
};
|
||||||
|
|
||||||
|
BEGIN_EVENT_TABLE(AtlasWindow, wxFrame)
|
||||||
|
EVT_MENU(ID_Quit, AtlasWindow::OnQuit)
|
||||||
|
EVT_MENU(ID_Import, AtlasWindow::OnImport)
|
||||||
|
EVT_MENU(ID_Export, AtlasWindow::OnExport)
|
||||||
|
EVT_MENU(wxID_UNDO, AtlasWindow::OnUndo)
|
||||||
|
EVT_MENU(wxID_REDO, AtlasWindow::OnRedo)
|
||||||
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
AtlasWindow::AtlasWindow(wxWindow* parent, const wxString& title, const wxSize& size)
|
||||||
|
: wxFrame(parent, wxID_ANY, _T(""), wxDefaultPosition, size)
|
||||||
|
, m_WindowTitle(title)
|
||||||
|
{
|
||||||
|
|
||||||
|
wxMenuBar *menuBar = new wxMenuBar;
|
||||||
|
SetMenuBar(menuBar);
|
||||||
|
|
||||||
|
wxMenu *menuFile = new wxMenu;
|
||||||
|
menuBar->Append(menuFile, _("&File"));
|
||||||
|
{
|
||||||
|
menuFile->Append(ID_Import, _("&Import..."));
|
||||||
|
menuFile->Append(ID_Export, _("&Export..."));
|
||||||
|
menuFile->AppendSeparator();//-----------
|
||||||
|
menuFile->Append(ID_Quit, _("E&xit"));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxMenu *menuEdit = new wxMenu;
|
||||||
|
menuBar->Append(menuEdit, _("&Edit"));
|
||||||
|
{
|
||||||
|
menuEdit->Append(wxID_UNDO, _("&Undo"));
|
||||||
|
menuEdit->Append(wxID_REDO, _("&Redo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_CommandProc.SetEditMenu(menuEdit);
|
||||||
|
m_CommandProc.Initialize();
|
||||||
|
|
||||||
|
CreateStatusBar();
|
||||||
|
//SetStatusText(_("Welcome to wxWidgets!"));
|
||||||
|
|
||||||
|
SetDisplayedFilename(_T(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtlasWindow::OnQuit(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtlasWindow::OnUndo(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
m_CommandProc.Undo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtlasWindow::OnRedo(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
m_CommandProc.Redo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AtlasWindow::OnImport(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
wxFileDialog dlg (this, _T("Select XML file to import"), _T(""), _T(""), _T("XML files (*.xml)|*.xml"), wxOPEN);
|
||||||
|
|
||||||
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString filename = dlg.GetPath();
|
||||||
|
|
||||||
|
AtObj file;
|
||||||
|
AtlasObject::LoadFromXML(file, filename.c_str());
|
||||||
|
|
||||||
|
Import(file);
|
||||||
|
|
||||||
|
SetDisplayedFilename(dlg.GetFilename());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtlasWindow::OnExport(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
wxFileDialog dlg (this, _T("Select XML file to export"), _T(""), _T(""), _T("XML files (*.xml)|*.xml"), wxSAVE | wxOVERWRITE_PROMPT);
|
||||||
|
|
||||||
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString filename = dlg.GetPath();
|
||||||
|
|
||||||
|
AtObj file;
|
||||||
|
Export(file);
|
||||||
|
|
||||||
|
AtlasObject::SaveToXML(file, filename.c_str());
|
||||||
|
|
||||||
|
SetDisplayedFilename(dlg.GetFilename());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AtlasWindow::SetDisplayedFilename(wxString filename)
|
||||||
|
{
|
||||||
|
if (filename == _T(""))
|
||||||
|
m_DisplayedFilename = _("Unnamed file");
|
||||||
|
else
|
||||||
|
m_DisplayedFilename = filename;
|
||||||
|
|
||||||
|
SetTitle(m_WindowTitle + _T(" - ") + m_DisplayedFilename);
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
#include "AtlasWindowCommandProc.h"
|
||||||
|
|
||||||
|
#include "IAtlasExporter.h"
|
||||||
|
|
||||||
|
#include "wx/frame.h"
|
||||||
|
|
||||||
|
class AtObj;
|
||||||
|
|
||||||
|
class AtlasWindow : public wxFrame, public IAtlasExporter
|
||||||
|
{
|
||||||
|
friend class AtlasWindowCommandProc;
|
||||||
|
|
||||||
|
DECLARE_CLASS(AtlasWindow);
|
||||||
|
|
||||||
|
public:
|
||||||
|
AtlasWindow(wxWindow* parent, const wxString& title, const wxSize& size);
|
||||||
|
|
||||||
|
void OnQuit(wxCommandEvent& event);
|
||||||
|
|
||||||
|
void OnImport(wxCommandEvent& event);
|
||||||
|
void OnExport(wxCommandEvent& event);
|
||||||
|
|
||||||
|
void OnUndo(wxCommandEvent& event);
|
||||||
|
void OnRedo(wxCommandEvent& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Call with the name of the currently opened file, or with the
|
||||||
|
// empty string for new unnamed documents
|
||||||
|
void SetDisplayedFilename(wxString filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AtlasWindowCommandProc m_CommandProc;
|
||||||
|
|
||||||
|
wxString m_DisplayedFilename;
|
||||||
|
wxString m_WindowTitle;
|
||||||
|
|
||||||
|
DECLARE_EVENT_TABLE();
|
||||||
|
};
|
@ -0,0 +1,5 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "AtlasWindowCommand.h"
|
||||||
|
|
||||||
|
IMPLEMENT_ABSTRACT_CLASS(AtlasWindowCommand, wxCommand);
|
19
source/tools/atlas/AtlasUI/General/AtlasWindowCommand.h
Normal file
19
source/tools/atlas/AtlasUI/General/AtlasWindowCommand.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "wx/cmdproc.h"
|
||||||
|
|
||||||
|
class AtlasWindowCommand : public wxCommand
|
||||||
|
{
|
||||||
|
DECLARE_ABSTRACT_CLASS(AtlasWindowCommand);
|
||||||
|
|
||||||
|
friend class AtlasWindowCommandProc;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AtlasWindowCommand(bool canUndoIt, const wxString& name)
|
||||||
|
: wxCommand(canUndoIt, name), m_Finalized(false) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Control merging of this command with a future one (so they
|
||||||
|
// can be undone in a single step)
|
||||||
|
virtual bool Merge(AtlasWindowCommand* command)=0;
|
||||||
|
|
||||||
|
bool m_Finalized;
|
||||||
|
};
|
@ -0,0 +1,66 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "AtlasWindow.h"
|
||||||
|
#include "AtlasWindowCommand.h"
|
||||||
|
#include "AtlasDialog.h"
|
||||||
|
|
||||||
|
AtlasWindowCommandProc* AtlasWindowCommandProc::GetFromParentFrame(wxWindow* object)
|
||||||
|
{
|
||||||
|
wxWindow* win = object;
|
||||||
|
while (win)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
AtlasWindow* tgt = wxDynamicCast(win, AtlasWindow);
|
||||||
|
if (tgt)
|
||||||
|
return &tgt->m_CommandProc;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
AtlasDialog* tgt = wxDynamicCast(win, AtlasDialog);
|
||||||
|
if (tgt)
|
||||||
|
return &tgt->m_CommandProc;
|
||||||
|
}
|
||||||
|
|
||||||
|
win = win->GetParent();
|
||||||
|
}
|
||||||
|
wxASSERT_MSG(0, _T("Couldn't find command processor"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtlasWindowCommandProc::Submit(wxCommand *command, bool storeIt)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG(command, false, _T("no command in wxCommandProcessor::Submit"));
|
||||||
|
|
||||||
|
AtlasWindowCommand* previousCommand = wxDynamicCast(GetCurrentCommand(), AtlasWindowCommand);
|
||||||
|
|
||||||
|
if (! DoCommand(*command))
|
||||||
|
{
|
||||||
|
delete command;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storeIt)
|
||||||
|
{
|
||||||
|
AtlasWindowCommand* currentCommand = wxDynamicCast(command, AtlasWindowCommand);
|
||||||
|
|
||||||
|
if (currentCommand && previousCommand
|
||||||
|
&& !previousCommand->m_Finalized
|
||||||
|
&& previousCommand->Merge(currentCommand))
|
||||||
|
{
|
||||||
|
delete command;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Store(command);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete command;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtlasWindowCommandProc::FinaliseLastCommand()
|
||||||
|
{
|
||||||
|
AtlasWindowCommand* previousCommand = wxDynamicCast(GetCurrentCommand(), AtlasWindowCommand);
|
||||||
|
if (previousCommand)
|
||||||
|
previousCommand->m_Finalized = true;
|
||||||
|
}
|
19
source/tools/atlas/AtlasUI/General/AtlasWindowCommandProc.h
Normal file
19
source/tools/atlas/AtlasUI/General/AtlasWindowCommandProc.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef ATLASWINDOWCOMMANDPROC_H__
|
||||||
|
#define ATLASWINDOWCOMMANDPROC_H__
|
||||||
|
|
||||||
|
#include "wx/cmdproc.h"
|
||||||
|
#include "wx/window.h"
|
||||||
|
|
||||||
|
class AtlasWindowCommandProc : public wxCommandProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Submit(wxCommand *command, bool storeIt = true);
|
||||||
|
|
||||||
|
// Mark the most recent command as finalized, so it won't be
|
||||||
|
// merged with any subsequent ones
|
||||||
|
void FinaliseLastCommand();
|
||||||
|
|
||||||
|
static AtlasWindowCommandProc* GetFromParentFrame(wxWindow* object);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ATLASWINDOWCOMMANDPROC_H__
|
13
source/tools/atlas/AtlasUI/General/IAtlasExporter.h
Normal file
13
source/tools/atlas/AtlasUI/General/IAtlasExporter.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef IATLASEXPORTER_H__
|
||||||
|
#define IATLASEXPORTER_H__
|
||||||
|
|
||||||
|
class AtObj;
|
||||||
|
|
||||||
|
class IAtlasExporter // and also importer, but I can't think of a nice concise name
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Import(AtObj& in)=0;
|
||||||
|
virtual void Export(AtObj& out)=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IATLASEXPORTER_H__
|
26
source/tools/atlas/AtlasUI/Misc/actored.cpp
Normal file
26
source/tools/atlas/AtlasUI/Misc/actored.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Just a boring app that creates an ActorEditor window
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "ActorEditor/ActorEditor.h"
|
||||||
|
|
||||||
|
#include "wx/app.h"
|
||||||
|
|
||||||
|
class MyApp: public wxApp
|
||||||
|
{
|
||||||
|
bool OnInit();
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPLEMENT_APP(MyApp)
|
||||||
|
|
||||||
|
#include <crtdbg.h>
|
||||||
|
|
||||||
|
bool MyApp::OnInit()
|
||||||
|
{
|
||||||
|
// _CrtSetBreakAlloc(1358);
|
||||||
|
// MyFrame *frame = new MyFrame("Hello World");
|
||||||
|
wxFrame *frame = new ActorEditor(NULL);
|
||||||
|
frame->Show();
|
||||||
|
SetTopWindow(frame);
|
||||||
|
return true;
|
||||||
|
}
|
0
source/tools/atlas/AtlasUI/Misc/actored.h
Normal file
0
source/tools/atlas/AtlasUI/Misc/actored.h
Normal file
1
source/tools/atlas/AtlasUI/Misc/stdafx.cpp
Normal file
1
source/tools/atlas/AtlasUI/Misc/stdafx.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "stdafx.h"
|
24
source/tools/atlas/AtlasUI/Misc/stdafx.h
Normal file
24
source/tools/atlas/AtlasUI/Misc/stdafx.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Precompiled headers:
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define HAVE_PCH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PCH
|
||||||
|
|
||||||
|
// Exclude rarely-used stuff from Windows headers
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
// Include useful wx headers
|
||||||
|
#include "wx/wxprec.h"
|
||||||
|
#include "wx/listctrl.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Nicer memory-leak detection:
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#define new new(_NORMAL_BLOCK ,__FILE__, __LINE__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // HAVE_PCH
|
23
source/tools/atlas/AtlasUI/TODO.txt
Normal file
23
source/tools/atlas/AtlasUI/TODO.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
* Copy and paste
|
||||||
|
|
||||||
|
* s/PropListEditor/PropListEditor/
|
||||||
|
|
||||||
|
* Rearrange directory structure
|
||||||
|
|
||||||
|
* Don't hardcode "actor" in XML files (urgh)
|
||||||
|
|
||||||
|
* Document lots
|
||||||
|
|
||||||
|
* Make import undoable
|
||||||
|
|
||||||
|
* wxListItemAttr* OnGetItemAttr(long item) >>>const<<< - wx documentation??
|
||||||
|
|
||||||
|
* Better widths
|
||||||
|
|
||||||
|
* Combo boxes for prop/anim names, loaded from file
|
||||||
|
|
||||||
|
* Input validation?
|
||||||
|
|
||||||
|
* Better input controls (=> export nicely, support undo, etc)
|
||||||
|
|
||||||
|
* Handle undo correctly after importing
|
Loading…
Reference in New Issue
Block a user