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/debug.hxx>
21 #include <vcl/settings.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/toolbox.hxx>
24 #include <vcl/virdev.hxx>
25 #include <sfx2/objsh.hxx>
27 #include <svtools/toolbarmenu.hxx>
28 #include <svtools/popupwindowcontroller.hxx>
29 #include <svtools/valueset.hxx>
31 #include <svx/strings.hrc>
32 #include <svx/svxids.hrc>
35 #include <svx/drawitem.hxx>
36 #include <svx/xlineit0.hxx>
37 #include <svx/xlndsit.hxx>
38 #include <svx/xlnstit.hxx>
39 #include <svx/xlnedit.hxx>
40 #include <svx/xtable.hxx>
41 #include <svx/linectrl.hxx>
42 #include <svx/itemwin.hxx>
43 #include <svx/dialmgr.hxx>
44 #include <tbxcolorupdate.hxx>
48 #include <comphelper/lok.hxx>
50 using namespace ::com::sun::star::uno
;
51 using namespace ::com::sun::star::beans
;
52 using namespace ::com::sun::star::util
;
53 using namespace ::com::sun::star::frame
;
54 using namespace ::com::sun::star::lang
;
55 using namespace ::com::sun::star
;
57 // For End Line Controller
60 SvxLineStyleToolBoxControl::SvxLineStyleToolBoxControl( const css::uno::Reference
<css::uno::XComponentContext
>& rContext
)
61 : svt::PopupWindowController( rContext
, nullptr, OUString() )
63 addStatusListener(".uno:LineDash");
66 SvxLineStyleToolBoxControl::~SvxLineStyleToolBoxControl()
70 void SAL_CALL
SvxLineStyleToolBoxControl::statusChanged( const frame::FeatureStateEvent
& rEvent
)
72 ToolBox
* pToolBox
= nullptr;
74 if (!getToolboxId(nId
, &pToolBox
) && !m_pToolbar
)
77 OString
sId(m_aCommandURL
.toUtf8());
79 if ( rEvent
.FeatureURL
.Complete
== m_aCommandURL
)
82 m_pToolbar
->set_item_sensitive(sId
, rEvent
.IsEnabled
);
84 pToolBox
->EnableItem( nId
, rEvent
.IsEnabled
);
87 m_xBtnUpdater
->Update(rEvent
);
89 SfxObjectShell
* pSh
= SfxObjectShell::Current();
93 const SvxDashListItem
* pItem
= pSh
->GetItem( SID_DASH_LIST
);
97 XDashListRef xList
= pItem
->GetDashList();
98 int nIndex
= m_xBtnUpdater
->GetStyleIndex();
99 bool bNoneLineStyle
= false;
105 BitmapEx
aEmpty(xList
->GetBitmapForUISolidLine());
106 aEmpty
.Erase(Application::GetSettings().GetStyleSettings().GetFieldColor());
109 Graphic
aGraf(aEmpty
);
110 m_pToolbar
->set_item_image(sId
, aGraf
.GetXGraphic());
113 pToolBox
->SetItemImage(nId
, Image(aEmpty
));
114 bNoneLineStyle
= true;
120 Graphic
aGraf(xList
->GetBitmapForUISolidLine());
121 m_pToolbar
->set_item_image(sId
, aGraf
.GetXGraphic());
124 pToolBox
->SetItemImage(nId
, Image(xList
->GetBitmapForUISolidLine()));
129 Graphic
aGraf(xList
->GetUiBitmap(nIndex
- 2));
130 m_pToolbar
->set_item_image(sId
, aGraf
.GetXGraphic());
133 pToolBox
->SetItemImage(nId
, Image(xList
->GetUiBitmap(nIndex
- 2)));
136 if (m_aLineStyleIsNoneFunction
)
137 m_aLineStyleIsNoneFunction(bNoneLineStyle
);
140 void SAL_CALL
SvxLineStyleToolBoxControl::execute(sal_Int16
/*KeyModifier*/)
144 // Toggle the popup also when toolbutton is activated
145 const OString
aId(m_aCommandURL
.toUtf8());
146 m_pToolbar
->set_menu_item_active(aId
, !m_pToolbar
->get_menu_item_active(aId
));
150 // Open the popup also when Enter key is pressed.
155 void SvxLineStyleToolBoxControl::initialize( const css::uno::Sequence
<css::uno::Any
>& rArguments
)
157 svt::PopupWindowController::initialize( rArguments
);
161 mxPopoverContainer
.reset(new ToolbarPopupContainer(m_pToolbar
));
162 m_pToolbar
->set_item_popover(m_aCommandURL
.toUtf8(), mxPopoverContainer
->getTopLevel());
165 ToolBox
* pToolBox
= nullptr;
167 if ( getToolboxId( nId
, &pToolBox
) )
169 pToolBox
->SetItemBits( nId
, pToolBox
->GetItemBits( nId
) | ToolBoxItemBits::DROPDOWNONLY
);
172 m_xBtnUpdater
.reset(new svx::ToolboxButtonLineStyleUpdater
);
175 void SvxLineStyleToolBoxControl::setLineStyleSelectFunction(const LineStyleSelectFunction
& rLineStyleSelectFunction
)
177 m_aLineStyleSelectFunction
= rLineStyleSelectFunction
;
180 void SvxLineStyleToolBoxControl::setLineStyleIsNoneFunction(const LineStyleIsNoneFunction
& rLineStyleIsNoneFunction
)
182 m_aLineStyleIsNoneFunction
= rLineStyleIsNoneFunction
;
185 void SvxLineStyleToolBoxControl::dispatchLineStyleCommand(const OUString
& rCommand
, const Sequence
<PropertyValue
>& rArgs
)
187 if (m_aLineStyleSelectFunction
&& m_aLineStyleSelectFunction(rCommand
, rArgs
[0].Value
))
190 dispatchCommand(rCommand
, rArgs
);
193 std::unique_ptr
<WeldToolbarPopup
> SvxLineStyleToolBoxControl::weldPopupWindow()
195 return std::make_unique
<SvxLineBox
>(this, m_pToolbar
, m_xBtnUpdater
->GetStyleIndex());
198 VclPtr
<vcl::Window
> SvxLineStyleToolBoxControl::createVclPopupWindow( vcl::Window
* pParent
)
200 mxInterimPopover
= VclPtr
<InterimToolbarPopup
>::Create(getFrameInterface(), pParent
,
201 std::make_unique
<SvxLineBox
>(this, pParent
->GetFrameWeld(), m_xBtnUpdater
->GetStyleIndex()));
203 mxInterimPopover
->Show();
205 return mxInterimPopover
;
208 OUString
SvxLineStyleToolBoxControl::getImplementationName()
210 return "com.sun.star.comp.svx.LineStyleToolBoxControl";
213 css::uno::Sequence
<OUString
> SvxLineStyleToolBoxControl::getSupportedServiceNames()
215 return { "com.sun.star.frame.ToolbarController" };
218 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
219 com_sun_star_comp_svx_LineStyleToolBoxControl_get_implementation(
220 css::uno::XComponentContext
* rContext
,
221 css::uno::Sequence
<css::uno::Any
> const & )
223 return cppu::acquire( new SvxLineStyleToolBoxControl( rContext
) );
228 class SvxLineEndToolBoxControl final
: public svt::PopupWindowController
231 explicit SvxLineEndToolBoxControl( const css::uno::Reference
<css::uno::XComponentContext
>& rContext
);
234 virtual void SAL_CALL
initialize( const css::uno::Sequence
<css::uno::Any
>& rArguments
) override
;
237 virtual OUString SAL_CALL
getImplementationName() override
;
238 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
;
240 virtual void SAL_CALL
execute(sal_Int16 nKeyModifier
) override
;
243 virtual std::unique_ptr
<WeldToolbarPopup
> weldPopupWindow() override
;
244 virtual VclPtr
<vcl::Window
> createVclPopupWindow( vcl::Window
* pParent
) override
;
247 class SvxLineEndWindow final
: public WeldToolbarPopup
250 XLineEndListRef mpLineEndList
;
251 rtl::Reference
<SvxLineEndToolBoxControl
> mxControl
;
252 std::unique_ptr
<ValueSet
> mxLineEndSet
;
253 std::unique_ptr
<weld::CustomWeld
> mxLineEndSetWin
;
257 DECL_LINK( SelectHdl
, ValueSet
*, void );
261 virtual void GrabFocus() override
263 mxLineEndSet
->GrabFocus();
267 SvxLineEndWindow(SvxLineEndToolBoxControl
* pControl
, weld::Widget
* pParent
);
268 virtual void statusChanged( const css::frame::FeatureStateEvent
& rEvent
) override
;
273 constexpr sal_uInt16 gnCols
= 2;
275 SvxLineEndWindow::SvxLineEndWindow(SvxLineEndToolBoxControl
* pControl
, weld::Widget
* pParent
)
276 : WeldToolbarPopup(pControl
->getFrameInterface(), pParent
, "svx/ui/floatinglineend.ui", "FloatingLineEnd")
277 , mxControl(pControl
)
278 , mxLineEndSet(new ValueSet(m_xBuilder
->weld_scrolled_window("valuesetwin", true)))
279 , mxLineEndSetWin(new weld::CustomWeld(*m_xBuilder
, "valueset", *mxLineEndSet
))
282 mxLineEndSet
->SetStyle(mxLineEndSet
->GetStyle() | WB_ITEMBORDER
| WB_3DLOOK
| WB_NO_DIRECTSELECT
);
283 mxLineEndSet
->SetHelpId(HID_POPUP_LINEEND_CTRL
);
284 m_xTopLevel
->set_help_id(HID_POPUP_LINEEND
);
286 SfxObjectShell
* pDocSh
= SfxObjectShell::Current();
289 const SfxPoolItem
* pItem
= pDocSh
->GetItem( SID_LINEEND_LIST
);
291 mpLineEndList
= static_cast<const SvxLineEndListItem
*>( pItem
)->GetLineEndList();
293 DBG_ASSERT( mpLineEndList
.is(), "LineEndList not found" );
295 mxLineEndSet
->SetSelectHdl( LINK( this, SvxLineEndWindow
, SelectHdl
) );
296 mxLineEndSet
->SetColCount( gnCols
);
298 // ValueSet fill with entries of LineEndList
301 AddStatusListener( ".uno:LineEndListState");
304 IMPL_LINK_NOARG(SvxLineEndWindow
, SelectHdl
, ValueSet
*, void)
306 std::unique_ptr
<XLineEndItem
> pLineEndItem
;
307 std::unique_ptr
<XLineStartItem
> pLineStartItem
;
308 sal_uInt16 nId
= mxLineEndSet
->GetSelectedItemId();
312 pLineStartItem
.reset(new XLineStartItem());
316 pLineEndItem
.reset(new XLineEndItem());
318 else if( nId
% 2 ) // beginning of line
320 const XLineEndEntry
* pEntry
= mpLineEndList
->GetLineEnd( (nId
- 1) / 2 - 1 );
321 pLineStartItem
.reset(new XLineStartItem(pEntry
->GetName(), pEntry
->GetLineEnd()));
325 const XLineEndEntry
* pEntry
= mpLineEndList
->GetLineEnd( nId
/ 2 - 2 );
326 pLineEndItem
.reset(new XLineEndItem(pEntry
->GetName(), pEntry
->GetLineEnd()));
329 Sequence
< PropertyValue
> aArgs( 1 );
332 if ( pLineStartItem
)
334 aArgs
[0].Name
= "LineStart";
335 pLineStartItem
->QueryValue( a
);
340 aArgs
[0].Name
= "LineEnd";
341 pLineEndItem
->QueryValue( a
);
345 /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call.
346 This instance may be deleted in the meantime (i.e. when a dialog is opened
347 while in Dispatch()), accessing members will crash in this case. */
348 mxLineEndSet
->SetNoSelection();
350 mxControl
->dispatchCommand(mxControl
->getCommandURL(), aArgs
);
352 mxControl
->EndPopupMode();
355 void SvxLineEndWindow::FillValueSet()
357 if( !mpLineEndList
.is() )
360 ScopedVclPtrInstance
< VirtualDevice
> pVD
;
362 tools::Long nCount
= mpLineEndList
->Count();
364 // First entry: no line end.
365 // An entry is temporarily added to get the UI bitmap
366 basegfx::B2DPolyPolygon aNothing
;
367 mpLineEndList
->Insert(std::make_unique
<XLineEndEntry
>(aNothing
,
368 comphelper::LibreOfficeKit::isActive() ? SvxResId(RID_SVXSTR_INVISIBLE
)
369 : SvxResId(RID_SVXSTR_NONE
)));
370 const XLineEndEntry
* pEntry
= mpLineEndList
->GetLineEnd(nCount
);
371 BitmapEx aBmp
= mpLineEndList
->GetUiBitmap( nCount
);
372 OSL_ENSURE( !aBmp
.IsEmpty(), "UI bitmap was not created" );
374 maBmpSize
= aBmp
.GetSizePixel();
375 pVD
->SetOutputSizePixel( maBmpSize
, false );
376 maBmpSize
.setWidth( maBmpSize
.Width() / 2 );
378 Point
aPt1( maBmpSize
.Width(), 0 );
380 pVD
->DrawBitmapEx( Point(), aBmp
);
381 mxLineEndSet
->InsertItem(1, Image(pVD
->GetBitmapEx(aPt0
, maBmpSize
)), pEntry
->GetName());
382 mxLineEndSet
->InsertItem(2, Image(pVD
->GetBitmapEx(aPt1
, maBmpSize
)), pEntry
->GetName());
384 mpLineEndList
->Remove(nCount
);
386 for( tools::Long i
= 0; i
< nCount
; i
++ )
388 pEntry
= mpLineEndList
->GetLineEnd( i
);
389 DBG_ASSERT( pEntry
, "Could not access LineEndEntry" );
390 aBmp
= mpLineEndList
->GetUiBitmap( i
);
391 OSL_ENSURE( !aBmp
.IsEmpty(), "UI bitmap was not created" );
393 pVD
->DrawBitmapEx( aPt0
, aBmp
);
394 mxLineEndSet
->InsertItem(static_cast<sal_uInt16
>((i
+1)*2L+1),
395 Image(pVD
->GetBitmapEx(aPt0
, maBmpSize
)), pEntry
->GetName());
396 mxLineEndSet
->InsertItem(static_cast<sal_uInt16
>((i
+2)*2L),
397 Image(pVD
->GetBitmapEx(aPt1
, maBmpSize
)), pEntry
->GetName());
399 mnLines
= std::min( static_cast<sal_uInt16
>(nCount
+ 1), sal_uInt16(MAX_LINES
) );
400 mxLineEndSet
->SetLineCount( mnLines
);
405 void SvxLineEndWindow::statusChanged( const css::frame::FeatureStateEvent
& rEvent
)
407 if ( rEvent
.FeatureURL
.Complete
!= ".uno:LineEndListState" )
410 // The list of line ends (LineEndList) has changed
411 css::uno::Reference
< css::uno::XWeak
> xWeak
;
412 if ( rEvent
.State
>>= xWeak
)
414 mpLineEndList
.set( static_cast< XLineEndList
* >( xWeak
.get() ) );
415 DBG_ASSERT( mpLineEndList
.is(), "LineEndList not found" );
417 mxLineEndSet
->Clear();
422 void SvxLineEndWindow::SetSize()
424 sal_uInt16 nItemCount
= mxLineEndSet
->GetItemCount();
425 sal_uInt16 nMaxLines
= nItemCount
/ gnCols
;
427 WinBits nBits
= mxLineEndSet
->GetStyle();
428 if ( mnLines
== nMaxLines
)
429 nBits
&= ~WB_VSCROLL
;
432 mxLineEndSet
->SetStyle( nBits
);
434 Size
aSize( maBmpSize
);
435 aSize
.AdjustWidth(6 );
436 aSize
.AdjustHeight(6 );
437 aSize
= mxLineEndSet
->CalcWindowSizePixel( aSize
);
438 mxLineEndSet
->GetDrawingArea()->set_size_request(aSize
.Width(), aSize
.Height());
439 mxLineEndSet
->SetOutputSizePixel(aSize
);
442 SvxLineEndToolBoxControl::SvxLineEndToolBoxControl( const css::uno::Reference
<css::uno::XComponentContext
>& rContext
)
443 : svt::PopupWindowController( rContext
, nullptr, OUString() )
447 void SAL_CALL
SvxLineEndToolBoxControl::execute(sal_Int16
/*KeyModifier*/)
451 // Toggle the popup also when toolbutton is activated
452 const OString
aId(m_aCommandURL
.toUtf8());
453 m_pToolbar
->set_menu_item_active(aId
, !m_pToolbar
->get_menu_item_active(aId
));
457 // Open the popup also when Enter key is pressed.
462 void SvxLineEndToolBoxControl::initialize( const css::uno::Sequence
<css::uno::Any
>& rArguments
)
464 svt::PopupWindowController::initialize( rArguments
);
468 mxPopoverContainer
.reset(new ToolbarPopupContainer(m_pToolbar
));
469 m_pToolbar
->set_item_popover(m_aCommandURL
.toUtf8(), mxPopoverContainer
->getTopLevel());
472 ToolBox
* pToolBox
= nullptr;
474 if ( getToolboxId( nId
, &pToolBox
) )
475 pToolBox
->SetItemBits( nId
, pToolBox
->GetItemBits( nId
) | ToolBoxItemBits::DROPDOWNONLY
);
478 std::unique_ptr
<WeldToolbarPopup
> SvxLineEndToolBoxControl::weldPopupWindow()
480 return std::make_unique
<SvxLineEndWindow
>(this, m_pToolbar
);
483 VclPtr
<vcl::Window
> SvxLineEndToolBoxControl::createVclPopupWindow( vcl::Window
* pParent
)
485 mxInterimPopover
= VclPtr
<InterimToolbarPopup
>::Create(getFrameInterface(), pParent
,
486 std::make_unique
<SvxLineEndWindow
>(this, pParent
->GetFrameWeld()));
488 mxInterimPopover
->Show();
490 mxInterimPopover
->SetText(SvxResId(RID_SVXSTR_LINEEND
));
492 return mxInterimPopover
;
495 OUString
SvxLineEndToolBoxControl::getImplementationName()
497 return "com.sun.star.comp.svx.LineEndToolBoxControl";
500 css::uno::Sequence
<OUString
> SvxLineEndToolBoxControl::getSupportedServiceNames()
502 return { "com.sun.star.frame.ToolbarController" };
505 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
506 com_sun_star_comp_svx_LineEndToolBoxControl_get_implementation(
507 css::uno::XComponentContext
* rContext
,
508 css::uno::Sequence
<css::uno::Any
> const & )
510 return cppu::acquire( new SvxLineEndToolBoxControl( rContext
) );
513 SvxLineBox::SvxLineBox(SvxLineStyleToolBoxControl
* pControl
, weld::Widget
* pParent
, int nInitialIndex
)
514 : WeldToolbarPopup(pControl
->getFrameInterface(), pParent
, "svx/ui/floatinglinestyle.ui", "FloatingLineStyle")
515 , mxControl(pControl
)
516 , mxLineStyleSet(new ValueSet(m_xBuilder
->weld_scrolled_window("valuesetwin", true)))
517 , mxLineStyleSetWin(new weld::CustomWeld(*m_xBuilder
, "valueset", *mxLineStyleSet
))
519 mxLineStyleSet
->SetStyle(WB_FLATVALUESET
| WB_ITEMBORDER
| WB_3DLOOK
| WB_NO_DIRECTSELECT
);
523 mxLineStyleSet
->SelectItem(nInitialIndex
+ 1);
525 mxLineStyleSet
->SetSelectHdl( LINK( this, SvxLineBox
, SelectHdl
) );
528 void SvxLineBox::GrabFocus()
530 mxLineStyleSet
->GrabFocus();
533 SvxLineBox::~SvxLineBox()
537 // Fills the listbox (provisional) with strings
539 void SvxLineBox::Fill( const XDashListRef
&pList
)
541 mxLineStyleSet
->Clear();
547 mxLineStyleSet
->InsertItem(1, Image(), pList
->GetStringForUiNoLine());
549 // entry for solid line
550 auto aBmp
= pList
->GetBitmapForUISolidLine();
551 Size aBmpSize
= aBmp
.GetSizePixel();
552 mxLineStyleSet
->InsertItem(2, Image(aBmp
), pList
->GetStringForUiSolidLine());
554 // entries for dashed lines
555 tools::Long nCount
= pList
->Count();
556 for( tools::Long i
= 0; i
< nCount
; i
++ )
558 const XDashEntry
* pEntry
= pList
->GetDash(i
);
559 const BitmapEx aBitmap
= pList
->GetUiBitmap(i
);
561 mxLineStyleSet
->InsertItem(i
+ 3, Image(aBitmap
), pEntry
->GetName());
564 sal_uInt16 nLines
= std::min( static_cast<sal_uInt16
>(nCount
+ 2), sal_uInt16(MAX_LINES
) );
565 mxLineStyleSet
->SetLineCount(nLines
);
567 WinBits nBits
= mxLineStyleSet
->GetStyle();
568 if ( nLines
== mxLineStyleSet
->GetItemCount() )
569 nBits
&= ~WB_VSCROLL
;
572 mxLineStyleSet
->SetStyle( nBits
);
574 Size
aSize(aBmpSize
);
575 aSize
.AdjustWidth(6);
576 aSize
.AdjustHeight(6);
577 aSize
= mxLineStyleSet
->CalcWindowSizePixel(aSize
);
578 mxLineStyleSet
->GetDrawingArea()->set_size_request(aSize
.Width(), aSize
.Height());
579 mxLineStyleSet
->SetOutputSizePixel(aSize
);
582 IMPL_LINK_NOARG(SvxLineBox
, SelectHdl
, ValueSet
*, void)
584 drawing::LineStyle eXLS
;
585 sal_Int32 nPos
= mxLineStyleSet
->GetSelectedItemId();
586 --nPos
; // ids start at 1, get the pos of the id
591 eXLS
= drawing::LineStyle_NONE
;
595 eXLS
= drawing::LineStyle_SOLID
;
600 eXLS
= drawing::LineStyle_DASH
;
603 SfxObjectShell::Current() &&
604 SfxObjectShell::Current()->GetItem( SID_DASH_LIST
) )
606 // LineDashItem will only be sent if it also has a dash.
608 SvxDashListItem
const * pItem
= SfxObjectShell::Current()->GetItem( SID_DASH_LIST
);
609 const XDashEntry
* pEntry
= pItem
->GetDashList()->GetDash(nPos
- 2);
610 XLineDashItem
aLineDashItem(pEntry
->GetName(), pEntry
->GetDash());
613 Sequence
< PropertyValue
> aArgs( 1 );
614 aArgs
[0].Name
= "LineDash";
615 aLineDashItem
.QueryValue ( a
);
617 mxControl
->dispatchLineStyleCommand(".uno:LineDash", aArgs
);
623 XLineStyleItem
aLineStyleItem( eXLS
);
625 Sequence
< PropertyValue
> aArgs( 1 );
626 aArgs
[0].Name
= "XLineStyle";
627 aLineStyleItem
.QueryValue ( a
);
629 mxControl
->dispatchLineStyleCommand(".uno:XLineStyle", aArgs
);
631 mxControl
->EndPopupMode();
634 void SvxLineBox::FillControl()
636 SfxObjectShell
* pSh
= SfxObjectShell::Current();
639 const SvxDashListItem
* pItem
= pSh
->GetItem( SID_DASH_LIST
);
641 Fill(pItem
->GetDashList());
645 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */