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 <vcl/wrkwin.hxx>
22 #include <tools/urlobj.hxx>
23 #include <unotools/pathoptions.hxx>
24 #include <sfx2/app.hxx>
25 #include <sfx2/dialoghelper.hxx>
26 #include <sfx2/filedlghelper.hxx>
27 #include <unotools/localfilehelper.hxx>
28 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
29 #include <svx/colorbox.hxx>
30 #include <svx/dialmgr.hxx>
31 #include <vcl/bitmapaccess.hxx>
32 #include <vcl/BitmapTools.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/svapp.hxx>
35 #include <vcl/weld.hxx>
36 #include <svx/dialogs.hrc>
37 #include <svx/strings.hrc>
39 #include <strings.hrc>
40 #include <svx/xbtmpit.hxx>
41 #include <svx/xpool.hxx>
42 #include <svx/xtable.hxx>
43 #include <svx/xoutbmp.hxx>
44 #include <svx/drawitem.hxx>
45 #include <svx/xflbmtit.hxx>
46 #include <cuitabarea.hxx>
47 #include <defdlgname.hxx>
48 #include <dlgname.hxx>
49 #include <svx/svxdlg.hxx>
50 #include <dialmgr.hxx>
51 #include <sfx2/opengrf.hxx>
52 #include <sal/log.hxx>
54 using namespace com::sun::star
;
56 /*************************************************************************
57 |* Preview control for the display of bitmaps
58 \************************************************************************/
63 Color aPixelColor
, aBackgroundColor
;
64 std::array
<sal_uInt8
,64> const * pBmpArray
;
67 // Constructor: BitmapCtl for SvxPixelCtl
73 // BitmapCtl: Returns the Bitmap
74 BitmapEx
GetBitmapEx()
78 return vcl::bitmap::createHistorical8x8FromArray(*pBmpArray
, aPixelColor
, aBackgroundColor
);
81 void SetBmpArray( std::array
<sal_uInt8
,64> const & pPixel
) { pBmpArray
= &pPixel
; }
82 void SetPixelColor( Color aColor
) { aPixelColor
= aColor
; }
83 void SetBackgroundColor( Color aColor
) { aBackgroundColor
= aColor
; }
86 SvxPatternTabPage::SvxPatternTabPage(TabPageParent pParent
, const SfxItemSet
& rInAttrs
)
87 : SvxTabPage(pParent
, "cui/ui/patterntabpage.ui", "PatternTabPage", rInAttrs
)
88 , m_rOutAttrs(rInAttrs
)
89 , m_pnPatternListState(nullptr)
90 , m_pnColorListState(nullptr)
91 , m_aXFillAttr(rInAttrs
.GetPool())
92 , m_rXFSet(m_aXFillAttr
.GetItemSet())
93 , m_xCtlPixel(new SvxPixelCtl(this))
94 , m_xLbColor(new ColorListBox(m_xBuilder
->weld_menu_button("LB_COLOR"), pParent
.GetFrameWeld()))
95 , m_xLbBackgroundColor(new ColorListBox(m_xBuilder
->weld_menu_button("LB_BACKGROUND_COLOR"), pParent
.GetFrameWeld()))
96 , m_xPatternLB(new SvxPresetListBox(m_xBuilder
->weld_scrolled_window("patternpresetlistwin")))
97 , m_xBtnAdd(m_xBuilder
->weld_button("BTN_ADD"))
98 , m_xBtnModify(m_xBuilder
->weld_button("BTN_MODIFY"))
99 , m_xCtlPixelWin(new weld::CustomWeld(*m_xBuilder
, "CTL_PIXEL", *m_xCtlPixel
))
100 , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder
, "CTL_PREVIEW", m_aCtlPreview
))
101 , m_xPatternLBWin(new weld::CustomWeld(*m_xBuilder
, "patternpresetlist", *m_xPatternLB
))
103 // size of the bitmap display
104 Size aSize
= getDrawPreviewOptimalSize(this);
105 m_xPatternLB
->set_size_request(aSize
.Width(), aSize
.Height());
106 m_xCtlPreview
->set_size_request(aSize
.Width(), aSize
.Height());
108 m_xBitmapCtl
.reset(new SvxBitmapCtl
);
110 // this page needs ExchangeSupport
111 SetExchangeSupport();
113 // setting the output device
114 m_rXFSet
.Put( XFillStyleItem(drawing::FillStyle_BITMAP
) );
115 m_rXFSet
.Put( XFillBitmapItem(OUString(), Graphic()) );
117 m_xBtnAdd
->connect_clicked( LINK( this, SvxPatternTabPage
, ClickAddHdl_Impl
) );
118 m_xBtnModify
->connect_clicked( LINK( this, SvxPatternTabPage
, ClickModifyHdl_Impl
) );
120 m_xPatternLB
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangePatternHdl_Impl
) );
121 m_xPatternLB
->SetRenameHdl( LINK( this, SvxPatternTabPage
, ClickRenameHdl_Impl
) );
122 m_xPatternLB
->SetDeleteHdl( LINK( this, SvxPatternTabPage
, ClickDeleteHdl_Impl
) );
123 m_xLbColor
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangeColorHdl_Impl
) );
124 m_xLbBackgroundColor
->SetSelectHdl( LINK( this, SvxPatternTabPage
, ChangeColorHdl_Impl
) );
127 SvxPatternTabPage::~SvxPatternTabPage()
132 void SvxPatternTabPage::dispose()
134 m_xPatternLBWin
.reset();
135 m_xCtlPreview
.reset();
136 m_xCtlPixelWin
.reset();
137 m_xPatternLB
.reset();
138 m_xLbBackgroundColor
.reset();
141 SvxTabPage::dispose();
144 void SvxPatternTabPage::Construct()
146 m_xPatternLB
->FillPresetListBox( *m_pPatternList
);
149 void SvxPatternTabPage::ActivatePage( const SfxItemSet
& rSet
)
151 if( m_pColorList
.is() )
154 if( *m_pnColorListState
& ChangeType::CHANGED
||
155 *m_pnColorListState
& ChangeType::MODIFIED
)
157 SvxAreaTabDialog
* pArea
= (*m_pnColorListState
& ChangeType::CHANGED
) ?
158 dynamic_cast<SvxAreaTabDialog
*>(GetParentDialog()) : nullptr;
160 m_pColorList
= pArea
->GetNewColorList();
163 // determining (possibly cutting) the name and
164 // displaying it in the GroupBox
165 OUString
aString( CuiResId( RID_SVXSTR_TABLE
) );
167 INetURLObject
aURL( m_pPatternList
->GetPath() );
169 aURL
.Append( m_pPatternList
->GetName() );
170 SAL_WARN_IF( aURL
.GetProtocol() == INetProtocol::NotValid
, "cui.tabpages", "invalid URL" );
172 if( aURL
.getBase().getLength() > 18 )
174 aString
+= aURL
.getBase().copy( 0, 15 ) + "...";
177 aString
+= aURL
.getBase();
179 XFillBitmapItem
aItem( rSet
.Get( XATTR_FILLBITMAP
) );
181 if ( aItem
.isPattern() )
183 sal_Int32 nPos
= SearchPatternList( aItem
.GetName() );
184 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
186 sal_uInt16 nId
= m_xPatternLB
->GetItemId( static_cast<size_t>( nPos
) );
187 m_xPatternLB
->SelectItem( nId
);
191 m_xPatternLB
->SelectItem( m_xPatternLB
->GetItemId( static_cast<size_t>( 0 ) ) );
196 DeactivateRC
SvxPatternTabPage::DeactivatePage( SfxItemSet
* _pSet
)
199 FillItemSet( _pSet
);
201 return DeactivateRC::LeavePage
;
205 bool SvxPatternTabPage::FillItemSet( SfxItemSet
* _rOutAttrs
)
207 _rOutAttrs
->Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
208 size_t nPos
= m_xPatternLB
->IsNoSelection() ? VALUESET_ITEM_NOTFOUND
: m_xPatternLB
->GetSelectItemPos();
209 if(VALUESET_ITEM_NOTFOUND
!= nPos
)
211 const XBitmapEntry
* pXBitmapEntry
= m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) );
212 const OUString
aString( m_xPatternLB
->GetItemText( m_xPatternLB
->GetSelectedItemId() ) );
214 _rOutAttrs
->Put(XFillBitmapItem(aString
, pXBitmapEntry
->GetGraphicObject()));
218 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
220 _rOutAttrs
->Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx
)));
222 _rOutAttrs
->Put(XFillBmpTileItem(true));
227 void SvxPatternTabPage::Reset( const SfxItemSet
* )
229 m_xBitmapCtl
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
230 m_xBitmapCtl
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
231 m_xBitmapCtl
->SetBmpArray( m_xCtlPixel
->GetBitmapPixelPtr() );
233 // get bitmap and display it
234 const XFillBitmapItem
aBmpItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx()));
235 if(aBmpItem
.isPattern())
237 m_rXFSet
.Put( aBmpItem
);
238 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
239 m_aCtlPreview
.Invalidate();
242 ChangePatternHdl_Impl(m_xPatternLB
.get());
244 // determine button state
245 if( m_pPatternList
.is() && m_pPatternList
->Count() )
247 m_xBtnAdd
->set_sensitive(true);
248 m_xBtnModify
->set_sensitive(true);
252 m_xBtnModify
->set_sensitive(false);
257 VclPtr
<SfxTabPage
> SvxPatternTabPage::Create( TabPageParent pWindow
,
258 const SfxItemSet
* rSet
)
260 return VclPtr
<SvxPatternTabPage
>::Create(pWindow
, *rSet
);
264 IMPL_LINK_NOARG(SvxPatternTabPage
, ChangePatternHdl_Impl
, SvtValueSet
*, void)
266 std::unique_ptr
<GraphicObject
> pGraphicObject
;
267 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
269 if(VALUESET_ITEM_NOTFOUND
!= nPos
)
271 pGraphicObject
.reset(new GraphicObject(m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) )->GetGraphicObject()));
275 const SfxPoolItem
* pPoolItem
= nullptr;
277 if(SfxItemState::SET
== m_rOutAttrs
.GetItemState(GetWhich(XATTR_FILLSTYLE
), true, &pPoolItem
))
279 const drawing::FillStyle
eXFS(static_cast<const XFillStyleItem
*>(pPoolItem
)->GetValue());
281 if((drawing::FillStyle_BITMAP
== eXFS
) && (SfxItemState::SET
== m_rOutAttrs
.GetItemState(GetWhich(XATTR_FILLBITMAP
), true, &pPoolItem
)))
283 pGraphicObject
.reset(new GraphicObject(static_cast<const XFillBitmapItem
*>(pPoolItem
)->GetGraphicObject()));
289 sal_uInt16 nPosition
= m_xPatternLB
->GetItemId( 0 );
290 m_xPatternLB
->SelectItem( nPosition
);
293 pGraphicObject
.reset(new GraphicObject(m_pPatternList
->GetBitmap(0)->GetGraphicObject()));
302 bool bIs8x8(vcl::bitmap::isHistorical8x8(pGraphicObject
->GetGraphic().GetBitmapEx(), aBackColor
, aPixelColor
));
304 m_xLbColor
->SetNoSelection();
305 m_xLbBackgroundColor
->SetNoSelection();
309 m_xCtlPixel
->SetPaintable( true );
310 m_xBtnModify
->set_sensitive(true);
311 m_xBtnAdd
->set_sensitive(true);
313 // setting the pixel control
315 m_xCtlPixel
->SetXBitmap(pGraphicObject
->GetGraphic().GetBitmapEx());
317 m_xLbColor
->SelectEntry( aPixelColor
);
318 m_xLbBackgroundColor
->SelectEntry( aBackColor
);
320 // update m_xBitmapCtl, rXFSet and m_aCtlPreview
321 m_xBitmapCtl
->SetPixelColor( aPixelColor
);
322 m_xBitmapCtl
->SetBackgroundColor( aBackColor
);
323 m_rXFSet
.ClearItem();
324 m_rXFSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
325 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
326 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
327 m_aCtlPreview
.Invalidate();
331 m_xCtlPixel
->Reset();
332 m_xCtlPixel
->SetPaintable( false );
333 m_xBtnModify
->set_sensitive(false);
334 m_xBtnAdd
->set_sensitive(false);
337 m_xCtlPixel
->Invalidate();
341 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickAddHdl_Impl
, weld::Button
&, void)
344 OUString
aNewName( SvxResId( RID_SVXSTR_PATTERN_UNTITLED
) );
345 OUString
aDesc( CuiResId( RID_SVXSTR_DESC_NEW_PATTERN
) );
348 long nCount
= m_pPatternList
->Count();
350 bool bValidPatternName
= false;
352 while( !bValidPatternName
)
354 aName
= aNewName
+ " " + OUString::number( j
++ );
355 bValidPatternName
= (SearchPatternList(aName
) == LISTBOX_ENTRY_NOTFOUND
);
358 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
359 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetDialogFrameWeld(), aName
, aDesc
));
360 sal_uInt16
nError(1);
362 while( pDlg
->Execute() == RET_OK
)
364 pDlg
->GetName( aName
);
366 bValidPatternName
= (SearchPatternList(aName
) == LISTBOX_ENTRY_NOTFOUND
);
368 if( bValidPatternName
) {
373 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
374 std::unique_ptr
<weld::MessageDialog
> xWarnBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
375 if (xWarnBox
->run() != RET_OK
)
379 pDlg
.disposeAndClear();
383 std::unique_ptr
<XBitmapEntry
> pEntry
;
384 if( m_xCtlPixel
->IsEnabled() )
386 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
388 pEntry
.reset(new XBitmapEntry(Graphic(aBitmapEx
), aName
));
390 else // it must be a not existing imported bitmap
392 const SfxPoolItem
* pPoolItem
= nullptr;
394 if(SfxItemState::SET
== m_rOutAttrs
.GetItemState(XATTR_FILLBITMAP
, true, &pPoolItem
))
396 auto pFillBmpItem
= dynamic_cast<const XFillBitmapItem
*>(pPoolItem
);
397 assert(pFillBmpItem
);
398 pEntry
.reset(new XBitmapEntry(pFillBmpItem
->GetGraphicObject(), aName
));
401 assert(!"SvxPatternTabPage::ClickAddHdl_Impl(), XBitmapEntry* pEntry == nullptr ?");
406 m_pPatternList
->Insert(std::move(pEntry
), nCount
);
407 sal_Int32 nId
= m_xPatternLB
->GetItemId( nCount
- 1 );
408 BitmapEx aBitmap
= m_pPatternList
->GetBitmapForPreview( nCount
, m_xPatternLB
->GetIconSize() );
409 m_xPatternLB
->InsertItem( nId
+ 1, Image(aBitmap
), aName
);
410 m_xPatternLB
->SelectItem( nId
+ 1 );
411 m_xPatternLB
->Resize();
413 *m_pnPatternListState
|= ChangeType::MODIFIED
;
415 ChangePatternHdl_Impl(m_xPatternLB
.get());
419 // determine button state
420 if( m_pPatternList
->Count() )
422 m_xBtnModify
->set_sensitive(true);
426 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickModifyHdl_Impl
, weld::Button
&, void)
428 sal_uInt16 nId
= m_xPatternLB
->GetSelectedItemId();
429 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
431 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
433 OUString
aName( m_pPatternList
->GetBitmap( static_cast<sal_uInt16
>(nPos
) )->GetName() );
435 const BitmapEx
aBitmapEx(m_xBitmapCtl
->GetBitmapEx());
437 // #i123497# Need to replace the existing entry with a new one (old returned needs to be deleted)
438 m_pPatternList
->Replace(std::make_unique
<XBitmapEntry
>(Graphic(aBitmapEx
), aName
), nPos
);
440 BitmapEx aBitmap
= m_pPatternList
->GetBitmapForPreview( static_cast<sal_uInt16
>( nPos
), m_xPatternLB
->GetIconSize() );
441 m_xPatternLB
->RemoveItem(nId
);
442 m_xPatternLB
->InsertItem( nId
, Image(aBitmap
), aName
, static_cast<sal_uInt16
>(nPos
) );
443 m_xPatternLB
->SelectItem( nId
);
445 *m_pnPatternListState
|= ChangeType::MODIFIED
;
450 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickRenameHdl_Impl
, SvxPresetListBox
*, void)
452 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
453 sal_Int32 nId
= m_xPatternLB
->GetSelectedItemId();
455 if ( nPos
!= VALUESET_ITEM_NOTFOUND
)
457 OUString
aDesc(CuiResId(RID_SVXSTR_DESC_NEW_PATTERN
));
458 OUString
aName(m_pPatternList
->GetBitmap(nPos
)->GetName());
460 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
461 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetDialogFrameWeld(), aName
, aDesc
));
465 while( bLoop
&& pDlg
->Execute() == RET_OK
)
467 pDlg
->GetName( aName
);
468 sal_Int32 nPatternPos
= SearchPatternList(aName
);
469 bool bValidPatternName
= (nPatternPos
== static_cast<sal_Int32
>(nPos
) ) || (nPatternPos
== LISTBOX_ENTRY_NOTFOUND
);
471 if( bValidPatternName
)
475 m_pPatternList
->GetBitmap(nPos
)->SetName(aName
);
477 m_xPatternLB
->SetItemText( nId
, aName
);
478 m_xPatternLB
->SelectItem( nId
);
480 *m_pnPatternListState
|= ChangeType::MODIFIED
;
484 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
485 std::unique_ptr
<weld::MessageDialog
> xWarnBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
492 IMPL_LINK_NOARG(SvxPatternTabPage
, ClickDeleteHdl_Impl
, SvxPresetListBox
*, void)
494 sal_uInt16 nId
= m_xPatternLB
->GetSelectedItemId();
495 size_t nPos
= m_xPatternLB
->GetSelectItemPos();
497 if( nPos
!= VALUESET_ITEM_NOTFOUND
)
499 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/querydeletebitmapdialog.ui"));
500 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("AskDelBitmapDialog"));
501 if (xQueryBox
->run() == RET_YES
)
503 m_pPatternList
->Remove(nPos
);
504 m_xPatternLB
->RemoveItem( nId
);
505 nId
= m_xPatternLB
->GetItemId(0);
506 m_xPatternLB
->SelectItem( nId
);
507 m_xPatternLB
->Resize();
509 m_aCtlPreview
.Invalidate();
510 m_xCtlPixel
->Invalidate();
512 ChangePatternHdl_Impl(m_xPatternLB
.get());
514 *m_pnPatternListState
|= ChangeType::MODIFIED
;
517 // determine button state
518 if( !m_pPatternList
->Count() )
520 m_xBtnModify
->set_sensitive(false);
524 IMPL_LINK_NOARG(SvxPatternTabPage
, ChangeColorHdl_Impl
, ColorListBox
&, void)
527 m_xPatternLB
->SetNoSelection();
530 void SvxPatternTabPage::ChangeColor_Impl()
532 m_xCtlPixel
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
533 m_xCtlPixel
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
534 m_xCtlPixel
->Invalidate();
536 m_xBitmapCtl
->SetPixelColor( m_xLbColor
->GetSelectEntryColor() );
537 m_xBitmapCtl
->SetBackgroundColor( m_xLbBackgroundColor
->GetSelectEntryColor() );
539 // get bitmap and display it
540 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
541 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
542 m_aCtlPreview
.Invalidate();
545 void SvxPatternTabPage::PointChanged(weld::DrawingArea
* pDrawingArea
, RectPoint
)
547 if (pDrawingArea
== m_xCtlPixel
->GetDrawingArea())
549 m_xBitmapCtl
->SetBmpArray(m_xCtlPixel
->GetBitmapPixelPtr());
551 // get bitmap and display it
552 m_rXFSet
.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl
->GetBitmapEx())));
553 m_aCtlPreview
.SetAttributes( m_aXFillAttr
.GetItemSet() );
554 m_aCtlPreview
.Invalidate();
557 m_xPatternLB
->SetNoSelection();
560 sal_Int32
SvxPatternTabPage::SearchPatternList(const OUString
& rPatternName
)
562 long nCount
= m_pPatternList
->Count();
563 bool bValidPatternName
= true;
564 sal_Int32 nPos
= LISTBOX_ENTRY_NOTFOUND
;
566 for(long i
= 0;i
< nCount
&& bValidPatternName
;i
++)
568 if(rPatternName
== m_pPatternList
->GetBitmap( i
)->GetName())
571 bValidPatternName
= false;
577 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */