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/filedlghelper.hxx>
26 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
28 #include <strings.hrc>
29 #include <svx/dialmgr.hxx>
30 #include <svx/dlgctrl.hxx>
31 #include <svx/svdobj.hxx>
32 #include <svx/svdopath.hxx>
33 #include <svx/xtable.hxx>
34 #include <svx/xlineit0.hxx>
35 #include <svx/xlnwtit.hxx>
36 #include <svx/xlnclit.hxx>
37 #include <svx/xlnstwit.hxx>
38 #include <svx/xlnedwit.hxx>
39 #include <svx/xlnstit.hxx>
40 #include <svx/xlnedit.hxx>
41 #include <cuitabline.hxx>
42 #include <cuitabarea.hxx>
43 #include <svx/svxdlg.hxx>
44 #include <dialmgr.hxx>
45 #include <basegfx/range/b2drange.hxx>
46 #include <basegfx/polygon/b2dpolypolygontools.hxx>
47 #include <basegfx/matrix/b2dhommatrixtools.hxx>
48 #include <svx/strings.hrc>
50 #define XOUT_WIDTH 150
52 SvxLineEndDefTabPage::SvxLineEndDefTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rInAttrs
)
53 : SfxTabPage(pPage
, pController
, "cui/ui/lineendstabpage.ui", "LineEndPage", &rInAttrs
)
56 , aXLineAttr(rInAttrs
.GetPool())
57 , rXLSet(aXLineAttr
.GetItemSet())
58 , pnLineEndListState(nullptr)
61 , pPosLineEndLb(nullptr)
62 , m_xEdtName(m_xBuilder
->weld_entry("EDT_NAME"))
63 , m_xLbLineEnds(new SvxLineEndLB(m_xBuilder
->weld_combo_box("LB_LINEENDS")))
64 , m_xBtnAdd(m_xBuilder
->weld_button("BTN_ADD"))
65 , m_xBtnModify(m_xBuilder
->weld_button("BTN_MODIFY"))
66 , m_xBtnDelete(m_xBuilder
->weld_button("BTN_DELETE"))
67 , m_xBtnLoad(m_xBuilder
->weld_button("BTN_LOAD"))
68 , m_xBtnSave(m_xBuilder
->weld_button("BTN_SAVE"))
69 , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder
, "CTL_PREVIEW", m_aCtlPreview
))
71 // this page needs ExchangeSupport
74 rXLSet
.Put( XLineStyleItem(css::drawing::LineStyle_SOLID
) );
75 rXLSet
.Put( XLineWidthItem(XOUT_WIDTH
) );
76 rXLSet
.Put( XLineColorItem( OUString(), COL_BLACK
) );
77 rXLSet
.Put( XLineStartWidthItem( m_aCtlPreview
.GetOutputSize().Height() / 2 ) );
78 rXLSet
.Put( XLineEndWidthItem( m_aCtlPreview
.GetOutputSize().Height() / 2 ) );
81 m_aCtlPreview
.SetLineAttributes(aXLineAttr
.GetItemSet());
83 m_xBtnAdd
->connect_clicked(LINK(this, SvxLineEndDefTabPage
, ClickAddHdl_Impl
));
84 m_xBtnModify
->connect_clicked(LINK( this, SvxLineEndDefTabPage
, ClickModifyHdl_Impl
));
85 m_xBtnDelete
->connect_clicked(LINK( this, SvxLineEndDefTabPage
, ClickDeleteHdl_Impl
));
86 m_xBtnLoad
->connect_clicked(LINK( this, SvxLineEndDefTabPage
, ClickLoadHdl_Impl
));
87 m_xBtnSave
->connect_clicked(LINK( this, SvxLineEndDefTabPage
, ClickSaveHdl_Impl
));
89 m_xLbLineEnds
->connect_changed(LINK(this, SvxLineEndDefTabPage
, SelectLineEndHdl_Impl
));
92 SvxLineEndDefTabPage::~SvxLineEndDefTabPage()
94 m_xCtlPreview
.reset();
95 m_xLbLineEnds
.reset();
98 void SvxLineEndDefTabPage::Construct()
100 m_xLbLineEnds
->Fill( pLineEndList
);
102 bool bCreateArrowPossible
= true;
106 bCreateArrowPossible
= false;
108 else if( nullptr == dynamic_cast<const SdrPathObj
*>( pPolyObj
) )
110 SdrObjTransformInfoRec aInfoRec
;
111 pPolyObj
->TakeObjInfo( aInfoRec
);
112 SdrObjectUniquePtr pNewObj
;
113 if( aInfoRec
.bCanConvToPath
)
114 pNewObj
= pPolyObj
->ConvertToPolyObj( true, false );
116 bCreateArrowPossible
= nullptr != dynamic_cast<const SdrPathObj
*>( pNewObj
.get());
119 if( !bCreateArrowPossible
)
120 m_xBtnAdd
->set_sensitive(false);
123 void SvxLineEndDefTabPage::ActivatePage( const SfxItemSet
& )
125 if( nDlgType
== 0 ) // area dialog
127 // ActivatePage() is called before the dialog receives PageCreated() !!!
128 if( pLineEndList
.is() )
130 if( *pPosLineEndLb
!= -1)
132 m_xLbLineEnds
->set_active(*pPosLineEndLb
);
133 SelectLineEndHdl_Impl();
135 INetURLObject
aURL( pLineEndList
->GetPath() );
137 aURL
.Append( pLineEndList
->GetName() );
138 DBG_ASSERT( aURL
.GetProtocol() != INetProtocol::NotValid
, "invalid URL" );
139 *pPageType
= PageType::Area
; // 3
146 DeactivateRC
SvxLineEndDefTabPage::DeactivatePage( SfxItemSet
* _pSet
)
151 FillItemSet( _pSet
);
153 return DeactivateRC::LeavePage
;
157 void SvxLineEndDefTabPage::CheckChanges_Impl()
159 int nPos
= m_xLbLineEnds
->get_active();
163 OUString aString
= m_xEdtName
->get_text();
165 if( aString
!= m_xLbLineEnds
->get_active_text() )
167 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querychangelineenddialog.ui"));
168 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("AskChangeLineEndDialog"));
169 if (xQueryBox
->run() == RET_YES
)
170 ClickModifyHdl_Impl(*m_xBtnModify
);
173 nPos
= m_xLbLineEnds
->get_active();
176 *pPosLineEndLb
= nPos
;
180 bool SvxLineEndDefTabPage::FillItemSet( SfxItemSet
* rSet
)
182 if( nDlgType
== 0 ) // line dialog
184 if( *pPageType
== PageType::Bitmap
)
188 int nPos
= m_xLbLineEnds
->get_active();
189 const XLineEndEntry
* pEntry
= pLineEndList
->GetLineEnd(nPos
);
191 rSet
->Put( XLineStartItem( pEntry
->GetName(), pEntry
->GetLineEnd() ) );
192 rSet
->Put( XLineEndItem( pEntry
->GetName(), pEntry
->GetLineEnd() ) );
198 void SvxLineEndDefTabPage::Reset( const SfxItemSet
* )
200 m_xLbLineEnds
->set_active(0);
203 if( pLineEndList
->Count() > 0 )
205 int nPos
= m_xLbLineEnds
->get_active();
207 const XLineEndEntry
* pEntry
= pLineEndList
->GetLineEnd(nPos
);
209 m_xEdtName
->set_text(m_xLbLineEnds
->get_active_text());
211 rXLSet
.Put( XLineStartItem( OUString(), pEntry
->GetLineEnd() ) );
212 rXLSet
.Put( XLineEndItem( OUString(), pEntry
->GetLineEnd() ) );
215 m_aCtlPreview
.SetLineAttributes(aXLineAttr
.GetItemSet());
216 m_aCtlPreview
.Invalidate();
219 // determine button state
220 if( pLineEndList
->Count() )
222 m_xBtnModify
->set_sensitive(true);
223 m_xBtnDelete
->set_sensitive(true);
224 m_xBtnSave
->set_sensitive(true);
228 m_xBtnModify
->set_sensitive(false);
229 m_xBtnDelete
->set_sensitive(false);
230 m_xBtnSave
->set_sensitive(false);
234 std::unique_ptr
<SfxTabPage
> SvxLineEndDefTabPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rSet
)
236 return std::make_unique
<SvxLineEndDefTabPage
>(pPage
, pController
, *rSet
);
239 void SvxLineEndDefTabPage::SelectLineEndHdl_Impl()
241 if( pLineEndList
->Count() > 0 )
243 int nPos
= m_xLbLineEnds
->get_active();
245 const XLineEndEntry
* pEntry
= pLineEndList
->GetLineEnd(nPos
);
247 m_xEdtName
->set_text(m_xLbLineEnds
->get_active_text());
249 rXLSet
.Put( XLineStartItem( OUString(), pEntry
->GetLineEnd() ) );
250 rXLSet
.Put( XLineEndItem( OUString(), pEntry
->GetLineEnd() ) );
253 m_aCtlPreview
.SetLineAttributes(aXLineAttr
.GetItemSet());
254 m_aCtlPreview
.Invalidate();
256 // Is not set before, in order to only take the new style,
257 // if there is an entry selected in the ListBox
258 *pPageType
= PageType::Bitmap
;
262 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, SelectLineEndHdl_Impl
, weld::ComboBox
&, void)
264 SelectLineEndHdl_Impl();
267 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickModifyHdl_Impl
, weld::Button
&, void)
269 int nPos
= m_xLbLineEnds
->get_active();
272 OUString
aDesc(CuiResId(RID_SVXSTR_DESC_LINEEND
));
273 OUString
aName(m_xEdtName
->get_text());
274 long nCount
= pLineEndList
->Count();
275 bool bDifferent
= true;
277 // check whether the name is existing already
278 for ( long i
= 0; i
< nCount
&& bDifferent
; i
++ )
279 if ( aName
== pLineEndList
->GetLineEnd( i
)->GetName() )
282 // if yes, repeat and demand a new name
285 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
286 std::unique_ptr
<weld::MessageDialog
> xWarningBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
289 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
290 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetFrameWeld(), aName
, aDesc
));
293 while( !bDifferent
&& bLoop
&& pDlg
->Execute() == RET_OK
)
295 pDlg
->GetName( aName
);
298 for( long i
= 0; i
< nCount
&& bDifferent
; i
++ )
300 if( aName
== pLineEndList
->GetLineEnd( i
)->GetName() )
311 // if not existing, enter the entry
314 const XLineEndEntry
* pOldEntry
= pLineEndList
->GetLineEnd(nPos
);
318 // #123497# Need to replace the existing entry with a new one
319 pLineEndList
->Replace(std::make_unique
<XLineEndEntry
>(pOldEntry
->GetLineEnd(), aName
), nPos
);
321 m_xEdtName
->set_text(aName
);
323 m_xLbLineEnds
->Modify(*pLineEndList
->GetLineEnd(nPos
), nPos
, pLineEndList
->GetUiBitmap(nPos
));
324 m_xLbLineEnds
->set_active(nPos
);
326 // set flag for modified
327 *pnLineEndListState
|= ChangeType::MODIFIED
;
329 *pPageType
= PageType::Bitmap
;
333 OSL_ENSURE(false, "LineEnd to be modified not existing (!)");
339 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickAddHdl_Impl
, weld::Button
&, void)
343 const SdrObject
* pNewObj
;
344 SdrObjectUniquePtr pConvPolyObj
;
346 if( nullptr != dynamic_cast<const SdrPathObj
*>( pPolyObj
) )
352 SdrObjTransformInfoRec aInfoRec
;
353 pPolyObj
->TakeObjInfo( aInfoRec
);
355 if( aInfoRec
.bCanConvToPath
)
357 pConvPolyObj
= pPolyObj
->ConvertToPolyObj( true, false );
358 pNewObj
= pConvPolyObj
.get();
360 if( !pNewObj
|| nullptr == dynamic_cast<const SdrPathObj
*>( pNewObj
) )
361 return; // cancel, additional safety, which
362 // has no use for group objects though.
364 else return; // cancel
367 basegfx::B2DPolyPolygon
aNewPolyPolygon(static_cast<const SdrPathObj
*>(pNewObj
)->GetPathPoly());
368 basegfx::B2DRange
aNewRange(basegfx::utils::getRange(aNewPolyPolygon
));
371 aNewPolyPolygon
.transform(basegfx::utils::createTranslateB2DHomMatrix( -aNewRange
.getMinX(), -aNewRange
.getMinY()));
373 pConvPolyObj
.reset();
375 OUString
aNewName(SvxResId(RID_SVXSTR_LINEEND
));
376 OUString
aDesc(CuiResId(RID_SVXSTR_DESC_LINEEND
));
379 long nCount
= pLineEndList
->Count();
381 bool bDifferent
= false;
383 while ( !bDifferent
)
385 aName
= aNewName
+ " " + OUString::number( j
++ );
388 for( long i
= 0; i
< nCount
&& bDifferent
; i
++ )
389 if ( aName
== pLineEndList
->GetLineEnd( i
)->GetName() )
393 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
394 ScopedVclPtr
<AbstractSvxNameDialog
> pDlg(pFact
->CreateSvxNameDialog(GetFrameWeld(), aName
, aDesc
));
397 while ( bLoop
&& pDlg
->Execute() == RET_OK
)
399 pDlg
->GetName( aName
);
402 for( long i
= 0; i
< nCount
&& bDifferent
; i
++ )
404 if( aName
== pLineEndList
->GetLineEnd( i
)->GetName() )
412 auto nLineEndCount
= pLineEndList
->Count();
413 pLineEndList
->Insert(std::make_unique
<XLineEndEntry
>(aNewPolyPolygon
, aName
), nLineEndCount
);
415 // add to the ListBox
416 m_xLbLineEnds
->Append(*pLineEndList
->GetLineEnd(nLineEndCount
), pLineEndList
->GetUiBitmap(nLineEndCount
));
417 m_xLbLineEnds
->set_active(m_xLbLineEnds
->get_count() - 1);
419 *pnLineEndListState
|= ChangeType::MODIFIED
;
421 SelectLineEndHdl_Impl();
425 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui"));
426 std::unique_ptr
<weld::MessageDialog
> xWarningBox(xBuilder
->weld_message_dialog("DuplicateNameDialog"));
432 m_xBtnAdd
->set_sensitive(false);
434 // determine button state
435 if ( pLineEndList
->Count() )
437 m_xBtnModify
->set_sensitive(true);
438 m_xBtnDelete
->set_sensitive(true);
439 m_xBtnSave
->set_sensitive(true);
443 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickDeleteHdl_Impl
, weld::Button
&, void)
445 int nPos
= m_xLbLineEnds
->get_active();
449 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletelineenddialog.ui"));
450 std::unique_ptr
<weld::MessageDialog
> xQueryBox(xBuilder
->weld_message_dialog("AskDelLineEndDialog"));
452 if (xQueryBox
->run() == RET_YES
)
454 pLineEndList
->Remove(nPos
);
455 m_xLbLineEnds
->remove(nPos
);
456 m_xLbLineEnds
->set_active(0);
458 SelectLineEndHdl_Impl();
459 *pPageType
= PageType::Area
; // LineEnd shall not be taken over
461 *pnLineEndListState
|= ChangeType::MODIFIED
;
463 m_aCtlPreview
.Invalidate();
466 // determine button state
467 if( !pLineEndList
->Count() )
469 m_xBtnModify
->set_sensitive(false);
470 m_xBtnDelete
->set_sensitive(false);
471 m_xBtnSave
->set_sensitive(false);
475 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickLoadHdl_Impl
, weld::Button
&, void)
477 sal_uInt16 nReturn
= RET_YES
;
479 if ( *pnLineEndListState
& ChangeType::MODIFIED
)
481 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querysavelistdialog.ui"));
482 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("AskSaveList"));
484 nReturn
= xBox
->run();
486 if ( nReturn
== RET_YES
)
487 pLineEndList
->Save();
490 if ( nReturn
!= RET_CANCEL
)
492 ::sfx2::FileDialogHelper
aDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE
,
493 FileDialogFlags::NONE
, GetFrameWeld());
494 OUString
aStrFilterType( "*.soe" );
495 aDlg
.AddFilter( aStrFilterType
, aStrFilterType
);
497 OUString
aPalettePath(SvtPathOptions().GetPalettePath());
499 sal_Int32 nIndex
= 0;
502 aLastDir
= aPalettePath
.getToken(0, ';', nIndex
);
506 INetURLObject
aFile(aLastDir
);
507 aDlg
.SetDisplayDirectory( aFile
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
509 if( aDlg
.Execute() == ERRCODE_NONE
)
511 INetURLObject
aURL( aDlg
.GetPath() );
512 INetURLObject
aPathURL( aURL
);
514 aPathURL
.removeSegment();
515 aPathURL
.removeFinalSlash();
517 XLineEndListRef pLeList
= XPropertyList::AsLineEndList(
518 XPropertyList::CreatePropertyList(
519 XPropertyListType::LineEnd
,
520 aPathURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
), ""));
521 pLeList
->SetName( aURL
.getName() );
522 if( pLeList
->Load() )
524 pLineEndList
= pLeList
;
525 static_cast<SvxLineTabDialog
*>(GetDialogController())->SetNewLineEndList( pLineEndList
);
526 m_xLbLineEnds
->clear();
527 m_xLbLineEnds
->Fill( pLineEndList
);
530 pLineEndList
->SetName( aURL
.getName() );
532 *pnLineEndListState
|= ChangeType::CHANGED
;
533 *pnLineEndListState
&= ~ChangeType::MODIFIED
;
537 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynoloadedfiledialog.ui"));
538 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("NoLoadedFileDialog"));
544 // determine button state
545 if ( pLineEndList
->Count() )
547 m_xBtnModify
->set_sensitive(true);
548 m_xBtnDelete
->set_sensitive(true);
549 m_xBtnSave
->set_sensitive(true);
553 m_xBtnModify
->set_sensitive(false);
554 m_xBtnDelete
->set_sensitive(false);
555 m_xBtnSave
->set_sensitive(false);
559 IMPL_LINK_NOARG(SvxLineEndDefTabPage
, ClickSaveHdl_Impl
, weld::Button
&, void)
561 ::sfx2::FileDialogHelper
aDlg(css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE
, FileDialogFlags::NONE
, GetFrameWeld());
562 OUString
aStrFilterType( "*.soe" );
563 aDlg
.AddFilter( aStrFilterType
, aStrFilterType
);
565 OUString
aPalettePath(SvtPathOptions().GetPalettePath());
567 sal_Int32 nIndex
= 0;
570 aLastDir
= aPalettePath
.getToken(0, ';', nIndex
);
574 INetURLObject
aFile(aLastDir
);
575 DBG_ASSERT( aFile
.GetProtocol() != INetProtocol::NotValid
, "invalid URL" );
577 if( !pLineEndList
->GetName().isEmpty() )
579 aFile
.Append( pLineEndList
->GetName() );
581 if( aFile
.getExtension().isEmpty() )
582 aFile
.SetExtension( "soe" );
585 aDlg
.SetDisplayDirectory( aFile
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
586 if ( aDlg
.Execute() == ERRCODE_NONE
)
588 INetURLObject
aURL( aDlg
.GetPath() );
589 INetURLObject
aPathURL( aURL
);
591 aPathURL
.removeSegment();
592 aPathURL
.removeFinalSlash();
594 pLineEndList
->SetName( aURL
.getName() );
595 pLineEndList
->SetPath( aPathURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
597 if( pLineEndList
->Save() )
599 *pnLineEndListState
&= ~ChangeType::MODIFIED
;
603 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynosavefiledialog.ui"));
604 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("NoSaveFileDialog"));
610 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */