1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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"
75 #include "sdresid.hxx"
76 #include "EventMultiplexer.hxx"
77 #include "ViewShellManager.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
;
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();
127 static SfxDispatcher
* getDispatcher( ViewShellBase
& rBase
)
129 if( rBase
.GetMainViewShell().get() && rBase
.GetMainViewShell()->GetViewFrame() )
130 return rBase
.GetMainViewShell()->GetViewFrame()->GetDispatcher();
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
)
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
);
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 );
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());
179 mbShowAnnotations
= pOptions
->IsShowComments();
182 void AnnotationManagerImpl::init()
184 // get current controller and initialize listeners
188 mxView
= Reference
< XDrawView
>::query(mrBase
.GetController());
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
);
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
);
222 if( mnUpdateTagsEvent
)
224 Application::RemoveUserEvent( mnUpdateTagsEvent
);
225 mnUpdateTagsEvent
= 0;
229 mxCurrentPage
.clear();
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" )
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());
254 pOptions
->SetShowComments( mbShowAnnotations
);
260 void AnnotationManagerImpl::ExecuteAnnotation(SfxRequest
& rReq
)
262 switch( rReq
.GetSlot() )
264 case SID_INSERT_POSTIT
:
265 ExecuteInsertAnnotation( rReq
);
267 case SID_DELETE_POSTIT
:
268 case SID_DELETEALL_POSTIT
:
269 case SID_DELETEALLBYAUTHOR_POSTIT
:
270 ExecuteDeleteAnnotation( rReq
);
272 case SID_PREVIOUS_POSTIT
:
273 case SID_NEXT_POSTIT
:
274 SelectNextAnnotation( rReq
.GetSlot() == SID_NEXT_POSTIT
);
276 case SID_REPLYTO_POSTIT
:
277 ExecuteReplyToAnnotation( rReq
);
279 case SID_SHOW_POSTIT
:
280 ShowAnnotations( !mbShowAnnotations
);
285 void AnnotationManagerImpl::ExecuteInsertAnnotation(SfxRequest
& /*rReq*/)
287 ShowAnnotations(true);
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();
302 case SID_DELETEALLBYAUTHOR_POSTIT
:
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
);
313 case SID_DELETE_POSTIT
:
315 Reference
< XAnnotation
> xAnnotation
;
317 if( rReq
.GetSlot() == SID_DELETE_POSTIT
)
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
);
338 void AnnotationManagerImpl::InsertAnnotation()
340 SdPage
* pPage
= GetCurrentPage();
343 if( mpDoc
->IsUndoEnabled() )
344 mpDoc
->BegUndo( SD_RESSTR( STR_ANNOTATION_UNDO_INSERT
) );
346 // find free space for new annotation
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;
359 Rectangle
aNewRect( x
, y
, x
+ width
- 1, y
+ height
- 1 );
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
) )
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() );
404 RealPoint2D
aPos( ((double)x
) / 100.0, ((double)y
) / 100.0 );
405 xAnnotation
->setPosition( aPos
);
407 if( mpDoc
->IsUndoEnabled() )
411 SelectAnnotation( xAnnotation
, true );
415 void AnnotationManagerImpl::ExecuteReplyToAnnotation( SfxRequest
& rReq
)
417 Reference
< XAnnotation
> xAnnotation
;
418 const SfxItemSet
* pArgs
= rReq
.GetArgs();
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
);
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() )
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
));
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() );
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() )
497 void AnnotationManagerImpl::DeleteAnnotationsByAuthor( const OUString
& sAuthor
)
499 if( mpDoc
->IsUndoEnabled() )
500 mpDoc
->BegUndo( SD_RESSTR( STR_ANNOTATION_UNDO_DELETE
) );
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
);
523 if( mpDoc
->IsUndoEnabled() )
527 void AnnotationManagerImpl::DeleteAllAnnotations()
529 if( mpDoc
->IsUndoEnabled() )
530 mpDoc
->BegUndo( SD_RESSTR( STR_ANNOTATION_UNDO_DELETE
) );
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
) );
549 mxSelectedAnnotation
.clear();
551 if( mpDoc
->IsUndoEnabled() )
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
);
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();
609 AnnotationVector
aAnnotations( pPage
->getAnnotations() );
615 for( AnnotationVector::iterator iter
= aAnnotations
.begin(); iter
!= aAnnotations
.end(); ++iter
)
617 if( (*iter
) == xCurrent
)
620 if( iter
!= aAnnotations
.end() )
622 SelectAnnotation( (*iter
) );
629 else if( !aAnnotations
.empty() )
631 SelectAnnotation( *(aAnnotations
.begin()) );
639 for( AnnotationVector::iterator iter
= aAnnotations
.begin(); iter
!= aAnnotations
.end(); ++iter
)
641 if( (*iter
) == xCurrent
)
643 if( iter
!= aAnnotations
.begin() )
646 SelectAnnotation( (*iter
) );
653 else if( !aAnnotations
.empty() )
655 AnnotationVector::iterator
iter( aAnnotations
.end() );
656 SelectAnnotation( *(--iter
) );
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
);
679 pDispatcher
->Execute( bForeward
? SID_NEXT_POSTIT
: SID_PREVIOUS_POSTIT
);
687 // The question text depends on the search direction.
688 bool bImpress
= mpDoc
->GetDocumentType() == DOCUMENT_TYPE_IMPRESS
;
689 sal_uInt16 nStringId
;
691 nStringId
= bImpress
? STR_ANNOTATION_WRAP_FORWARD
: STR_ANNOTATION_WRAP_FORWARD_DRAW
;
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
)
705 void AnnotationManagerImpl::onTagSelected( AnnotationTag
& rTag
)
707 mxSelectedAnnotation
= rTag
.GetAnnotation();
711 void AnnotationManagerImpl::onTagDeselected( AnnotationTag
& rTag
)
713 if( rTag
.GetAnnotation() == mxSelectedAnnotation
)
715 mxSelectedAnnotation
.clear();
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
);
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
);
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
;
773 OSL_FAIL( "sd::AnnotationManagerImpl::onSelectionChanged(), exception caught!" );
777 void AnnotationManagerImpl::UpdateTags( bool bSynchron
)
781 if( mnUpdateTagsEvent
)
782 Application::RemoveUserEvent( mnUpdateTagsEvent
);
788 if( !mnUpdateTagsEvent
&& mxView
.is() )
789 mnUpdateTagsEvent
= Application::PostUserEvent( LINK( this, AnnotationManagerImpl
, UpdateTagsHdl
) );
793 IMPL_LINK_NOARG(AnnotationManagerImpl
, UpdateTagsHdl
)
795 mnUpdateTagsEvent
= 0;
798 if( mbShowAnnotations
)
801 if( mrBase
.GetDrawView() )
802 static_cast< ::sd::View
* >( mrBase
.GetDrawView() )->updateHandles();
809 void AnnotationManagerImpl::CreateTags()
812 if( mxCurrentPage
.is() && mpDoc
) try
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
)
833 if( xSelectedTag
.is() )
835 SmartTagReference
xTag( xSelectedTag
.get() );
836 mrBase
.GetMainViewShell()->GetView()->getSmartTags().select( xTag
);
840 // no tag, no selection!
841 mxSelectedAnnotation
.clear();
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() );
865 void AnnotationManagerImpl::addListener()
867 Link
<> aLink( LINK(this,AnnotationManagerImpl
,EventMultiplexerListener
) );
868 mrBase
.GetEventMultiplexer()->AddEventListener (
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();
892 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
:
894 onSelectionChanged();
897 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
:
898 mxView
= Reference
<XDrawView
>::query( mrBase
.GetController() );
899 onSelectionChanged();
905 void AnnotationManagerImpl::ExecuteAnnotationContextMenu( Reference
< XAnnotation
> xAnnotation
, vcl::Window
* pParent
, const Rectangle
& rContextRect
, bool bButtonMenu
/* = false */ )
907 SfxDispatcher
* pDispatcher( getDispatcher( mrBase
) );
911 const bool bReadOnly
= mrBase
.GetDocShell()->IsReadOnly();
913 AnnotationWindow
* pAnnotationWindow
= bButtonMenu
? 0 : dynamic_cast< AnnotationWindow
* >( pParent
);
915 if( bReadOnly
&& !pAnnotationWindow
)
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 );
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() );
982 Reference
< ::com::sun::star::frame::XFrame
> xFrame( mrBase
.GetMainViewShell()->GetViewFrame()->GetFrame().GetFrameInterface() );
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 ) );
995 pMenu
->SetItemImage( nId
, aImage
);
1000 nId
= pMenu
->Execute( pParent
, rContextRect
, PopupMenuFlags::ExecuteDown
|PopupMenuFlags::NoMouseUpClose
);
1003 case SID_REPLYTO_POSTIT
:
1005 const SfxUnoAnyItem
aItem( SID_REPLYTO_POSTIT
, Any( xAnnotation
) );
1006 pDispatcher
->Execute( SID_REPLYTO_POSTIT
, SfxCallMode::ASYNCHRON
, &aItem
, 0 );
1009 case SID_DELETE_POSTIT
:
1011 const SfxUnoAnyItem
aItem( SID_DELETE_POSTIT
, Any( xAnnotation
) );
1012 pDispatcher
->Execute( SID_DELETE_POSTIT
, SfxCallMode::ASYNCHRON
, &aItem
, 0 );
1015 case SID_DELETEALLBYAUTHOR_POSTIT
:
1017 const SfxStringItem
aItem( SID_DELETEALLBYAUTHOR_POSTIT
, sAuthor
);
1018 pDispatcher
->Execute( SID_DELETEALLBYAUTHOR_POSTIT
, SfxCallMode::ASYNCHRON
, &aItem
, 0 );
1021 case SID_DELETEALL_POSTIT
:
1022 pDispatcher
->Execute( SID_DELETEALL_POSTIT
);
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
);
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
)
1084 return bForeward
? GetFirstPage() : GetLastPage();
1086 sal_uInt16 nPageNum
= (pPage
->GetPageNum() - 1) >> 1;
1088 // first all non master pages
1089 if( !pPage
->IsMasterPage() )
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
);
1103 return 0; // we are already on the first draw page, finished
1107 return mpDoc
->GetSdPage(nPageNum
, PK_STANDARD
);
1113 if( nPageNum
>= mpDoc
->GetMasterSdPageCount(PK_STANDARD
)-1 )
1115 return 0; // we reached the end, there is nothing more to see here
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
);
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();
1151 AnnotationManager::AnnotationManager( ViewShellBase
& rViewShellBase
)
1152 : mxImpl( new AnnotationManagerImpl( rViewShellBase
) )
1157 AnnotationManager::~AnnotationManager()
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: */