1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        foldpanelbar.h
3 // Purpose:     wxFoldPanel
4 // Author:      Jorgen Bodde
5 // Modified by: ABX - 19/12/2004 : possibility of horizontal orientation
6 //                               : wxWidgets coding standards
7 // Created:     22/06/2004
8 // RCS-ID:      $Id: foldpanelbar.h 34972 2005-07-28 23:23:27Z VZ $
9 // Copyright:   (c) Jorgen Bodde
10 // Licence:     wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12 
13 #ifndef __WXFOLDPANELBAR_H__
14 #define __WXFOLDPANELBAR_H__
15 
16 /** Not yet supported but added for future reference. Single fold forces other panels to close when
17     they are open, and only opens the current panel. This will allow the open panel to gain the full
18     size left in the client area */
19 #define wxFPB_SINGLE_FOLD           0x0001
20 
21 /** All panels are stacked to the bottom. When they are expanded again they show up at the top */
22 #define wxFPB_COLLAPSE_TO_BOTTOM    0x0002
23 
24 /** Orientation flag **/
25 #define wxFPB_HORIZONTAL            wxHORIZONTAL /*  0x0004 */
26 #define wxFPB_VERTICAL              wxVERTICAL   /*  0x0008 */
27 
28 /** Not yet supported, but added for future reference. Single fold plus panels will be stacked at the bottom */
29 #define wxFPB_EXCLUSIVE_FOLD        wxFPB_SINGLE_FOLD | wxFPB_COLLAPSE_TO_BOTTOM
30 
31 /** Default style of the wxFoldPanelBar */
32 #define wxFPB_DEFAULT_EXTRASTYLE    0
33 
34 #define wxFPB_DEFAULT_STYLE         wxTAB_TRAVERSAL | wxNO_BORDER
35 
36 #include "wx/foldbar/foldpanelitem.h"
37 
38 /** \class wxFoldPanel
39     This class is used to return a reference to the fold panel that is added by wxFoldPanelBar::AddFoldPanel(). Use
40     wxFoldPanel::IsOk() to check wether the result is ok to be used in further operations. Use wxFoldPanel::GetItem()
41     to obtain a parent window reference to create the controls on you want to add with wxFoldPanelBar::AddFoldPanelWindow().<br><br>
42 */
43 
44 class wxFoldPanel
45 {
46 private:
47     wxFoldPanelItem *m_item;
48 
49 public:
50     /** Constructor, usually not directly used by the developer. */
wxFoldPanel(wxFoldPanelItem * item)51     wxFoldPanel(wxFoldPanelItem *item)
52         : m_item(item)
53     {
54     }
55 
56     /** Returns true if this is a valid wxFoldPanelItem reference. */
IsOk()57     bool IsOk() const {
58         return (m_item != 0);
59     };
60 
61     /** Copy operator to assign one instance to the other, this is needed because these classes are passed
62         as instance not by reference. */
63     virtual void operator=(const wxFoldPanel &item) {
64         m_item = item.m_item;
65     };
66 
67 #ifndef _NO_DOXYGEN_
68     // not allowed to be seen by doxygen
GetItem()69     wxFoldPanelItem *GetItem() const {
70         return m_item;
71     };
72 #endif
73 
74     /** Use this method to obtain the wxPanel derived class to which you need to add your components. For example;<br>
75 
76     \code
77         wxFoldPanel item = m_pnl->AddFoldPanel(wxT("Test me"), false);
78         m_pnl->AddFoldPanelWindow(item, new wxButton(item.GetParent(), wxID_ANY, wxT("Press Me")));
79     \endcode
80     */
GetParent()81     wxFoldPanelItem *GetParent() const {
82         wxASSERT(m_item);
83         return m_item;
84     };
85 
86 
87 };
88 
89 #include <wx/dynarray.h>
90 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxFoldPanelItem *, wxFoldPanelItemArray, class WXDLLIMPEXP_FOLDBAR);
91 
92 /** \class wxFoldPanelBar
93     The wxFoldPanelBar is a class which can maintain a list of collapsable panels. Once a panel is collapsed, only
94     it's panel bar is visible to the user. This will provide more space for the other panels, or allow the user to
95     close panels which are not used often to get the most out of the work area.
96 
97     This control is easy to use. Simply create it as a child for a panel or sash window, and populate panels with
98     wxFoldPanelBar::AddFoldPanel(). Then use the wxFoldPanelBar::AddFoldPanelWindow() to add wxWindow derived controls
99     to the current fold panel. Use wxFoldPanelBar::AddFoldPanelSeparator() to put separators between the groups of
100     controls that need a visual separator to group them together. After all is constructed, the user can fold
101     the panels by doubleclicking on the bar or single click on the arrow, which will indicate the collapsed or
102     expanded state.
103 */
104 
105 class WXDLLIMPEXP_FOLDBAR wxFoldPanelBar: public wxPanel
106 {
107 private:
108     DECLARE_DYNAMIC_CLASS( wxFoldPanelBar )
109     DECLARE_EVENT_TABLE()
110 
111     wxImageList *m_images;
112     wxFoldPanelItemArray m_panels;
113     wxBoxSizer* m_panelSizer;
114     wxPanel *m_foldPanel, *m_bottomPanel;
115     wxFlexGridSizer* m_mainSizer;
116     bool m_controlCreated;
117     wxBitmap *m_moreBmp;
118     int m_extraStyle;
119 
120 private:
121     /** Refreshes all the panels from given index down to last one */
122     void RefreshPanelsFrom(size_t i);
123 
124     /** Refreshes all the panels from given pointer down to last one in the list */
125     void RefreshPanelsFrom(wxFoldPanelItem *item);
126 
127     /** Returns the length of the panels that are expanded and collapsed. This is useful to determine
128         quickly what size is used to display, and what is left at the bottom (right) to align
129         the collapsed panels. */
130     int GetPanelsLength(int &collapsed, int &expanded);
131 
132     /** Reposition all the collapsed panels to the bottom. When it is not possible to
133         align them to the bottom, stick them behind the visible panels. The Rect holds the
134         slack area left between last repositioned panel and the bottom panels. This needs to
135         get a refresh */
136     wxRect RepositionCollapsedToBottom();
137 
138 public:
139     /** Two step constructor used for XRC. Use wxFoldPanelBar::Create() to create the panel. Do not call
140         any other methods before the control is fully created! */
141     wxFoldPanelBar();
142     /** One step creation. Look at wxPanel for the argument and style flags. The extraStyle flags are
143         - wxFPB_DEFAULT_EXTRASTYLE : Takes default styles.
144         - wxFPB_COLLAPSE_TO_BOTTOM : When panels are collapsed, they are put at the bottom of the area. */
145     wxFoldPanelBar( wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
146                     const wxSize& size = wxDefaultSize, long style = wxFPB_DEFAULT_STYLE,
147                     long extraStyle = wxFPB_DEFAULT_EXTRASTYLE);
148 
149     /** wxFoldPanelBar destructor */
150     virtual ~wxFoldPanelBar();
151 
152     /** Two step create call. Use this when the control is not created using the wxPanel derived constructor.
153         WARNING: Do not create this component more then once! */
154     virtual void Create( wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
155                          const wxSize& size = wxDefaultSize, long style = wxFPB_DEFAULT_STYLE,
156                          long extraStyle = wxFPB_DEFAULT_EXTRASTYLE);
157 
158     /** Adds a fold panel to the list of panels. If the flag collapsedInitially is set to true, the panel
159         is collapsed initially. The wxFoldPanel item which is returned, can be used as a reference to
160         perform actions upon the fold panel like collapsing it, expanding it, or deleting it from the list.
161 
162         Use this foldpanel to add windows to it. Please consult wxFoldPanelBar::AddFoldPanelWindow() and
163         wxFoldPanelBar::AddFoldPanelSeparator() how to add wxWindow items to the panels. */
164     wxFoldPanel AddFoldPanel(const wxString &caption, bool collapsedInitially = false,
165                              const wxCaptionBarStyle &style = wxEmptyCaptionBarStyle);
166 
167 
168     /** Adds a wxWindow derived class to the referenced wxFoldPanel. IMPORTANT: Make the to be created window,
169         child of the wxFoldPanel. See example that follows. The flags to be used are:
170         - wxFPB_ALIGN_WIDTH: Which means the wxWindow to be added will be aligned to fit the width of the
171           wxFoldPanel when it is resized. Very handy for sizer items, buttons and text boxes.
172         - wxFPB_ALIGN_LEFT: Aligns left instead of fitting the width of the child window to be added. Use either
173           this one or wxFPB_ALIGN_WIDTH.
174 
175         The wxWindow to be added can be slightly indented from left and right so it is more visibly placed
176         in the wxFoldPanel. Use ySpacing > 0 to give the control an y offset from the previous wxWindow added,
177         use leftSpacing to give it a slight indent from the left, and rightSpacing also reserves a little space
178         on the right so the wxWindow can be properly placed in the wxFoldPanel.
179 
180         The following example adds a wxFoldPanel to the wxFoldPanelBar and adds two wxWindow derived controls
181         to the wxFoldPanel:
182 
183         \code
184 
185             // create the wxFoldPanelBar
186             m_pnl = new wxFoldPanelBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFPB_DEFAULT_STYLE, wxFPB_COLLAPSE_TO_BOTTOM);
187 
188             // add a foldpanel to the control. "Test me" is the caption and it is initially not collapsed.
189             wxFoldPanel item = m_pnl->AddFoldPanel(wxT("Test me"), false);
190 
191             // now add a button to the fold panel. Mind that the button should be made child of the
192             // wxFoldPanel and not of the main form.
193             m_pnl->AddFoldPanelWindow(item, new wxButton(item.GetParent(), ID_COLLAPSEME, wxT("Collapse Me")));
194 
195             // add a separator between the two controls. This is purely a visual line that can have a certain
196             // color and also the indents and width alligning like a control.
197             m_pnl->AddFoldPanelSeperator(item);
198 
199             // now add a text ctrl. Also very easy. Align this on width so that when the control gets wider
200             // the text control also sizes along.
201             m_pnl->AddFoldPanelWindow(item, new wxTextCtrl(item.GetParent(), wxID_ANY, wxT("Comment")), wxFPB_ALIGN_WIDTH, wxFPB_DEFAULT_SPACING, 20);
202 
203         \endcode
204     */
205     int AddFoldPanelWindow(const wxFoldPanel &panel, wxWindow *window, int flags = wxFPB_ALIGN_WIDTH,
206                            int Spacing = wxFPB_DEFAULT_SPACING, int leftSpacing = wxFPB_DEFAULT_LEFTSPACING,
207                            int rightSpacing = wxFPB_DEFAULT_RIGHTSPACING);
208 
209     /** Adds a separator line to the current wxFoldPanel. The separator is a simple line which is drawn and is no
210         real component. It can be used to separate groups of controls which belong to each other. The colour is
211         adjustable, and it takes the same ySpacing, leftSpacing and rightSpacing as AddFoldPanelWindow(). */
212     int AddFoldPanelSeperator(const wxFoldPanel &panel, const wxColour &color = wxColour(167,167,167),
213                            int Spacing = wxFPB_DEFAULT_SPACING, int leftSpacing = wxFPB_DEFAULT_LEFTLINESPACING,
214                            int rightSpacing = wxFPB_DEFAULT_RIGHTLINESPACING);
215 
216     /** Returns the number of panels currently present in the wxFoldPanelBar. This is independent if they are
217         visible or hidden. */
GetCount()218     size_t GetCount() const {
219         return m_panels.GetCount();
220     };
221 
IsVertical()222     inline bool IsVertical() const
223         {
224             return HasFlag(wxFPB_VERTICAL);
225         }
226 
227     /** Returns the wxFoldPanel reference belonging to the current index. An empty panel is returned when the
228         index is out of bounds. Use GetCount() to get the amount of panels present. Collapsing and folding the
229         panel does not change the order in which they are indexed. So it is safe enough to keep a reference
230         to the panel by number. */
Item(size_t i)231     wxFoldPanel Item(size_t i) {
232         wxCHECK((int)i >= 0 && i < GetCount(), wxFoldPanel(0));
233         return wxFoldPanel(m_panels.Item(i));
234     };
235 
236     /** Collapses the given wxFoldPanel reference, and updates the foldpanel bar. In the wxFPB_COLLAPSE_TO_BOTTOM
237         style, all collapsed captions are put at the bottom of the control. In the normal mode, they stay where
238         they are */
Collapse(const wxFoldPanel & item)239     void Collapse(const wxFoldPanel &item) {
240         wxCHECK2(item.IsOk(), return);
241         item.GetItem()->Collapse();
242 
243         RefreshPanelsFrom(item.GetItem());
244     };
245 
246     /** Expands the given wxFoldPanel reference, and updates the foldpanel bar. In the wxFPB_COLLAPSE_TO_BOTTOM
247        they will be removed from the bottom and the order where the panel originally was placed is restored.  */
Expand(const wxFoldPanel & item)248     void Expand(const wxFoldPanel &item) {
249         wxCHECK2(item.IsOk(), return);
250         item.GetItem()->Expand();
251 
252         RefreshPanelsFrom(item.GetItem());
253     };
254 
255  /** Sets the style of the caption bar (called wxCaptionBar) of the wxFoldPanel. The changes are applied immediately.
256         All styles not set in the wxCaptionBarStyle class are not applied. Use the wxCaptionBar reference to indicate
257         what captionbar you want to apply the style to. To apply one style to all wxCaptionBar items, use
258         ApplyCaptionStyleAll() */
ApplyCaptionStyle(wxFoldPanel & fp,const wxCaptionBarStyle & style)259     void ApplyCaptionStyle(wxFoldPanel &fp, const wxCaptionBarStyle &style) {
260         wxCHECK2(fp.IsOk(), return);
261         fp.GetItem()->ApplyCaptionStyle(style);
262     };
263 
264     /** Sets the style of all the caption bars of the wxFoldPanel. The changes are applied immediately */
ApplyCaptionStyleAll(const wxCaptionBarStyle & style)265     void ApplyCaptionStyleAll(const wxCaptionBarStyle &style) {
266         for(size_t i = 0; i < GetCount(); i++)
267         {
268             wxFoldPanel item = Item(i);
269             ApplyCaptionStyle(item, style);
270         }
271     };
272 
273     /** Returns the currently used caption style for the wxFoldPanel. It is returned as a wxCaptionBarStyle class.
274         after modifying it, it can be set again */
GetCaptionStyle(wxFoldPanel & fp)275     wxCaptionBarStyle GetCaptionStyle(wxFoldPanel &fp) const {
276         wxCHECK2(fp.IsOk(), return wxEmptyCaptionBarStyle);
277         return fp.GetItem()->GetCaptionStyle();
278     };
279 
280 private:
281     void OnPressCaption(wxCaptionBarEvent &event);
282     void OnSizePanel(wxSizeEvent &event);
283 
284     /** Resize the fold panels so they match the width */
285     void RedisplayFoldPanelItems();
286 
287     void OnPaint(wxPaintEvent &event);
288 };
289 
290 #endif // __WXFOLDPANELBAR_H__
291