blob: 8cda4b3a2b236301600a7b2c1054aa5376051635 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"
#include "sddll.hxx"
//#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/XMultiPropertyStates.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <com/sun/star/geometry/RealPoint2D.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <svx/svxids.hrc>
#include <vcl/menu.hxx>
#include <vcl/msgbox.hxx>
#include <svl/style.hxx>
#include <svl/itempool.hxx>
#include <unotools/useroptions.hxx>
#include <unotools/syslocale.hxx>
#include <unotools/saveopt.hxx>
#include <tools/datetime.hxx>
#include <sfx2/imagemgr.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/app.hxx>
#include <sfx2/request.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/imagemgr.hxx>
#include <editeng/editeng.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/postitem.hxx>
#include <editeng/wghtitem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/crsditem.hxx>
#include <svx/svdetc.hxx>
#include "annotationmanager.hxx"
#include "annotationmanagerimpl.hxx"
#include "annotationwindow.hxx"
#include "annotations.hrc"
#include "ToolBarManager.hxx"
#include "DrawDocShell.hxx"
#include "DrawViewShell.hxx"
#include "DrawController.hxx"
#include "glob.hrc"
#include "sdresid.hxx"
#include "EventMultiplexer.hxx"
#include "ViewShellManager.hxx"
#include "helpids.h"
#include "sdpage.hxx"
#include "drawdoc.hxx"
#include "textapi.hxx"
#include "optsitem.hxx"
#define C2U(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
using ::rtl::OUString;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::document;
using namespace ::com::sun::star::geometry;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::view;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::ui;
using namespace ::com::sun::star::task;
using namespace ::com::sun::star::office;
namespace sd {
// --------------------------------------------------------------------
extern TextApiObject* getTextApiObject( const Reference< XAnnotation >& xAnnotation );
// --------------------------------------------------------------------
SfxItemPool* GetAnnotationPool()
{
static SfxItemPool* mpAnnotationPool = 0;
if( mpAnnotationPool == 0 )
{
mpAnnotationPool = EditEngine::CreatePool( sal_False );
mpAnnotationPool->SetPoolDefaultItem(SvxFontHeightItem(423,100,EE_CHAR_FONTHEIGHT));
Font aAppFont( Application::GetSettings().GetStyleSettings().GetAppFont() );
String EMPTYSTRING;
mpAnnotationPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamily(),aAppFont.GetName(), EMPTYSTRING,PITCH_DONTKNOW,RTL_TEXTENCODING_DONTKNOW,EE_CHAR_FONTINFO));
}
return mpAnnotationPool;
}
// --------------------------------------------------------------------
static SfxBindings* getBindings( ViewShellBase& rBase )
{
if( rBase.GetMainViewShell().get() && rBase.GetMainViewShell()->GetViewFrame() )
return &rBase.GetMainViewShell()->GetViewFrame()->GetBindings();
else
return 0;
}
// --------------------------------------------------------------------
static SfxDispatcher* getDispatcher( ViewShellBase& rBase )
{
if( rBase.GetMainViewShell().get() && rBase.GetMainViewShell()->GetViewFrame() )
return rBase.GetMainViewShell()->GetViewFrame()->GetDispatcher();
else
return 0;
}
com::sun::star::util::DateTime getCurrentDateTime()
{
DateTime aCurrentDate;
return com::sun::star::util::DateTime( 0, aCurrentDate.GetSec(), aCurrentDate.GetMin(), aCurrentDate.GetHour(), aCurrentDate.GetDay(), aCurrentDate.GetMonth(), aCurrentDate.GetYear() );
}
OUString getAnnotationDateTimeString( const Reference< XAnnotation >& xAnnotation )
{
OUString sRet;
if( xAnnotation.is() )
{
const LocaleDataWrapper& rLocalData = SvtSysLocale().GetLocaleData();
com::sun::star::util::DateTime aDateTime( xAnnotation->getDateTime() );
Date aDate = Date( aDateTime.Day, aDateTime.Month, aDateTime.Year );
if (aDate==Date())
sRet = sRet + String(SdResId(STR_ANNOTATION_TODAY));
else
if (aDate == Date(Date()-1))
sRet = sRet + String(SdResId(STR_ANNOTATION_YESTERDAY));
else
if (aDate.IsValid() )
sRet = sRet + rLocalData.getDate(aDate);
Time aTime( aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds, aDateTime.HundredthSeconds );
if(aTime.GetTime() != 0)
sRet = sRet + rtl::OUString::createFromAscii(" ") + rLocalData.getTime( aTime,false );
}
return sRet;
}
// --------------------------------------------------------------------
AnnotationManagerImpl::AnnotationManagerImpl( ViewShellBase& rViewShellBase )
: AnnotationManagerImplBase( m_aMutex )
, mrBase( rViewShellBase )
, mpDoc( rViewShellBase.GetDocument() )
, mbShowAnnotations( true )
, mnUpdateTagsEvent( 0 )
{
SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType());
if( pOptions )
mbShowAnnotations = pOptions->IsShowComments() == sal_True;
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::init()
{
// get current controller and initialize listeners
try
{
addListener();
mxView = Reference< XDrawView >::query(mrBase.GetController());
}
catch( Exception& e )
{
(void)e;
DBG_ERROR( "sd::AnnotationManagerImpl::AnnotationManagerImpl(), Exception caught!" );
}
try
{
Reference<XEventBroadcaster> xModel (mrBase.GetDocShell()->GetModel(), UNO_QUERY_THROW );
Reference<XEventListener> xListener( this );
xModel->addEventListener( xListener );
}
catch( Exception& )
{
}
}
// --------------------------------------------------------------------
// WeakComponentImplHelper1
void SAL_CALL AnnotationManagerImpl::disposing ()
{
try
{
Reference<XEventBroadcaster> xModel (mrBase.GetDocShell()->GetModel(), UNO_QUERY_THROW );
Reference<XEventListener> xListener( this );
xModel->removeEventListener( xListener );
}
catch( Exception& )
{
}
removeListener();
DisposeTags();
if( mnUpdateTagsEvent )
{
Application::RemoveUserEvent( mnUpdateTagsEvent );
mnUpdateTagsEvent = 0;
}
mxView.clear();
mxCurrentPage.clear();
}
// --------------------------------------------------------------------
// XEventListener
void SAL_CALL AnnotationManagerImpl::notifyEvent( const ::com::sun::star::document::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException)
{
if( aEvent.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnAnnotationInserted") ) ||
aEvent.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnAnnotationRemoved") ) ||
aEvent.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnAnnotationChanged" )) )
{
UpdateTags();
}
}
void SAL_CALL AnnotationManagerImpl::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException)
{
}
void AnnotationManagerImpl::ShowAnnotations( bool bShow )
{
// enforce show annotations if a new annotation is inserted
if( mbShowAnnotations != bShow )
{
mbShowAnnotations = bShow;
SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType());
if( pOptions )
pOptions->SetShowComments( mbShowAnnotations ? sal_True : sal_False );
UpdateTags();
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::ExecuteAnnotation(SfxRequest& rReq )
{
switch( rReq.GetSlot() )
{
case SID_INSERT_POSTIT:
ExecuteInsertAnnotation( rReq );
break;
case SID_DELETE_POSTIT:
case SID_DELETEALL_POSTIT:
case SID_DELETEALLBYAUTHOR_POSTIT:
ExecuteDeleteAnnotation( rReq );
break;
case SID_PREVIOUS_POSTIT:
case SID_NEXT_POSTIT:
SelectNextAnnotation( rReq.GetSlot() == SID_NEXT_POSTIT );
break;
case SID_REPLYTO_POSTIT:
ExecuteReplyToAnnotation( rReq );
break;
case SID_SHOW_POSTIT:
ShowAnnotations( !mbShowAnnotations );
break;
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::ExecuteInsertAnnotation(SfxRequest& /*rReq*/)
{
ShowAnnotations(true);
InsertAnnotation();
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::ExecuteDeleteAnnotation(SfxRequest& rReq)
{
ShowAnnotations( true );
const SfxItemSet* pArgs = rReq.GetArgs();
switch( rReq.GetSlot() )
{
case SID_DELETEALL_POSTIT:
DeleteAllAnnotations();
break;
case SID_DELETEALLBYAUTHOR_POSTIT:
if( pArgs )
{
const SfxPoolItem* pPoolItem = NULL;
if( SFX_ITEM_SET == pArgs->GetItemState( SID_DELETEALLBYAUTHOR_POSTIT, sal_True, &pPoolItem ) )
{
OUString sAuthor( (( const SfxStringItem* ) pPoolItem )->GetValue() );
DeleteAnnotationsByAuthor( sAuthor );
}
}
break;
case SID_DELETE_POSTIT:
{
Reference< XAnnotation > xAnnotation;
if( rReq.GetSlot() == SID_DELETE_POSTIT )
{
if( pArgs )
{
const SfxPoolItem* pPoolItem = NULL;
if( SFX_ITEM_SET == pArgs->GetItemState( SID_DELETE_POSTIT, sal_True, &pPoolItem ) )
( ( const SfxUnoAnyItem* ) pPoolItem )->GetValue() >>= xAnnotation;
}
}
if( !xAnnotation.is() )
GetSelectedAnnotation( xAnnotation );
DeleteAnnotation( xAnnotation );
}
break;
}
UpdateTags();
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::InsertAnnotation()
{
SdPage* pPage = GetCurrentPage();
if( pPage )
{
if( mpDoc->IsUndoEnabled() )
mpDoc->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_INSERT ) ) );
// find free space for new annotation
int y = 0, x = 0;
AnnotationVector aAnnotations( pPage->getAnnotations() );
if( !aAnnotations.empty() )
{
const int page_width = pPage->GetSize().Width();
const int width = 1000;
const int height = 800;
Rectangle aTagRect;
while( true )
{
Rectangle aNewRect( x, y, x + width - 1, y + height - 1 );
bool bFree = true;
for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); iter++ )
{
RealPoint2D aPoint( (*iter)->getPosition() );
aTagRect.nLeft = sal::static_int_cast< long >( aPoint.X * 100.0 );
aTagRect.nTop = sal::static_int_cast< long >( aPoint.Y * 100.0 );
aTagRect.nRight = aTagRect.nLeft + width - 1;
aTagRect.nBottom = aTagRect.nTop + height - 1;
if( aNewRect.IsOver( aTagRect ) )
{
bFree = false;
break;
}
}
if( bFree == false)
{
x += width;
if( x > page_width )
{
x = 0;
y += height;
}
}
else
{
break;
}
}
}
Reference< XAnnotation > xAnnotation;
pPage->createAnnotation( xAnnotation );
// set current author to new annotation
SvtUserOptions aUserOptions;
xAnnotation->setAuthor( aUserOptions.GetFullName() );
// set current time to new annotation
xAnnotation->setDateTime( getCurrentDateTime() );
// set position
RealPoint2D aPos( ((double)x) / 100.0, ((double)y) / 100.0 );
xAnnotation->setPosition( aPos );
if( mpDoc->IsUndoEnabled() )
mpDoc->EndUndo();
UpdateTags(true);
SelectAnnotation( xAnnotation, true );
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::ExecuteReplyToAnnotation( SfxRequest& rReq )
{
Reference< XAnnotation > xAnnotation;
const SfxItemSet* pArgs = rReq.GetArgs();
if( pArgs )
{
const SfxPoolItem* pPoolItem = NULL;
if( SFX_ITEM_SET == pArgs->GetItemState( rReq.GetSlot(), sal_True, &pPoolItem ) )
( ( const SfxUnoAnyItem* ) pPoolItem )->GetValue() >>= xAnnotation;
}
TextApiObject* pTextApi = getTextApiObject( xAnnotation );
if( pTextApi )
{
std::auto_ptr< ::Outliner > pOutliner( new ::Outliner(GetAnnotationPool(),OUTLINERMODE_TEXTOBJECT) );
mpDoc->SetCalcFieldValueHdl( pOutliner.get() );
pOutliner->SetUpdateMode( sal_True );
String aStr(SdResId(STR_ANNOTATION_REPLY));
OUString sAuthor( xAnnotation->getAuthor() );
if( sAuthor.getLength() == 0 )
sAuthor = String( SdResId( STR_ANNOTATION_NOAUTHOR ) );
aStr.SearchAndReplaceAscii("%1", sAuthor);
aStr.Append( String(RTL_CONSTASCII_USTRINGPARAM(" (") ) );
aStr.Append( String( getAnnotationDateTimeString( xAnnotation ) ) );
aStr.Append( String(RTL_CONSTASCII_USTRINGPARAM("): \"") ) );
String sQuote( pTextApi->GetText() );
if( sQuote.Len() == 0 )
sQuote = String( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
aStr.Append( sQuote );
aStr.Append( String(RTL_CONSTASCII_USTRINGPARAM("\"\n") ) );
sal_uInt16 nParaCount = aStr.GetTokenCount( '\n' );
for( sal_uInt16 nPara = 0; nPara < nParaCount; nPara++ )
pOutliner->Insert( aStr.GetToken( nPara, '\n' ), LIST_APPEND, -1 );
if( pOutliner->GetParagraphCount() > 1 )
{
SfxItemSet aAnswerSet( pOutliner->GetEmptyItemSet() );
aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC));
ESelection aSel;
aSel.nEndPara = (sal_uInt16)pOutliner->GetParagraphCount()-2;
aSel.nEndPos = pOutliner->GetText( pOutliner->GetParagraph( aSel.nEndPara ) ).Len();
pOutliner->QuickSetAttribs( aAnswerSet, aSel );
}
std::auto_ptr< OutlinerParaObject > pOPO( pOutliner->CreateParaObject() );
pTextApi->SetText( *pOPO.get() );
SvtUserOptions aUserOptions;
xAnnotation->setAuthor( aUserOptions.GetFullName() );
// set current time to reply
xAnnotation->setDateTime( getCurrentDateTime() );
UpdateTags(true);
SelectAnnotation( xAnnotation, true );
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::DeleteAnnotation( Reference< XAnnotation > xAnnotation )
{
SdPage* pPage = GetCurrentPage();
if( xAnnotation.is() && pPage )
{
if( mpDoc->IsUndoEnabled() )
mpDoc->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_DELETE ) ) );
pPage->removeAnnotation( xAnnotation );
if( mpDoc->IsUndoEnabled() )
mpDoc->EndUndo();
UpdateTags();
}
}
void AnnotationManagerImpl::DeleteAnnotationsByAuthor( const rtl::OUString& sAuthor )
{
if( mpDoc->IsUndoEnabled() )
mpDoc->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_DELETE ) ) );
SdPage* pPage = 0;
do
{
pPage = GetNextPage( pPage, true );
if( pPage && !pPage->getAnnotations().empty() )
{
AnnotationVector aAnnotations( pPage->getAnnotations() );
for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); iter++ )
{
Reference< XAnnotation > xAnnotation( *iter );
if( xAnnotation->getAuthor() == sAuthor )
{
if( mxSelectedAnnotation == xAnnotation )
mxSelectedAnnotation.clear();
pPage->removeAnnotation( xAnnotation );
}
}
}
} while( pPage );
if( mpDoc->IsUndoEnabled() )
mpDoc->EndUndo();
}
void AnnotationManagerImpl::DeleteAllAnnotations()
{
if( mpDoc->IsUndoEnabled() )
mpDoc->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_DELETE ) ) );
SdPage* pPage = 0;
do
{
pPage = GetNextPage( pPage, true );
if( pPage && !pPage->getAnnotations().empty() )
{
AnnotationVector aAnnotations( pPage->getAnnotations() );
for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); iter++ )
{
pPage->removeAnnotation( (*iter) );
}
}
}
while( pPage );
mxSelectedAnnotation.clear();
if( mpDoc->IsUndoEnabled() )
mpDoc->EndUndo();
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::GetAnnotationState(SfxItemSet& rSet)
{
SdPage* pCurrentPage = GetCurrentPage();
const bool bReadOnly = mrBase.GetDocShell()->IsReadOnly();
const bool bWrongPageKind = (pCurrentPage == 0) || (pCurrentPage->GetPageKind() != PK_STANDARD);
const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion( SvtSaveOptions().GetODFDefaultVersion() );
if( bReadOnly || bWrongPageKind || (nCurrentODFVersion != SvtSaveOptions::ODFVER_LATEST) )
rSet.DisableItem( SID_INSERT_POSTIT );
rSet.Put(SfxBoolItem(SID_SHOW_POSTIT, mbShowAnnotations));
Reference< XAnnotation > xAnnotation;
GetSelectedAnnotation( xAnnotation );
if( !xAnnotation.is() || bReadOnly )
rSet.DisableItem( SID_DELETE_POSTIT );
SdPage* pPage = 0;
bool bHasAnnotations = false;
do
{
pPage = GetNextPage( pPage, true );
if( pPage && !pPage->getAnnotations().empty() )
bHasAnnotations = true;
}
while( pPage && !bHasAnnotations );
if( !bHasAnnotations || bReadOnly )
{
rSet.DisableItem( SID_DELETEALL_POSTIT );
}
if( bWrongPageKind || !bHasAnnotations )
{
rSet.DisableItem( SID_PREVIOUS_POSTIT );
rSet.DisableItem( SID_NEXT_POSTIT );
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::SelectNextAnnotation(bool bForeward)
{
ShowAnnotations( true );
Reference< XAnnotation > xCurrent;
GetSelectedAnnotation( xCurrent );
SdPage* pPage = GetCurrentPage();
if( !pPage )
return;
AnnotationVector aAnnotations( pPage->getAnnotations() );
if( bForeward )
{
if( xCurrent.is() )
{
for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); iter++ )
{
if( (*iter) == xCurrent )
{
iter++;
if( iter != aAnnotations.end() )
{
SelectAnnotation( (*iter) );
return;
}
break;
}
}
}
else if( !aAnnotations.empty() )
{
SelectAnnotation( *(aAnnotations.begin()) );
return;
}
}
else
{
if( xCurrent.is() )
{
for( AnnotationVector::iterator iter = aAnnotations.begin(); iter != aAnnotations.end(); iter++ )
{
if( (*iter) == xCurrent )
{
if( iter != aAnnotations.begin() )
{
iter--;
SelectAnnotation( (*iter) );
return;
}
break;
}
}
}
else if( !aAnnotations.empty() )
{
AnnotationVector::iterator iter( aAnnotations.end() );
SelectAnnotation( *(--iter) );
return;
}
}
mxSelectedAnnotation.clear();
do
{
do
{
pPage = GetNextPage( pPage, bForeward );
if( pPage && !pPage->getAnnotations().empty() )
{
// switch to next/previous slide with annotations
::boost::shared_ptr<DrawViewShell> pDrawViewShell(::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell()));
if (pDrawViewShell.get() != NULL)
{
pDrawViewShell->ChangeEditMode(pPage->IsMasterPage() ? EM_MASTERPAGE : EM_PAGE, sal_False);
pDrawViewShell->SwitchPage((pPage->GetPageNum() - 1) >> 1);
SfxDispatcher* pDispatcher = getDispatcher( mrBase );
if( pDispatcher )
pDispatcher->Execute( bForeward ? SID_NEXT_POSTIT : SID_PREVIOUS_POSTIT );
return;
}
}
}
while( pPage );
// The question text depends on the search direction.
bool bImpress = mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS;
sal_uInt16 nStringId;
if(bForeward)
nStringId = bImpress ? STR_ANNOTATION_WRAP_FORWARD : STR_ANNOTATION_WRAP_FORWARD_DRAW;
else
nStringId = bImpress ? STR_ANNOTATION_WRAP_BACKWARD : STR_ANNOTATION_WRAP_BACKWARD_DRAW;
// Pop up question box that asks the user whether to wrap arround.
// The dialog is made modal with respect to the whole application.
QueryBox aQuestionBox (
NULL,
WB_YES_NO | WB_DEF_YES,
String(SdResId(nStringId)));
aQuestionBox.SetImage (QueryBox::GetStandardImage());
sal_uInt16 nBoxResult = aQuestionBox.Execute();
if(nBoxResult != BUTTONID_YES)
break;
}
while( true );
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::onTagSelected( AnnotationTag& rTag )
{
mxSelectedAnnotation = rTag.GetAnnotation();
invalidateSlots();
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::onTagDeselected( AnnotationTag& rTag )
{
if( rTag.GetAnnotation() == mxSelectedAnnotation )
{
mxSelectedAnnotation.clear();
invalidateSlots();
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::SelectAnnotation( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation > xAnnotation, bool bEdit /* = sal_False */ )
{
mxSelectedAnnotation = xAnnotation;
for( AnnotationTagVector::iterator iter( maTagVector.begin() ); iter != maTagVector.end(); iter++ )
{
if( (*iter)->GetAnnotation() == xAnnotation )
{
SmartTagReference xTag( (*iter).get() );
mrBase.GetMainViewShell()->GetView()->getSmartTags().select( xTag );
(*iter)->OpenPopup( bEdit );
break;
}
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::GetSelectedAnnotation( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation >& xAnnotation )
{
xAnnotation = mxSelectedAnnotation;
}
void AnnotationManagerImpl::invalidateSlots()
{
SfxBindings* pBindings = getBindings( mrBase );
if( pBindings )
{
pBindings->Invalidate( SID_INSERT_POSTIT );
pBindings->Invalidate( SID_DELETE_POSTIT );
pBindings->Invalidate( SID_DELETEALL_POSTIT );
pBindings->Invalidate( SID_PREVIOUS_POSTIT );
pBindings->Invalidate( SID_NEXT_POSTIT );
pBindings->Invalidate( SID_UNDO );
pBindings->Invalidate( SID_REDO );
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::onSelectionChanged()
{
if( mxView.is() && mrBase.GetDrawView() ) try
{
Reference< XAnnotationAccess > xPage( mxView->getCurrentPage(), UNO_QUERY );
if( xPage != mxCurrentPage )
{
mxCurrentPage = xPage;
UpdateTags(true);
}
}
catch( Exception& )
{
DBG_ERROR( "sd::AnnotationManagerImpl::onSelectionChanged(), exception caught!" );
}
}
void AnnotationManagerImpl::UpdateTags( bool bSynchron )
{
if( bSynchron )
{
if( mnUpdateTagsEvent )
Application::RemoveUserEvent( mnUpdateTagsEvent );
UpdateTagsHdl(0);
}
else
{
if( !mnUpdateTagsEvent && mxView.is() )
mnUpdateTagsEvent = Application::PostUserEvent( LINK( this, AnnotationManagerImpl, UpdateTagsHdl ) );
}
}
IMPL_LINK(AnnotationManagerImpl,UpdateTagsHdl, void *, EMPTYARG)
{
mnUpdateTagsEvent = 0;
DisposeTags();
if( mbShowAnnotations )
CreateTags();
if( mrBase.GetDrawView() )
static_cast< ::sd::View* >( mrBase.GetDrawView() )->updateHandles();
invalidateSlots();
return 0;
}
void AnnotationManagerImpl::CreateTags()
{
if( mxCurrentPage.is() && mpDoc ) try
{
int nIndex = 1;
maFont = Application::GetSettings().GetStyleSettings().GetAppFont();
rtl::Reference< AnnotationTag > xSelectedTag;
Reference< XAnnotationEnumeration > xEnum( mxCurrentPage->createAnnotationEnumeration() );
while( xEnum->hasMoreElements() )
{
Reference< XAnnotation > xAnnotation( xEnum->nextElement() );
Color aColor( GetColorLight( mpDoc->GetAnnotationAuthorIndex( xAnnotation->getAuthor() ) ) );
rtl::Reference< AnnotationTag > xTag( new AnnotationTag( *this, *mrBase.GetMainViewShell()->GetView(), xAnnotation, aColor, nIndex++, maFont ) );
maTagVector.push_back(xTag);
if( xAnnotation == mxSelectedAnnotation )
{
xSelectedTag = xTag;
}
}
if( xSelectedTag.is() )
{
SmartTagReference xTag( xSelectedTag.get() );
mrBase.GetMainViewShell()->GetView()->getSmartTags().select( xTag );
}
else
{
// no tag, no selection!
mxSelectedAnnotation.clear();
}
}
catch( Exception& )
{
DBG_ERROR( "sd::AnnotationManagerImpl::onSelectionChanged(), exception caught!" );
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::DisposeTags()
{
if( !maTagVector.empty() )
{
AnnotationTagVector::iterator iter = maTagVector.begin();
do
{
(*iter++)->Dispose();
}
while( iter != maTagVector.end() );
maTagVector.clear();
}
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::addListener()
{
Link aLink( LINK(this,AnnotationManagerImpl,EventMultiplexerListener) );
mrBase.GetEventMultiplexer()->AddEventListener (
aLink,
tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
| tools::EventMultiplexerEvent::EID_CURRENT_PAGE
| tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
| tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED);
}
// --------------------------------------------------------------------
void AnnotationManagerImpl::removeListener()
{
Link aLink( LINK(this,AnnotationManagerImpl,EventMultiplexerListener) );
mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
}
// --------------------------------------------------------------------
IMPL_LINK(AnnotationManagerImpl,EventMultiplexerListener,
tools::EventMultiplexerEvent*,pEvent)
{
switch (pEvent->meEventId)
{
case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
case tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION:
onSelectionChanged();
break;
case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
mxView = Reference<XDrawView>();
onSelectionChanged();
break;
case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
mxView = Reference<XDrawView>::query( mrBase.GetController() );
onSelectionChanged();
break;
}
return 0;
}
#if 0
OUString AnnotationManagerImpl::GetHelpText( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation >& xAnnotation )
{
OUString sRet;
if( xAnnotation.is() )
{
OUString sAuthor( xAnnotation->getAuthor() );
if( sAuthor.getLength() != 0 )
{
sRet += sAuthor;
}
sRet += OUString( RTL_CONSTASCII_USTRINGPARAM( " [" ) );
sRet += getAnnotationDateTimeString( xAnnotation );
sRet += OUString( RTL_CONSTASCII_USTRINGPARAM( "]\n" ) );
Reference< XText > xText( xAnnotation->getTextRange() );
if( xText.is() )
sRet += xText->getString();
}
return sRet;
}
#endif
void AnnotationManagerImpl::ExecuteAnnotationContextMenu( Reference< XAnnotation > xAnnotation, ::Window* pParent, const Rectangle& rContextRect, bool bButtonMenu /* = false */ )
{
SfxDispatcher* pDispatcher( getDispatcher( mrBase ) );
if( !pDispatcher )
return;
const bool bReadOnly = mrBase.GetDocShell()->IsReadOnly();
AnnotationWindow* pAnnotationWindow = bButtonMenu ? 0 : dynamic_cast< AnnotationWindow* >( pParent );
if( bReadOnly && !pAnnotationWindow )
return;
std::auto_ptr< PopupMenu > pMenu( new PopupMenu( SdResId( pAnnotationWindow ? RID_ANNOTATION_CONTEXTMENU : RID_ANNOTATION_TAG_CONTEXTMENU ) ) );
SvtUserOptions aUserOptions;
OUString sCurrentAuthor( aUserOptions.GetFullName() );
OUString sAuthor( xAnnotation->getAuthor() );
String aStr( pMenu->GetItemText( SID_DELETEALLBYAUTHOR_POSTIT ) ), aReplace( sAuthor );
if( aReplace.Len() == 0 )
aReplace = String( SdResId( STR_ANNOTATION_NOAUTHOR ) );
aStr.SearchAndReplaceAscii("%1", aReplace);
pMenu->SetItemText( SID_DELETEALLBYAUTHOR_POSTIT, aStr );
pMenu->EnableItem( SID_REPLYTO_POSTIT, (sAuthor != sCurrentAuthor) && !bReadOnly );
pMenu->EnableItem( SID_DELETE_POSTIT, (xAnnotation.is() && !bReadOnly) ? sal_True : sal_False );
pMenu->EnableItem( SID_DELETEALLBYAUTHOR_POSTIT, !bReadOnly );
pMenu->EnableItem( SID_DELETEALL_POSTIT, !bReadOnly );
if( pAnnotationWindow )
{
if( pAnnotationWindow->IsProtected() || bReadOnly )
{
pMenu->EnableItem( SID_ATTR_CHAR_WEIGHT, sal_False );
pMenu->EnableItem( SID_ATTR_CHAR_POSTURE, sal_False );
pMenu->EnableItem( SID_ATTR_CHAR_UNDERLINE, sal_False );
pMenu->EnableItem( SID_ATTR_CHAR_STRIKEOUT, sal_False );
pMenu->EnableItem( SID_PASTE, sal_False );
}
else
{
SfxItemSet aSet(pAnnotationWindow->getView()->GetAttribs());
if ( aSet.GetItemState( EE_CHAR_WEIGHT ) == SFX_ITEM_ON )
{
if( ((const SvxWeightItem&)aSet.Get( EE_CHAR_WEIGHT )).GetWeight() == WEIGHT_BOLD )
pMenu->CheckItem( SID_ATTR_CHAR_WEIGHT );
}
if ( aSet.GetItemState( EE_CHAR_ITALIC ) == SFX_ITEM_ON )
{
if( ((const SvxPostureItem&)aSet.Get( EE_CHAR_ITALIC )).GetPosture() != ITALIC_NONE )
pMenu->CheckItem( SID_ATTR_CHAR_POSTURE );
}
if ( aSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON )
{
if( ((const SvxUnderlineItem&)aSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() != UNDERLINE_NONE )
pMenu->CheckItem( SID_ATTR_CHAR_UNDERLINE );
}
if ( aSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON )
{
if( ((const SvxCrossedOutItem&)aSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() != STRIKEOUT_NONE )
pMenu->CheckItem( SID_ATTR_CHAR_STRIKEOUT );
}
TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pAnnotationWindow ) );
pMenu->EnableItem( SID_PASTE, aDataHelper.GetFormatCount() != 0 );
}
pMenu->EnableItem( SID_COPY, pAnnotationWindow->getView()->HasSelection() );
}
sal_uInt16 nId = 0;
// set slot images
Reference< ::com::sun::star::frame::XFrame > xFrame( mrBase.GetMainViewShell()->GetViewFrame()->GetFrame().GetFrameInterface() );
if( xFrame.is() )
{
const bool bHighContrast = Application::GetSettings().GetStyleSettings().GetHighContrastMode();
for( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
{
nId = pMenu->GetItemId( nPos );
if( pMenu->IsItemEnabled( nId ) )
{
OUString sSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
sSlotURL += OUString::valueOf( sal_Int32( nId ));
Image aImage( GetImage( xFrame, sSlotURL, false, bHighContrast ) );
if( !!aImage )
pMenu->SetItemImage( nId, aImage );
}
}
}
nId = pMenu->Execute( pParent, rContextRect, POPUPMENU_EXECUTE_DOWN|POPUPMENU_NOMOUSEUPCLOSE );
switch( nId )
{
case SID_REPLYTO_POSTIT:
{
const SfxUnoAnyItem aItem( SID_REPLYTO_POSTIT, Any( xAnnotation ) );
pDispatcher->Execute( SID_REPLYTO_POSTIT, SFX_CALLMODE_ASYNCHRON, &aItem, 0 );
break;
}
case SID_DELETE_POSTIT:
{
const SfxUnoAnyItem aItem( SID_DELETE_POSTIT, Any( xAnnotation ) );
pDispatcher->Execute( SID_DELETE_POSTIT, SFX_CALLMODE_ASYNCHRON, &aItem, 0 );
break;
}
case SID_DELETEALLBYAUTHOR_POSTIT:
{
const SfxStringItem aItem( SID_DELETEALLBYAUTHOR_POSTIT, sAuthor );
pDispatcher->Execute( SID_DELETEALLBYAUTHOR_POSTIT, SFX_CALLMODE_ASYNCHRON, &aItem, 0 );
break;
}
case SID_DELETEALL_POSTIT:
pDispatcher->Execute( SID_DELETEALL_POSTIT );
break;
case SID_COPY:
case SID_PASTE:
case SID_ATTR_CHAR_WEIGHT:
case SID_ATTR_CHAR_POSTURE:
case SID_ATTR_CHAR_UNDERLINE:
case SID_ATTR_CHAR_STRIKEOUT:
if( pAnnotationWindow )
pAnnotationWindow->ExecuteSlot( nId );
break;
}
}
// ====================================================================
Color AnnotationManagerImpl::GetColor(sal_uInt16 aAuthorIndex)
{
if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
{
static const Color aArrayNormal[] = {
COL_AUTHOR1_NORMAL, COL_AUTHOR2_NORMAL, COL_AUTHOR3_NORMAL,
COL_AUTHOR4_NORMAL, COL_AUTHOR5_NORMAL, COL_AUTHOR6_NORMAL,
COL_AUTHOR7_NORMAL, COL_AUTHOR8_NORMAL, COL_AUTHOR9_NORMAL };
return Color( aArrayNormal[ aAuthorIndex % (sizeof( aArrayNormal )/ sizeof( aArrayNormal[0] ))]);
}
else
return Color(COL_WHITE);
}
Color AnnotationManagerImpl::GetColorLight(sal_uInt16 aAuthorIndex)
{
if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
{
static const Color aArrayLight[] = {
COL_AUTHOR1_LIGHT, COL_AUTHOR2_LIGHT, COL_AUTHOR3_LIGHT,
COL_AUTHOR4_LIGHT, COL_AUTHOR5_LIGHT, COL_AUTHOR6_LIGHT,
COL_AUTHOR7_LIGHT, COL_AUTHOR8_LIGHT, COL_AUTHOR9_LIGHT };
return Color( aArrayLight[ aAuthorIndex % (sizeof( aArrayLight )/ sizeof( aArrayLight[0] ))]);
}
else
return Color(COL_WHITE);
}
Color AnnotationManagerImpl::GetColorDark(sal_uInt16 aAuthorIndex)
{
if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
{
static const Color aArrayAnkor[] = {
COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK,
COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK,
COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK };
return Color( aArrayAnkor[ aAuthorIndex % (sizeof( aArrayAnkor ) / sizeof( aArrayAnkor[0] ))]);
}
else
return Color(COL_WHITE);
}
SdPage* AnnotationManagerImpl::GetNextPage( SdPage* pPage, bool bForeward )
{
if( pPage == 0 )
return bForeward ? GetFirstPage() : GetLastPage();
sal_uInt16 nPageNum = (pPage->GetPageNum() - 1) >> 1;
// first all non master pages
if( !pPage->IsMasterPage() )
{
if( bForeward )
{
if( nPageNum >= mpDoc->GetSdPageCount(PK_STANDARD)-1 )
{
// we reached end of draw pages, start with master pages (skip handout master for draw)
return mpDoc->GetMasterSdPage( (mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS) ? 0 : 1, PK_STANDARD );
}
nPageNum++;
}
else
{
if( nPageNum == 0 )
return 0; // we are already on the first draw page, finished
nPageNum--;
}
return mpDoc->GetSdPage(nPageNum, PK_STANDARD);
}
else
{
if( bForeward )
{
if( nPageNum >= mpDoc->GetMasterSdPageCount(PK_STANDARD)-1 )
{
return 0; // we reached the end, there is nothing more to see here
}
nPageNum++;
}
else
{
if( nPageNum == (mpDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS) ? 0 : 1 )
{
// we reached beginning of master pages, start with end if pages
return mpDoc->GetSdPage( mpDoc->GetSdPageCount(PK_STANDARD)-1, PK_STANDARD );
}
nPageNum--;
}
return mpDoc->GetMasterSdPage(nPageNum,PK_STANDARD);
}
}
SdPage* AnnotationManagerImpl::GetFirstPage()
{
// return first drawing page
return mpDoc->GetSdPage(0, PK_STANDARD );
}
SdPage* AnnotationManagerImpl::GetLastPage()
{
return mpDoc->GetMasterSdPage( mpDoc->GetMasterSdPageCount(PK_STANDARD) - 1, PK_STANDARD );
}
SdPage* AnnotationManagerImpl::GetCurrentPage()
{
/*
::boost::shared_ptr<DrawViewShell> pDrawViewShell(::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell()));
if (pDrawViewShell.get() != NULL)
return pDrawViewShell->GetActualPage();
*/
return mrBase.GetMainViewShell()->getCurrentPage();
}
// ====================================================================
AnnotationManager::AnnotationManager( ViewShellBase& rViewShellBase )
: mxImpl( new AnnotationManagerImpl( rViewShellBase ) )
{
mxImpl->init();
}
AnnotationManager::~AnnotationManager()
{
mxImpl->dispose();
}
void AnnotationManager::ExecuteAnnotation(SfxRequest& rRequest)
{
mxImpl->ExecuteAnnotation( rRequest );
}
void AnnotationManager::GetAnnotationState(SfxItemSet& rItemSet)
{
mxImpl->GetAnnotationState(rItemSet);
}
}