Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
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 Go to next message
Lance is currently offline  Lance
Messages: 526
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. Smile 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 #31587 is a reply to message #31586] Wed, 16 March 2011 17:26 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
i'm currently facing the same problem, to easily create controls in a tree, without keeping them around somwhere else. the use case is to have the Ctrl's edit and manipulate some central Values of the app, where more than one, and different Ctrls can 'point' to the same bit of Value information and the user can create and release those controls. i suppose you have something similar.

AFAIK, the thing of owning Ctrls would make some more changes nessecary. and i dont know if mirek is willing to take the risk of braking some API handling, and actually a rule of thumb, which you outlined.

maybe think of some additional mechanism..

anyway, this question is a design aspect decision.
maybe it is to be considered..
Re: Proposed change to U++ to allow owning children. [message #31588 is a reply to message #31586] Wed, 16 March 2011 17:29 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
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 450 times)

[Updated on: Wed, 16 March 2011 20:05]

Report message to a moderator

Re: Proposed change to U++ to allow owning children. [message #31589 is a reply to message #31586] Wed, 16 March 2011 17:30 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
Registered: March 2007
Contributor
And CtrlChild.cpp
Re: Proposed change to U++ to allow owning children. [message #31590 is a reply to message #31586] Wed, 16 March 2011 17:39 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
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 #31592 is a reply to message #31590] Wed, 16 March 2011 18:01 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
havent tried it yet, but more things that are involved, and need to be checked is at least this:

adding an owned control, which is part of a tree already, to another tree needs to traslate the ownership to the new tree..

i'll try it soon..
but first, i want to hear from mirek if this is worth it at all Smile
Re: Proposed change to U++ to allow owning children. [message #31593 is a reply to message #31592] Wed, 16 March 2011 18:10 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
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 #31595 is a reply to message #31593] Wed, 16 March 2011 18:29 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
Registered: March 2007
Contributor
That's why I praise the design and implementation of U++.

Even though I don't know U++ really well, I can be pretty much sure my solution works or will work with minor refinement.

It can be proved by reasoning:

1. Every child of a Ctrl is itself a Ctrl2. However deep the derivation chain, the virtual destructor of Ctrl will alway be called and there will be only one version of the destructor which I touched.
3. In the destructor of Ctrl, it repeatedly remove each of its children by calling RemoveChild;
4. U++ design guaranteed each Ctrl will have but 1 or 0 parent.
So however ownership is changed during a Ctrl's life time, it will have 1 parent if it was ever assigned a parent. When its parent is destructed, and its owned flag is set to true, it's guaranteed to be destruct by our implementation of RemoveChild family functions.
Re: Proposed change to U++ to allow owning children. [message #31596 is a reply to message #31595] Wed, 16 March 2011 18:35 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
Registered: March 2007
Contributor
I just successfully built TheIDE with the revised library. So it should not affect exsiting code.

Only questions left, will there be some code in the U++ libary that will make use of the bit I assigned to the new memebe, i.e. owned, magically change it, or will some Ctrl derived class decides to remove its children by itself and without make use of Ctrl::RemoveChild family of functions?


If answer to these questions are no, they my way should work (maybe with some more modifications).
Re: Proposed change to U++ to allow owning children. [message #31597 is a reply to message #31596] Wed, 16 March 2011 18:43 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
Registered: March 2007
Contributor
Yet another file that's changed (by insert a single line )

Ctrl.cpp
  • Attachment: Ctrl.cpp
    (Size: 19.35KB, Downloaded 288 times)

[Updated on: Wed, 16 March 2011 19:27]

Report message to a moderator

Re: Proposed change to U++ to allow owning children. [message #31598 is a reply to message #31586] Wed, 16 March 2011 19:24 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
Registered: March 2007
Contributor
Here is the line that's been changed in Ctrl.cpp in case you don't want don't the whole file.

Ctrl::Ctrl() {
	GuiLock __;
	LLOG("Ctrl::Ctrl");
	destroying = false;
	owned = false; // <---This line initialized owned to make
                       // which is necessary!
	parent = prev = next = firstchild = lastchild = NULL;

[Updated on: Wed, 16 March 2011 19:29]

Report message to a moderator

Re: Proposed change to U++ to allow owning children. [message #31619 is a reply to message #31598] Fri, 18 March 2011 02:13 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
Registered: March 2007
Contributor
Not related to this topic.

One little thing that worries me, U++'s support for Chinese Fonts need more work, or may be it's because I don't know how to add more fonts yet. See attached for a sample.

The sample text is:

ultimate++是一个性能优良的C++GUI库


I guess U++ misinterpreted certain parameters in the non-western font information. Neither GTK nor QT has the same problem.
Re: Proposed change to U++ to allow owning children. [message #31626 is a reply to message #31619] Fri, 18 March 2011 11:01 Go to previous messageGo to next message
kohait00 is currently offline  kohait00
Messages: 939
Registered: July 2009
Location: Germany
Experienced Contributor
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
Re: Proposed change to U++ to allow owning children. [message #31631 is a reply to message #31626] Fri, 18 March 2011 14:39 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
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 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
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 #31638 is a reply to message #31635] Fri, 18 March 2011 15:40 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
Registered: March 2007
Contributor
Kohait00, Thank for the input.

The second option I proposed is way better. That way:
1. AddChild*/Add, RemoveChild* etc's prototype don't need to be changed.
2. RemoveChild's implementation do not need to be changed.
3. Only Ctrl default constructor and RemoveChild* need to be changed slightly.

I will implement it and upload changed version.

Re: Proposed change to U++ to allow owning children. [message #31641 is a reply to message #31638] Fri, 18 March 2011 16:22 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
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 249 times)
Re: Proposed change to U++ to allow owning children. [message #31642 is a reply to message #31641] Fri, 18 March 2011 16:34 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 526
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
Re: Proposed change to U++ to allow owning children. [message #31648 is a reply to message #31586] Fri, 18 March 2011 19:32 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Lance wrote on Wed, 16 March 2011 12:18

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.




Sorry, but you would have hard time to convince me to go this way.

I guess the 'U++ legit' solution to this problem is to use Array.

struct Parent : ParentCtrl {
   Array<Ctrl> child;

   template<class T> T& Create() { T& x = child.Create<T>(); Add(x); return x; }
};


I believe that the moment you encourage using manual heap usage, the whole idea collapses. You start adding flags to what is owned and what is not everywhere and end in regular C/C++ heap mess, moments later wishing that you had garbage collector to deal with it... Smile

Mirek
Re: Proposed change to U++ to allow owning children. [message #31649 is a reply to message #31619] Fri, 18 March 2011 19:35 Go to previous messageGo to previous message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Lance wrote on Thu, 17 March 2011 21:13

Not related to this topic.

One little thing that worries me, U++'s support for Chinese Fonts need more work, or may be it's because I don't know how to add more fonts yet. See attached for a sample.

The sample text is:

ultimate++是一个性能优良的C++GUI库


I guess U++ misinterpreted certain parameters in the non-western font information. Neither GTK nor QT has the same problem.


I guess you should repost this in separate thread and also provide information about the host-OS.


Mirek
Previous Topic: Get MAC addresses for windows and linux
Next Topic: Testing framework in U++.
Goto Forum:
  


Current Time: Fri Apr 19 16:22:26 CEST 2024

Total time taken to generate the page: 0.02885 seconds