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
This commit is contained in:
kohait 2011-09-17 19:20:31 +00:00
parent 7be80375f6
commit b46af0a49b
11 changed files with 282 additions and 160 deletions

View file

@ -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,

View file

@ -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<Ctrl>& 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<Ctrl>::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<ValueAccessorCtrl*>(&c))
{
One<Ctrl> oc;
DefaultValueEditor(oc, v);
{
//LogPosCtrl needs instance infos to live show changes
if(LogPosCtrl* ple = dynamic_cast<LogPosCtrl*>(~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<LogPosCtrl*>(~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

View file

@ -1,38 +1,27 @@
#ifndef _CtrlProp_PropEdit_h_
#define _CtrlProp_PropEdit_h_
#include <Property/Property.h>
#include <Gen/VTypes.h>
#include <ValueCtrl/ValueCtrl.h>
#include <ValueAccessorEdit/ValueAccessorEdit.h>
NAMESPACE_UPP
#define LAYOUTFILE <CtrlProp/PropEdit.lay>
#include <CtrlCore/lay.h>
class PropEditCtrl : public WithPropEditLay<ParentCtrl>
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<Ctrl*>::Extract(v)); }
void OnUpdateRow(int i);
void OnUpdateCurrentRow();
void OnAction();
const AccessorMap& GetAccessorMap() const { return am; }
protected:
void ReloadFactory(int i, One<Ctrl>& 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;
};

View file

@ -25,6 +25,8 @@ public:
virtual Value GetData() const { return RawToValue(ctrl); }
virtual void SetData(const Value& v) { SetCtrl(RawValue<Ctrl*>::Extract(v)); }
virtual void Serialize(Stream& s) { GuiLock __; for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) q->Serialize(s); }
protected:
Ctrl* ctrl;
};

View file

@ -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__

View file

@ -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; }

View file

@ -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<Ctrl>& 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<ValueAccessorInstance*>(&a))
{
//special ValueAccessors, need their own editor
Value q = vi->TypeOf(); //defines which editor
Instancer<ValueAccessorEdit>::MapType& map = Instancer<ValueAccessorEdit>::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

View file

@ -0,0 +1,87 @@
#ifndef _ValueAccessorEdit_ValueAccessorEdit_h
#define _ValueAccessorEdit_ValueAccessorEdit_h
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
#include <Property/Property.h>
#include <Gen/Gen.h>
#include <ValueCtrl/ValueCtrl.h>
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<Ctrl> oc;
protected:
void UpdateTarget();
};
//for usage with Instancer<ValueAccessor>
typedef Instance<ValueAccessor> 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<ValueAccessorEdit>, organized by ValueAccessorInstance::TypeOf()
#define LAYOUTFILE <ValueAccessorEdit/ValueAccessorEdit.lay>
#include <CtrlCore/lay.h>
class AccessorMapCtrl : public WithValueAccessorEditLayout<ParentCtrl>
{
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<AccessorMap*>::Extract(v)); }
virtual void Serialize(Stream& s);
protected:
void ReloadFactory(int i, One<Ctrl>& o);
void ReloadAction(int i);
void UpdateMap();
AccessorMap* am;
ArrayMap<String, ValueAccessorEdit> avae;
};
END_UPP_NAMESPACE
#endif

View file

@ -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

View file

@ -0,0 +1,14 @@
uses
CtrlLib,
Property,
Gen,
ValueCtrl;
file
ValueAccessorEdit.h,
ValueAccessorEdit.cpp,
ValueAccessorEdit.lay;
mainconfig
"" = "GUI SSE2";

View file

@ -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