1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  */
5 
6 #ifndef CBAUIBOOK_H_INCLUDED
7 #define CBAUIBOOK_H_INCLUDED
8 
9 #include "prep.h"
10 #include "settings.h" // DLLIMPORT
11 
12 #include <vector>
13 
14 #include <wx/aui/auibook.h>
15 #include <wx/dynarray.h>
16 
17 class wxTipWindow;
18 class cbAuiNotebook;
19 
20 WX_DEFINE_ARRAY_PTR(wxAuiTabCtrl*,cbAuiTabCtrlArray);
21 WX_DEFINE_ARRAY_PTR(cbAuiNotebook*,cbAuiNotebookArray);
22 
23 /** \brief A notebook class
24   * This class is derived from wxAuiNotebook, to enhance its abilities.
25   * It adds the ability to store (and restore) the visible tab-order, because
26   * wxAuiNotebook-tabs can be reordered with drag and drop.
27   * Another added feature is the possibility to add tooltips to the tabs belonging
28   * to added panes.
29   */
30 class DLLIMPORT cbAuiNotebook : public wxAuiNotebook
31 {
32     public:
33         /** \brief cbAuiNotebook constructor
34          *
35          * \param pParent the parent window, usually the app-window
36          * \param id the notebook id
37          * \param pos the position
38          * \param size the size
39          * \param style the notebook style
40          */
41         cbAuiNotebook(wxWindow* pParent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxAUI_NB_DEFAULT_STYLE);
42         /** cbAuiNotebook destructor  */
43         ~cbAuiNotebook() override;
44 
45         /** \brief Advances the selection
46          *
47          * In contrast to the base-classes function, it uses the visible tab-order, not the order
48          * of creation and jumps to the first tab, if the last is reached (and vice versa)
49          * \param forward if false direction is backwards
50          */
51         void AdvanceSelection(bool forward = true);
52         /** \brief Save layout of the notebook
53          * \param projectTitle only save the layout of the project with this title, save all projects layout, if empty
54          * \return wxString the serialized layout
55          */
56         wxString SavePerspective(const wxString projectTitle = wxEmptyString);
57         /** \brief Loads serialized notebook layout
58          * \param layout the serialized layout
59          * \param mergeLayouts try to merge the tab-layouts
60          * \return bool true if successfull
61          *
62          */
63         bool LoadPerspective(const wxString& layout, bool mergeLayouts = false);
64         /** \brief Get the tab index from tooltiptext
65          * \param text the notebooks name
66          * \return int the tab's index
67          * @remarks We use the name internally to store the tooltip-text. To use it
68          * in this function, we create a unique string from the relative filename
69          * and the projects title. So it should be unique even after a
70          * restart of C::B.
71          */
72         int GetTabIndexFromTooltip(const wxString& text);
73         /** \brief Get the tab position
74          *
75          * Returns the position of the tab as it is visible.
76          * Starts with 0
77          * \param index the index of the tab in order of creation
78          * \return int the visible position
79          */
80         int GetTabPositionFromIndex(int index);
81 #if !wxCHECK_VERSION(3, 0, 0)
82         /** \brief Set a tab tooltip
83          *
84          * Sets the tooltip for the tab belonging to win.
85          * Starts the dwell timer and the stopwatch if it is not already done.
86          * \param idx the index of the pane that belongs to the tab
87          * \param text the tooltip
88          * @remarks Uses the name of the wxWindow to store the message
89          * \return bool true if tooltip was updated
90          */
91         bool SetPageToolTip(size_t idx, const wxString & text );
92         /** \brief Get a tab tooltip
93          *
94          * Returns the tooltip for the tab label of the page.
95          * @remarks Uses the name of the wxWindow to store the message
96          * \return wxString the tooltip of the page with the given index
97          */
98         wxString GetPageToolTip(size_t idx	);
99 #endif // !wxCHECK_VERSION(3, 0, 0)
100         /** \brief Minmize free horizontal page
101          *
102          * Moves the active tab of all tabCtrl's to the rightmost place,
103          * to show as many tabs as possible.
104          */
105         void MinimizeFreeSpace();
106         /** \brief Delete Page
107          *
108          * Calls the base-class function and after that
109          * MinmizeFreeSpace(), needed to hook into the close-events.
110          * The system generated close event has to be veto'd, and Close()
111          * has to be called manually, so we can handle it ourselves.
112          * \param The index of the tab to be closed
113          * \return true if successfull
114          */
115         bool DeletePage(size_t page);
116         /** \brief Remove Page
117          *
118          * Calls the base-class function and after that
119          * MinmizeFreeSpace(), needed to hook into the close-events.
120          * The system generated close event has to be veto'd, and Close()
121          * has to be called manually, so we can handle it ourselves.
122          * \param The index of the tab to be closed
123          * \return true if successfull
124          */
125         bool RemovePage(size_t page);
126         /** \brief Move page
127          *
128          * Moves the tab containing page to new_idx
129          * \param page The page to move (e.g. cbEditor*)
130          * \param new_idx The index the page should be moved to
131          * \return true if successfull
132          */
133         bool MovePage(wxWindow* page, size_t new_idx);
134         /** \brief Add Page
135          *
136          * Calls the base-class function and after that
137          * MinmizeFreeSpace().
138          * \param page The page to add
139          * \param caption The caption of the page
140          * \param select If true the page gets selected
141          * \param bitmap The bitmap of the tab
142          * \return true if successfull
143          */
144         bool AddPage(wxWindow* page,
145                      const wxString& caption,
146                      bool select = false,
147                      const wxBitmap& bitmap = wxNullBitmap);
148         /** \brief Insert Page
149          *
150          * Calls the base-class function and after that
151          * MinmizeFreeSpace().
152          * \param page_idx The index where the page should be inserted
153          * \param page The page to add
154          * \param caption The caption of the page
155          * \param select If true the page gets selected
156          * \param bitmap The bitmap of the tab
157          * \return true if successfull
158          */
159         bool InsertPage(size_t page_idx,
160                         wxWindow* page,
161                         const wxString& caption,
162                         bool select = false,
163                         const wxBitmap& bitmap = wxNullBitmap);
164         /** \brief Set zoomfactor for builtin editors
165          *
166          * Sets the zoomfactor for all visible builtin
167          * editors.
168          * \param zoom zoomfactor to use
169          */
170         void SetZoom(int zoom);
171         /** \brief Set Focus on the tabCtrl belonging to the active tab
172          */
173         void FocusActiveTabCtrl();
174 
175         /** \brief Returns a pointer to the page's tab control or nullptr.
176          */
177         wxAuiTabCtrl* GetTabCtrl(wxWindow *page);
178 
179         /** \brief Return a vector containing all pages that are in the same
180          * tab control as the page passed as parameter.
181          */
182         void GetPagesInTabCtrl(std::vector<wxWindow*> &result, wxWindow *page);
183     protected:
184         /** \brief Create a unique id from the tooltip-text
185          *
186          * Tries to create a unique id from the tooltip.
187          * Find the projectfile, geet the relative filename and put it
188          * together with the projects name.
189          * We use it to save and load the pane layout.
190          * By using the relative filename, it works even if the project
191          * gets moved to another place.
192          * \param text The tooltip text
193          */
194         wxString UniqueIdFromTooltip(const wxString& text);
195         /** \brief Minmize free horizontal page of tabCtrl
196          *
197          * Moves the active tab of tabCtrl to the rightmost place,
198          * to show as many tabs as possible.
199          * \param tabCtrl The tabCtrl to act on
200          */
201         void MinimizeFreeSpace(wxAuiTabCtrl* tabCtrl);
202         /** \brief Handle the navigation key event
203          *
204          * Tries to handle the navigation key-event and use "our" AdvanceSelection().
205          * \param event
206          * @remarks Works not reliable, due to OS/wxWidgets-limitations
207          */
208 #if wxCHECK_VERSION(3, 0, 0)
209         void OnNavigationKeyNotebook(wxNavigationKeyEvent& event);
210 #else
211         void OnNavigationKey(wxNavigationKeyEvent& event);
212 #endif // wxCHECK_VERSION(3, 0, 0)
213         /** \brief OnIdle
214          *
215          * \param event unused
216          */
217         void OnIdle(cb_unused wxIdleEvent& event);
218 #if !wxCHECK_VERSION(3, 0, 0)
219         /** \brief Catch mousemotion-events
220          *
221          * Needed for the backport of tabtooltip from wx2.9
222          *
223          * \param event holds the wxTabCtrl, that sends the event
224          */
225         void OnMotion(wxMouseEvent& event);
226 #endif // !wxCHECK_VERSION(3, 0, 0)
227         /** \brief Catch doubleclick-events from wxTabCtrl
228          *
229          * Sends cbEVT_CBAUIBOOK_LEFT_DCLICK, if doubleclick was on a tab,
230          * event-Id is the notebook-Id, event-object is the pointer to the window the
231          * tab belongs to.
232          * \param event holds the wxTabCtrl, that sends the event
233          */
234         void OnTabCtrlDblClick(wxMouseEvent& event);
235         /** \brief Catch mousewheel-events from wxTabCtrl
236          *
237          * Sends cbEVT_CBAUIBOOK_MOUSEWHEEL, if doubleclick was on a tab,
238          * event-Id is the notebook-Id, event-object is the pointer to the window the
239          * tab belongs to.
240          * \param event holds the wxTabCtrl, that sends the event
241          */
242         void OnTabCtrlMouseWheel(wxMouseEvent& event);
243         /** \brief Catch resize-events and call MinimizeFreeSpace()
244          *
245          * \param event unused
246          */
247         void OnResize(wxSizeEvent& event);
248         /** \brief Catch dragdone-events from wxTabCtrl
249          *
250          */
251         void OnDragDone(wxAuiNotebookEvent& event);
252 #ifdef __WXMSW__
253         /** \brief Catch mouseenter-events from wxTabCtrl
254          *
255          * Set focus on wxTabCtrl
256          * \param event holds the wxTabCtrl, that sends the event
257          */
258         void OnEnterTabCtrl(wxMouseEvent& event);
259         /** \brief Catch mouseleave-events from wxTabCtrl
260          *
261          * \param event holds the wxTabCtrl, that sends the event
262          */
263         void OnLeaveTabCtrl(wxMouseEvent& event);
264         // hack needed on wxMSW, because only focused windows get mousewheel-events
265         /** \brief Checks the old focus
266          *
267          * Checks whether the old focused window or one of it's
268          * parents is the same as page.
269          * If they are equal, we have to reset the stored pointer,
270          * because we get a crash otherwise.
271          * \param page The page to check against
272          * \return bool
273          */
274         bool IsFocusStored(wxWindow* page);
275         /** \brief Save old focus
276          *
277          * Save old focus and tab-selection,
278          * \param event holds the wxTabCtrl, that sends the event
279          */
280         void StoreFocus();
281         /** \brief Restore old focus
282          *
283          * Restore old focus or set the focus on the activated tab
284          * \param event holds the wxTabCtrl, that sends the event
285          */
286         void RestoreFocus();
287 #endif // __WXMSW__
288         /** \brief Reset tabctrl events
289          */
290         void ResetTabCtrlEvents();
291         /** \brief Updates the array, that holds the wxTabCtrls
292          */
293         void UpdateTabControlsArray();
294         /** \brief Check for pressed modifier-keys
295          *
296          * Check whether all modifier keys in keyModifier are pressed
297          * or not
298          * \param keyModifier wxSTring containing the modifier(s) to check for
299          * \return true If all modifier-keys are pressed
300          */
301         bool CheckKeyModifier();
302         /** \brief Holds the wxTabCtrls used by the notebook
303          * @remarks Should be updated with UpdateTabControlsArray(),
304          * before it's used
305          */
306         cbAuiTabCtrlArray m_TabCtrls;
307 #ifdef __WXMSW__
308         // needed for wxMSW-hack, see above
309         /** \brief Last selected tab
310          *
311          * Used to determine whether the tab-selection has changed btween mouseenter
312          * and mouseleave-event.
313          */
314         int m_LastSelected;
315         /** \brief Id of last focused window
316          *
317          * Used to restore the focus after a mouseleave-event on wxTabCtrl.
318          */
319         long m_LastId;
320 #endif // __WXMSW__
321 #if !wxCHECK_VERSION(3, 0, 0)
322         /** \brief If false, tooltips are not shown
323          *
324          * Needed to only show tooltips, if they have been explicitely set.
325          * We store the tooltip-text in the tabs name, without this flag, we
326          * get the wxWidgets default-names as tooltips.
327          */
328         bool m_HasToolTip;
329 #endif // !wxCHECK_VERSION(3, 0, 0)
330         /** \brief If true, zoom for all editors
331          * is set in next OnIdle-call
332          */
333         bool m_SetZoomOnIdle;
334         /** \brief If true, MinimizeFreeSpace is called
335          * in next OnIdle-call
336          */
337         bool m_MinimizeFreeSpaceOnIdle;
338         /** \brief Holds the size of a tabCtrl after a resize event
339          *
340          * Needed to skip a resize event, if size did not change
341          * it gets triggered on any tab-click
342          */
343         wxSize m_TabCtrlSize;
344 
345 //static stuff (common to all cbAuiNotebooks)
346     public:
347         /** \brief Enable or disable tabtooltips globally
348          *
349          * \param use If true tooltips are allowed
350          */
351         static void UseToolTips(bool use = true);
352         /** \brief Enable or disable tab-scrolling with mousewheel
353          *
354          * \param allow If true scrolling is allowed
355          */
356         static void AllowScrolling(bool allow = true);
357         /** \brief Sets the modifier keys for scrolling
358          */
359         static void SetModKeys(wxString keys = _T("Strg"));
360         /** \brief Use modkey to advance through tabs with mousewheel
361          */
362         static void UseModToAdvance(bool use = false);
363         /** \brief Change direction of tab-advancing with mousewheel
364          *
365          * \param invert If true advance direction is inverted
366          */
367         static void InvertAdvanceDirection(bool invert = false);
368         /** \brief Change direction of tab-moving with mousewheel
369          *
370          * \param invert If true move direction is inverted
371          */
372         static void InvertMoveDirection(bool invert = false);
373     protected:
374         /** \brief Enable or disable tab tooltips
375          */
376         static bool s_UseTabTooltips;
377         /** \brief Enable or disable scrolling tabs with mousewheel
378          */
379         static bool s_AllowMousewheel;
380         /** \brief Holds an array of all existing cbAuiNotebooks
381          */
382         static cbAuiNotebookArray s_cbAuiNotebookArray;
383         /** \brief Holds the modifier keys for scrolling
384          */
385         static wxString s_modKeys;
386         /** \brief Use modkey to advance through tabs with mousewheel
387          */
388         static bool s_modToAdvance;
389         /** \brief Mousewheel move direction: negative => invert
390          */
391         static int s_moveDirection;
392         /** \brief Mouseweheel advance direction: negative => invert
393          */
394         static int s_advanceDirection;
395 
396     private:
397         // the following two using directives remove the "-Woverloaded-virtual" warnings
398         using wxAuiNotebook::AddPage;
399         using wxAuiNotebook::InsertPage;
400 
401         DECLARE_EVENT_TABLE()
402 };
403 
404 #endif // CBAUIBOOK_H_INCLUDED
405