1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sd.hxx" 30 31 #include "FormShellManager.hxx" 32 33 #include "EventMultiplexer.hxx" 34 #include "ViewShell.hxx" 35 #include "ViewShellBase.hxx" 36 #include "ViewShellManager.hxx" 37 #include "Window.hxx" 38 #include <svx/fmshell.hxx> 39 40 namespace sd { 41 42 namespace { 43 44 /** This factory is responsible for creating and deleting the FmFormShell. 45 */ 46 class FormShellManagerFactory 47 : public ::sd::ShellFactory<SfxShell> 48 { 49 public: 50 FormShellManagerFactory (ViewShell& rViewShell, FormShellManager& rManager); 51 virtual FmFormShell* CreateShell (ShellId nId, ::Window* pParentWindow, FrameView* pFrameView); 52 virtual void ReleaseShell (SfxShell* pShell); 53 54 private: 55 ::sd::ViewShell& mrViewShell; 56 FormShellManager& mrFormShellManager; 57 }; 58 59 } // end of anonymous namespace 60 61 62 FormShellManager::FormShellManager (ViewShellBase& rBase) 63 : mrBase(rBase), 64 mpFormShell(NULL), 65 mbFormShellAboveViewShell(false), 66 mpSubShellFactory(), 67 mbIsMainViewChangePending(false), 68 mpMainViewShellWindow(NULL) 69 { 70 // Register at the EventMultiplexer to be informed about changes in the 71 // center pane. 72 Link aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler)); 73 mrBase.GetEventMultiplexer()->AddEventListener( 74 aLink, 75 sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED 76 | sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED 77 | sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED); 78 79 RegisterAtCenterPane(); 80 } 81 82 83 84 85 FormShellManager::~FormShellManager (void) 86 { 87 SetFormShell(NULL); 88 UnregisterAtCenterPane(); 89 90 // Unregister from the EventMultiplexer. 91 Link aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler)); 92 mrBase.GetEventMultiplexer()->RemoveEventListener(aLink); 93 94 if (mpSubShellFactory.get() != NULL) 95 { 96 ViewShell* pShell = mrBase.GetMainViewShell().get(); 97 if (pShell != NULL) 98 mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell,mpSubShellFactory); 99 } 100 } 101 102 103 104 105 void FormShellManager::SetFormShell (FmFormShell* pFormShell) 106 { 107 if (mpFormShell != pFormShell) 108 { 109 // Disconnect from the old form shell. 110 if (mpFormShell != NULL) 111 { 112 mpFormShell->SetControlActivationHandler(Link()); 113 EndListening(*mpFormShell); 114 mpFormShell->SetView(NULL); 115 } 116 117 mpFormShell = pFormShell; 118 119 // Connect to the new form shell. 120 if (mpFormShell != NULL) 121 { 122 mpFormShell->SetControlActivationHandler( 123 LINK( 124 this, 125 FormShellManager, 126 FormControlActivated)); 127 StartListening(*mpFormShell); 128 129 ViewShell* pMainViewShell = mrBase.GetMainViewShell().get(); 130 if (pMainViewShell != NULL) 131 { 132 // Prevent setting the view twice at the FmFormShell. 133 FmFormView* pFormView = static_cast<FmFormView*>(pMainViewShell->GetView()); 134 if (mpFormShell->GetFormView() != pFormView) 135 mpFormShell->SetView(pFormView); 136 } 137 } 138 139 // Tell the ViewShellManager where on the stack to place the form shell. 140 mrBase.GetViewShellManager()->SetFormShell( 141 mrBase.GetMainViewShell().get(), 142 mpFormShell, 143 mbFormShellAboveViewShell); 144 } 145 } 146 147 148 149 150 FmFormShell* FormShellManager::GetFormShell (void) 151 { 152 return mpFormShell; 153 } 154 155 156 157 158 void FormShellManager::RegisterAtCenterPane (void) 159 { 160 do 161 { 162 ViewShell* pShell = mrBase.GetMainViewShell().get(); 163 if (pShell == NULL) 164 break; 165 166 // No form shell for the slide sorter. Besides that it is not 167 // necessary, using both together results in crashes. 168 if (pShell->GetShellType() == ViewShell::ST_SLIDE_SORTER) 169 break; 170 171 mpMainViewShellWindow = pShell->GetActiveWindow(); 172 if (mpMainViewShellWindow == NULL) 173 break; 174 175 // Register at the window to get informed when to move the form 176 // shell to the bottom of the shell stack. 177 mpMainViewShellWindow->AddEventListener( 178 LINK( 179 this, 180 FormShellManager, 181 WindowEventHandler)); 182 183 // Create a shell factory and with it activate the form shell. 184 OSL_ASSERT(mpSubShellFactory.get()==NULL); 185 mpSubShellFactory.reset(new FormShellManagerFactory(*pShell, *this)); 186 mrBase.GetViewShellManager()->AddSubShellFactory(pShell,mpSubShellFactory); 187 mrBase.GetViewShellManager()->ActivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX); 188 } 189 while (false); 190 } 191 192 193 194 195 void FormShellManager::UnregisterAtCenterPane (void) 196 { 197 do 198 { 199 if (mpMainViewShellWindow != NULL) 200 { 201 // Unregister from the window. 202 mpMainViewShellWindow->RemoveEventListener( 203 LINK( 204 this, 205 FormShellManager, 206 WindowEventHandler)); 207 mpMainViewShellWindow = NULL; 208 } 209 210 // Unregister form at the form shell. 211 SetFormShell(NULL); 212 213 // Deactivate the form shell and destroy the shell factory. 214 ViewShell* pShell = mrBase.GetMainViewShell().get(); 215 if (pShell != NULL) 216 { 217 mrBase.GetViewShellManager()->DeactivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX); 218 mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell, mpSubShellFactory); 219 } 220 221 mpSubShellFactory.reset(); 222 } 223 while (false); 224 } 225 226 227 228 229 IMPL_LINK(FormShellManager, FormControlActivated, FmFormShell*, EMPTYARG) 230 { 231 // The form shell has been actived. To give it priority in reacting to 232 // slot calls the form shell is moved to the top of the object bar shell 233 // stack. 234 ViewShell* pShell = mrBase.GetMainViewShell().get(); 235 if (pShell!=NULL && !mbFormShellAboveViewShell) 236 { 237 mbFormShellAboveViewShell = true; 238 239 ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager()); 240 mrBase.GetViewShellManager()->SetFormShell(pShell,mpFormShell,mbFormShellAboveViewShell); 241 } 242 243 return 0; 244 } 245 246 247 248 249 IMPL_LINK(FormShellManager, ConfigurationUpdateHandler, sd::tools::EventMultiplexerEvent*, pEvent) 250 { 251 switch (pEvent->meEventId) 252 { 253 case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED: 254 UnregisterAtCenterPane(); 255 break; 256 257 case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED: 258 mbIsMainViewChangePending = true; 259 break; 260 261 case sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED: 262 if (mbIsMainViewChangePending) 263 { 264 mbIsMainViewChangePending = false; 265 RegisterAtCenterPane(); 266 } 267 break; 268 269 default: 270 break; 271 } 272 273 return 0; 274 } 275 276 277 278 279 IMPL_LINK(FormShellManager, WindowEventHandler, VclWindowEvent*, pEvent) 280 { 281 if (pEvent != NULL) 282 { 283 switch (pEvent->GetId()) 284 { 285 case VCLEVENT_WINDOW_GETFOCUS: 286 { 287 // The window of the center pane got the focus. Therefore 288 // the form shell is moved to the bottom of the object bar 289 // stack. 290 ViewShell* pShell = mrBase.GetMainViewShell().get(); 291 if (pShell!=NULL && mbFormShellAboveViewShell) 292 { 293 mbFormShellAboveViewShell = false; 294 ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager()); 295 mrBase.GetViewShellManager()->SetFormShell( 296 pShell, 297 mpFormShell, 298 mbFormShellAboveViewShell); 299 } 300 } 301 break; 302 303 case VCLEVENT_WINDOW_LOSEFOCUS: 304 // We follow the sloppy focus policy. Losing the focus is 305 // ignored. We wait for the focus to be placed either in 306 // the window or the form shell. The later, however, is 307 // notified over the FormControlActivated handler, not this 308 // one. 309 break; 310 311 case VCLEVENT_OBJECT_DYING: 312 mpMainViewShellWindow = NULL; 313 break; 314 } 315 } 316 317 return 0; 318 } 319 320 321 322 323 void FormShellManager::Notify(SfxBroadcaster&, const SfxHint& rHint) 324 { 325 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint); 326 if (pSimpleHint!=NULL && pSimpleHint->GetId()==SFX_HINT_DYING) 327 { 328 // If all goes well this listener is called after the 329 // FormShellManager was notified about the dying form shell by the 330 // FormShellManagerFactory. 331 OSL_ASSERT(mpFormShell==NULL); 332 if (mpFormShell != NULL) 333 { 334 mpFormShell = NULL; 335 mrBase.GetViewShellManager()->SetFormShell( 336 mrBase.GetMainViewShell().get(), 337 NULL, 338 false); 339 } 340 } 341 } 342 343 344 345 346 347 //===== FormShellManagerFactory =============================================== 348 349 namespace { 350 351 FormShellManagerFactory::FormShellManagerFactory ( 352 ::sd::ViewShell& rViewShell, 353 FormShellManager& rManager) 354 : mrViewShell(rViewShell), 355 mrFormShellManager(rManager) 356 { 357 } 358 359 360 361 362 FmFormShell* FormShellManagerFactory::CreateShell ( 363 ::sd::ShellId nId, 364 ::Window*, 365 ::sd::FrameView*) 366 { 367 FmFormShell* pShell = NULL; 368 369 ::sd::View* pView = mrViewShell.GetView(); 370 if (nId == RID_FORMLAYER_TOOLBOX) 371 { 372 pShell = new FmFormShell(&mrViewShell.GetViewShellBase(), pView); 373 mrFormShellManager.SetFormShell(pShell); 374 } 375 376 return pShell; 377 } 378 379 380 381 382 void FormShellManagerFactory::ReleaseShell (SfxShell* pShell) 383 { 384 if (pShell != NULL) 385 { 386 mrFormShellManager.SetFormShell(NULL); 387 delete pShell; 388 } 389 } 390 391 } // end of anonymous namespace 392 393 } // end of namespace sd 394