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 <com/sun/star/util/XChangesNotifier.hpp>
28 
29 #include <vcl/help.hxx>
30 #include <vcl/svapp.hxx>
31 
32 #include <sfx2/viewfrm.hxx>
33 #include <sfx2/dispatch.hxx>
34 
35 #include <svx/sdr/overlay/overlaymanager.hxx>
36 #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
37 #include <svx/sdr/overlay/overlaybitmapex.hxx>
38 #include <svx/svdpagv.hxx>
39 #include <svx/sdrpagewindow.hxx>
40 #include <svx/sdrpaintwindow.hxx>
41 #include <svx/svddrgmt.hxx>
42 
43 #include "View.hxx"
44 #include "sdresid.hxx"
45 #include "annotations.hrc"
46 #include "annotationmanagerimpl.hxx"
47 #include "annotationwindow.hxx"
48 #include "annotationtag.hxx"
49 #include "sdpage.hxx"
50 #include "ViewShell.hxx"
51 #include "app.hrc"
52 #include "Window.hxx"
53 #include "drawdoc.hxx"
54 
55 using ::rtl::OUString;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::lang;
58 //using namespace ::com::sun::star::util;
59 using namespace ::com::sun::star::drawing;
60 using namespace ::com::sun::star::office;
61 using namespace ::com::sun::star::geometry;
62 
63 namespace sd
64 {
65 
66 const sal_uInt32 SMART_TAG_HDL_NUM = SAL_MAX_UINT32;
67 static const int DRGPIX     = 2;                               // Drag MinMove in Pixel
68 
69 // --------------------------------------------------------------------
70 
getInitials(const OUString & rName)71 static OUString getInitials( const OUString& rName )
72 {
73 	OUString sInitials;
74 
75 	const sal_Unicode * pStr = rName.getStr();
76 	sal_Int32 nLength = rName.getLength();
77 
78 	while( nLength )
79 	{
80 		// skip whitespace
81 		while( nLength && (*pStr <= ' ') )
82 		{
83 			nLength--; pStr++;
84 		}
85 
86 		// take letter
87 		if( nLength )
88 		{
89 			sInitials += OUString( *pStr );
90 			nLength--; pStr++;
91 		}
92 
93 		// skip letters until whitespace
94 		while( nLength && (*pStr > ' ') )
95 		{
96 			nLength--; pStr++;
97 		}
98 	}
99 
100 	return sInitials;
101 }
102 
103 // --------------------------------------------------------------------
104 
105 // --------------------------------------------------------------------
106 
107 class AnnotationDragMove : public SdrDragMove
108 {
109 public:
110 	AnnotationDragMove(SdrDragView& rNewView, const rtl::Reference <AnnotationTag >& xTag);
111 	virtual bool BeginSdrDrag();
112 	virtual bool EndSdrDrag(bool bCopy);
113 	virtual void MoveSdrDrag(const Point& rNoSnapPnt);
114 	virtual void CancelSdrDrag();
115 
116 private:
117 	rtl::Reference <AnnotationTag > mxTag;
118 	Point maOrigin;
119 };
120 
AnnotationDragMove(SdrDragView & rNewView,const rtl::Reference<AnnotationTag> & xTag)121 AnnotationDragMove::AnnotationDragMove(SdrDragView& rNewView, const rtl::Reference <AnnotationTag >& xTag)
122 : SdrDragMove(rNewView)
123 , mxTag( xTag )
124 {
125 }
126 
BeginSdrDrag()127 bool AnnotationDragMove::BeginSdrDrag()
128 {
129 	DragStat().Ref1()=GetDragHdl()->GetPos();
130 	DragStat().SetShown(!DragStat().IsShown());
131 
132 	maOrigin = GetDragHdl()->GetPos();
133 	DragStat().SetActionRect(Rectangle(maOrigin,maOrigin));
134 
135 	return true;
136 }
137 
MoveSdrDrag(const Point & rNoSnapPnt)138 void AnnotationDragMove::MoveSdrDrag(const Point& rNoSnapPnt)
139 {
140 	Point aPnt(rNoSnapPnt);
141 
142 	if (DragStat().CheckMinMoved(rNoSnapPnt))
143 	{
144 		if (aPnt!=DragStat().GetNow())
145 		{
146 			Hide();
147 			DragStat().NextMove(aPnt);
148             GetDragHdl()->SetPos( maOrigin + Point( DragStat().GetDX(), DragStat().GetDY() ) );
149 			Show();
150 			DragStat().SetActionRect(Rectangle(aPnt,aPnt));
151 		}
152 	}
153 }
154 
EndSdrDrag(bool)155 bool AnnotationDragMove::EndSdrDrag(bool /*bCopy*/)
156 {
157 	Hide();
158 	if( mxTag.is() )
159 		mxTag->Move( DragStat().GetDX(), DragStat().GetDY() );
160 	return sal_True;
161 }
162 
CancelSdrDrag()163 void AnnotationDragMove::CancelSdrDrag()
164 {
165 	Hide();
166 }
167 
168 // --------------------------------------------------------------------
169 
170 class AnnotationHdl : public SmartHdl
171 {
172 public:
173 	AnnotationHdl( const SmartTagReference& xTag, const Reference< XAnnotation >& xAnnotation, const Point& rPnt );
174 	virtual ~AnnotationHdl();
175 	virtual void CreateB2dIAObject();
176 	virtual sal_Bool IsFocusHdl() const;
177 	virtual Pointer GetSdrDragPointer() const;
178 	virtual bool isMarkable() const;
179 
180 
181 private:
182 	Reference< XAnnotation > mxAnnotation;
183 	rtl::Reference< AnnotationTag > mxTag;
184 };
185 
186 // --------------------------------------------------------------------
187 
AnnotationHdl(const SmartTagReference & xTag,const Reference<XAnnotation> & xAnnotation,const Point & rPnt)188 AnnotationHdl::AnnotationHdl( const SmartTagReference& xTag, const Reference< XAnnotation >& xAnnotation, const Point& rPnt )
189 : SmartHdl( xTag, rPnt )
190 , mxAnnotation( xAnnotation )
191 , mxTag( dynamic_cast< AnnotationTag* >( xTag.get() ) )
192 {
193 }
194 
195 // --------------------------------------------------------------------
196 
~AnnotationHdl()197 AnnotationHdl::~AnnotationHdl()
198 {
199 }
200 
201 // --------------------------------------------------------------------
202 
CreateB2dIAObject()203 void AnnotationHdl::CreateB2dIAObject()
204 {
205 	// first throw away old one
206 	GetRidOfIAObject();
207 
208 	if( mxAnnotation.is() )
209 	{
210 		const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
211 
212 		const Point aTagPos( GetPos() );
213 		basegfx::B2DPoint aPosition( aTagPos.X(), aTagPos.Y() );
214 
215         const bool bFocused = IsFocusHdl() && pHdlList && (pHdlList->GetFocusHdl() == this);
216 
217 		BitmapEx aBitmapEx( mxTag->CreateAnnotationBitmap(mxTag->isSelected()) );
218 		BitmapEx aBitmapEx2;
219 		if( bFocused )
220 		    aBitmapEx2 = mxTag->CreateAnnotationBitmap(!mxTag->isSelected() );
221 
222 		if(pHdlList)
223 		{
224 			SdrMarkView* pView = pHdlList->GetView();
225 
226 			if(pView && !pView->areMarkHandlesHidden())
227 			{
228 				SdrPageView* pPageView = pView->GetSdrPageView();
229 
230 				if(pPageView)
231 				{
232 					for(sal_uInt32 b = 0; b < pPageView->PageWindowCount(); b++)
233 					{
234 						// const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
235 						const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
236 
237 						SdrPaintWindow& rPaintWindow = rPageWindow.GetPaintWindow();
238 						if(rPaintWindow.OutputToWindow() && rPageWindow.GetOverlayManager() )
239 						{
240 							::sdr::overlay::OverlayObject* pOverlayObject = 0;
241 
242 					        // animate focused handles
243 					        if(bFocused)
244 					        {
245 						        const sal_uInt32 nBlinkTime = sal::static_int_cast<sal_uInt32>(rStyleSettings.GetCursorBlinkTime());
246 
247 						        pOverlayObject = new ::sdr::overlay::OverlayAnimatedBitmapEx(aPosition, aBitmapEx, aBitmapEx2, nBlinkTime, 0, 0, 0, 0 );
248 /*
249 							        (sal_uInt16)(aBitmapEx.GetSizePixel().Width() - 1) >> 1,
250 							        (sal_uInt16)(aBitmapEx.GetSizePixel().Height() - 1) >> 1,
251 							        (sal_uInt16)(aBitmapEx2.GetSizePixel().Width() - 1) >> 1,
252 							        (sal_uInt16)(aBitmapEx2.GetSizePixel().Height() - 1) >> 1);
253 */
254 					        }
255 					        else
256 					        {
257 							    pOverlayObject = new ::sdr::overlay::OverlayBitmapEx( aPosition, aBitmapEx, 0, 0 );
258 							}
259 
260 							rPageWindow.GetOverlayManager()->add(*pOverlayObject);
261 							maOverlayGroup.append(*pOverlayObject);
262 						}
263 					}
264 				}
265 			}
266 		}
267 	}
268 }
269 
270 // --------------------------------------------------------------------
271 
IsFocusHdl() const272 sal_Bool AnnotationHdl::IsFocusHdl() const
273 {
274 	return sal_True;
275 }
276 
277 // --------------------------------------------------------------------
278 
isMarkable() const279 bool AnnotationHdl::isMarkable() const
280 {
281 	return false;
282 }
283 
284 // --------------------------------------------------------------------
285 
GetSdrDragPointer() const286 Pointer AnnotationHdl::GetSdrDragPointer() const
287 {
288 	PointerStyle eStyle = POINTER_NOTALLOWED;
289 	if( mxTag.is() )
290 	{
291 		if( mxTag->isSelected() )
292 		{
293 			eStyle = POINTER_MOVE;
294 		}
295 		else
296 		{
297 			eStyle = POINTER_ARROW;
298 
299 		}
300 	}
301 	return Pointer( eStyle );
302 }
303 
304 // ====================================================================
305 
AnnotationTag(AnnotationManagerImpl & rManager,::sd::View & rView,const Reference<XAnnotation> & xAnnotation,Color & rColor,int nIndex,const Font & rFont)306 AnnotationTag::AnnotationTag( AnnotationManagerImpl& rManager, ::sd::View& rView, const Reference< XAnnotation >& xAnnotation, Color& rColor, int nIndex, const Font& rFont )
307 : SmartTag( rView )
308 , mrManager( rManager )
309 , mxAnnotation( xAnnotation )
310 , maColor( rColor )
311 , mnIndex( nIndex )
312 , mrFont( rFont )
313 , mnClosePopupEvent( 0 )
314 , mpListenWindow( 0 )
315 {
316 }
317 
318 // --------------------------------------------------------------------
319 
~AnnotationTag()320 AnnotationTag::~AnnotationTag()
321 {
322 	DBG_ASSERT( !mxAnnotation.is(), "sd::AnnotationTag::~AnnotationTag(), dispose me first!" );
323 	Dispose();
324 }
325 
326 // --------------------------------------------------------------------
327 
328 /** returns true if the AnnotationTag handled the event. */
MouseButtonDown(const MouseEvent & rMEvt,SmartHdl &)329 bool AnnotationTag::MouseButtonDown( const MouseEvent& rMEvt, SmartHdl& /*rHdl*/ )
330 {
331 	if( !mxAnnotation.is() )
332 		return false;
333 
334     bool bRet = false;
335 	if( !isSelected() )
336 	{
337 		SmartTagReference xTag( this );
338 		mrView.getSmartTags().select( xTag );
339 		bRet = true;
340 	}
341 	/*
342 	if( rMEvt.IsLeft() && (rMEvt.GetClicks() == 2) )
343 	{
344 		// double click;
345 		return true;
346 	}
347 	else */
348 	if( rMEvt.IsLeft() && !rMEvt.IsRight() )
349 	{
350 		Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
351 		if( pWindow )
352 		{
353             maMouseDownPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
354 
355 		    if( mpListenWindow )
356 		        mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
357 
358 		    mpListenWindow = pWindow;
359             mpListenWindow->AddEventListener( LINK(this, AnnotationTag, WindowEventHandler));
360         }
361 
362 		bRet = true;
363 	}
364 
365 	return bRet;
366 }
367 
368 // --------------------------------------------------------------------
369 
370 /** returns true if the SmartTag consumes this event. */
KeyInput(const KeyEvent & rKEvt)371 bool AnnotationTag::KeyInput( const KeyEvent& rKEvt )
372 {
373 	if( !mxAnnotation.is() )
374 		return false;
375 
376 	sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
377 	switch( nCode )
378 	{
379 	case KEY_DELETE:
380 	    mrManager.DeleteAnnotation( mxAnnotation );
381 	    return true;
382 
383 	case KEY_DOWN:
384 	case KEY_UP:
385 	case KEY_LEFT:
386 	case KEY_RIGHT:
387 		return OnMove( rKEvt );
388 
389 	case KEY_ESCAPE:
390 	{
391 		SmartTagReference xThis( this );
392 		mrView.getSmartTags().deselect();
393 		return true;
394 	}
395 
396 	case KEY_TAB:
397 	    mrManager.SelectNextAnnotation(!rKEvt.GetKeyCode().IsShift());
398 	    return true;
399 
400     case KEY_RETURN:
401    	case KEY_SPACE:
402    	    OpenPopup( true );
403    	    return true;
404 
405 	default:
406 		return false;
407 	}
408 }
409 
410 /** returns true if the SmartTag consumes this event. */
RequestHelp(const HelpEvent &)411 bool AnnotationTag::RequestHelp( const HelpEvent& /*rHEvt*/ )
412 {
413 /*
414 	::Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
415     if( mxAnnotation.is() && pWindow )
416     {
417         OUString aHelpText( mrManager.GetHelpText( mxAnnotation ) );
418 
419 	    RealPoint2D aPosition( mxAnnotation->getPosition() );
420 	    Point aPos( pWindow->LogicToPixel( Point( static_cast<long>(aPosition.X * 100.0), static_cast<long>(aPosition.Y * 100.0) ) ) );
421 
422         Rectangle aRect( aPos, maSize );
423 
424 	    if (Help::IsBalloonHelpEnabled())
425 		    Help::ShowBalloon( pWindow, aPos, aRect, aHelpText);
426 	    else if (Help::IsQuickHelpEnabled())
427 		    Help::ShowQuickHelp( pWindow, aRect, aHelpText);
428 
429         return true;
430    }
431 */
432    return false;
433 }
434 
435 /** returns true if the SmartTag consumes this event. */
Command(const CommandEvent & rCEvt)436 bool AnnotationTag::Command( const CommandEvent& rCEvt )
437 {
438     if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
439     {
440         ::Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
441         if( pWindow )
442         {
443             Rectangle aContextRect(rCEvt.GetMousePosPixel(),Size(1,1));
444        	    mrManager.ExecuteAnnotationContextMenu( mxAnnotation, pWindow, aContextRect );
445 	        return true;
446 	    }
447     }
448 
449     return false;
450 }
451 
Move(int nDX,int nDY)452 void AnnotationTag::Move( int nDX, int nDY )
453 {
454 	if( mxAnnotation.is() )
455 	{
456         if( mrManager.GetDoc()->IsUndoEnabled() )
457             mrManager.GetDoc()->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_MOVE ) ) );
458 
459 		RealPoint2D aPosition( mxAnnotation->getPosition() );
460 		aPosition.X += (double)nDX / 100.0;
461 		aPosition.Y += (double)nDY / 100.0;
462 		mxAnnotation->setPosition( aPosition );
463 
464         if( mrManager.GetDoc()->IsUndoEnabled() )
465             mrManager.GetDoc()->EndUndo();
466 
467 		mrView.updateHandles();
468 	}
469 }
470 
OnMove(const KeyEvent & rKEvt)471 bool AnnotationTag::OnMove( const KeyEvent& rKEvt )
472 {
473 	long nX = 0;
474 	long nY = 0;
475 
476 	switch( rKEvt.GetKeyCode().GetCode() )
477 	{
478 	case KEY_UP:	nY = -1; break;
479 	case KEY_DOWN:	nY =  1; break;
480 	case KEY_LEFT:	nX = -1; break;
481 	case KEY_RIGHT:	nX =  1; break;
482 	default: break;
483 	}
484 
485 	if(rKEvt.GetKeyCode().IsMod2())
486 	{
487 		OutputDevice* pOut = mrView.GetViewShell()->GetActiveWindow();
488 		Size aLogicSizeOnePixel = (pOut) ? pOut->PixelToLogic(Size(1,1)) : Size(100, 100);
489 		nX *= aLogicSizeOnePixel.Width();
490 		nY *= aLogicSizeOnePixel.Height();
491 	}
492 	else
493 	{
494 		// old, fixed move distance
495 		nX *= 100;
496 		nY *= 100;
497 	}
498 
499 	if( nX || nY )
500 	{
501 		// move the annotation
502 		Move( nX, nY );
503 	}
504 
505 	return true;
506 }
507 
508 // --------------------------------------------------------------------
509 
CheckPossibilities()510 void AnnotationTag::CheckPossibilities()
511 {
512 }
513 
514 // --------------------------------------------------------------------
515 
GetMarkablePointCount() const516 sal_uLong AnnotationTag::GetMarkablePointCount() const
517 {
518 	return 0;
519 }
520 
521 // --------------------------------------------------------------------
522 
GetMarkedPointCount() const523 sal_uLong AnnotationTag::GetMarkedPointCount() const
524 {
525 	return 0;
526 }
527 
528 // --------------------------------------------------------------------
529 
MarkPoint(SdrHdl &,sal_Bool)530 sal_Bool AnnotationTag::MarkPoint(SdrHdl& /*rHdl*/, sal_Bool /*bUnmark*/ )
531 {
532 	sal_Bool bRet=sal_False;
533 	return bRet;
534 }
535 
536 // --------------------------------------------------------------------
537 
MarkPoints(const Rectangle *,sal_Bool)538 sal_Bool AnnotationTag::MarkPoints(const Rectangle* /*pRect*/, sal_Bool /*bUnmark*/ )
539 {
540 	sal_Bool bChgd=sal_False;
541 	return bChgd;
542 }
543 
544 // --------------------------------------------------------------------
545 
getContext(SdrViewContext &)546 bool AnnotationTag::getContext( SdrViewContext& /*rContext*/ )
547 {
548 	return false;
549 }
550 
551 // --------------------------------------------------------------------
552 
addCustomHandles(SdrHdlList & rHandlerList)553 void AnnotationTag::addCustomHandles( SdrHdlList& rHandlerList )
554 {
555 	if( mxAnnotation.is() )
556 	{
557 		SmartTagReference xThis( this );
558 		Point aPoint;
559 		AnnotationHdl* pHdl = new AnnotationHdl( xThis, mxAnnotation, aPoint );
560 		pHdl->SetObjHdlNum( SMART_TAG_HDL_NUM );
561 		pHdl->SetPageView( mrView.GetSdrPageView() );
562 
563 		RealPoint2D aPosition( mxAnnotation->getPosition() );
564 		Point aBasePos( static_cast<long>(aPosition.X * 100.0), static_cast<long>(aPosition.Y * 100.0) );
565 		pHdl->SetPos( aBasePos );
566 
567 		rHandlerList.AddHdl( pHdl );
568 	}
569 }
570 
571 // --------------------------------------------------------------------
572 
disposing()573 void AnnotationTag::disposing()
574 {
575     if( mpListenWindow )
576     {
577         mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
578     }
579 
580     if( mnClosePopupEvent )
581     {
582         Application::RemoveUserEvent( mnClosePopupEvent );
583         mnClosePopupEvent = 0;
584     }
585 
586 	mxAnnotation.clear();
587     ClosePopup();
588 	SmartTag::disposing();
589 }
590 
591 // --------------------------------------------------------------------
592 
select()593 void AnnotationTag::select()
594 {
595 	SmartTag::select();
596 
597 	mrManager.onTagSelected( *this );
598 
599 	Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
600 	if( pWindow )
601 	{
602         RealPoint2D aPosition( mxAnnotation->getPosition() );
603         Point aPos( static_cast<long>(aPosition.X * 100.0), static_cast<long>(aPosition.Y * 100.0) );
604 
605         Rectangle aVisRect( aPos, pWindow->PixelToLogic(maSize) );
606 		mrView.MakeVisible(aVisRect, *pWindow);
607 	}
608 }
609 
610 // --------------------------------------------------------------------
611 
deselect()612 void AnnotationTag::deselect()
613 {
614 	SmartTag::deselect();
615 
616     ClosePopup();
617 
618 	mrManager.onTagDeselected( *this );
619 }
620 
621 // --------------------------------------------------------------------
622 
CreateAnnotationBitmap(bool bSelected)623 BitmapEx AnnotationTag::CreateAnnotationBitmap( bool bSelected )
624 {
625 	VirtualDevice aVDev;
626 
627 	OUString sAuthor( getInitials( mxAnnotation->getAuthor() ) );
628 	sAuthor += OUString( sal_Unicode( ' ' ) );
629 	sAuthor += OUString::valueOf( (sal_Int32)mnIndex );
630 
631 	aVDev.SetFont( mrFont );
632 
633 	const int BORDER_X = 4; // pixels
634 	const int BORDER_Y = 4; // pixels
635 
636 	maSize = Size( aVDev.GetTextWidth( sAuthor ) + 2*BORDER_X, aVDev.GetTextHeight() + 2*BORDER_Y );
637 	aVDev.SetOutputSizePixel( maSize, sal_False );
638 
639 	Color aBorderColor( maColor );
640 
641 	if( bSelected )
642 	{
643 		aBorderColor.Invert();
644 	}
645 	else
646 	{
647 		if( maColor.IsDark() )
648 		{
649 			aBorderColor.IncreaseLuminance( 32 );
650 		}
651 		else
652 		{
653 			aBorderColor.DecreaseLuminance( 32 );
654 		}
655 	}
656 
657 	Point aPos;
658 	Rectangle aBorderRect( aPos, maSize );
659 	aVDev.SetLineColor(aBorderColor);
660 	aVDev.SetFillColor(maColor);
661 	aVDev.DrawRect( aBorderRect );
662 
663 	aVDev.SetTextColor( maColor.IsDark() ? COL_WHITE : COL_BLACK );
664 	aVDev.DrawText( Point( BORDER_X, BORDER_Y ), sAuthor );
665 
666 	return aVDev.GetBitmapEx( aPos, maSize );
667 }
668 
OpenPopup(bool bEdit)669 void AnnotationTag::OpenPopup( bool bEdit )
670 {
671     if( !mxAnnotation.is() )
672         return;
673 
674     if( !mpAnnotationWindow.get() )
675     {
676    	    ::Window* pWindow = dynamic_cast< ::Window* >( getView().GetFirstOutputDevice() );
677    	    if( pWindow )
678    	    {
679             RealPoint2D aPosition( mxAnnotation->getPosition() );
680 	        Point aPos( pWindow->OutputToScreenPixel( pWindow->LogicToPixel( Point( static_cast<long>(aPosition.X * 100.0), static_cast<long>(aPosition.Y * 100.0) ) ) ) );
681 
682             aPos.X() += 4; // magic!
683             aPos.Y() += 1;
684 
685             Rectangle aRect( aPos, maSize );
686 
687             mpAnnotationWindow.reset( new AnnotationWindow( mrManager, mrView.GetDocSh(), pWindow->GetWindow(WINDOW_FRAME) ) );
688         	mpAnnotationWindow->InitControls();
689         	mpAnnotationWindow->setAnnotation(mxAnnotation);
690 
691             sal_uInt16 nArrangeIndex = 0;
692             Point aPopupPos( FloatingWindow::CalcFloatingPosition( mpAnnotationWindow.get(), aRect, FLOATWIN_POPUPMODE_RIGHT, nArrangeIndex ) );
693             Size aPopupSize( 320, 240 );
694 
695             mpAnnotationWindow->SetPosSizePixel( aPopupPos, aPopupSize );
696             mpAnnotationWindow->DoResize();
697 
698             mpAnnotationWindow->Show();
699             mpAnnotationWindow->GrabFocus();
700             mpAnnotationWindow->AddEventListener( LINK(this, AnnotationTag, WindowEventHandler));
701         }
702     }
703 
704     if( bEdit && mpAnnotationWindow.get() )
705         mpAnnotationWindow->StartEdit();
706 }
707 
ClosePopup()708 void AnnotationTag::ClosePopup()
709 {
710     if( mpAnnotationWindow.get() )
711     {
712         mpAnnotationWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
713         mpAnnotationWindow->Deactivate();
714         mpAnnotationWindow.reset();
715     }
716 }
717 
IMPL_LINK(AnnotationTag,WindowEventHandler,VclWindowEvent *,pEvent)718 IMPL_LINK(AnnotationTag, WindowEventHandler, VclWindowEvent*, pEvent)
719 {
720     if( pEvent != NULL )
721     {
722         ::Window* pWindow = pEvent->GetWindow();
723 
724         if( pWindow )
725         {
726             if( pWindow == mpAnnotationWindow.get() )
727             {
728                 if( pEvent->GetId() == VCLEVENT_WINDOW_DEACTIVATE )
729                 {
730                     if( mnClosePopupEvent )
731                         Application::RemoveUserEvent( mnClosePopupEvent );
732 
733                     mnClosePopupEvent = Application::PostUserEvent( LINK( this, AnnotationTag, ClosePopupHdl ) );
734                 }
735             }
736             else if( pWindow == mpListenWindow )
737             {
738                 switch( pEvent->GetId() )
739                 {
740                 case VCLEVENT_WINDOW_MOUSEBUTTONUP:
741                     {
742                         // if we stop pressing the button without a mouse move we open the popup
743                         mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
744                         mpListenWindow = 0;
745                         if( mpAnnotationWindow.get() == 0 )
746                             OpenPopup(false);
747                     }
748                     break;
749                 case VCLEVENT_WINDOW_MOUSEMOVE:
750                     {
751                         // if we move the mouse after a button down we wan't to start draging
752                         mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
753                         mpListenWindow = 0;
754 
755 	                    SdrHdl* pHdl = mrView.PickHandle(maMouseDownPos);
756                         if( pHdl )
757                         {
758 		                    mrView.BrkAction();
759 		                    const sal_uInt16 nDrgLog = (sal_uInt16)pWindow->PixelToLogic(Size(DRGPIX,0)).Width();
760 
761 		                    rtl::Reference< AnnotationTag > xTag( this );
762 
763 		                    SdrDragMethod* pDragMethod = new AnnotationDragMove( mrView, xTag );
764 		                    mrView.BegDragObj(maMouseDownPos, NULL, pHdl, nDrgLog, pDragMethod );
765 		                }
766 		            }
767                     break;
768                 case VCLEVENT_OBJECT_DYING:
769                     mpListenWindow = 0;
770                     break;
771                 }
772             }
773         }
774     }
775     return sal_True;
776 }
777 
IMPL_LINK(AnnotationTag,ClosePopupHdl,void *,EMPTYARG)778 IMPL_LINK( AnnotationTag, ClosePopupHdl, void *, EMPTYARG )
779 {
780     mnClosePopupEvent = 0;
781     ClosePopup();
782     return 0;
783 }
784 
785 } // end of namespace sd
786 
787