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 » U++ Library support » U++ Widgets - General questions or Mixed problems » Howto create control-collection -control? [SOLVED -good example]
Howto create control-collection -control? [SOLVED -good example] [message #1519] Tue, 07 March 2006 22:45 Go to next message
wilho is currently offline  wilho
Messages: 19
Registered: February 2006
Promising Member
Hi!

Edit: this was a way too hasty question now slowly becoming tutorial it seems Smile I'm creating simple control by combining splitter, button and user defined control. Couple of these SplitterButtons could create something like there's in outlook's left pane. So here's what I got so far:

class SplitterButton : public ParentCtrl{
	Splitter splitter;
	Button button;
	typedef SplitterButton CLASSNAME;
public:
	SplitterButton();
	void Vert(Ctrl&);
	void Toggle();
	void SplitterButton::SetSplitPos(int);
};
SplitterButton::SplitterButton(){
	button <<= THISBACK(Toggle);
	Add(splitter);
}
void SplitterButton::Vert(Ctrl& ctrl){
	splitter.Vert(ctrl, button);
}
void SplitterButton::Toggle(){
	splitter.Zoom(splitter.GetZoom() == 1 ? -1 : 1);		
	//todo:resize code
}
void SplitterButton::SetSplitPos(int newpos){
	splitter.SetPos(newpos);
}


Next thing is to create code for the control to resize itself...I suppose that there's no way link controls position into another one, so I have to move other controls out of the way and back by hand?

If you think this is wrong approach or here's something wrong, feel free to open up. I'll be back.

[Updated on: Sun, 09 April 2006 04:08] by Moderator

Report message to a moderator

Re: Howto create control-collection -control? [message #1526 is a reply to message #1519] Tue, 07 March 2006 23:32 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Quote:


Next thing is to create code for the control to resize itself...I suppose that there's no way link controls position into another one, so I have to move other controls out of the way and back by hand?



Sometimes you can use regular layout for composite Ctrls (it is not limited for dialogs only). Of course, sometimes you have to deal with it with your code (which usually is quite easy too).

Mirek
Re: Howto create control-collection -control? [message #1654 is a reply to message #1519] Sat, 11 March 2006 18:09 Go to previous messageGo to next message
wilho is currently offline  wilho
Messages: 19
Registered: February 2006
Promising Member
Ahh, sweet weekend - time for hobby-coding. I had to play with MFC a bit during a week and I must say it's pleasure get back with upp again Smile

This is how I solved the thing above:
class dummy{};
class SButton : public Button{
	typedef SButton CLASSNAME;
	Splitter* container;
	Ctrl* slaveCtrl;
	bool visible;
	
	public:
		void Toggle(){
			if (visible){
				container->RemoveChild(slaveCtrl);
				container->RefreshLayout();
			}
			else{			
				*container << *slaveCtrl;
				container->RefreshLayout();
			}
			visible = visible == true ? false:true;
		}
		SButton(Splitter* splitter, Ctrl* slave ){
			container = splitter;
			slaveCtrl = slave;
			visible = false;
			*this <<= THISBACK(Toggle);
		}
};

#define LAYOUTFILE <localizer/empty.lay>
#include <CtrlCore/lay.h>
class SButtons : public WithEmptyLayout<ParentCtrl>, public dummy{

	static const int BTN_SPACE = 25; 
	Vector<SButton*> buttons;
	int btnIndx;
	Splitter vert;
	ParentCtrl container;
public:
	SButtons();
	~SButtons();
	void Vert(Ctrl&);
};
SButtons::SButtons(){
	CtrlLayout(*this);
	Add(container);
	vert.Vert();
	Add(vert);
}
SButtons::~SButtons(){
	Vector<SButton*>::Iterator bpi = buttons.Begin();
	for (;bpi < buttons.End();bpi++ ){
		delete *bpi;
	}
}
void SButtons::Vert(Ctrl& ctrl){
	SButton* button = new SButton(&vert, &ctrl);
	Add(*button);

	button->HSizePosZ(0, 0).BottomPosZ(BTN_SPACE * btnIndx++, BTN_SPACE -2);
	vert.HSizePosZ(0, 0).VSizePosZ(0, BTN_SPACE * btnIndx);
	buttons.Add(button);
}


Couple of questions though:
1) How in the hell my buttons won't get visible with that derived dummy class? Doesn't make sense to me...
2) Is there a way to derive a class from layout without defining empty layout as above?
Re: Howto create control-collection -control? [message #1655 is a reply to message #1654] Sat, 11 March 2006 18:43 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Well, a couple of comments first:

Vector<SButton*> buttons;
......
new SButton(&vert, &ctrl);

This is "non-U++" way - forces you to take care of deleting in destructor.

U++ way is to:

- use member function in SButton instead of constructor
- use Array<SButton>
- not use pointers here
- (and, for the record, use indexes instead of iterators....)

What is "dummy" class for?

Why Empty layout?

To me it seems like you could simply derive from ParentCtrl...

(also: visible = !visible Smile

Now, I was not sure what exactly is the goal, until I run (after long time) Outlook express. Well, I am afraid that the solution will have to be a bit different - what you do here has problem with ordering of those subpanes.

I guess the right solution should be single class like

class ExpressPane : public Ctrl {
    Array<Button>  closer;
    Vector<Ctrl *> slave;
    Splitter       splitter;

    void CloseButton();
    void Rearrange();
public:
    void Add(const char *text, Ctrl& slave);
};


The important part is that Rearrange should reset the splitter and add all subpanes again. And both Add and CloseButton should call Rearrange....

Mirek
Re: Howto create control-collection -control? [message #1657 is a reply to message #1655] Sat, 11 March 2006 19:33 Go to previous messageGo to next message
wilho is currently offline  wilho
Messages: 19
Registered: February 2006
Promising Member
Thanks for the tips. I'll have some ultimizing to do.

luzr wrote on Sat, 11 March 2006 12:43


Well, a What is "dummy" class for?


It shouldn't change a thing shouldn't it? But anyway, if I removed it, the toggle buttons just didn't appear and I don't know why... I made new separate cpp/h -files for the classes, derived SButtons class from ParentCtrl as you suggested, and now it works fine without it. And please, don't think I've lost my marbles, I retested this couple of times Smile

luzr wrote on Sat, 11 March 2006 12:43


Why Empty layout?


I bet I once had a good reason for this... Razz

luzr wrote on Sat, 11 March 2006 12:43

Well, a What is
The important part is that Rearrange should reset the splitter and add all subpanes again. And both Add and CloseButton should call Rearrange....


I was pondering if I'm going to do this or not, I will if this seems messy in actual context.
Re: Howto create control-collection -control? [message #1658 is a reply to message #1657] Sat, 11 March 2006 20:39 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Quote:


luzr wrote on Sat, 11 March 2006 12:43

Well, a What is
The important part is that Rearrange should reset the splitter and add all subpanes again. And both Add and CloseButton should call Rearrange....


I was pondering if I'm going to do this or not, I will if this seems messy in actual context.

[/quote]

Do not hesitate, it is the simplest and cleanest thing to do... Wink

Mirek
Re: Howto create control-collection -control? [message #1663 is a reply to message #1519] Sun, 12 March 2006 11:25 Go to previous messageGo to next message
wilho is currently offline  wilho
Messages: 19
Registered: February 2006
Promising Member
OK, you convinced me.

class ExpressPane : public Ctrl {
	struct SlaveControl {
	    bool isInSplitter;
	    Ctrl* slave;
	};	
	Array<Button> closer;
	Array<SlaveControl> slaves;
	Splitter splitter;

	static const int BTN_SPACE = 22;
	typedef ExpressPane CLASSNAME;

	int btnIndx;	
	void Toggle(int);
public:
	void Add(const char *text, Ctrl& slave);
	ExpressPane();
};

ExpressPane::ExpressPane(){
	Ctrl::Add(splitter);
	splitter.Vert();
}
void ExpressPane::Toggle(int indx){
	slaves[indx].isInSplitter = slaves[indx].isInSplitter == true ? false:true; 

	for(int loopI=slaves.GetCount()-1; loopI>-1; loopI--){
		splitter.RemoveChild( slaves[loopI].slave );
		if (slaves[loopI].isInSplitter == true){
			splitter << *slaves[loopI].slave;
		}
	}
	splitter.RefreshLayout();
}
void ExpressPane::Add(const char *text, Ctrl& slave){

	Button* button = new Button;
	Callback argCB = callback1(this,Toggle, btnIndx++);
	*button <<= argCB;
	button->SetLabel(text);
	button->HSizePosZ(0, 0).BottomPosZ(BTN_SPACE * (btnIndx-1), BTN_SPACE -2);
	splitter.HSizePosZ(0, 0).VSizePosZ(0, BTN_SPACE * btnIndx);
	Ctrl::Add(*button);
	closer.Add(button);

	SlaveControl slvCtrl;
	slvCtrl.isInSplitter = false;
	slvCtrl.slave = &slave; 
	slaves.Add(slvCtrl);
}


Thank you, this has ben very...educational Smile

[Updated on: Sun, 12 March 2006 11:26]

Report message to a moderator

Re: Howto create control-collection -control? [message #1666 is a reply to message #1663] Sun, 12 March 2006 12:47 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Callback argCB = callback1(this,Toggle, btnIndx++);

usually, we now prefer to place

typedef ExpressPane CLASSNAME;

inside ExpressPane declaration and then

Callback argCB = THISBACK1(Toggle, btnIndx++);

(pays off if you are about to assing more callbacks.

Avoid btnIndex, use "closer.GetCount()".

Also, avoid "new":

Button& button = closer.Add();

means:

void ExpressPane::Add(const char *text, Ctrl& slave){
        int btnIndx = closer.GetCount();
	Button& button = closer.Add();
	button <<= THISBACK1(Toggle, btnIndx);
	button.SetLabel(text);
	button.HSizePosZ(0, 0).BottomPosZ(BTN_SPACE * (btnIndx-1), BTN_SPACE -2);
	splitter.HSizePosZ(0, 0).VSizePosZ(0, BTN_SPACE * btnIndx);
	Ctrl::Add(button);
	SlaveControl& slvCtrl = slaves.Add();
	slvCtrl.isInSplitter = false;
	slvCtrl.slave = &slave;
}


Even more optimal would be to place Button inside SlaveControl and manage just a single array...

(I am still missing Rearrange, just toying with the code as it is)

Mirek

[Updated on: Sun, 12 March 2006 12:50]

Report message to a moderator

Re: Howto create control-collection -control? [message #1684 is a reply to message #1663] Mon, 13 March 2006 20:42 Go to previous messageGo to next message
wilho is currently offline  wilho
Messages: 19
Registered: February 2006
Promising Member
Ok, here we go again:
class DblClckBtn : public Button {
public:
	Callback WhenLeftDouble;
	virtual void DblClckBtn::LeftDouble(Point, dword);
};
class ExpressPane : public Ctrl {
	struct SlaveControl {
	    bool isInSplitter;
	    DblClckBtn button;
	    Ctrl* slave;
	};	
	Array<SlaveControl> slaves;
	Splitter splitter;
	static const int BTN_SPACE = 22;
	typedef ExpressPane CLASSNAME;	
	void Toggle(int);
	void OpenOne(int);
public:
	void Add(const char *text, Ctrl& slave);
	void Rearrange();
	ExpressPane();
};
void DblClckBtn::LeftDouble(Point p, dword) {
	if(IsReadOnly()) return;
	WhenLeftDouble();
}
ExpressPane::ExpressPane(){
	Ctrl::Add(splitter);
	splitter.Vert();
}
void ExpressPane::OpenOne(int indx){	
	for(int loopI=slaves.GetCount()-1; loopI>-1; loopI--){
		slaves[loopI].isInSplitter = false; 
	}
	slaves[indx].isInSplitter = true;
	Rearrange();
}
void ExpressPane::Toggle(int indx){
	slaves[indx].isInSplitter = !slaves[indx].isInSplitter; 
	Rearrange();
}
void ExpressPane::Rearrange(){
	for(int loopI=slaves.GetCount()-1; loopI>-1; loopI--){
		splitter.RemoveChild( slaves[loopI].slave );
		if (slaves[loopI].isInSplitter == true){
			splitter << *slaves[loopI].slave;
		}
	}
	splitter.RefreshLayout();
}
void ExpressPane::Add(const char *text, Ctrl& slave){	
	SlaveControl& slvCtrl = slaves.Add();
	int btnIndx = slaves.GetCount()-1;
	slvCtrl.button <<= THISBACK1(Toggle,btnIndx);
	slvCtrl.button.WhenLeftDouble << THISBACK1(OpenOne,btnIndx);
	slvCtrl.button.SetLabel(text);
	slvCtrl.button.HSizePosZ(0, 0).BottomPosZ(BTN_SPACE * (btnIndx), BTN_SPACE -2);
	slvCtrl.isInSplitter = false;
	slvCtrl.slave = &slave;	
	splitter.HSizePosZ(0, 0).VSizePosZ(0, BTN_SPACE * (btnIndx+1));
	Ctrl::Add(slvCtrl.button);
}

Here's rearrange and some use for it in form double-click feature. And I finally got the !visible hint Wink

[Updated on: Mon, 13 March 2006 20:46]

Report message to a moderator

Re: Howto create control-collection -control? [message #1692 is a reply to message #1684] Mon, 13 March 2006 22:04 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
wilho wrote on Mon, 13 March 2006 14:42

Ok, here we go again:
class DblClckBtn : public Button {
public:
	Callback WhenLeftDouble;
	virtual void DblClckBtn::LeftDouble(Point, dword);
};
class ExpressPane : public Ctrl {
	struct SlaveControl {
	    bool isInSplitter;
	    DblClckBtn button;
	    Ctrl* slave;
	};	
	Array<SlaveControl> slaves;
	Splitter splitter;
	static const int BTN_SPACE = 22;
	typedef ExpressPane CLASSNAME;	
	void Toggle(int);
	void OpenOne(int);
public:
	void Add(const char *text, Ctrl& slave);
	void Rearrange();
	ExpressPane();
};
void DblClckBtn::LeftDouble(Point p, dword) {
	if(IsReadOnly()) return;
	WhenLeftDouble();
}
ExpressPane::ExpressPane(){
	Ctrl::Add(splitter);
	splitter.Vert();
}
void ExpressPane::OpenOne(int indx){	
	for(int loopI=slaves.GetCount()-1; loopI>-1; loopI--){
		slaves[loopI].isInSplitter = false; 
	}
	slaves[indx].isInSplitter = true;
	Rearrange();
}
void ExpressPane::Toggle(int indx){
	slaves[indx].isInSplitter = !slaves[indx].isInSplitter; 
	Rearrange();
}
void ExpressPane::Rearrange(){
	for(int loopI=slaves.GetCount()-1; loopI>-1; loopI--){
		splitter.RemoveChild( slaves[loopI].slave );
		if (slaves[loopI].isInSplitter == true){
			splitter << *slaves[loopI].slave;
		}
	}
	splitter.RefreshLayout();
}
void ExpressPane::Add(const char *text, Ctrl& slave){	
	SlaveControl& slvCtrl = slaves.Add();
	int btnIndx = slaves.GetCount()-1;
	slvCtrl.button <<= THISBACK1(Toggle,btnIndx);
	slvCtrl.button.WhenLeftDouble << THISBACK1(OpenOne,btnIndx);
	slvCtrl.button.SetLabel(text);
	slvCtrl.button.HSizePosZ(0, 0).BottomPosZ(BTN_SPACE * (btnIndx), BTN_SPACE -2);
	slvCtrl.isInSplitter = false;
	slvCtrl.slave = &slave;	
	splitter.HSizePosZ(0, 0).VSizePosZ(0, BTN_SPACE * (btnIndx+1));
	Ctrl::Add(slvCtrl.button);
}

Here's rearrange and some use for it in form double-click feature. And I finally got the !visible hint Wink



Well, now this actually looks like some U++ code Smile

Mirek
Re: Howto create control-collection -control? [message #1709 is a reply to message #1692] Tue, 14 March 2006 18:05 Go to previous messageGo to next message
fudadmin is currently offline  fudadmin
Messages: 1321
Registered: November 2005
Location: Kaunas, Lithuania
Ultimate Contributor
Administrator
wilho, would you mind placing this your complete package into "Extra libraries..." -> "U++ users applications..." forum?

[Updated on: Tue, 14 March 2006 21:29]

Report message to a moderator

Re: Howto create control-collection -control? [message #1714 is a reply to message #1519] Tue, 14 March 2006 19:23 Go to previous messageGo to next message
wilho is currently offline  wilho
Messages: 19
Registered: February 2006
Promising Member
sure
Re: Howto create control-collection -control? [SOLVED -good example] [message #20782 is a reply to message #1519] Tue, 07 April 2009 10:53 Go to previous messageGo to next message
kbyte is currently offline  kbyte
Messages: 87
Registered: July 2008
Member
Any simple app example to show the way how we use this new control?

Alex
Re: Howto create control-collection -control? [SOLVED -good example] [message #20786 is a reply to message #20782] Tue, 07 April 2009 12:10 Go to previous messageGo to next message
mrjt is currently offline  mrjt
Messages: 705
Registered: March 2007
Location: London
Contributor
kbyte wrote on Tue, 07 April 2009 09:53

Any simple app example to show the way how we use this new control?

Alex

It's very easy:
class CtrlLibTest : public WithCtrlLibTestLayout<TopWindow> {
public:
	typedef CtrlLibTest CLASSNAME;	
	WithTestLayout<ParentCtrl> c1, c2;
	ExpressPane pane;

	CtrlLibTest::CtrlLibTest()
	{
		CtrlLayout(*this, "Window title");
		Sizeable();
		CtrlLayout(c1);
		CtrlLayout(c2);
		pane.Add("Child 1", c1);
		pane.Add("Child 2", c2);	
		Add(pane.SizePos());
	}
};

It's basically a Splitter with a set of buttons at the bottom for different Ctrls that can be dynamically added/removed by the user. A nice concept.

My suggestions for improvement:
-Instead of having the buttons in the Splitter put them in a FrameSplitter. This will make your layout simpler and also give you the option of having the buttons on the left, right or top of the ctrl.
-The buttons would look better if you used a ButtonOption, maybe with a custom Style, and no spacing between them. This would also remove the need for the isInSplitter member.
-Inherit from ParentCtrl, not Ctrl.
-I'm not entirely convinced a Splitter is the best way here, Outlook seems to just swap the controls (only having one visible at a time).
-You may also be interested in this package, which is a different approach to a similar problem.

James

[Updated on: Wed, 08 April 2009 10:47]

Report message to a moderator

Re: Howto create control-collection -control? [SOLVED -good example] [message #20788 is a reply to message #20786] Tue, 07 April 2009 15:29 Go to previous messageGo to next message
kbyte is currently offline  kbyte
Messages: 87
Registered: July 2008
Member
I already tryied that package your mention on the end of the message but that control fills all the client are and i am lookinf for one that draws only on the left side of the client are, like outlook


Alex
Re: Howto create control-collection -control? [SOLVED -good example] [message #20789 is a reply to message #20788] Tue, 07 April 2009 15:36 Go to previous messageGo to next message
kbyte is currently offline  kbyte
Messages: 87
Registered: July 2008
Member
When i try this control following the steps you referred i can see nothing on the main dialog


Alex
Re: Howto create control-collection -control? [SOLVED -good example] [message #20797 is a reply to message #20788] Wed, 08 April 2009 10:52 Go to previous messageGo to next message
mrjt is currently offline  mrjt
Messages: 705
Registered: March 2007
Location: London
Contributor
kbyte wrote on Tue, 07 April 2009 14:29

I already tryied that package your mention on the end of the message but that control fills all the client are and i am lookinf for one that draws only on the left side of the client are, like outlook
Thats because in the example the ExpanderCtrl is added with SizePos to deliberately fill up the whole wndow (since there's nothing else to see). If you want it just on the left add it with LeftPos(0, 150) or whatever.
Quote:

When i try this control following the steps you referred i can see nothing on the main dialog

Sorry, my mistake. The last line should be:
Add(pane.SizePos())
I've updated the original post.
Re: Howto create control-collection -control? [SOLVED -good example] [message #20798 is a reply to message #20797] Wed, 08 April 2009 11:46 Go to previous messageGo to next message
kbyte is currently offline  kbyte
Messages: 87
Registered: July 2008
Member
now it works but i have to use the both lines:

Add(expander.SizePos());

Add(expander.LeftPos(0, 150));

If i just use the
Add(expander.LeftPos(0, 150));

The control in not drawn


Thanks
Alex
Re: Howto create control-collection -control? [SOLVED -good example] [message #20801 is a reply to message #20798] Wed, 08 April 2009 16:05 Go to previous messageGo to next message
mrjt is currently offline  mrjt
Messages: 705
Registered: March 2007
Location: London
Contributor
LeftPos() only sets the horizontal size/position, so if you haven't set the vertical size/position it will not be visible. Try using VSizePos(). SizePos() is the equivalent of VSizePos().HSizePos().
Re: Howto create control-collection -control? [SOLVED -good example] [message #20806 is a reply to message #20801] Thu, 09 April 2009 10:26 Go to previous message
kbyte is currently offline  kbyte
Messages: 87
Registered: July 2008
Member
Great!

Alex
Previous Topic: Help needed to deal with Display
Next Topic: Application crush
Goto Forum:
  


Current Time: Thu Mar 28 14:35:34 CET 2024

Total time taken to generate the page: 0.01898 seconds