Qt WidgetStack, Java CardLayout Topic is solved

This forum can be used to talk about general design strategies, new ideas and questions in general related to wxWidgets. If you feel your questions doesn't fit anywhere, put it here.
Post Reply
jimmygyuma
In need of some credit
In need of some credit
Posts: 7
Joined: Fri Mar 30, 2007 11:45 pm

Qt WidgetStack, Java CardLayout

Post by jimmygyuma »

Question: Does wxWidgets have a widget analogous to Qt's WidgetStack or Java's CardLayout? Essentially I'm looking for a notebook without tabs that can only be changed programmatically...
Complete Novice to wxWidgets
metalogic
Super wx Problem Solver
Super wx Problem Solver
Posts: 307
Joined: Fri Oct 08, 2004 8:21 am
Location: Area 51
Contact:

Post by metalogic »

You could probably accomplish this with panels and just showing one while hiding the others.
upCASE
Moderator
Moderator
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE »

Hi!
No, wxWidgets does not have a buildin class like that.
However, it is easily possible to achieve this by using sizer. Create a sizer and add all the widgets, hiding the ones you don't need right now. Then using wxSizer::Show() to show the one you want. The only drawback is that you'll need to add some small code to hide all the other widgets.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda
upCASE
Moderator
Moderator
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE »

I just hacked up a little wxWidgetStack class using a panel and a sizer. It's not perfect, but maybe you can make something out of it and implement some new methods etc.

header:

Code: Select all

class wxWidgetStack :
	public wxPanel
{
	wxBoxSizer* m_sizer;

	bool HasVisibleWidget();
public:
	wxWidgetStack(wxWindow* parent);
	~wxWidgetStack(void);

	void AddWidget(wxWindow* widget);
	void RemoveWidget(wxWindow* widget);

	void RaiseWidget(int index);
};
code

Code: Select all

wxWidgetStack::wxWidgetStack(wxWindow* parent)
:wxPanel(parent,-1)
{
	m_sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(m_sizer);
}

wxWidgetStack::~wxWidgetStack(void)
{
}
void wxWidgetStack::AddWidget(wxWindow* widget)
{
	if(widget == NULL)
		return;

	if( widget->GetParent() != this )
		widget->Reparent(this);

	if(HasVisibleWidget())
		widget->Show(false);

	m_sizer->Add(widget,1,wxEXPAND,0);

}
void wxWidgetStack::RemoveWidget(wxWindow* widget)
{
	m_sizer->Detach(widget);
	widget->Destroy();
}

void wxWidgetStack::RaiseWidget(int index)
{
	wxSizerItemList& list = m_sizer->GetChildren();
	
	int i=0;
    for ( wxSizerItemList::Node *node = list.GetFirst(); node; node = node->GetNext(), i++ )
    {
		wxSizerItem *current = node->GetData();
		if(i == index)
			current->Show(true);
		else
			current->Show(false);
    }

	Layout();
}

bool wxWidgetStack::HasVisibleWidget()
{
	wxSizerItemList& list = m_sizer->GetChildren();
	for ( wxSizerItemList::Node *node = list.GetFirst(); node; node = node->GetNext() )
    {
		wxSizerItem *current = node->GetData();
		if(current->IsShown())
			return true;
    }
	return false;
}
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda
HeReSY
Earned some good credits
Earned some good credits
Posts: 120
Joined: Fri Sep 17, 2004 8:58 pm
Location: Germany

Post by HeReSY »

I wrote this class a long time ago. It works fine for the last few month.

wx/windowstack.h

Code: Select all

#ifndef WINDOWSTACK_H
#define WINDOWSTACK_H

//// Begin wxWidgets includes
#include <wx/dynarray.h>
#include <wx/wx.h>
//// End wxWidgets includes

//// Begin application specific includes

//// End application specific includes

//// Begin forward declarations
class wxWinInfo;
//// End forward declarations

//// Begin typedef declarations
WX_DECLARE_OBJARRAY(wxWinInfo*, wxStackList);
//// End typedef declarations

/**
 * \brief This class represents a stack for windows.
 *
 * To use the class, create a wxWindowStack object and call AddPage or
 * InsertPage, passing a window to be used as the window.
 * Do not delete any window. They will be deleted when the object will
 * be destroyed.
 *
 * \class wxWindowStack
 * \author Bruno Pierucki
 * \date 27.12.2006 10.59.11
 * \version 0.0.1
 */
class wxWindowStack: public wxPanel
{
	public:
        /**
         * class constructor
         */
		wxWindowStack(wxWindow* parent,
                      wxWindowID id = wxID_ANY,
                      const wxPoint& pos = wxDefaultPosition,
                      const wxSize& size = wxDefaultSize,
                      long style = wxTAB_TRAVERSAL,
                      const wxString& name = _("stack"));
		/**
		 * class destructor
		 */
		virtual ~wxWindowStack();
		/**
		 * Adds a page to the window stack.
		 * And shows it when select = true.
		 * \param win A pointer to window to add to the stack.
		 * \param name The name for the new window.
		 * \param select Should the page selected?
		 *
         * \return Returns true if successful, false otherwise.
		 */
		bool AddWindow(wxWindow* win,
                       const wxString &name,
                       bool select = false);
        /**
         * Deletes all windows in the this class.
         */
        bool DeleteAll();
        /**
         * Deletes a specific window at the given position.
         * \param pos The position of the window to be deleted.
         * \return Returns true when successful, false otherwise.
         */
        bool DeletePage(int pos);
        /**
         * Deletes a specific window.
         * \param win The window to be deleted.
         * \return Returns true when successful, false otherwise.
         */
        bool DeletePage(wxWindow *win);
        /**
         * \param win The window
         * \return Returns the position of the given window.
         */
        int GetPosition(wxWindow *win);
        /**
         * \param pos The position of the window.
         * \return Returns the window at the given position.
         */
        wxWindow* GetWindow(int pos);
        /**
         * \return Returns the number of windows in the stack.
         */
        int Count();
        /**
         * \param pos The position of the window.
         * \return Returns the name of the window at the given position.
         */
        wxString GetWinName(int pos);
        /**
         * \param win A pointer to the window.
         * \return Returns the name of the given window.
         */
        wxString GetWinName(wxWindow *win);
        /**
         * \return Returns the position of the selected window.
         */
        int GetSelection();
        /**
         * \return Returns the selected window.
         */
        wxWindow* GetCurrentWindow();
        /**
         * Inserts a new window at the specific position.
         * \param pos The position for the window in the stack.
         * \param win A pointer to window to add to the stack.
         * \param name The name for the new window.
         * \param select Should the page selected?
         *
         * \return Returns true if successful, false otherwise.
         */
        bool InsertWindow(int pos,
                          wxWindow *win,
                          const wxString &name,
                          bool select = false);
        /**
         * Sets the name of a window at the given position.
         * \param pos The position of the window in the stack.
         * \param name The new name for the window.
         * \return Returns true if successful, false otherwise.
         */
        bool SetWinName(int pos, const wxString &name);
        /**
         * Sets the name of the given window.
         * \param win A pointer to the window in the stack.
         * \param name the new name for the window.
         * \return Returns true if successful, false otherwise.
         */
        bool SetWinName(wxWindow *win, const wxString &name);
        /**
         * Sets the active window.
         * \param pos The position for the window to select.
         * \return Returns the position of the previous selected window.
         */
        int SetSelection(int pos);
        /**
         * Sets the active window.
         * \param win The window to select.
         * \return Returns a pointer to the previus selected window.
         */
        wxWindow* SetSelection(wxWindow *win);
        wxString SetSelection(const wxString &name);

    protected:
        DECLARE_EVENT_TABLE()
    private:
        /**
         * The current selected page or -1 if none.
         */
        int m_iSelection;
        /**
         * The window list.
         */
        wxStackList m_WindowList;
        void OnSize(wxSizeEvent &event);
};

class wxWinInfo
{
    public:
        wxWinInfo(wxWindow *win, wxString name)
        {
            m_pWin = win;
            m_sName = name;
        };
        ~wxWinInfo()
        {
            m_pWin->Destroy();
        };
        wxWindow *GetWindow(){return m_pWin;};
        wxString GetName(){return m_sName;};
        void SetName(wxString name)
        {
            m_sName = name;
        };
    private:
        wxWindow *m_pWin;
        wxString m_sName;
};

#endif // WINDOWSTACK_H
and the source file:

Code: Select all

//// Begin application specific includes
#include <wx/windowstack.h>
//// End application specific includes

//// Begin wxWidgets includes
#include <wx/arrimpl.cpp>
//// End wxWidgets includes

//// Begin control identifiers

//// End control identifiers

WX_DEFINE_OBJARRAY(wxStackList);

//// Begin wxWindowStack event table entries
BEGIN_EVENT_TABLE(wxWindowStack, wxPanel)
    EVT_SIZE(wxWindowStack::OnSize)
END_EVENT_TABLE()
//// End wxWindowStack event table entries.

//// Begin wxWindowStack public functions
wxWindowStack::wxWindowStack(wxWindow* parent,
                             wxWindowID id,
                             const wxPoint& pos,
                             const wxSize& size,
                             long style,
                             const wxString& name)
:wxPanel(parent, id, pos, size, style, name)
{
    m_iSelection = -1;
    wxFlexGridSizer* sizer = new wxFlexGridSizer( 1, 1, 0, 0 );
	sizer->AddGrowableCol( 0 );
	sizer->AddGrowableRow( 0 );
	sizer->SetFlexibleDirection( wxBOTH );
    SetSizer(sizer);
}

wxWindowStack::~wxWindowStack()
{
}

bool wxWindowStack::AddWindow(wxWindow* win,
                              const wxString &name,
                              bool select)
{
    return InsertWindow(-1, win, name, select);
}

bool wxWindowStack::DeleteAll()
{
    for(int i = Count() - 1; i >= 0; i--)
    {
        DeletePage(i);
    }
    return true;
}

bool wxWindowStack::DeletePage(int pos)
{
    wxWinInfo *info = m_WindowList.Item(pos);
    delete info;
    m_WindowList.RemoveAt(pos);
    if(pos == m_iSelection)
        SetSelection(pos - 1);
    return true;
}

bool wxWindowStack::DeletePage(wxWindow *win)
{
    return DeletePage(GetPosition(win));
}

int wxWindowStack::GetPosition(wxWindow *win)
{
    for(int i = 0; i < Count(); i++)
    {
        if(GetWindow(i) == win)
            return i;
    }
    return -1;
}

wxWindow* wxWindowStack::GetWindow(int pos)
{
    if(pos >= Count() || pos == -1) return NULL;
    else return m_WindowList.Item(pos)->GetWindow();

    return NULL;
}

int wxWindowStack::Count()
{
    return m_WindowList.GetCount();
}

wxString wxWindowStack::GetWinName(int pos)
{
    return m_WindowList.Item(pos)->GetName();
}

wxString wxWindowStack::GetWinName(wxWindow *win)
{
    return GetWinName(GetPosition(win));
}

int wxWindowStack::GetSelection()
{
    return m_iSelection;
}

wxWindow* wxWindowStack::GetCurrentWindow()
{
    return GetWindow(m_iSelection);
}

bool wxWindowStack::InsertWindow(int pos,
                                 wxWindow *win,
                                 const wxString &name,
                                 bool select)
{
    //GetSizer()->Add(win);
    win->Hide();
    GetSizer()->Layout();
    wxWinInfo *info = new wxWinInfo(win, name);

    if(pos >= Count() || pos == -1)
    {
        m_WindowList.Add(info);
        pos = Count() - 1;
    }
    else m_WindowList.Insert(info, pos);

    if(select) SetSelection(pos);

    return true;
}

bool wxWindowStack::SetWinName(int pos, const wxString &name)
{
    if(pos >= Count() || pos == -1) return false;
    else
    {
        m_WindowList.Item(pos)->SetName(name);
        return true;
    }
    return false;
}

bool wxWindowStack::SetWinName(wxWindow *win, const wxString &name)
{
    return SetWinName(GetPosition(win), name);
}

int wxWindowStack::SetSelection(int pos)
{
    int old = m_iSelection;
    SetSelection(m_WindowList.Item(pos)->GetWindow());
    return old;
}

wxWindow* wxWindowStack::SetSelection(wxWindow *win)
{
    wxWindow *old = GetCurrentWindow();
    if(old)
    {
        old->Hide();
        GetSizer()->Remove(old);
    }
    GetSizer()->Add(win, 0, wxALL|wxEXPAND, 0 );
    win->Show();
    m_iSelection = GetPosition(win);
    GetSizer()->Layout();
    return old;
}
wxString wxWindowStack::SetSelection(const wxString &name)
{
    wxString old = m_WindowList.Item(GetSelection())->GetName();
    for(int i = 0; i < Count(); i++)
    {
        if(GetWinName(i) == name)
            SetSelection(i);
    }
    return old;
}
//// End wxWindowStack public functions

//// Begin wxWindowStack private member functions

//// End wxWindowStack private member functions

//// Begin wxWindowStack event functions
void wxWindowStack::OnSize(wxSizeEvent &event)
{
    GetSizer()->Layout();
    event.Skip();
}
//// End wxWindowStack event functions
But there are no Event-functions when the User changes one of the windows, or when it will be destroyed, or whatever.

HeReSY
gtafan
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 201
Joined: Wed Mar 29, 2017 9:52 am

Re: Qt WidgetStack, Java CardLayout

Post by gtafan »

Seems to be some interesting solutions, but can they also be used in wxSmith project?
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Qt WidgetStack, Java CardLayout

Post by PB »

I am not familiar with such a control. Is it different from the now built-in wxSimpleBook?
gtafan
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 201
Joined: Wed Mar 29, 2017 9:52 am

Re: Qt WidgetStack, Java CardLayout

Post by gtafan »

PB wrote:I am not familiar with such a control. Is it different from the now built-in wxSimpleBook?
That wxSimpleBook could be realy the easiest solution to the problem, unfortunately there is no example for using it.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Qt WidgetStack, Java CardLayout

Post by PB »

gtafan wrote:That wxSimpleBook could be realy the easiest solution to the problem, unfortunately there is no example for using it.
Actually, its use is demonstrated in the notebook sample. On top of that, I believe it is just a another wx*book control which are well-documented and understood, there is not much to show...
gtafan
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 201
Joined: Wed Mar 29, 2017 9:52 am

Re: Qt WidgetStack, Java CardLayout

Post by gtafan »

PB wrote:
gtafan wrote:That wxSimpleBook could be realy the easiest solution to the problem, unfortunately there is no example for using it.
Actually, its use is demonstrated in the notebook sample. On top of that, I believe it is just a another wx*book control which are well-documented and understood, there is not much to show...
The problem is links to the samples are dead.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Qt WidgetStack, Java CardLayout

Post by PB »

gtafan wrote:The problem is links to the samples are dead.
I have no idea what you mean by this. All bundled wxWidgets samples are in the samples folder in your WXWIN folder, the notebook sample obviously in the WXWIN/samples/notebook folder..
gtafan
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 201
Joined: Wed Mar 29, 2017 9:52 am

Re: Qt WidgetStack, Java CardLayout

Post by gtafan »

PB wrote:
gtafan wrote:The problem is links to the samples are dead.
I have no idea what you mean by this. All bundled wxWidgets samples are in the samples folder in your WXWIN folder, the notebook sample obviously in the WXWIN/samples/notebook folder..
I am tallking about this links: http://docs.wxwidgets.org/3.0/page_samp ... s_notebook
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: Qt WidgetStack, Java CardLayout

Post by New Pagodi »

PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: Qt WidgetStack, Java CardLayout

Post by PB »

I will submit a PR to have the links fixed in the docs for the latest stable version too.
gtafan
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 201
Joined: Wed Mar 29, 2017 9:52 am

Re: Qt WidgetStack, Java CardLayout

Post by gtafan »

Thanks.
Post Reply