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