bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / annotations / annotationmanager.cxx
blob99451ab8a62526d79da4600a674a7e61b827f847
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sddll.hxx"
22 #include <com/sun/star/beans/XMultiPropertyStates.hpp>
23 #include <com/sun/star/frame/XController.hpp>
24 #include <com/sun/star/frame/XModel.hpp>
25 #include <com/sun/star/view/XSelectionSupplier.hpp>
26 #include <com/sun/star/geometry/RealPoint2D.hpp>
27 #include <com/sun/star/text/XText.hpp>
28 #include <com/sun/star/document/XEventBroadcaster.hpp>
29 #include <comphelper/string.hxx>
30 #include <svx/svxids.hrc>
32 #include <vcl/settings.hxx>
33 #include <vcl/menu.hxx>
34 #include <vcl/msgbox.hxx>
36 #include <sal/macros.h>
37 #include <svl/style.hxx>
38 #include <svl/itempool.hxx>
39 #include <unotools/useroptions.hxx>
40 #include <unotools/syslocale.hxx>
41 #include <unotools/saveopt.hxx>
43 #include <tools/datetime.hxx>
45 #include <sfx2/imagemgr.hxx>
46 #include <sfx2/viewfrm.hxx>
47 #include <sfx2/bindings.hxx>
48 #include <sfx2/app.hxx>
49 #include <sfx2/request.hxx>
50 #include <sfx2/dispatch.hxx>
51 #include <sfx2/objface.hxx>
53 #include <editeng/editeng.hxx>
54 #include <editeng/eeitem.hxx>
55 #include <editeng/fontitem.hxx>
56 #include <editeng/fhgtitem.hxx>
57 #include <editeng/outlobj.hxx>
58 #include <editeng/postitem.hxx>
59 #include <editeng/wghtitem.hxx>
60 #include <editeng/udlnitem.hxx>
61 #include <editeng/crossedoutitem.hxx>
63 #include <svx/svdetc.hxx>
65 #include "annotationmanager.hxx"
66 #include "annotationmanagerimpl.hxx"
67 #include "annotationwindow.hxx"
68 #include "annotations.hrc"
70 #include "ToolBarManager.hxx"
71 #include "DrawDocShell.hxx"
72 #include "DrawViewShell.hxx"
73 #include "DrawController.hxx"
74 #include "glob.hrc"
75 #include "sdresid.hxx"
76 #include "EventMultiplexer.hxx"
77 #include "ViewShellManager.hxx"
78 #include "helpids.h"
79 #include "sdpage.hxx"
80 #include "drawdoc.hxx"
81 #include "textapi.hxx"
82 #include "optsitem.hxx"
84 #include <boost/scoped_ptr.hpp>
86 using namespace ::com::sun::star;
87 using namespace ::com::sun::star::uno;
88 using namespace ::com::sun::star::drawing;
89 using namespace ::com::sun::star::document;
90 using namespace ::com::sun::star::geometry;
91 using namespace ::com::sun::star::container;
92 using namespace ::com::sun::star::beans;
93 using namespace ::com::sun::star::text;
94 using namespace ::com::sun::star::view;
95 using namespace ::com::sun::star::style;
96 using namespace ::com::sun::star::frame;
97 using namespace ::com::sun::star::lang;
98 using namespace ::com::sun::star::ui;
99 using namespace ::com::sun::star::task;
100 using namespace ::com::sun::star::office;
102 namespace sd {
104 SfxItemPool* GetAnnotationPool()
106 static SfxItemPool* mpAnnotationPool = 0;
107 if( mpAnnotationPool == 0 )
109 mpAnnotationPool = EditEngine::CreatePool( false );
110 mpAnnotationPool->SetPoolDefaultItem(SvxFontHeightItem(423,100,EE_CHAR_FONTHEIGHT));
112 vcl::Font aAppFont( Application::GetSettings().GetStyleSettings().GetAppFont() );
113 mpAnnotationPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamily(),aAppFont.GetName(),"",PITCH_DONTKNOW,RTL_TEXTENCODING_DONTKNOW,EE_CHAR_FONTINFO));
116 return mpAnnotationPool;
119 static SfxBindings* getBindings( ViewShellBase& rBase )
121 if( rBase.GetMainViewShell().get() && rBase.GetMainViewShell()->GetViewFrame() )
122 return &rBase.GetMainViewShell()->GetViewFrame()->GetBindings();
124 return 0;
127 static SfxDispatcher* getDispatcher( ViewShellBase& rBase )
129 if( rBase.GetMainViewShell().get() && rBase.GetMainViewShell()->GetViewFrame() )
130 return rBase.GetMainViewShell()->GetViewFrame()->GetDispatcher();
132 return 0;
135 com::sun::star::util::DateTime getCurrentDateTime()
137 DateTime aCurrentDate( DateTime::SYSTEM );
138 return com::sun::star::util::DateTime( 0, aCurrentDate.GetSec(),
139 aCurrentDate.GetMin(), aCurrentDate.GetHour(),
140 aCurrentDate.GetDay(), aCurrentDate.GetMonth(),
141 aCurrentDate.GetYear(), false );
144 OUString getAnnotationDateTimeString( const Reference< XAnnotation >& xAnnotation )
146 OUString sRet;
147 if( xAnnotation.is() )
149 const SvtSysLocale aSysLocale;
150 const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
152 com::sun::star::util::DateTime aDateTime( xAnnotation->getDateTime() );
154 Date aSysDate( Date::SYSTEM );
155 Date aDate = Date( aDateTime.Day, aDateTime.Month, aDateTime.Year );
156 if (aDate==aSysDate)
157 sRet = SdResId(STR_ANNOTATION_TODAY);
158 else if (aDate == Date(aSysDate-1))
159 sRet = SdResId(STR_ANNOTATION_YESTERDAY);
160 else if (aDate.IsValidAndGregorian() )
161 sRet = rLocalData.getDate(aDate);
163 ::tools::Time aTime( aDateTime );
164 if(aTime.GetTime() != 0)
165 sRet = sRet + " " + rLocalData.getTime( aTime,false );
167 return sRet;
170 AnnotationManagerImpl::AnnotationManagerImpl( ViewShellBase& rViewShellBase )
171 : AnnotationManagerImplBase( m_aMutex )
172 , mrBase( rViewShellBase )
173 , mpDoc( rViewShellBase.GetDocument() )
174 , mbShowAnnotations( true )
175 , mnUpdateTagsEvent( 0 )
177 SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType());
178 if( pOptions )
179 mbShowAnnotations = pOptions->IsShowComments();
182 void AnnotationManagerImpl::init()
184 // get current controller and initialize listeners
187 addListener();
188 mxView = Reference< XDrawView >::query(mrBase.GetController());
190 catch( Exception& )
192 OSL_FAIL( "sd::AnnotationManagerImpl::AnnotationManagerImpl(), Exception caught!" );
197 Reference<XEventBroadcaster> xModel (mrBase.GetDocShell()->GetModel(), UNO_QUERY_THROW );
198 Reference<XEventListener> xListener( this );
199 xModel->addEventListener( xListener );
201 catch( Exception& )
206 // WeakComponentImplHelper1
207 void SAL_CALL AnnotationManagerImpl::disposing ()
211 Reference<XEventBroadcaster> xModel (mrBase.GetDocShell()->GetModel(), UNO_QUERY_THROW );
212 Reference<XEventListener> xListener( this );
213 xModel->removeEventListener( xListener );
215 catch( Exception& )
219 removeListener();
220 DisposeTags();
222 if( mnUpdateTagsEvent )
224 Application::RemoveUserEvent( mnUpdateTagsEvent );
225 mnUpdateTagsEvent = 0;
228 mxView.clear();
229 mxCurrentPage.clear();
232 // XEventListener
233 void SAL_CALL AnnotationManagerImpl::notifyEvent( const ::com::sun::star::document::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException, std::exception)
235 if( aEvent.EventName == "OnAnnotationInserted" || aEvent.EventName == "OnAnnotationRemoved" || aEvent.EventName == "OnAnnotationChanged" )
237 UpdateTags();
241 void SAL_CALL AnnotationManagerImpl::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException, std::exception)
245 void AnnotationManagerImpl::ShowAnnotations( bool bShow )
247 // enforce show annotations if a new annotation is inserted
248 if( mbShowAnnotations != bShow )
250 mbShowAnnotations = bShow;
252 SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType());
253 if( pOptions )
254 pOptions->SetShowComments( mbShowAnnotations );
256 UpdateTags();
260 void AnnotationManagerImpl::ExecuteAnnotation(SfxRequest& rReq )
262 switch( rReq.GetSlot() )
264 case SID_INSERT_POSTIT:
265 ExecuteInsertAnnotation( rReq );
266 break;
267 case SID_DELETE_POSTIT:
268 case SID_DELETEALL_POSTIT:
269 case SID_DELETEALLBYAUTHOR_POSTIT:
270 ExecuteDeleteAnnotation( rReq );
271 break;
272 case SID_PREVIOUS_POSTIT:
273 case SID_NEXT_POSTIT:
274 SelectNextAnnotation( rReq.GetSlot() == SID_NEXT_POSTIT );
275 break;
276 case SID_REPLYTO_POSTIT:
277 ExecuteReplyToAnnotation( rReq );
278 break;
279 case SID_SHOW_POSTIT:
280 ShowAnnotations( !mbShowAnnotations );
281 break;
285 void AnnotationManagerImpl::ExecuteInsertAnnotation(SfxRequest& /*rReq*/)
287 ShowAnnotations(true);
288 InsertAnnotation();
291 void AnnotationManagerImpl::ExecuteDeleteAnnotation(SfxRequest& rReq)
293 ShowAnnotations( true );
295 const SfxItemSet* pArgs = rReq.GetArgs();
297 switch( rReq.GetSlot() )
299 case SID_DELETEALL_POSTIT:
300 DeleteAllAnnotations();
301 break;
302 case SID_DELETEALLBYAUTHOR_POSTIT:
303 if( pArgs )
305 const SfxPoolItem* pPoolItem = NULL;
306 if( SfxItemState::SET == pArgs->GetItemState( SID_DELETEALLBYAUTHOR_POSTIT, true, &pPoolItem ) )
308 OUString sAuthor( static_cast<const SfxStringItem*>( pPoolItem )->GetValue() );
309 DeleteAnnotationsByAuthor( sAuthor );
312 break;
313 case SID_DELETE_POSTIT:
315 Reference< XAnnotation > xAnnotation;
317 if( rReq.GetSlot() == SID_DELETE_POSTIT )
319 if( pArgs )
321 const SfxPoolItem* pPoolItem = NULL;
322 if( SfxItemState::SET == pArgs->GetItemState( SID_DELETE_POSTIT, true, &pPoolItem ) )
323 static_cast<const SfxUnoAnyItem*>(pPoolItem)->GetValue() >>= xAnnotation;
327 if( !xAnnotation.is() )
328 GetSelectedAnnotation( xAnnotation );
330 DeleteAnnotation( xAnnotation );
332 break;
335 UpdateTags();
338 void AnnotationManagerImpl::InsertAnnotation()
340 SdPage* pPage = GetCurrentPage();
341 if( pPage )
343 if( mpDoc->IsUndoEnabled() )
344 mpDoc->BegUndo( SD_RESSTR( STR_ANNOTATION_UNDO_INSERT ) );
346 // find free space for new annotation
347 int y = 0, x = 0;
349 AnnotationVector aAnnotations( pPage->getAnnotations() );
350 if( !aAnnotations.empty() )
352 const int page_width = pPage->GetSize().Width();
353 const int width = 1000;
354 const int height = 800;
355 Rectangle aTagRect;
357 while( true )
359 Rectangle aNewRect( x, y, x + width - 1, y + height - 1 );
360 bool bFree = true;
362 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
364 RealPoint2D aPoint( (*iter)->getPosition() );
365 aTagRect.Left() = sal::static_int_cast< long >( aPoint.X * 100.0 );
366 aTagRect.Top() = sal::static_int_cast< long >( aPoint.Y * 100.0 );
367 aTagRect.Right() = aTagRect.Left() + width - 1;
368 aTagRect.Bottom() = aTagRect.Top() + height - 1;
370 if( aNewRect.IsOver( aTagRect ) )
372 bFree = false;
373 break;
377 if( !bFree )
379 x += width;
380 if( x > page_width )
382 x = 0;
383 y += height;
386 else
388 break;
393 Reference< XAnnotation > xAnnotation;
394 pPage->createAnnotation( xAnnotation );
396 // set current author to new annotation
397 SvtUserOptions aUserOptions;
398 xAnnotation->setAuthor( aUserOptions.GetFullName() );
400 // set current time to new annotation
401 xAnnotation->setDateTime( getCurrentDateTime() );
403 // set position
404 RealPoint2D aPos( ((double)x) / 100.0, ((double)y) / 100.0 );
405 xAnnotation->setPosition( aPos );
407 if( mpDoc->IsUndoEnabled() )
408 mpDoc->EndUndo();
410 UpdateTags(true);
411 SelectAnnotation( xAnnotation, true );
415 void AnnotationManagerImpl::ExecuteReplyToAnnotation( SfxRequest& rReq )
417 Reference< XAnnotation > xAnnotation;
418 const SfxItemSet* pArgs = rReq.GetArgs();
419 if( pArgs )
421 const SfxPoolItem* pPoolItem = NULL;
422 if( SfxItemState::SET == pArgs->GetItemState( rReq.GetSlot(), true, &pPoolItem ) )
423 static_cast<const SfxUnoAnyItem*>( pPoolItem )->GetValue() >>= xAnnotation;
426 TextApiObject* pTextApi = getTextApiObject( xAnnotation );
427 if( pTextApi )
429 boost::scoped_ptr< ::Outliner > pOutliner( new ::Outliner(GetAnnotationPool(),OUTLINERMODE_TEXTOBJECT) );
431 mpDoc->SetCalcFieldValueHdl( pOutliner.get() );
432 pOutliner->SetUpdateMode( true );
434 OUString aStr(SD_RESSTR(STR_ANNOTATION_REPLY));
435 OUString sAuthor( xAnnotation->getAuthor() );
436 if( sAuthor.isEmpty() )
437 sAuthor = SD_RESSTR( STR_ANNOTATION_NOAUTHOR );
439 aStr = aStr.replaceFirst("%1", sAuthor);
441 aStr += " (" + getAnnotationDateTimeString( xAnnotation ) + "): \"";
443 OUString sQuote( pTextApi->GetText() );
445 if( sQuote.isEmpty() )
446 sQuote = "...";
447 aStr += sQuote + "\"\n";
449 sal_Int32 nParaCount = comphelper::string::getTokenCount(aStr, '\n');
450 for( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ )
451 pOutliner->Insert( aStr.getToken( nPara, '\n' ), EE_PARA_APPEND, -1 );
453 if( pOutliner->GetParagraphCount() > 1 )
455 SfxItemSet aAnswerSet( pOutliner->GetEmptyItemSet() );
456 aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC));
458 ESelection aSel;
459 aSel.nEndPara = pOutliner->GetParagraphCount()-2;
460 aSel.nEndPos = pOutliner->GetText( pOutliner->GetParagraph( aSel.nEndPara ) ).getLength();
462 pOutliner->QuickSetAttribs( aAnswerSet, aSel );
465 boost::scoped_ptr< OutlinerParaObject > pOPO( pOutliner->CreateParaObject() );
466 pTextApi->SetText( *pOPO.get() );
468 SvtUserOptions aUserOptions;
469 xAnnotation->setAuthor( aUserOptions.GetFullName() );
471 // set current time to reply
472 xAnnotation->setDateTime( getCurrentDateTime() );
474 UpdateTags(true);
475 SelectAnnotation( xAnnotation, true );
479 void AnnotationManagerImpl::DeleteAnnotation( Reference< XAnnotation > xAnnotation )
481 SdPage* pPage = GetCurrentPage();
483 if( xAnnotation.is() && pPage )
485 if( mpDoc->IsUndoEnabled() )
486 mpDoc->BegUndo( SD_RESSTR( STR_ANNOTATION_UNDO_DELETE ) );
488 pPage->removeAnnotation( xAnnotation );
490 if( mpDoc->IsUndoEnabled() )
491 mpDoc->EndUndo();
493 UpdateTags();
497 void AnnotationManagerImpl::DeleteAnnotationsByAuthor( const OUString& sAuthor )
499 if( mpDoc->IsUndoEnabled() )
500 mpDoc->BegUndo( SD_RESSTR( STR_ANNOTATION_UNDO_DELETE ) );
502 SdPage* pPage = 0;
505 pPage = GetNextPage( pPage, true );
507 if( pPage && !pPage->getAnnotations().empty() )
509 AnnotationVector aAnnotations( pPage->getAnnotations() );
510 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
512 Reference< XAnnotation > xAnnotation( *iter );
513 if( xAnnotation->getAuthor() == sAuthor )
515 if( mxSelectedAnnotation == xAnnotation )
516 mxSelectedAnnotation.clear();
517 pPage->removeAnnotation( xAnnotation );
521 } while( pPage );
523 if( mpDoc->IsUndoEnabled() )
524 mpDoc->EndUndo();
527 void AnnotationManagerImpl::DeleteAllAnnotations()
529 if( mpDoc->IsUndoEnabled() )
530 mpDoc->BegUndo( SD_RESSTR( STR_ANNOTATION_UNDO_DELETE ) );
532 SdPage* pPage = 0;
535 pPage = GetNextPage( pPage, true );
537 if( pPage && !pPage->getAnnotations().empty() )
540 AnnotationVector aAnnotations( pPage->getAnnotations() );
541 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
543 pPage->removeAnnotation( (*iter) );
547 while( pPage );
549 mxSelectedAnnotation.clear();
551 if( mpDoc->IsUndoEnabled() )
552 mpDoc->EndUndo();
555 void AnnotationManagerImpl::GetAnnotationState(SfxItemSet& rSet)
557 SdPage* pCurrentPage = GetCurrentPage();
559 const bool bReadOnly = mrBase.GetDocShell()->IsReadOnly();
560 const bool bWrongPageKind = (pCurrentPage == 0) || (pCurrentPage->GetPageKind() != PK_STANDARD);
562 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
564 if( bReadOnly || bWrongPageKind || (nCurrentODFVersion <= SvtSaveOptions::ODFVER_012) )
565 rSet.DisableItem( SID_INSERT_POSTIT );
567 rSet.Put(SfxBoolItem(SID_SHOW_POSTIT, mbShowAnnotations));
569 Reference< XAnnotation > xAnnotation;
570 GetSelectedAnnotation( xAnnotation );
572 if( !xAnnotation.is() || bReadOnly )
573 rSet.DisableItem( SID_DELETE_POSTIT );
575 SdPage* pPage = 0;
577 bool bHasAnnotations = false;
580 pPage = GetNextPage( pPage, true );
582 if( pPage && !pPage->getAnnotations().empty() )
583 bHasAnnotations = true;
585 while( pPage && !bHasAnnotations );
587 if( !bHasAnnotations || bReadOnly )
589 rSet.DisableItem( SID_DELETEALL_POSTIT );
592 if( bWrongPageKind || !bHasAnnotations )
594 rSet.DisableItem( SID_PREVIOUS_POSTIT );
595 rSet.DisableItem( SID_NEXT_POSTIT );
599 void AnnotationManagerImpl::SelectNextAnnotation(bool bForeward)
601 ShowAnnotations( true );
603 Reference< XAnnotation > xCurrent;
604 GetSelectedAnnotation( xCurrent );
605 SdPage* pPage = GetCurrentPage();
606 if( !pPage )
607 return;
609 AnnotationVector aAnnotations( pPage->getAnnotations() );
611 if( bForeward )
613 if( xCurrent.is() )
615 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
617 if( (*iter) == xCurrent )
619 ++iter;
620 if( iter != aAnnotations.end() )
622 SelectAnnotation( (*iter) );
623 return;
625 break;
629 else if( !aAnnotations.empty() )
631 SelectAnnotation( *(aAnnotations.begin()) );
632 return;
635 else
637 if( xCurrent.is() )
639 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
641 if( (*iter) == xCurrent )
643 if( iter != aAnnotations.begin() )
645 --iter;
646 SelectAnnotation( (*iter) );
647 return;
649 break;
653 else if( !aAnnotations.empty() )
655 AnnotationVector::iterator iter( aAnnotations.end() );
656 SelectAnnotation( *(--iter) );
657 return;
661 mxSelectedAnnotation.clear();
666 pPage = GetNextPage( pPage, bForeward );
668 if( pPage && !pPage->getAnnotations().empty() )
670 // switch to next/previous slide with annotations
671 ::boost::shared_ptr<DrawViewShell> pDrawViewShell(::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell()));
672 if (pDrawViewShell.get() != NULL)
674 pDrawViewShell->ChangeEditMode(pPage->IsMasterPage() ? EM_MASTERPAGE : EM_PAGE, false);
675 pDrawViewShell->SwitchPage((pPage->GetPageNum() - 1) >> 1);
677 SfxDispatcher* pDispatcher = getDispatcher( mrBase );
678 if( pDispatcher )
679 pDispatcher->Execute( bForeward ? SID_NEXT_POSTIT : SID_PREVIOUS_POSTIT );
681 return;
685 while( pPage );
687 // The question text depends on the search direction.
688 bool bImpress = mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS;
689 sal_uInt16 nStringId;
690 if(bForeward)
691 nStringId = bImpress ? STR_ANNOTATION_WRAP_FORWARD : STR_ANNOTATION_WRAP_FORWARD_DRAW;
692 else
693 nStringId = bImpress ? STR_ANNOTATION_WRAP_BACKWARD : STR_ANNOTATION_WRAP_BACKWARD_DRAW;
695 // Pop up question box that asks the user whether to wrap around.
696 // The dialog is made modal with respect to the whole application.
697 ScopedVclPtrInstance< QueryBox > aQuestionBox( nullptr, (WB_YES_NO | WB_DEF_YES), SD_RESSTR(nStringId));
698 aQuestionBox->SetImage( QueryBox::GetStandardImage() );
699 if (aQuestionBox->Execute() != RET_YES)
700 break;
702 while( true );
705 void AnnotationManagerImpl::onTagSelected( AnnotationTag& rTag )
707 mxSelectedAnnotation = rTag.GetAnnotation();
708 invalidateSlots();
711 void AnnotationManagerImpl::onTagDeselected( AnnotationTag& rTag )
713 if( rTag.GetAnnotation() == mxSelectedAnnotation )
715 mxSelectedAnnotation.clear();
716 invalidateSlots();
720 void AnnotationManagerImpl::SelectAnnotation( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation > xAnnotation, bool bEdit /* = sal_False */ )
722 mxSelectedAnnotation = xAnnotation;
724 const AnnotationTagVector::const_iterator aEnd( maTagVector.end() );
725 for( AnnotationTagVector::const_iterator iter( maTagVector.begin() );
726 iter != aEnd; ++iter)
728 if( (*iter)->GetAnnotation() == xAnnotation )
730 SmartTagReference xTag( (*iter).get() );
731 mrBase.GetMainViewShell()->GetView()->getSmartTags().select( xTag );
732 (*iter)->OpenPopup( bEdit );
733 break;
738 void AnnotationManagerImpl::GetSelectedAnnotation( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation >& xAnnotation )
740 xAnnotation = mxSelectedAnnotation;
743 void AnnotationManagerImpl::invalidateSlots()
745 SfxBindings* pBindings = getBindings( mrBase );
746 if( pBindings )
748 pBindings->Invalidate( SID_INSERT_POSTIT );
749 pBindings->Invalidate( SID_DELETE_POSTIT );
750 pBindings->Invalidate( SID_DELETEALL_POSTIT );
751 pBindings->Invalidate( SID_PREVIOUS_POSTIT );
752 pBindings->Invalidate( SID_NEXT_POSTIT );
753 pBindings->Invalidate( SID_UNDO );
754 pBindings->Invalidate( SID_REDO );
758 void AnnotationManagerImpl::onSelectionChanged()
760 if( mxView.is() && mrBase.GetDrawView() ) try
762 Reference< XAnnotationAccess > xPage( mxView->getCurrentPage(), UNO_QUERY );
764 if( xPage != mxCurrentPage )
766 mxCurrentPage = xPage;
768 UpdateTags(true);
771 catch( Exception& )
773 OSL_FAIL( "sd::AnnotationManagerImpl::onSelectionChanged(), exception caught!" );
777 void AnnotationManagerImpl::UpdateTags( bool bSynchron )
779 if( bSynchron )
781 if( mnUpdateTagsEvent )
782 Application::RemoveUserEvent( mnUpdateTagsEvent );
784 UpdateTagsHdl(0);
786 else
788 if( !mnUpdateTagsEvent && mxView.is() )
789 mnUpdateTagsEvent = Application::PostUserEvent( LINK( this, AnnotationManagerImpl, UpdateTagsHdl ) );
793 IMPL_LINK_NOARG(AnnotationManagerImpl, UpdateTagsHdl)
795 mnUpdateTagsEvent = 0;
796 DisposeTags();
798 if( mbShowAnnotations )
799 CreateTags();
801 if( mrBase.GetDrawView() )
802 static_cast< ::sd::View* >( mrBase.GetDrawView() )->updateHandles();
804 invalidateSlots();
806 return 0;
809 void AnnotationManagerImpl::CreateTags()
812 if( mxCurrentPage.is() && mpDoc ) try
814 int nIndex = 1;
815 maFont = Application::GetSettings().GetStyleSettings().GetAppFont();
817 rtl::Reference< AnnotationTag > xSelectedTag;
819 Reference< XAnnotationEnumeration > xEnum( mxCurrentPage->createAnnotationEnumeration() );
820 while( xEnum->hasMoreElements() )
822 Reference< XAnnotation > xAnnotation( xEnum->nextElement() );
823 Color aColor( GetColorLight( mpDoc->GetAnnotationAuthorIndex( xAnnotation->getAuthor() ) ) );
824 rtl::Reference< AnnotationTag > xTag( new AnnotationTag( *this, *mrBase.GetMainViewShell()->GetView(), xAnnotation, aColor, nIndex++, maFont ) );
825 maTagVector.push_back(xTag);
827 if( xAnnotation == mxSelectedAnnotation )
829 xSelectedTag = xTag;
833 if( xSelectedTag.is() )
835 SmartTagReference xTag( xSelectedTag.get() );
836 mrBase.GetMainViewShell()->GetView()->getSmartTags().select( xTag );
838 else
840 // no tag, no selection!
841 mxSelectedAnnotation.clear();
844 catch( Exception& )
846 OSL_FAIL( "sd::AnnotationManagerImpl::onSelectionChanged(), exception caught!" );
850 void AnnotationManagerImpl::DisposeTags()
852 if( !maTagVector.empty() )
854 AnnotationTagVector::iterator iter = maTagVector.begin();
857 (*iter++)->Dispose();
859 while( iter != maTagVector.end() );
861 maTagVector.clear();
865 void AnnotationManagerImpl::addListener()
867 Link<> aLink( LINK(this,AnnotationManagerImpl,EventMultiplexerListener) );
868 mrBase.GetEventMultiplexer()->AddEventListener (
869 aLink,
870 tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
871 | tools::EventMultiplexerEvent::EID_CURRENT_PAGE
872 | tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
873 | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED);
876 void AnnotationManagerImpl::removeListener()
878 Link<> aLink( LINK(this,AnnotationManagerImpl,EventMultiplexerListener) );
879 mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
882 IMPL_LINK(AnnotationManagerImpl,EventMultiplexerListener,
883 tools::EventMultiplexerEvent*,pEvent)
885 switch (pEvent->meEventId)
887 case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
888 case tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION:
889 onSelectionChanged();
890 break;
892 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
893 mxView.clear();
894 onSelectionChanged();
895 break;
897 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
898 mxView = Reference<XDrawView>::query( mrBase.GetController() );
899 onSelectionChanged();
900 break;
902 return 0;
905 void AnnotationManagerImpl::ExecuteAnnotationContextMenu( Reference< XAnnotation > xAnnotation, vcl::Window* pParent, const Rectangle& rContextRect, bool bButtonMenu /* = false */ )
907 SfxDispatcher* pDispatcher( getDispatcher( mrBase ) );
908 if( !pDispatcher )
909 return;
911 const bool bReadOnly = mrBase.GetDocShell()->IsReadOnly();
913 AnnotationWindow* pAnnotationWindow = bButtonMenu ? 0 : dynamic_cast< AnnotationWindow* >( pParent );
915 if( bReadOnly && !pAnnotationWindow )
916 return;
918 boost::scoped_ptr< PopupMenu > pMenu( new PopupMenu( SdResId( pAnnotationWindow ? RID_ANNOTATION_CONTEXTMENU : RID_ANNOTATION_TAG_CONTEXTMENU ) ) );
920 SvtUserOptions aUserOptions;
921 OUString sCurrentAuthor( aUserOptions.GetFullName() );
922 OUString sAuthor( xAnnotation->getAuthor() );
924 OUString aStr( pMenu->GetItemText( SID_DELETEALLBYAUTHOR_POSTIT ) );
925 OUString aReplace( sAuthor );
926 if( aReplace.isEmpty() )
927 aReplace = SD_RESSTR( STR_ANNOTATION_NOAUTHOR );
928 aStr = aStr.replaceFirst("%1", aReplace);
929 pMenu->SetItemText( SID_DELETEALLBYAUTHOR_POSTIT, aStr );
930 pMenu->EnableItem( SID_REPLYTO_POSTIT, (sAuthor != sCurrentAuthor) && !bReadOnly );
931 pMenu->EnableItem( SID_DELETE_POSTIT, xAnnotation.is() && !bReadOnly );
932 pMenu->EnableItem( SID_DELETEALLBYAUTHOR_POSTIT, !bReadOnly );
933 pMenu->EnableItem( SID_DELETEALL_POSTIT, !bReadOnly );
935 if( pAnnotationWindow )
937 if( pAnnotationWindow->IsProtected() || bReadOnly )
939 pMenu->EnableItem( SID_ATTR_CHAR_WEIGHT, false );
940 pMenu->EnableItem( SID_ATTR_CHAR_POSTURE, false );
941 pMenu->EnableItem( SID_ATTR_CHAR_UNDERLINE, false );
942 pMenu->EnableItem( SID_ATTR_CHAR_STRIKEOUT, false );
943 pMenu->EnableItem( SID_PASTE, false );
945 else
947 SfxItemSet aSet(pAnnotationWindow->getView()->GetAttribs());
949 if ( aSet.GetItemState( EE_CHAR_WEIGHT ) == SfxItemState::SET )
951 if( static_cast<const SvxWeightItem&>(aSet.Get( EE_CHAR_WEIGHT )).GetWeight() == WEIGHT_BOLD )
952 pMenu->CheckItem( SID_ATTR_CHAR_WEIGHT );
955 if ( aSet.GetItemState( EE_CHAR_ITALIC ) == SfxItemState::SET )
957 if( static_cast<const SvxPostureItem&>(aSet.Get( EE_CHAR_ITALIC )).GetPosture() != ITALIC_NONE )
958 pMenu->CheckItem( SID_ATTR_CHAR_POSTURE );
961 if ( aSet.GetItemState( EE_CHAR_UNDERLINE ) == SfxItemState::SET )
963 if( static_cast<const SvxUnderlineItem&>(aSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() != UNDERLINE_NONE )
964 pMenu->CheckItem( SID_ATTR_CHAR_UNDERLINE );
967 if ( aSet.GetItemState( EE_CHAR_STRIKEOUT ) == SfxItemState::SET )
969 if( static_cast<const SvxCrossedOutItem&>(aSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() != STRIKEOUT_NONE )
970 pMenu->CheckItem( SID_ATTR_CHAR_STRIKEOUT );
972 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pAnnotationWindow ) );
973 pMenu->EnableItem( SID_PASTE, aDataHelper.GetFormatCount() != 0 );
976 pMenu->EnableItem( SID_COPY, pAnnotationWindow->getView()->HasSelection() );
979 sal_uInt16 nId = 0;
981 // set slot images
982 Reference< ::com::sun::star::frame::XFrame > xFrame( mrBase.GetMainViewShell()->GetViewFrame()->GetFrame().GetFrameInterface() );
983 if( xFrame.is() )
985 for( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
987 nId = pMenu->GetItemId( nPos );
988 if( pMenu->IsItemEnabled( nId ) )
990 OUString sSlotURL( "slot:" );
991 sSlotURL += OUString::number( nId);
993 Image aImage( GetImage( xFrame, sSlotURL, false ) );
994 if( !!aImage )
995 pMenu->SetItemImage( nId, aImage );
1000 nId = pMenu->Execute( pParent, rContextRect, PopupMenuFlags::ExecuteDown|PopupMenuFlags::NoMouseUpClose );
1001 switch( nId )
1003 case SID_REPLYTO_POSTIT:
1005 const SfxUnoAnyItem aItem( SID_REPLYTO_POSTIT, Any( xAnnotation ) );
1006 pDispatcher->Execute( SID_REPLYTO_POSTIT, SfxCallMode::ASYNCHRON, &aItem, 0 );
1007 break;
1009 case SID_DELETE_POSTIT:
1011 const SfxUnoAnyItem aItem( SID_DELETE_POSTIT, Any( xAnnotation ) );
1012 pDispatcher->Execute( SID_DELETE_POSTIT, SfxCallMode::ASYNCHRON, &aItem, 0 );
1013 break;
1015 case SID_DELETEALLBYAUTHOR_POSTIT:
1017 const SfxStringItem aItem( SID_DELETEALLBYAUTHOR_POSTIT, sAuthor );
1018 pDispatcher->Execute( SID_DELETEALLBYAUTHOR_POSTIT, SfxCallMode::ASYNCHRON, &aItem, 0 );
1019 break;
1021 case SID_DELETEALL_POSTIT:
1022 pDispatcher->Execute( SID_DELETEALL_POSTIT );
1023 break;
1024 case SID_COPY:
1025 case SID_PASTE:
1026 case SID_ATTR_CHAR_WEIGHT:
1027 case SID_ATTR_CHAR_POSTURE:
1028 case SID_ATTR_CHAR_UNDERLINE:
1029 case SID_ATTR_CHAR_STRIKEOUT:
1030 if( pAnnotationWindow )
1031 pAnnotationWindow->ExecuteSlot( nId );
1032 break;
1036 Color AnnotationManagerImpl::GetColor(sal_uInt16 aAuthorIndex)
1038 if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1040 static const Color aArrayNormal[] = {
1041 COL_AUTHOR1_NORMAL, COL_AUTHOR2_NORMAL, COL_AUTHOR3_NORMAL,
1042 COL_AUTHOR4_NORMAL, COL_AUTHOR5_NORMAL, COL_AUTHOR6_NORMAL,
1043 COL_AUTHOR7_NORMAL, COL_AUTHOR8_NORMAL, COL_AUTHOR9_NORMAL };
1045 return Color( aArrayNormal[ aAuthorIndex % (sizeof( aArrayNormal )/ sizeof( aArrayNormal[0] ))]);
1048 return Color(COL_WHITE);
1051 Color AnnotationManagerImpl::GetColorLight(sal_uInt16 aAuthorIndex)
1053 if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1055 static const Color aArrayLight[] = {
1056 COL_AUTHOR1_LIGHT, COL_AUTHOR2_LIGHT, COL_AUTHOR3_LIGHT,
1057 COL_AUTHOR4_LIGHT, COL_AUTHOR5_LIGHT, COL_AUTHOR6_LIGHT,
1058 COL_AUTHOR7_LIGHT, COL_AUTHOR8_LIGHT, COL_AUTHOR9_LIGHT };
1060 return Color( aArrayLight[ aAuthorIndex % (sizeof( aArrayLight )/ sizeof( aArrayLight[0] ))]);
1063 return Color(COL_WHITE);
1066 Color AnnotationManagerImpl::GetColorDark(sal_uInt16 aAuthorIndex)
1068 if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1070 static const Color aArrayAnkor[] = {
1071 COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK,
1072 COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK,
1073 COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK };
1075 return Color( aArrayAnkor[ aAuthorIndex % (sizeof( aArrayAnkor ) / sizeof( aArrayAnkor[0] ))]);
1078 return Color(COL_WHITE);
1081 SdPage* AnnotationManagerImpl::GetNextPage( SdPage* pPage, bool bForeward )
1083 if( pPage == 0 )
1084 return bForeward ? GetFirstPage() : GetLastPage();
1086 sal_uInt16 nPageNum = (pPage->GetPageNum() - 1) >> 1;
1088 // first all non master pages
1089 if( !pPage->IsMasterPage() )
1091 if( bForeward )
1093 if( nPageNum >= mpDoc->GetSdPageCount(PK_STANDARD)-1 )
1095 // we reached end of draw pages, start with master pages (skip handout master for draw)
1096 return mpDoc->GetMasterSdPage( (mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS) ? 0 : 1, PK_STANDARD );
1098 nPageNum++;
1100 else
1102 if( nPageNum == 0 )
1103 return 0; // we are already on the first draw page, finished
1105 nPageNum--;
1107 return mpDoc->GetSdPage(nPageNum, PK_STANDARD);
1109 else
1111 if( bForeward )
1113 if( nPageNum >= mpDoc->GetMasterSdPageCount(PK_STANDARD)-1 )
1115 return 0; // we reached the end, there is nothing more to see here
1117 nPageNum++;
1119 else
1121 if( nPageNum == (mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS ? 0 : 1) )
1123 // we reached beginning of master pages, start with end if pages
1124 return mpDoc->GetSdPage( mpDoc->GetSdPageCount(PK_STANDARD)-1, PK_STANDARD );
1127 nPageNum--;
1129 return mpDoc->GetMasterSdPage(nPageNum,PK_STANDARD);
1133 SdPage* AnnotationManagerImpl::GetFirstPage()
1135 // return first drawing page
1136 return mpDoc->GetSdPage(0, PK_STANDARD );
1139 SdPage* AnnotationManagerImpl::GetLastPage()
1141 return mpDoc->GetMasterSdPage( mpDoc->GetMasterSdPageCount(PK_STANDARD) - 1, PK_STANDARD );
1144 SdPage* AnnotationManagerImpl::GetCurrentPage()
1146 if (mrBase.GetMainViewShell().get())
1147 return mrBase.GetMainViewShell()->getCurrentPage();
1148 return nullptr;
1151 AnnotationManager::AnnotationManager( ViewShellBase& rViewShellBase )
1152 : mxImpl( new AnnotationManagerImpl( rViewShellBase ) )
1154 mxImpl->init();
1157 AnnotationManager::~AnnotationManager()
1159 mxImpl->dispose();
1162 void AnnotationManager::ExecuteAnnotation(SfxRequest& rRequest)
1164 mxImpl->ExecuteAnnotation( rRequest );
1167 void AnnotationManager::GetAnnotationState(SfxItemSet& rItemSet)
1169 mxImpl->GetAnnotationState(rItemSet);
1174 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */