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