xref: /trunk/main/sfx2/source/sidebar/SidebarController.hxx (revision 9d37da743abb7db0a497688391f6e55a19f27c44)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #ifndef SFX_SIDEBAR_CONTROLLER_HXX
23 #define SFX_SIDEBAR_CONTROLLER_HXX
24 
25 #include "AsynchronousCall.hxx"
26 #include "Context.hxx"
27 #include "FocusManager.hxx"
28 #include "Panel.hxx"
29 #include "ResourceManager.hxx"
30 #include "TabBar.hxx"
31 
32 #include <vcl/menu.hxx>
33 
34 #include <com/sun/star/awt/XWindowPeer.hpp>
35 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
36 #include <com/sun/star/frame/XDispatch.hpp>
37 #include <com/sun/star/ui/XContextChangeEventListener.hpp>
38 #include <com/sun/star/ui/XUIElement.hpp>
39 #include <com/sun/star/ui/XSidebar.hpp>
40 
41 #include <boost/noncopyable.hpp>
42 #include <boost/optional.hpp>
43 #include <cppuhelper/compbase4.hxx>
44 #include <cppuhelper/basemutex.hxx>
45 #include <cppuhelper/weakref.hxx>
46 #include <comphelper/stl_types.hxx>
47 
48 
49 namespace css = ::com::sun::star;
50 namespace cssu = ::com::sun::star::uno;
51 
52 
53 namespace
54 {
55     typedef ::cppu::WeakComponentImplHelper4 <
56         css::ui::XContextChangeEventListener,
57         css::beans::XPropertyChangeListener,
58         css::ui::XSidebar,
59         css::frame::XStatusListener
60         > SidebarControllerInterfaceBase;
61 }
62 
63 class SfxSplitWindow;
64 class FixedBitmap;
65 
66 namespace sfx2 { namespace sidebar {
67 
68 class ContentPanelDescriptor;
69 class Deck;
70 class DeckDescriptor;
71 class SidebarDockingWindow;
72 class TabBar;
73 class TabBarConfiguration;
74 
75 class SidebarController
76     : private ::boost::noncopyable,
77       private ::cppu::BaseMutex,
78       public SidebarControllerInterfaceBase
79 {
80 public:
81     SidebarController(
82         SidebarDockingWindow* pParentWindow,
83         const cssu::Reference<css::frame::XFrame>& rxFrame);
84     virtual ~SidebarController (void);
85 
86     /** Return the SidebarController object that is associated with
87         the given XFrame.
88         @return
89             When there is no SidebarController object for the given
90             XFrame then <NULL/> is returned.
91     */
92     static SidebarController* GetSidebarControllerForFrame (
93         const cssu::Reference<css::frame::XFrame>& rxFrame);
94 
95     // ui::XContextChangeEventListener
96     virtual void SAL_CALL notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent);
97 
98     // XEventListener
99     virtual void SAL_CALL disposing (const css::lang::EventObject& rEventObject);
100 
101     // beans::XPropertyChangeListener
102     virtual void SAL_CALL propertyChange (const css::beans::PropertyChangeEvent& rEvent);
103 
104     // frame::XStatusListener
105     virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent);
106 
107     // ui::XSidebar
108     virtual void SAL_CALL requestLayout (void);
109 
110     void NotifyResize (void);
111 
112     /** In some situations it is necessary to force an update of the
113         current deck and its panels.  One reason is a change of the
114         view scale.  Some panels can handle this only when
115         constructed.  In this case we have to a context change and
116         also force that all panels are destroyed and created new.
117     */
118     const static sal_Int32 SwitchFlag_NoForce = 0x00;
119     const static sal_Int32 SwitchFlag_ForceSwitch = 0x01;
120     const static sal_Int32 SwitchFlag_ForceNewDeck = 0x02;
121     const static sal_Int32 SwitchFlag_ForceNewPanels = 0x02;
122 
123     void RequestSwitchToDeck (
124         const ::rtl::OUString& rsDeckId);
125     void OpenThenSwitchToDeck (
126         const ::rtl::OUString& rsDeckId);
127 
128     /** Show only the tab bar, not the deck.
129     */
130     void RequestCloseDeck (void);
131 
132     /** Open the deck area and restore the parent window to its old width.
133     */
134     void RequestOpenDeck (void);
135 
136     FocusManager& GetFocusManager (void);
137 
138 private:
139     typedef ::std::map<
140         const cssu::Reference<css::frame::XFrame>,
141         cssu::WeakReference<SidebarController>
142     > SidebarControllerContainer;
143     static SidebarControllerContainer maSidebarControllerContainer;
144 
145     ::boost::scoped_ptr<Deck> mpCurrentDeck;
146     SidebarDockingWindow* mpParentWindow;
147     ::boost::scoped_ptr<TabBar> mpTabBar;
148     cssu::Reference<css::frame::XFrame> mxFrame;
149     Context maCurrentContext;
150     Context maRequestedContext;
151     /// Use a combination of SwitchFlag_* as value.
152     sal_Int32 mnRequestedForceFlags;
153     ::rtl::OUString msCurrentDeckId;
154     ::rtl::OUString msCurrentDeckTitle;
155     AsynchronousCall maPropertyChangeForwarder;
156     AsynchronousCall maContextChangeUpdate;
157     AsynchronousCall maAsynchronousDeckSwitch;
158 
159     /** Two flags control whether the deck is displayed or if only the
160         tab bar remains visible.
161         The mbIsDeckOpen flag stores the current state while
162         mbIsDeckRequestedOpen stores how this state should be.  User
163         actions like clicking on the deck closer affect the
164         mbIsDeckRequestedOpen.  Normally both flags have the same
165         value.  A document being read-only can prevent the deck from opening.
166     */
167     ::boost::optional<bool> mbIsDeckRequestedOpen;
168     ::boost::optional<bool> mbIsDeckOpen;
169     bool mbCanDeckBeOpened;
170 
171     /** Before the deck is closed the sidebar width is saved into this variable,
172         so that it can be restored when the deck is reopened.
173     */
174     sal_Int32 mnSavedSidebarWidth;
175     FocusManager maFocusManager;
176     cssu::Reference<css::frame::XDispatch> mxReadOnlyModeDispatch;
177     bool mbIsDocumentReadOnly;
178     SfxSplitWindow* mpSplitWindow;
179     /** When the user moves the splitter then we remember the
180         width at that time.
181     */
182     sal_Int32 mnWidthOnSplitterButtonDown;
183     /** Control that is temporarily used as replacement for the deck
184         to indicate that when the current mouse drag operation ends, the
185         sidebar will only show the tab bar.
186     */
187     ::boost::scoped_ptr<Window> mpCloseIndicator;
188 
189     DECL_LINK(WindowEventHandler, VclWindowEvent*);
190     /** Make maRequestedContext the current context.
191     */
192     void UpdateConfigurations (void);
193 
194     cssu::Reference<css::ui::XUIElement> CreateUIElement (
195         const cssu::Reference<css::awt::XWindowPeer>& rxWindow,
196         const ::rtl::OUString& rsImplementationURL,
197         const bool bWantsCanvas,
198         const Context& rContext);
199     SharedPanel CreatePanel (
200         const ::rtl::OUString& rsPanelId,
201         ::Window* pParentWindow,
202         const bool bIsInitiallyExpanded,
203         const Context& rContext);
204     void SwitchToDeck (
205         const ::rtl::OUString& rsDeckId);
206     void SwitchToDeck (
207         const DeckDescriptor& rDeckDescriptor,
208         const Context& rContext);
209     void ShowPopupMenu (
210         const Rectangle& rButtonBox,
211         const ::std::vector<TabBar::DeckMenuData>& rMenuData) const;
212     void ShowDetailMenu (const ::rtl::OUString& rsMenuCommand) const;
213     ::boost::shared_ptr<PopupMenu> CreatePopupMenu (
214         const ::std::vector<TabBar::DeckMenuData>& rMenuData) const;
215     DECL_LINK(OnMenuItemSelected, Menu*);
216     void BroadcastPropertyChange (void);
217 
218     /** The close of the deck changes the width of the child window.
219         That is only possible if there is no other docking window docked above or below the sidebar.
220         Return whether the width of the child window can be modified.
221     */
222     bool CanModifyChildWindowWidth (void);
223 
224     /** Set the child window container to a new width.
225         Return the old width.
226     */
227     sal_Int32 SetChildWindowWidth (const sal_Int32 nNewWidth);
228 
229     /** Update the icons displayed in the title bars of the deck and
230         the panels.  This is called once when a deck is created and
231         every time when a data change event is processed.
232     */
233     void UpdateTitleBarIcons (void);
234 
235     void UpdateDeckOpenState (void);
236     void RestrictWidth (void);
237     SfxSplitWindow* GetSplitWindow (void);
238     void ProcessNewWidth (const sal_Int32 nNewWidth);
239     void UpdateCloseIndicator (const bool bIsIndicatorVisible);
240 
241     /** Typically called when a panel is focused via keyboard.
242         Tries to scroll the deck up or down to make the given panel
243         completely visible.
244     */
245     void ShowPanel (const Panel& rPanel);
246 
247     Context GetCurrentContext (void) const;
248 
249     virtual void SAL_CALL disposing (void);
250 };
251 
252 
253 } } // end of namespace sfx2::sidebar
254 
255 #endif
256