diff --git a/uppsrc/Core/Util.cpp b/uppsrc/Core/Util.cpp index aeccd9bf1..7124051b4 100644 --- a/uppsrc/Core/Util.cpp +++ b/uppsrc/Core/Util.cpp @@ -628,81 +628,88 @@ String FromSystemCharset(const String& src) #endif #endif -static VectorMap& sGCfg() -{ - static VectorMap m; - return m; -} static StaticCriticalSection sGCfgLock; -static Vector >& sGFlush() +static VectorMap& sGCfg() { - static Vector > m; - return m; + static VectorMap h; + return h; } -static StaticCriticalSection sGFlushLock; +static Vector>& sGFlush() +{ + static Vector> h; + return h; +} + +static VectorMap>& sGSerialize() +{ + static VectorMap> h; + return h; +} void RegisterGlobalConfig(const char *name) { - INTERLOCKED_(sGCfgLock) { - ASSERT(sGCfg().Find(name) < 0); - sGCfg().Add(name); - } + Mutex::Lock __(sGCfgLock); + ASSERT(sGCfg().Find(name) < 0); + sGCfg().Add(name); +} + +void RegisterGlobalSerialize(const char *name, Event WhenSerialize) +{ + Mutex::Lock __(sGCfgLock); + RegisterGlobalConfig(name); + sGSerialize().Add(name, WhenSerialize); } void RegisterGlobalConfig(const char *name, Event<> WhenFlush) { + Mutex::Lock __(sGCfgLock); RegisterGlobalConfig(name); - INTERLOCKED_(sGFlushLock) { - sGFlush().Add(WhenFlush); - } + sGFlush().Add(WhenFlush); } String GetGlobalConfigData(const char *name) { - INTERLOCKED_(sGCfgLock) { - return sGCfg().GetAdd(name); - } - return String(); + Mutex::Lock __(sGCfgLock); + return sGCfg().GetAdd(name); } void SetGlobalConfigData(const char *name, const String& data) { - INTERLOCKED_(sGCfgLock) { - sGCfg().GetAdd(name) = data; - } + Mutex::Lock __(sGCfgLock); + sGCfg().GetAdd(name) = data; } void SerializeGlobalConfigs(Stream& s) { - INTERLOCKED_(sGFlushLock) { - for(int i = 0; i < sGFlush().GetCount(); i++) - sGFlush()[i](); - } - INTERLOCKED_(sGCfgLock) { - VectorMap& cfg = sGCfg(); - int version = 0; - s / version; - int count = cfg.GetCount(); - s / count; - for(int i = 0; i < count; i++) { - String name; - if(s.IsStoring()) - name = cfg.GetKey(i); - s % name; - int q = cfg.Find(name); - if(q >= 0) - s % cfg[q]; + Mutex::Lock __(sGCfgLock); + for(int i = 0; i < sGFlush().GetCount(); i++) + sGFlush()[i](); + int version = 0; + s / version; + int count = sGCfg().GetCount(); + s / count; + for(int i = 0; i < count; i++) { + String name; + if(s.IsStoring()) + name = sGCfg().GetKey(i); + s % name; + int q = sGCfg().Find(name); + if(q >= 0) { + int w = sGSerialize().Find(name); + if(w >= 0) + sGSerialize()[w](s); else - { - String dummy; - s % dummy; - } + s % sGCfg()[q]; + } + else { + String dummy; + s % dummy; } - s.Magic(); } + s.Magic(); } AbortExc::AbortExc() : diff --git a/uppsrc/Core/Util.h b/uppsrc/Core/Util.h index 61f23ce16..3808b9f6d 100644 --- a/uppsrc/Core/Util.h +++ b/uppsrc/Core/Util.h @@ -450,8 +450,9 @@ bool LoadFromString(T& x, const String& s) { return Load(x, ss); } -void RegisterGlobalConfig(const char *name) init_; -void RegisterGlobalConfig(const char *name, Event<> WhenFlush) init_; +void RegisterGlobalConfig(const char *name); +void RegisterGlobalSerialize(const char *name, Event WhenSerialize); +void RegisterGlobalConfig(const char *name, Event<> WhenFlush); String GetGlobalConfigData(const char *name); void SetGlobalConfigData(const char *name, const String& data); diff --git a/uppsrc/Core/src.tpp/SerializationUtils$en-us.tpp b/uppsrc/Core/src.tpp/SerializationUtils$en-us.tpp index 6bb2c4330..5eb042737 100644 --- a/uppsrc/Core/src.tpp/SerializationUtils$en-us.tpp +++ b/uppsrc/Core/src.tpp/SerializationUtils$en-us.tpp @@ -165,45 +165,42 @@ serialization of all such data with single stream.&] [s0;0%- &] [s5;:RegisterGlobalConfig`(const char`*`):%- [@(0.0.255) void]_[* RegisterGlobalConfig]([@(0.0.255) c onst]_[@(0.0.255) char]_`*[*@3 name])&] -[s2; Registers name as global configuration key.&] -[s7; [%-*C@3 name]-|Key.&] +[s7; Registers name as global configuration key.&] [s3; &] [s4;%- &] -[s5;:RegisterGlobalConfig`(const char`*`,Callback`):%- [@(0.0.255) void]_[* RegisterGloba -lConfig]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 name], [_^Callback^ Callback]_[*@3 Whe -nFlush])&] -[s2; Registers name as global configuration key, with flush callback.&] -[s7; [%-*C@3 name]-|Key.&] -[s7; [%-*C@3 WhenFlush]-|This callback is called before storing of all -configuration keys is performed by SerializeGlobalConfigs `- -this is useful when StoreToGlobal has to be explicitly triggered -before storing configuration.&] +[s5;:Upp`:`:RegisterGlobalSerialize`(const char`*`,Upp`:`:Event``):%- [@(0.0.255) v +oid]_[* RegisterGlobalSerialize]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 name], +[_^Upp`:`:Event^ Event]_[*@3 WhenSerialize])&] +[s2; Registers name as global configuration key. [%-*@3 WhenSerialize] +is directly used to serialize data, unlike other variants of +global config key, where data are stored / retrieved using LoadFromGlobal +/ StoreToGlobal.&] +[s3; &] +[s4;%- &] +[s5;:Upp`:`:RegisterGlobalConfig`(const char`*`,Upp`:`:Event`<`>`):%- [@(0.0.255) void]_ +[* RegisterGlobalConfig]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 name], +[_^Upp`:`:Event^ Event]<>_[*@3 WhenFlush])&] +[s2; Registers name as global configuration key. [%-*C@3 WhenFlush] + is called before storing of all configuration keys is performed +by SerializeGlobalConfigs `- this is useful when StoreToGlobal +has to be explicitly triggered before storing configuration.&] [s3; &] [s4;%- &] [s5;:LoadFromGlobal`(T`&`,const char`*`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T ][@(0.0.255) >]_[@(0.0.255) bool]_[* LoadFromGlobal]([*@4 T][@(0.0.255) `&]_[*@3 x], [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 name])&] -[s2; Loads [%-*@3 x] from global configuration key, using smart backup -methods provided by [^topic`:`/`/Core`/src`/SerializationUtils`$en`-us`#`:`:Load`(Callback1``,Stream`&`)^ L -oad].&] -[s7; [*C@4 T]-|Type of serialized object.&] -[s7; [%-*C@3 x]-|Reference to serialized object.&] -[s7; [%-*C@3 name]-|Configuration key.&] -[s7; [*/ Return value]-|true indicates success.&] +[s2; Loads [%-*@3 x] from global configuration key [%-*@3 name].&] [s3; &] [s4;%- &] [s5;:StoreToGlobal`(T`&`,const char`*`):%- [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T ][@(0.0.255) >]_[@(0.0.255) void]_[* StoreToGlobal]([*@4 T][@(0.0.255) `&]_[*@3 x], [@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 name])&] -[s2; Stores [@3 x] to global configuration key.&] -[s7; [*C@4 T]-|Type of serialized object.&] -[s7; [%-*C@3 x]-|Reference to serialized object.&] -[s7; [%-*C@3 name]-|Configuration key.&] +[s2; Stores [@3 x] to global configuration key [%-*C@3 name].&] [s3; &] [s4;%- &] [s5;:SerializeGlobalConfigs`(Stream`&`):%- [@(0.0.255) void]_[* SerializeGlobalConfigs]([_^Stream^ S tream][@(0.0.255) `&]_[*@3 s])&] -[s2; Serializes all global configuration data from/to single stream.&] -[s7; [%-*C@3 s]-|Stream.&] +[s2; Serializes all registered global configuration data from/to +single stream.&] [s3; &] [s0; ]] \ No newline at end of file diff --git a/uppsrc/CtrlLib/TreeCtrl.cpp b/uppsrc/CtrlLib/TreeCtrl.cpp index b7e50ca66..5bb5af02d 100644 --- a/uppsrc/CtrlLib/TreeCtrl.cpp +++ b/uppsrc/CtrlLib/TreeCtrl.cpp @@ -502,6 +502,22 @@ bool TreeCtrl::IsOpen(int id) const return item[id].isopen; } +Vector TreeCtrl::GetOpenIds() const +{ + Vector r; + for(int id = 0; id < item.GetCount(); id++) + if(!item[id].free && item[id].isopen) + r.Add(id); + return r; +} + +void TreeCtrl::OpenIds(const Vector& ids) +{ + for(int id : ids) + if(IsValid(id)) + Open(id); +} + void TreeCtrl::Dirty(int id) { // if(selectcount) SelClear(0); diff --git a/uppsrc/CtrlLib/TreeCtrl.h b/uppsrc/CtrlLib/TreeCtrl.h index 85f04a570..31d641082 100644 --- a/uppsrc/CtrlLib/TreeCtrl.h +++ b/uppsrc/CtrlLib/TreeCtrl.h @@ -235,6 +235,8 @@ public: bool IsOpen(int id) const; void Open(int id, bool open = true); void Close(int id) { Open(id, false); } + Vector GetOpenIds() const; + void OpenIds(const Vector& ids); void OpenDeep(int id, bool open = true); void CloseDeep(int id) { OpenDeep(id, false); } diff --git a/uppsrc/CtrlLib/src.tpp/TreeCtrl$en-us.tpp b/uppsrc/CtrlLib/src.tpp/TreeCtrl$en-us.tpp index 3a734cd2d..9c441f696 100644 --- a/uppsrc/CtrlLib/src.tpp/TreeCtrl$en-us.tpp +++ b/uppsrc/CtrlLib/src.tpp/TreeCtrl$en-us.tpp @@ -289,6 +289,11 @@ t]_[*@3 id])_[@(0.0.255) const]&] [s2;%% Sets attributes.&] [s3; &] [s4; &] +[s5;:Upp`:`:TreeCtrl`:`:IsValid`(int`)const: [@(0.0.255) bool]_[* IsValid]([@(0.0.255) int]_ +[*@3 id])_[@(0.0.255) const]&] +[s2;%% Returns true if [%-*@3 id] represents a valid node id.&] +[s3;%% &] +[s4; &] [s5;:TreeCtrl`:`:IsOpen`(int`)const: [@(0.0.255) bool]_[* IsOpen]([@(0.0.255) int]_[*@3 id])_ [@(0.0.255) const]&] [s2;%% Tests whether item is opened.&] @@ -304,6 +309,16 @@ all child items visible.&] [s2;%% Same as Open(id, false).&] [s3; &] [s4; &] +[s5;:Upp`:`:TreeCtrl`:`:GetOpenIds`(`)const: [_^Upp`:`:Vector^ Vector]<[@(0.0.255) int]>_ +[* GetOpenIds]()_[@(0.0.255) const]&] +[s2;%% Returns all open node ids.&] +[s3; &] +[s4; &] +[s5;:Upp`:`:TreeCtrl`:`:OpenIds`(const Upp`:`:Vector``&`): [@(0.0.255) void]_[* Ope +nIds]([@(0.0.255) const]_[_^Upp`:`:Vector^ Vector]<[@(0.0.255) int]>`&_[*@3 ids])&] +[s2;%% Opens all valid [%-*@3 ids].&] +[s3;%% &] +[s4; &] [s5;:TreeCtrl`:`:OpenDeep`(int`,bool`): [@(0.0.255) void]_[* OpenDeep]([@(0.0.255) int]_[*@3 i d], [@(0.0.255) bool]_[*@3 open]_`=_[@(0.0.255) true])&] [s2;%% Opens/closes item with [%-*@3 id] and all of its child items.&] diff --git a/uppsrc/ide/Designers/Designers.h b/uppsrc/ide/Designers/Designers.h index 2d98fb661..77af2ca4a 100644 --- a/uppsrc/ide/Designers/Designers.h +++ b/uppsrc/ide/Designers/Designers.h @@ -27,6 +27,8 @@ struct IdePngDes : IdeIconDes { void Create(const char *filename); }; +INITIALIZE(Img) + class FileHexView : public IdeDesigner, public HexView, private LRUCache::Maker { public: virtual int Byte(int64 addr); @@ -59,10 +61,96 @@ public: ~FileHexView(); }; -bool FileIsBinary(const char *path); - -INITIALIZE(Img) -INITIALIZE(Qtf) INITIALIZE(HexView) +struct IdeQtfDes : IdeDesigner, RichEditWithToolBar { + String filename; + + virtual String GetFileName() const { return filename; } + virtual void Save(); + virtual void SaveEditPos(); + virtual void EditMenu(Bar& menu); + virtual Ctrl& DesignerCtrl() { return *this; } + + virtual void Serialize(Stream& s); + + bool Load(const char *filename); + void FileProperties(); + void CopyId(const String& n); + + typedef IdeQtfDes CLASSNAME; + + IdeQtfDes() { Extended(); } +}; + +INITIALIZE(Qtf) + +bool FileIsBinary(const char *path); + +struct TreeDesPos { + Time filetime = Null; + Vector openid; + int cursor = -1; + Point scroll; + + void Serialize(Stream& s) { s % filetime % openid % cursor % scroll; } + void Save(Time filetime, TreeCtrl& tree); + void Restore(Time filetime, TreeCtrl& tree); +}; + +void Save(ArrayMap& pos, const String& filename, Time filetime, TreeCtrl& tree); +void Restore(ArrayMap& pos, const String& filename, Time filetime, TreeCtrl& tree); +void Serialize(Stream& s, ArrayMap& pos); + +struct TreeViewDes : IdeDesigner, Ctrl { + virtual String GetFileName() const { return filename; } + virtual void Save() {} + virtual void EditMenu(Bar& menu); + virtual Ctrl& DesignerCtrl() { return *this; } + virtual void RestoreEditPos(); + virtual void SaveEditPos(); + + static ArrayMap pos; + + String filename; + Time filetime; + TreeCtrl tree; + FrameTop errorbg; + Label error; + ParentCtrl data; + + TreeViewDes(); + + void Error(const char *e); + bool Load(const String& txt); + + virtual String GetId() = 0; + virtual void CopyPath() = 0; + virtual String Load0(const String& data) = 0; +}; + +INITIALIZE(TreeViewDes) + +struct XmlViewDes : TreeViewDes { + virtual String GetId() { return "XML"; } + virtual void CopyPath(); + virtual String Load0(const String& data); + + void Load0(int parent, XmlParser& p); +}; + +INITIALIZE(XmlViewDes) + +struct JsonViewDes : TreeViewDes { + virtual String GetId() { return "JSON"; } + virtual String Load0(const String& json); + virtual void CopyPath(); + + int AddNode(int parent_id, const Value& id, const String& name, const Value& v); + + JsonViewDes(); +}; + +INITIALIZE(JsonViewDes) + #endif diff --git a/uppsrc/ide/Designers/Designers.upp b/uppsrc/ide/Designers/Designers.upp index 377e0d399..c661034e6 100644 --- a/uppsrc/ide/Designers/Designers.upp +++ b/uppsrc/ide/Designers/Designers.upp @@ -8,5 +8,8 @@ file Png.cpp, Img.cpp, Qtf.cpp, - HexView.cpp; + HexView.cpp, + TreeDes.cpp, + Xml.cpp, + Json.cpp; diff --git a/uppsrc/ide/Designers/Json.cpp b/uppsrc/ide/Designers/Json.cpp new file mode 100644 index 000000000..556957397 --- /dev/null +++ b/uppsrc/ide/Designers/Json.cpp @@ -0,0 +1,105 @@ +#include + +JsonViewDes::JsonViewDes() +{ + tree.SetDisplay(QTFDisplay()); +} + +void JsonViewDes::CopyPath() +{ + int id = tree.GetCursor(); + String path; + while(id) { + Value k = tree.Get(id); + if(!IsNull(k)) { + if(IsNumber(k)) + path = "[" + AsString(k) + "]" + path; + if(IsString(k)) + path = "[" + AsCString(String(k)) + "]" + path; + } + id = tree.GetParent(id); + } + WriteClipboardText(path); +} + +String JsonViewDes::Load0(const String& json) +{ + String parsingError; + + CParser p(json); + try { + tree.Open(AddNode(0, Null, "JSON", ParseJSON(p))); + } + catch(const CParser::Error& e) { + parsingError << e; + } + + return parsingError; +} + +int JsonViewDes::AddNode(int parent_id, const Value& id, const String& name, const Value& v) +{ + if(IsError(v)) { + // TODO: Replace with JsonExc or something that is more accurate in this situation. + String errorText = GetErrorText(v); + errorText.Remove(0, errorText.Find(" ") + 1); + throw Exc(errorText); + } + else + if(v.Is()) { + ValueMap m = v; + parent_id = tree.Add(parent_id, IdeImg::JsonStruct(), id, "[G1 [* " + name); + for(int i = 0; i < m.GetCount(); i++) + AddNode(parent_id, m.GetKey(i), "[@B \1" + String(m.GetKey(i)) + "\1:]", m.GetValue(i)); + } + else + if(v.Is()) { + parent_id = tree.Add(parent_id, IdeImg::JsonArray(), id, "[G1 [* " + name); + for(int i = 0; i < v.GetCount(); i++) + AddNode(parent_id, i, "[@c " + AsString(i) + ":]", v[i]); + } + else { + String qtf = "[G1 [* " + name + "]"; + Image img = IdeImg::JsonNumber(); + if(IsString(v)) { + img = IdeImg::JsonString(); + if(IsNull(v)) + qtf << "[*@g Null"; + else + qtf << "[@r \1 " + AsCString(String(v)); + } + else { + if(v.Is()) + img = IdeImg::JsonBool(); + if(IsNull(v)) + qtf << "[*@g Null"; + else + qtf << "\1 " + AsString(v); + } + parent_id = tree.Add(parent_id, img, id, qtf); + } + return parent_id; +} + +struct JsonDesModule : public IdeModule { + virtual String GetID() { return "JsonDesModule"; } + + virtual bool AcceptsFile(const char *path) { + return ToLower(GetFileExt(path)) == ".json"; + } + + virtual IdeDesigner *CreateDesigner(const char *path, byte) { + if(!AcceptsFile(path)) + return NULL; + JsonViewDes *d = new JsonViewDes; + if(d->Load(path)) + return d; + delete d; + return NULL; + } +}; + +INITIALIZER(JsonViewDes) +{ + RegisterIdeModule(Single()); +} diff --git a/uppsrc/ide/Designers/Png.cpp b/uppsrc/ide/Designers/Png.cpp index ffad66831..c12d8fef3 100644 --- a/uppsrc/ide/Designers/Png.cpp +++ b/uppsrc/ide/Designers/Png.cpp @@ -12,7 +12,7 @@ void IdePngDes::Load(const char *_filename) Clear(); filename = _filename; filetime = FileGetTime(filename); - Image m = StreamRaster::LoadFileAny(filename); + Image m = StreamRaster::LoadFileAny(filename); AddImage(filename, m, false); SingleMode(); } diff --git a/uppsrc/ide/Designers/Qtf.cpp b/uppsrc/ide/Designers/Qtf.cpp index 6868d43ac..3662cfb36 100644 --- a/uppsrc/ide/Designers/Qtf.cpp +++ b/uppsrc/ide/Designers/Qtf.cpp @@ -1,25 +1,5 @@ #include "Designers.h" -struct IdeQtfDes : IdeDesigner, RichEditWithToolBar { - String filename; - - virtual String GetFileName() const { return filename; } - virtual void Save(); - virtual void SaveEditPos(); - virtual void EditMenu(Bar& menu); - virtual Ctrl& DesignerCtrl() { return *this; } - - virtual void Serialize(Stream& s); - - bool Load(const char *filename); - void FileProperties(); - void CopyId(const String& n); - - typedef IdeQtfDes CLASSNAME; - - IdeQtfDes() { Extended(); } -}; - struct IdeQtfEditPos : Moveable { Time filetime; RichEdit::PosInfo pos; diff --git a/uppsrc/ide/Designers/TreeDes.cpp b/uppsrc/ide/Designers/TreeDes.cpp new file mode 100644 index 000000000..b1ae932c2 --- /dev/null +++ b/uppsrc/ide/Designers/TreeDes.cpp @@ -0,0 +1,93 @@ +#include "Designers.h" + +void TreeDesPos::Save(Time afiletime, TreeCtrl& tree) +{ + filetime = afiletime; + scroll = tree.GetScroll(); + cursor = tree.GetCursor(); + openid = tree.GetOpenIds(); +} + +void TreeDesPos::Restore(Time afiletime, TreeCtrl& tree) +{ + if(afiletime == filetime) { + tree.OpenIds(openid); + if(tree.IsValid(cursor)) + tree.SetCursor(cursor); + tree.ScrollTo(scroll); + } + tree.SetFocus(); +} + +void Serialize(Stream& s, ArrayMap& pos) +{ + int version = 0; + s / version; + s % pos; +} + +TreeViewDes::TreeViewDes() +{ + tree.NoRoot(); + + error.SetFont(Arial(20)).SetInk(Red); + errorbg.Height(Zy(25)).Add(error.SizePos()); + + Add(tree.SizePos()); + + tree.WhenLeftDouble = [=] { CopyPath(); }; +} + +ArrayMap TreeViewDes::pos; + +bool TreeViewDes::Load(const String& fn) +{ + RemoveFrame(errorbg); + tree.Clear(); + + filename = fn; + + FileIn in(filename); + if(!in) + return false; + + filetime = in.GetTime(); + + const int limit = 20000000; + + String txt = in.Get(limit); + + String parsingError = Load0(txt); + if(in.GetSize() >= limit) + MergeWith(parsingError, ", ", "file was longer than 20MB and was truncated"); + if(parsingError.GetCount()) { + error = String() << "XML parsing error: " << parsingError << "."; + AddFrame(errorbg); + } + + return tree.GetChildCount(0); +} + +void TreeViewDes::EditMenu(Bar& menu) +{ + menu.Add(tree.IsCursor(), "Copy current path to clipboard", [=] { CopyPath(); }); +} + +void TreeViewDes::RestoreEditPos() +{ + pos.GetAdd(filename + "\n" + GetId()).Restore(filetime, tree); +} + +void TreeViewDes::SaveEditPos() +{ + pos.GetAdd(filename + "\n" + GetId()).Save(filetime, tree); +} + +INITIALIZER(TreeViewDes) +{ + RegisterGlobalSerialize("TreeViewDes", [](Stream& s) { + int version = 0; + s / version; + s % TreeViewDes::pos; + }); +} diff --git a/uppsrc/ide/Designers/Xml.cpp b/uppsrc/ide/Designers/Xml.cpp new file mode 100644 index 000000000..cd1360c4c --- /dev/null +++ b/uppsrc/ide/Designers/Xml.cpp @@ -0,0 +1,86 @@ +#include + +void XmlViewDes::CopyPath() +{ + String path; + int id = tree.GetCursor(); + while(id >= 0) { + String tag = tree.Get(id); + if(tag.GetCount()) + path = "[" + AsCString(tag) + "]" + path; + id = tree.GetParent(id); + } + WriteClipboardText(path); +} + +String XmlViewDes::Load0(const String& data) { + XmlParser p(data); + + String parsingError; + + try { + while(!p.IsEof()) + Load0(0, p); + } + catch(const XmlError& e) { + parsingError = e; + } + + if(!parsingError.GetCount() && !tree.GetChildCount(0)) + parsingError = "Not found any XML tags"; + + return parsingError; +} + +void XmlViewDes::Load0(int parent, XmlParser& p) +{ + if(p.IsTag()) { + String tag = p.ReadTag(); + String txt = tag; + for(int i = 0; i < p.GetAttrCount(); i++) + txt << ' ' << p.GetAttr(i) << "=\"" << p[i] << "\""; + parent = tree.Add(parent, IdeImg::XmlTag(), tag, txt); + while(!p.End()) { + if(p.IsEof()) + throw XmlError("Unexpected end of text"); + Load0(parent, p); + } + } + else + if(p.IsText()) + tree.Add(parent, IdeImg::XmlText(), Null, NormalizeSpaces(p.ReadText())); + else + if(p.IsPI()) + tree.Add(parent, IdeImg::XmlPI(), Null, NormalizeSpaces(p.ReadPI())); + else + if(p.IsDecl()) + tree.Add(parent, IdeImg::XmlDecl(), Null, NormalizeSpaces(p.ReadDecl())); + else + if(p.IsComment()) + tree.Add(parent, IdeImg::XmlComment(), Null, NormalizeSpaces(p.ReadComment())); + else + throw XmlError("Unexpected input"); +} + +struct XmlDesModule : public IdeModule { + virtual String GetID() { return "XmlDesModule"; } + + virtual bool AcceptsFile(const char *path) { + return ToLower(GetFileExt(path)) == ".xml"; + } + + virtual IdeDesigner *CreateDesigner(const char *path, byte) { + if(!AcceptsFile(path)) + return NULL; + XmlViewDes *d = new XmlViewDes; + if(d->Load(path)) + return d; + delete d; + return NULL; + } +}; + +INITIALIZER(XmlViewDes) +{ + RegisterIdeModule(Single()); +} diff --git a/uppsrc/ide/idebar.cpp b/uppsrc/ide/idebar.cpp index 35f70b753..797cd8cad 100644 --- a/uppsrc/ide/idebar.cpp +++ b/uppsrc/ide/idebar.cpp @@ -217,7 +217,7 @@ void Ide::Edit(Bar& menu) menu.MenuSeparator(); } else - if(editastext.Find(editfile) >= 0 && IsDesignerFile(editfile)) { + if(editastext.Find(editfile) >= 0/* && IsDesignerFile(editfile)*/) { menu.Add(AK_DESIGNER, THISBACK(EditUsingDesigner)) .Help("Edit using the designer (not as text)"); menu.MenuSeparator(); diff --git a/uppsrc/ide/idefile.cpp b/uppsrc/ide/idefile.cpp index 604f5d5d7..081ab6241 100644 --- a/uppsrc/ide/idefile.cpp +++ b/uppsrc/ide/idefile.cpp @@ -458,12 +458,12 @@ void Ide::EditFile0(const String& path, byte charset, int spellcheck_comments, c if(designer) { editpane.Add(designer->DesignerCtrl().SizePos()); + designer->DesignerCtrl().SetFocus(); designer->RestoreEditPos(); if(filetabs) tabs.SetAddFile(editfile); MakeTitle(); SetBar(); - designer->SetFocus(); editor.SyncNavigatorShow(); return; }