mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
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:
parent
7be80375f6
commit
b46af0a49b
11 changed files with 282 additions and 160 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
146
bazaar/ValueAccessorEdit/ValueAccessorEdit.cpp
Normal file
146
bazaar/ValueAccessorEdit/ValueAccessorEdit.cpp
Normal 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
|
||||
87
bazaar/ValueAccessorEdit/ValueAccessorEdit.h
Normal file
87
bazaar/ValueAccessorEdit/ValueAccessorEdit.h
Normal 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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
14
bazaar/ValueAccessorEdit/ValueAccessorEdit.upp
Normal file
14
bazaar/ValueAccessorEdit/ValueAccessorEdit.upp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
uses
|
||||
CtrlLib,
|
||||
Property,
|
||||
Gen,
|
||||
ValueCtrl;
|
||||
|
||||
file
|
||||
ValueAccessorEdit.h,
|
||||
ValueAccessorEdit.cpp,
|
||||
ValueAccessorEdit.lay;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI SSE2";
|
||||
|
||||
7
bazaar/ValueAccessorEdit/init
Normal file
7
bazaar/ValueAccessorEdit/init
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue