/src/libreoffice/svx/source/dialog/imapwnd.cxx
Line | Count | Source (jump to first uncovered line) |
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 <tools/urlobj.hxx> |
21 | | #include <vcl/commandevent.hxx> |
22 | | #include <vcl/imaprect.hxx> |
23 | | #include <vcl/imapcirc.hxx> |
24 | | #include <vcl/imappoly.hxx> |
25 | | #include <vcl/svapp.hxx> |
26 | | #include <svl/urlbmk.hxx> |
27 | | |
28 | | #include <svx/svxids.hrc> |
29 | | #include "imapwnd.hxx" |
30 | | #include <svx/svdpage.hxx> |
31 | | #include <svx/svdorect.hxx> |
32 | | #include <svx/svdocirc.hxx> |
33 | | #include <svx/svdopath.hxx> |
34 | | #include <svx/xfltrit.hxx> |
35 | | #include <svx/svdpagv.hxx> |
36 | | #include <svx/xfillit0.hxx> |
37 | | #include <svx/xflclit.hxx> |
38 | | #include <svx/xlnclit.hxx> |
39 | | |
40 | | #include <sfx2/evntconf.hxx> |
41 | | |
42 | | #include <sot/formats.hxx> |
43 | | |
44 | | #include <svx/svxdlg.hxx> |
45 | | #include <basegfx/polygon/b2dpolygon.hxx> |
46 | | #include <memory> |
47 | | |
48 | | using namespace com::sun::star; |
49 | | using ::com::sun::star::frame::XFrame; |
50 | | using ::com::sun::star::uno::Reference; |
51 | | |
52 | 0 | #define TRANSCOL COL_WHITE |
53 | | |
54 | | static ItemInfoPackage& getItemInfoPackageIMapWindow() |
55 | 0 | { |
56 | 0 | class ItemInfoPackageIMapWindow : public ItemInfoPackage |
57 | 0 | { |
58 | 0 | typedef std::array<ItemInfoStatic, 1> ItemInfoArrayIMapWindow; |
59 | 0 | ItemInfoArrayIMapWindow maItemInfos {{ |
60 | | // m_nWhich, m_pItem, m_nSlotID, m_nItemInfoFlags |
61 | 0 | { SID_ATTR_MACROITEM, new SvxMacroItem(SID_ATTR_MACROITEM), 0, SFX_ITEMINFOFLAG_NONE } |
62 | 0 | }}; |
63 | |
|
64 | 0 | virtual const ItemInfoStatic& getItemInfoStatic(size_t nIndex) const override { return maItemInfos[nIndex]; } |
65 | |
|
66 | 0 | public: |
67 | 0 | virtual size_t size() const override { return maItemInfos.size(); } |
68 | 0 | virtual const ItemInfo& getItemInfo(size_t nIndex, SfxItemPool& /*rPool*/) override { return maItemInfos[nIndex]; } |
69 | 0 | }; |
70 | |
|
71 | 0 | static std::unique_ptr<ItemInfoPackageIMapWindow> g_aItemInfoPackageIMapWindow; |
72 | 0 | if (!g_aItemInfoPackageIMapWindow) |
73 | 0 | g_aItemInfoPackageIMapWindow.reset(new ItemInfoPackageIMapWindow); |
74 | 0 | return *g_aItemInfoPackageIMapWindow; |
75 | 0 | } |
76 | | |
77 | | IMapWindow::IMapWindow(const Reference< XFrame >& rxDocumentFrame, weld::Dialog* pDialog) |
78 | 0 | : GraphCtrl(pDialog) |
79 | 0 | , mxDocumentFrame(rxDocumentFrame) |
80 | 0 | { |
81 | 0 | pIMapPool = new SfxItemPool(u"IMapItemPool"_ustr); |
82 | 0 | pIMapPool->registerItemInfoPackage(getItemInfoPackageIMapWindow()); |
83 | 0 | } |
84 | | |
85 | | IMapWindow::~IMapWindow() |
86 | 0 | { |
87 | 0 | } |
88 | | |
89 | | void IMapWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea) |
90 | 0 | { |
91 | 0 | weld::CustomWidgetController::SetDrawingArea(pDrawingArea); |
92 | 0 | Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(270, 170), MapMode(MapUnit::MapAppFont))); |
93 | 0 | pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); |
94 | 0 | SetOutputSizePixel(aSize); |
95 | |
|
96 | 0 | SetSdrMode(true); |
97 | |
|
98 | 0 | mxDropTargetHelper.reset(new IMapDropTargetHelper(*this)); |
99 | 0 | } |
100 | | |
101 | | void IMapWindow::SetImageMap( const ImageMap& rImageMap ) |
102 | 0 | { |
103 | 0 | ReplaceImageMap( rImageMap ); |
104 | 0 | } |
105 | | |
106 | | void IMapWindow::ReplaceImageMap( const ImageMap& rImageMap ) |
107 | 0 | { |
108 | 0 | SdrPage* pPage = nullptr; |
109 | 0 | aIMap = rImageMap; |
110 | |
|
111 | 0 | if(GetSdrModel()) |
112 | 0 | { |
113 | | // try to access page |
114 | 0 | pPage = GetSdrModel()->GetPage(0); |
115 | 0 | } |
116 | |
|
117 | 0 | if(pPage) |
118 | 0 | { |
119 | | // clear SdrObjects with broadcasting |
120 | 0 | pPage->ClearSdrObjList(); |
121 | 0 | } |
122 | |
|
123 | 0 | if(GetSdrView()) |
124 | 0 | { |
125 | | // #i63762# reset selection at view |
126 | 0 | GetSdrView()->UnmarkAllObj(); |
127 | 0 | } |
128 | | |
129 | | // create new drawing objects |
130 | 0 | const sal_uInt16 nCount(rImageMap.GetIMapObjectCount()); |
131 | |
|
132 | 0 | for ( sal_uInt16 i(nCount); i > 0; i-- ) |
133 | 0 | { |
134 | 0 | rtl::Reference<SdrObject> pNewObj = CreateObj( rImageMap.GetIMapObject( i - 1 ) ); |
135 | |
|
136 | 0 | if (pNewObj && pPage) |
137 | 0 | { |
138 | 0 | pPage->InsertObject( pNewObj.get() ); |
139 | 0 | } |
140 | 0 | } |
141 | 0 | } |
142 | | |
143 | | void IMapWindow::ReplaceActualIMapInfo( const NotifyInfo& rNewInfo ) |
144 | 0 | { |
145 | 0 | const SdrObject* pSdrObj = GetSelectedSdrObject(); |
146 | |
|
147 | 0 | if ( pSdrObj ) |
148 | 0 | { |
149 | 0 | IMapObject* pIMapObj = GetIMapObj( pSdrObj ); |
150 | 0 | if (pIMapObj) |
151 | 0 | { |
152 | 0 | pIMapObj->SetURL( rNewInfo.aMarkURL ); |
153 | 0 | pIMapObj->SetAltText( rNewInfo.aMarkAltText ); |
154 | 0 | pIMapObj->SetTarget( rNewInfo.aMarkTarget ); |
155 | 0 | pModel->SetChanged(); |
156 | 0 | UpdateInfo( false ); |
157 | 0 | } |
158 | 0 | } |
159 | 0 | } |
160 | | |
161 | | const ImageMap& IMapWindow::GetImageMap() |
162 | 0 | { |
163 | 0 | if ( pModel->IsChanged() ) |
164 | 0 | { |
165 | 0 | SdrPage* pPage = pModel->GetPage( 0 ); |
166 | |
|
167 | 0 | if ( pPage ) |
168 | 0 | { |
169 | 0 | const size_t nCount = pPage->GetObjCount(); |
170 | |
|
171 | 0 | aIMap.ClearImageMap(); |
172 | |
|
173 | 0 | for ( size_t i = nCount; i; ) |
174 | 0 | { |
175 | 0 | --i; |
176 | 0 | aIMap.InsertIMapObject( *( static_cast<IMapUserData*>( pPage->GetObj( i )->GetUserData( 0 ) )->GetObject() ) ); |
177 | 0 | } |
178 | 0 | } |
179 | |
|
180 | 0 | pModel->SetChanged( false ); |
181 | 0 | } |
182 | |
|
183 | 0 | return aIMap; |
184 | 0 | } |
185 | | |
186 | | void IMapWindow::SetTargetList( const TargetList& rTargetList ) |
187 | 0 | { |
188 | | // Delete old List |
189 | | // Fill with the provided list |
190 | 0 | aTargetList = rTargetList; |
191 | |
|
192 | 0 | pModel->SetChanged( false ); |
193 | 0 | } |
194 | | |
195 | | rtl::Reference<SdrObject> IMapWindow::CreateObj( const IMapObject* pIMapObj ) |
196 | 0 | { |
197 | 0 | tools::Rectangle aClipRect( Point(), GetGraphicSize() ); |
198 | 0 | rtl::Reference<SdrObject> pSdrObj; |
199 | 0 | IMapObjectPtr pCloneIMapObj; |
200 | |
|
201 | 0 | switch( pIMapObj->GetType() ) |
202 | 0 | { |
203 | 0 | case IMapObjectType::Rectangle: |
204 | 0 | { |
205 | 0 | const IMapRectangleObject* pIMapRectObj = static_cast<const IMapRectangleObject*>(pIMapObj); |
206 | 0 | tools::Rectangle aDrawRect( pIMapRectObj->GetRectangle( false ) ); |
207 | | |
208 | | // clipped on CanvasPane |
209 | 0 | aDrawRect.Intersection( aClipRect ); |
210 | |
|
211 | 0 | pSdrObj = new SdrRectObj(*pModel, aDrawRect); |
212 | 0 | pCloneIMapObj.reset(static_cast<IMapObject*>(new IMapRectangleObject( *pIMapRectObj ))); |
213 | 0 | } |
214 | 0 | break; |
215 | | |
216 | 0 | case IMapObjectType::Circle: |
217 | 0 | { |
218 | 0 | const IMapCircleObject* pIMapCircleObj = static_cast<const IMapCircleObject*>(pIMapObj); |
219 | 0 | const Point aCenter( pIMapCircleObj->GetCenter( false ) ); |
220 | 0 | const tools::Long nRadius = pIMapCircleObj->GetRadius( false ); |
221 | 0 | const Point aOffset( nRadius, nRadius ); |
222 | 0 | tools::Rectangle aCircle( aCenter - aOffset, aCenter + aOffset ); |
223 | | |
224 | | // limited to CanvasPane |
225 | 0 | aCircle.Intersection( aClipRect ); |
226 | |
|
227 | 0 | pSdrObj = new SdrCircObj( |
228 | 0 | *pModel, |
229 | 0 | SdrCircKind::Full, |
230 | 0 | aCircle, |
231 | 0 | 0_deg100, |
232 | 0 | 36000_deg100); |
233 | 0 | pCloneIMapObj.reset(static_cast<IMapObject*>(new IMapCircleObject( *pIMapCircleObj ))); |
234 | 0 | } |
235 | 0 | break; |
236 | | |
237 | 0 | case IMapObjectType::Polygon: |
238 | 0 | { |
239 | 0 | const IMapPolygonObject* pIMapPolyObj = static_cast<const IMapPolygonObject*>(pIMapObj); |
240 | | |
241 | | // If it actually is an ellipse, then another ellipse is created again |
242 | 0 | if ( pIMapPolyObj->HasExtraEllipse() ) |
243 | 0 | { |
244 | 0 | tools::Rectangle aDrawRect( pIMapPolyObj->GetExtraEllipse() ); |
245 | | |
246 | | // clipped on CanvasPane |
247 | 0 | aDrawRect.Intersection( aClipRect ); |
248 | |
|
249 | 0 | pSdrObj = new SdrCircObj( |
250 | 0 | *pModel, |
251 | 0 | SdrCircKind::Full, |
252 | 0 | aDrawRect, |
253 | 0 | 0_deg100, |
254 | 0 | 36000_deg100); |
255 | 0 | } |
256 | 0 | else |
257 | 0 | { |
258 | 0 | const tools::Polygon aPoly = pIMapPolyObj->GetPolygon( false ); |
259 | 0 | tools::Polygon aDrawPoly( aPoly ); |
260 | | |
261 | | // clipped on CanvasPane |
262 | 0 | aDrawPoly.Clip( aClipRect ); |
263 | |
|
264 | 0 | basegfx::B2DPolygon aPolygon; |
265 | 0 | aPolygon.append(aDrawPoly.getB2DPolygon()); |
266 | 0 | pSdrObj = new SdrPathObj( |
267 | 0 | *pModel, |
268 | 0 | SdrObjKind::Polygon, |
269 | 0 | basegfx::B2DPolyPolygon(aPolygon)); |
270 | 0 | } |
271 | |
|
272 | 0 | pCloneIMapObj.reset(static_cast<IMapObject*>(new IMapPolygonObject( *pIMapPolyObj ))); |
273 | 0 | } |
274 | 0 | break; |
275 | | |
276 | 0 | default: |
277 | 0 | break; |
278 | 0 | } |
279 | | |
280 | 0 | if ( pSdrObj ) |
281 | 0 | { |
282 | 0 | SfxItemSet aSet( pModel->GetItemPool() ); |
283 | |
|
284 | 0 | aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); |
285 | 0 | aSet.Put( XFillColorItem( u""_ustr, TRANSCOL ) ); |
286 | |
|
287 | 0 | if ( !pIMapObj->IsActive() ) |
288 | 0 | { |
289 | 0 | aSet.Put( XFillTransparenceItem( 100 ) ); |
290 | 0 | aSet.Put( XLineColorItem( u""_ustr, COL_RED ) ); |
291 | 0 | } |
292 | 0 | else |
293 | 0 | { |
294 | 0 | aSet.Put( XFillTransparenceItem( 50 ) ); |
295 | 0 | aSet.Put( XLineColorItem( u""_ustr, COL_BLACK ) ); |
296 | 0 | } |
297 | |
|
298 | 0 | pSdrObj->SetMergedItemSetAndBroadcast(aSet); |
299 | |
|
300 | 0 | pSdrObj->AppendUserData( std::unique_ptr<SdrObjUserData>(new IMapUserData( std::move(pCloneIMapObj) )) ); |
301 | 0 | pSdrObj->SetUserCall( GetSdrUserCall() ); |
302 | 0 | } |
303 | |
|
304 | 0 | return pSdrObj; |
305 | 0 | } |
306 | | |
307 | | void IMapWindow::InitSdrModel() |
308 | 0 | { |
309 | 0 | GraphCtrl::InitSdrModel(); |
310 | |
|
311 | 0 | SfxItemSet aSet( pModel->GetItemPool() ); |
312 | |
|
313 | 0 | aSet.Put( XFillColorItem( u""_ustr, TRANSCOL ) ); |
314 | 0 | aSet.Put( XFillTransparenceItem( 50 ) ); |
315 | 0 | pView->SetAttributes( aSet ); |
316 | 0 | pView->SetFrameDragSingles(); |
317 | 0 | } |
318 | | |
319 | | void IMapWindow::SdrObjCreated( const SdrObject& rObj ) |
320 | 0 | { |
321 | 0 | switch( rObj.GetObjIdentifier() ) |
322 | 0 | { |
323 | 0 | case SdrObjKind::Rectangle: |
324 | 0 | { |
325 | 0 | SdrRectObj* pRectObj = const_cast<SdrRectObj*>(static_cast<const SdrRectObj*>(&rObj)); |
326 | 0 | auto pObj = std::make_shared<IMapRectangleObject>( pRectObj->GetLogicRect(), "", "", "", "", "", true, false ); |
327 | |
|
328 | 0 | pRectObj->AppendUserData( std::unique_ptr<SdrObjUserData>(new IMapUserData( pObj )) ); |
329 | 0 | } |
330 | 0 | break; |
331 | | |
332 | 0 | case SdrObjKind::CircleOrEllipse: |
333 | 0 | { |
334 | 0 | SdrCircObj* pCircObj = const_cast<SdrCircObj*>( static_cast<const SdrCircObj*>(&rObj) ); |
335 | 0 | rtl::Reference<SdrPathObj> pPathObj = static_cast<SdrPathObj*>( pCircObj->ConvertToPolyObj( false, false ).get() ); |
336 | 0 | tools::Polygon aPoly(pPathObj->GetPathPoly().getB2DPolygon(0)); |
337 | |
|
338 | 0 | pPathObj.clear(); |
339 | |
|
340 | 0 | auto pObj = std::make_shared<IMapPolygonObject>( aPoly, "", "", "", "", "", true, false ); |
341 | 0 | pObj->SetExtraEllipse( aPoly.GetBoundRect() ); |
342 | 0 | pCircObj->AppendUserData( std::unique_ptr<SdrObjUserData>(new IMapUserData( pObj )) ); |
343 | 0 | } |
344 | 0 | break; |
345 | | |
346 | 0 | case SdrObjKind::Polygon: |
347 | 0 | case SdrObjKind::FreehandFill: |
348 | 0 | case SdrObjKind::PathPoly: |
349 | 0 | case SdrObjKind::PathFill: |
350 | 0 | { |
351 | 0 | SdrPathObj* pPathObj = const_cast<SdrPathObj*>( static_cast<const SdrPathObj*>(&rObj) ); |
352 | 0 | const basegfx::B2DPolyPolygon& rXPolyPoly = pPathObj->GetPathPoly(); |
353 | |
|
354 | 0 | if ( rXPolyPoly.count() ) |
355 | 0 | { |
356 | 0 | tools::Polygon aPoly(rXPolyPoly.getB2DPolygon(0)); |
357 | 0 | auto pObj = std::make_shared<IMapPolygonObject>( aPoly, "", "", "", "", "", true, false ); |
358 | 0 | pPathObj->AppendUserData( std::unique_ptr<SdrObjUserData>(new IMapUserData( pObj )) ); |
359 | 0 | } |
360 | 0 | } |
361 | 0 | break; |
362 | | |
363 | 0 | default: |
364 | 0 | break; |
365 | 0 | } |
366 | 0 | } |
367 | | |
368 | | void IMapWindow::SdrObjChanged( const SdrObject& rObj ) |
369 | 0 | { |
370 | 0 | IMapUserData* pUserData = static_cast<IMapUserData*>( rObj.GetUserData( 0 ) ); |
371 | |
|
372 | 0 | if ( !pUserData ) |
373 | 0 | return; |
374 | | |
375 | 0 | OUString aURL; |
376 | 0 | OUString aAltText; |
377 | 0 | OUString aDesc; |
378 | 0 | OUString aTarget; |
379 | 0 | IMapObjectPtr pIMapObj = pUserData->GetObject(); |
380 | 0 | bool bActive = true; |
381 | |
|
382 | 0 | if ( pIMapObj ) |
383 | 0 | { |
384 | 0 | aURL = pIMapObj->GetURL(); |
385 | 0 | aAltText = pIMapObj->GetAltText(); |
386 | 0 | aDesc = pIMapObj->GetDesc(); |
387 | 0 | aTarget = pIMapObj->GetTarget(); |
388 | 0 | bActive = pIMapObj->IsActive(); |
389 | 0 | } |
390 | |
|
391 | 0 | switch( rObj.GetObjIdentifier() ) |
392 | 0 | { |
393 | 0 | case SdrObjKind::Rectangle: |
394 | 0 | { |
395 | 0 | pUserData->ReplaceObject( std::make_shared<IMapRectangleObject>( static_cast<const SdrRectObj&>(rObj).GetLogicRect(), |
396 | 0 | aURL, aAltText, aDesc, aTarget, "", bActive, false ) ); |
397 | 0 | } |
398 | 0 | break; |
399 | | |
400 | 0 | case SdrObjKind::CircleOrEllipse: |
401 | 0 | { |
402 | 0 | const SdrCircObj& rCircObj = static_cast<const SdrCircObj&>(rObj); |
403 | 0 | rtl::Reference<SdrPathObj> pPathObj = static_cast<SdrPathObj*>( rCircObj.ConvertToPolyObj( false, false ).get() ); |
404 | 0 | tools::Polygon aPoly(pPathObj->GetPathPoly().getB2DPolygon(0)); |
405 | |
|
406 | 0 | auto pObj = std::make_shared<IMapPolygonObject>( aPoly, aURL, aAltText, aDesc, aTarget, "", bActive, false ); |
407 | 0 | pObj->SetExtraEllipse( aPoly.GetBoundRect() ); |
408 | |
|
409 | 0 | pPathObj.clear(); |
410 | |
|
411 | 0 | pUserData->ReplaceObject( pObj ); |
412 | 0 | } |
413 | 0 | break; |
414 | | |
415 | 0 | case SdrObjKind::Polygon: |
416 | 0 | case SdrObjKind::FreehandFill: |
417 | 0 | case SdrObjKind::PathPoly: |
418 | 0 | case SdrObjKind::PathFill: |
419 | 0 | { |
420 | 0 | const SdrPathObj& rPathObj = static_cast<const SdrPathObj&>(rObj); |
421 | 0 | const basegfx::B2DPolyPolygon& rXPolyPoly = rPathObj.GetPathPoly(); |
422 | |
|
423 | 0 | if ( rXPolyPoly.count() ) |
424 | 0 | { |
425 | 0 | tools::Polygon aPoly(rPathObj.GetPathPoly().getB2DPolygon(0)); |
426 | 0 | auto pObj = std::make_shared<IMapPolygonObject>( aPoly, aURL, aAltText, aDesc, aTarget, "", bActive, false ); |
427 | 0 | pUserData->ReplaceObject( pObj ); |
428 | 0 | } |
429 | 0 | } |
430 | 0 | break; |
431 | | |
432 | 0 | default: |
433 | 0 | break; |
434 | 0 | } |
435 | 0 | } |
436 | | |
437 | | bool IMapWindow::MouseButtonUp(const MouseEvent& rMEvt) |
438 | 0 | { |
439 | 0 | bool bRet = GraphCtrl::MouseButtonUp( rMEvt ); |
440 | 0 | UpdateInfo( true ); |
441 | 0 | return bRet; |
442 | 0 | } |
443 | | |
444 | | void IMapWindow::MarkListHasChanged() |
445 | 0 | { |
446 | 0 | GraphCtrl::MarkListHasChanged(); |
447 | 0 | UpdateInfo( false ); |
448 | 0 | } |
449 | | |
450 | | SdrObject* IMapWindow::GetHitSdrObj( const Point& rPosPixel ) const |
451 | 0 | { |
452 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
453 | |
|
454 | 0 | SdrObject* pObj = nullptr; |
455 | 0 | Point aPt = rDevice.PixelToLogic( rPosPixel ); |
456 | |
|
457 | 0 | if ( tools::Rectangle( Point(), GetGraphicSize() ).Contains( aPt ) ) |
458 | 0 | { |
459 | 0 | SdrPage* pPage = pModel->GetPage( 0 ); |
460 | 0 | if ( pPage ) |
461 | 0 | { |
462 | 0 | for ( size_t i = pPage->GetObjCount(); i > 0; ) |
463 | 0 | { |
464 | 0 | --i; |
465 | 0 | SdrObject* pTestObj = pPage->GetObj( i ); |
466 | 0 | IMapObject* pIMapObj = GetIMapObj( pTestObj ); |
467 | |
|
468 | 0 | if ( pIMapObj && pIMapObj->IsHit( aPt ) ) |
469 | 0 | { |
470 | 0 | pObj = pTestObj; |
471 | 0 | break; |
472 | 0 | } |
473 | 0 | } |
474 | 0 | } |
475 | 0 | } |
476 | |
|
477 | 0 | return pObj; |
478 | 0 | } |
479 | | |
480 | | IMapObject* IMapWindow::GetIMapObj( const SdrObject* pSdrObj ) |
481 | 0 | { |
482 | 0 | IMapObject* pIMapObj = nullptr; |
483 | |
|
484 | 0 | if ( pSdrObj ) |
485 | 0 | { |
486 | 0 | IMapUserData* pUserData = static_cast<IMapUserData*>( pSdrObj->GetUserData( 0 ) ); |
487 | |
|
488 | 0 | if ( pUserData ) |
489 | 0 | pIMapObj = pUserData->GetObject().get(); |
490 | 0 | } |
491 | |
|
492 | 0 | return pIMapObj; |
493 | 0 | } |
494 | | |
495 | | bool IMapWindow::Command(const CommandEvent& rCEvt) |
496 | 0 | { |
497 | 0 | if ( rCEvt.GetCommand() == CommandEventId::ContextMenu ) |
498 | 0 | { |
499 | 0 | std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetDrawingArea(), u"svx/ui/imapmenu.ui"_ustr)); |
500 | 0 | mxPopupMenu = xBuilder->weld_menu(u"menu"_ustr); |
501 | 0 | const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); |
502 | 0 | const size_t nMarked = rMarkList.GetMarkCount(); |
503 | |
|
504 | 0 | mxPopupMenu->set_sensitive(u"url"_ustr, false); |
505 | 0 | mxPopupMenu->set_sensitive(u"active"_ustr, false); |
506 | 0 | mxPopupMenu->set_sensitive(u"macro"_ustr, false); |
507 | 0 | mxPopupMenu->set_sensitive(u"selectall"_ustr, pModel->GetPage(0)->GetObjCount() != rMarkList.GetMarkCount()); |
508 | |
|
509 | 0 | if ( !nMarked ) |
510 | 0 | { |
511 | 0 | mxPopupMenu->set_sensitive(u"arrange"_ustr, false); |
512 | 0 | mxPopupMenu->set_sensitive(u"delete"_ustr, false); |
513 | 0 | } |
514 | 0 | else |
515 | 0 | { |
516 | 0 | if ( nMarked == 1 ) |
517 | 0 | { |
518 | 0 | SdrObject* pSdrObj = GetSelectedSdrObject(); |
519 | |
|
520 | 0 | mxPopupMenu->set_sensitive(u"url"_ustr, true); |
521 | 0 | mxPopupMenu->set_sensitive(u"active"_ustr, true); |
522 | 0 | mxPopupMenu->set_sensitive(u"macro"_ustr, true); |
523 | 0 | mxPopupMenu->set_active(u"active"_ustr, GetIMapObj(pSdrObj)->IsActive()); |
524 | 0 | } |
525 | |
|
526 | 0 | mxPopupMenu->set_sensitive(u"arrange"_ustr, true); |
527 | 0 | mxPopupMenu->set_sensitive(u"delete"_ustr, true); |
528 | 0 | } |
529 | |
|
530 | 0 | MenuSelectHdl(mxPopupMenu->popup_at_rect(GetDrawingArea(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)))); |
531 | |
|
532 | 0 | mxPopupMenu.reset(); |
533 | |
|
534 | 0 | return true; |
535 | 0 | } |
536 | 0 | return CustomWidgetController::Command(rCEvt); |
537 | 0 | } |
538 | | |
539 | | IMapDropTargetHelper::IMapDropTargetHelper(IMapWindow& rImapWindow) |
540 | 0 | : DropTargetHelper(rImapWindow.GetDrawingArea()->get_drop_target()) |
541 | 0 | , m_rImapWindow(rImapWindow) |
542 | 0 | { |
543 | 0 | } |
544 | | |
545 | | sal_Int8 IMapDropTargetHelper::AcceptDrop( const AcceptDropEvent& rEvt ) |
546 | 0 | { |
547 | 0 | return m_rImapWindow.AcceptDrop(rEvt); |
548 | 0 | } |
549 | | |
550 | | sal_Int8 IMapDropTargetHelper::ExecuteDrop( const ExecuteDropEvent& rEvt ) |
551 | 0 | { |
552 | 0 | return m_rImapWindow.ExecuteDrop(rEvt); |
553 | 0 | } |
554 | | |
555 | | sal_Int8 IMapWindow::AcceptDrop( const AcceptDropEvent& rEvt ) |
556 | 0 | { |
557 | 0 | return( ( GetHitSdrObj( rEvt.maPosPixel ) != nullptr ) ? rEvt.mnAction : DND_ACTION_NONE ); |
558 | 0 | } |
559 | | |
560 | | sal_Int8 IMapWindow::ExecuteDrop( const ExecuteDropEvent& rEvt ) |
561 | 0 | { |
562 | 0 | sal_Int8 nRet = DND_ACTION_NONE; |
563 | |
|
564 | 0 | if (mxDropTargetHelper->IsDropFormatSupported(SotClipboardFormatId::NETSCAPE_BOOKMARK)) |
565 | 0 | { |
566 | 0 | INetBookmark aBookMark( u""_ustr, u""_ustr ); |
567 | 0 | SdrObject* pSdrObj = GetHitSdrObj( rEvt.maPosPixel ); |
568 | |
|
569 | 0 | if( pSdrObj && TransferableDataHelper( rEvt.maDropEvent.Transferable ).GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aBookMark ) ) |
570 | 0 | { |
571 | 0 | IMapObject* pIMapObj = GetIMapObj( pSdrObj ); |
572 | |
|
573 | 0 | pIMapObj->SetURL( aBookMark.GetURL() ); |
574 | 0 | pIMapObj->SetAltText( aBookMark.GetDescription() ); |
575 | 0 | pModel->SetChanged(); |
576 | 0 | pView->UnmarkAll(); |
577 | 0 | pView->MarkObj( pSdrObj, pView->GetSdrPageView() ); |
578 | 0 | UpdateInfo( true ); |
579 | 0 | nRet = rEvt.mnAction; |
580 | 0 | } |
581 | 0 | } |
582 | |
|
583 | 0 | return nRet; |
584 | 0 | } |
585 | | |
586 | | OUString IMapWindow::RequestHelp(tools::Rectangle& rHelpArea) |
587 | 0 | { |
588 | 0 | OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); |
589 | |
|
590 | 0 | Point aPos = rDevice.PixelToLogic(rHelpArea.TopLeft()); |
591 | |
|
592 | 0 | SdrPageView* pPageView = nullptr; |
593 | 0 | SdrObject* pSdrObj = pView->PickObj(aPos, pView->getHitTolLog(), pPageView); |
594 | 0 | if (pSdrObj) |
595 | 0 | { |
596 | 0 | const IMapObject* pIMapObj = GetIMapObj( pSdrObj ); |
597 | 0 | if ( pIMapObj ) |
598 | 0 | { |
599 | 0 | OUString aStr = pIMapObj->GetURL(); |
600 | 0 | if ( !aStr.isEmpty() ) |
601 | 0 | { |
602 | 0 | rHelpArea = rDevice.LogicToPixel(tools::Rectangle( Point(), GetGraphicSize())); |
603 | 0 | return aStr; |
604 | 0 | } |
605 | 0 | } |
606 | 0 | } |
607 | | |
608 | 0 | return OUString(); |
609 | 0 | } |
610 | | |
611 | | void IMapWindow::SetCurrentObjState( bool bActive ) |
612 | 0 | { |
613 | 0 | SdrObject* pObj = GetSelectedSdrObject(); |
614 | |
|
615 | 0 | if ( !pObj ) |
616 | 0 | return; |
617 | | |
618 | 0 | SfxItemSet aSet( pModel->GetItemPool() ); |
619 | |
|
620 | 0 | GetIMapObj( pObj )->SetActive( bActive ); |
621 | |
|
622 | 0 | aSet.Put( XFillColorItem( u""_ustr, TRANSCOL ) ); |
623 | |
|
624 | 0 | if ( !bActive ) |
625 | 0 | { |
626 | 0 | aSet.Put( XFillTransparenceItem( 100 ) ); |
627 | 0 | aSet.Put( XLineColorItem( u""_ustr, COL_RED ) ); |
628 | 0 | } |
629 | 0 | else |
630 | 0 | { |
631 | 0 | aSet.Put( XFillTransparenceItem( 50 ) ); |
632 | 0 | aSet.Put( XLineColorItem( u""_ustr, COL_BLACK ) ); |
633 | 0 | } |
634 | |
|
635 | 0 | pView->SetAttributes( aSet ); |
636 | 0 | } |
637 | | |
638 | | void IMapWindow::UpdateInfo( bool bNewObj ) |
639 | 0 | { |
640 | 0 | if ( !aInfoLink.IsSet() ) |
641 | 0 | return; |
642 | | |
643 | 0 | const SdrObject* pSdrObj = GetSelectedSdrObject(); |
644 | 0 | const IMapObject* pIMapObj = pSdrObj ? GetIMapObj( pSdrObj ) : nullptr; |
645 | |
|
646 | 0 | aInfo.bNewObj = bNewObj; |
647 | |
|
648 | 0 | if ( pIMapObj ) |
649 | 0 | { |
650 | 0 | aInfo.bOneMarked = true; |
651 | 0 | aInfo.aMarkURL = pIMapObj->GetURL(); |
652 | 0 | aInfo.aMarkAltText = pIMapObj->GetAltText(); |
653 | 0 | aInfo.aMarkTarget = pIMapObj->GetTarget(); |
654 | 0 | aInfo.bActivated = pIMapObj->IsActive(); |
655 | 0 | aInfoLink.Call( *this ); |
656 | 0 | } |
657 | 0 | else |
658 | 0 | { |
659 | 0 | aInfo.aMarkURL.clear(); |
660 | 0 | aInfo.aMarkAltText.clear(); |
661 | 0 | aInfo.aMarkTarget.clear(); |
662 | 0 | aInfo.bOneMarked = false; |
663 | 0 | aInfo.bActivated = false; |
664 | 0 | } |
665 | |
|
666 | 0 | aInfoLink.Call( *this ); |
667 | 0 | } |
668 | | |
669 | | void IMapWindow::DoMacroAssign() |
670 | 0 | { |
671 | 0 | SdrObject* pSdrObj = GetSelectedSdrObject(); |
672 | |
|
673 | 0 | if ( !pSdrObj ) |
674 | 0 | return; |
675 | | |
676 | 0 | auto xSet = std::make_unique<SfxItemSetFixed<SID_ATTR_MACROITEM, SID_ATTR_MACROITEM, SID_EVENTCONFIG, SID_EVENTCONFIG>> |
677 | 0 | (*pIMapPool); |
678 | |
|
679 | 0 | SfxEventNamesItem aNamesItem(SID_EVENTCONFIG); |
680 | 0 | aNamesItem.AddEvent( u"MouseOver"_ustr, u""_ustr, SvMacroItemId::OnMouseOver ); |
681 | 0 | aNamesItem.AddEvent( u"MouseOut"_ustr, u""_ustr, SvMacroItemId::OnMouseOut ); |
682 | 0 | xSet->Put( aNamesItem ); |
683 | |
|
684 | 0 | SvxMacroItem aMacroItem(SID_ATTR_MACROITEM); |
685 | 0 | IMapObject* pIMapObj = GetIMapObj( pSdrObj ); |
686 | 0 | aMacroItem.SetMacroTable( pIMapObj->GetMacroTable() ); |
687 | 0 | xSet->Put( aMacroItem ); |
688 | |
|
689 | 0 | SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); |
690 | 0 | VclPtr<SfxAbstractDialog> pMacroDlg(pFact->CreateEventConfigDialog(GetDrawingArea(), std::move(xSet), mxDocumentFrame)); |
691 | |
|
692 | 0 | pMacroDlg->StartExecuteAsync( |
693 | 0 | [this, pMacroDlg, pIMapObj] (sal_Int32 nResult)->void |
694 | 0 | { |
695 | 0 | if (nResult == RET_OK) |
696 | 0 | { |
697 | 0 | const SfxItemSet* pOutSet = pMacroDlg->GetOutputItemSet(); |
698 | 0 | pIMapObj->SetMacroTable( pOutSet->Get( SID_ATTR_MACROITEM ).GetMacroTable() ); |
699 | 0 | pModel->SetChanged(); |
700 | 0 | UpdateInfo( false ); |
701 | 0 | } |
702 | 0 | pMacroDlg->disposeOnce(); |
703 | 0 | } |
704 | 0 | ); |
705 | 0 | } |
706 | | |
707 | | void IMapWindow::DoPropertyDialog() |
708 | 0 | { |
709 | 0 | SdrObject* pSdrObj = GetSelectedSdrObject(); |
710 | |
|
711 | 0 | if ( !pSdrObj ) |
712 | 0 | return; |
713 | | |
714 | 0 | IMapObject* pIMapObj = GetIMapObj( pSdrObj ); |
715 | 0 | SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); |
716 | 0 | ScopedVclPtr<AbstractURLDlg> aDlg(pFact->CreateURLDialog(GetDrawingArea(), pIMapObj->GetURL(), pIMapObj->GetAltText(), pIMapObj->GetDesc(), |
717 | 0 | pIMapObj->GetTarget(), pIMapObj->GetName(), aTargetList)); |
718 | 0 | if ( aDlg->Execute() != RET_OK ) |
719 | 0 | return; |
720 | | |
721 | 0 | const OUString aURLText( aDlg->GetURL() ); |
722 | |
|
723 | 0 | if ( !aURLText.isEmpty() ) |
724 | 0 | { |
725 | 0 | INetURLObject aObj( aURLText, INetProtocol::File ); |
726 | 0 | DBG_ASSERT( aObj.GetProtocol() != INetProtocol::NotValid, "Invalid URL" ); |
727 | 0 | pIMapObj->SetURL( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); |
728 | 0 | } |
729 | 0 | else |
730 | 0 | pIMapObj->SetURL( aURLText ); |
731 | |
|
732 | 0 | pIMapObj->SetAltText( aDlg->GetAltText() ); |
733 | 0 | pIMapObj->SetDesc( aDlg->GetDesc() ); |
734 | 0 | pIMapObj->SetTarget( aDlg->GetTarget() ); |
735 | 0 | pIMapObj->SetName( aDlg->GetName() ); |
736 | 0 | pModel->SetChanged(); |
737 | 0 | UpdateInfo( true ); |
738 | 0 | } |
739 | | |
740 | | void IMapWindow::MenuSelectHdl(const OUString& rId) |
741 | 0 | { |
742 | 0 | if (rId == "url") |
743 | 0 | DoPropertyDialog(); |
744 | 0 | else if (rId == "macro") |
745 | 0 | DoMacroAssign(); |
746 | 0 | else if (rId == "active") |
747 | 0 | { |
748 | 0 | const bool bNewState = !mxPopupMenu->get_active(rId); |
749 | 0 | SetCurrentObjState(bNewState); |
750 | 0 | UpdateInfo( false ); |
751 | 0 | } |
752 | 0 | else if (rId == "front") |
753 | 0 | pView->PutMarkedToTop(); |
754 | 0 | else if (rId == "forward") |
755 | 0 | pView->MovMarkedToTop(); |
756 | 0 | else if (rId == "backward") |
757 | 0 | pView->MovMarkedToBtm(); |
758 | 0 | else if (rId == "back") |
759 | 0 | pView->PutMarkedToBtm(); |
760 | 0 | else if (rId == "selectall") |
761 | 0 | pView->MarkAll(); |
762 | 0 | else if (rId == "delete") |
763 | 0 | pView->DeleteMarked(); |
764 | 0 | } |
765 | | |
766 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |