1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <tools/urlobj.hxx>
22 #include <sfx2/dialoghelper.hxx>
23 #include <svx/colorbox.hxx>
24 #include <svx/dialmgr.hxx>
25 #include <vcl/BitmapTools.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/weld.hxx>
28 #include <svx/strings.hrc>
30 #include <strings.hrc>
31 #include <svx/xfillit0.hxx>
32 #include <svx/xbtmpit.hxx>
33 #include <svx/xtable.hxx>
34 #include <svx/xflbmtit.hxx>
35 #include <cuitabarea.hxx>
36 #include <svx/svxdlg.hxx>
37 #include <dialmgr.hxx>
38 #include <sal/log.hxx>
40 using namespace com::sun::star
;
42 /*************************************************************************
43 |* Preview control for the display of bitmaps
44 \************************************************************************/
49 Color aPixelColor
, aBackgroundColor
;
50 std::array
<sal_uInt8
,64> const * pBmpArray
;
53 // Constructor: BitmapCtl for SvxPixelCtl
59 // BitmapCtl: Returns the Bitmap
60 BitmapEx
GetBitmapEx() const
64 return vcl::bitmap::createHistorical8x8FromArray(*pBmpArray
, aPixelColor
, aBackgroundColor
);
67 void SetBmpArray( std::array
<sal_uInt8
,64> const & pPixel
) { pBmpArray
= &pPixel
; }
68 void SetPixelColor( Color aColor
) { aPixelColor
= aColor
; }
69 void SetBackgroundColor( Color aColor
) { aBackgroundColor
= aColor
; }
72 SvxPatternTabPage::SvxPatternTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rInAttrs
)
73 : SvxTabPage(pPage
, pController
, "cui/ui/patterntabpage.ui", "PatternTabPage", rInAttrs
)
74 , m_rOutAttrs(rInAttrs
)
75 , m_pnPatternListState(nullptr)
76 , m_pnColorListState(nullptr)
77 , m_aXFillAttr(rInAttrs
.GetPool())
78 , m_rXFSet(m_aXFillAttr
.GetItemSet())
79 , m_xCtlPixel(new SvxPixelCtl(this))
80 , m_xLbColor(new ColorListBox(m_xBuilder
->weld_menu_button("LB_COLOR"),
81 [this]{ return GetDialogController()->getDialog(); }))
82 , m_xLbBackgroundColor(new ColorListBox(m_xBuilder
->weld_menu_button("LB_BACKGROUND_COLOR"),
83 [this]{ return GetDialogController()->getDialog(); }))
84 , m_xPatternLB(new SvxPresetListBox(m_xBuilder
->weld_scrolled_window("patternpresetlistwin", true)))
85 , m_xBtnAdd(m_xBuilder
->weld_button("BTN_ADD"))
86 , m_xBtnModify(m_xBuilder
->weld_button("BTN_MODIFY"))
87 , m_xCtlPixelWin(new weld::CustomWeld(*m_xBuilder
, "CTL_PIXEL", *m_xCtlPixel
))
88 , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder
, "CTL_PREVIEW", m_aCtlPreview
))
89 , m_xPatternLBWin(new weld::CustomWeld(*m_xBuilder
, "patternpresetlist", *m_xPatternLB
))
91 // size of the bitmap display
92 Size aSize
= getDrawPreviewOptimalSize(m_aCtlPreview
.GetDrawingArea()->get_ref_device());
93 m_xPatternLB
->set_size_request(aSize
.Width(), aSize
.Height());
94 m_xCtlPreview
->set_size_request(aSize
.Width(), aSize
.Height());
96 m_xBitmapCtl
.reset(new SvxBitmapCtl
);
98 // this page needs ExchangeSupport
101 // setting the output device
102 m_rXFSet
.Put( XFillStyleItem(drawing::FillStyle_BITMAP
) );
103 m_rXFSet
.Put( XFillBitmapItem(OUString(), Graphic()) );
105 m_xBtnAdd
->connect_clicked( LINK( this, SvxPatternTabPage
, ClickAddHdl_Impl
) );
106 m_xBtnModify
->connect_clicked( LINK( this, SvxPatternTabPage
, ClickModifyHdl_Impl
) );
108 m_xPatternLB
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangePatternHdl_Impl
) );
109 m_xPatternLB
->SetRenameHdl( LINK( this, SvxPatternTabPage
, ClickRenameHdl_Impl
) );
110 m_xPatternLB
->SetDeleteHdl( LINK( this, SvxPatternTabPage
, ClickDeleteHdl_Impl
) );
111 m_xLbColor
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangeColorHdl_Impl
) );
112 m_xLbBackgroundColor
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangeColorHdl_Impl
) );
114 m_xPatternLB
->SetStyle(WB_FLATVALUESET
| WB_NO_DIRECTSELECT
| WB_TABSTOP
);
117 SvxPatternTabPage::~SvxPatternTabPage()
119 m_xPatternLBWin
.reset();
120 m_xCtlPreview
.reset();
121 m_xCtlPixelWin
.reset();
122 m_xPatternLB
.reset();
123 m_xLbBackgroundColor
.reset();
128 void SvxPatternTabPage::Construct()
130 m_xPatternLB
->FillPresetListBox( *m_pPatternList
);
133 void SvxPatternTabPage::ActivatePage( const SfxItemSet
& rSet
)
135 if( !m_pColorList
.is() )
139 if( *m_pnColorListState
& ChangeType::CHANGED
||
140 *m_pnColorListState
& ChangeType::MODIFIED
)
142 SvxAreaTabDialog
* pArea
= (*m_pnColorListState
& ChangeType::CHANGED
) ?
143 dynamic_cast<SvxAreaTabDialog
*>(GetDialogController()) : nullptr;
145 m_pColorList
= pArea
->GetNewColorList();
148 // determining (possibly cutting) the name and
149 // displaying it in the GroupBox
150 OUString aString
= CuiResId( RID_CUISTR_TABLE
) + ": ";
151 INetURLObject
aURL( m_pPatternList
->GetPath() );
153 aURL
.Append( m_pPatternList
->GetName() );
154 SAL_WARN_IF( aURL
.GetProtocol() == INetProtocol::NotValid
, "cui.tabpages", "invalid URL" );
156 if( aURL
.getBase().getLength() > 18 )
158 aString
+= OUString::Concat(aURL
.getBase().subView( 0, 15 )) + "...";
161 aString
+= aURL
.getBase();
163 XFillBitmapItem
aItem( rSet
.Get( XATTR_FILLBITMAP
) );
165 if ( aItem
.isPattern() )
167 sal_Int32 nPos
= SearchPatternList( aItem
.GetName() );
170 sal_uInt16 nId
= m_xPatternLB
->GetItemId( static_cast<size_t>( nPos
) );
171 m_xPatternLB
->SelectItem( nId
);
175 m_xPatternLB
->SelectItem( m_xPatternLB
->GetItemId( static_cast<size_t>( 0 ) ) );
179 DeactivateRC
SvxPatternTabPage::DeactivatePage( SfxItemSet
* _pSet
)
182 FillItemSet( _pSet
);
184 return DeactivateRC::LeavePage
;
188 bool SvxPatternTabPage::FillItemSet( SfxItemSet
* _rOutAttrs
)
190 _rOutAttrs
->Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
191 size_t nPos
= m_xPatternLB
->IsNoSelection() ? VALUESET_ITEM_NOTFOUND
: m_xPatternLB
->GetSelectItemPos();
192 if(VALUESET_ITEM_NOTFOUND
!= nPos
)
194 const XBitmapEntry
* pXBitmapEntry
= m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) );
195 const OUString
aString( m_xPatternLB
->GetItemText( m_xPatternLB
->GetSelectedItemId() ) );
197 _rOutAttrs
->Put(XFillBitmapItem(aString
, pXBitmapEntry
->GetGraphicObject()));
201 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
203 _rOutAttrs
->Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx
)));
205 _rOutAttrs
->Put(XFillBmpTileItem(true));
210 void SvxPatternTabPage::Reset( const SfxItemSet
* )
212 m_xBitmapCtl
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
213 m_xBitmapCtl
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
214 m_xBitmapCtl
->SetBmpArray( m_xCtlPixel
->GetBitmapPixelPtr() );
216 // get bitmap and display it
217 const XFillBitmapItem
aBmpItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx()));
218 if(aBmpItem
.isPattern())
220 m_rXFSet
.Put( aBmpItem
);
221 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
222 m_aCtlPreview
.Invalidate();
225 ChangePatternHdl_Impl(m_xPatternLB
.get());
227 // determine button state
228 if( m_pPatternList
.is() && m_pPatternList
->Count() )
230 m_xBtnAdd
->set_sensitive(true);
231 m_xBtnModify
->set_sensitive(true);
235 m_xBtnModify
->set_sensitive(false);
239 std::unique_ptr
<SfxTabPage
> SvxPatternTabPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
240 const SfxItemSet
* rSet
)
242 return std::make_unique
<SvxPatternTabPage
>(pPage
, pController
, *rSet
);
245 IMPL_LINK_NOARG(SvxPatternTabPage
, ChangePatternHdl_Impl
, ValueSet
*, void)
247 std::unique_ptr
<GraphicObject
> pGraphicObject
;
248 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
250 if(VALUESET_ITEM_NOTFOUND
!= nPos
)
252 pGraphicObject
.reset(new GraphicObject(m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) )->GetGraphicObject()));
256 if(const XFillStyleItem
* pFillStyleItem
= m_rOutAttrs
.GetItemIfSet(GetWhich(XATTR_FILLSTYLE
)))
258 const drawing::FillStyle
eXFS(pFillStyleItem
->GetValue());
260 const XFillBitmapItem
* pBitmapItem
;
261 if((drawing::FillStyle_BITMAP
== eXFS
) && (pBitmapItem
= m_rOutAttrs
.GetItemIfSet(GetWhich(XATTR_FILLBITMAP
))))
263 pGraphicObject
.reset(new GraphicObject(pBitmapItem
->GetGraphicObject()));
269 sal_uInt16 nPosition
= m_xPatternLB
->GetItemId( 0 );
270 m_xPatternLB
->SelectItem( nPosition
);
273 pGraphicObject
.reset(new GraphicObject(m_pPatternList
->GetBitmap(0)->GetGraphicObject()));
283 bool bIs8x8(vcl::bitmap::isHistorical8x8(pGraphicObject
->GetGraphic().GetBitmapEx(), aBackColor
, aPixelColor
));
285 m_xLbColor
->SetNoSelection();
286 m_xLbBackgroundColor
->SetNoSelection();
290 m_xCtlPixel
->SetPaintable( true );
291 m_xBtnModify
->set_sensitive(true);
292 m_xBtnAdd
->set_sensitive(true);
294 // setting the pixel control
296 m_xCtlPixel
->SetXBitmap(pGraphicObject
->GetGraphic().GetBitmapEx());
298 m_xLbColor
->SelectEntry( aPixelColor
);
299 m_xLbBackgroundColor
->SelectEntry( aBackColor
);
301 // update m_xBitmapCtl, rXFSet and m_aCtlPreview
302 m_xBitmapCtl
->SetPixelColor( aPixelColor
);
303 m_xBitmapCtl
->SetBackgroundColor( aBackColor
);
304 m_rXFSet
.ClearItem();
305 m_rXFSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
306 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
307 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
308 m_aCtlPreview
.Invalidate();
312 m_xCtlPixel
->Reset();
313 m_xCtlPixel
->SetPaintable( false );
314 m_xBtnModify
->set_sensitive(false);
315 m_xBtnAdd
->set_sensitive(false);
318 m_xCtlPixel
->Invalidate();
321 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickAddHdl_Impl
, weld::Button
&, void)
324 OUString
aNewName( SvxResId( RID_SVXSTR_PATTERN_UNTITLED
) );
325 OUString
aDesc( CuiResId( RID_CUISTR_DESC_NEW_PATTERN
) );
328 tools::Long nCount
= m_pPatternList
->Count();
330 bool bValidPatternName
= false;
332 while( !bValidPatternName
)
334 aName
= aNewName
+ " " + OUString::number( j
++ );
335 bValidPatternName
= (SearchPatternList(aName
) == -1);
338 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
339 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetFrameWeld(), aName
, aDesc
));
340 sal_uInt16
nError(1);
342 while( pDlg
->Execute() == RET_OK
)
344 pDlg
->GetName( aName
);
346 bValidPatternName
= (SearchPatternList(aName
) == -1);
348 if( bValidPatternName
) {
353 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
354 std::unique_ptr
<weld::MessageDialog
> xWarnBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
355 if (xWarnBox
->run() != RET_OK
)
359 pDlg
.disposeAndClear();
363 std::unique_ptr
<XBitmapEntry
> pEntry
;
364 if( m_xCtlPixel
->IsEnabled() )
366 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
368 pEntry
.reset(new XBitmapEntry(Graphic(aBitmapEx
), aName
));
370 else // it must be a not existing imported bitmap
372 if(const XFillBitmapItem
* pFillBmpItem
= m_rOutAttrs
.GetItemIfSet(XATTR_FILLBITMAP
))
374 pEntry
.reset(new XBitmapEntry(pFillBmpItem
->GetGraphicObject(), aName
));
377 assert(!"SvxPatternTabPage::ClickAddHdl_Impl(), XBitmapEntry* pEntry == nullptr ?");
382 m_pPatternList
->Insert(std::move(pEntry
), nCount
);
383 sal_Int32 nId
= m_xPatternLB
->GetItemId( nCount
- 1 );
384 BitmapEx aBitmap
= m_pPatternList
->GetBitmapForPreview( nCount
, m_xPatternLB
->GetIconSize() );
385 m_xPatternLB
->InsertItem( nId
+ 1, Image(aBitmap
), aName
);
386 m_xPatternLB
->SelectItem( nId
+ 1 );
387 m_xPatternLB
->Resize();
389 *m_pnPatternListState
|= ChangeType::MODIFIED
;
391 ChangePatternHdl_Impl(m_xPatternLB
.get());
395 // determine button state
396 if( m_pPatternList
->Count() )
398 m_xBtnModify
->set_sensitive(true);
402 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickModifyHdl_Impl
, weld::Button
&, void)
404 sal_uInt16 nId
= m_xPatternLB
->GetSelectedItemId();
405 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
407 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
410 OUString
aName( m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) )->GetName() );
412 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
414 // #i123497# Need to replace the existing entry with a new one (old returned needs to be deleted)
415 m_pPatternList
->Replace(std::make_unique
<XBitmapEntry
>(Graphic(aBitmapEx
), aName
), nPos
);
417 BitmapEx aBitmap
= m_pPatternList
->GetBitmapForPreview( static_cast<sal_uInt16
>( nPos
), m_xPatternLB
->GetIconSize() );
418 m_xPatternLB
->RemoveItem(nId
);
419 m_xPatternLB
->InsertItem( nId
, Image(aBitmap
), aName
, static_cast<sal_uInt16
>(nPos
) );
420 m_xPatternLB
->SelectItem( nId
);
422 *m_pnPatternListState
|= ChangeType::MODIFIED
;
426 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickRenameHdl_Impl
, SvxPresetListBox
*, void)
428 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
429 sal_Int32 nId
= m_xPatternLB
->GetSelectedItemId();
431 if ( nPos
== VALUESET_ITEM_NOTFOUND
)
434 OUString
aDesc(CuiResId(RID_CUISTR_DESC_NEW_PATTERN
));
435 OUString
aName(m_pPatternList
->GetBitmap(nPos
)->GetName());
437 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
438 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetFrameWeld(), aName
, aDesc
));
442 while( bLoop
&& pDlg
->Execute() == RET_OK
)
444 pDlg
->GetName( aName
);
445 sal_Int32 nPatternPos
= SearchPatternList(aName
);
446 bool bValidPatternName
= (nPatternPos
== static_cast<sal_Int32
>(nPos
) ) || (nPatternPos
== -1);
448 if( bValidPatternName
)
452 m_pPatternList
->GetBitmap(nPos
)->SetName(aName
);
454 m_xPatternLB
->SetItemText( nId
, aName
);
455 m_xPatternLB
->SelectItem( nId
);
457 *m_pnPatternListState
|= ChangeType::MODIFIED
;
461 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
462 std::unique_ptr
<weld::MessageDialog
> xWarnBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
468 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickDeleteHdl_Impl
, SvxPresetListBox
*, void)
470 sal_uInt16 nId
= m_xPatternLB
->GetSelectedItemId();
471 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
473 if( nPos
!= VALUESET_ITEM_NOTFOUND
)
475 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletebitmapdialog.ui"));
476 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("AskDelBitmapDialog"));
477 if (xQueryBox
->run() == RET_YES
)
479 m_pPatternList
->Remove(nPos
);
480 m_xPatternLB
->RemoveItem( nId
);
481 nId
= m_xPatternLB
->GetItemId(0);
482 m_xPatternLB
->SelectItem( nId
);
483 m_xPatternLB
->Resize();
485 m_aCtlPreview
.Invalidate();
486 m_xCtlPixel
->Invalidate();
488 ChangePatternHdl_Impl(m_xPatternLB
.get());
490 *m_pnPatternListState
|= ChangeType::MODIFIED
;
493 // determine button state
494 if( !m_pPatternList
->Count() )
496 m_xBtnModify
->set_sensitive(false);
500 IMPL_LINK_NOARG(SvxPatternTabPage
, ChangeColorHdl_Impl
, ColorListBox
&, void)
503 m_xPatternLB
->SetNoSelection();
506 void SvxPatternTabPage::ChangeColor_Impl()
508 m_xCtlPixel
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
509 m_xCtlPixel
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
510 m_xCtlPixel
->Invalidate();
512 m_xBitmapCtl
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
513 m_xBitmapCtl
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
515 // get bitmap and display it
516 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
517 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
518 m_aCtlPreview
.Invalidate();
521 void SvxPatternTabPage::PointChanged(weld::DrawingArea
* pDrawingArea
, RectPoint
)
523 if (pDrawingArea
== m_xCtlPixel
->GetDrawingArea())
525 m_xBitmapCtl
->SetBmpArray(m_xCtlPixel
->GetBitmapPixelPtr());
527 // get bitmap and display it
528 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
529 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
530 m_aCtlPreview
.Invalidate();
533 m_xPatternLB
->SetNoSelection();
536 sal_Int32
SvxPatternTabPage::SearchPatternList(std::u16string_view rPatternName
)
538 tools::Long nCount
= m_pPatternList
->Count();
539 bool bValidPatternName
= true;
542 for(tools::Long i
= 0;i
< nCount
&& bValidPatternName
;i
++)
544 if(rPatternName
== m_pPatternList
->GetBitmap( i
)->GetName())
547 bValidPatternName
= false;
553 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */