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 .
20 #include <tools/urlobj.hxx>
21 #include <vcl/settings.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/weld.hxx>
24 #include <unotools/pathoptions.hxx>
25 #include <sfx2/app.hxx>
26 #include <sfx2/filedlghelper.hxx>
27 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
29 #include <strings.hrc>
30 #include <svx/dialmgr.hxx>
31 #include <svx/svdobj.hxx>
32 #include <svx/svdopath.hxx>
33 #include <svx/drawitem.hxx>
34 #include <svx/xpool.hxx>
35 #include <svx/xtable.hxx>
36 #include <svx/xlnwtit.hxx>
37 #include <svx/xlnclit.hxx>
38 #include <svx/xlnstwit.hxx>
39 #include <svx/xlnedwit.hxx>
40 #include <svx/xlnstit.hxx>
41 #include <svx/xlnedit.hxx>
42 #include <cuitabline.hxx>
43 #include <cuitabarea.hxx>
44 #include <svx/svxdlg.hxx>
45 #include <dialmgr.hxx>
46 #include <svx/dlgutil.hxx>
47 #include <basegfx/range/b2drange.hxx>
48 #include <basegfx/polygon/b2dpolygontools.hxx>
49 #include <basegfx/matrix/b2dhommatrix.hxx>
50 #include <basegfx/polygon/b2dpolygon.hxx>
51 #include <basegfx/polygon/b2dpolypolygontools.hxx>
52 #include <basegfx/matrix/b2dhommatrixtools.hxx>
53 #include <svx/dialogs.hrc>
54 #include <svx/strings.hrc>
56 #define XOUT_WIDTH 150
58 SvxLineEndDefTabPage::SvxLineEndDefTabPage(TabPageParent pParent
, const SfxItemSet
& rInAttrs
)
59 : SfxTabPage(pParent
, "cui/ui/lineendstabpage.ui", "LineEndPage", &rInAttrs
)
62 , aXLineAttr(rInAttrs
.GetPool())
63 , rXLSet(aXLineAttr
.GetItemSet())
64 , pnLineEndListState(nullptr)
67 , pPosLineEndLb(nullptr)
68 , m_xEdtName(m_xBuilder
->weld_entry("EDT_NAME"))
69 , m_xLbLineEnds(new SvxLineEndLB(m_xBuilder
->weld_combo_box("LB_LINEENDS")))
70 , m_xBtnAdd(m_xBuilder
->weld_button("BTN_ADD"))
71 , m_xBtnModify(m_xBuilder
->weld_button("BTN_MODIFY"))
72 , m_xBtnDelete(m_xBuilder
->weld_button("BTN_DELETE"))
73 , m_xBtnLoad(m_xBuilder
->weld_button("BTN_LOAD"))
74 , m_xBtnSave(m_xBuilder
->weld_button("BTN_SAVE"))
75 , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder
, "CTL_PREVIEW", m_aCtlPreview
))
77 // this page needs ExchangeSupport
80 rXLSet
.Put( XLineStyleItem(css::drawing::LineStyle_SOLID
) );
81 rXLSet
.Put( XLineWidthItem(XOUT_WIDTH
) );
82 rXLSet
.Put( XLineColorItem( OUString(), COL_BLACK
) );
83 rXLSet
.Put( XLineStartWidthItem( m_aCtlPreview
.GetOutputSize().Height() / 2 ) );
84 rXLSet
.Put( XLineEndWidthItem( m_aCtlPreview
.GetOutputSize().Height() / 2 ) );
87 m_aCtlPreview
.SetLineAttributes(aXLineAttr
.GetItemSet());
89 m_xBtnAdd
->connect_clicked(LINK(this, SvxLineEndDefTabPage
, ClickAddHdl_Impl
));
90 m_xBtnModify
->connect_clicked(LINK( this, SvxLineEndDefTabPage
, ClickModifyHdl_Impl
));
91 m_xBtnDelete
->connect_clicked(LINK( this, SvxLineEndDefTabPage
, ClickDeleteHdl_Impl
));
92 m_xBtnLoad
->connect_clicked(LINK( this, SvxLineEndDefTabPage
, ClickLoadHdl_Impl
));
93 m_xBtnSave
->connect_clicked(LINK( this, SvxLineEndDefTabPage
, ClickSaveHdl_Impl
));
95 m_xLbLineEnds
->connect_changed(LINK(this, SvxLineEndDefTabPage
, SelectLineEndHdl_Impl
));
98 SvxLineEndDefTabPage::~SvxLineEndDefTabPage()
103 void SvxLineEndDefTabPage::dispose()
105 m_xCtlPreview
.reset();
106 m_xLbLineEnds
.reset();
107 SfxTabPage::dispose();
110 void SvxLineEndDefTabPage::Resize()
112 rXLSet
.Put(XLineStartWidthItem(m_aCtlPreview
.GetOutputSize().Height() / 2));
113 rXLSet
.Put(XLineEndWidthItem(m_aCtlPreview
.GetOutputSize().Height() / 2));
114 SfxTabPage::Resize();
117 void SvxLineEndDefTabPage::Construct()
119 m_xLbLineEnds
->Fill( pLineEndList
);
121 bool bCreateArrowPossible
= true;
125 bCreateArrowPossible
= false;
127 else if( nullptr == dynamic_cast<const SdrPathObj
*>( pPolyObj
) )
129 SdrObjTransformInfoRec aInfoRec
;
130 pPolyObj
->TakeObjInfo( aInfoRec
);
131 SdrObject
* pNewObj
= nullptr;
132 if( aInfoRec
.bCanConvToPath
)
133 pNewObj
= pPolyObj
->ConvertToPolyObj( true, false );
135 bCreateArrowPossible
= nullptr != dynamic_cast<const SdrPathObj
*>( pNewObj
);
136 SdrObject::Free( pNewObj
);
139 if( !bCreateArrowPossible
)
140 m_xBtnAdd
->set_sensitive(false);
143 void SvxLineEndDefTabPage::ActivatePage( const SfxItemSet
& )
145 if( nDlgType
== 0 ) // area dialog
147 // ActivatePage() is called before the dialog receives PageCreated() !!!
148 if( pLineEndList
.is() )
150 if( *pPosLineEndLb
!= -1)
152 m_xLbLineEnds
->set_active(*pPosLineEndLb
);
153 SelectLineEndHdl_Impl();
155 INetURLObject
aURL( pLineEndList
->GetPath() );
157 aURL
.Append( pLineEndList
->GetName() );
158 DBG_ASSERT( aURL
.GetProtocol() != INetProtocol::NotValid
, "invalid URL" );
159 *pPageType
= PageType::Area
; // 3
166 DeactivateRC
SvxLineEndDefTabPage::DeactivatePage( SfxItemSet
* _pSet
)
171 FillItemSet( _pSet
);
173 return DeactivateRC::LeavePage
;
177 void SvxLineEndDefTabPage::CheckChanges_Impl()
179 int nPos
= m_xLbLineEnds
->get_active();
183 OUString aString
= m_xEdtName
->get_text();
185 if( aString
!= m_xLbLineEnds
->get_active_text() )
187 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/querychangelineenddialog.ui"));
188 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("AskChangeLineEndDialog"));
189 if (xQueryBox
->run() == RET_YES
)
190 ClickModifyHdl_Impl(*m_xBtnModify
);
193 nPos
= m_xLbLineEnds
->get_active();
196 *pPosLineEndLb
= nPos
;
200 bool SvxLineEndDefTabPage::FillItemSet( SfxItemSet
* rSet
)
202 if( nDlgType
== 0 ) // line dialog
204 if( *pPageType
== PageType::Bitmap
)
208 int nPos
= m_xLbLineEnds
->get_active();
209 const XLineEndEntry
* pEntry
= pLineEndList
->GetLineEnd(nPos
);
211 rSet
->Put( XLineStartItem( pEntry
->GetName(), pEntry
->GetLineEnd() ) );
212 rSet
->Put( XLineEndItem( pEntry
->GetName(), pEntry
->GetLineEnd() ) );
218 void SvxLineEndDefTabPage::Reset( const SfxItemSet
* )
220 m_xLbLineEnds
->set_active(0);
223 if( pLineEndList
->Count() > 0 )
225 int nPos
= m_xLbLineEnds
->get_active();
227 const XLineEndEntry
* pEntry
= pLineEndList
->GetLineEnd(nPos
);
229 m_xEdtName
->set_text(m_xLbLineEnds
->get_active_text());
231 rXLSet
.Put( XLineStartItem( OUString(), pEntry
->GetLineEnd() ) );
232 rXLSet
.Put( XLineEndItem( OUString(), pEntry
->GetLineEnd() ) );
235 m_aCtlPreview
.SetLineAttributes(aXLineAttr
.GetItemSet());
236 m_aCtlPreview
.Invalidate();
239 // determine button state
240 if( pLineEndList
->Count() )
242 m_xBtnModify
->set_sensitive(true);
243 m_xBtnDelete
->set_sensitive(true);
244 m_xBtnSave
->set_sensitive(true);
248 m_xBtnModify
->set_sensitive(false);
249 m_xBtnDelete
->set_sensitive(false);
250 m_xBtnSave
->set_sensitive(false);
254 VclPtr
<SfxTabPage
> SvxLineEndDefTabPage::Create(TabPageParent pParent
, const SfxItemSet
* rSet
)
256 return VclPtr
<SvxLineEndDefTabPage
>::Create(pParent
, *rSet
);
259 void SvxLineEndDefTabPage::SelectLineEndHdl_Impl()
261 if( pLineEndList
->Count() > 0 )
263 int nPos
= m_xLbLineEnds
->get_active();
265 const XLineEndEntry
* pEntry
= pLineEndList
->GetLineEnd(nPos
);
267 m_xEdtName
->set_text(m_xLbLineEnds
->get_active_text());
269 rXLSet
.Put( XLineStartItem( OUString(), pEntry
->GetLineEnd() ) );
270 rXLSet
.Put( XLineEndItem( OUString(), pEntry
->GetLineEnd() ) );
273 m_aCtlPreview
.SetLineAttributes(aXLineAttr
.GetItemSet());
274 m_aCtlPreview
.Invalidate();
276 // Is not set before, in order to only take the new style,
277 // if there is an entry selected in the ListBox
278 *pPageType
= PageType::Bitmap
;
282 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, SelectLineEndHdl_Impl
, weld::ComboBox
&, void)
284 SelectLineEndHdl_Impl();
287 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickModifyHdl_Impl
, weld::Button
&, void)
289 int nPos
= m_xLbLineEnds
->get_active();
292 OUString
aDesc(CuiResId(RID_SVXSTR_DESC_LINEEND
));
293 OUString
aName(m_xEdtName
->get_text());
294 long nCount
= pLineEndList
->Count();
295 bool bDifferent
= true;
297 // check whether the name is existing already
298 for ( long i
= 0; i
< nCount
&& bDifferent
; i
++ )
299 if ( aName
== pLineEndList
->GetLineEnd( i
)->GetName() )
302 // if yes, repeat and demand a new name
305 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
306 std::unique_ptr
<weld::MessageDialog
> xWarningBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
309 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
310 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetDialogFrameWeld(), aName
, aDesc
));
313 while( !bDifferent
&& bLoop
&& pDlg
->Execute() == RET_OK
)
315 pDlg
->GetName( aName
);
318 for( long i
= 0; i
< nCount
&& bDifferent
; i
++ )
320 if( aName
== pLineEndList
->GetLineEnd( i
)->GetName() )
331 // if not existing, enter the entry
334 const XLineEndEntry
* pOldEntry
= pLineEndList
->GetLineEnd(nPos
);
338 // #123497# Need to replace the existing entry with a new one
339 pLineEndList
->Replace(std::make_unique
<XLineEndEntry
>(pOldEntry
->GetLineEnd(), aName
), nPos
);
341 m_xEdtName
->set_text(aName
);
343 m_xLbLineEnds
->Modify(*pLineEndList
->GetLineEnd(nPos
), nPos
, pLineEndList
->GetUiBitmap(nPos
));
344 m_xLbLineEnds
->set_active(nPos
);
346 // set flag for modified
347 *pnLineEndListState
|= ChangeType::MODIFIED
;
349 *pPageType
= PageType::Bitmap
;
353 OSL_ENSURE(false, "LineEnd to be modified not existing (!)");
359 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickAddHdl_Impl
, weld::Button
&, void)
363 const SdrObject
* pNewObj
;
364 SdrObject
* pConvPolyObj
= nullptr;
366 if( nullptr != dynamic_cast<const SdrPathObj
*>( pPolyObj
) )
372 SdrObjTransformInfoRec aInfoRec
;
373 pPolyObj
->TakeObjInfo( aInfoRec
);
375 if( aInfoRec
.bCanConvToPath
)
377 pNewObj
= pConvPolyObj
= pPolyObj
->ConvertToPolyObj( true, false );
379 if( !pNewObj
|| nullptr == dynamic_cast<const SdrPathObj
*>( pNewObj
) )
380 return; // cancel, additional safety, which
381 // has no use for group objects though.
383 else return; // cancel
386 basegfx::B2DPolyPolygon
aNewPolyPolygon(static_cast<const SdrPathObj
*>(pNewObj
)->GetPathPoly());
387 basegfx::B2DRange
aNewRange(basegfx::utils::getRange(aNewPolyPolygon
));
390 aNewPolyPolygon
.transform(basegfx::utils::createTranslateB2DHomMatrix( -aNewRange
.getMinX(), -aNewRange
.getMinY()));
392 SdrObject::Free( pConvPolyObj
);
394 OUString
aNewName(SvxResId(RID_SVXSTR_LINEEND
));
395 OUString
aDesc(CuiResId(RID_SVXSTR_DESC_LINEEND
));
398 long nCount
= pLineEndList
->Count();
400 bool bDifferent
= false;
402 while ( !bDifferent
)
404 aName
= aNewName
+ " " + OUString::number( j
++ );
407 for( long i
= 0; i
< nCount
&& bDifferent
; i
++ )
408 if ( aName
== pLineEndList
->GetLineEnd( i
)->GetName() )
412 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
413 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetDialogFrameWeld(), aName
, aDesc
));
416 while ( bLoop
&& pDlg
->Execute() == RET_OK
)
418 pDlg
->GetName( aName
);
421 for( long i
= 0; i
< nCount
&& bDifferent
; i
++ )
423 if( aName
== pLineEndList
->GetLineEnd( i
)->GetName() )
431 auto nLineEndCount
= pLineEndList
->Count();
432 pLineEndList
->Insert(std::make_unique
<XLineEndEntry
>(aNewPolyPolygon
, aName
), nLineEndCount
);
434 // add to the ListBox
435 m_xLbLineEnds
->Append(*pLineEndList
->GetLineEnd(nLineEndCount
), pLineEndList
->GetUiBitmap(nLineEndCount
));
436 m_xLbLineEnds
->set_active(m_xLbLineEnds
->get_count() - 1);
438 *pnLineEndListState
|= ChangeType::MODIFIED
;
440 SelectLineEndHdl_Impl();
444 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
445 std::unique_ptr
<weld::MessageDialog
> xWarningBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
451 m_xBtnAdd
->set_sensitive(false);
453 // determine button state
454 if ( pLineEndList
->Count() )
456 m_xBtnModify
->set_sensitive(true);
457 m_xBtnDelete
->set_sensitive(true);
458 m_xBtnSave
->set_sensitive(true);
462 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickDeleteHdl_Impl
, weld::Button
&, void)
464 int nPos
= m_xLbLineEnds
->get_active();
468 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/querydeletelineenddialog.ui"));
469 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("AskDelLineEndDialog"));
471 if (xQueryBox
->run() == RET_YES
)
473 pLineEndList
->Remove(nPos
);
474 m_xLbLineEnds
->remove(nPos
);
475 m_xLbLineEnds
->set_active(0);
477 SelectLineEndHdl_Impl();
478 *pPageType
= PageType::Area
; // LineEnd shall not be taken over
480 *pnLineEndListState
|= ChangeType::MODIFIED
;
482 m_aCtlPreview
.Invalidate();
485 // determine button state
486 if( !pLineEndList
->Count() )
488 m_xBtnModify
->set_sensitive(false);
489 m_xBtnDelete
->set_sensitive(false);
490 m_xBtnSave
->set_sensitive(false);
494 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickLoadHdl_Impl
, weld::Button
&, void)
496 sal_uInt16 nReturn
= RET_YES
;
498 if ( *pnLineEndListState
& ChangeType::MODIFIED
)
500 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/querysavelistdialog.ui"));
501 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("AskSaveList"));
503 nReturn
= xBox
->run();
505 if ( nReturn
== RET_YES
)
506 pLineEndList
->Save();
509 if ( nReturn
!= RET_CANCEL
)
511 ::sfx2::FileDialogHelper
aDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE
,
512 FileDialogFlags::NONE
, GetDialogFrameWeld());
513 OUString
aStrFilterType( "*.soe" );
514 aDlg
.AddFilter( aStrFilterType
, aStrFilterType
);
516 OUString
aPalettePath(SvtPathOptions().GetPalettePath());
518 sal_Int32 nIndex
= 0;
521 aLastDir
= aPalettePath
.getToken(0, ';', nIndex
);
525 INetURLObject
aFile(aLastDir
);
526 aDlg
.SetDisplayDirectory( aFile
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
528 if( aDlg
.Execute() == ERRCODE_NONE
)
530 INetURLObject
aURL( aDlg
.GetPath() );
531 INetURLObject
aPathURL( aURL
);
533 aPathURL
.removeSegment();
534 aPathURL
.removeFinalSlash();
536 XLineEndListRef pLeList
= XPropertyList::AsLineEndList(
537 XPropertyList::CreatePropertyList(
538 XPropertyListType::LineEnd
,
539 aPathURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
), ""));
540 pLeList
->SetName( aURL
.getName() );
541 if( pLeList
->Load() )
543 pLineEndList
= pLeList
;
544 static_cast<SvxLineTabDialog
*>(GetDialogController())->SetNewLineEndList( pLineEndList
);
545 m_xLbLineEnds
->clear();
546 m_xLbLineEnds
->Fill( pLineEndList
);
549 pLineEndList
->SetName( aURL
.getName() );
551 *pnLineEndListState
|= ChangeType::CHANGED
;
552 *pnLineEndListState
&= ~ChangeType::MODIFIED
;
556 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/querynoloadedfiledialog.ui"));
557 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("NoLoadedFileDialog"));
563 // determine button state
564 if ( pLineEndList
->Count() )
566 m_xBtnModify
->set_sensitive(true);
567 m_xBtnDelete
->set_sensitive(true);
568 m_xBtnSave
->set_sensitive(true);
572 m_xBtnModify
->set_sensitive(false);
573 m_xBtnDelete
->set_sensitive(false);
574 m_xBtnSave
->set_sensitive(false);
578 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickSaveHdl_Impl
, weld::Button
&, void)
580 ::sfx2::FileDialogHelper
aDlg(css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE
, FileDialogFlags::NONE
, GetDialogFrameWeld());
581 OUString
aStrFilterType( "*.soe" );
582 aDlg
.AddFilter( aStrFilterType
, aStrFilterType
);
584 OUString
aPalettePath(SvtPathOptions().GetPalettePath());
586 sal_Int32 nIndex
= 0;
589 aLastDir
= aPalettePath
.getToken(0, ';', nIndex
);
593 INetURLObject
aFile(aLastDir
);
594 DBG_ASSERT( aFile
.GetProtocol() != INetProtocol::NotValid
, "invalid URL" );
596 if( !pLineEndList
->GetName().isEmpty() )
598 aFile
.Append( pLineEndList
->GetName() );
600 if( aFile
.getExtension().isEmpty() )
601 aFile
.SetExtension( "soe" );
604 aDlg
.SetDisplayDirectory( aFile
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
605 if ( aDlg
.Execute() == ERRCODE_NONE
)
607 INetURLObject
aURL( aDlg
.GetPath() );
608 INetURLObject
aPathURL( aURL
);
610 aPathURL
.removeSegment();
611 aPathURL
.removeFinalSlash();
613 pLineEndList
->SetName( aURL
.getName() );
614 pLineEndList
->SetPath( aPathURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
616 if( pLineEndList
->Save() )
618 *pnLineEndListState
&= ~ChangeType::MODIFIED
;
622 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetDialogFrameWeld(), "cui/ui/querynosavefiledialog.ui"));
623 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("NoSaveFileDialog"));
629 void SvxLineEndDefTabPage::DataChanged( const DataChangedEvent
& rDCEvt
)
631 SfxTabPage::DataChanged( rDCEvt
);
633 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
635 auto nOldSelect
= m_xLbLineEnds
->get_active();
636 m_xLbLineEnds
->clear();
637 m_xLbLineEnds
->Fill(pLineEndList
);
638 m_xLbLineEnds
->set_active(nOldSelect
);
642 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */