1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <com/sun/star/frame/XFrame.hpp>
23 #include <sfx2/imagemgr.hxx>
24 #include <sfx2/viewfrm.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/app.hxx>
27 #include <sfx2/request.hxx>
28 #include <sfx2/dispatch.hxx>
30 #include <tools/rcid.h>
32 #include <vcl/help.hxx>
33 #include <vcl/lazydelete.hxx>
35 #include <svx/sdrpagewindow.hxx>
36 #include <svx/sdrpaintwindow.hxx>
37 #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
38 #include <svx/sdr/overlay/overlaybitmapex.hxx>
39 #include <svx/sdr/overlay/overlaymanager.hxx>
40 #include <svx/svxids.hrc>
42 #include "view/viewoverlaymanager.hxx"
44 #include "res_bmp.hrc"
45 #include "DrawDocShell.hxx"
46 #include "DrawViewShell.hxx"
47 #include "DrawController.hxx"
49 #include "strings.hrc"
50 #include "sdresid.hxx"
51 #include "EventMultiplexer.hxx"
52 #include "ViewShellManager.hxx"
55 #include "drawdoc.hxx"
56 #include "smarttag.hxx"
58 using namespace ::com::sun::star::uno
;
59 using namespace ::com::sun::star::frame
;
65 static const sal_uInt16 gButtonSlots
[] = { SID_INSERT_TABLE
, SID_INSERT_DIAGRAM
, SID_INSERT_GRAPHIC
, SID_INSERT_AVMEDIA
};
66 static const sal_uInt16 gButtonToolTips
[] = { STR_INSERT_TABLE
, STR_INSERT_CHART
, STR_INSERT_PICTURE
, STR_INSERT_MOVIE
};
68 static BitmapEx
loadImageResource( sal_uInt16 nId
)
70 SdResId
aResId( nId
);
71 aResId
.SetRT( RSC_BITMAP
);
73 return BitmapEx( aResId
);
76 static BitmapEx
* getButtonImage( int index
, bool large
)
78 static vcl::DeleteOnDeinit
< BitmapEx
> gSmallButtonImages
[BMP_PLACEHOLDER_SMALL_END
- BMP_PLACEHOLDER_SMALL_START
] = { 0, 0, 0, 0, 0, 0, 0, 0 };
79 static vcl::DeleteOnDeinit
< BitmapEx
> gLargeButtonImages
[BMP_PLACEHOLDER_LARGE_END
- BMP_PLACEHOLDER_LARGE_START
] = { 0, 0, 0, 0, 0, 0, 0, 0 };
81 if( !gSmallButtonImages
[0].get() )
83 for( sal_uInt16 i
= 0; i
< (BMP_PLACEHOLDER_SMALL_END
-BMP_PLACEHOLDER_SMALL_START
); i
++ )
85 gSmallButtonImages
[i
].set( new BitmapEx( loadImageResource( BMP_PLACEHOLDER_SMALL_START
+ i
) ) );
86 gLargeButtonImages
[i
].set( new BitmapEx( loadImageResource( BMP_PLACEHOLDER_LARGE_START
+ i
) ) );
92 return gLargeButtonImages
[index
].get();
96 return gSmallButtonImages
[index
].get();
100 const sal_uInt32 SMART_TAG_HDL_NUM
= SAL_MAX_UINT32
;
102 class ChangePlaceholderTag
: public SmartTag
104 friend class ImageButtonHdl
;
106 ChangePlaceholderTag( ::sd::View
& rView
, SdrObject
& rPlaceholderObj
);
107 virtual ~ChangePlaceholderTag();
109 /** returns true if the SmartTag handled the event. */
110 virtual bool MouseButtonDown( const MouseEvent
&, SmartHdl
& ) SAL_OVERRIDE
;
112 /** returns true if the SmartTag consumes this event. */
113 virtual bool KeyInput( const KeyEvent
& rKEvt
) SAL_OVERRIDE
;
115 BitmapEx
createOverlayImage( int nHighlight
= -1 );
118 virtual void addCustomHandles( SdrHdlList
& rHandlerList
) SAL_OVERRIDE
;
119 virtual void disposing() SAL_OVERRIDE
;
120 virtual void select() SAL_OVERRIDE
;
121 virtual void deselect() SAL_OVERRIDE
;
124 SdrObjectWeakRef mxPlaceholderObj
;
127 class ImageButtonHdl
: public SmartHdl
130 ImageButtonHdl( const SmartTagReference
& xTag
, /* sal_uInt16 nSID, const Image& rImage, const Image& rImageMO, */ const Point
& rPnt
);
131 virtual ~ImageButtonHdl();
132 virtual void CreateB2dIAObject() SAL_OVERRIDE
;
133 virtual bool IsFocusHdl() const SAL_OVERRIDE
;
134 virtual Pointer
GetPointer() const SAL_OVERRIDE
;
135 virtual bool isMarkable() const SAL_OVERRIDE
;
137 virtual void onMouseEnter(const MouseEvent
& rMEvt
) SAL_OVERRIDE
;
138 virtual void onMouseLeave() SAL_OVERRIDE
;
140 int getHighlightId() const { return mnHighlightId
; }
145 rtl::Reference
< ChangePlaceholderTag
> mxTag
;
152 ImageButtonHdl::ImageButtonHdl( const SmartTagReference
& xTag
/*, sal_uInt16 nSID, const Image& rImage, const Image& rImageMO*/, const Point
& rPnt
)
153 : SmartHdl( xTag
, rPnt
)
154 , mxTag( dynamic_cast< ChangePlaceholderTag
* >( xTag
.get() ) )
155 , mnHighlightId( -1 )
156 , maImageSize( 42, 42 )
161 ImageButtonHdl::~ImageButtonHdl()
166 void ImageButtonHdl::HideTip()
170 Help::HideTip( mnTip
);
175 void ImageButtonHdl::onMouseEnter(const MouseEvent
& rMEvt
)
178 if( pHdlList
&& pHdlList
->GetView())
180 int nHighlightId
= 0;
181 OutputDevice
* pDev
= pHdlList
->GetView()->GetFirstOutputDevice();
183 pDev
= Application::GetDefaultDevice();
185 Point
aMDPos( rMEvt
.GetPosPixel() );
186 aMDPos
-= pDev
->LogicToPixel( GetPos() );
188 nHighlightId
+= aMDPos
.X() > maImageSize
.Width() ? 1 : 0;
189 nHighlightId
+= aMDPos
.Y() > maImageSize
.Height() ? 2 : 0;
191 if( mnHighlightId
!= nHighlightId
)
195 mnHighlightId
= nHighlightId
;
199 SdResId
aResId( gButtonToolTips
[mnHighlightId
] );
200 aResId
.SetRT( RSC_STRING
);
202 OUString
aHelpText( aResId
);
203 Rectangle
aScreenRect( pDev
->LogicToPixel( GetPos() ), maImageSize
);
204 mnTip
= Help::ShowTip( static_cast< vcl::Window
* >( pHdlList
->GetView()->GetFirstOutputDevice() ), aScreenRect
, aHelpText
) ;
211 void ImageButtonHdl::onMouseLeave()
218 void ImageButtonHdl::CreateB2dIAObject()
220 // first throw away old one
223 const Point
aTagPos( GetPos() );
224 basegfx::B2DPoint
aPosition( aTagPos
.X(), aTagPos
.Y() );
226 BitmapEx
aBitmapEx( mxTag
->createOverlayImage( mnHighlightId
) ); // maImageMO.GetBitmapEx() : maImage.GetBitmapEx() );
227 maImageSize
= aBitmapEx
.GetSizePixel();
228 maImageSize
.Width() >>= 1;
229 maImageSize
.Height() >>= 1;
233 SdrMarkView
* pView
= pHdlList
->GetView();
235 if(pView
&& !pView
->areMarkHandlesHidden())
237 SdrPageView
* pPageView
= pView
->GetSdrPageView();
241 for(sal_uInt32 b
= 0; b
< pPageView
->PageWindowCount(); b
++)
243 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
245 SdrPaintWindow
& rPaintWindow
= rPageWindow
.GetPaintWindow();
246 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
247 if(rPaintWindow
.OutputToWindow() && xManager
.is() )
249 sdr::overlay::OverlayObject
* pOverlayObject
= 0;
251 pOverlayObject
= new sdr::overlay::OverlayBitmapEx( aPosition
, aBitmapEx
, 0, 0 );
252 xManager
->add(*pOverlayObject
);
253 maOverlayGroup
.append(*pOverlayObject
);
261 bool ImageButtonHdl::IsFocusHdl() const
266 bool ImageButtonHdl::isMarkable() const
271 Pointer
ImageButtonHdl::GetPointer() const
273 return Pointer( PointerStyle::Arrow
);
276 ChangePlaceholderTag::ChangePlaceholderTag( ::sd::View
& rView
, SdrObject
& rPlaceholderObj
)
278 , mxPlaceholderObj( &rPlaceholderObj
)
282 ChangePlaceholderTag::~ChangePlaceholderTag()
286 /** returns true if the ChangePlaceholderTag handled the event. */
287 bool ChangePlaceholderTag::MouseButtonDown( const MouseEvent
& /*rMEvt*/, SmartHdl
& rHdl
)
289 int nHighlightId
= static_cast< ImageButtonHdl
& >(rHdl
).getHighlightId();
290 if( nHighlightId
>= 0 )
292 sal_uInt16 nSID
= gButtonSlots
[nHighlightId
];
294 if( mxPlaceholderObj
.get() )
296 // mark placeholder if it is not currently marked (or if also others are marked)
297 if( !mrView
.IsObjMarked( mxPlaceholderObj
.get() ) || (mrView
.GetMarkedObjectList().GetMarkCount() != 1) )
299 SdrPageView
* pPV
= mrView
.GetSdrPageView();
300 mrView
.UnmarkAllObj(pPV
);
301 mrView
.MarkObj(mxPlaceholderObj
.get(), pPV
, false);
305 mrView
.GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( nSID
, SfxCallMode::ASYNCHRON
);
310 /** returns true if the SmartTag consumes this event. */
311 bool ChangePlaceholderTag::KeyInput( const KeyEvent
& rKEvt
)
313 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
329 BitmapEx
ChangePlaceholderTag::createOverlayImage( int nHighlight
)
332 if( mxPlaceholderObj
.is() )
334 SdrObject
* pPlaceholder
= mxPlaceholderObj
.get();
335 SmartTagReference
xThis( this );
336 const Rectangle
& rSnapRect
= pPlaceholder
->GetSnapRect();
338 OutputDevice
* pDev
= mrView
.GetFirstOutputDevice();
340 pDev
= Application::GetDefaultDevice();
342 Size aShapeSizePix
= pDev
->LogicToPixel(rSnapRect
.GetSize());
343 long nShapeSizePix
= std::min(aShapeSizePix
.Width(),aShapeSizePix
.Height());
345 bool bLarge
= nShapeSizePix
> 250;
347 Size
aSize( getButtonImage( 0, bLarge
)->GetSizePixel() );
349 aRet
.SetSizePixel( Size( aSize
.Width() << 1, aSize
.Height() << 1 ) );
351 const Rectangle
aRectSrc( Point( 0, 0 ), aSize
);
353 aRet
= *(getButtonImage((nHighlight
== 0) ? 4 : 0, bLarge
));
354 aRet
.Expand( aSize
.Width(), aSize
.Height(), NULL
, true );
356 aRet
.CopyPixel( Rectangle( Point( aSize
.Width(), 0 ), aSize
), aRectSrc
, getButtonImage((nHighlight
== 1) ? 5 : 1, bLarge
) );
357 aRet
.CopyPixel( Rectangle( Point( 0, aSize
.Height() ), aSize
), aRectSrc
, getButtonImage((nHighlight
== 2) ? 6 : 2, bLarge
) );
358 aRet
.CopyPixel( Rectangle( Point( aSize
.Width(), aSize
.Height() ), aSize
), aRectSrc
, getButtonImage((nHighlight
== 3) ? 7 : 3, bLarge
) );
364 void ChangePlaceholderTag::addCustomHandles( SdrHdlList
& rHandlerList
)
366 if( mxPlaceholderObj
.is() )
368 SdrObject
* pPlaceholder
= mxPlaceholderObj
.get();
369 SmartTagReference
xThis( this );
370 const Rectangle
& rSnapRect
= pPlaceholder
->GetSnapRect();
373 OutputDevice
* pDev
= mrView
.GetFirstOutputDevice();
375 pDev
= Application::GetDefaultDevice();
377 Size aShapeSizePix
= pDev
->LogicToPixel(rSnapRect
.GetSize());
378 long nShapeSizePix
= std::min(aShapeSizePix
.Width(),aShapeSizePix
.Height());
379 if( 50 > nShapeSizePix
)
382 bool bLarge
= nShapeSizePix
> 250;
384 Size
aButtonSize( pDev
->PixelToLogic( getButtonImage(0, bLarge
)->GetSizePixel()) );
386 const int nColumns
= 2;
389 long all_width
= nColumns
* aButtonSize
.Width();
390 long all_height
= nRows
* aButtonSize
.Height();
392 Point
aPos( rSnapRect
.Center() );
393 aPos
.X() -= all_width
>> 1;
394 aPos
.Y() -= all_height
>> 1;
396 ImageButtonHdl
* pHdl
= new ImageButtonHdl( xThis
, aPoint
);
397 pHdl
->SetObjHdlNum( SMART_TAG_HDL_NUM
);
398 pHdl
->SetPageView( mrView
.GetSdrPageView() );
400 pHdl
->SetPos( aPos
);
402 rHandlerList
.AddHdl( pHdl
);
406 void ChangePlaceholderTag::disposing()
408 SmartTag::disposing();
411 void ChangePlaceholderTag::select()
416 void ChangePlaceholderTag::deselect()
418 SmartTag::deselect();
421 ViewOverlayManager::ViewOverlayManager( ViewShellBase
& rViewShellBase
)
422 : mrBase( rViewShellBase
)
423 , mnUpdateTagsEvent( 0 )
425 Link
<> aLink( LINK(this,ViewOverlayManager
,EventMultiplexerListener
) );
426 mrBase
.GetEventMultiplexer()->AddEventListener(aLink
, tools::EventMultiplexerEvent::EID_CURRENT_PAGE
427 | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
428 | tools::EventMultiplexerEvent::EID_VIEW_ADDED
429 | tools::EventMultiplexerEvent::EID_BEGIN_TEXT_EDIT
430 | tools::EventMultiplexerEvent::EID_END_TEXT_EDIT
);
432 StartListening( *mrBase
.GetDocShell() );
435 ViewOverlayManager::~ViewOverlayManager()
437 Link
<> aLink( LINK(this,ViewOverlayManager
,EventMultiplexerListener
) );
438 mrBase
.GetEventMultiplexer()->RemoveEventListener( aLink
);
440 if( mnUpdateTagsEvent
)
442 Application::RemoveUserEvent( mnUpdateTagsEvent
);
443 mnUpdateTagsEvent
= 0;
449 void ViewOverlayManager::Notify(SfxBroadcaster
&, const SfxHint
& rHint
)
451 const SfxSimpleHint
* pSimpleHint
= dynamic_cast<const SfxSimpleHint
*>(&rHint
);
452 if (pSimpleHint
!= NULL
)
454 if (pSimpleHint
->GetId() == SFX_HINT_DOCCHANGED
)
461 void ViewOverlayManager::onZoomChanged()
463 if( !maTagVector
.empty() )
469 void ViewOverlayManager::UpdateTags()
471 if( !mnUpdateTagsEvent
)
472 mnUpdateTagsEvent
= Application::PostUserEvent( LINK( this, ViewOverlayManager
, UpdateTagsHdl
) );
475 IMPL_LINK_NOARG(ViewOverlayManager
, UpdateTagsHdl
)
477 OSL_TRACE("ViewOverlayManager::UpdateTagsHdl");
479 mnUpdateTagsEvent
= 0;
480 bool bChanges
= DisposeTags();
481 bChanges
|= CreateTags();
483 if( bChanges
&& mrBase
.GetDrawView() )
484 static_cast< ::sd::View
* >( mrBase
.GetDrawView() )->updateHandles();
488 bool ViewOverlayManager::CreateTags()
490 bool bChanges
= false;
492 ::boost::shared_ptr
<ViewShell
> aMainShell
= mrBase
.GetMainViewShell();
494 SdPage
* pPage
= aMainShell
.get() ? aMainShell
->getCurrentPage() : NULL
;
496 if( pPage
&& !pPage
->IsMasterPage() && (pPage
->GetPageKind() == PK_STANDARD
) )
498 const std::list
< SdrObject
* >& rShapes
= pPage
->GetPresentationShapeList().getList();
500 for( std::list
< SdrObject
* >::const_iterator
iter( rShapes
.begin() ); iter
!= rShapes
.end(); ++iter
)
502 if( (*iter
)->IsEmptyPresObj() && ((*iter
)->GetObjIdentifier() == OBJ_OUTLINETEXT
) && (mrBase
.GetDrawView()->GetTextEditObject() != (*iter
)) )
504 rtl::Reference
< SmartTag
> xTag( new ChangePlaceholderTag( *mrBase
.GetMainViewShell()->GetView(), *(*iter
) ) );
505 maTagVector
.push_back(xTag
);
514 bool ViewOverlayManager::DisposeTags()
516 if( !maTagVector
.empty() )
519 vec
.swap( maTagVector
);
521 ViewTagVector::iterator iter
= vec
.begin();
524 (*iter
++)->Dispose();
526 while( iter
!= vec
.end() );
533 IMPL_LINK(ViewOverlayManager
,EventMultiplexerListener
,
534 tools::EventMultiplexerEvent
*,pEvent
)
536 switch (pEvent
->meEventId
)
538 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
:
539 case tools::EventMultiplexerEvent::EID_VIEW_ADDED
:
540 case tools::EventMultiplexerEvent::EID_BEGIN_TEXT_EDIT
:
541 case tools::EventMultiplexerEvent::EID_END_TEXT_EDIT
:
542 case tools::EventMultiplexerEvent::EID_CURRENT_PAGE
:
551 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */