Main Page Namespace List Class Hierarchy Compound List File List Namespace Members Compound Members Related Pages
Lesson6: Using dialogs and proper positioning and resizing. - In this lesson you will learn how to use dialogs and properly position your controls. We will modify code from Lesson 3.
- There are two ways one can manage controls inside of the window. The first one is to position all controls using OnReshape(), this method will give you maximum control over your controls size and position, but it also requires you to take care of everything (what if window is resized, what if it is too small, and so on). The second one is to use panel classes sjgui::CPanel, sjgui::CStackPanel, sjgui::CSqueezePanel classes, which could:
- Hide areas of child controls, which are outside of their area
- Resize child controls to be complete within their area
- Position child controls in a certain order You will learn both methods.
- Note:
- There is an option for each window to have minimum size (sjgui::CWnd::SetMinSize()). By default you can set it to any size, but if it is set to some value, it means that nothing will be able to make it smaller. This could be convenient for dialogs window, but if you are using such controls within panels they will not obey to the rules of the panel class.
- See also:
- sjgui::CPanelCtrlTmpl, sjgui::CStackCtrlPanel, sjgui::CSqueezePanelCtrlTmpl
- Let us explore the first one: Manual control over positioning.
- First dialog should be created:
- See also:
- sjgui::CDlg, sjgui::CWnd::OnReshape(), sjgui::CWnd::Reshape()
class CCustomTextDlg: public sjgui::CDlg
{
sjgui::CEdit m_edt;
sjgui::CLabel m_lbl;
public:
std::string m_str;
CCustomTextDlg()
{
sjgui::CDlg();
SetAutoHide();
SetCaption("Text Dialog!");
SetMinSize(200,100);
SetSize(250,80);
RegisterChild(&m_lbl);
RegisterChild(&m_edt);
m_edt.SetText("sjgui");
m_lbl.SetText("New Text:");
}
virtual void OnReshape()
{
m_lbl.PosWnd(5,m_Caption.GetBottom()+1,GetWidth()-10,m_edt.GetHeight());
m_edt.PosWnd(5,m_lbl.GetBottom()+1,GetWidth()-10,m_edt.GetHeight());
}
virtual void OnComplete(){if(m_btnOk.IsPushed())m_str=m_edt.GetText();}
};
Now it is time to modify space window:
sjgui::CButton, sjgui::CWnd::OnKeyUp()
class CSpcWnd : public sjgui::CWnd
{
sjgui::CButton m_btn;
CCustomTextDlg m_dlg;
public:
CSpcWnd():CWnd()
{
RegisterChild(&m_btn);
RegisterChild(&m_dlg);
}
void virtual OnReshape()
{
m_btn.SetSize((m_btn.GetTextLen()+1)*m_btn.GetFontSize(),80);
m_btn.ToCenter();
m_dlg.ToCenter();
using namespace sjgui;
CWnd::OnReshape();
}
void virtual OnKeyUp(int &iKey)
{
if(m_dlg.IsOk())
{
m_btn.SetLabel(m_dlg.m_str.data());
Reshape();
}
if(m_dlg.IsOk() || m_dlg.IsCancel())
m_dlg.Reset();
if(m_btn.IsPushed())
{
m_btn.Reset();
m_dlg.Show(!m_dlg.IsVisible());
}
}
virtual void OnDraw(){Animate();SET_GL_FOR_GUI_DRAW;}
};
As one can see it was not that hard, but we had just two controls for CSpcWnd and two for CCustomTextDlg. Imagine that you have ten or more controls in one window? It would be just a pain to position all of them (look at the "examples/pos_manual.cpp" and you will see what I mean). So you would like elements to be positioned automatically! Easy! Use CStackPanel class as a base class for CustomTextDlg and see what happens:
typedef CDlgTmpl<CButton,CLabel,CSqueezePanel> base;
class CCustomTextDlg: public base
{
CEdit m_edt;
CLabel m_lbl;
public:
std::string m_str;
CCustomTextDlg()
{
base();
m_pnlClientArea.SetVertMode();
m_pnlClientArea.SetDist(1);
m_pnlClientArea.SetOffset(1);
m_pnlClientArea.SetSideDist(5);
m_pnlClientArea.SetSideDist(5);
SetAutoHide();
SetCaption("Text Dialog!");
SetMinSize(200,100);
SetSize(250,80);
RegisterToClientArea(&m_lbl);
RegisterToClientArea(&m_edt);
m_edt.SetText("sjgui");
m_lbl.SetText("New Text:");
}
virtual void OnComplete(){if(m_btnOk.IsPushed())m_str=m_edt.GetText();}
};
The rest of the code should stay the same! As you can see there was no OnReshape() function at all, because panel class takes care of it. Just a few settings to set the panel as we would like it to be and we are ready to go! For more complex layouts you could combine panels one within another, so be creative. Look at the "examples/pos_auto.cpp" for an example containing 10 controls, other then controls of standard dialog.
- Note:
- You may ask what about order of elements? The answer is, that it is denoted by the order of registering child windows. You have option to reverse this order using sjgui::CStackPanel::ReverseOrder()
- See also:
- sjgui::CStackPanel::ReverseOrder()
- Back to Lesson 5. Forward to Lesson 7.
- This is full source code:
#include <sjgui/sjgui.h>
#ifndef AUTO
class CCustomTextDlg: public sjgui::CDlg
{
sjgui::CEdit m_edt;
sjgui::CLabel m_lbl;
public:
std::string m_str;
CCustomTextDlg()
{
sjgui::CDlg();
SetAutoHide();
SetCaption("Text Dialog!");
SetMinSize(200,100);
SetSize(250,80);
RegisterChild(&m_lbl);
RegisterChild(&m_edt);
m_edt.SetText("sjgui");
m_lbl.SetText("New Text:");
}
virtual void OnReshape()
{
m_lbl.PosWnd(5,m_Caption.GetBottom()+1,GetWidth()-10,m_edt.GetHeight());
m_edt.PosWnd(5,m_lbl.GetBottom()+1,GetWidth()-10,m_edt.GetHeight());
}
virtual void OnComplete(){if(m_btnOk.IsPushed())m_str=m_edt.GetText();}
};
#else // !AUTO
using namespace sjgui;
typedef CDlgTmpl<CButton,CLabel,CSqueezePanel> base;
class CCustomTextDlg: public base
{
CEdit m_edt;
CLabel m_lbl;
public:
std::string m_str;
CCustomTextDlg()
{
base();
m_pnlClientArea.SetVertMode();
m_pnlClientArea.SetDist(1);
m_pnlClientArea.SetOffset(1);
m_pnlClientArea.SetSideDist(5);
m_pnlClientArea.SetSideDist(5);
SetAutoHide();
SetCaption("Text Dialog!");
SetMinSize(200,100);
SetSize(250,80);
RegisterToClientArea(&m_lbl);
RegisterToClientArea(&m_edt);
m_edt.SetText("sjgui");
m_lbl.SetText("New Text:");
}
virtual void OnComplete(){if(m_btnOk.IsPushed())m_str=m_edt.GetText();}
};
#endif // !AUTO
class CSpcWnd : public sjgui::CWnd
{
sjgui::CButton m_btn;
CCustomTextDlg m_dlg;
public:
CSpcWnd():CWnd()
{
RegisterChild(&m_btn);
RegisterChild(&m_dlg);
}
void virtual OnReshape()
{
m_btn.SetSize((m_btn.GetTextLen()+1)*m_btn.GetFontSize(),80);
m_btn.ToCenter();
m_dlg.ToCenter();
using namespace sjgui;
CWnd::OnReshape();
}
void virtual OnKeyUp(int &iKey)
{
if(m_dlg.IsOk())
{
m_btn.SetLabel(m_dlg.m_str.data());
Reshape();
}
if(m_dlg.IsOk() || m_dlg.IsCancel())
m_dlg.Reset();
if(m_btn.IsPushed())
{
m_btn.Reset();
m_dlg.Show(!m_dlg.IsVisible());
}
}
virtual void OnDraw(){Animate();SET_GL_FOR_GUI_DRAW;}
};
int main(int argc, char* argv[])
{
CSpcWnd SpcWnd;
SpcWnd.PosWnd(20,50,320,240);
if(sjgui::Create(argv[0],&SpcWnd))
{
sjgui::GlobalMainLoop();
}
else
printf("Could not create opengl window.\n");
return 0;
}
|
|