From b46af0a49b414c5660d1635fe047b2ffce43f9fe Mon Sep 17 00:00:00 2001 From: kohait Date: Sat, 17 Sep 2011 19:20:31 +0000 Subject: [PATCH] bazaar: CtrlProp: simplification of PropEditCtrl with general ValueAccessorEdit Ctrls; Property: virtual fixes git-svn-id: svn://ultimatepp.org/upp/trunk@3876 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- bazaar/CtrlProp/CtrlProp.upp | 4 +- bazaar/CtrlProp/PropEdit.cpp | 146 ++---------------- bazaar/CtrlProp/PropEdit.h | 23 +-- bazaar/CtrlProp/PropList.h | 2 + bazaar/CtrlProp/init | 1 + bazaar/Property/Property.h | 10 +- .../ValueAccessorEdit/ValueAccessorEdit.cpp | 146 ++++++++++++++++++ bazaar/ValueAccessorEdit/ValueAccessorEdit.h | 87 +++++++++++ .../ValueAccessorEdit.lay} | 2 +- .../ValueAccessorEdit/ValueAccessorEdit.upp | 14 ++ bazaar/ValueAccessorEdit/init | 7 + 11 files changed, 282 insertions(+), 160 deletions(-) create mode 100644 bazaar/ValueAccessorEdit/ValueAccessorEdit.cpp create mode 100644 bazaar/ValueAccessorEdit/ValueAccessorEdit.h rename bazaar/{CtrlProp/PropEdit.lay => ValueAccessorEdit/ValueAccessorEdit.lay} (63%) create mode 100644 bazaar/ValueAccessorEdit/ValueAccessorEdit.upp create mode 100644 bazaar/ValueAccessorEdit/init diff --git a/bazaar/CtrlProp/CtrlProp.upp b/bazaar/CtrlProp/CtrlProp.upp index 0c4bb902b..ff3e5edc3 100644 --- a/bazaar/CtrlProp/CtrlProp.upp +++ b/bazaar/CtrlProp/CtrlProp.upp @@ -5,7 +5,8 @@ uses LogPosCtrl, ValueCtrl, Property, - Gen; + Gen, + ValueAccessorEdit; file PropList.h, @@ -13,7 +14,6 @@ file PropList.lay, PropEdit.h, PropEdit.cpp, - PropEdit.lay, CtrlProp.h, Props readonly separator, CtrlPropCommon.h, diff --git a/bazaar/CtrlProp/PropEdit.cpp b/bazaar/CtrlProp/PropEdit.cpp index 87b60918a..2374b5d5e 100644 --- a/bazaar/CtrlProp/PropEdit.cpp +++ b/bazaar/CtrlProp/PropEdit.cpp @@ -2,43 +2,10 @@ NAMESPACE_UPP -PropEditCtrl::PropEditCtrl() -{ - CtrlLayout(*this); - ac.AddColumn("Property"); - ac.AddColumn("Value"); - ac.AddColumn("Reload").Ctrls(THISBACK(ReloadFactory)); - ac.ColumnWidths("3 6 1"); - //ac.WhenUpdateRow = THISBACK(OnUpdateCurrentRow); only invoked after cursor leaves the edited row, but we need live -} - -void PropEditCtrl::ReloadFactory(int i, One& o) -{ - Button* b = new Button(); - b->SetImage(CtrlImg::Toggle); - b->WhenAction = THISBACK1(ReloadAction, i); - o.Attach(b); -} - -void PropEditCtrl::ReloadAction(int i) -{ - int ii = am.Find(ac.Get(i, 0)); - if(ii<0) return; - Value v; - if(!am[ii].get(v)) return; - ac.Set(i, 1, v); -} - -void PropEditCtrl::Updated() -{ - for(int i = 0; i < ac.GetCount(); i++) - ReloadAction(i); -} - void PropEditCtrl::UpdateCtrl() { - ac.Clear(); - am.Clear(); + ClearMap(); + am.Clear(); if(!ctrl) return; //init local accessor map @@ -48,71 +15,26 @@ void PropEditCtrl::UpdateCtrl() if(ami) am <<= ami->GetAccessorMap(); else if(!Props::SetupAccessorMap(*ctrl, am)) return; - for(int i = 0, k = 0; i < am.GetCount(); i++) + SetMap(&am); + + for(int i = 0; i < avae.GetCount(); i++) { - String tag = am.GetKey(i); - ValueAccessor& a = am[i]; - Value v; - - if(a.get && !a.get(v)) //if cant get a gettable - continue; - ac.Set(k, 0, tag); - ac.Set(k, 1, v); //forwarded to controls when specified - - if(a.get && a.set) + ValueAccessorEdit& c = avae[i]; + if(ValueAccessorCtrl* vac = dynamic_cast(&c)) { - One oc; - DefaultValueEditor(oc, v); - { - //LogPosCtrl needs instance infos to live show changes - if(LogPosCtrl* ple = dynamic_cast(~oc)) - ple->Set(*ctrl); - } - (*oc) <<= THISBACK1(OnUpdateRow, k); //for live editing, unlike WhenUpdateRow - ac.SetCtrl(k, 1, oc.Detach()); //owned - ++k; - } - else if(a.get) - { - StaticText* pc = new StaticText(); - pc->SetText(AsString(v)); - ac.SetCtrl(k, 1, pc); //owned - ++k; - } - else if(a.set) - { - //FIXME needs to know which type - //meanwhile, we let user choose - ValueCtrl* pc = new ValueCtrl(); - (*pc) <<= THISBACK1(OnUpdateRow, k); //for live editing, unlike WhenUpdateRow - ac.SetCtrl(k, 1, pc); //owned - ++k; - } - else - { - ASSERT(0); //Property without accessors + //LogPosCtrl needs instance infos to live show changes + if(LogPosCtrl* ple = dynamic_cast(~vac->oc)) + ple->Set(*ctrl); } } - ac.Layout(); - //ac.UpdateRefresh(); } -void PropEditCtrl::OnUpdateRow(int i) +void PropEditCtrl::OnAction() { - am[i].set(ac.Get(i, 1)); - Action(); if(!ctrl) return; ctrl->UpdateActionRefresh(); //propagate user action } -void PropEditCtrl::OnUpdateCurrentRow() -{ - if(!ac.IsCursor()) return; //FIXME Option Focus issue - int ii = am.Find(ac.Get(0)); - if(ii<0) return; - OnUpdateRow(ii); -} - // PropEdit::PropEdit() @@ -123,50 +45,4 @@ PropEdit::PropEdit() //WhenDeactivate = THISBACK1(RejectBreak, int(IDCANCEL)); } -void PropEdit::Serialize(Stream& s) -{ - const AccessorMap& am = pec.GetAccessorMap(); - if(s.IsStoring()) - { - for(int i = 0; i < am.GetCount(); i++) - { - const ValueAccessor& a = am[i]; - Value v; - if(a.get && !a.get(v)) continue; //if cant get a gettable - if(!a.get || !a.set) continue; - RLOG("Storing: " << i << " => " << v); - s % i % v; - } - int i = -1; - s % i; //end marker - } - if(s.IsLoading()) - { - int i = -1; - do - { - int i = -1; - s % i; - if(i<0) break; - ASSERT(i<=am.GetCount()); - - Value v, _v; - s % _v; - - const ValueAccessor& a = am[i]; - if(a.get && !a.get(v)) { ASSERT(0); continue; }//if cant get a gettable - if(!a.get || !a.set) { ASSERT(0); continue; } - - RLOG("Loading: " << i << " => " << v); - - if(v != _v) - { - RLOG("setting: " << _v); - a.set(_v); - } - } - while(1); - } -} - END_UPP_NAMESPACE diff --git a/bazaar/CtrlProp/PropEdit.h b/bazaar/CtrlProp/PropEdit.h index 8665b34db..a9095f8e8 100644 --- a/bazaar/CtrlProp/PropEdit.h +++ b/bazaar/CtrlProp/PropEdit.h @@ -1,38 +1,27 @@ #ifndef _CtrlProp_PropEdit_h_ #define _CtrlProp_PropEdit_h_ -#include -#include -#include +#include NAMESPACE_UPP -#define LAYOUTFILE -#include - -class PropEditCtrl : public WithPropEditLay +class PropEditCtrl : public AccessorMapCtrl { public: typedef PropEditCtrl CLASSNAME; - PropEditCtrl(); + PropEditCtrl() { WhenAction = THISBACK(OnAction); } - virtual void Updated(); - - void SetCtrl(Ctrl* c) { if(ctrl != c) { ctrl = c; UpdateCtrl(); } UpdateRefresh(); } + void SetCtrl(Ctrl* c) { if(ctrl != c) { ctrl = c; UpdateCtrl(); } Update(); } Ctrl* GetCtrl() const { return ctrl; } void ClearCtrl() { SetCtrl(NULL); } virtual Value GetData() const { return RawToValue(ctrl); } virtual void SetData(const Value& v) { SetCtrl(RawValue::Extract(v)); } - void OnUpdateRow(int i); - void OnUpdateCurrentRow(); - + void OnAction(); const AccessorMap& GetAccessorMap() const { return am; } protected: - void ReloadFactory(int i, One& o); - void ReloadAction(int i); void UpdateCtrl(); Ctrl* ctrl; @@ -50,8 +39,6 @@ public: using PopUpC::PopUp; void PopUp(Ctrl* owner, Ctrl& e) { pec.SetCtrl(&e); PopUpC::PopUp(owner); } - virtual void Serialize(Stream& s); - PropEditCtrl pec; }; diff --git a/bazaar/CtrlProp/PropList.h b/bazaar/CtrlProp/PropList.h index cc13d400c..b9366a115 100644 --- a/bazaar/CtrlProp/PropList.h +++ b/bazaar/CtrlProp/PropList.h @@ -25,6 +25,8 @@ public: virtual Value GetData() const { return RawToValue(ctrl); } virtual void SetData(const Value& v) { SetCtrl(RawValue::Extract(v)); } + virtual void Serialize(Stream& s) { GuiLock __; for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) q->Serialize(s); } + protected: Ctrl* ctrl; }; diff --git a/bazaar/CtrlProp/init b/bazaar/CtrlProp/init index 5c3b9c031..a61901296 100644 --- a/bazaar/CtrlProp/init +++ b/bazaar/CtrlProp/init @@ -5,6 +5,7 @@ #include "ValueCtrl/init" #include "Property/init" #include "Gen/init" +#include "ValueAccessorEdit/init" #define BLITZ_INDEX__ F8F3D3A8C39C8921944B39C96DAA6C238 #include "Ctrl.icpp" #undef BLITZ_INDEX__ diff --git a/bazaar/Property/Property.h b/bazaar/Property/Property.h index 8134eb953..c61d9cd5a 100644 --- a/bazaar/Property/Property.h +++ b/bazaar/Property/Property.h @@ -13,9 +13,10 @@ struct Property Property(const S& s, const G& g) : set(s), get(g) {} + virtual ~Property() {} - const T& Set(const T& a) const { ASSERT(set); set(a); return a; } - T Get() const { ASSERT(get); T t; get(t); return t; } + virtual const T& Set(const T& a) const { ASSERT(set); set(a); return a; } + virtual T Get() const { ASSERT(get); T t; get(t); return t; } inline T operator= (const T& a) const { return Set(a); } inline operator T() const { return Get(); } @@ -35,9 +36,10 @@ struct Accessor Accessor(const S& s, const G& g) : set(s), get(g) {} + virtual ~Accessor() {} - bool Set(const T& a) const { ASSERT(set); return set(a); } - bool Get(T& a) const { ASSERT(get); return get(a); } + virtual bool Set(const T& a) const { ASSERT(set); return set(a); } + virtual bool Get(T& a) const { ASSERT(get); return get(a); } inline T operator= (const T& a) const { Set(a); return a; } inline operator T() const { T t; Get(t); return t; } diff --git a/bazaar/ValueAccessorEdit/ValueAccessorEdit.cpp b/bazaar/ValueAccessorEdit/ValueAccessorEdit.cpp new file mode 100644 index 000000000..d713207c2 --- /dev/null +++ b/bazaar/ValueAccessorEdit/ValueAccessorEdit.cpp @@ -0,0 +1,146 @@ +#include "ValueAccessorEdit.h" + +NAMESPACE_UPP + +void ValueAccessorEdit::Serialize(Stream& s) +{ + if(!tg) return; + Value v; + if(tg->get && !tg->get(v)) return; //if cant get a gettable + if(!tg->get || !tg->set) return; + if(s.IsStoring()) + s % v; + if(s.IsLoading()) + { + Value _v; + s % _v; + if(v != _v) + tg->set(_v); + } +} + +// + +//if nesseeccary, changes the editor of the accessor get/set type underneath +void ValueAccessorCtrl::UpdateTarget() +{ + oc.Clear(); + if(!tg) return; + + Value v; + if(tg->get && !tg->get(v)) //if cant get a gettable + return; + + if(tg->get && tg->set) + { + DefaultValueEditor(oc, v); + } + else if(tg->get) + { + StaticText* pc = new StaticText(); pc->SetText(AsString(v)); oc = pc; + } + else if(tg->set) + { + //FIXME needs to know which type + //meanwhile, we let user choose + ValueCtrl* pc = new ValueCtrl(); oc = pc; + } + else + { + ASSERT(0); //Property without accessors + return; + } + (*oc) <<= THISBACK(OnAction); + Add(oc->SizePos()); +} + +void ValueAccessorCtrl::Updated() +{ + if(!tg) return; + Value v; + if(!tg->get(v)) return; + if(oc.IsEmpty()) return; + oc->SetData(v); +} + +// + +AccessorMapCtrl::AccessorMapCtrl() +{ + CtrlLayout(*this); + ac.AddColumn("Property"); + ac.AddColumn("Value"); + ac.AddColumn("Reload").Ctrls(THISBACK(ReloadFactory)); + ac.ColumnWidths("3 6 1"); +} + +void AccessorMapCtrl::ReloadFactory(int i, One& o) +{ + Button* b = new Button(); + b->SetImage(CtrlImg::Toggle); + b->WhenAction = THISBACK1(ReloadAction, i); + o.Attach(b); +} + +void AccessorMapCtrl::ReloadAction(int i) +{ + Ctrl* c = ac.GetCtrl(i, 1); + if(!c) return; + c->Update(); +} + +void AccessorMapCtrl::Updated() +{ + for(int i = 0; i < ac.GetCount(); i++) + ReloadAction(i); +} + +void AccessorMapCtrl::UpdateMap() +{ + ac.Clear(); + avae.Clear(); + if(!am) return; + + for(int i = 0; i < am->GetCount(); i++) + { + String tag = am->GetKey(i); + ValueAccessor& a = (*am)[i]; + + ac.Set(i, 0, tag); + + ValueAccessorEdit* ep = NULL; + if(ValueAccessorInstance* vi = dynamic_cast(&a)) + { + //special ValueAccessors, need their own editor + Value q = vi->TypeOf(); //defines which editor + + Instancer::MapType& map = Instancer::Map(); + int ix = map.Find(q); + if(ix>=0) + ep = map[ix](); + } + + if(!ep) //second chance, default + ep = new ValueAccessorCtrl(); + + ASSERT(ep); + ep->SetTarget(&a); + + (*ep) <<= Proxy(WhenAction); + ValueAccessorEdit& c = avae.Add(tag, ep); + ac.SetCtrl(i, 1, c, false); //independant control + } + ac.Layout(); + //ac.UpdateRefresh(); +} + +void AccessorMapCtrl::Serialize(Stream& s) +{ + GuiLock __; + for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) + q->Serialize(s); + for(int i = 0; i < avae.GetCount(); i++) + avae[i].Serialize(s); +} + +END_UPP_NAMESPACE diff --git a/bazaar/ValueAccessorEdit/ValueAccessorEdit.h b/bazaar/ValueAccessorEdit/ValueAccessorEdit.h new file mode 100644 index 000000000..1def6e126 --- /dev/null +++ b/bazaar/ValueAccessorEdit/ValueAccessorEdit.h @@ -0,0 +1,87 @@ +#ifndef _ValueAccessorEdit_ValueAccessorEdit_h +#define _ValueAccessorEdit_ValueAccessorEdit_h + +#include +using namespace Upp; + +#include +#include +#include + +NAMESPACE_UPP + +class ValueAccessorEdit : public ParentCtrl { +public: + typedef ValueAccessorEdit CLASSNAME; + typedef ValueAccessor VA; + + //need get set data because of serialize + virtual void SetData(const Value& v) { if(!tg) return; tg->set(v); Update(); } + virtual Value GetData() const { if(!tg) return Null; Value v; tg->get(v); return v; } + + virtual void SetTarget(ValueAccessor* va) { if(tg != va) { tg = va; UpdateTarget(); } Update(); } + virtual ValueAccessor* GetTarget() const { return tg; } + void ClearTarget() { SetTarget(NULL); } + + virtual void Serialize(Stream& s); + +protected: + virtual void UpdateTarget() =0; //should do the init on target change + + ValueAccessor* tg; +}; + +//this is the default ValueAccessor Editor, it loads the respective default editors for the value type of get/set +class ValueAccessorCtrl : public ValueAccessorEdit +{ +public: + typedef ValueAccessorCtrl CLASSNAME; + + virtual void Updated(); //will load (get) data from ValueAccessor target + void OnAction() { if(!tg) return; Value v = oc->GetData(); tg->set(v); Action(); } + + One oc; + +protected: + void UpdateTarget(); +}; + +//for usage with Instancer +typedef Instance ValueAccessorInstance; + +//depending on the ValueAccessor type, there might be a different editor or presenter +//these types should be ValueAccessorInstance derived +//all editors are found in Instancer, organized by ValueAccessorInstance::TypeOf() + +#define LAYOUTFILE +#include + +class AccessorMapCtrl : public WithValueAccessorEditLayout +{ +public: + typedef AccessorMapCtrl CLASSNAME; + AccessorMapCtrl(); + + virtual void Updated(); + + void SetMap(AccessorMap* a) { if(am != a) { am = a; UpdateMap(); } Update(); } + AccessorMap* GetMap() const { return am; } + void ClearMap() { SetMap(NULL); } + + virtual Value GetData() const { return RawToValue(am); } + virtual void SetData(const Value& v) { SetMap(RawValue::Extract(v)); } + virtual void Serialize(Stream& s); + +protected: + void ReloadFactory(int i, One& o); + void ReloadAction(int i); + void UpdateMap(); + + AccessorMap* am; + ArrayMap avae; +}; + +END_UPP_NAMESPACE + +#endif + diff --git a/bazaar/CtrlProp/PropEdit.lay b/bazaar/ValueAccessorEdit/ValueAccessorEdit.lay similarity index 63% rename from bazaar/CtrlProp/PropEdit.lay rename to bazaar/ValueAccessorEdit/ValueAccessorEdit.lay index 54173db8d..ea480cf07 100644 --- a/bazaar/CtrlProp/PropEdit.lay +++ b/bazaar/ValueAccessorEdit/ValueAccessorEdit.lay @@ -1,4 +1,4 @@ -LAYOUT(PropEditLay, 400, 200) +LAYOUT(ValueAccessorEditLayout, 300, 100) ITEM(ArrayCtrl, ac, Header(false).HSizePosZ(0, 0).VSizePosZ(0, 0)) END_LAYOUT diff --git a/bazaar/ValueAccessorEdit/ValueAccessorEdit.upp b/bazaar/ValueAccessorEdit/ValueAccessorEdit.upp new file mode 100644 index 000000000..325abfc5f --- /dev/null +++ b/bazaar/ValueAccessorEdit/ValueAccessorEdit.upp @@ -0,0 +1,14 @@ +uses + CtrlLib, + Property, + Gen, + ValueCtrl; + +file + ValueAccessorEdit.h, + ValueAccessorEdit.cpp, + ValueAccessorEdit.lay; + +mainconfig + "" = "GUI SSE2"; + diff --git a/bazaar/ValueAccessorEdit/init b/bazaar/ValueAccessorEdit/init new file mode 100644 index 000000000..7d0f7ce85 --- /dev/null +++ b/bazaar/ValueAccessorEdit/init @@ -0,0 +1,7 @@ +#ifndef _ValueAccessorEdit_icpp_init_stub +#define _ValueAccessorEdit_icpp_init_stub +#include "CtrlLib/init" +#include "Property/init" +#include "Gen/init" +#include "ValueCtrl/init" +#endif