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
= getDrawPreviewOptimalSize(m_aCtlPreview
.GetDrawingArea()->get_ref_device());
91 m_xPatternLB
->set_size_request(aSize
.Width(), aSize
.Height());
92 m_xCtlPreview
->set_size_request(aSize
.Width(), aSize
.Height());
94 m_xBitmapCtl
.reset(new SvxBitmapCtl
);
96 // this page needs ExchangeSupport
99 // setting the output device
100 m_rXFSet
.Put( XFillStyleItem(drawing::FillStyle_BITMAP
) );
101 m_rXFSet
.Put( XFillBitmapItem(OUString(), Graphic()) );
103 m_xBtnAdd
->connect_clicked( LINK( this, SvxPatternTabPage
, ClickAddHdl_Impl
) );
104 m_xBtnModify
->connect_clicked( LINK( this, SvxPatternTabPage
, ClickModifyHdl_Impl
) );
106 m_xPatternLB
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangePatternHdl_Impl
) );
107 m_xPatternLB
->SetRenameHdl( LINK( this, SvxPatternTabPage
, ClickRenameHdl_Impl
) );
108 m_xPatternLB
->SetDeleteHdl( LINK( this, SvxPatternTabPage
, ClickDeleteHdl_Impl
) );
109 m_xLbColor
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangeColorHdl_Impl
) );
110 m_xLbBackgroundColor
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangeColorHdl_Impl
) );
113 SvxPatternTabPage::~SvxPatternTabPage()
115 m_xPatternLBWin
.reset();
116 m_xCtlPreview
.reset();
117 m_xCtlPixelWin
.reset();
118 m_xPatternLB
.reset();
119 m_xLbBackgroundColor
.reset();
124 void SvxPatternTabPage::Construct()
126 m_xPatternLB
->FillPresetListBox( *m_pPatternList
);
129 void SvxPatternTabPage::ActivatePage( const SfxItemSet
& rSet
)
131 if( m_pColorList
.is() )
134 if( *m_pnColorListState
& ChangeType::CHANGED
||
135 *m_pnColorListState
& ChangeType::MODIFIED
)
137 SvxAreaTabDialog
* pArea
= (*m_pnColorListState
& ChangeType::CHANGED
) ?
138 dynamic_cast<SvxAreaTabDialog
*>(GetDialogController()) : nullptr;
140 m_pColorList
= pArea
->GetNewColorList();
143 // determining (possibly cutting) the name and
144 // displaying it in the GroupBox
145 OUString aString
= CuiResId( RID_SVXSTR_TABLE
) + ": ";
146 INetURLObject
aURL( m_pPatternList
->GetPath() );
148 aURL
.Append( m_pPatternList
->GetName() );
149 SAL_WARN_IF( aURL
.GetProtocol() == INetProtocol::NotValid
, "cui.tabpages", "invalid URL" );
151 if( aURL
.getBase().getLength() > 18 )
153 aString
+= aURL
.getBase().copy( 0, 15 ) + "...";
156 aString
+= aURL
.getBase();
158 XFillBitmapItem
aItem( rSet
.Get( XATTR_FILLBITMAP
) );
160 if ( aItem
.isPattern() )
162 sal_Int32 nPos
= SearchPatternList( aItem
.GetName() );
163 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
165 sal_uInt16 nId
= m_xPatternLB
->GetItemId( static_cast<size_t>( nPos
) );
166 m_xPatternLB
->SelectItem( nId
);
170 m_xPatternLB
->SelectItem( m_xPatternLB
->GetItemId( static_cast<size_t>( 0 ) ) );
175 DeactivateRC
SvxPatternTabPage::DeactivatePage( SfxItemSet
* _pSet
)
178 FillItemSet( _pSet
);
180 return DeactivateRC::LeavePage
;
184 bool SvxPatternTabPage::FillItemSet( SfxItemSet
* _rOutAttrs
)
186 _rOutAttrs
->Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
187 size_t nPos
= m_xPatternLB
->IsNoSelection() ? VALUESET_ITEM_NOTFOUND
: m_xPatternLB
->GetSelectItemPos();
188 if(VALUESET_ITEM_NOTFOUND
!= nPos
)
190 const XBitmapEntry
* pXBitmapEntry
= m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) );
191 const OUString
aString( m_xPatternLB
->GetItemText( m_xPatternLB
->GetSelectedItemId() ) );
193 _rOutAttrs
->Put(XFillBitmapItem(aString
, pXBitmapEntry
->GetGraphicObject()));
197 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
199 _rOutAttrs
->Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx
)));
201 _rOutAttrs
->Put(XFillBmpTileItem(true));
206 void SvxPatternTabPage::Reset( const SfxItemSet
* )
208 m_xBitmapCtl
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
209 m_xBitmapCtl
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
210 m_xBitmapCtl
->SetBmpArray( m_xCtlPixel
->GetBitmapPixelPtr() );
212 // get bitmap and display it
213 const XFillBitmapItem
aBmpItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx()));
214 if(aBmpItem
.isPattern())
216 m_rXFSet
.Put( aBmpItem
);
217 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
218 m_aCtlPreview
.Invalidate();
221 ChangePatternHdl_Impl(m_xPatternLB
.get());
223 // determine button state
224 if( m_pPatternList
.is() && m_pPatternList
->Count() )
226 m_xBtnAdd
->set_sensitive(true);
227 m_xBtnModify
->set_sensitive(true);
231 m_xBtnModify
->set_sensitive(false);
235 std::unique_ptr
<SfxTabPage
> SvxPatternTabPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
236 const SfxItemSet
* rSet
)
238 return std::make_unique
<SvxPatternTabPage
>(pPage
, pController
, *rSet
);
241 IMPL_LINK_NOARG(SvxPatternTabPage
, ChangePatternHdl_Impl
, SvtValueSet
*, void)
243 std::unique_ptr
<GraphicObject
> pGraphicObject
;
244 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
246 if(VALUESET_ITEM_NOTFOUND
!= nPos
)
248 pGraphicObject
.reset(new GraphicObject(m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) )->GetGraphicObject()));
252 const SfxPoolItem
* pPoolItem
= nullptr;
254 if(SfxItemState::SET
== m_rOutAttrs
.GetItemState(GetWhich(XATTR_FILLSTYLE
), true, &pPoolItem
))
256 const drawing::FillStyle
eXFS(static_cast<const XFillStyleItem
*>(pPoolItem
)->GetValue());
258 if((drawing::FillStyle_BITMAP
== eXFS
) && (SfxItemState::SET
== m_rOutAttrs
.GetItemState(GetWhich(XATTR_FILLBITMAP
), true, &pPoolItem
)))
260 pGraphicObject
.reset(new GraphicObject(static_cast<const XFillBitmapItem
*>(pPoolItem
)->GetGraphicObject()));
266 sal_uInt16 nPosition
= m_xPatternLB
->GetItemId( 0 );
267 m_xPatternLB
->SelectItem( nPosition
);
270 pGraphicObject
.reset(new GraphicObject(m_pPatternList
->GetBitmap(0)->GetGraphicObject()));
279 bool bIs8x8(vcl::bitmap::isHistorical8x8(pGraphicObject
->GetGraphic().GetBitmapEx(), aBackColor
, aPixelColor
));
281 m_xLbColor
->SetNoSelection();
282 m_xLbBackgroundColor
->SetNoSelection();
286 m_xCtlPixel
->SetPaintable( true );
287 m_xBtnModify
->set_sensitive(true);
288 m_xBtnAdd
->set_sensitive(true);
290 // setting the pixel control
292 m_xCtlPixel
->SetXBitmap(pGraphicObject
->GetGraphic().GetBitmapEx());
294 m_xLbColor
->SelectEntry( aPixelColor
);
295 m_xLbBackgroundColor
->SelectEntry( aBackColor
);
297 // update m_xBitmapCtl, rXFSet and m_aCtlPreview
298 m_xBitmapCtl
->SetPixelColor( aPixelColor
);
299 m_xBitmapCtl
->SetBackgroundColor( aBackColor
);
300 m_rXFSet
.ClearItem();
301 m_rXFSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
302 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
303 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
304 m_aCtlPreview
.Invalidate();
308 m_xCtlPixel
->Reset();
309 m_xCtlPixel
->SetPaintable( false );
310 m_xBtnModify
->set_sensitive(false);
311 m_xBtnAdd
->set_sensitive(false);
314 m_xCtlPixel
->Invalidate();
318 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickAddHdl_Impl
, weld::Button
&, void)
321 OUString
aNewName( SvxResId( RID_SVXSTR_PATTERN_UNTITLED
) );
322 OUString
aDesc( CuiResId( RID_SVXSTR_DESC_NEW_PATTERN
) );
325 long nCount
= m_pPatternList
->Count();
327 bool bValidPatternName
= false;
329 while( !bValidPatternName
)
331 aName
= aNewName
+ " " + OUString::number( j
++ );
332 bValidPatternName
= (SearchPatternList(aName
) == LISTBOX_ENTRY_NOTFOUND
);
335 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
336 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetFrameWeld(), aName
, aDesc
));
337 sal_uInt16
nError(1);
339 while( pDlg
->Execute() == RET_OK
)
341 pDlg
->GetName( aName
);
343 bValidPatternName
= (SearchPatternList(aName
) == LISTBOX_ENTRY_NOTFOUND
);
345 if( bValidPatternName
) {
350 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
351 std::unique_ptr
<weld::MessageDialog
> xWarnBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
352 if (xWarnBox
->run() != RET_OK
)
356 pDlg
.disposeAndClear();
360 std::unique_ptr
<XBitmapEntry
> pEntry
;
361 if( m_xCtlPixel
->IsEnabled() )
363 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
365 pEntry
.reset(new XBitmapEntry(Graphic(aBitmapEx
), aName
));
367 else // it must be a not existing imported bitmap
369 const SfxPoolItem
* pPoolItem
= nullptr;
371 if(SfxItemState::SET
== m_rOutAttrs
.GetItemState(XATTR_FILLBITMAP
, true, &pPoolItem
))
373 auto pFillBmpItem
= dynamic_cast<const XFillBitmapItem
*>(pPoolItem
);
374 assert(pFillBmpItem
);
375 pEntry
.reset(new XBitmapEntry(pFillBmpItem
->GetGraphicObject(), aName
));
378 assert(!"SvxPatternTabPage::ClickAddHdl_Impl(), XBitmapEntry* pEntry == nullptr ?");
383 m_pPatternList
->Insert(std::move(pEntry
), nCount
);
384 sal_Int32 nId
= m_xPatternLB
->GetItemId( nCount
- 1 );
385 BitmapEx aBitmap
= m_pPatternList
->GetBitmapForPreview( nCount
, m_xPatternLB
->GetIconSize() );
386 m_xPatternLB
->InsertItem( nId
+ 1, Image(aBitmap
), aName
);
387 m_xPatternLB
->SelectItem( nId
+ 1 );
388 m_xPatternLB
->Resize();
390 *m_pnPatternListState
|= ChangeType::MODIFIED
;
392 ChangePatternHdl_Impl(m_xPatternLB
.get());
396 // determine button state
397 if( m_pPatternList
->Count() )
399 m_xBtnModify
->set_sensitive(true);
403 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickModifyHdl_Impl
, weld::Button
&, void)
405 sal_uInt16 nId
= m_xPatternLB
->GetSelectedItemId();
406 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
408 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
;
427 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickRenameHdl_Impl
, SvxPresetListBox
*, void)
429 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
430 sal_Int32 nId
= m_xPatternLB
->GetSelectedItemId();
432 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
434 OUString
aDesc(CuiResId(RID_SVXSTR_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
== LISTBOX_ENTRY_NOTFOUND
);
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"));
469 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickDeleteHdl_Impl
, SvxPresetListBox
*, void)
471 sal_uInt16 nId
= m_xPatternLB
->GetSelectedItemId();
472 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
474 if( nPos
!= VALUESET_ITEM_NOTFOUND
)
476 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletebitmapdialog.ui"));
477 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("AskDelBitmapDialog"));
478 if (xQueryBox
->run() == RET_YES
)
480 m_pPatternList
->Remove(nPos
);
481 m_xPatternLB
->RemoveItem( nId
);
482 nId
= m_xPatternLB
->GetItemId(0);
483 m_xPatternLB
->SelectItem( nId
);
484 m_xPatternLB
->Resize();
486 m_aCtlPreview
.Invalidate();
487 m_xCtlPixel
->Invalidate();
489 ChangePatternHdl_Impl(m_xPatternLB
.get());
491 *m_pnPatternListState
|= ChangeType::MODIFIED
;
494 // determine button state
495 if( !m_pPatternList
->Count() )
497 m_xBtnModify
->set_sensitive(false);
501 IMPL_LINK_NOARG(SvxPatternTabPage
, ChangeColorHdl_Impl
, ColorListBox
&, void)
504 m_xPatternLB
->SetNoSelection();
507 void SvxPatternTabPage::ChangeColor_Impl()
509 m_xCtlPixel
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
510 m_xCtlPixel
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
511 m_xCtlPixel
->Invalidate();
513 m_xBitmapCtl
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
514 m_xBitmapCtl
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
516 // get bitmap and display it
517 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
518 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
519 m_aCtlPreview
.Invalidate();
522 void SvxPatternTabPage::PointChanged(weld::DrawingArea
* pDrawingArea
, RectPoint
)
524 if (pDrawingArea
== m_xCtlPixel
->GetDrawingArea())
526 m_xBitmapCtl
->SetBmpArray(m_xCtlPixel
->GetBitmapPixelPtr());
528 // get bitmap and display it
529 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
530 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
531 m_aCtlPreview
.Invalidate();
534 m_xPatternLB
->SetNoSelection();
537 sal_Int32
SvxPatternTabPage::SearchPatternList(const OUString
& rPatternName
)
539 long nCount
= m_pPatternList
->Count();
540 bool bValidPatternName
= true;
541 sal_Int32 nPos
= LISTBOX_ENTRY_NOTFOUND
;
543 for(long i
= 0;i
< nCount
&& bValidPatternName
;i
++)
545 if(rPatternName
== m_pPatternList
->GetBitmap( i
)->GetName())
548 bValidPatternName
= false;
554 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */