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 "CurrentMasterPagesSelector.hxx" 25 #include "PreviewValueSet.hxx" 26 #include "ViewShellBase.hxx" 27 #include "../SidebarShellManager.hxx" 28 #include "DrawViewShell.hxx" 29 #include "drawdoc.hxx" 30 #include "sdpage.hxx" 31 #include "MasterPageContainer.hxx" 32 #include "MasterPageDescriptor.hxx" 33 #include "EventMultiplexer.hxx" 34 #include "app.hrc" 35 #include "DrawDocShell.hxx" 36 #include "DrawViewShell.hxx" 37 #include "res_bmp.hrc" 38 #include "sdresid.hxx" 39 #include "helpids.h" 40 41 #include <vcl/image.hxx> 42 #include <svx/svdmodel.hxx> 43 #include <sfx2/request.hxx> 44 45 #include <set> 46 47 48 using namespace ::com::sun::star; 49 50 namespace sd { namespace sidebar { 51 52 MasterPagesSelector* CurrentMasterPagesSelector::Create ( 53 ::Window* pParent, 54 ViewShellBase& rViewShellBase, 55 SidebarShellManager& rSubShellManager) 56 { 57 SdDrawDocument* pDocument = rViewShellBase.GetDocument(); 58 if (pDocument == NULL) 59 return NULL; 60 61 ::boost::shared_ptr<MasterPageContainer> pContainer (new MasterPageContainer()); 62 63 MasterPagesSelector* pSelector( 64 new CurrentMasterPagesSelector ( 65 pParent, 66 *pDocument, 67 rViewShellBase, 68 rSubShellManager, 69 pContainer)); 70 pSelector->LateInit(); 71 pSelector->SetHelpId( HID_SD_TASK_PANE_PREVIEW_CURRENT ); 72 rSubShellManager.AddSubShell( 73 SHELLID_SD_TASK_PANE_PREVIEW_CURRENT, 74 pSelector, 75 pSelector->GetWindow()); 76 77 return pSelector; 78 } 79 80 81 82 83 CurrentMasterPagesSelector::CurrentMasterPagesSelector ( 84 ::Window* pParent, 85 SdDrawDocument& rDocument, 86 ViewShellBase& rBase, 87 SidebarShellManager& rShellManager, 88 const ::boost::shared_ptr<MasterPageContainer>& rpContainer) 89 : MasterPagesSelector (pParent, rDocument, rBase, rShellManager, rpContainer) 90 { 91 SetName(String(RTL_CONSTASCII_USTRINGPARAM("CurrentMasterPagesSelector"))); 92 93 // For this master page selector only we change the default action for 94 // left clicks. 95 mnDefaultClickAction = SID_TP_APPLY_TO_SELECTED_SLIDES; 96 97 Link aLink (LINK(this,CurrentMasterPagesSelector,EventMultiplexerListener)); 98 rBase.GetEventMultiplexer()->AddEventListener(aLink, 99 sd::tools::EventMultiplexerEvent::EID_CURRENT_PAGE 100 | sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_NORMAL 101 | sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_MASTER 102 | sd::tools::EventMultiplexerEvent::EID_PAGE_ORDER 103 | sd::tools::EventMultiplexerEvent::EID_SHAPE_CHANGED 104 | sd::tools::EventMultiplexerEvent::EID_SHAPE_INSERTED 105 | sd::tools::EventMultiplexerEvent::EID_SHAPE_REMOVED); 106 } 107 108 109 110 111 CurrentMasterPagesSelector::~CurrentMasterPagesSelector (void) 112 { 113 if (mrDocument.GetDocSh() != NULL) 114 { 115 EndListening(*mrDocument.GetDocSh()); 116 } 117 else 118 { 119 OSL_ASSERT(mrDocument.GetDocSh() != NULL); 120 } 121 122 Link aLink (LINK(this,CurrentMasterPagesSelector,EventMultiplexerListener)); 123 mrBase.GetEventMultiplexer()->RemoveEventListener(aLink); 124 } 125 126 127 128 129 void CurrentMasterPagesSelector::LateInit (void) 130 { 131 MasterPagesSelector::LateInit(); 132 MasterPagesSelector::Fill(); 133 if (mrDocument.GetDocSh() != NULL) 134 { 135 StartListening(*mrDocument.GetDocSh()); 136 } 137 else 138 { 139 OSL_ASSERT(mrDocument.GetDocSh() != NULL); 140 } 141 } 142 143 144 145 146 void CurrentMasterPagesSelector::Fill (ItemList& rItemList) 147 { 148 sal_uInt16 nPageCount = mrDocument.GetMasterSdPageCount(PK_STANDARD); 149 SdPage* pMasterPage; 150 // Remember the names of the master pages that have been inserted to 151 // avoid double insertion. 152 ::std::set<String> aMasterPageNames; 153 for (sal_uInt16 nIndex=0; nIndex<nPageCount; nIndex++) 154 { 155 pMasterPage = mrDocument.GetMasterSdPage (nIndex, PK_STANDARD); 156 if (pMasterPage == NULL) 157 continue; 158 159 // Use the name of the master page to avoid duplicate entries. 160 String sName (pMasterPage->GetName()); 161 if (aMasterPageNames.find(sName)!=aMasterPageNames.end()) 162 continue; 163 aMasterPageNames.insert (sName); 164 165 // Look up the master page in the container and, when it is not yet 166 // in it, insert it. 167 MasterPageContainer::Token aToken = mpContainer->GetTokenForPageObject(pMasterPage); 168 if (aToken == MasterPageContainer::NIL_TOKEN) 169 { 170 SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor( 171 MasterPageContainer::MASTERPAGE, 172 nIndex, 173 String(), 174 pMasterPage->GetName(), 175 String(), 176 pMasterPage->IsPrecious(), 177 ::boost::shared_ptr<PageObjectProvider>(new ExistingPageProvider(pMasterPage)), 178 ::boost::shared_ptr<PreviewProvider>(new PagePreviewProvider()))); 179 aToken = mpContainer->PutMasterPage(pDescriptor); 180 } 181 182 rItemList.push_back(aToken); 183 } 184 } 185 186 187 188 189 ResId CurrentMasterPagesSelector::GetContextMenuResId (void) const 190 { 191 return SdResId(RID_TASKPANE_CURRENT_MASTERPAGESSELECTOR_POPUP); 192 } 193 194 195 196 197 void CurrentMasterPagesSelector::UpdateSelection (void) 198 { 199 // Iterate over all pages and for the selected ones put the name of 200 // their master page into a set. 201 sal_uInt16 nPageCount = mrDocument.GetSdPageCount(PK_STANDARD); 202 SdPage* pPage; 203 ::std::set<String> aNames; 204 sal_uInt16 nIndex; 205 bool bLoop (true); 206 for (nIndex=0; nIndex<nPageCount && bLoop; nIndex++) 207 { 208 pPage = mrDocument.GetSdPage (nIndex, PK_STANDARD); 209 if (pPage != NULL && pPage->IsSelected()) 210 { 211 if ( ! pPage->TRG_HasMasterPage()) 212 { 213 // One of the pages has no master page. This is an 214 // indicator for that this method is called in the middle of 215 // a document change and that the model is not in a valid 216 // state. Therefore we stop update the selection and wait 217 // for another call to UpdateSelection when the model is 218 // valid again. 219 bLoop = false; 220 } 221 else 222 { 223 SdrPage& rMasterPage (pPage->TRG_GetMasterPage()); 224 SdPage* pMasterPage = static_cast<SdPage*>(&rMasterPage); 225 if (pMasterPage != NULL) 226 aNames.insert (pMasterPage->GetName()); 227 } 228 } 229 } 230 231 // Find the items for the master pages in the set. 232 sal_uInt16 nItemCount (PreviewValueSet::GetItemCount()); 233 for (nIndex=1; nIndex<=nItemCount && bLoop; nIndex++) 234 { 235 String sName (PreviewValueSet::GetItemText (nIndex)); 236 if (aNames.find(sName) != aNames.end()) 237 { 238 PreviewValueSet::SelectItem (nIndex); 239 } 240 } 241 } 242 243 244 245 246 void CurrentMasterPagesSelector::Execute (SfxRequest& rRequest) 247 { 248 switch (rRequest.GetSlot()) 249 { 250 case SID_DELETE_MASTER_PAGE: 251 { 252 // Check once again that the master page can safely be deleted, 253 // i.e. is not used. 254 SdPage* pMasterPage = GetSelectedMasterPage(); 255 if (pMasterPage != NULL 256 && mrDocument.GetMasterPageUserCount(pMasterPage) == 0) 257 { 258 // Removing the precious flag so that the following call to 259 // RemoveUnnessesaryMasterPages() will remove this master page. 260 pMasterPage->SetPrecious(false); 261 mrDocument.RemoveUnnecessaryMasterPages(pMasterPage, sal_False, sal_True); 262 } 263 } 264 break; 265 266 default: 267 MasterPagesSelector::Execute(rRequest); 268 break; 269 } 270 } 271 272 273 274 275 void CurrentMasterPagesSelector::GetState (SfxItemSet& rItemSet) 276 { 277 // Disable the SID_DELTE_MASTER slot when there is only one master page. 278 if (rItemSet.GetItemState(SID_DELETE_MASTER_PAGE) == SFX_ITEM_AVAILABLE 279 && mrDocument.GetMasterPageUserCount(GetSelectedMasterPage()) > 0) 280 { 281 rItemSet.DisableItem(SID_DELETE_MASTER_PAGE); 282 } 283 284 ::boost::shared_ptr<DrawViewShell> pDrawViewShell ( 285 ::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell())); 286 if (rItemSet.GetItemState(SID_TP_EDIT_MASTER) == SFX_ITEM_AVAILABLE 287 && pDrawViewShell 288 && pDrawViewShell->GetEditMode() == EM_MASTERPAGE) 289 { 290 rItemSet.DisableItem (SID_TP_EDIT_MASTER); 291 } 292 293 MasterPagesSelector::GetState(rItemSet); 294 } 295 296 297 298 299 300 301 IMPL_LINK(CurrentMasterPagesSelector,EventMultiplexerListener, 302 sd::tools::EventMultiplexerEvent*,pEvent) 303 { 304 if (pEvent != NULL) 305 { 306 switch (pEvent->meEventId) 307 { 308 case sd::tools::EventMultiplexerEvent::EID_CURRENT_PAGE: 309 case sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_NORMAL: 310 case sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_MASTER: 311 case sd::tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION: 312 UpdateSelection(); 313 break; 314 315 case sd::tools::EventMultiplexerEvent::EID_PAGE_ORDER: 316 // This is tricky. If a master page is removed, moved, or 317 // added we have to wait until both the notes master page 318 // and the standard master page have been removed, moved, 319 // or added. We do this by looking at the number of master 320 // pages which has to be odd in the consistent state (the 321 // handout master page is always present). If the number is 322 // even we ignore the hint. 323 if (mrBase.GetDocument()->GetMasterPageCount()%2 == 1) 324 MasterPagesSelector::Fill(); 325 break; 326 327 case sd::tools::EventMultiplexerEvent::EID_SHAPE_CHANGED: 328 case sd::tools::EventMultiplexerEvent::EID_SHAPE_INSERTED: 329 case sd::tools::EventMultiplexerEvent::EID_SHAPE_REMOVED: 330 InvalidatePreview((const SdPage*)pEvent->mpUserData); 331 break; 332 } 333 } 334 335 return 0; 336 } 337 338 339 340 341 void CurrentMasterPagesSelector::Notify (SfxBroadcaster&, const SfxHint& rHint) 342 { 343 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint); 344 if (pSimpleHint != NULL) 345 { 346 if (pSimpleHint->GetId() == SFX_HINT_DOCCHANGED) 347 { 348 // Is the edit view visible in the center pane? 349 ::boost::shared_ptr<DrawViewShell> pDrawViewShell ( 350 ::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell())); 351 if (pDrawViewShell.get() != NULL) 352 { 353 // Is the edit view in master page mode? 354 if (pDrawViewShell->GetEditMode() == EM_MASTERPAGE) 355 { 356 // Mark the currently edited master page as precious. 357 SdPage* pCurrentMasterPage = pDrawViewShell->getCurrentPage(); 358 if (pCurrentMasterPage != NULL) 359 pCurrentMasterPage->SetPrecious(true); 360 } 361 } 362 } 363 } 364 } 365 366 367 } } // end of namespace sd::sidebar 368