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