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_sd.hxx" 23 24 #include "SidebarFactory.hxx" 25 #include "framework/FrameworkHelper.hxx" 26 #include "framework/Pane.hxx" 27 #include "ViewShellBase.hxx" 28 #include "UIElementWrapper.hxx" 29 30 #include <sfx2/viewfrm.hxx> 31 #include <comphelper/namedvaluecollection.hxx> 32 #include <vcl/window.hxx> 33 #include <toolkit/helper/vclunohelper.hxx> 34 35 #include <com/sun/star/drawing/framework/XControllerManager.hpp> 36 37 using namespace css; 38 using namespace cssu; 39 using namespace css::drawing::framework; 40 using namespace ::sd::framework; 41 using ::rtl::OUString; 42 43 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) 44 45 namespace sd { namespace sidebar { 46 47 namespace { 48 /** Note that these names have to be identical to (the tail of) 49 the entries in officecfg/registry/data/org/openoffice/Office/Impress.xcu 50 for the TaskPanelFactory. 51 */ 52 const static char* gsResourceNameCustomAnimations = "/CustomAnimations"; 53 const static char* gsResourceNameLayouts = "/Layouts"; 54 const static char* gsResourceNameAllMasterPages = "/AllMasterPages"; 55 const static char* gsResourceNameRecentMasterPages = "/RecentMasterPages"; 56 const static char* gsResourceNameUsedMasterPages = "/UsedMasterPages"; 57 const static char* gsResourceNameSlideTransitions = "/SlideTransitions"; 58 const static char* gsResourceNameTableDesign = "/TableDesign"; 59 } 60 61 class SidebarFactory::Implementation 62 { 63 public: 64 Reference<cssdf::XConfigurationController> mxConfigurationController; 65 rtl::Reference<framework::Pane> mxPane; 66 Reference<ui::XUIElement> mxUIElement; 67 Reference<frame::XController> mxController; 68 Reference<awt::XWindow> mxParentWindow; 69 bool mbIsDisposed; 70 71 Implementation (const Reference<frame::XController>& rxController); 72 ~Implementation (void); 73 void Dispose (void); 74 }; 75 76 77 SidebarFactory::ControllerToImplementationMap SidebarFactory::maControllerToImplementationMap; 78 Reference<lang::XEventListener> mxControllerDisposeListener; 79 80 81 82 // ----- Service functions ---------------------------------------------------- 83 84 Reference<XInterface> SAL_CALL SidebarFactory_createInstance ( 85 const Reference<XComponentContext>& rxContext) 86 { 87 return Reference<XInterface>(static_cast<XWeak*>(new SidebarFactory(rxContext))); 88 } 89 90 91 92 93 ::rtl::OUString SidebarFactory_getImplementationName (void) throw(RuntimeException) 94 { 95 return ::rtl::OUString( 96 RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.Draw.framework.SidebarFactory")); 97 } 98 99 100 101 102 Sequence<rtl::OUString> SAL_CALL SidebarFactory_getSupportedServiceNames (void) 103 throw (RuntimeException) 104 { 105 static const ::rtl::OUString sServiceName( 106 ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.SidebarFactory")); 107 return Sequence<rtl::OUString>(&sServiceName, 1); 108 } 109 110 111 112 113 //----- SidebarFactory -------------------------------------------------------- 114 115 SidebarFactory::SidebarFactory( 116 const css::uno::Reference<css::uno::XComponentContext>& rxContext) 117 : SidebarFactoryInterfaceBase(m_aMutex), 118 mpImplementation() 119 { 120 } 121 122 123 124 125 SidebarFactory::~SidebarFactory (void) 126 { 127 } 128 129 130 131 132 void SAL_CALL SidebarFactory::disposing (void) 133 { 134 SharedImplementation pImplementation; 135 pImplementation.swap(mpImplementation); 136 if (pImplementation) 137 pImplementation->Dispose(); 138 } 139 140 141 142 143 // XInitialization 144 145 void SAL_CALL SidebarFactory::initialize (const Sequence<Any>& aArguments) 146 throw (Exception, RuntimeException) 147 { 148 if (aArguments.getLength() > 0) 149 { 150 mpImplementation = GetImplementationForController( 151 Reference<frame::XController>(aArguments[0], UNO_QUERY)); 152 } 153 } 154 155 156 157 158 // XUIElementFactory 159 160 Reference<ui::XUIElement> SAL_CALL SidebarFactory::createUIElement ( 161 const ::rtl::OUString& rsUIElementResourceURL, 162 const ::cssu::Sequence<css::beans::PropertyValue>& rArguments) 163 throw( 164 css::container::NoSuchElementException, 165 css::lang::IllegalArgumentException, 166 cssu::RuntimeException) 167 { 168 // Process arguments. 169 const ::comphelper::NamedValueCollection aArguments (rArguments); 170 Reference<frame::XFrame> xFrame (aArguments.getOrDefault("Frame", Reference<frame::XFrame>())); 171 Reference<awt::XWindow> xParentWindow (aArguments.getOrDefault("ParentWindow", Reference<awt::XWindow>())); 172 Reference<ui::XSidebar> xSidebar (aArguments.getOrDefault("Sidebar", Reference<ui::XSidebar>())); 173 174 // Throw exceptions when the arguments are not as expected. 175 ::Window* pParentWindow = VCLUnoHelper::GetWindow(xParentWindow); 176 if ( ! xParentWindow.is() || pParentWindow==NULL) 177 throw RuntimeException( 178 A2S("SidebarFactory::createUIElement called without ParentWindow"), 179 NULL); 180 if ( ! xFrame.is()) 181 throw RuntimeException( 182 A2S("SidebarFactory::createUIElement called without XFrame"), 183 NULL); 184 mpImplementation = GetImplementationForController(xFrame->getController()); 185 if ( ! mpImplementation) 186 throw RuntimeException( 187 A2S("SidebarFactory::createUIElement called without XController"), 188 NULL); 189 if (mpImplementation->mxConfigurationController.is()) 190 mpImplementation->mxConfigurationController->addResourceFactory( 191 FrameworkHelper::msSidebarPaneURL+A2S("*"), this); 192 193 // Remember the parent window, so that following calls to 194 // createResource() can access it. 195 mpImplementation->mxParentWindow = xParentWindow; 196 if (mpImplementation->mxPane.is()) 197 mpImplementation->mxPane->SetWindow(VCLUnoHelper::GetWindow(xParentWindow)); 198 199 // Create a framework view. 200 OUString sTaskPanelURL; 201 #define EndsWith(s,t) s.endsWithAsciiL(t,strlen(t)) 202 if (EndsWith(rsUIElementResourceURL, gsResourceNameCustomAnimations)) 203 sTaskPanelURL = FrameworkHelper::msCustomAnimationTaskPanelURL; 204 else if (EndsWith(rsUIElementResourceURL, gsResourceNameLayouts)) 205 sTaskPanelURL = FrameworkHelper::msLayoutTaskPanelURL; 206 else if (EndsWith(rsUIElementResourceURL, gsResourceNameAllMasterPages)) 207 sTaskPanelURL = FrameworkHelper::msAllMasterPagesTaskPanelURL; 208 else if (EndsWith(rsUIElementResourceURL, gsResourceNameRecentMasterPages)) 209 sTaskPanelURL = FrameworkHelper::msRecentMasterPagesTaskPanelURL; 210 else if (EndsWith(rsUIElementResourceURL, gsResourceNameUsedMasterPages)) 211 sTaskPanelURL = FrameworkHelper::msUsedMasterPagesTaskPanelURL; 212 else if (EndsWith(rsUIElementResourceURL, gsResourceNameSlideTransitions)) 213 sTaskPanelURL = FrameworkHelper::msSlideTransitionTaskPanelURL; 214 else if (EndsWith(rsUIElementResourceURL, gsResourceNameTableDesign)) 215 sTaskPanelURL = FrameworkHelper::msTableDesignPanelURL; 216 #undef EndsWith 217 218 if (sTaskPanelURL.getLength() == 0) 219 throw lang::IllegalArgumentException(); 220 221 // Create a wrapper around pane and view and return it as 222 // XUIElement. 223 Reference<ui::XUIElement> xUIElement; 224 try 225 { 226 xUIElement.set(new UIElementWrapper( 227 rsUIElementResourceURL, 228 xFrame, 229 sTaskPanelURL, 230 xSidebar, 231 VCLUnoHelper::GetWindow(xParentWindow))); 232 } 233 catch(Exception& rException) 234 { 235 // Creation of XUIElement failed. mxUIElement remains empty. 236 } 237 238 Reference<lang::XComponent> xComponent (xUIElement, UNO_QUERY); 239 if (xComponent.is()) 240 xComponent->addEventListener(this); 241 242 return xUIElement; 243 } 244 245 246 247 248 // XResourceFactory 249 250 Reference<drawing::framework::XResource> 251 SAL_CALL SidebarFactory::createResource ( 252 const Reference<drawing::framework::XResourceId>& rxPaneId) 253 throw (RuntimeException, lang::IllegalArgumentException, lang::WrappedTargetException) 254 { 255 if ( ! rxPaneId.is()) 256 throw lang::IllegalArgumentException(); 257 258 const OUString sResourceURL (rxPaneId->getResourceURL()); 259 if ( ! sResourceURL.equals(FrameworkHelper::msSidebarPaneURL)) 260 throw lang::IllegalArgumentException(); 261 262 if ( ! mpImplementation) 263 throw RuntimeException(A2S("SidebarFactory not initialized"), NULL); 264 265 ::Window* pWindow = VCLUnoHelper::GetWindow(mpImplementation->mxParentWindow); 266 if (pWindow == NULL) 267 throw RuntimeException(); 268 269 mpImplementation->mxPane.set(new Pane(rxPaneId, pWindow)); 270 Reference<drawing::framework::XResource> xPane (static_cast<XPane*>(mpImplementation->mxPane.get())); 271 return xPane; 272 } 273 274 275 276 277 void SAL_CALL SidebarFactory::releaseResource ( 278 const Reference<drawing::framework::XResource>& rxPane) 279 throw (RuntimeException) 280 { 281 (void)rxPane; 282 283 // Any panes created by us are just wrappers around windows whose lifetime 284 // is controlled somewhere else => nothing to do. 285 } 286 287 288 289 290 void SAL_CALL SidebarFactory::disposing (const ::css::lang::EventObject& rEvent) 291 throw(cssu::RuntimeException) 292 { 293 /* 294 if (mpImplementation 295 && rEvent.Source == mpImplementation->mxUIElement) 296 { 297 mpImplementation->mxUIElement.clear(); 298 } 299 */ 300 } 301 302 303 304 305 SidebarFactory::SharedImplementation SidebarFactory::GetImplementationForController ( 306 const cssu::Reference<css::frame::XController>& rxController) 307 { 308 SharedImplementation pImplementation; 309 if (rxController.is()) 310 { 311 ControllerToImplementationMap::const_iterator iImplementation ( 312 maControllerToImplementationMap.find(rxController)); 313 if (iImplementation == maControllerToImplementationMap.end()) 314 { 315 pImplementation.reset(new Implementation(rxController)); 316 maControllerToImplementationMap[rxController] = pImplementation; 317 318 // Each Implementation object is referenced by two 319 // SidebarFactory objects. The Implementation object is 320 // destroyed when the first of the SidebarFactory objects 321 // is disposed. 322 } 323 else 324 pImplementation = iImplementation->second; 325 } 326 return pImplementation; 327 } 328 329 330 331 332 //----- SidebarFactory::Implementation ---------------------------------------- 333 334 SidebarFactory::Implementation::Implementation (const Reference<frame::XController>& rxController) 335 : mxConfigurationController(), 336 mxPane(), 337 mxUIElement(), 338 mxController(rxController), 339 mxParentWindow(), 340 mbIsDisposed(false) 341 { 342 Reference<XControllerManager> xCM (rxController, UNO_QUERY); 343 if (xCM.is()) 344 { 345 mxConfigurationController = xCM->getConfigurationController(); 346 } 347 } 348 349 350 351 352 SidebarFactory::Implementation::~Implementation (void) 353 { 354 Dispose(); 355 } 356 357 358 359 360 void SidebarFactory::Implementation::Dispose (void) 361 { 362 if (mbIsDisposed) 363 return; 364 365 mbIsDisposed = true; 366 367 // Release the entry in the maControllerToImplementationMap even though there 368 // may be another object that "references" to it. 369 ControllerToImplementationMap::iterator iImplementation ( 370 maControllerToImplementationMap.find(mxController)); 371 if (iImplementation != maControllerToImplementationMap.end()) 372 maControllerToImplementationMap.erase(iImplementation); 373 374 mxController.clear(); 375 } 376 377 378 } } // end of namespace sd::sidebar 379