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