Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "sddll.hxx"
21 :
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>
29 :
30 : #include <tools/rcid.h>
31 :
32 : #include <vcl/help.hxx>
33 : #include <vcl/lazydelete.hxx>
34 :
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>
41 :
42 : #include "view/viewoverlaymanager.hxx"
43 :
44 : #include "res_bmp.hrc"
45 : #include "DrawDocShell.hxx"
46 : #include "DrawViewShell.hxx"
47 : #include "DrawController.hxx"
48 : #include "glob.hrc"
49 : #include "strings.hrc"
50 : #include "sdresid.hxx"
51 : #include "EventMultiplexer.hxx"
52 : #include "ViewShellManager.hxx"
53 : #include "helpids.h"
54 : #include "sdpage.hxx"
55 : #include "drawdoc.hxx"
56 : #include "smarttag.hxx"
57 :
58 : using namespace ::com::sun::star::uno;
59 : using namespace ::com::sun::star::frame;
60 :
61 : namespace sd {
62 :
63 : class ImageButtonHdl;
64 :
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 };
67 :
68 0 : static BitmapEx loadImageResource( sal_uInt16 nId )
69 : {
70 0 : SdResId aResId( nId );
71 0 : aResId.SetRT( RSC_BITMAP );
72 :
73 0 : return BitmapEx( aResId );
74 : }
75 :
76 0 : static BitmapEx* getButtonImage( int index, bool large )
77 : {
78 0 : static vcl::DeleteOnDeinit< BitmapEx > gSmallButtonImages[BMP_PLACEHOLDER_SMALL_END - BMP_PLACEHOLDER_SMALL_START] = { 0, 0, 0, 0, 0, 0, 0, 0 };
79 0 : static vcl::DeleteOnDeinit< BitmapEx > gLargeButtonImages[BMP_PLACEHOLDER_LARGE_END - BMP_PLACEHOLDER_LARGE_START] = { 0, 0, 0, 0, 0, 0, 0, 0 };
80 :
81 0 : if( !gSmallButtonImages[0].get() )
82 : {
83 0 : for( sal_uInt16 i = 0; i < (BMP_PLACEHOLDER_SMALL_END-BMP_PLACEHOLDER_SMALL_START); i++ )
84 : {
85 0 : gSmallButtonImages[i].set( new BitmapEx( loadImageResource( BMP_PLACEHOLDER_SMALL_START + i ) ) );
86 0 : gLargeButtonImages[i].set( new BitmapEx( loadImageResource( BMP_PLACEHOLDER_LARGE_START + i ) ) );
87 : }
88 : }
89 :
90 0 : if( large )
91 : {
92 0 : return gLargeButtonImages[index].get();
93 : }
94 : else
95 : {
96 0 : return gSmallButtonImages[index].get();
97 : }
98 : }
99 :
100 : const sal_uInt32 SMART_TAG_HDL_NUM = SAL_MAX_UINT32;
101 :
102 : class ChangePlaceholderTag : public SmartTag
103 : {
104 : friend class ImageButtonHdl;
105 : public:
106 : ChangePlaceholderTag( ::sd::View& rView, SdrObject& rPlaceholderObj );
107 : virtual ~ChangePlaceholderTag();
108 :
109 : /** returns true if the SmartTag handled the event. */
110 : virtual bool MouseButtonDown( const MouseEvent&, SmartHdl& ) SAL_OVERRIDE;
111 :
112 : /** returns true if the SmartTag consumes this event. */
113 : virtual bool KeyInput( const KeyEvent& rKEvt ) SAL_OVERRIDE;
114 :
115 : BitmapEx createOverlayImage( int nHighlight = -1 );
116 :
117 : protected:
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;
122 :
123 : private:
124 : SdrObjectWeakRef mxPlaceholderObj;
125 : };
126 :
127 : class ImageButtonHdl : public SmartHdl
128 : {
129 : public:
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;
136 :
137 : virtual void onMouseEnter(const MouseEvent& rMEvt) SAL_OVERRIDE;
138 : virtual void onMouseLeave() SAL_OVERRIDE;
139 :
140 0 : int getHighlightId() const { return mnHighlightId; }
141 :
142 : void HideTip();
143 :
144 : private:
145 : rtl::Reference< ChangePlaceholderTag > mxTag;
146 :
147 : int mnHighlightId;
148 : Size maImageSize;
149 : sal_uLong mnTip;
150 : };
151 :
152 0 : ImageButtonHdl::ImageButtonHdl( const SmartTagReference& xTag /*, sal_uInt16 nSID, const Image& rImage, const Image& rImageMO*/, const Point& rPnt )
153 : : SmartHdl( xTag, rPnt )
154 0 : , mxTag( dynamic_cast< ChangePlaceholderTag* >( xTag.get() ) )
155 : , mnHighlightId( -1 )
156 : , maImageSize( 42, 42 )
157 0 : , mnTip( 0 )
158 : {
159 0 : }
160 :
161 0 : ImageButtonHdl::~ImageButtonHdl()
162 : {
163 0 : HideTip();
164 0 : }
165 :
166 0 : void ImageButtonHdl::HideTip()
167 : {
168 0 : if( mnTip )
169 : {
170 0 : Help::HideTip( mnTip );
171 0 : mnTip = 0;
172 : }
173 0 : }
174 :
175 0 : void ImageButtonHdl::onMouseEnter(const MouseEvent& rMEvt)
176 : {
177 :
178 0 : if( pHdlList && pHdlList->GetView())
179 : {
180 0 : int nHighlightId = 0;
181 0 : OutputDevice* pDev = pHdlList->GetView()->GetFirstOutputDevice();
182 0 : if( pDev == 0 )
183 0 : pDev = Application::GetDefaultDevice();
184 :
185 0 : Point aMDPos( rMEvt.GetPosPixel() );
186 0 : aMDPos -= pDev->LogicToPixel( GetPos() );
187 :
188 0 : nHighlightId += aMDPos.X() > maImageSize.Width() ? 1 : 0;
189 0 : nHighlightId += aMDPos.Y() > maImageSize.Height() ? 2 : 0;
190 :
191 0 : if( mnHighlightId != nHighlightId )
192 : {
193 0 : HideTip();
194 :
195 0 : mnHighlightId = nHighlightId;
196 :
197 0 : if( pHdlList )
198 : {
199 0 : SdResId aResId( gButtonToolTips[mnHighlightId] );
200 0 : aResId.SetRT( RSC_STRING );
201 :
202 0 : OUString aHelpText( aResId );
203 0 : Rectangle aScreenRect( pDev->LogicToPixel( GetPos() ), maImageSize );
204 0 : mnTip = Help::ShowTip( static_cast< vcl::Window* >( pHdlList->GetView()->GetFirstOutputDevice() ), aScreenRect, aHelpText ) ;
205 : }
206 0 : Touch();
207 : }
208 : }
209 0 : }
210 :
211 0 : void ImageButtonHdl::onMouseLeave()
212 : {
213 0 : mnHighlightId = -1;
214 0 : HideTip();
215 0 : Touch();
216 0 : }
217 :
218 0 : void ImageButtonHdl::CreateB2dIAObject()
219 : {
220 : // first throw away old one
221 0 : GetRidOfIAObject();
222 :
223 0 : const Point aTagPos( GetPos() );
224 0 : basegfx::B2DPoint aPosition( aTagPos.X(), aTagPos.Y() );
225 :
226 0 : BitmapEx aBitmapEx( mxTag->createOverlayImage( mnHighlightId ) ); // maImageMO.GetBitmapEx() : maImage.GetBitmapEx() );
227 0 : maImageSize = aBitmapEx.GetSizePixel();
228 0 : maImageSize.Width() >>= 1;
229 0 : maImageSize.Height() >>= 1;
230 :
231 0 : if(pHdlList)
232 : {
233 0 : SdrMarkView* pView = pHdlList->GetView();
234 :
235 0 : if(pView && !pView->areMarkHandlesHidden())
236 : {
237 0 : SdrPageView* pPageView = pView->GetSdrPageView();
238 :
239 0 : if(pPageView)
240 : {
241 0 : for(sal_uInt32 b = 0; b < pPageView->PageWindowCount(); b++)
242 : {
243 0 : const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
244 :
245 0 : SdrPaintWindow& rPaintWindow = rPageWindow.GetPaintWindow();
246 0 : rtl::Reference< sdr::overlay::OverlayManager > xManager = rPageWindow.GetOverlayManager();
247 0 : if(rPaintWindow.OutputToWindow() && xManager.is() )
248 : {
249 0 : sdr::overlay::OverlayObject* pOverlayObject = 0;
250 :
251 0 : pOverlayObject = new sdr::overlay::OverlayBitmapEx( aPosition, aBitmapEx, 0, 0 );
252 0 : xManager->add(*pOverlayObject);
253 0 : maOverlayGroup.append(*pOverlayObject);
254 : }
255 0 : }
256 : }
257 : }
258 0 : }
259 0 : }
260 :
261 0 : bool ImageButtonHdl::IsFocusHdl() const
262 : {
263 0 : return false;
264 : }
265 :
266 0 : bool ImageButtonHdl::isMarkable() const
267 : {
268 0 : return false;
269 : }
270 :
271 0 : Pointer ImageButtonHdl::GetPointer() const
272 : {
273 0 : return Pointer( PointerStyle::Arrow );
274 : }
275 :
276 0 : ChangePlaceholderTag::ChangePlaceholderTag( ::sd::View& rView, SdrObject& rPlaceholderObj )
277 : : SmartTag( rView )
278 0 : , mxPlaceholderObj( &rPlaceholderObj )
279 : {
280 0 : }
281 :
282 0 : ChangePlaceholderTag::~ChangePlaceholderTag()
283 : {
284 0 : }
285 :
286 : /** returns true if the ChangePlaceholderTag handled the event. */
287 0 : bool ChangePlaceholderTag::MouseButtonDown( const MouseEvent& /*rMEvt*/, SmartHdl& rHdl )
288 : {
289 0 : int nHighlightId = static_cast< ImageButtonHdl& >(rHdl).getHighlightId();
290 0 : if( nHighlightId >= 0 )
291 : {
292 0 : sal_uInt16 nSID = gButtonSlots[nHighlightId];
293 :
294 0 : if( mxPlaceholderObj.get() )
295 : {
296 : // mark placeholder if it is not currently marked (or if also others are marked)
297 0 : if( !mrView.IsObjMarked( mxPlaceholderObj.get() ) || (mrView.GetMarkedObjectList().GetMarkCount() != 1) )
298 : {
299 0 : SdrPageView* pPV = mrView.GetSdrPageView();
300 0 : mrView.UnmarkAllObj(pPV );
301 0 : mrView.MarkObj(mxPlaceholderObj.get(), pPV, false);
302 : }
303 : }
304 :
305 0 : mrView.GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( nSID, SfxCallMode::ASYNCHRON);
306 : }
307 0 : return false;
308 : }
309 :
310 : /** returns true if the SmartTag consumes this event. */
311 0 : bool ChangePlaceholderTag::KeyInput( const KeyEvent& rKEvt )
312 : {
313 0 : sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
314 0 : switch( nCode )
315 : {
316 : case KEY_DOWN:
317 : case KEY_UP:
318 : case KEY_LEFT:
319 : case KEY_RIGHT:
320 : case KEY_ESCAPE:
321 : case KEY_TAB:
322 : case KEY_RETURN:
323 : case KEY_SPACE:
324 : default:
325 0 : return false;
326 : }
327 : }
328 :
329 0 : BitmapEx ChangePlaceholderTag::createOverlayImage( int nHighlight )
330 : {
331 0 : BitmapEx aRet;
332 0 : if( mxPlaceholderObj.is() )
333 : {
334 0 : SdrObject* pPlaceholder = mxPlaceholderObj.get();
335 0 : SmartTagReference xThis( this );
336 0 : const Rectangle& rSnapRect = pPlaceholder->GetSnapRect();
337 :
338 0 : OutputDevice* pDev = mrView.GetFirstOutputDevice();
339 0 : if( pDev == 0 )
340 0 : pDev = Application::GetDefaultDevice();
341 :
342 0 : Size aShapeSizePix = pDev->LogicToPixel(rSnapRect.GetSize());
343 0 : long nShapeSizePix = std::min(aShapeSizePix.Width(),aShapeSizePix.Height());
344 :
345 0 : bool bLarge = nShapeSizePix > 250;
346 :
347 0 : Size aSize( getButtonImage( 0, bLarge )->GetSizePixel() );
348 :
349 0 : aRet.SetSizePixel( Size( aSize.Width() << 1, aSize.Height() << 1 ) );
350 :
351 0 : const Rectangle aRectSrc( Point( 0, 0 ), aSize );
352 :
353 0 : aRet = *(getButtonImage((nHighlight == 0) ? 4 : 0, bLarge));
354 0 : aRet.Expand( aSize.Width(), aSize.Height(), NULL, true );
355 :
356 0 : aRet.CopyPixel( Rectangle( Point( aSize.Width(), 0 ), aSize ), aRectSrc, getButtonImage((nHighlight == 1) ? 5 : 1, bLarge) );
357 0 : aRet.CopyPixel( Rectangle( Point( 0, aSize.Height() ), aSize ), aRectSrc, getButtonImage((nHighlight == 2) ? 6 : 2, bLarge) );
358 0 : aRet.CopyPixel( Rectangle( Point( aSize.Width(), aSize.Height() ), aSize ), aRectSrc, getButtonImage((nHighlight == 3) ? 7 : 3, bLarge) );
359 : }
360 :
361 0 : return aRet;
362 : }
363 :
364 0 : void ChangePlaceholderTag::addCustomHandles( SdrHdlList& rHandlerList )
365 : {
366 0 : if( mxPlaceholderObj.is() )
367 : {
368 0 : SdrObject* pPlaceholder = mxPlaceholderObj.get();
369 0 : SmartTagReference xThis( this );
370 0 : const Rectangle& rSnapRect = pPlaceholder->GetSnapRect();
371 0 : const Point aPoint;
372 :
373 0 : OutputDevice* pDev = mrView.GetFirstOutputDevice();
374 0 : if( pDev == 0 )
375 0 : pDev = Application::GetDefaultDevice();
376 :
377 0 : Size aShapeSizePix = pDev->LogicToPixel(rSnapRect.GetSize());
378 0 : long nShapeSizePix = std::min(aShapeSizePix.Width(),aShapeSizePix.Height());
379 0 : if( 50 > nShapeSizePix )
380 0 : return;
381 :
382 0 : bool bLarge = nShapeSizePix > 250;
383 :
384 0 : Size aButtonSize( pDev->PixelToLogic( getButtonImage(0, bLarge )->GetSizePixel()) );
385 :
386 0 : const int nColumns = 2;
387 0 : const int nRows = 2;
388 :
389 0 : long all_width = nColumns * aButtonSize.Width();
390 0 : long all_height = nRows * aButtonSize.Height();
391 :
392 0 : Point aPos( rSnapRect.Center() );
393 0 : aPos.X() -= all_width >> 1;
394 0 : aPos.Y() -= all_height >> 1;
395 :
396 0 : ImageButtonHdl* pHdl = new ImageButtonHdl( xThis, aPoint );
397 0 : pHdl->SetObjHdlNum( SMART_TAG_HDL_NUM );
398 0 : pHdl->SetPageView( mrView.GetSdrPageView() );
399 :
400 0 : pHdl->SetPos( aPos );
401 :
402 0 : rHandlerList.AddHdl( pHdl );
403 : }
404 : }
405 :
406 0 : void ChangePlaceholderTag::disposing()
407 : {
408 0 : SmartTag::disposing();
409 0 : }
410 :
411 0 : void ChangePlaceholderTag::select()
412 : {
413 0 : SmartTag::select();
414 0 : }
415 :
416 0 : void ChangePlaceholderTag::deselect()
417 : {
418 0 : SmartTag::deselect();
419 0 : }
420 :
421 133 : ViewOverlayManager::ViewOverlayManager( ViewShellBase& rViewShellBase )
422 : : mrBase( rViewShellBase )
423 133 : , mnUpdateTagsEvent( 0 )
424 : {
425 133 : 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 133 : | tools::EventMultiplexerEvent::EID_END_TEXT_EDIT );
431 :
432 133 : StartListening( *mrBase.GetDocShell() );
433 133 : }
434 :
435 399 : ViewOverlayManager::~ViewOverlayManager()
436 : {
437 133 : Link<> aLink( LINK(this,ViewOverlayManager,EventMultiplexerListener) );
438 133 : mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
439 :
440 133 : if( mnUpdateTagsEvent )
441 : {
442 75 : Application::RemoveUserEvent( mnUpdateTagsEvent );
443 75 : mnUpdateTagsEvent = 0;
444 : }
445 :
446 133 : DisposeTags();
447 266 : }
448 :
449 43101 : void ViewOverlayManager::Notify(SfxBroadcaster&, const SfxHint& rHint)
450 : {
451 43101 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
452 43101 : if (pSimpleHint != NULL)
453 : {
454 42398 : if (pSimpleHint->GetId() == SFX_HINT_DOCCHANGED)
455 : {
456 41891 : UpdateTags();
457 : }
458 : }
459 43101 : }
460 :
461 430 : void ViewOverlayManager::onZoomChanged()
462 : {
463 430 : if( !maTagVector.empty() )
464 : {
465 0 : UpdateTags();
466 : }
467 430 : }
468 :
469 42358 : void ViewOverlayManager::UpdateTags()
470 : {
471 42358 : if( !mnUpdateTagsEvent )
472 403 : mnUpdateTagsEvent = Application::PostUserEvent( LINK( this, ViewOverlayManager, UpdateTagsHdl ) );
473 42358 : }
474 :
475 656 : IMPL_LINK_NOARG(ViewOverlayManager, UpdateTagsHdl)
476 : {
477 : OSL_TRACE("ViewOverlayManager::UpdateTagsHdl");
478 :
479 328 : mnUpdateTagsEvent = 0;
480 328 : bool bChanges = DisposeTags();
481 328 : bChanges |= CreateTags();
482 :
483 328 : if( bChanges && mrBase.GetDrawView() )
484 0 : static_cast< ::sd::View* >( mrBase.GetDrawView() )->updateHandles();
485 328 : return 0;
486 : }
487 :
488 328 : bool ViewOverlayManager::CreateTags()
489 : {
490 328 : bool bChanges = false;
491 :
492 328 : ::boost::shared_ptr<ViewShell> aMainShell = mrBase.GetMainViewShell();
493 :
494 328 : SdPage* pPage = aMainShell.get() ? aMainShell->getCurrentPage() : NULL;
495 :
496 328 : if( pPage && !pPage->IsMasterPage() && (pPage->GetPageKind() == PK_STANDARD) )
497 : {
498 328 : const std::list< SdrObject* >& rShapes = pPage->GetPresentationShapeList().getList();
499 :
500 381 : for( std::list< SdrObject* >::const_iterator iter( rShapes.begin() ); iter != rShapes.end(); ++iter )
501 : {
502 53 : if( (*iter)->IsEmptyPresObj() && ((*iter)->GetObjIdentifier() == OBJ_OUTLINETEXT) && (mrBase.GetDrawView()->GetTextEditObject() != (*iter)) )
503 : {
504 0 : rtl::Reference< SmartTag > xTag( new ChangePlaceholderTag( *mrBase.GetMainViewShell()->GetView(), *(*iter) ) );
505 0 : maTagVector.push_back(xTag);
506 0 : bChanges = true;
507 : }
508 : }
509 : }
510 :
511 328 : return bChanges;
512 : }
513 :
514 461 : bool ViewOverlayManager::DisposeTags()
515 : {
516 461 : if( !maTagVector.empty() )
517 : {
518 0 : ViewTagVector vec;
519 0 : vec.swap( maTagVector );
520 :
521 0 : ViewTagVector::iterator iter = vec.begin();
522 0 : do
523 : {
524 0 : (*iter++)->Dispose();
525 : }
526 0 : while( iter != vec.end() );
527 0 : return true;
528 : }
529 :
530 461 : return false;
531 : }
532 :
533 11124 : IMPL_LINK(ViewOverlayManager,EventMultiplexerListener,
534 : tools::EventMultiplexerEvent*,pEvent)
535 : {
536 5562 : switch (pEvent->meEventId)
537 : {
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:
543 467 : UpdateTags();
544 467 : break;
545 : }
546 5562 : return 0;
547 : }
548 :
549 66 : }
550 :
551 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|