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"), pController
->getDialog()))
81 , m_xLbBackgroundColor(new ColorListBox(m_xBuilder
->weld_menu_button("LB_BACKGROUND_COLOR"), pController
->getDialog()))
82 , m_xPatternLB(new SvxPresetListBox(m_xBuilder
->weld_scrolled_window("patternpresetlistwin")))
83 , m_xBtnAdd(m_xBuilder
->weld_button("BTN_ADD"))
84 , m_xBtnModify(m_xBuilder
->weld_button("BTN_MODIFY"))
85 , m_xCtlPixelWin(new weld::CustomWeld(*m_xBuilder
, "CTL_PIXEL", *m_xCtlPixel
))
86 , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder
, "CTL_PREVIEW", m_aCtlPreview
))
87 , m_xPatternLBWin(new weld::CustomWeld(*m_xBuilder
, "patternpresetlist", *m_xPatternLB
))
89 // size of the bitmap display
90 Size aSize
= getPagePropertiesOptimalSize(m_xPatternLB
->GetDrawingArea()->get_ref_device());
91 m_xPatternLB
->set_size_request(aSize
.Width(), aSize
.Height());
93 aSize
= getDrawPreviewOptimalSize(m_aCtlPreview
.GetDrawingArea()->get_ref_device());
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
) );
115 SvxPatternTabPage::~SvxPatternTabPage()
117 m_xPatternLBWin
.reset();
118 m_xCtlPreview
.reset();
119 m_xCtlPixelWin
.reset();
120 m_xPatternLB
.reset();
121 m_xLbBackgroundColor
.reset();
126 void SvxPatternTabPage::Construct()
128 m_xPatternLB
->FillPresetListBox( *m_pPatternList
);
131 void SvxPatternTabPage::ActivatePage( const SfxItemSet
& rSet
)
133 if( m_pColorList
.is() )
136 if( *m_pnColorListState
& ChangeType::CHANGED
||
137 *m_pnColorListState
& ChangeType::MODIFIED
)
139 SvxAreaTabDialog
* pArea
= (*m_pnColorListState
& ChangeType::CHANGED
) ?
140 dynamic_cast<SvxAreaTabDialog
*>(GetDialogController()) : nullptr;
142 m_pColorList
= pArea
->GetNewColorList();
145 // determining (possibly cutting) the name and
146 // displaying it in the GroupBox
147 OUString aString
= CuiResId( RID_SVXSTR_TABLE
) + ": ";
148 INetURLObject
aURL( m_pPatternList
->GetPath() );
150 aURL
.Append( m_pPatternList
->GetName() );
151 SAL_WARN_IF( aURL
.GetProtocol() == INetProtocol::NotValid
, "cui.tabpages", "invalid URL" );
153 if( aURL
.getBase().getLength() > 18 )
155 aString
+= aURL
.getBase().copy( 0, 15 ) + "...";
158 aString
+= aURL
.getBase();
160 XFillBitmapItem
aItem( rSet
.Get( XATTR_FILLBITMAP
) );
162 if ( aItem
.isPattern() )
164 sal_Int32 nPos
= SearchPatternList( aItem
.GetName() );
165 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
167 sal_uInt16 nId
= m_xPatternLB
->GetItemId( static_cast<size_t>( nPos
) );
168 m_xPatternLB
->SelectItem( nId
);
172 m_xPatternLB
->SelectItem( m_xPatternLB
->GetItemId( static_cast<size_t>( 0 ) ) );
177 DeactivateRC
SvxPatternTabPage::DeactivatePage( SfxItemSet
* _pSet
)
180 FillItemSet( _pSet
);
182 return DeactivateRC::LeavePage
;
186 bool SvxPatternTabPage::FillItemSet( SfxItemSet
* _rOutAttrs
)
188 _rOutAttrs
->Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
189 size_t nPos
= m_xPatternLB
->IsNoSelection() ? VALUESET_ITEM_NOTFOUND
: m_xPatternLB
->GetSelectItemPos();
190 if(VALUESET_ITEM_NOTFOUND
!= nPos
)
192 const XBitmapEntry
* pXBitmapEntry
= m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) );
193 const OUString
aString( m_xPatternLB
->GetItemText( m_xPatternLB
->GetSelectedItemId() ) );
195 _rOutAttrs
->Put(XFillBitmapItem(aString
, pXBitmapEntry
->GetGraphicObject()));
199 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
201 _rOutAttrs
->Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx
)));
203 _rOutAttrs
->Put(XFillBmpTileItem(true));
208 void SvxPatternTabPage::Reset( const SfxItemSet
* )
210 m_xBitmapCtl
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
211 m_xBitmapCtl
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
212 m_xBitmapCtl
->SetBmpArray( m_xCtlPixel
->GetBitmapPixelPtr() );
214 // get bitmap and display it
215 const XFillBitmapItem
aBmpItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx()));
216 if(aBmpItem
.isPattern())
218 m_rXFSet
.Put( aBmpItem
);
219 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
220 m_aCtlPreview
.Invalidate();
223 ChangePatternHdl_Impl(m_xPatternLB
.get());
225 // determine button state
226 if( m_pPatternList
.is() && m_pPatternList
->Count() )
228 m_xBtnAdd
->set_sensitive(true);
229 m_xBtnModify
->set_sensitive(true);
233 m_xBtnModify
->set_sensitive(false);
237 std::unique_ptr
<SfxTabPage
> SvxPatternTabPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
238 const SfxItemSet
* rSet
)
240 return std::make_unique
<SvxPatternTabPage
>(pPage
, pController
, *rSet
);
243 IMPL_LINK_NOARG(SvxPatternTabPage
, ChangePatternHdl_Impl
, SvtValueSet
*, void)
245 std::unique_ptr
<GraphicObject
> pGraphicObject
;
246 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
248 if(VALUESET_ITEM_NOTFOUND
!= nPos
)
250 pGraphicObject
.reset(new GraphicObject(m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) )->GetGraphicObject()));
254 const SfxPoolItem
* pPoolItem
= nullptr;
256 if(SfxItemState::SET
== m_rOutAttrs
.GetItemState(GetWhich(XATTR_FILLSTYLE
), true, &pPoolItem
))
258 const drawing::FillStyle
eXFS(static_cast<const XFillStyleItem
*>(pPoolItem
)->GetValue());
260 if((drawing::FillStyle_BITMAP
== eXFS
) && (SfxItemState::SET
== m_rOutAttrs
.GetItemState(GetWhich(XATTR_FILLBITMAP
), true, &pPoolItem
)))
262 pGraphicObject
.reset(new GraphicObject(static_cast<const XFillBitmapItem
*>(pPoolItem
)->GetGraphicObject()));
268 sal_uInt16 nPosition
= m_xPatternLB
->GetItemId( 0 );
269 m_xPatternLB
->SelectItem( nPosition
);
272 pGraphicObject
.reset(new GraphicObject(m_pPatternList
->GetBitmap(0)->GetGraphicObject()));
281 bool bIs8x8(vcl::bitmap::isHistorical8x8(pGraphicObject
->GetGraphic().GetBitmapEx(), aBackColor
, aPixelColor
));
283 m_xLbColor
->SetNoSelection();
284 m_xLbBackgroundColor
->SetNoSelection();
288 m_xCtlPixel
->SetPaintable( true );
289 m_xBtnModify
->set_sensitive(true);
290 m_xBtnAdd
->set_sensitive(true);
292 // setting the pixel control
294 m_xCtlPixel
->SetXBitmap(pGraphicObject
->GetGraphic().GetBitmapEx());
296 m_xLbColor
->SelectEntry( aPixelColor
);
297 m_xLbBackgroundColor
->SelectEntry( aBackColor
);
299 // update m_xBitmapCtl, rXFSet and m_aCtlPreview
300 m_xBitmapCtl
->SetPixelColor( aPixelColor
);
301 m_xBitmapCtl
->SetBackgroundColor( aBackColor
);
302 m_rXFSet
.ClearItem();
303 m_rXFSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
304 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
305 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
306 m_aCtlPreview
.Invalidate();
310 m_xCtlPixel
->Reset();
311 m_xCtlPixel
->SetPaintable( false );
312 m_xBtnModify
->set_sensitive(false);
313 m_xBtnAdd
->set_sensitive(false);
316 m_xCtlPixel
->Invalidate();
320 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickAddHdl_Impl
, weld::Button
&, void)
323 OUString
aNewName( SvxResId( RID_SVXSTR_PATTERN_UNTITLED
) );
324 OUString
aDesc( CuiResId( RID_SVXSTR_DESC_NEW_PATTERN
) );
327 long nCount
= m_pPatternList
->Count();
329 bool bValidPatternName
= false;
331 while( !bValidPatternName
)
333 aName
= aNewName
+ " " + OUString::number( j
++ );
334 bValidPatternName
= (SearchPatternList(aName
) == LISTBOX_ENTRY_NOTFOUND
);
337 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
338 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetFrameWeld(), aName
, aDesc
));
339 sal_uInt16
nError(1);
341 while( pDlg
->Execute() == RET_OK
)
343 pDlg
->GetName( aName
);
345 bValidPatternName
= (SearchPatternList(aName
) == LISTBOX_ENTRY_NOTFOUND
);
347 if( bValidPatternName
) {
352 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
353 std::unique_ptr
<weld::MessageDialog
> xWarnBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
354 if (xWarnBox
->run() != RET_OK
)
358 pDlg
.disposeAndClear();
362 std::unique_ptr
<XBitmapEntry
> pEntry
;
363 if( m_xCtlPixel
->IsEnabled() )
365 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
367 pEntry
.reset(new XBitmapEntry(Graphic(aBitmapEx
), aName
));
369 else // it must be a not existing imported bitmap
371 const SfxPoolItem
* pPoolItem
= nullptr;
373 if(SfxItemState::SET
== m_rOutAttrs
.GetItemState(XATTR_FILLBITMAP
, true, &pPoolItem
))
375 auto pFillBmpItem
= dynamic_cast<const XFillBitmapItem
*>(pPoolItem
);
376 assert(pFillBmpItem
);
377 pEntry
.reset(new XBitmapEntry(pFillBmpItem
->GetGraphicObject(), aName
));
380 assert(!"SvxPatternTabPage::ClickAddHdl_Impl(), XBitmapEntry* pEntry == nullptr ?");
385 m_pPatternList
->Insert(std::move(pEntry
), nCount
);
386 sal_Int32 nId
= m_xPatternLB
->GetItemId( nCount
- 1 );
387 BitmapEx aBitmap
= m_pPatternList
->GetBitmapForPreview( nCount
, m_xPatternLB
->GetIconSize() );
388 m_xPatternLB
->InsertItem( nId
+ 1, Image(aBitmap
), aName
);
389 m_xPatternLB
->SelectItem( nId
+ 1 );
390 m_xPatternLB
->Resize();
392 *m_pnPatternListState
|= ChangeType::MODIFIED
;
394 ChangePatternHdl_Impl(m_xPatternLB
.get());
398 // determine button state
399 if( m_pPatternList
->Count() )
401 m_xBtnModify
->set_sensitive(true);
405 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickModifyHdl_Impl
, weld::Button
&, void)
407 sal_uInt16 nId
= m_xPatternLB
->GetSelectedItemId();
408 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
410 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
412 OUString
aName( m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) )->GetName() );
414 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
416 // #i123497# Need to replace the existing entry with a new one (old returned needs to be deleted)
417 m_pPatternList
->Replace(std::make_unique
<XBitmapEntry
>(Graphic(aBitmapEx
), aName
), nPos
);
419 BitmapEx aBitmap
= m_pPatternList
->GetBitmapForPreview( static_cast<sal_uInt16
>( nPos
), m_xPatternLB
->GetIconSize() );
420 m_xPatternLB
->RemoveItem(nId
);
421 m_xPatternLB
->InsertItem( nId
, Image(aBitmap
), aName
, static_cast<sal_uInt16
>(nPos
) );
422 m_xPatternLB
->SelectItem( nId
);
424 *m_pnPatternListState
|= ChangeType::MODIFIED
;
429 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickRenameHdl_Impl
, SvxPresetListBox
*, void)
431 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
432 sal_Int32 nId
= m_xPatternLB
->GetSelectedItemId();
434 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
436 OUString
aDesc(CuiResId(RID_SVXSTR_DESC_NEW_PATTERN
));
437 OUString
aName(m_pPatternList
->GetBitmap(nPos
)->GetName());
439 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
440 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetFrameWeld(), aName
, aDesc
));
444 while( bLoop
&& pDlg
->Execute() == RET_OK
)
446 pDlg
->GetName( aName
);
447 sal_Int32 nPatternPos
= SearchPatternList(aName
);
448 bool bValidPatternName
= (nPatternPos
== static_cast<sal_Int32
>(nPos
) ) || (nPatternPos
== LISTBOX_ENTRY_NOTFOUND
);
450 if( bValidPatternName
)
454 m_pPatternList
->GetBitmap(nPos
)->SetName(aName
);
456 m_xPatternLB
->SetItemText( nId
, aName
);
457 m_xPatternLB
->SelectItem( nId
);
459 *m_pnPatternListState
|= ChangeType::MODIFIED
;
463 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
464 std::unique_ptr
<weld::MessageDialog
> xWarnBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
471 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickDeleteHdl_Impl
, SvxPresetListBox
*, void)
473 sal_uInt16 nId
= m_xPatternLB
->GetSelectedItemId();
474 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
476 if( nPos
!= VALUESET_ITEM_NOTFOUND
)
478 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletebitmapdialog.ui"));
479 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("AskDelBitmapDialog"));
480 if (xQueryBox
->run() == RET_YES
)
482 m_pPatternList
->Remove(nPos
);
483 m_xPatternLB
->RemoveItem( nId
);
484 nId
= m_xPatternLB
->GetItemId(0);
485 m_xPatternLB
->SelectItem( nId
);
486 m_xPatternLB
->Resize();
488 m_aCtlPreview
.Invalidate();
489 m_xCtlPixel
->Invalidate();
491 ChangePatternHdl_Impl(m_xPatternLB
.get());
493 *m_pnPatternListState
|= ChangeType::MODIFIED
;
496 // determine button state
497 if( !m_pPatternList
->Count() )
499 m_xBtnModify
->set_sensitive(false);
503 IMPL_LINK_NOARG(SvxPatternTabPage
, ChangeColorHdl_Impl
, ColorListBox
&, void)
506 m_xPatternLB
->SetNoSelection();
509 void SvxPatternTabPage::ChangeColor_Impl()
511 m_xCtlPixel
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
512 m_xCtlPixel
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
513 m_xCtlPixel
->Invalidate();
515 m_xBitmapCtl
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
516 m_xBitmapCtl
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
518 // get bitmap and display it
519 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
520 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
521 m_aCtlPreview
.Invalidate();
524 void SvxPatternTabPage::PointChanged(weld::DrawingArea
* pDrawingArea
, RectPoint
)
526 if (pDrawingArea
== m_xCtlPixel
->GetDrawingArea())
528 m_xBitmapCtl
->SetBmpArray(m_xCtlPixel
->GetBitmapPixelPtr());
530 // get bitmap and display it
531 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
532 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
533 m_aCtlPreview
.Invalidate();
536 m_xPatternLB
->SetNoSelection();
539 sal_Int32
SvxPatternTabPage::SearchPatternList(const OUString
& rPatternName
)
541 long nCount
= m_pPatternList
->Count();
542 bool bValidPatternName
= true;
543 sal_Int32 nPos
= LISTBOX_ENTRY_NOTFOUND
;
545 for(long i
= 0;i
< nCount
&& bValidPatternName
;i
++)
547 if(rPatternName
== m_pPatternList
->GetBitmap( i
)->GetName())
550 bValidPatternName
= false;
556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */