|
|
Home » Developing U++ » U++ Developers corner » Proposed change to U++ to allow owning children.
Proposed change to U++ to allow owning children. [message #31586] |
Wed, 16 March 2011 17:18 |
Lance
Messages: 534 Registered: March 2007
|
Contributor |
|
|
Newbie proposes changes to the library? Well, this is another proof of how well U++ is designed and implemented.
But will this break the "Everything belongs somewhere" principle? I don't think so. Owned Ctrls will be taken care of by their parents who own them. So they belong to their parents. As it's clearly defined and easily determineable, the principle is actually perfectly confirmed.
1. Advantage of allowing parent Ctrl to own certain child.
a. sometimes it's more natural to allocate Ctrl's on the heap;
b. it can relieve the programmer(library user) from keeping track of uninterested objects only to properly destroy them afterwards;
c. if used with discretion, it can reduce the memory footprint of generated program. I will give some examples if you don't believe me.
2. Will the proposed change break any existing code?
No. If not impossible, it's very very unprobable that the changes will affect any existing codes that was not aware of it
3. How signicant are the changes in the current libary codes to allow for children ownship?
It's minimal. I cannot handle it if it's too big as my knowledge with U++ is still very limited. About 6-10 function has been changed, another flag (1 bit) is added which will not increase memory requirement of Ctrl objects.
Here is a list of the changes (may not be complete)
A. In Ctrl.h
A.1
#ifdef PLATFORM_X11
bool ignoretakefocus:1;
#endif
bool owned:1; // <--This line
static Ptr<Ctrl> eventCtrl;
AND
// proposed changed, open door for libary developer
// but still concealed from library user
//
bool IsOwned()const{ return owned; }
void SetOwned(bool v=true){ owned=v; }
AND
// flag: 0 - not to be owned, eg for Ctrl alloc on stack or otherwise maintained
// 1 - yes, own the child, will be responsible for its destruction
// 2 or other values - the owned flag has been properly set, just use it.
void AddChild(Ctrl *child,int flag=2);
void AddChild(Ctrl *child, Ctrl *insafter,int flag=2);
void AddChildBefore(Ctrl *child, Ctrl *insbefore, int flag=2);
// seel RemoveChild0 for explanation of detachOnly parameter
//
void RemoveChild(Ctrl *child, bool detachOnly=false);
AND
// flag 2 means to leave the owned flag untouched( already properly set)
void Add(Ctrl& ctrl, int flag=2) { AddChild(&ctrl, flag); }
To be continued. I am running out of my time.
[Updated on: Wed, 16 March 2011 17:53] Report message to a moderator
|
|
|
|
Re: Proposed change to U++ to allow owning children. [message #31588 is a reply to message #31586] |
Wed, 16 March 2011 17:29 |
Lance
Messages: 534 Registered: March 2007
|
Contributor |
|
|
AND
// when a child is removed, it should be delete'd if its @param owned
// flag is true. Sometimes we may want to keep it alive and transfer the
// ownership to some other Ctrl, in this case, we should call the following
// function with @param detachOnly set to true
//
void RemoveChild0(Ctrl *q, bool detachOnly=false);
And corresponding changes in the CtrlChild.cpp file. I have attached these files. The changes have been commented, so it should stand out. I am on a library computer, session time is limited.
-
Attachment: CtrlCore.h
(Size: 56.75KB, Downloaded 456 times)
[Updated on: Wed, 16 March 2011 20:05] Report message to a moderator
|
|
|
|
Re: Proposed change to U++ to allow owning children. [message #31590 is a reply to message #31586] |
Wed, 16 March 2011 17:39 |
Lance
Messages: 534 Registered: March 2007
|
Contributor |
|
|
kohait00:
I have implemented the requested changes. Just replace existing files with my attached version (make backup before doing that) and you should be able to use it immediately.
Here is some sample how you can use it.
struct MyButton : Moveable<MyButton>, Button
{
// note: alwasy default to false becasue
// existing U++ user are used to this behaviour
//
MyButton(bool toBeOwned=false)
{
SetOwned(toBeOwned);
}
virtual ~MyButton()
{
DUMP("Yes, I am properly destructed!!!");
}
};
class App : public TopWindow
{
public:
App()
{
Button * p=new MyButton(true);
Button * p2=new MyButton();
p->SetLabel("Button 1").TopSizeZ(2,20).LeftSize(2, 60);
p2->SetLabel("Button 2").TopSizeZ(40,20).LeftSize(2, 60);
Add(*p); // p will be destructed because we SetOwned in
// its constructor;
// or (*this) << p;
Add(*p2, 1);
}
};
Please try it and let me know there is any problem. I am not very sure if I changed anything in Ctrl.cpp.
[Updated on: Wed, 16 March 2011 17:40] Report message to a moderator
|
|
|
|
Re: Proposed change to U++ to allow owning children. [message #31593 is a reply to message #31592] |
Wed, 16 March 2011 18:10 |
Lance
Messages: 534 Registered: March 2007
|
Contributor |
|
|
AFAIK, that has already been taken care of by AddChild0 or something like that.
void Ctrl::AddChild(Ctrl *q, Ctrl *p, int flag)
{
GuiLock __;
ASSERT(q);
LLOG("Add " << UPP::Name(q) << " to: " << Name());
if(p == q) return;
bool updaterect = true;
bool owned;
switch(flag)
{
default: // note, all value of flag other than 0&1 in this branch
owned=q->owned;
break;
case 0:
case 1:
q->owned=flag==1;
}
///if(dynamic_cast<q
if(q->parent) {
ASSERT(!q->inframe);
//************************
// following couple of lines takes care of the issues you raised.
//*************************
if(q->parent == this) {
RemoveChild0(q, true); // detach only
updaterect = false;
}
else
q->parent->RemoveChild(q, true); // detach only }
q->parent = this;
if(p) {
ASSERT(p->parent == this);
q->prev = p;
q->next = p->next;
if(p == lastchild)
lastchild = q;
else
p->next->prev = q;
p->next = q;
}
else
if(firstchild) {
q->prev = NULL;
q->next = firstchild;
firstchild->prev = q;
firstchild = q;
}
else {
ASSERT(lastchild == NULL);
firstchild = lastchild = q;
q->prev = q->next = NULL;
}
q->CancelModeDeep();
if(updaterect)
q->UpdateRect();
ChildAdded(q);
q->ParentChange();
if(updaterect && GetTopCtrl()->IsOpen())
q->StateH(OPEN);
if(dynamic_cast<DHCtrl *>(q))
SyncDHCtrl();
}
[Updated on: Wed, 16 March 2011 18:11] Report message to a moderator
|
|
|
|
|
|
|
|
|
Re: Proposed change to U++ to allow owning children. [message #31631 is a reply to message #31626] |
Fri, 18 March 2011 14:39 |
Lance
Messages: 534 Registered: March 2007
|
Contributor |
|
|
Hi Kohait00:
Internally, the owned flag has but 2 possible values: true or false. When a Ctrl is removed from its parent by RemoveChild family of functions, there are 3 scenarios:
1. it's owned and should be automatically deleted by the parent control thereby it's destructor is called and the memory in the heap to house the Ctrl is also freed;
2. it's not owned. Basically this is the behaviour before the owned flag is introduced. So business as usual. Exisiting code should not feel any difference. They don't know anything about the owned flag, don't rely on it and will not be bothered by it.
3. it's owned and should be leave alone. Techinically, it should be named DetachChild. But again, we don't want to any unexpected impact to users who don't know the existence of this newly installed capability. So I add an additionaly parameter detachOnly[ to the RemoveChild family of functions, with carefully chosen default value so as no to break existing code. As you can see, in the AddChild function implementation I highlightly in a previous post, RemoveChild is called with detachOnly set to true so that it's not destroyed as our realy intention is just to change a dad for it.
Also, it could be useful to library user. User programs can detach a child and take appropriate actions. The only thing to remember is once a child is detached, the one who detach it has its ownership. It can either free it, or entrust it to someone else. The principle of "Everything belongs somewhere" is consistently confirmed.
|
|
|
Re: Proposed change to U++ to allow owning children. [message #31635 is a reply to message #31626] |
Fri, 18 March 2011 15:21 |
Lance
Messages: 534 Registered: March 2007
|
Contributor |
|
|
kohait00 wrote on Fri, 18 March 2011 11:01 | the flag handling should be better IMHO.
flag = 2 is quite bad, leaving things untouched...
it should determine itself, when the control is owned by someone else, to take over the responsibility
|
Sorry I misinterpreted you. Your point is valid.
Yes it's possible to revise flag from tribool to bool for all the AddChild*(and Add) functions. The implementation of the function will need to be changed accordingly.
Another option is to promote SetOwned(bool owned=false) from protected to public, and keep AddChild prototypes untouched.
...
public:
...
// query owned flag
bool IsOwned()const{ return owned; }
Ctrl& Owned(bool b=false){ owned=b; return *this; }
...
};
And the way it's used will be changed to something like this
class App: public TopWindow{
...
App()
{
Button * p = new Button();
Button * p2 = new Button();
this->Add(p.Owned());
this->Add(p2); // Error, p2 is not owned.
// fixed p2;
p2.Owned();
};
Anyway, the detail can be polished and fixed to satisfy majority of users as long as there is no big holes in the design.
[Updated on: Fri, 18 March 2011 15:25] Report message to a moderator
|
|
|
|
Re: Proposed change to U++ to allow owning children. [message #31641 is a reply to message #31638] |
Fri, 18 March 2011 16:22 |
Lance
Messages: 534 Registered: March 2007
|
Contributor |
|
|
Now we have a much cleaner solution thanks to Kohait00's input.
Brief list of changes to the current libary code:
In CtrlCore.h
Added to Ctrl class
bool owned : 1;
And 2 public members
bool IsOwned()const{ return owned; }
Ctrl& Owned(bool v=true){ owned=v; return *this; }
In Ctrl.cpp, initialized owned flag to false
Ctrl::Ctrl() {
GuiLock __;
LLOG("Ctrl::Ctrl");
destroying = false;
owned = false; // <-----This line is added
parent = prev = next = firstchild = lastchild = NULL;
top = NULL;
exitcode = 0;
frame.Add().frame = &NullFrame();
enabled = visible = wantfocus = initfocus = true;
editable = true;
// GLX = false;
#ifdef PLATFORM_WIN32
activex = false;
isdhctrl = false;
#endif
backpaint = IsCompositedGui() ? FULLBACKPAINT : TRANSPARENTBACKPAINT;
inframe = false;
ignoremouse = transparent = false;
caretcx = caretcy = caretx = carety = 0;
SetRect(Rect(0, 0, 0, 0));
inloop = popup = isopen = false;
modify = false;
unicode = false;
popupgrab = false;
fullrefresh = false;
akv = false;
hasdhctrl = false;
}
And in CtrlChild.cpp
// @param: q , the child to be added
// q, an existing child to precede p
void Ctrl::AddChild(Ctrl *q, Ctrl *p)
{
GuiLock __;
ASSERT(q);
LLOG("Add " << UPP::Name(q) << " to: " << Name());
if(p == q) return;
bool updaterect = true;
// remember and change
bool owned=q->owned;
q->Owned(false); // that way it's guarenteed not to be
// accidently delete'd when possibly changing parents
if(q->parent) {
ASSERT(!q->inframe);
if(q->parent == this) {
RemoveChild0(q);
updaterect = false;
}
else
q->parent->RemoveChild(q);
}
q->parent = this;
if(p) {
ASSERT(p->parent == this);
q->prev = p;
q->next = p->next;
if(p == lastchild)
lastchild = q;
else
p->next->prev = q;
p->next = q;
}
else
if(firstchild) {
q->prev = NULL;
q->next = firstchild;
firstchild->prev = q;
firstchild = q;
}
else {
ASSERT(lastchild == NULL);
firstchild = lastchild = q;
q->prev = q->next = NULL;
}
// succesfully added as children of *this, now
// it's perfect time to restore saved owned flag
q->Owned(owned);
q->CancelModeDeep();
if(updaterect)
q->UpdateRect();
ChildAdded(q);
q->ParentChange();
if(updaterect && GetTopCtrl()->IsOpen())
q->StateH(OPEN);
if(dynamic_cast<DHCtrl *>(q))
SyncDHCtrl();
}
.....
void Ctrl::RemoveChild0(Ctrl *q)
{
GuiLock __;
ChildRemoved(q);
q->DoRemove();
q->parent = NULL;
if(q == firstchild)
firstchild = firstchild->next;
if(q == lastchild)
lastchild = lastchild->prev;
if(q->prev)
q->prev->next = q->next;
if(q->next)
q->next->prev = q->prev;
q->next = q->prev = NULL;
if(dynamic_cast<DHCtrl *>(q))
SyncDHCtrl();
// code added to allowed owned child****
if(q->owned)
delete q;
// end code added by Lance
}
void Ctrl::RemoveChild(Ctrl *q)
{
GuiLock __;
if(q->parent != this) return;
q->RefreshFrame();
bool owned=q->IsOwned();
q->Owned(false); // we still need it to be alive
RemoveChild0(q);
q->ParentChange();
if(GetTopCtrl()->IsOpen())
q->StateH(CLOSE);
if( owned )
{
delete q; // this is why the new'd-only requirement.
}
// no need to restore q's owned flag, it's either destroyed or
// its owned flag is correctly set
}
-
Attachment: CtrlCore.rar
(Size: 20.38KB, Downloaded 261 times)
|
|
|
Re: Proposed change to U++ to allow owning children. [message #31642 is a reply to message #31641] |
Fri, 18 March 2011 16:34 |
Lance
Messages: 534 Registered: March 2007
|
Contributor |
|
|
And a sample program using this newly added capability.
#include <CtrlLib/CtrlLib.h>
// http://java.sun.com/docs/books/tutorial/uiswing/start/swingTour.html
using namespace Upp;
struct MyButton : Moveable<MyButton>, Button
{
public:
// should always default to false to confirm with
// existing U++ users habit
//
MyButton(bool toBeOwned=false)
{
if(toBeOwned)
Owned();
}
virtual ~MyButton()
{
String msg=String().Cat()<<"From within MyButton's destructor, with label "<<GetLabel();
DUMP(msg);
}
};
struct ButtonApp : TopWindow {
int count;
MyButton button;
Label label;
void RefreshLabel()
{
label = Format("Number of button clicks %d", count);
}
void Click()
{
++count;
RefreshLabel();
}
typedef ButtonApp CLASSNAME;
ButtonApp()
{
count = 0;
//button=*new MyButton();
Button * p = new MyButton(true);
Button * p2 = new MyButton();
button <<= THISBACK(Click);
button.SetLabel("&I'm an Ultimate++ button!");
Add(button.VCenterPos(20).HCenterPos(200));
Add(label.BottomPos(0, 20).HCenterPos(200));
label.SetAlign(ALIGN_CENTER);
Sizeable().Zoomable();
RefreshLabel();
Add(p->SetLabel("&Another button").TopPosZ(10, 50).LeftPosZ(30, 200)); // becuase MyButton is contructed with proper flag
Add(p2->SetLabel("Heap Button 2").TopPosZ(10, 50).LeftPosZ(250,200).Owned());
}
};
GUI_APP_MAIN
{
ButtonApp().Run();
}
With output:
msg = From within MyButton's destructor, with label I'm an Ultimate++ button!
msg = From within MyButton's destructor, with label Another button
msg = From within MyButton's destructor, with label Heap Button 2
|
|
|
|
|
Goto Forum:
Current Time: Sun Jun 16 15:12:04 CEST 2024
Total time taken to generate the page: 0.02365 seconds
|
|
|