Update ooo320-m1
[ooovba.git] / sd / source / ui / annotations / annotationtag.cxx
blob5206e4aeff2b6bf4f7575aeb10c6b930afc082a2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: motionpathtag.cxx,v $
10 * $Revision: 1.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include <com/sun/star/util/XChangesNotifier.hpp>
36 #include <vcl/help.hxx>
37 #include <vcl/svapp.hxx>
39 #include <sfx2/viewfrm.hxx>
40 #include <sfx2/dispatch.hxx>
42 #include <svx/sdr/overlay/overlaymanager.hxx>
43 #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
44 #include <svx/sdr/overlay/overlaybitmapex.hxx>
45 #include <svx/svdpagv.hxx>
46 #include <svx/sdrpagewindow.hxx>
47 #include <svx/sdrpaintwindow.hxx>
48 #include <svx/svddrgmt.hxx>
50 #include "View.hxx"
51 #include "sdresid.hxx"
52 #include "annotations.hrc"
53 #include "annotationmanagerimpl.hxx"
54 #include "annotationwindow.hxx"
55 #include "annotationtag.hxx"
56 #include "sdpage.hxx"
57 #include "ViewShell.hxx"
58 #include "app.hrc"
59 #include "Window.hxx"
60 #include "drawdoc.hxx"
62 using ::rtl::OUString;
63 using namespace ::com::sun::star::uno;
64 using namespace ::com::sun::star::lang;
65 //using namespace ::com::sun::star::util;
66 using namespace ::com::sun::star::drawing;
67 using namespace ::com::sun::star::office;
68 using namespace ::com::sun::star::geometry;
70 namespace sd
73 const sal_uInt32 SMART_TAG_HDL_NUM = SAL_MAX_UINT32;
74 static const int DRGPIX = 2; // Drag MinMove in Pixel
76 // --------------------------------------------------------------------
78 static OUString getInitials( const OUString& rName )
80 OUString sInitials;
82 const sal_Unicode * pStr = rName.getStr();
83 sal_Int32 nLength = rName.getLength();
85 while( nLength )
87 // skip whitespace
88 while( nLength && (*pStr <= ' ') )
90 nLength--; pStr++;
93 // take letter
94 if( nLength )
96 sInitials += OUString( *pStr );
97 nLength--; pStr++;
100 // skip letters until whitespace
101 while( nLength && (*pStr > ' ') )
103 nLength--; pStr++;
107 return sInitials;
110 // --------------------------------------------------------------------
112 // --------------------------------------------------------------------
114 class AnnotationDragMove : public SdrDragMove
116 public:
117 AnnotationDragMove(SdrDragView& rNewView, const rtl::Reference <AnnotationTag >& xTag);
118 virtual bool BeginSdrDrag();
119 virtual bool EndSdrDrag(bool bCopy);
120 virtual void MoveSdrDrag(const Point& rNoSnapPnt);
121 virtual void CancelSdrDrag();
123 private:
124 rtl::Reference <AnnotationTag > mxTag;
125 Point maOrigin;
128 AnnotationDragMove::AnnotationDragMove(SdrDragView& rNewView, const rtl::Reference <AnnotationTag >& xTag)
129 : SdrDragMove(rNewView)
130 , mxTag( xTag )
134 bool AnnotationDragMove::BeginSdrDrag()
136 DragStat().Ref1()=GetDragHdl()->GetPos();
137 DragStat().SetShown(!DragStat().IsShown());
139 maOrigin = GetDragHdl()->GetPos();
140 DragStat().SetActionRect(Rectangle(maOrigin,maOrigin));
142 return true;
145 void AnnotationDragMove::MoveSdrDrag(const Point& rNoSnapPnt)
147 Point aPnt(rNoSnapPnt);
149 if (DragStat().CheckMinMoved(rNoSnapPnt))
151 if (aPnt!=DragStat().GetNow())
153 Hide();
154 DragStat().NextMove(aPnt);
155 GetDragHdl()->SetPos( maOrigin + Point( DragStat().GetDX(), DragStat().GetDY() ) );
156 Show();
157 DragStat().SetActionRect(Rectangle(aPnt,aPnt));
162 bool AnnotationDragMove::EndSdrDrag(bool /*bCopy*/)
164 Hide();
165 if( mxTag.is() )
166 mxTag->Move( DragStat().GetDX(), DragStat().GetDY() );
167 return TRUE;
170 void AnnotationDragMove::CancelSdrDrag()
172 Hide();
175 // --------------------------------------------------------------------
177 class AnnotationHdl : public SmartHdl
179 public:
180 AnnotationHdl( const SmartTagReference& xTag, const Reference< XAnnotation >& xAnnotation, const Point& rPnt );
181 virtual ~AnnotationHdl();
182 virtual void CreateB2dIAObject();
183 virtual BOOL IsFocusHdl() const;
184 virtual Pointer GetSdrDragPointer() const;
185 virtual bool isMarkable() const;
188 private:
189 Reference< XAnnotation > mxAnnotation;
190 rtl::Reference< AnnotationTag > mxTag;
193 // --------------------------------------------------------------------
195 AnnotationHdl::AnnotationHdl( const SmartTagReference& xTag, const Reference< XAnnotation >& xAnnotation, const Point& rPnt )
196 : SmartHdl( xTag, rPnt )
197 , mxAnnotation( xAnnotation )
198 , mxTag( dynamic_cast< AnnotationTag* >( xTag.get() ) )
202 // --------------------------------------------------------------------
204 AnnotationHdl::~AnnotationHdl()
208 // --------------------------------------------------------------------
210 void AnnotationHdl::CreateB2dIAObject()
212 // first throw away old one
213 GetRidOfIAObject();
215 if( mxAnnotation.is() )
217 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
219 const Point aTagPos( GetPos() );
220 basegfx::B2DPoint aPosition( aTagPos.X(), aTagPos.Y() );
222 const bool bFocused = IsFocusHdl() && pHdlList && (pHdlList->GetFocusHdl() == this);
224 BitmapEx aBitmapEx( mxTag->CreateAnnotationBitmap(mxTag->isSelected()) );
225 BitmapEx aBitmapEx2;
226 if( bFocused )
227 aBitmapEx2 = mxTag->CreateAnnotationBitmap(!mxTag->isSelected() );
229 if(pHdlList)
231 SdrMarkView* pView = pHdlList->GetView();
233 if(pView && !pView->areMarkHandlesHidden())
235 SdrPageView* pPageView = pView->GetSdrPageView();
237 if(pPageView)
239 for(sal_uInt32 b = 0; b < pPageView->PageWindowCount(); b++)
241 // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
242 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
244 SdrPaintWindow& rPaintWindow = rPageWindow.GetPaintWindow();
245 if(rPaintWindow.OutputToWindow() && rPageWindow.GetOverlayManager() )
247 ::sdr::overlay::OverlayObject* pOverlayObject = 0;
249 // animate focused handles
250 if(bFocused)
252 const sal_uInt32 nBlinkTime = sal::static_int_cast<sal_uInt32>(rStyleSettings.GetCursorBlinkTime());
254 pOverlayObject = new ::sdr::overlay::OverlayAnimatedBitmapEx(aPosition, aBitmapEx, aBitmapEx2, nBlinkTime, 0, 0, 0, 0 );
256 (UINT16)(aBitmapEx.GetSizePixel().Width() - 1) >> 1,
257 (UINT16)(aBitmapEx.GetSizePixel().Height() - 1) >> 1,
258 (UINT16)(aBitmapEx2.GetSizePixel().Width() - 1) >> 1,
259 (UINT16)(aBitmapEx2.GetSizePixel().Height() - 1) >> 1);
262 else
264 pOverlayObject = new ::sdr::overlay::OverlayBitmapEx( aPosition, aBitmapEx, 0, 0 );
267 rPageWindow.GetOverlayManager()->add(*pOverlayObject);
268 maOverlayGroup.append(*pOverlayObject);
277 // --------------------------------------------------------------------
279 BOOL AnnotationHdl::IsFocusHdl() const
281 return TRUE;
284 // --------------------------------------------------------------------
286 bool AnnotationHdl::isMarkable() const
288 return false;
291 // --------------------------------------------------------------------
293 Pointer AnnotationHdl::GetSdrDragPointer() const
295 PointerStyle eStyle = POINTER_NOTALLOWED;
296 if( mxTag.is() )
298 if( mxTag->isSelected() )
300 eStyle = POINTER_MOVE;
302 else
304 eStyle = POINTER_ARROW;
308 return Pointer( eStyle );
311 // ====================================================================
313 AnnotationTag::AnnotationTag( AnnotationManagerImpl& rManager, ::sd::View& rView, const Reference< XAnnotation >& xAnnotation, Color& rColor, int nIndex, const Font& rFont )
314 : SmartTag( rView )
315 , mrManager( rManager )
316 , mxAnnotation( xAnnotation )
317 , maColor( rColor )
318 , mnIndex( nIndex )
319 , mrFont( rFont )
320 , mnClosePopupEvent( 0 )
321 , mpListenWindow( 0 )
325 // --------------------------------------------------------------------
327 AnnotationTag::~AnnotationTag()
329 DBG_ASSERT( !mxAnnotation.is(), "sd::AnnotationTag::~AnnotationTag(), dispose me first!" );
330 Dispose();
333 // --------------------------------------------------------------------
335 /** returns true if the AnnotationTag handled the event. */
336 bool AnnotationTag::MouseButtonDown( const MouseEvent& rMEvt, SmartHdl& /*rHdl*/ )
338 if( !mxAnnotation.is() )
339 return false;
341 bool bRet = false;
342 if( !isSelected() )
344 SmartTagReference xTag( this );
345 mrView.getSmartTags().select( xTag );
346 bRet = true;
349 if( rMEvt.IsLeft() && (rMEvt.GetClicks() == 2) )
351 // double click;
352 return true;
354 else */
355 if( rMEvt.IsLeft() && !rMEvt.IsRight() )
357 Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
358 if( pWindow )
360 maMouseDownPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
362 if( mpListenWindow )
363 mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
365 mpListenWindow = pWindow;
366 mpListenWindow->AddEventListener( LINK(this, AnnotationTag, WindowEventHandler));
369 bRet = true;
372 return bRet;
375 // --------------------------------------------------------------------
377 /** returns true if the SmartTag consumes this event. */
378 bool AnnotationTag::KeyInput( const KeyEvent& rKEvt )
380 if( !mxAnnotation.is() )
381 return false;
383 USHORT nCode = rKEvt.GetKeyCode().GetCode();
384 switch( nCode )
386 case KEY_DELETE:
387 mrManager.DeleteAnnotation( mxAnnotation );
388 return true;
390 case KEY_DOWN:
391 case KEY_UP:
392 case KEY_LEFT:
393 case KEY_RIGHT:
394 return OnMove( rKEvt );
396 case KEY_ESCAPE:
398 SmartTagReference xThis( this );
399 mrView.getSmartTags().deselect();
400 return true;
403 case KEY_TAB:
404 mrManager.SelectNextAnnotation(!rKEvt.GetKeyCode().IsShift());
405 return true;
407 case KEY_RETURN:
408 case KEY_SPACE:
409 OpenPopup( true );
410 return true;
412 default:
413 return false;
417 /** returns true if the SmartTag consumes this event. */
418 bool AnnotationTag::RequestHelp( const HelpEvent& /*rHEvt*/ )
421 ::Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
422 if( mxAnnotation.is() && pWindow )
424 OUString aHelpText( mrManager.GetHelpText( mxAnnotation ) );
426 RealPoint2D aPosition( mxAnnotation->getPosition() );
427 Point aPos( pWindow->LogicToPixel( Point( static_cast<long>(aPosition.X * 100.0), static_cast<long>(aPosition.Y * 100.0) ) ) );
429 Rectangle aRect( aPos, maSize );
431 if (Help::IsBalloonHelpEnabled())
432 Help::ShowBalloon( pWindow, aPos, aRect, aHelpText);
433 else if (Help::IsQuickHelpEnabled())
434 Help::ShowQuickHelp( pWindow, aRect, aHelpText);
436 return true;
439 return false;
442 /** returns true if the SmartTag consumes this event. */
443 bool AnnotationTag::Command( const CommandEvent& rCEvt )
445 if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
447 ::Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
448 if( pWindow )
450 Rectangle aContextRect(rCEvt.GetMousePosPixel(),Size(1,1));
451 mrManager.ExecuteAnnotationContextMenu( mxAnnotation, pWindow, aContextRect );
452 return true;
456 return false;
459 void AnnotationTag::Move( int nDX, int nDY )
461 if( mxAnnotation.is() )
463 if( mrManager.GetDoc()->IsUndoEnabled() )
464 mrManager.GetDoc()->BegUndo( String( SdResId( STR_ANNOTATION_UNDO_MOVE ) ) );
466 RealPoint2D aPosition( mxAnnotation->getPosition() );
467 aPosition.X += (double)nDX / 100.0;
468 aPosition.Y += (double)nDY / 100.0;
469 mxAnnotation->setPosition( aPosition );
471 if( mrManager.GetDoc()->IsUndoEnabled() )
472 mrManager.GetDoc()->EndUndo();
474 mrView.updateHandles();
478 bool AnnotationTag::OnMove( const KeyEvent& rKEvt )
480 long nX = 0;
481 long nY = 0;
483 switch( rKEvt.GetKeyCode().GetCode() )
485 case KEY_UP: nY = -1; break;
486 case KEY_DOWN: nY = 1; break;
487 case KEY_LEFT: nX = -1; break;
488 case KEY_RIGHT: nX = 1; break;
489 default: break;
492 if(rKEvt.GetKeyCode().IsMod2())
494 OutputDevice* pOut = mrView.GetViewShell()->GetActiveWindow();
495 Size aLogicSizeOnePixel = (pOut) ? pOut->PixelToLogic(Size(1,1)) : Size(100, 100);
496 nX *= aLogicSizeOnePixel.Width();
497 nY *= aLogicSizeOnePixel.Height();
499 else
501 // old, fixed move distance
502 nX *= 100;
503 nY *= 100;
506 if( nX || nY )
508 // move the annotation
509 Move( nX, nY );
512 return true;
515 // --------------------------------------------------------------------
517 void AnnotationTag::CheckPossibilities()
521 // --------------------------------------------------------------------
523 ULONG AnnotationTag::GetMarkablePointCount() const
525 return 0;
528 // --------------------------------------------------------------------
530 ULONG AnnotationTag::GetMarkedPointCount() const
532 return 0;
535 // --------------------------------------------------------------------
537 BOOL AnnotationTag::MarkPoint(SdrHdl& /*rHdl*/, BOOL /*bUnmark*/ )
539 BOOL bRet=FALSE;
540 return bRet;
543 // --------------------------------------------------------------------
545 BOOL AnnotationTag::MarkPoints(const Rectangle* /*pRect*/, BOOL /*bUnmark*/ )
547 BOOL bChgd=FALSE;
548 return bChgd;
551 // --------------------------------------------------------------------
553 bool AnnotationTag::getContext( SdrViewContext& /*rContext*/ )
555 return false;
558 // --------------------------------------------------------------------
560 void AnnotationTag::addCustomHandles( SdrHdlList& rHandlerList )
562 if( mxAnnotation.is() )
564 SmartTagReference xThis( this );
565 Point aPoint;
566 AnnotationHdl* pHdl = new AnnotationHdl( xThis, mxAnnotation, aPoint );
567 pHdl->SetObjHdlNum( SMART_TAG_HDL_NUM );
568 pHdl->SetPageView( mrView.GetSdrPageView() );
570 RealPoint2D aPosition( mxAnnotation->getPosition() );
571 Point aBasePos( static_cast<long>(aPosition.X * 100.0), static_cast<long>(aPosition.Y * 100.0) );
572 pHdl->SetPos( aBasePos );
574 rHandlerList.AddHdl( pHdl );
578 // --------------------------------------------------------------------
580 void AnnotationTag::disposing()
582 if( mpListenWindow )
584 mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
587 if( mnClosePopupEvent )
589 Application::RemoveUserEvent( mnClosePopupEvent );
590 mnClosePopupEvent = 0;
593 mxAnnotation.clear();
594 ClosePopup();
595 SmartTag::disposing();
598 // --------------------------------------------------------------------
600 void AnnotationTag::select()
602 SmartTag::select();
604 mrManager.onTagSelected( *this );
606 Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
607 if( pWindow )
609 RealPoint2D aPosition( mxAnnotation->getPosition() );
610 Point aPos( static_cast<long>(aPosition.X * 100.0), static_cast<long>(aPosition.Y * 100.0) );
612 Rectangle aVisRect( aPos, pWindow->PixelToLogic(maSize) );
613 mrView.MakeVisible(aVisRect, *pWindow);
617 // --------------------------------------------------------------------
619 void AnnotationTag::deselect()
621 SmartTag::deselect();
623 ClosePopup();
625 mrManager.onTagDeselected( *this );
628 // --------------------------------------------------------------------
630 BitmapEx AnnotationTag::CreateAnnotationBitmap( bool bSelected )
632 VirtualDevice aVDev;
634 OUString sAuthor( getInitials( mxAnnotation->getAuthor() ) );
635 sAuthor += OUString( sal_Unicode( ' ' ) );
636 sAuthor += OUString::valueOf( (sal_Int32)mnIndex );
638 aVDev.SetFont( mrFont );
640 const int BORDER_X = 4; // pixels
641 const int BORDER_Y = 4; // pixels
643 maSize = Size( aVDev.GetTextWidth( sAuthor ) + 2*BORDER_X, aVDev.GetTextHeight() + 2*BORDER_Y );
644 aVDev.SetOutputSizePixel( maSize, FALSE );
646 Color aBorderColor( maColor );
648 if( bSelected )
650 aBorderColor.Invert();
652 else
654 if( maColor.IsDark() )
656 aBorderColor.IncreaseLuminance( 32 );
658 else
660 aBorderColor.DecreaseLuminance( 32 );
664 Point aPos;
665 Rectangle aBorderRect( aPos, maSize );
666 aVDev.SetLineColor(aBorderColor);
667 aVDev.SetFillColor(maColor);
668 aVDev.DrawRect( aBorderRect );
670 aVDev.SetTextColor( maColor.IsDark() ? COL_WHITE : COL_BLACK );
671 aVDev.DrawText( Point( BORDER_X, BORDER_Y ), sAuthor );
673 return aVDev.GetBitmapEx( aPos, maSize );
676 void AnnotationTag::OpenPopup( bool bEdit )
678 if( !mxAnnotation.is() )
679 return;
681 if( !mpAnnotationWindow.get() )
683 ::Window* pWindow = dynamic_cast< ::Window* >( getView().GetFirstOutputDevice() );
684 if( pWindow )
686 RealPoint2D aPosition( mxAnnotation->getPosition() );
687 Point aPos( pWindow->OutputToScreenPixel( pWindow->LogicToPixel( Point( static_cast<long>(aPosition.X * 100.0), static_cast<long>(aPosition.Y * 100.0) ) ) ) );
689 aPos.X() += 4; // magic!
690 aPos.Y() += 1;
692 Rectangle aRect( aPos, maSize );
694 mpAnnotationWindow.reset( new AnnotationWindow( mrManager, mrView.GetDocSh(), pWindow->GetWindow(WINDOW_FRAME) ) );
695 mpAnnotationWindow->InitControls();
696 mpAnnotationWindow->setAnnotation(mxAnnotation);
698 USHORT nArrangeIndex = 0;
699 Point aPopupPos( FloatingWindow::CalcFloatingPosition( mpAnnotationWindow.get(), aRect, FLOATWIN_POPUPMODE_RIGHT, nArrangeIndex ) );
700 Size aPopupSize( 320, 240 );
702 mpAnnotationWindow->SetPosSizePixel( aPopupPos, aPopupSize );
703 mpAnnotationWindow->DoResize();
705 mpAnnotationWindow->Show();
706 mpAnnotationWindow->GrabFocus();
707 mpAnnotationWindow->AddEventListener( LINK(this, AnnotationTag, WindowEventHandler));
711 if( bEdit && mpAnnotationWindow.get() )
712 mpAnnotationWindow->StartEdit();
715 void AnnotationTag::ClosePopup()
717 if( mpAnnotationWindow.get() )
719 mpAnnotationWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
720 mpAnnotationWindow->Deactivate();
721 mpAnnotationWindow.reset();
725 IMPL_LINK(AnnotationTag, WindowEventHandler, VclWindowEvent*, pEvent)
727 if( pEvent != NULL )
729 ::Window* pWindow = pEvent->GetWindow();
731 if( pWindow )
733 if( pWindow == mpAnnotationWindow.get() )
735 if( pEvent->GetId() == VCLEVENT_WINDOW_DEACTIVATE )
737 if( mnClosePopupEvent )
738 Application::RemoveUserEvent( mnClosePopupEvent );
740 mnClosePopupEvent = Application::PostUserEvent( LINK( this, AnnotationTag, ClosePopupHdl ) );
743 else if( pWindow == mpListenWindow )
745 switch( pEvent->GetId() )
747 case VCLEVENT_WINDOW_MOUSEBUTTONUP:
749 // if we stop pressing the button without a mouse move we open the popup
750 mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
751 mpListenWindow = 0;
752 if( mpAnnotationWindow.get() == 0 )
753 OpenPopup(false);
755 break;
756 case VCLEVENT_WINDOW_MOUSEMOVE:
758 // if we move the mouse after a button down we wan't to start draging
759 mpListenWindow->RemoveEventListener( LINK(this, AnnotationTag, WindowEventHandler));
760 mpListenWindow = 0;
762 SdrHdl* pHdl = mrView.PickHandle(maMouseDownPos);
763 if( pHdl )
765 mrView.BrkAction();
766 const USHORT nDrgLog = (USHORT)pWindow->PixelToLogic(Size(DRGPIX,0)).Width();
768 rtl::Reference< AnnotationTag > xTag( this );
770 SdrDragMethod* pDragMethod = new AnnotationDragMove( mrView, xTag );
771 mrView.BegDragObj(maMouseDownPos, NULL, pHdl, nDrgLog, pDragMethod );
774 break;
775 case VCLEVENT_OBJECT_DYING:
776 mpListenWindow = 0;
777 break;
782 return TRUE;
785 IMPL_LINK( AnnotationTag, ClosePopupHdl, void *, EMPTYARG )
787 mnClosePopupEvent = 0;
788 ClosePopup();
789 return 0;
792 } // end of namespace sd