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