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