xref: /core/cui/source/tabpages/tpbitmap.cxx (revision 322a6ca8)
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 <memory>
21 #include <stdlib.h>
22 #include <tools/urlobj.hxx>
23 #include <svx/xbtmpit.hxx>
24 #include <svx/svxids.hrc>
25 #include <strings.hrc>
26 #include <svx/xfillit0.hxx>
27 #include <svx/xtable.hxx>
28 #include <svx/xflbmsxy.hxx>
29 #include <svx/xflbmtit.hxx>
30 #include <svx/xflbstit.hxx>
31 #include <svx/xflbmsli.hxx>
32 #include <svx/xflbmpit.hxx>
33 #include <svx/xflboxy.hxx>
34 #include <svx/xflbtoxy.hxx>
35 #include <cuitabarea.hxx>
36 #include <dialmgr.hxx>
37 #include <svx/dlgutil.hxx>
38 #include <svl/intitem.hxx>
39 #include <sfx2/opengrf.hxx>
40 #include <vcl/image.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/weld.hxx>
43 #include <svx/svxdlg.hxx>
44 #include <sfx2/viewsh.hxx>
45 #include <sfx2/dialoghelper.hxx>
46 #include <sal/log.hxx>
47 #include <comphelper/lok.hxx>
48 #include <svtools/unitconv.hxx>
49 
50 using namespace com::sun::star;
51 
52 namespace {
53 
54 enum BitmapStyle
55 {
56     CUSTOM,
57     TILED,
58     STRETCHED
59 };
60 
61 enum TileOffset
62 {
63     ROW,
64     COLUMN
65 };
66 
67 }
68 
SvxBitmapTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rInAttrs)69 SvxBitmapTabPage::SvxBitmapTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
70     : SfxTabPage(pPage, pController, u"cui/ui/imagetabpage.ui"_ustr, u"ImageTabPage"_ustr, &rInAttrs)
71     , m_rOutAttrs(rInAttrs)
72     , m_pnBitmapListState(nullptr)
73     , m_fObjectWidth(0.0)
74     , m_fObjectHeight(0.0)
75     , m_bLogicalSize(false)
76     , m_aXFillAttr(rInAttrs.GetPool())
77     , m_rXFSet(m_aXFillAttr.GetItemSet())
78     , mpView(nullptr)
79     , m_xBitmapLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window(u"imagewin"_ustr, true)))
80     , m_xBitmapStyleLB(m_xBuilder->weld_combo_box(u"imagestyle"_ustr))
81     , m_xSizeBox(m_xBuilder->weld_container(u"sizebox"_ustr))
82     , m_xTsbScale(m_xBuilder->weld_check_button(u"scaletsb"_ustr))
83     , m_xBitmapWidth(m_xBuilder->weld_metric_spin_button(u"width"_ustr, FieldUnit::PERCENT))
84     , m_xBitmapHeight(m_xBuilder->weld_metric_spin_button(u"height"_ustr, FieldUnit::PERCENT))
85     , m_xPositionBox(m_xBuilder->weld_container(u"posbox"_ustr))
86     , m_xPositionLB(m_xBuilder->weld_combo_box(u"positionlb"_ustr))
87     , m_xPositionOffBox(m_xBuilder->weld_container(u"posoffbox"_ustr))
88     , m_xPositionOffX(m_xBuilder->weld_metric_spin_button(u"posoffx"_ustr, FieldUnit::PERCENT))
89     , m_xPositionOffY(m_xBuilder->weld_metric_spin_button(u"posoffy"_ustr, FieldUnit::PERCENT))
90     , m_xTileOffBox(m_xBuilder->weld_container(u"tileoffbox"_ustr))
91     , m_xTileOffLB(m_xBuilder->weld_combo_box(u"tileofflb"_ustr))
92     , m_xTileOffset(m_xBuilder->weld_metric_spin_button(u"tileoffmtr"_ustr, FieldUnit::PERCENT))
93     , m_xBtnImport(m_xBuilder->weld_button(u"BTN_IMPORT"_ustr))
94     , m_xCtlBitmapPreview(new weld::CustomWeld(*m_xBuilder, u"CTL_IMAGE_PREVIEW"_ustr, m_aCtlBitmapPreview))
95     , m_xBitmapLBWin(new weld::CustomWeld(*m_xBuilder, u"IMAGE"_ustr, *m_xBitmapLB))
96 {
97     // setting the output device
98     m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_BITMAP) );
99     m_rXFSet.Put( XFillBitmapItem(OUString(), Graphic()) );
100     m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() );
101 
102     m_xBitmapLB->SetSelectHdl( LINK(this, SvxBitmapTabPage, ModifyBitmapHdl) );
103     m_xBitmapLB->SetRenameHdl( LINK(this, SvxBitmapTabPage, ClickRenameHdl) );
104     m_xBitmapLB->SetDeleteHdl( LINK(this, SvxBitmapTabPage, ClickDeleteHdl) );
105     m_xBitmapStyleLB->connect_changed( LINK(this, SvxBitmapTabPage, ModifyBitmapStyleHdl) );
106     Link<weld::MetricSpinButton&, void> aLink1( LINK(this, SvxBitmapTabPage, ModifyBitmapSizeHdl) );
107     m_xBitmapWidth->connect_value_changed( aLink1 );
108     m_xBitmapHeight->connect_value_changed( aLink1 );
109     m_xTsbScale->connect_toggled(LINK(this, SvxBitmapTabPage, ClickScaleHdl));
110     m_xPositionLB->connect_changed( LINK( this, SvxBitmapTabPage, ModifyBitmapPositionHdl ) );
111     Link<weld::MetricSpinButton&, void> aLink( LINK( this, SvxBitmapTabPage, ModifyPositionOffsetHdl ) );
112     m_xPositionOffX->connect_value_changed(aLink);
113     m_xPositionOffY->connect_value_changed(aLink);
114     m_xTileOffset->connect_value_changed( LINK( this, SvxBitmapTabPage, ModifyTileOffsetHdl ) );
115     m_xBtnImport->connect_clicked( LINK(this, SvxBitmapTabPage, ClickImportHdl) );
116     if (comphelper::LibreOfficeKit::isActive())
117         m_xBtnImport->hide();
118 
119     // Calculate size of display boxes
120     Size aSize = getDrawPreviewOptimalSize(m_aCtlBitmapPreview.GetDrawingArea()->get_ref_device());
121     m_xBitmapLB->set_size_request(aSize.Width(), aSize.Height());
122     m_xCtlBitmapPreview->set_size_request(aSize.Width(), aSize.Height());
123 
124     SfxItemPool* pPool = m_rXFSet.GetPool();
125     mePoolUnit = pPool->GetMetric( XATTR_FILLBMP_SIZEX );
126     meFieldUnit = GetModuleFieldUnit( rInAttrs );
127     SetFieldUnit( *m_xBitmapWidth, meFieldUnit, true );
128     SetFieldUnit( *m_xBitmapHeight, meFieldUnit, true );
129 
130     m_xBitmapLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP);
131 
132     SfxViewShell* pViewShell = SfxViewShell::Current();
133     if( pViewShell )
134         mpView = pViewShell->GetDrawView();
135     DBG_ASSERT( mpView, "no valid view (!)" );
136 }
137 
~SvxBitmapTabPage()138 SvxBitmapTabPage::~SvxBitmapTabPage()
139 {
140     m_xBitmapLBWin.reset();
141     m_xBitmapLB.reset();
142     m_xCtlBitmapPreview.reset();
143 }
144 
Construct()145 void SvxBitmapTabPage::Construct()
146 {
147     m_xBitmapLB->FillPresetListBox( *m_pBitmapList );
148 }
149 
ActivatePage(const SfxItemSet & rSet)150 void SvxBitmapTabPage::ActivatePage( const SfxItemSet& rSet )
151 {
152     XFillBitmapItem aItem( rSet.Get(XATTR_FILLBITMAP) );
153 
154     sal_Int32 nPos( 0 );
155     if ( !aItem.isPattern() )
156     {
157         nPos = SearchBitmapList( aItem.GetGraphicObject() );
158         if (nPos == -1)
159             return;
160     }
161     else
162     {
163         m_xBitmapWidth->set_value( 100, FieldUnit::NONE );
164         m_xBitmapHeight->set_value( 100, FieldUnit::NONE );
165         const_cast<SfxItemSet&>(rSet).Put( XFillBmpSizeXItem( GetCoreValue( *m_xBitmapWidth, mePoolUnit ) ) );
166         const_cast<SfxItemSet&>(rSet).Put( XFillBmpSizeYItem( GetCoreValue( *m_xBitmapHeight, mePoolUnit ) ) );
167     }
168 
169     sal_uInt16 nId = m_xBitmapLB->GetItemId( static_cast<size_t>( nPos ) );
170     m_xBitmapLB->SelectItem( nId );
171 }
172 
DeactivatePage(SfxItemSet * _pSet)173 DeactivateRC SvxBitmapTabPage::DeactivatePage( SfxItemSet* _pSet )
174 {
175     if( _pSet )
176         FillItemSet( _pSet );
177 
178     return DeactivateRC::LeavePage;
179 }
180 
181 
FillItemSet(SfxItemSet * rAttrs)182 bool SvxBitmapTabPage::FillItemSet( SfxItemSet* rAttrs )
183 {
184     rAttrs->Put(XFillStyleItem(drawing::FillStyle_BITMAP));
185     size_t nPos = m_xBitmapLB->GetSelectItemPos();
186     if(VALUESET_ITEM_NOTFOUND != nPos)
187     {
188         const XBitmapEntry* pXBitmapEntry = m_pBitmapList->GetBitmap(nPos);
189         const OUString aString(m_xBitmapLB->GetItemText( m_xBitmapLB->GetSelectedItemId() ));
190         rAttrs->Put(XFillBitmapItem(aString, pXBitmapEntry->GetGraphicObject()));
191     }
192 
193     BitmapStyle eStylePos = static_cast<BitmapStyle>(m_xBitmapStyleLB->get_active());
194     bool bIsStretched( eStylePos == STRETCHED );
195     bool bIsTiled( eStylePos == TILED );
196 
197     rAttrs->Put( XFillBmpTileItem(bIsTiled) );
198     rAttrs->Put( XFillBmpStretchItem(bIsStretched) );
199 
200     if(!bIsStretched)
201     {
202         Size aSetBitmapSize;
203         switch(eStylePos)
204         {
205             case CUSTOM:
206             case TILED:
207             {
208                 sal_Int64 nWidthPercent = m_xBitmapWidth->get_value(FieldUnit::NONE);
209                 sal_Int64 nHeightPercent = m_xBitmapHeight->get_value(FieldUnit::NONE);
210                 if (m_xTsbScale->get_sensitive() && m_xTsbScale->get_state() == TRISTATE_TRUE)
211                 {
212                     aSetBitmapSize.setWidth( -nWidthPercent );
213                     aSetBitmapSize.setHeight( -nHeightPercent );
214                 }
215                 else if (!m_bLogicalSize)
216                 {
217                     aSetBitmapSize.setWidth( GetCoreValue(*m_xBitmapWidth, mePoolUnit) );
218                     aSetBitmapSize.setHeight( GetCoreValue(*m_xBitmapHeight, mePoolUnit) );
219                 }
220                 else
221                 {
222                     rAttrs->Put( XFillBmpSizeLogItem(true) );
223                     aSetBitmapSize.setWidth( 0 );
224                     aSetBitmapSize.setHeight( 0 );
225                 }
226 
227                 break;
228             }
229             default:
230                 break;
231         }
232 
233         rAttrs->Put( XFillBmpSizeXItem( aSetBitmapSize.Width() ) );
234         rAttrs->Put( XFillBmpSizeYItem( aSetBitmapSize.Height() ) );
235     }
236 
237     if (m_xPositionLB->get_sensitive())
238         rAttrs->Put( XFillBmpPosItem( static_cast<RectPoint>( m_xPositionLB->get_active() ) ) );
239     if (m_xPositionOffX->get_sensitive())
240         rAttrs->Put( XFillBmpPosOffsetXItem(m_xPositionOffX->get_value(FieldUnit::PERCENT)));
241     if (m_xPositionOffY->get_sensitive())
242         rAttrs->Put( XFillBmpPosOffsetYItem(m_xPositionOffY->get_value(FieldUnit::PERCENT)));
243     if (m_xTileOffBox->get_sensitive())
244     {
245         TileOffset eValue = static_cast<TileOffset>(m_xTileOffLB->get_active());
246         sal_uInt16 nOffsetValue = static_cast<sal_uInt16>(m_xTileOffset->get_value(FieldUnit::PERCENT));
247         sal_uInt16 nRowOff = (eValue == ROW) ? nOffsetValue : 0;
248         sal_uInt16 nColOff = (eValue == COLUMN) ? nOffsetValue : 0;
249         rAttrs->Put( XFillBmpTileOffsetXItem(nRowOff) );
250         rAttrs->Put( XFillBmpTileOffsetYItem(nColOff) );
251     }
252     return true;
253 }
254 
255 
Reset(const SfxItemSet * rAttrs)256 void SvxBitmapTabPage::Reset( const SfxItemSet* rAttrs )
257 {
258     double transfWidth = 0.0;
259     double transfHeight = 0.0;
260     double fUIScale  = 1.0;
261     if (mpView)
262     {
263         fUIScale  = double(mpView->GetModel().GetUIScale());
264 
265 
266         if (mpView->GetMarkedObjectList().GetMarkCount() != 0)
267         {
268             SfxItemSet rGeoAttr(mpView->GetGeoAttrFromMarked());
269             transfWidth = static_cast<double>(GetItem( rGeoAttr, SID_ATTR_TRANSFORM_WIDTH )->GetValue());
270             transfHeight= static_cast<double>(GetItem( rGeoAttr, SID_ATTR_TRANSFORM_HEIGHT )->GetValue());
271         }
272     }
273     m_fObjectWidth = std::max( transfWidth, 1.0 );
274     m_fObjectHeight = std::max( transfHeight, 1.0 );
275     double fTmpWidth((OutputDevice::LogicToLogic(static_cast<sal_Int32>(m_fObjectWidth), mePoolUnit, MapUnit::Map100thMM )) / fUIScale);
276     m_fObjectWidth = fTmpWidth;
277 
278     double fTmpHeight((OutputDevice::LogicToLogic(static_cast<sal_Int32>(m_fObjectHeight), mePoolUnit, MapUnit::Map100thMM )) / fUIScale);
279     m_fObjectHeight = fTmpHeight;
280 
281     XFillBitmapItem aItem( rAttrs->Get(XATTR_FILLBITMAP) );
282 
283     if(!aItem.isPattern())
284     {
285         m_rXFSet.Put( aItem );
286         m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() );
287         m_aCtlBitmapPreview.Invalidate();
288     }
289     else
290         m_xCtlBitmapPreview->set_sensitive(false);
291 
292     std::unique_ptr<GraphicObject> pGraphicObject;
293     pGraphicObject.reset( new GraphicObject(aItem.GetGraphicObject()) );
294 
295     BitmapEx aBmpEx(pGraphicObject->GetGraphic().GetBitmapEx());
296     Size aTempBitmapSize = aBmpEx.GetSizePixel();
297     rBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aTempBitmapSize, MapMode(MapUnit::Map100thMM));
298     CalculateBitmapPresetSize();
299 
300     bool bTiled = false; bool bStretched = false;
301     if(rAttrs->GetItemState( XATTR_FILLBMP_TILE ) != SfxItemState::INVALID)
302         bTiled = rAttrs->Get( XATTR_FILLBMP_TILE ).GetValue();
303     if(rAttrs->GetItemState( XATTR_FILLBMP_STRETCH ) != SfxItemState::INVALID)
304         bStretched = rAttrs->Get( XATTR_FILLBMP_STRETCH ).GetValue();
305 
306     if (bTiled)
307         m_xBitmapStyleLB->set_active(static_cast<sal_Int32>(TILED));
308     else if (bStretched)
309         m_xBitmapStyleLB->set_active(static_cast<sal_Int32>(STRETCHED));
310     else
311         m_xBitmapStyleLB->set_active(static_cast<sal_Int32>(CUSTOM));
312 
313     tools::Long nWidth = 0;
314     tools::Long nHeight = 0;
315 
316     if(rAttrs->GetItemState(XATTR_FILLBMP_SIZELOG) != SfxItemState::INVALID)
317     {
318         if (rAttrs->Get( XATTR_FILLBMP_SIZELOG ).GetValue())
319             m_xTsbScale->set_state(TRISTATE_FALSE);
320         else
321             m_xTsbScale->set_state(TRISTATE_TRUE);
322     }
323     else
324         m_xTsbScale->set_state(TRISTATE_INDET);
325 
326     TriState eRelative = TRISTATE_FALSE;
327     if(rAttrs->GetItemState(XATTR_FILLBMP_SIZEX) != SfxItemState::INVALID)
328     {
329         nWidth = static_cast<const XFillBmpSizeXItem&>( rAttrs->Get( XATTR_FILLBMP_SIZEX ) ).GetValue();
330         if(nWidth == 0)
331             nWidth = rBitmapSize.Width();
332         else if(nWidth < 0)
333         {
334             m_bLogicalSize = true;
335             eRelative = TRISTATE_TRUE;
336             nWidth = std::abs(nWidth);
337         }
338     }
339 
340     if(rAttrs->GetItemState( XATTR_FILLBMP_SIZEY ) != SfxItemState::INVALID)
341     {
342         nHeight = rAttrs->Get( XATTR_FILLBMP_SIZEY ).GetValue();
343         if(nHeight == 0)
344             nHeight = rBitmapSize.Height();
345         else if(nHeight < 0)
346         {
347             m_bLogicalSize = true;
348             eRelative = TRISTATE_TRUE;
349             nHeight = std::abs(nHeight);
350         }
351     }
352     m_xTsbScale->set_state(eRelative);
353     ClickScaleHdl(*m_xTsbScale);
354 
355 
356     if(!rBitmapSize.IsEmpty())
357     {
358         if (eRelative == TRISTATE_TRUE)
359         {
360             m_xBitmapWidth->set_value(nWidth, FieldUnit::NONE);
361             m_xBitmapHeight->set_value(nHeight, FieldUnit::NONE);
362         }
363         else
364         {
365             SetMetricValue(*m_xBitmapWidth, nWidth, mePoolUnit);
366             SetMetricValue(*m_xBitmapHeight, nHeight, mePoolUnit);
367         }
368     }
369 
370     if( rAttrs->GetItemState( XATTR_FILLBMP_POS ) != SfxItemState::INVALID )
371     {
372         RectPoint eValue = rAttrs->Get( XATTR_FILLBMP_POS ).GetValue();
373         m_xPositionLB->set_active( static_cast< sal_Int32 >(eValue) );
374     }
375 
376     if( rAttrs->GetItemState( XATTR_FILLBMP_POSOFFSETX ) != SfxItemState::INVALID )
377     {
378         sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_POSOFFSETX ).GetValue();
379         m_xPositionOffX->set_value(nValue, FieldUnit::PERCENT);
380     }
381     else
382         m_xPositionOffX->set_text(u""_ustr);
383 
384     if( rAttrs->GetItemState( XATTR_FILLBMP_POSOFFSETY ) != SfxItemState::INVALID )
385     {
386         sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_POSOFFSETY ).GetValue();
387         m_xPositionOffY->set_value(nValue, FieldUnit::PERCENT);
388     }
389     else
390         m_xPositionOffY->set_text(u""_ustr);
391 
392     if( rAttrs->GetItemState( XATTR_FILLBMP_TILEOFFSETX ) != SfxItemState::INVALID)
393     {
394         sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_TILEOFFSETX ).GetValue();
395         if(nValue > 0)
396         {
397             m_xTileOffLB->set_active(static_cast<sal_Int32>(ROW));
398             m_xTileOffset->set_value(nValue, FieldUnit::PERCENT);
399         }
400     }
401 
402     if( rAttrs->GetItemState( XATTR_FILLBMP_TILEOFFSETY ) != SfxItemState::INVALID )
403     {
404         sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_TILEOFFSETY ).GetValue();
405         if(nValue > 0)
406         {
407             m_xTileOffLB->set_active(static_cast<sal_Int32>(COLUMN));
408             m_xTileOffset->set_value(nValue, FieldUnit::PERCENT);
409         }
410     }
411 
412     ClickBitmapHdl_Impl();
413 }
414 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrs)415 std::unique_ptr<SfxTabPage> SvxBitmapTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs)
416 {
417     return std::make_unique<SvxBitmapTabPage>(pPage, pController, *rAttrs);
418 }
419 
ClickBitmapHdl_Impl()420 void SvxBitmapTabPage::ClickBitmapHdl_Impl()
421 {
422     m_xBitmapLBWin->set_sensitive(true);
423     m_xCtlBitmapPreview->set_sensitive(true);
424 
425     ModifyBitmapHdl(m_xBitmapLB.get());
426 }
427 
CalculateBitmapPresetSize()428 void SvxBitmapTabPage::CalculateBitmapPresetSize()
429 {
430     if(rBitmapSize.IsEmpty())
431         return;
432 
433     tools::Long nObjectWidth = static_cast<tools::Long>(m_fObjectWidth);
434     tools::Long nObjectHeight = static_cast<tools::Long>(m_fObjectHeight);
435 
436     if(std::abs(rBitmapSize.Width() - nObjectWidth) < std::abs(rBitmapSize.Height() - nObjectHeight))
437     {
438         rFilledSize.setWidth( nObjectWidth );
439         rFilledSize.setHeight( rBitmapSize.Height()*nObjectWidth/rBitmapSize.Width() );
440         rZoomedSize.setWidth( rBitmapSize.Width()*nObjectHeight/rBitmapSize.Height() );
441         rZoomedSize.setHeight( nObjectHeight );
442     }
443     else
444     {
445         rFilledSize.setWidth( rBitmapSize.Width()*nObjectHeight/rBitmapSize.Height() );
446         rFilledSize.setHeight( nObjectHeight );
447         rZoomedSize.setWidth( nObjectWidth );
448         rZoomedSize.setHeight( rBitmapSize.Height()*nObjectWidth/rBitmapSize.Width() );
449     }
450 }
451 
IMPL_LINK_NOARG(SvxBitmapTabPage,ModifyBitmapHdl,ValueSet *,void)452 IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapHdl, ValueSet*, void)
453 {
454     std::unique_ptr<GraphicObject> pGraphicObject;
455     size_t nPos = m_xBitmapLB->GetSelectItemPos();
456 
457     if( nPos != VALUESET_ITEM_NOTFOUND )
458     {
459         pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap( static_cast<sal_uInt16>(nPos) )->GetGraphicObject()));
460     }
461     else
462     {
463         if(const XFillStyleItem* pFillStyleItem = m_rOutAttrs.GetItemIfSet(GetWhich(XATTR_FILLSTYLE)))
464         {
465             const drawing::FillStyle eXFS(pFillStyleItem->GetValue());
466 
467             const XFillBitmapItem* pBitmapItem;
468             if((drawing::FillStyle_BITMAP == eXFS) && (pBitmapItem = m_rOutAttrs.GetItemIfSet(GetWhich(XATTR_FILLBITMAP))))
469             {
470                 pGraphicObject.reset(new GraphicObject(pBitmapItem->GetGraphicObject()));
471             }
472         }
473 
474         if(!pGraphicObject)
475         {
476             sal_uInt16 nId = m_xBitmapLB->GetItemId(0);
477             m_xBitmapLB->SelectItem(nId);
478 
479             if(0 != nId)
480             {
481                 pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap(0)->GetGraphicObject()));
482             }
483         }
484     }
485 
486     if(pGraphicObject)
487     {
488         BitmapEx aBmpEx(pGraphicObject->GetGraphic().GetBitmapEx());
489         Size aTempBitmapSize = aBmpEx.GetSizePixel();
490         const double fUIScale = mpView ? double(mpView->GetModel().GetUIScale()) : 1.0;
491         Size aBitmapSize100mm = o3tl::convert(aTempBitmapSize, o3tl::Length::pt, o3tl::Length::mm100);
492 
493         rBitmapSize.setWidth(aBitmapSize100mm.Width() / fUIScale);
494         rBitmapSize.setHeight(aBitmapSize100mm.Height() / fUIScale);
495         CalculateBitmapPresetSize();
496         ModifyBitmapStyleHdl( *m_xBitmapStyleLB );
497         ModifyBitmapPositionHdl( *m_xPositionLB );
498 
499         m_rXFSet.ClearItem(XATTR_FILLBITMAP);
500         m_rXFSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
501         m_rXFSet.Put(XFillBitmapItem(OUString(), *pGraphicObject));
502 
503         m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() );
504         m_aCtlBitmapPreview.Invalidate();
505     }
506     else
507     {
508         SAL_WARN("cui.tabpages", "SvxBitmapTabPage::ModifyBitmapHdl(): null pGraphicObject");
509     }
510 
511 }
512 
IMPL_LINK_NOARG(SvxBitmapTabPage,ClickRenameHdl,SvxPresetListBox *,void)513 IMPL_LINK_NOARG(SvxBitmapTabPage, ClickRenameHdl, SvxPresetListBox*, void)
514 {
515     sal_uInt16 nId = m_xBitmapLB->GetSelectedItemId();
516     size_t nPos = m_xBitmapLB->GetSelectItemPos();
517 
518     if( nPos == VALUESET_ITEM_NOTFOUND )
519         return;
520 
521     OUString aDesc( CuiResId( RID_CUISTR_DESC_NEW_BITMAP ) );
522     OUString aName( m_pBitmapList->GetBitmap( nPos )->GetName() );
523 
524     SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
525     ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc));
526 
527     bool bLoop = true;
528     while( bLoop && pDlg->Execute() == RET_OK )
529     {
530         aName = pDlg->GetName();
531         sal_Int32 nBitmapPos = SearchBitmapList( aName );
532         bool bValidBitmapName = (nBitmapPos == static_cast<sal_Int32>(nPos) ) || (nBitmapPos == -1);
533 
534         if(bValidBitmapName)
535         {
536             bLoop = false;
537             m_pBitmapList->GetBitmap(nPos)->SetName(aName);
538 
539             m_xBitmapLB->SetItemText(nId, aName);
540             m_xBitmapLB->SelectItem( nId );
541 
542             *m_pnBitmapListState |= ChangeType::MODIFIED;
543         }
544         else
545         {
546             std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), u"cui/ui/queryduplicatedialog.ui"_ustr));
547             std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog(u"DuplicateNameDialog"_ustr));
548             xBox->run();
549         }
550     }
551 }
552 
IMPL_LINK_NOARG(SvxBitmapTabPage,ClickDeleteHdl,SvxPresetListBox *,void)553 IMPL_LINK_NOARG(SvxBitmapTabPage, ClickDeleteHdl, SvxPresetListBox*, void)
554 {
555     sal_uInt16 nId = m_xBitmapLB->GetSelectedItemId();
556     size_t nPos = m_xBitmapLB->GetSelectItemPos();
557 
558     if( nPos == VALUESET_ITEM_NOTFOUND )
559         return;
560 
561     std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), u"cui/ui/querydeletebitmapdialog.ui"_ustr));
562     std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog(u"AskDelBitmapDialog"_ustr));
563 
564     if (xQueryBox->run() != RET_YES)
565         return;
566 
567     sal_uInt16 nNextId = m_xBitmapLB->GetItemId(nPos + 1);
568     if (!nNextId)
569         nNextId = m_xBitmapLB->GetItemId(nPos - 1);
570 
571     m_pBitmapList->Remove( static_cast<sal_uInt16>(nPos) );
572     m_xBitmapLB->RemoveItem( nId );
573 
574     m_xBitmapLB->SelectItem(nNextId);
575 
576     m_aCtlBitmapPreview.Invalidate();
577     ModifyBitmapHdl(m_xBitmapLB.get());
578     *m_pnBitmapListState |= ChangeType::MODIFIED;
579 }
580 
IMPL_LINK_NOARG(SvxBitmapTabPage,ModifyBitmapSizeHdl,weld::MetricSpinButton &,void)581 IMPL_LINK_NOARG( SvxBitmapTabPage, ModifyBitmapSizeHdl, weld::MetricSpinButton&, void )
582 {
583     m_bLogicalSize = false;
584     if (m_xTsbScale->get_state() != TRISTATE_TRUE && static_cast<BitmapStyle>(m_xBitmapStyleLB->get_active()) != TILED)
585     {
586         sal_Int64 nWidthPercent = m_xBitmapWidth->denormalize(m_xBitmapWidth->get_value(FieldUnit::NONE));
587         sal_Int64 nHeightPercent = m_xBitmapHeight->denormalize(m_xBitmapHeight->get_value(FieldUnit::NONE));
588         if (nWidthPercent == 100 && nHeightPercent == 100)
589             m_xBitmapStyleLB->set_active(static_cast<sal_Int32>(CUSTOM));
590     }
591     ModifyBitmapStyleHdl(*m_xBitmapStyleLB);
592 
593     m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() );
594     m_aCtlBitmapPreview.Invalidate();
595 }
596 
IMPL_LINK_NOARG(SvxBitmapTabPage,ClickScaleHdl,weld::Toggleable &,void)597 IMPL_LINK_NOARG( SvxBitmapTabPage, ClickScaleHdl, weld::Toggleable&, void )
598 {
599     if (m_xTsbScale->get_state() == TRISTATE_TRUE)
600     {
601         m_xBitmapWidth->set_digits( 0 );
602         m_xBitmapWidth->set_unit(FieldUnit::PERCENT);
603         m_xBitmapWidth->set_value(100, FieldUnit::NONE);
604         m_xBitmapWidth->set_range(0, 100, FieldUnit::NONE);
605 
606         m_xBitmapHeight->set_digits( 0 );
607         m_xBitmapHeight->set_unit(FieldUnit::PERCENT);
608         m_xBitmapHeight->set_value(100, FieldUnit::NONE);
609         m_xBitmapHeight->set_range(0, 100, FieldUnit::NONE);
610     }
611     else
612     {
613         m_xBitmapWidth->set_digits( 2 );
614         m_xBitmapWidth->set_unit(meFieldUnit);
615         m_xBitmapWidth->set_value(100, FieldUnit::NONE);
616         m_xBitmapWidth->set_range(0, 999900, FieldUnit::NONE);
617 
618         m_xBitmapHeight->set_digits( 2 );
619         m_xBitmapHeight->set_unit(meFieldUnit);
620         m_xBitmapHeight->set_value(100, FieldUnit::NONE);
621         m_xBitmapHeight->set_range(0, 999900, FieldUnit::NONE);
622     }
623 
624     ModifyBitmapStyleHdl( *m_xBitmapStyleLB );
625 }
626 
IMPL_LINK_NOARG(SvxBitmapTabPage,ModifyBitmapStyleHdl,weld::ComboBox &,void)627 IMPL_LINK_NOARG( SvxBitmapTabPage, ModifyBitmapStyleHdl, weld::ComboBox&, void )
628 {
629     BitmapStyle eStylePos = static_cast<BitmapStyle>(m_xBitmapStyleLB->get_active());
630     bool bIsStretched( eStylePos == STRETCHED );
631     bool bIsTiled( eStylePos == TILED );
632 
633     m_xSizeBox->set_sensitive( !bIsStretched );
634     m_xPositionBox->set_sensitive( !bIsStretched );
635     m_xPositionOffBox->set_sensitive( bIsTiled );
636     m_xTileOffBox->set_sensitive( bIsTiled );
637 
638     m_rXFSet.Put( XFillBmpTileItem( bIsTiled ) );
639     m_rXFSet.Put( XFillBmpStretchItem( bIsStretched ) );
640 
641     if(!bIsStretched)
642     {
643         Size aSetBitmapSize;
644         switch(eStylePos)
645         {
646             case CUSTOM:
647             case TILED:
648             {
649                 if (m_xTsbScale->get_sensitive() && m_xTsbScale->get_state() == TRISTATE_TRUE)
650                 {
651                     aSetBitmapSize.setWidth(-m_xBitmapWidth->get_value(FieldUnit::NONE));
652                     aSetBitmapSize.setHeight(-m_xBitmapHeight->get_value(FieldUnit::NONE));
653                 }
654                 else
655                 {
656                     aSetBitmapSize.setWidth( GetCoreValue( *m_xBitmapWidth, mePoolUnit ) );
657                     aSetBitmapSize.setHeight( GetCoreValue( *m_xBitmapHeight, mePoolUnit ) );
658                 }
659             }
660                 break;
661             default:
662                 break;
663         }
664 
665         m_rXFSet.Put( XFillBmpSizeXItem( aSetBitmapSize.Width() ) );
666         m_rXFSet.Put( XFillBmpSizeYItem( aSetBitmapSize.Height() ) );
667     }
668 
669     m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() );
670     m_aCtlBitmapPreview.Invalidate();
671 }
672 
IMPL_LINK_NOARG(SvxBitmapTabPage,ModifyBitmapPositionHdl,weld::ComboBox &,void)673 IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapPositionHdl, weld::ComboBox&, void)
674 {
675     if (m_xPositionLB->get_sensitive())
676         m_rXFSet.Put( XFillBmpPosItem( static_cast< RectPoint >( m_xPositionLB->get_active() ) ) );
677 
678     m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() );
679     m_aCtlBitmapPreview.Invalidate();
680 }
681 
IMPL_LINK_NOARG(SvxBitmapTabPage,ModifyPositionOffsetHdl,weld::MetricSpinButton &,void)682 IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyPositionOffsetHdl, weld::MetricSpinButton&, void)
683 {
684     if (m_xPositionOffX->get_sensitive())
685         m_rXFSet.Put( XFillBmpPosOffsetXItem( m_xPositionOffX->get_value(FieldUnit::PERCENT) ) );
686 
687     if (m_xPositionOffY->get_sensitive())
688         m_rXFSet.Put( XFillBmpPosOffsetYItem( m_xPositionOffY->get_value(FieldUnit::PERCENT) ) );
689 
690     m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() );
691     m_aCtlBitmapPreview.Invalidate();
692 }
693 
IMPL_LINK_NOARG(SvxBitmapTabPage,ModifyTileOffsetHdl,weld::MetricSpinButton &,void)694 IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyTileOffsetHdl, weld::MetricSpinButton&, void)
695 {
696     sal_uInt16 nTileXOff = 0;
697     sal_uInt16 nTileYOff = 0;
698 
699     if(m_xTileOffLB->get_active() == static_cast<sal_Int32>(ROW))
700         nTileXOff = m_xTileOffset->get_value(FieldUnit::PERCENT);
701 
702     if(m_xTileOffLB->get_active() == static_cast<sal_Int32>(COLUMN))
703         nTileYOff = m_xTileOffset->get_value(FieldUnit::PERCENT);
704 
705     m_rXFSet.Put( XFillBmpTileOffsetXItem(nTileXOff) );
706     m_rXFSet.Put( XFillBmpTileOffsetYItem(nTileYOff) );
707 
708     m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() );
709     m_aCtlBitmapPreview.Invalidate();
710 }
711 
IMPL_LINK_NOARG(SvxBitmapTabPage,ClickImportHdl,weld::Button &,void)712 IMPL_LINK_NOARG(SvxBitmapTabPage, ClickImportHdl, weld::Button&, void)
713 {
714     weld::Window* pDialogFrameWeld = GetFrameWeld();
715 
716     SvxOpenGraphicDialog aDlg(CuiResId(RID_CUISTR_ADD_IMAGE), pDialogFrameWeld);
717     aDlg.EnableLink(false);
718     tools::Long nCount = m_pBitmapList->Count();
719 
720     if( aDlg.Execute() )
721         return;
722 
723     Graphic         aGraphic;
724 
725     std::unique_ptr<weld::WaitObject> xWait(new weld::WaitObject(pDialogFrameWeld));
726     ErrCode nError = aDlg.GetGraphic( aGraphic );
727     xWait.reset();
728 
729     if( !nError )
730     {
731         OUString aDesc(CuiResId(RID_CUISTR_DESC_EXT_BITMAP));
732 
733         // convert file URL to UI name
734         OUString        aName;
735         INetURLObject   aURL( aDlg.GetPath() );
736         SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
737         ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(
738             pDialogFrameWeld, aURL.GetLastName().getToken(0, '.'), aDesc));
739         nError = ErrCode(1);
740 
741         while( pDlg->Execute() == RET_OK )
742         {
743             aName = pDlg->GetName();
744 
745             bool bDifferent = true;
746 
747             for( tools::Long i = 0; i < nCount && bDifferent; i++ )
748                 if( aName == m_pBitmapList->GetBitmap( i )->GetName() )
749                     bDifferent = false;
750 
751             if( bDifferent ) {
752                 nError = ERRCODE_NONE;
753                 break;
754             }
755 
756             std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pDialogFrameWeld, u"cui/ui/queryduplicatedialog.ui"_ustr));
757             std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog(u"DuplicateNameDialog"_ustr));
758             if (xBox->run() != RET_OK)
759                 break;
760         }
761 
762         pDlg.disposeAndClear();
763 
764         if( !nError )
765         {
766             m_pBitmapList->Insert(std::make_unique<XBitmapEntry>(aGraphic, aName), nCount);
767 
768             sal_Int32 nId = m_xBitmapLB->GetItemId( nCount - 1 );
769             BitmapEx aBitmap = m_pBitmapList->GetBitmapForPreview( nCount, m_xBitmapLB->GetIconSize() );
770 
771             m_xBitmapLB->InsertItem( nId + 1, Image(aBitmap), aName );
772             m_xBitmapLB->SelectItem( nId + 1 );
773             *m_pnBitmapListState |= ChangeType::MODIFIED;
774 
775             ModifyBitmapHdl(m_xBitmapLB.get());
776         }
777     }
778     else
779     {
780         // graphic couldn't be loaded
781         std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pDialogFrameWeld, u"cui/ui/querynoloadedfiledialog.ui"_ustr));
782         std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog(u"NoLoadedFileDialog"_ustr));
783         xBox->run();
784     }
785 }
786 
SearchBitmapList(const GraphicObject & rGraphicObject)787 sal_Int32 SvxBitmapTabPage::SearchBitmapList(const GraphicObject& rGraphicObject)
788 {
789     tools::Long nCount = m_pBitmapList->Count();
790     sal_Int32 nPos = -1;
791 
792     for(tools::Long i = 0;i < nCount;i++)
793     {
794         if(rGraphicObject.GetUniqueID() == m_pBitmapList->GetBitmap( i )->GetGraphicObject().GetUniqueID())
795         {
796             nPos = i;
797             break;
798         }
799     }
800     return nPos;
801 }
802 
SearchBitmapList(std::u16string_view rBitmapName)803 sal_Int32 SvxBitmapTabPage::SearchBitmapList(std::u16string_view rBitmapName)
804 {
805     tools::Long nCount = m_pBitmapList->Count();
806     bool bValidBitmapName = true;
807     sal_Int32 nPos = -1;
808 
809     for(tools::Long i = 0;i < nCount && bValidBitmapName;i++)
810     {
811         if(rBitmapName == m_pBitmapList->GetBitmap( i )->GetName())
812         {
813             nPos = i;
814             bValidBitmapName = false;
815         }
816     }
817     return nPos;
818 }
819 
820 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
821