1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
30 
31 #include "osl/time.h"
32 #include "sal/config.h"
33 
34 #include <com/sun/star/uno/XComponentContext.hpp>
35 #include <com/sun/star/office/XAnnotation.hpp>
36 #include <com/sun/star/drawing/XDrawPage.hpp>
37 
38 #include <comphelper/processfactory.hxx>
39 #include <cppuhelper/propertysetmixin.hxx>
40 #include <cppuhelper/compbase1.hxx>
41 #include <cppuhelper/basemutex.hxx>
42 
43 #include "drawdoc.hxx"
44 #include "sdpage.hxx"
45 #include "textapi.hxx"
46 
47 using ::rtl::OUString;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::lang;
50 using namespace ::com::sun::star::beans;
51 using namespace ::com::sun::star::office;
52 using namespace ::com::sun::star::drawing;
53 using namespace ::com::sun::star::geometry;
54 using namespace ::com::sun::star::text;
55 using namespace ::com::sun::star::util;
56 using namespace ::com::sun::star;
57 
58 extern void NotifyDocumentEvent( SdDrawDocument* pDocument, const rtl::OUString& rEventName, const Reference< XInterface >& xSource );
59 
60 namespace sd {
61 
62 class Annotation : private ::cppu::BaseMutex,
63 				   public ::cppu::WeakComponentImplHelper1< XAnnotation>,
64 				   public ::cppu::PropertySetMixin< XAnnotation >
65 {
66 public:
67     explicit Annotation( const Reference< XComponentContext >& context, SdPage* pPage );
68 
69     SdPage* GetPage() const { return mpPage; }
70     SdrModel* GetModel() { return (mpPage != 0) ? mpPage->GetModel() : 0; }
71 
72     // XInterface:
73     virtual Any SAL_CALL queryInterface(Type const & type) throw (RuntimeException);
74     virtual void SAL_CALL acquire() throw () { ::cppu::WeakComponentImplHelper1< XAnnotation >::acquire(); }
75     virtual void SAL_CALL release() throw () { ::cppu::WeakComponentImplHelper1< XAnnotation >::release(); }
76 
77     // ::com::sun::star::beans::XPropertySet:
78     virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() throw (RuntimeException);
79     virtual void SAL_CALL setPropertyValue(const OUString & aPropertyName, const Any & aValue) throw (RuntimeException, UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException);
80     virtual Any SAL_CALL getPropertyValue(const OUString & PropertyName) throw (RuntimeException, UnknownPropertyException, WrappedTargetException);
81     virtual void SAL_CALL addPropertyChangeListener(const OUString & aPropertyName, const Reference< XPropertyChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException);
82     virtual void SAL_CALL removePropertyChangeListener(const OUString & aPropertyName, const Reference< XPropertyChangeListener > & aListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException);
83     virtual void SAL_CALL addVetoableChangeListener(const OUString & PropertyName, const Reference< XVetoableChangeListener > & aListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException);
84     virtual void SAL_CALL removeVetoableChangeListener(const OUString & PropertyName, const Reference< XVetoableChangeListener > & aListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException);
85 
86     // ::com::sun::star::office::XAnnotation:
87     virtual ::com::sun::star::uno::Any SAL_CALL getAnchor() throw (::com::sun::star::uno::RuntimeException);
88     virtual RealPoint2D SAL_CALL getPosition() throw (RuntimeException);
89     virtual void SAL_CALL setPosition(const RealPoint2D & the_value) throw (RuntimeException);
90     virtual ::com::sun::star::geometry::RealSize2D SAL_CALL getSize() throw (::com::sun::star::uno::RuntimeException);
91     virtual void SAL_CALL setSize( const ::com::sun::star::geometry::RealSize2D& _size ) throw (::com::sun::star::uno::RuntimeException);
92     virtual OUString SAL_CALL getAuthor() throw (RuntimeException);
93     virtual void SAL_CALL setAuthor(const OUString & the_value) throw (RuntimeException);
94     virtual util::DateTime SAL_CALL getDateTime() throw (RuntimeException);
95     virtual void SAL_CALL setDateTime(const util::DateTime & the_value) throw (RuntimeException);
96     virtual Reference< XText > SAL_CALL getTextRange() throw (RuntimeException);
97 
98 private:
99     Annotation(const Annotation &); // not defined
100     Annotation& operator=(const Annotation &); // not defined
101 
102     // destructor is private and will be called indirectly by the release call    virtual ~Annotation() {}
103 
104     void createChangeUndo();
105 
106     // overload WeakComponentImplHelperBase::disposing()
107     // This function is called upon disposing the component,
108     // if your component needs special work when it becomes
109     // disposed, do it here.
110     virtual void SAL_CALL disposing();
111 
112 	SdPage* mpPage;
113     Reference< XComponentContext > m_xContext;
114     mutable ::osl::Mutex m_aMutex;
115     RealPoint2D m_Position;
116     RealSize2D m_Size;
117     OUString m_Author;
118     util::DateTime m_DateTime;
119 	rtl::Reference< TextApiObject > m_TextRange;
120 };
121 
122 class UndoInsertOrRemoveAnnotation : public SdrUndoAction
123 {
124 public:
125 	UndoInsertOrRemoveAnnotation( Annotation& rAnnotation, bool bInsert );
126 
127 	virtual void Undo();
128 	virtual void Redo();
129 
130 protected:
131     rtl::Reference< Annotation > mxAnnotation;
132     bool mbInsert;
133     int mnIndex;
134 };
135 
136 struct AnnotationData
137 {
138     RealPoint2D m_Position;
139     RealSize2D m_Size;
140     OUString m_Author;
141     util::DateTime m_DateTime;
142 
143     void get( const rtl::Reference< Annotation >& xAnnotation )
144     {
145         m_Position = xAnnotation->getPosition();
146         m_Size = xAnnotation->getSize();
147         m_Author = xAnnotation->getAuthor();
148         m_DateTime = xAnnotation->getDateTime();
149     }
150 
151     void set( const rtl::Reference< Annotation >& xAnnotation )
152     {
153         xAnnotation->setPosition(m_Position);
154         xAnnotation->setSize(m_Size);
155         xAnnotation->setAuthor(m_Author);
156         xAnnotation->setDateTime(m_DateTime);
157     }
158 };
159 
160 class UndoAnnotation : public SdrUndoAction
161 {
162 public:
163 	UndoAnnotation( Annotation& rAnnotation );
164 
165 	virtual void Undo();
166 	virtual void Redo();
167 
168 protected:
169     rtl::Reference< Annotation > mxAnnotation;
170     AnnotationData maUndoData;
171     AnnotationData maRedoData;
172 };
173 
174 void createAnnotation( Reference< XAnnotation >& xAnnotation, SdPage* pPage )
175 {
176 	Reference<XComponentContext> xContext (comphelper_getProcessComponentContext());
177 	xAnnotation.set( new Annotation(xContext, pPage) );
178 	pPage->addAnnotation(xAnnotation);
179 }
180 
181 Annotation::Annotation( const Reference< XComponentContext >& context, SdPage* pPage )
182 : ::cppu::WeakComponentImplHelper1< XAnnotation >(m_aMutex)
183 , ::cppu::PropertySetMixin< XAnnotation >(context, static_cast< Implements >(IMPLEMENTS_PROPERTY_SET), Sequence< ::rtl::OUString >())
184 , mpPage( pPage )
185 {
186 }
187 
188 // overload WeakComponentImplHelperBase::disposing()
189 // This function is called upon disposing the component,
190 // if your component needs special work when it becomes
191 // disposed, do it here.
192 void SAL_CALL Annotation::disposing()
193 {
194 	mpPage = 0;
195 	if( m_TextRange.is() )
196 	{
197 		m_TextRange->dispose();
198 		m_TextRange.clear();
199 	}
200 }
201 
202 Any Annotation::queryInterface(Type const & type) throw (RuntimeException)
203 {
204     return ::cppu::WeakComponentImplHelper1< XAnnotation>::queryInterface(type);
205 }
206 
207 // com.sun.star.beans.XPropertySet:
208 Reference< XPropertySetInfo > SAL_CALL Annotation::getPropertySetInfo() throw (RuntimeException)
209 {
210     return ::cppu::PropertySetMixin< XAnnotation >::getPropertySetInfo();
211 }
212 
213 void SAL_CALL Annotation::setPropertyValue(const OUString & aPropertyName, const Any & aValue) throw (RuntimeException, UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException)
214 {
215     ::cppu::PropertySetMixin< XAnnotation >::setPropertyValue(aPropertyName, aValue);
216 }
217 
218 Any SAL_CALL Annotation::getPropertyValue(const OUString & aPropertyName) throw (RuntimeException, UnknownPropertyException, WrappedTargetException)
219 {
220     return ::cppu::PropertySetMixin< XAnnotation >::getPropertyValue(aPropertyName);
221 }
222 
223 void SAL_CALL Annotation::addPropertyChangeListener(const OUString & aPropertyName, const Reference< XPropertyChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException)
224 {
225     ::cppu::PropertySetMixin< XAnnotation >::addPropertyChangeListener(aPropertyName, xListener);
226 }
227 
228 void SAL_CALL Annotation::removePropertyChangeListener(const OUString & aPropertyName, const Reference< XPropertyChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException)
229 {
230     ::cppu::PropertySetMixin< XAnnotation >::removePropertyChangeListener(aPropertyName, xListener);
231 }
232 
233 void SAL_CALL Annotation::addVetoableChangeListener(const OUString & aPropertyName, const Reference< XVetoableChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException)
234 {
235     ::cppu::PropertySetMixin< XAnnotation >::addVetoableChangeListener(aPropertyName, xListener);
236 }
237 
238 void SAL_CALL Annotation::removeVetoableChangeListener(const OUString & aPropertyName, const Reference< XVetoableChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException)
239 {
240     ::cppu::PropertySetMixin< XAnnotation >::removeVetoableChangeListener(aPropertyName, xListener);
241 }
242 
243 Any SAL_CALL Annotation::getAnchor() throw (RuntimeException)
244 {
245     osl::MutexGuard g(m_aMutex);
246     Any aRet;
247     if( mpPage )
248     {
249         Reference< XDrawPage > xPage( mpPage->getUnoPage(), UNO_QUERY );
250         aRet <<= xPage;
251     }
252     return aRet;
253 }
254 
255 // ::com::sun::star::office::XAnnotation:
256 RealPoint2D SAL_CALL Annotation::getPosition() throw (RuntimeException)
257 {
258     osl::MutexGuard g(m_aMutex);
259     return m_Position;
260 }
261 
262 void SAL_CALL Annotation::setPosition(const RealPoint2D & the_value) throw (RuntimeException)
263 {
264     prepareSet(
265         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Position")),
266         Any(), Any(), 0);
267     {
268         osl::MutexGuard g(m_aMutex);
269         createChangeUndo();
270         m_Position = the_value;
271     }
272 }
273 
274 // ::com::sun::star::office::XAnnotation:
275 RealSize2D SAL_CALL Annotation::getSize() throw (RuntimeException)
276 {
277     osl::MutexGuard g(m_aMutex);
278     return m_Size;
279 }
280 
281 void SAL_CALL Annotation::setSize(const RealSize2D & the_value) throw (RuntimeException)
282 {
283     prepareSet(
284         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Size")),
285         Any(), Any(), 0);
286     {
287         osl::MutexGuard g(m_aMutex);
288         createChangeUndo();
289         m_Size = the_value;
290     }
291 }
292 
293 OUString SAL_CALL Annotation::getAuthor() throw (RuntimeException)
294 {
295     osl::MutexGuard g(m_aMutex);
296     return m_Author;
297 }
298 
299 void SAL_CALL Annotation::setAuthor(const OUString & the_value) throw (RuntimeException)
300 {
301     prepareSet(
302         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Author")),
303         Any(), Any(), 0);
304     {
305         osl::MutexGuard g(m_aMutex);
306         createChangeUndo();
307         m_Author = the_value;
308     }
309 }
310 
311 util::DateTime SAL_CALL Annotation::getDateTime() throw (RuntimeException)
312 {
313     osl::MutexGuard g(m_aMutex);
314     return m_DateTime;
315 }
316 
317 void SAL_CALL Annotation::setDateTime(const util::DateTime & the_value) throw (RuntimeException)
318 {
319     prepareSet(
320         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DateTime")),
321         Any(), Any(), 0);
322     {
323         osl::MutexGuard g(m_aMutex);
324         createChangeUndo();
325         m_DateTime = the_value;
326     }
327 }
328 
329 void Annotation::createChangeUndo()
330 {
331     SdrModel* pModel = GetModel();
332     if( pModel && pModel->IsUndoEnabled() )
333         pModel->AddUndo( new UndoAnnotation( *this ) );
334 
335     if( pModel )
336     {
337         pModel->SetChanged();
338         Reference< XInterface > xSource( static_cast<uno::XWeak*>( this ) );
339         NotifyDocumentEvent( static_cast< SdDrawDocument* >( pModel ), OUString( RTL_CONSTASCII_USTRINGPARAM("OnAnnotationChanged") ), xSource );
340     }
341 }
342 
343 Reference< XText > SAL_CALL Annotation::getTextRange() throw (RuntimeException)
344 {
345     osl::MutexGuard g(m_aMutex);
346 	if( !m_TextRange.is() && (mpPage != 0) )
347 	{
348 		m_TextRange = TextApiObject::create( static_cast< SdDrawDocument* >( mpPage->GetModel() ) );
349 	}
350     return Reference< XText >( m_TextRange.get() );
351 }
352 
353 SdrUndoAction* CreateUndoInsertOrRemoveAnnotation( const Reference< XAnnotation >& xAnnotation, bool bInsert )
354 {
355     Annotation* pAnnotation = dynamic_cast< Annotation* >( xAnnotation.get() );
356     if( pAnnotation )
357     {
358         return new UndoInsertOrRemoveAnnotation( *pAnnotation, bInsert );
359     }
360     else
361     {
362         return 0;
363     }
364 }
365 
366 UndoInsertOrRemoveAnnotation::UndoInsertOrRemoveAnnotation( Annotation& rAnnotation, bool bInsert )
367 : SdrUndoAction( *rAnnotation.GetModel() )
368 , mxAnnotation( &rAnnotation )
369 , mbInsert( bInsert )
370 , mnIndex( 0 )
371 {
372     SdPage* pPage = rAnnotation.GetPage();
373     if( pPage )
374     {
375         Reference< XAnnotation > xAnnotation( &rAnnotation );
376 
377         const AnnotationVector& rVec = pPage->getAnnotations();
378         for( AnnotationVector::const_iterator iter = rVec.begin(); iter != rVec.end(); iter++ )
379         {
380             if( (*iter) == xAnnotation )
381                 break;
382 
383             mnIndex++;
384         }
385     }
386 }
387 
388 void UndoInsertOrRemoveAnnotation::Undo()
389 {
390     SdPage* pPage = mxAnnotation->GetPage();
391     SdrModel* pModel = mxAnnotation->GetModel();
392     if( pPage && pModel )
393     {
394         Reference< XAnnotation > xAnnotation( mxAnnotation.get() );
395         if( mbInsert )
396         {
397             pPage->removeAnnotation( xAnnotation );
398         }
399         else
400         {
401             pPage->addAnnotation( xAnnotation, mnIndex );
402         }
403     }
404 }
405 
406 void UndoInsertOrRemoveAnnotation::Redo()
407 {
408     SdPage* pPage = mxAnnotation->GetPage();
409     SdrModel* pModel = mxAnnotation->GetModel();
410     if( pPage && pModel )
411     {
412         Reference< XAnnotation > xAnnotation( mxAnnotation.get() );
413 
414         if( mbInsert )
415         {
416             pPage->addAnnotation( xAnnotation, mnIndex );
417         }
418         else
419         {
420             pPage->removeAnnotation( xAnnotation );
421         }
422     }
423 }
424 
425 UndoAnnotation::UndoAnnotation( Annotation& rAnnotation )
426 : SdrUndoAction( *rAnnotation.GetModel() )
427 , mxAnnotation( &rAnnotation )
428 {
429     maUndoData.get( mxAnnotation );
430 }
431 
432 void UndoAnnotation::Undo()
433 {
434     maRedoData.get( mxAnnotation );
435     maUndoData.set( mxAnnotation );
436 }
437 
438 void UndoAnnotation::Redo()
439 {
440     maUndoData.get( mxAnnotation );
441     maRedoData.set( mxAnnotation );
442 }
443 
444 } // namespace sd
445 
446