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 #include "precompiled_sfx2.hxx" 23 24 #include "SidebarController.hxx" 25 #include "Deck.hxx" 26 #include "Panel.hxx" 27 #include "TitleBar.hxx" 28 #include "SidebarLayouter.hxx" 29 #include "TabBar.hxx" 30 #include "sfxresid.hxx" 31 #include "sfx2/sfxsids.hrc" 32 33 #include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp> 34 #include <com/sun/star/ui/ContextChangeEventObject.hpp> 35 36 #include <boost/bind.hpp> 37 #include <comphelper/componentfactory.hxx> 38 #include <comphelper/componentcontext.hxx> 39 #include <comphelper/namedvaluecollection.hxx> 40 41 42 using namespace css; 43 using namespace cssu; 44 45 46 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) 47 48 namespace sfx2 { 49 50 51 class SidebarController::Configuration 52 { 53 public: 54 Deck* mpDeck; 55 ::std::vector<Panel*> maPanels; 56 57 Configuration (void); 58 void Disable (void); 59 void Activate (void); 60 }; 61 62 63 64 65 SidebarController::SidebarController ( 66 Window* pParentWindow, 67 const cssu::Reference<css::frame::XFrame>& rxFrame) 68 : SidebarControllerInterfaceBase(m_aMutex), 69 mpCurrentConfiguration(), 70 mpParentWindow(pParentWindow), 71 mpTabBar(new TabBar(mpParentWindow)), 72 mxFrame(rxFrame) 73 { 74 if (pParentWindow == NULL) 75 { 76 OSL_ASSERT(pParentWindow!=NULL); 77 return; 78 } 79 80 UpdateConfiguration(Context(A2S("default"), A2S("default"))); 81 82 // Listen for context change events. 83 cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer ( 84 css::ui::ContextChangeEventMultiplexer::get( 85 ::comphelper::getProcessComponentContext())); 86 if (xMultiplexer.is()) 87 xMultiplexer->addContextChangeEventListener( 88 static_cast<css::ui::XContextChangeEventListener*>(this), 89 NULL); 90 91 // Listen for window events. 92 mpParentWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler)); 93 } 94 95 96 97 98 SidebarController::~SidebarController (void) 99 { 100 } 101 102 103 104 105 void SAL_CALL SidebarController::disposing (void) 106 { 107 cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer ( 108 css::ui::ContextChangeEventMultiplexer::get( 109 ::comphelper::getProcessComponentContext())); 110 if (xMultiplexer.is()) 111 xMultiplexer->removeAllContextChangeEventListeners( 112 static_cast<css::ui::XContextChangeEventListener*>(this)); 113 114 if (mpParentWindow != NULL) 115 { 116 mpParentWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler)); 117 mpParentWindow = NULL; 118 } 119 } 120 121 122 123 124 void SAL_CALL SidebarController::notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent) 125 throw(cssu::RuntimeException) 126 { 127 UpdateConfiguration(Context(rEvent.ApplicationName, rEvent.ContextName)); 128 } 129 130 131 132 133 void SAL_CALL SidebarController::disposing (const css::lang::EventObject& rEventObject) 134 throw(cssu::RuntimeException) 135 { 136 if (mpCurrentConfiguration) 137 { 138 mpCurrentConfiguration->Disable(); 139 mpCurrentConfiguration.reset(); 140 } 141 if (mpTabBar != NULL) 142 { 143 mpTabBar->Hide(); 144 delete mpTabBar; 145 mpTabBar = NULL; 146 } 147 } 148 149 150 151 152 void SidebarController::NotifyResize (void) 153 { 154 if (mpCurrentConfiguration != NULL) 155 { 156 SidebarLayouter::LayoutSidebar(mpCurrentConfiguration->mpDeck, mpTabBar); 157 SidebarLayouter::LayoutPanels(mpCurrentConfiguration->mpDeck, mpCurrentConfiguration->maPanels); 158 } 159 } 160 161 162 163 164 void SidebarController::UpdateConfiguration (const Context& rContext) 165 { 166 ::boost::scoped_ptr<Configuration> pConfiguration(new Configuration()); 167 168 SharedContentPanelManager pContentManager (ContentPanelManager::Instance()); 169 pContentManager->CallForBestMatchingDeck ( 170 ::boost::bind(&SidebarController::ProcessMatchingDeck, this, _1, ::boost::ref(*pConfiguration)), 171 rContext); 172 173 if (pConfiguration->mpDeck == NULL) 174 return; 175 176 pContentManager->CallForMatchingPanels ( 177 ::boost::bind(&SidebarController::ProcessMatchingPanel, this, _1, ::boost::ref(*pConfiguration)), 178 rContext, 179 pConfiguration->mpDeck->GetId()); 180 181 MakeConfigurationCurrent(*pConfiguration); 182 mpCurrentConfiguration.swap(pConfiguration); 183 } 184 185 186 187 188 void SidebarController::ProcessMatchingDeck ( 189 const DeckDescriptor& rDeckDescriptor, 190 Configuration& rConfiguration) 191 { 192 if (rConfiguration.mpDeck != NULL) 193 { 194 // When more than one deck matches the context then choose the first. 195 return; 196 } 197 198 rConfiguration.mpDeck = new Deck(rDeckDescriptor, mpParentWindow); 199 } 200 201 202 203 204 void SidebarController::ProcessMatchingPanel ( 205 const ContentPanelDescriptor& rPanelDescriptor, 206 Configuration& rConfiguration) 207 { 208 // Create the panel which is the parent window of the UIElement 209 // that we are about to create. 210 Panel* pPanel = new Panel(rPanelDescriptor, rConfiguration.mpDeck); 211 212 Reference<ui::XUIElement> xElement; 213 try 214 { 215 const ::comphelper::ComponentContext aComponentContext (::comphelper::getProcessServiceFactory()); 216 const Reference<ui::XUIElementFactory> xUIElementFactory ( 217 aComponentContext.createComponent("com.sun.star.ui.UIElementFactoryManager"), 218 UNO_QUERY_THROW); 219 220 ::comphelper::NamedValueCollection aCreationArguments; 221 aCreationArguments.put("Frame", makeAny(mxFrame)); 222 aCreationArguments.put("ParentWindow", makeAny(pPanel->GetComponentInterface())); 223 224 pPanel->SetUIElement( 225 Reference<ui::XUIElement>( 226 xUIElementFactory->createUIElement( 227 rPanelDescriptor.msImplementationURL, 228 aCreationArguments.getPropertyValues()), 229 UNO_QUERY_THROW)); 230 } 231 catch(Exception& rException) 232 { 233 OSL_TRACE("caught exception: %s", 234 OUStringToOString(rException.Message, RTL_TEXTENCODING_ASCII_US).getStr()); 235 // For some reason we can not create the actual panel. 236 // Probably because its factory was not properly registered. 237 // TODO: provide feedback to developer to better pinpoint the 238 // source of the error. 239 } 240 rConfiguration.maPanels.push_back(pPanel); 241 } 242 243 244 245 246 void SidebarController::MakeConfigurationCurrent (Configuration& rConfiguration) 247 { 248 if (rConfiguration.mpDeck == NULL) 249 return; 250 251 // Deactivate the current deck and panels. 252 if (mpCurrentConfiguration && mpCurrentConfiguration->mpDeck!=NULL) 253 mpCurrentConfiguration->Disable(); 254 SidebarLayouter::LayoutSidebar(rConfiguration.mpDeck, mpTabBar); 255 rConfiguration.Activate(); 256 } 257 258 259 260 261 IMPL_LINK(SidebarController, WindowEventHandler, VclWindowEvent*, pEvent) 262 { 263 if (pEvent != NULL) 264 { 265 ::Window* pWindow = pEvent->GetWindow(); 266 switch (pEvent->GetId()) 267 { 268 case VCLEVENT_WINDOW_GETFOCUS: 269 case VCLEVENT_WINDOW_LOSEFOCUS: 270 break; 271 272 case VCLEVENT_WINDOW_SHOW: 273 case VCLEVENT_WINDOW_RESIZE: 274 NotifyResize(); 275 break; 276 277 case SFX_HINT_DYING: 278 dispose(); 279 break; 280 281 default: 282 break; 283 } 284 } 285 286 return sal_True; 287 } 288 289 290 291 292 //===== SidebarController::Configuration ====================================== 293 294 SidebarController::Configuration::Configuration (void) 295 : mpDeck(NULL), 296 maPanels() 297 { 298 } 299 300 301 302 303 void SidebarController::Configuration::Disable (void) 304 { 305 // Hide and destroy the panels. 306 for (::std::vector<Panel*>::const_iterator 307 iPanel(maPanels.begin()), 308 iEnd(maPanels.end()); 309 iPanel!=iEnd; 310 ++iPanel) 311 { 312 (*iPanel)->Hide(); 313 mpDeck->removeWindow(*iPanel, NULL); 314 delete *iPanel; 315 } 316 maPanels.clear(); 317 318 // Hide and destroy the deck window. 319 mpDeck->Hide(); 320 mpDeck->GetParent()->removeWindow(mpDeck, NULL); 321 delete mpDeck; 322 mpDeck = NULL; 323 } 324 325 326 327 328 void SidebarController::Configuration::Activate (void) 329 { 330 SidebarLayouter::LayoutPanels(mpDeck, maPanels); 331 332 // Show the deck window. 333 mpDeck->GetTitleBar()->Show(); 334 mpDeck->Show(); 335 336 // Show the panels. 337 for (::std::vector<Panel*>::const_iterator 338 iPanel(maPanels.begin()), 339 iEnd(maPanels.end()); 340 iPanel!=iEnd; 341 ++iPanel) 342 { 343 (*iPanel)->GetTitleBar()->Show(); 344 (*iPanel)->Show(); 345 } 346 } 347 348 349 } // end of namespace sfx2 350