bump product version to 4.1.6.2
[LibreOffice.git] / sd / source / ui / annotations / annotationmanager.cxx
blob184cc3df337efff885758ed95a1d7d9981fb4b0a
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 .
21 #include "sddll.hxx"
23 #include <com/sun/star/beans/XMultiPropertyStates.hpp>
24 #include <com/sun/star/frame/XController.hpp>
25 #include <com/sun/star/frame/XModel.hpp>
26 #include <com/sun/star/view/XSelectionSupplier.hpp>
27 #include <com/sun/star/geometry/RealPoint2D.hpp>
28 #include <com/sun/star/text/XText.hpp>
29 #include <com/sun/star/document/XEventBroadcaster.hpp>
30 #include <comphelper/string.hxx>
31 #include <svx/svxids.hrc>
32 #include <vcl/menu.hxx>
33 #include <vcl/msgbox.hxx>
35 #include <sal/macros.h>
36 #include <svl/style.hxx>
37 #include <svl/itempool.hxx>
38 #include <unotools/useroptions.hxx>
39 #include <unotools/syslocale.hxx>
40 #include <unotools/saveopt.hxx>
42 #include <tools/datetime.hxx>
44 #include <sfx2/imagemgr.hxx>
45 #include <sfx2/viewfrm.hxx>
46 #include <sfx2/bindings.hxx>
47 #include <sfx2/app.hxx>
48 #include <sfx2/request.hxx>
49 #include <sfx2/dispatch.hxx>
50 #include <sfx2/objface.hxx>
52 #include <editeng/editeng.hxx>
53 #include <editeng/eeitem.hxx>
54 #include <editeng/fontitem.hxx>
55 #include <editeng/fhgtitem.hxx>
56 #include <editeng/outlobj.hxx>
57 #include <editeng/postitem.hxx>
58 #include <editeng/wghtitem.hxx>
59 #include <editeng/udlnitem.hxx>
60 #include <editeng/crossedoutitem.hxx>
62 #include <svx/svdetc.hxx>
64 #include "annotationmanager.hxx"
65 #include "annotationmanagerimpl.hxx"
66 #include "annotationwindow.hxx"
67 #include "annotations.hrc"
69 #include "ToolBarManager.hxx"
70 #include "DrawDocShell.hxx"
71 #include "DrawViewShell.hxx"
72 #include "DrawController.hxx"
73 #include "glob.hrc"
74 #include "sdresid.hxx"
75 #include "EventMultiplexer.hxx"
76 #include "ViewShellManager.hxx"
77 #include "helpids.h"
78 #include "sdpage.hxx"
79 #include "drawdoc.hxx"
80 #include "textapi.hxx"
81 #include "optsitem.hxx"
83 using namespace ::com::sun::star;
84 using namespace ::com::sun::star::uno;
85 using namespace ::com::sun::star::drawing;
86 using namespace ::com::sun::star::document;
87 using namespace ::com::sun::star::geometry;
88 using namespace ::com::sun::star::container;
89 using namespace ::com::sun::star::beans;
90 using namespace ::com::sun::star::text;
91 using namespace ::com::sun::star::view;
92 using namespace ::com::sun::star::style;
93 using namespace ::com::sun::star::frame;
94 using namespace ::com::sun::star::lang;
95 using namespace ::com::sun::star::ui;
96 using namespace ::com::sun::star::task;
97 using namespace ::com::sun::star::office;
99 namespace sd {
101 // --------------------------------------------------------------------
103 extern TextApiObject* getTextApiObject( const Reference< XAnnotation >& xAnnotation );
105 // --------------------------------------------------------------------
107 SfxItemPool* GetAnnotationPool()
109 static SfxItemPool* mpAnnotationPool = 0;
110 if( mpAnnotationPool == 0 )
112 mpAnnotationPool = EditEngine::CreatePool( sal_False );
113 mpAnnotationPool->SetPoolDefaultItem(SvxFontHeightItem(423,100,EE_CHAR_FONTHEIGHT));
115 Font aAppFont( Application::GetSettings().GetStyleSettings().GetAppFont() );
116 String EMPTYSTRING;
117 mpAnnotationPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamily(),aAppFont.GetName(), EMPTYSTRING,PITCH_DONTKNOW,RTL_TEXTENCODING_DONTKNOW,EE_CHAR_FONTINFO));
120 return mpAnnotationPool;
123 // --------------------------------------------------------------------
125 static SfxBindings* getBindings( ViewShellBase& rBase )
127 if( rBase.GetMainViewShell().get() && rBase.GetMainViewShell()->GetViewFrame() )
128 return &rBase.GetMainViewShell()->GetViewFrame()->GetBindings();
130 return 0;
133 // --------------------------------------------------------------------
135 static SfxDispatcher* getDispatcher( ViewShellBase& rBase )
137 if( rBase.GetMainViewShell().get() && rBase.GetMainViewShell()->GetViewFrame() )
138 return rBase.GetMainViewShell()->GetViewFrame()->GetDispatcher();
140 return 0;
143 com::sun::star::util::DateTime getCurrentDateTime()
145 DateTime aCurrentDate( DateTime::SYSTEM );
146 return com::sun::star::util::DateTime( 0, aCurrentDate.GetSec(),
147 aCurrentDate.GetMin(), aCurrentDate.GetHour(),
148 aCurrentDate.GetDay(), aCurrentDate.GetMonth(),
149 aCurrentDate.GetYear(), false );
152 OUString getAnnotationDateTimeString( const Reference< XAnnotation >& xAnnotation )
154 OUString sRet;
155 if( xAnnotation.is() )
157 const SvtSysLocale aSysLocale;
158 const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
160 com::sun::star::util::DateTime aDateTime( xAnnotation->getDateTime() );
162 Date aSysDate( Date::SYSTEM );
163 Date aDate = Date( aDateTime.Day, aDateTime.Month, aDateTime.Year );
164 if (aDate==aSysDate)
165 sRet = SdResId(STR_ANNOTATION_TODAY);
166 else if (aDate == Date(aSysDate-1))
167 sRet = SdResId(STR_ANNOTATION_YESTERDAY);
168 else if (aDate.IsValidAndGregorian() )
169 sRet = rLocalData.getDate(aDate);
171 Time aTime( aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds, aDateTime.NanoSeconds );
172 if(aTime.GetTime() != 0)
173 sRet = sRet + " " + rLocalData.getTime( aTime,false );
175 return sRet;
178 // --------------------------------------------------------------------
180 AnnotationManagerImpl::AnnotationManagerImpl( ViewShellBase& rViewShellBase )
181 : AnnotationManagerImplBase( m_aMutex )
182 , mrBase( rViewShellBase )
183 , mpDoc( rViewShellBase.GetDocument() )
184 , mbShowAnnotations( true )
185 , mnUpdateTagsEvent( 0 )
187 SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType());
188 if( pOptions )
189 mbShowAnnotations = pOptions->IsShowComments() == sal_True;
192 // --------------------------------------------------------------------
194 void AnnotationManagerImpl::init()
196 // get current controller and initialize listeners
199 addListener();
200 mxView = Reference< XDrawView >::query(mrBase.GetController());
202 catch( Exception& )
204 OSL_FAIL( "sd::AnnotationManagerImpl::AnnotationManagerImpl(), Exception caught!" );
209 Reference<XEventBroadcaster> xModel (mrBase.GetDocShell()->GetModel(), UNO_QUERY_THROW );
210 Reference<XEventListener> xListener( this );
211 xModel->addEventListener( xListener );
213 catch( Exception& )
218 // --------------------------------------------------------------------
220 // WeakComponentImplHelper1
221 void SAL_CALL AnnotationManagerImpl::disposing ()
225 Reference<XEventBroadcaster> xModel (mrBase.GetDocShell()->GetModel(), UNO_QUERY_THROW );
226 Reference<XEventListener> xListener( this );
227 xModel->removeEventListener( xListener );
229 catch( Exception& )
233 removeListener();
234 DisposeTags();
236 if( mnUpdateTagsEvent )
238 Application::RemoveUserEvent( mnUpdateTagsEvent );
239 mnUpdateTagsEvent = 0;
242 mxView.clear();
243 mxCurrentPage.clear();
246 // --------------------------------------------------------------------
248 // XEventListener
249 void SAL_CALL AnnotationManagerImpl::notifyEvent( const ::com::sun::star::document::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException)
251 if( aEvent.EventName == "OnAnnotationInserted" || aEvent.EventName == "OnAnnotationRemoved" || aEvent.EventName == "OnAnnotationChanged" )
253 UpdateTags();
257 void SAL_CALL AnnotationManagerImpl::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException)
261 void AnnotationManagerImpl::ShowAnnotations( bool bShow )
263 // enforce show annotations if a new annotation is inserted
264 if( mbShowAnnotations != bShow )
266 mbShowAnnotations = bShow;
268 SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType());
269 if( pOptions )
270 pOptions->SetShowComments( mbShowAnnotations ? sal_True : sal_False );
272 UpdateTags();
276 // --------------------------------------------------------------------
278 void AnnotationManagerImpl::ExecuteAnnotation(SfxRequest& rReq )
280 switch( rReq.GetSlot() )
282 case SID_INSERT_POSTIT:
283 ExecuteInsertAnnotation( rReq );
284 break;
285 case SID_DELETE_POSTIT:
286 case SID_DELETEALL_POSTIT:
287 case SID_DELETEALLBYAUTHOR_POSTIT:
288 ExecuteDeleteAnnotation( rReq );
289 break;
290 case SID_PREVIOUS_POSTIT:
291 case SID_NEXT_POSTIT:
292 SelectNextAnnotation( rReq.GetSlot() == SID_NEXT_POSTIT );
293 break;
294 case SID_REPLYTO_POSTIT:
295 ExecuteReplyToAnnotation( rReq );
296 break;
297 case SID_SHOW_POSTIT:
298 ShowAnnotations( !mbShowAnnotations );
299 break;
303 // --------------------------------------------------------------------
305 void AnnotationManagerImpl::ExecuteInsertAnnotation(SfxRequest& /*rReq*/)
307 ShowAnnotations(true);
308 InsertAnnotation();
311 // --------------------------------------------------------------------
313 void AnnotationManagerImpl::ExecuteDeleteAnnotation(SfxRequest& rReq)
315 ShowAnnotations( true );
317 const SfxItemSet* pArgs = rReq.GetArgs();
319 switch( rReq.GetSlot() )
321 case SID_DELETEALL_POSTIT:
322 DeleteAllAnnotations();
323 break;
324 case SID_DELETEALLBYAUTHOR_POSTIT:
325 if( pArgs )
327 const SfxPoolItem* pPoolItem = NULL;
328 if( SFX_ITEM_SET == pArgs->GetItemState( SID_DELETEALLBYAUTHOR_POSTIT, sal_True, &pPoolItem ) )
330 OUString sAuthor( (( const SfxStringItem* ) pPoolItem )->GetValue() );
331 DeleteAnnotationsByAuthor( sAuthor );
334 break;
335 case SID_DELETE_POSTIT:
337 Reference< XAnnotation > xAnnotation;
339 if( rReq.GetSlot() == SID_DELETE_POSTIT )
341 if( pArgs )
343 const SfxPoolItem* pPoolItem = NULL;
344 if( SFX_ITEM_SET == pArgs->GetItemState( SID_DELETE_POSTIT, sal_True, &pPoolItem ) )
345 ( ( const SfxUnoAnyItem* ) pPoolItem )->GetValue() >>= xAnnotation;
349 if( !xAnnotation.is() )
350 GetSelectedAnnotation( xAnnotation );
352 DeleteAnnotation( xAnnotation );
354 break;
357 UpdateTags();
360 // --------------------------------------------------------------------
362 void AnnotationManagerImpl::InsertAnnotation()
364 SdPage* pPage = GetCurrentPage();
365 if( pPage )
367 if( mpDoc->IsUndoEnabled() )
368 mpDoc->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_INSERT ) ) );
370 // find free space for new annotation
371 int y = 0, x = 0;
373 AnnotationVector aAnnotations( pPage->getAnnotations() );
374 if( !aAnnotations.empty() )
376 const int page_width = pPage->GetSize().Width();
377 const int width = 1000;
378 const int height = 800;
379 Rectangle aTagRect;
381 while( true )
383 Rectangle aNewRect( x, y, x + width - 1, y + height - 1 );
384 bool bFree = true;
386 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
388 RealPoint2D aPoint( (*iter)->getPosition() );
389 aTagRect.Left() = sal::static_int_cast< long >( aPoint.X * 100.0 );
390 aTagRect.Top() = sal::static_int_cast< long >( aPoint.Y * 100.0 );
391 aTagRect.Right() = aTagRect.Left() + width - 1;
392 aTagRect.Bottom() = aTagRect.Top() + height - 1;
394 if( aNewRect.IsOver( aTagRect ) )
396 bFree = false;
397 break;
401 if( bFree == false)
403 x += width;
404 if( x > page_width )
406 x = 0;
407 y += height;
410 else
412 break;
417 Reference< XAnnotation > xAnnotation;
418 pPage->createAnnotation( xAnnotation );
420 // set current author to new annotation
421 SvtUserOptions aUserOptions;
422 xAnnotation->setAuthor( aUserOptions.GetFullName() );
424 // set current time to new annotation
425 xAnnotation->setDateTime( getCurrentDateTime() );
427 // set position
428 RealPoint2D aPos( ((double)x) / 100.0, ((double)y) / 100.0 );
429 xAnnotation->setPosition( aPos );
431 if( mpDoc->IsUndoEnabled() )
432 mpDoc->EndUndo();
434 UpdateTags(true);
435 SelectAnnotation( xAnnotation, true );
439 // --------------------------------------------------------------------
441 void AnnotationManagerImpl::ExecuteReplyToAnnotation( SfxRequest& rReq )
443 Reference< XAnnotation > xAnnotation;
444 const SfxItemSet* pArgs = rReq.GetArgs();
445 if( pArgs )
447 const SfxPoolItem* pPoolItem = NULL;
448 if( SFX_ITEM_SET == pArgs->GetItemState( rReq.GetSlot(), sal_True, &pPoolItem ) )
449 ( ( const SfxUnoAnyItem* ) pPoolItem )->GetValue() >>= xAnnotation;
453 TextApiObject* pTextApi = getTextApiObject( xAnnotation );
454 if( pTextApi )
456 std::auto_ptr< ::Outliner > pOutliner( new ::Outliner(GetAnnotationPool(),OUTLINERMODE_TEXTOBJECT) );
458 mpDoc->SetCalcFieldValueHdl( pOutliner.get() );
459 pOutliner->SetUpdateMode( sal_True );
461 String aStr(SdResId(STR_ANNOTATION_REPLY));
462 OUString sAuthor( xAnnotation->getAuthor() );
463 if( sAuthor.isEmpty() )
464 sAuthor = String( SdResId( STR_ANNOTATION_NOAUTHOR ) );
466 aStr.SearchAndReplaceAscii("%1", sAuthor);
468 aStr.Append( OUString(" (") );
469 aStr.Append( OUString( getAnnotationDateTimeString( xAnnotation ) ) );
470 aStr.Append( OUString("): \"") );
472 String sQuote( pTextApi->GetText() );
474 if( sQuote.Len() == 0 )
475 sQuote = OUString( "..." );
476 aStr.Append( sQuote );
477 aStr.Append( OUString("\"\n") );
479 sal_Int32 nParaCount = comphelper::string::getTokenCount(aStr, '\n');
480 for( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ )
481 pOutliner->Insert( aStr.GetToken( nPara, '\n' ), EE_PARA_APPEND, -1 );
483 if( pOutliner->GetParagraphCount() > 1 )
485 SfxItemSet aAnswerSet( pOutliner->GetEmptyItemSet() );
486 aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC));
488 ESelection aSel;
489 aSel.nEndPara = pOutliner->GetParagraphCount()-2;
490 aSel.nEndPos = pOutliner->GetText( pOutliner->GetParagraph( aSel.nEndPara ) ).Len();
492 pOutliner->QuickSetAttribs( aAnswerSet, aSel );
495 std::auto_ptr< OutlinerParaObject > pOPO( pOutliner->CreateParaObject() );
496 pTextApi->SetText( *pOPO.get() );
498 SvtUserOptions aUserOptions;
499 xAnnotation->setAuthor( aUserOptions.GetFullName() );
501 // set current time to reply
502 xAnnotation->setDateTime( getCurrentDateTime() );
504 UpdateTags(true);
505 SelectAnnotation( xAnnotation, true );
509 // --------------------------------------------------------------------
511 void AnnotationManagerImpl::DeleteAnnotation( Reference< XAnnotation > xAnnotation )
513 SdPage* pPage = GetCurrentPage();
515 if( xAnnotation.is() && pPage )
517 if( mpDoc->IsUndoEnabled() )
518 mpDoc->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_DELETE ) ) );
520 pPage->removeAnnotation( xAnnotation );
522 if( mpDoc->IsUndoEnabled() )
523 mpDoc->EndUndo();
525 UpdateTags();
529 void AnnotationManagerImpl::DeleteAnnotationsByAuthor( const OUString& sAuthor )
531 if( mpDoc->IsUndoEnabled() )
532 mpDoc->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_DELETE ) ) );
534 SdPage* pPage = 0;
537 pPage = GetNextPage( pPage, true );
539 if( pPage && !pPage->getAnnotations().empty() )
541 AnnotationVector aAnnotations( pPage->getAnnotations() );
542 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
544 Reference< XAnnotation > xAnnotation( *iter );
545 if( xAnnotation->getAuthor() == sAuthor )
547 if( mxSelectedAnnotation == xAnnotation )
548 mxSelectedAnnotation.clear();
549 pPage->removeAnnotation( xAnnotation );
553 } while( pPage );
555 if( mpDoc->IsUndoEnabled() )
556 mpDoc->EndUndo();
559 void AnnotationManagerImpl::DeleteAllAnnotations()
561 if( mpDoc->IsUndoEnabled() )
562 mpDoc->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_DELETE ) ) );
564 SdPage* pPage = 0;
567 pPage = GetNextPage( pPage, true );
569 if( pPage && !pPage->getAnnotations().empty() )
572 AnnotationVector aAnnotations( pPage->getAnnotations() );
573 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
575 pPage->removeAnnotation( (*iter) );
579 while( pPage );
581 mxSelectedAnnotation.clear();
583 if( mpDoc->IsUndoEnabled() )
584 mpDoc->EndUndo();
587 // --------------------------------------------------------------------
589 void AnnotationManagerImpl::GetAnnotationState(SfxItemSet& rSet)
591 SdPage* pCurrentPage = GetCurrentPage();
593 const bool bReadOnly = mrBase.GetDocShell()->IsReadOnly();
594 const bool bWrongPageKind = (pCurrentPage == 0) || (pCurrentPage->GetPageKind() != PK_STANDARD);
596 const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
598 if( bReadOnly || bWrongPageKind || (nCurrentODFVersion <= SvtSaveOptions::ODFVER_012) )
599 rSet.DisableItem( SID_INSERT_POSTIT );
601 rSet.Put(SfxBoolItem(SID_SHOW_POSTIT, mbShowAnnotations));
603 Reference< XAnnotation > xAnnotation;
604 GetSelectedAnnotation( xAnnotation );
606 if( !xAnnotation.is() || bReadOnly )
607 rSet.DisableItem( SID_DELETE_POSTIT );
609 SdPage* pPage = 0;
611 bool bHasAnnotations = false;
614 pPage = GetNextPage( pPage, true );
616 if( pPage && !pPage->getAnnotations().empty() )
617 bHasAnnotations = true;
619 while( pPage && !bHasAnnotations );
621 if( !bHasAnnotations || bReadOnly )
623 rSet.DisableItem( SID_DELETEALL_POSTIT );
626 if( bWrongPageKind || !bHasAnnotations )
628 rSet.DisableItem( SID_PREVIOUS_POSTIT );
629 rSet.DisableItem( SID_NEXT_POSTIT );
633 // --------------------------------------------------------------------
635 void AnnotationManagerImpl::SelectNextAnnotation(bool bForeward)
637 ShowAnnotations( true );
639 Reference< XAnnotation > xCurrent;
640 GetSelectedAnnotation( xCurrent );
641 SdPage* pPage = GetCurrentPage();
642 if( !pPage )
643 return;
645 AnnotationVector aAnnotations( pPage->getAnnotations() );
647 if( bForeward )
649 if( xCurrent.is() )
651 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
653 if( (*iter) == xCurrent )
655 ++iter;
656 if( iter != aAnnotations.end() )
658 SelectAnnotation( (*iter) );
659 return;
661 break;
665 else if( !aAnnotations.empty() )
667 SelectAnnotation( *(aAnnotations.begin()) );
668 return;
671 else
673 if( xCurrent.is() )
675 for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); ++iter )
677 if( (*iter) == xCurrent )
679 if( iter != aAnnotations.begin() )
681 --iter;
682 SelectAnnotation( (*iter) );
683 return;
685 break;
689 else if( !aAnnotations.empty() )
691 AnnotationVector::iterator iter( aAnnotations.end() );
692 SelectAnnotation( *(--iter) );
693 return;
697 mxSelectedAnnotation.clear();
702 pPage = GetNextPage( pPage, bForeward );
704 if( pPage && !pPage->getAnnotations().empty() )
706 // switch to next/previous slide with annotations
707 ::boost::shared_ptr<DrawViewShell> pDrawViewShell(::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell()));
708 if (pDrawViewShell.get() != NULL)
710 pDrawViewShell->ChangeEditMode(pPage->IsMasterPage() ? EM_MASTERPAGE : EM_PAGE, sal_False);
711 pDrawViewShell->SwitchPage((pPage->GetPageNum() - 1) >> 1);
713 SfxDispatcher* pDispatcher = getDispatcher( mrBase );
714 if( pDispatcher )
715 pDispatcher->Execute( bForeward ? SID_NEXT_POSTIT : SID_PREVIOUS_POSTIT );
717 return;
721 while( pPage );
723 // The question text depends on the search direction.
724 bool bImpress = mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS;
725 sal_uInt16 nStringId;
726 if(bForeward)
727 nStringId = bImpress ? STR_ANNOTATION_WRAP_FORWARD : STR_ANNOTATION_WRAP_FORWARD_DRAW;
728 else
729 nStringId = bImpress ? STR_ANNOTATION_WRAP_BACKWARD : STR_ANNOTATION_WRAP_BACKWARD_DRAW;
731 // Pop up question box that asks the user whether to wrap arround.
732 // The dialog is made modal with respect to the whole application.
733 QueryBox aQuestionBox ( NULL, (WB_YES_NO | WB_DEF_YES), String(SdResId(nStringId)));
734 aQuestionBox.SetImage (QueryBox::GetStandardImage());
735 short nBoxResult = aQuestionBox.Execute();
736 if (nBoxResult != RET_YES)
737 break;
739 while( true );
742 // --------------------------------------------------------------------
744 void AnnotationManagerImpl::onTagSelected( AnnotationTag& rTag )
746 mxSelectedAnnotation = rTag.GetAnnotation();
747 invalidateSlots();
750 // --------------------------------------------------------------------
752 void AnnotationManagerImpl::onTagDeselected( AnnotationTag& rTag )
754 if( rTag.GetAnnotation() == mxSelectedAnnotation )
756 mxSelectedAnnotation.clear();
757 invalidateSlots();
761 // --------------------------------------------------------------------
763 void AnnotationManagerImpl::SelectAnnotation( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation > xAnnotation, bool bEdit /* = sal_False */ )
765 mxSelectedAnnotation = xAnnotation;
767 const AnnotationTagVector::const_iterator aEnd( maTagVector.end() );
768 for( AnnotationTagVector::const_iterator iter( maTagVector.begin() );
769 iter != aEnd; ++iter)
771 if( (*iter)->GetAnnotation() == xAnnotation )
773 SmartTagReference xTag( (*iter).get() );
774 mrBase.GetMainViewShell()->GetView()->getSmartTags().select( xTag );
775 (*iter)->OpenPopup( bEdit );
776 break;
781 // --------------------------------------------------------------------
783 void AnnotationManagerImpl::GetSelectedAnnotation( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation >& xAnnotation )
785 xAnnotation = mxSelectedAnnotation;
788 void AnnotationManagerImpl::invalidateSlots()
790 SfxBindings* pBindings = getBindings( mrBase );
791 if( pBindings )
793 pBindings->Invalidate( SID_INSERT_POSTIT );
794 pBindings->Invalidate( SID_DELETE_POSTIT );
795 pBindings->Invalidate( SID_DELETEALL_POSTIT );
796 pBindings->Invalidate( SID_PREVIOUS_POSTIT );
797 pBindings->Invalidate( SID_NEXT_POSTIT );
798 pBindings->Invalidate( SID_UNDO );
799 pBindings->Invalidate( SID_REDO );
803 // --------------------------------------------------------------------
805 void AnnotationManagerImpl::onSelectionChanged()
807 if( mxView.is() && mrBase.GetDrawView() ) try
809 Reference< XAnnotationAccess > xPage( mxView->getCurrentPage(), UNO_QUERY );
811 if( xPage != mxCurrentPage )
813 mxCurrentPage = xPage;
815 UpdateTags(true);
818 catch( Exception& )
820 OSL_FAIL( "sd::AnnotationManagerImpl::onSelectionChanged(), exception caught!" );
824 void AnnotationManagerImpl::UpdateTags( bool bSynchron )
826 if( bSynchron )
828 if( mnUpdateTagsEvent )
829 Application::RemoveUserEvent( mnUpdateTagsEvent );
831 UpdateTagsHdl(0);
833 else
835 if( !mnUpdateTagsEvent && mxView.is() )
836 mnUpdateTagsEvent = Application::PostUserEvent( LINK( this, AnnotationManagerImpl, UpdateTagsHdl ) );
840 IMPL_LINK_NOARG(AnnotationManagerImpl, UpdateTagsHdl)
842 mnUpdateTagsEvent = 0;
843 DisposeTags();
845 if( mbShowAnnotations )
846 CreateTags();
848 if( mrBase.GetDrawView() )
849 static_cast< ::sd::View* >( mrBase.GetDrawView() )->updateHandles();
851 invalidateSlots();
853 return 0;
856 void AnnotationManagerImpl::CreateTags()
859 if( mxCurrentPage.is() && mpDoc ) try
861 int nIndex = 1;
862 maFont = Application::GetSettings().GetStyleSettings().GetAppFont();
864 rtl::Reference< AnnotationTag > xSelectedTag;
866 Reference< XAnnotationEnumeration > xEnum( mxCurrentPage->createAnnotationEnumeration() );
867 while( xEnum->hasMoreElements() )
869 Reference< XAnnotation > xAnnotation( xEnum->nextElement() );
870 Color aColor( GetColorLight( mpDoc->GetAnnotationAuthorIndex( xAnnotation->getAuthor() ) ) );
871 rtl::Reference< AnnotationTag > xTag( new AnnotationTag( *this, *mrBase.GetMainViewShell()->GetView(), xAnnotation, aColor, nIndex++, maFont ) );
872 maTagVector.push_back(xTag);
874 if( xAnnotation == mxSelectedAnnotation )
876 xSelectedTag = xTag;
880 if( xSelectedTag.is() )
882 SmartTagReference xTag( xSelectedTag.get() );
883 mrBase.GetMainViewShell()->GetView()->getSmartTags().select( xTag );
885 else
887 // no tag, no selection!
888 mxSelectedAnnotation.clear();
891 catch( Exception& )
893 OSL_FAIL( "sd::AnnotationManagerImpl::onSelectionChanged(), exception caught!" );
897 // --------------------------------------------------------------------
899 void AnnotationManagerImpl::DisposeTags()
901 if( !maTagVector.empty() )
903 AnnotationTagVector::iterator iter = maTagVector.begin();
906 (*iter++)->Dispose();
908 while( iter != maTagVector.end() );
910 maTagVector.clear();
914 // --------------------------------------------------------------------
916 void AnnotationManagerImpl::addListener()
918 Link aLink( LINK(this,AnnotationManagerImpl,EventMultiplexerListener) );
919 mrBase.GetEventMultiplexer()->AddEventListener (
920 aLink,
921 tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
922 | tools::EventMultiplexerEvent::EID_CURRENT_PAGE
923 | tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
924 | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED);
927 // --------------------------------------------------------------------
929 void AnnotationManagerImpl::removeListener()
931 Link aLink( LINK(this,AnnotationManagerImpl,EventMultiplexerListener) );
932 mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
935 // --------------------------------------------------------------------
937 IMPL_LINK(AnnotationManagerImpl,EventMultiplexerListener,
938 tools::EventMultiplexerEvent*,pEvent)
940 switch (pEvent->meEventId)
942 case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
943 case tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION:
944 onSelectionChanged();
945 break;
947 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
948 mxView = Reference<XDrawView>();
949 onSelectionChanged();
950 break;
952 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
953 mxView = Reference<XDrawView>::query( mrBase.GetController() );
954 onSelectionChanged();
955 break;
957 return 0;
960 void AnnotationManagerImpl::ExecuteAnnotationContextMenu( Reference< XAnnotation > xAnnotation, ::Window* pParent, const Rectangle& rContextRect, bool bButtonMenu /* = false */ )
962 SfxDispatcher* pDispatcher( getDispatcher( mrBase ) );
963 if( !pDispatcher )
964 return;
966 const bool bReadOnly = mrBase.GetDocShell()->IsReadOnly();
968 AnnotationWindow* pAnnotationWindow = bButtonMenu ? 0 : dynamic_cast< AnnotationWindow* >( pParent );
970 if( bReadOnly && !pAnnotationWindow )
971 return;
973 std::auto_ptr< PopupMenu > pMenu( new PopupMenu( SdResId( pAnnotationWindow ? RID_ANNOTATION_CONTEXTMENU : RID_ANNOTATION_TAG_CONTEXTMENU ) ) );
975 SvtUserOptions aUserOptions;
976 OUString sCurrentAuthor( aUserOptions.GetFullName() );
977 OUString sAuthor( xAnnotation->getAuthor() );
979 String aStr( pMenu->GetItemText( SID_DELETEALLBYAUTHOR_POSTIT ) ), aReplace( sAuthor );
980 if( aReplace.Len() == 0 )
981 aReplace = String( SdResId( STR_ANNOTATION_NOAUTHOR ) );
982 aStr.SearchAndReplaceAscii("%1", aReplace);
983 pMenu->SetItemText( SID_DELETEALLBYAUTHOR_POSTIT, aStr );
984 pMenu->EnableItem( SID_REPLYTO_POSTIT, (sAuthor != sCurrentAuthor) && !bReadOnly );
985 pMenu->EnableItem( SID_DELETE_POSTIT, (xAnnotation.is() && !bReadOnly) ? sal_True : sal_False );
986 pMenu->EnableItem( SID_DELETEALLBYAUTHOR_POSTIT, !bReadOnly );
987 pMenu->EnableItem( SID_DELETEALL_POSTIT, !bReadOnly );
989 if( pAnnotationWindow )
991 if( pAnnotationWindow->IsProtected() || bReadOnly )
993 pMenu->EnableItem( SID_ATTR_CHAR_WEIGHT, sal_False );
994 pMenu->EnableItem( SID_ATTR_CHAR_POSTURE, sal_False );
995 pMenu->EnableItem( SID_ATTR_CHAR_UNDERLINE, sal_False );
996 pMenu->EnableItem( SID_ATTR_CHAR_STRIKEOUT, sal_False );
997 pMenu->EnableItem( SID_PASTE, sal_False );
999 else
1001 SfxItemSet aSet(pAnnotationWindow->getView()->GetAttribs());
1003 if ( aSet.GetItemState( EE_CHAR_WEIGHT ) == SFX_ITEM_ON )
1005 if( ((const SvxWeightItem&)aSet.Get( EE_CHAR_WEIGHT )).GetWeight() == WEIGHT_BOLD )
1006 pMenu->CheckItem( SID_ATTR_CHAR_WEIGHT );
1009 if ( aSet.GetItemState( EE_CHAR_ITALIC ) == SFX_ITEM_ON )
1011 if( ((const SvxPostureItem&)aSet.Get( EE_CHAR_ITALIC )).GetPosture() != ITALIC_NONE )
1012 pMenu->CheckItem( SID_ATTR_CHAR_POSTURE );
1015 if ( aSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON )
1017 if( ((const SvxUnderlineItem&)aSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() != UNDERLINE_NONE )
1018 pMenu->CheckItem( SID_ATTR_CHAR_UNDERLINE );
1021 if ( aSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON )
1023 if( ((const SvxCrossedOutItem&)aSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() != STRIKEOUT_NONE )
1024 pMenu->CheckItem( SID_ATTR_CHAR_STRIKEOUT );
1026 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pAnnotationWindow ) );
1027 pMenu->EnableItem( SID_PASTE, aDataHelper.GetFormatCount() != 0 );
1030 pMenu->EnableItem( SID_COPY, pAnnotationWindow->getView()->HasSelection() );
1033 sal_uInt16 nId = 0;
1035 // set slot images
1036 Reference< ::com::sun::star::frame::XFrame > xFrame( mrBase.GetMainViewShell()->GetViewFrame()->GetFrame().GetFrameInterface() );
1037 if( xFrame.is() )
1039 for( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
1041 nId = pMenu->GetItemId( nPos );
1042 if( pMenu->IsItemEnabled( nId ) )
1044 OUString sSlotURL( "slot:" );
1045 sSlotURL += OUString::valueOf( sal_Int32( nId ));
1047 Image aImage( GetImage( xFrame, sSlotURL, false ) );
1048 if( !!aImage )
1049 pMenu->SetItemImage( nId, aImage );
1054 nId = pMenu->Execute( pParent, rContextRect, POPUPMENU_EXECUTE_DOWN|POPUPMENU_NOMOUSEUPCLOSE );
1055 switch( nId )
1057 case SID_REPLYTO_POSTIT:
1059 const SfxUnoAnyItem aItem( SID_REPLYTO_POSTIT, Any( xAnnotation ) );
1060 pDispatcher->Execute( SID_REPLYTO_POSTIT, SFX_CALLMODE_ASYNCHRON, &aItem, 0 );
1061 break;
1063 case SID_DELETE_POSTIT:
1065 const SfxUnoAnyItem aItem( SID_DELETE_POSTIT, Any( xAnnotation ) );
1066 pDispatcher->Execute( SID_DELETE_POSTIT, SFX_CALLMODE_ASYNCHRON, &aItem, 0 );
1067 break;
1069 case SID_DELETEALLBYAUTHOR_POSTIT:
1071 const SfxStringItem aItem( SID_DELETEALLBYAUTHOR_POSTIT, sAuthor );
1072 pDispatcher->Execute( SID_DELETEALLBYAUTHOR_POSTIT, SFX_CALLMODE_ASYNCHRON, &aItem, 0 );
1073 break;
1075 case SID_DELETEALL_POSTIT:
1076 pDispatcher->Execute( SID_DELETEALL_POSTIT );
1077 break;
1078 case SID_COPY:
1079 case SID_PASTE:
1080 case SID_ATTR_CHAR_WEIGHT:
1081 case SID_ATTR_CHAR_POSTURE:
1082 case SID_ATTR_CHAR_UNDERLINE:
1083 case SID_ATTR_CHAR_STRIKEOUT:
1084 if( pAnnotationWindow )
1085 pAnnotationWindow->ExecuteSlot( nId );
1086 break;
1090 // ====================================================================
1092 Color AnnotationManagerImpl::GetColor(sal_uInt16 aAuthorIndex)
1094 if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1096 static const Color aArrayNormal[] = {
1097 COL_AUTHOR1_NORMAL, COL_AUTHOR2_NORMAL, COL_AUTHOR3_NORMAL,
1098 COL_AUTHOR4_NORMAL, COL_AUTHOR5_NORMAL, COL_AUTHOR6_NORMAL,
1099 COL_AUTHOR7_NORMAL, COL_AUTHOR8_NORMAL, COL_AUTHOR9_NORMAL };
1101 return Color( aArrayNormal[ aAuthorIndex % (sizeof( aArrayNormal )/ sizeof( aArrayNormal[0] ))]);
1104 return Color(COL_WHITE);
1107 Color AnnotationManagerImpl::GetColorLight(sal_uInt16 aAuthorIndex)
1109 if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1111 static const Color aArrayLight[] = {
1112 COL_AUTHOR1_LIGHT, COL_AUTHOR2_LIGHT, COL_AUTHOR3_LIGHT,
1113 COL_AUTHOR4_LIGHT, COL_AUTHOR5_LIGHT, COL_AUTHOR6_LIGHT,
1114 COL_AUTHOR7_LIGHT, COL_AUTHOR8_LIGHT, COL_AUTHOR9_LIGHT };
1116 return Color( aArrayLight[ aAuthorIndex % (sizeof( aArrayLight )/ sizeof( aArrayLight[0] ))]);
1119 return Color(COL_WHITE);
1122 Color AnnotationManagerImpl::GetColorDark(sal_uInt16 aAuthorIndex)
1124 if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1126 static const Color aArrayAnkor[] = {
1127 COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK,
1128 COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK,
1129 COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK };
1131 return Color( aArrayAnkor[ aAuthorIndex % (sizeof( aArrayAnkor ) / sizeof( aArrayAnkor[0] ))]);
1134 return Color(COL_WHITE);
1137 SdPage* AnnotationManagerImpl::GetNextPage( SdPage* pPage, bool bForeward )
1139 if( pPage == 0 )
1140 return bForeward ? GetFirstPage() : GetLastPage();
1142 sal_uInt16 nPageNum = (pPage->GetPageNum() - 1) >> 1;
1144 // first all non master pages
1145 if( !pPage->IsMasterPage() )
1147 if( bForeward )
1149 if( nPageNum >= mpDoc->GetSdPageCount(PK_STANDARD)-1 )
1151 // we reached end of draw pages, start with master pages (skip handout master for draw)
1152 return mpDoc->GetMasterSdPage( (mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS) ? 0 : 1, PK_STANDARD );
1154 nPageNum++;
1156 else
1158 if( nPageNum == 0 )
1159 return 0; // we are already on the first draw page, finished
1161 nPageNum--;
1163 return mpDoc->GetSdPage(nPageNum, PK_STANDARD);
1165 else
1167 if( bForeward )
1169 if( nPageNum >= mpDoc->GetMasterSdPageCount(PK_STANDARD)-1 )
1171 return 0; // we reached the end, there is nothing more to see here
1173 nPageNum++;
1175 else
1177 if( nPageNum == (mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS) ? 0 : 1 )
1179 // we reached beginning of master pages, start with end if pages
1180 return mpDoc->GetSdPage( mpDoc->GetSdPageCount(PK_STANDARD)-1, PK_STANDARD );
1183 nPageNum--;
1185 return mpDoc->GetMasterSdPage(nPageNum,PK_STANDARD);
1189 SdPage* AnnotationManagerImpl::GetFirstPage()
1191 // return first drawing page
1192 return mpDoc->GetSdPage(0, PK_STANDARD );
1195 SdPage* AnnotationManagerImpl::GetLastPage()
1197 return mpDoc->GetMasterSdPage( mpDoc->GetMasterSdPageCount(PK_STANDARD) - 1, PK_STANDARD );
1200 SdPage* AnnotationManagerImpl::GetCurrentPage()
1202 return mrBase.GetMainViewShell()->getCurrentPage();
1205 // ====================================================================
1207 AnnotationManager::AnnotationManager( ViewShellBase& rViewShellBase )
1208 : mxImpl( new AnnotationManagerImpl( rViewShellBase ) )
1210 mxImpl->init();
1213 AnnotationManager::~AnnotationManager()
1215 mxImpl->dispose();
1218 void AnnotationManager::ExecuteAnnotation(SfxRequest& rRequest)
1220 mxImpl->ExecuteAnnotation( rRequest );
1223 void AnnotationManager::GetAnnotationState(SfxItemSet& rItemSet)
1225 mxImpl->GetAnnotationState(rItemSet);
1230 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */