1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 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/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 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 . 18 */ 19 20 #include <utility> 21 22 #include <comphelper/configurationlistener.hxx> 23 #include <comphelper/propertysequence.hxx> 24 #include <comphelper/propertyvalue.hxx> 25 #include <tools/color.hxx> 26 #include <svl/numformat.hxx> 27 #include <svl/poolitem.hxx> 28 #include <svl/itemset.hxx> 29 #include <vcl/commandinfoprovider.hxx> 30 #include <vcl/event.hxx> 31 #include <vcl/toolbox.hxx> 32 #include <vcl/customweld.hxx> 33 #include <vcl/vclptr.hxx> 34 #include <vcl/weldutils.hxx> 35 #include <svtools/valueset.hxx> 36 #include <svtools/ctrlbox.hxx> 37 #include <svl/style.hxx> 38 #include <svtools/ctrltool.hxx> 39 #include <svtools/borderhelper.hxx> 40 #include <vcl/InterimItemWindow.hxx> 41 #include <sfx2/tbxctrl.hxx> 42 #include <sfx2/tplpitem.hxx> 43 #include <sfx2/sfxstatuslistener.hxx> 44 #include <toolkit/helper/vclunohelper.hxx> 45 #include <sfx2/viewfrm.hxx> 46 #include <vcl/svapp.hxx> 47 #include <vcl/settings.hxx> 48 #include <vcl/virdev.hxx> 49 #include <com/sun/star/awt/FontDescriptor.hpp> 50 #include <com/sun/star/table/BorderLine2.hpp> 51 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> 52 #include <com/sun/star/lang/XServiceInfo.hpp> 53 #include <com/sun/star/beans/XPropertySet.hpp> 54 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 55 #include <com/sun/star/frame/XDispatchProvider.hpp> 56 #include <com/sun/star/frame/XFrame.hpp> 57 #include <svx/strings.hrc> 58 #include <svx/svxids.hrc> 59 #include <helpids.h> 60 #include <sfx2/sidebar/Sidebar.hxx> 61 #include <svx/xtable.hxx> 62 #include <editeng/editids.hrc> 63 #include <editeng/fontitem.hxx> 64 #include <editeng/fhgtitem.hxx> 65 #include <editeng/boxitem.hxx> 66 #include <editeng/charreliefitem.hxx> 67 #include <editeng/contouritem.hxx> 68 #include <editeng/colritem.hxx> 69 #include <editeng/crossedoutitem.hxx> 70 #include <editeng/emphasismarkitem.hxx> 71 #include <editeng/flstitem.hxx> 72 #include <editeng/lineitem.hxx> 73 #include <editeng/postitem.hxx> 74 #include <editeng/shdditem.hxx> 75 #include <editeng/udlnitem.hxx> 76 #include <editeng/wghtitem.hxx> 77 #include <editeng/svxfont.hxx> 78 #include <editeng/cmapitem.hxx> 79 #include <svx/colorwindow.hxx> 80 #include <svx/colorbox.hxx> 81 #include <svx/tbcontrl.hxx> 82 #include <svx/dialmgr.hxx> 83 #include <svx/PaletteManager.hxx> 84 #include <memory> 85 86 #include <tbxcolorupdate.hxx> 87 #include <editeng/eerdll.hxx> 88 #include <editeng/editrids.hrc> 89 #include <svx/xdef.hxx> 90 #include <svx/xfillit0.hxx> 91 #include <svx/xflclit.hxx> 92 #include <svl/currencytable.hxx> 93 #include <svtools/langtab.hxx> 94 #include <cppu/unotype.hxx> 95 #include <cppuhelper/supportsservice.hxx> 96 #include <officecfg/Office/Common.hxx> 97 #include <o3tl/safeint.hxx> 98 #include <o3tl/typed_flags_set.hxx> 99 #include <bitmaps.hlst> 100 #include <sal/log.hxx> 101 #include <unotools/collatorwrapper.hxx> 102 103 #include <comphelper/lok.hxx> 104 #include <tools/json_writer.hxx> 105 106 #define MAX_MRU_FONTNAME_ENTRIES 5 107 108 #define COMBO_WIDTH_IN_CHARS 18 109 110 // namespaces 111 using namespace ::editeng; 112 using namespace ::com::sun::star; 113 using namespace ::com::sun::star::uno; 114 using namespace ::com::sun::star::frame; 115 using namespace ::com::sun::star::beans; 116 using namespace ::com::sun::star::lang; 117 118 namespace 119 { 120 class SvxStyleBox_Base 121 { 122 public: 123 SvxStyleBox_Base(std::unique_ptr<weld::ComboBox> xWidget, const OUString& rCommand, SfxStyleFamily eFamily, 124 const Reference<XDispatchProvider>& rDispatchProvider, 125 const Reference<XFrame>& _xFrame,const OUString& rClearFormatKey, 126 const OUString& rMoreKey, bool bInSpecialMode, SvxStyleToolBoxControl& rCtrl); 127 128 virtual ~SvxStyleBox_Base() 129 { 130 } 131 132 void SetFamily( SfxStyleFamily eNewFamily ); 133 134 void SetDefaultStyle( const OUString& rDefault ) { sDefaultStyle = rDefault; } 135 136 int get_count() const { return m_xWidget->get_count(); } 137 OUString get_text(int nIndex) const { return m_xWidget->get_text(nIndex); } 138 OUString get_active_text() const { return m_xWidget->get_active_text(); } 139 140 void append_text(const OUString& rStr) 141 { 142 OUString sId(OUString::number(m_xWidget->get_count())); 143 m_xWidget->append(sId, rStr); 144 } 145 146 void insert_separator(int pos, const OUString& rId) 147 { 148 m_xWidget->insert_separator(pos, rId); 149 } 150 151 void set_active_or_entry_text(const OUString& rText) 152 { 153 const int nFound = m_xWidget->find_text(rText); 154 if (nFound != -1) 155 m_xWidget->set_active(nFound); 156 else 157 m_xWidget->set_entry_text(rText); 158 } 159 160 void set_active(int nActive) 161 { 162 m_xWidget->set_active(nActive); 163 } 164 165 void freeze() 166 { 167 m_xWidget->freeze(); 168 } 169 170 void save_value() 171 { 172 m_xWidget->save_value(); 173 } 174 175 void clear() 176 { 177 m_xWidget->clear(); 178 m_nMaxUserDrawFontWidth = 0; 179 } 180 181 void thaw() 182 { 183 m_xWidget->thaw(); 184 } 185 186 virtual bool DoKeyInput(const KeyEvent& rKEvt); 187 188 private: 189 DECL_LINK(SelectHdl, weld::ComboBox&, void); 190 DECL_LINK(KeyInputHdl, const KeyEvent&, bool); 191 DECL_LINK(ActivateHdl, weld::ComboBox&, bool); 192 DECL_LINK(FocusOutHdl, weld::Widget&, void); 193 DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void); 194 DECL_LINK(CustomRenderHdl, weld::ComboBox::render_args, void); 195 DECL_LINK(CustomGetSizeHdl, OutputDevice&, Size); 196 197 /// Calculate the optimal width of the dropdown. Very expensive operation, triggers lots of font measurement. 198 void CalcOptimalExtraUserWidth(vcl::RenderContext& rRenderContext); 199 200 void Select(bool bNonTravelSelect); 201 202 protected: 203 SvxStyleToolBoxControl& m_rCtrl; 204 205 std::unique_ptr<weld::Builder> m_xMenuBuilder; 206 std::unique_ptr<weld::Menu> m_xMenu; 207 std::unique_ptr<weld::ComboBox> m_xWidget; 208 209 SfxStyleFamily eStyleFamily; 210 int m_nMaxUserDrawFontWidth; 211 int m_nLastItemWithMenu; 212 bool bRelease; 213 Reference< XDispatchProvider > m_xDispatchProvider; 214 Reference< XFrame > m_xFrame; 215 OUString m_aCommand; 216 OUString aClearFormatKey; 217 OUString aMoreKey; 218 OUString sDefaultStyle; 219 bool bInSpecialMode; 220 221 void ReleaseFocus(); 222 static Color TestColorsVisible(const Color &FontCol, const Color &BackCol); 223 static void UserDrawEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const OUString &rStyleName); 224 void SetupEntry(vcl::RenderContext& rRenderContext, sal_Int32 nItem, const tools::Rectangle& rRect, std::u16string_view rStyleName, bool bIsNotSelected); 225 static bool AdjustFontForItemHeight(OutputDevice& rDevice, tools::Rectangle const & rTextRect, tools::Long nHeight); 226 DECL_LINK(MenuSelectHdl, const OString&, void); 227 DECL_STATIC_LINK(SvxStyleBox_Base, ShowMoreHdl, void*, void); 228 }; 229 230 class SvxStyleBox_Impl final : public InterimItemWindow 231 , public SvxStyleBox_Base 232 { 233 public: 234 SvxStyleBox_Impl(vcl::Window* pParent, const OUString& rCommand, SfxStyleFamily eFamily, const Reference< XDispatchProvider >& rDispatchProvider, 235 const Reference< XFrame >& _xFrame,const OUString& rClearFormatKey, const OUString& rMoreKey, bool bInSpecialMode, SvxStyleToolBoxControl& rCtrl); 236 237 virtual ~SvxStyleBox_Impl() override 238 { 239 disposeOnce(); 240 } 241 242 virtual void dispose() override 243 { 244 m_xWidget.reset(); 245 m_xMenu.reset(); 246 m_xMenuBuilder.reset(); 247 InterimItemWindow::dispose(); 248 } 249 250 virtual bool DoKeyInput(const KeyEvent& rKEvt) override; 251 252 private: 253 254 virtual void DataChanged(const DataChangedEvent& rDCEvt) override; 255 void SetOptimalSize(); 256 }; 257 258 class SvxFontNameBox_Impl; 259 class SvxFontNameBox_Base; 260 261 class SvxFontNameToolBoxControl final : public cppu::ImplInheritanceHelper<svt::ToolboxController, 262 css::lang::XServiceInfo> 263 { 264 public: 265 SvxFontNameToolBoxControl(); 266 267 // XStatusListener 268 virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; 269 270 // XToolbarController 271 virtual css::uno::Reference<css::awt::XWindow> SAL_CALL createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) override; 272 273 // XComponent 274 virtual void SAL_CALL dispose() override; 275 276 // XServiceInfo 277 virtual OUString SAL_CALL getImplementationName() override; 278 virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override; 279 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; 280 281 private: 282 VclPtr<SvxFontNameBox_Impl> m_xVclBox; 283 std::unique_ptr<SvxFontNameBox_Base> m_xWeldBox; 284 SvxFontNameBox_Base* m_pBox; 285 }; 286 287 class FontOptionsListener final : public comphelper::ConfigurationListenerProperty<bool> 288 { 289 private: 290 SvxFontNameBox_Base& m_rBox; 291 292 virtual void setProperty(const css::uno::Any &rProperty) override; 293 public: 294 FontOptionsListener(const rtl::Reference<comphelper::ConfigurationListener>& rListener, const OUString& rProp, SvxFontNameBox_Base& rBox) 295 : comphelper::ConfigurationListenerProperty<bool>(rListener, rProp) 296 , m_rBox(rBox) 297 { 298 } 299 }; 300 301 class SvxFontNameBox_Base 302 { 303 private: 304 rtl::Reference<comphelper::ConfigurationListener> m_xListener; 305 FontOptionsListener m_aWYSIWYG; 306 FontOptionsListener m_aHistory; 307 308 protected: 309 SvxFontNameToolBoxControl& m_rCtrl; 310 311 std::unique_ptr<FontNameBox> m_xWidget; 312 const FontList* pFontList; 313 ::std::unique_ptr<FontList> m_aOwnFontList; 314 vcl::Font aCurFont; 315 sal_uInt16 nFtCount; 316 bool bRelease; 317 Reference< XDispatchProvider > m_xDispatchProvider; 318 Reference< XFrame > m_xFrame; 319 bool mbCheckingUnknownFont; 320 321 void ReleaseFocus_Impl(); 322 323 void Select(bool bNonTravelSelect); 324 325 void EndPreview() 326 { 327 Sequence< PropertyValue > aArgs; 328 SfxToolBoxControl::Dispatch( m_xDispatchProvider, 329 ".uno:CharEndPreviewFontName", 330 aArgs ); 331 } 332 void CheckAndMarkUnknownFont(); 333 334 public: 335 SvxFontNameBox_Base(std::unique_ptr<weld::ComboBox> xWidget, const Reference<XDispatchProvider>& rDispatchProvider, 336 const Reference<XFrame>& rFrame, SvxFontNameToolBoxControl& rCtrl); 337 virtual ~SvxFontNameBox_Base() 338 { 339 m_xListener->dispose(); 340 } 341 342 void FillList(); 343 void Update( const css::awt::FontDescriptor* pFontDesc ); 344 sal_uInt16 GetListCount() const { return nFtCount; } 345 void Clear() { m_xWidget->clear(); nFtCount = 0; } 346 void Fill( const FontList* pList ) 347 { 348 m_xWidget->Fill(pList); 349 nFtCount = pList->GetFontNameCount(); 350 } 351 352 void SetOwnFontList(::std::unique_ptr<FontList> && _aOwnFontList) { m_aOwnFontList = std::move(_aOwnFontList); } 353 354 virtual void set_sensitive(bool bSensitive) 355 { 356 m_xWidget->set_sensitive(bSensitive); 357 } 358 359 void set_active_or_entry_text(const OUString& rText); 360 361 void statusChanged_Impl(const css::frame::FeatureStateEvent& rEvent); 362 363 virtual bool DoKeyInput(const KeyEvent& rKEvt); 364 365 void EnableControls(); 366 367 DECL_LINK(SelectHdl, weld::ComboBox&, void); 368 DECL_LINK(KeyInputHdl, const KeyEvent&, bool); 369 DECL_LINK(ActivateHdl, weld::ComboBox&, bool); 370 DECL_LINK(FocusInHdl, weld::Widget&, void); 371 DECL_LINK(FocusOutHdl, weld::Widget&, void); 372 DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void); 373 }; 374 375 void FontOptionsListener::setProperty(const css::uno::Any &rProperty) 376 { 377 comphelper::ConfigurationListenerProperty<bool>::setProperty(rProperty); 378 m_rBox.EnableControls(); 379 } 380 381 class SvxFontNameBox_Impl final : public InterimItemWindow 382 , public SvxFontNameBox_Base 383 { 384 private: 385 virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; 386 virtual void GetFocus() override 387 { 388 if (m_xWidget) 389 m_xWidget->grab_focus(); 390 InterimItemWindow::GetFocus(); 391 } 392 393 void SetOptimalSize(); 394 395 virtual bool DoKeyInput(const KeyEvent& rKEvt) override; 396 397 public: 398 SvxFontNameBox_Impl(vcl::Window* pParent, const Reference<XDispatchProvider>& rDispatchProvider, 399 const Reference<XFrame>& rFrame, SvxFontNameToolBoxControl& rCtrl); 400 401 virtual void dispose() override 402 { 403 m_xWidget.reset(); 404 InterimItemWindow::dispose(); 405 } 406 407 virtual ~SvxFontNameBox_Impl() override 408 { 409 disposeOnce(); 410 } 411 412 virtual Reference< css::accessibility::XAccessible > CreateAccessible() override; 413 414 virtual void set_sensitive(bool bSensitive) override 415 { 416 m_xWidget->set_sensitive(bSensitive); 417 if (bSensitive) 418 InterimItemWindow::Enable(); 419 else 420 InterimItemWindow::Disable(); 421 } 422 }; 423 424 425 // SelectHdl needs the Modifiers, get them in MouseButtonUp 426 class SvxFrmValueSet_Impl final : public ValueSet 427 { 428 private: 429 sal_uInt16 nModifier; 430 431 virtual bool MouseButtonUp(const MouseEvent& rMEvt) override 432 { 433 nModifier = rMEvt.GetModifier(); 434 return ValueSet::MouseButtonUp(rMEvt); 435 } 436 437 public: 438 SvxFrmValueSet_Impl() 439 : ValueSet(nullptr) 440 , nModifier(0) 441 { 442 } 443 sal_uInt16 GetModifier() const {return nModifier;} 444 }; 445 446 } 447 448 namespace { 449 450 class SvxFrameToolBoxControl; 451 452 class SvxFrameWindow_Impl final : public WeldToolbarPopup 453 { 454 private: 455 rtl::Reference<SvxFrameToolBoxControl> mxControl; 456 std::unique_ptr<SvxFrmValueSet_Impl> mxFrameSet; 457 std::unique_ptr<weld::CustomWeld> mxFrameSetWin; 458 std::vector<std::pair<BitmapEx, OUString>> aImgVec; 459 bool bParagraphMode; 460 bool m_bIsWriter; 461 462 void InitImageList(); 463 void CalcSizeValueSet(); 464 DECL_LINK( SelectHdl, ValueSet*, void ); 465 466 void SetDiagonalDownBorder(const SvxLineItem& dDownLineItem); 467 void SetDiagonalUpBorder(const SvxLineItem& dUpLineItem); 468 469 public: 470 SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent); 471 virtual void GrabFocus() override 472 { 473 mxFrameSet->GrabFocus(); 474 } 475 476 virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; 477 }; 478 479 class SvxFrameToolBoxControl : public svt::PopupWindowController 480 { 481 public: 482 explicit SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext ); 483 484 // XInitialization 485 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) override; 486 487 // XServiceInfo 488 virtual OUString SAL_CALL getImplementationName() override; 489 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; 490 491 virtual void SAL_CALL execute(sal_Int16 nKeyModifier) override; 492 private: 493 virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; 494 virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; 495 }; 496 497 class LineListBox final : public ValueSet 498 { 499 public: 500 typedef Color (*ColorFunc)(Color); 501 typedef Color (*ColorDistFunc)(Color, Color); 502 503 LineListBox(); 504 505 /** Set the width in Twips */ 506 Size SetWidth( tools::Long nWidth ) 507 { 508 tools::Long nOldWidth = m_nWidth; 509 m_nWidth = nWidth; 510 return UpdateEntries( nOldWidth ); 511 } 512 513 void SetNone( const OUString& sNone ) 514 { 515 m_sNone = sNone; 516 } 517 518 /** Insert a listbox entry with all widths in Twips. */ 519 void InsertEntry(const BorderWidthImpl& rWidthImpl, 520 SvxBorderLineStyle nStyle, tools::Long nMinWidth = 0, 521 ColorFunc pColor1Fn = &sameColor, 522 ColorFunc pColor2Fn = &sameColor, 523 ColorDistFunc pColorDistFn = &sameDistColor); 524 525 SvxBorderLineStyle GetEntryStyle( sal_Int32 nPos ) const; 526 527 SvxBorderLineStyle GetSelectEntryStyle() const; 528 529 void SetSourceUnit( FieldUnit eNewUnit ) { eSourceUnit = eNewUnit; } 530 531 const Color& GetColor() const { return aColor; } 532 533 virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; 534 private: 535 536 void ImpGetLine(tools::Long nLine1, tools::Long nLine2, tools::Long nDistance, 537 Color nColor1, Color nColor2, Color nColorDist, 538 SvxBorderLineStyle nStyle, BitmapEx& rBmp); 539 540 void UpdatePaintLineColor(); // returns sal_True if maPaintCol has changed 541 542 Size UpdateEntries( tools::Long nOldWidth ); 543 sal_Int32 GetStylePos( sal_Int32 nListPos, tools::Long nWidth ); 544 545 const Color& GetPaintColor() const 546 { 547 return maPaintCol; 548 } 549 550 Color GetColorLine1( sal_Int32 nPos ); 551 Color GetColorLine2( sal_Int32 nPos ); 552 Color GetColorDist( sal_Int32 nPos ); 553 554 LineListBox( const LineListBox& ) = delete; 555 LineListBox& operator =( const LineListBox& ) = delete; 556 557 std::vector<std::unique_ptr<ImpLineListData>> m_vLineList; 558 tools::Long m_nWidth; 559 OUString m_sNone; 560 ScopedVclPtr<VirtualDevice> aVirDev; 561 Size aTxtSize; 562 Color const aColor; 563 Color maPaintCol; 564 FieldUnit eSourceUnit; 565 }; 566 567 SvxBorderLineStyle LineListBox::GetSelectEntryStyle() const 568 { 569 SvxBorderLineStyle nStyle = SvxBorderLineStyle::SOLID; 570 size_t nPos = GetSelectItemPos(); 571 if (nPos != VALUESET_ITEM_NOTFOUND) 572 { 573 if (!m_sNone.isEmpty()) 574 --nPos; 575 nStyle = GetEntryStyle( nPos ); 576 } 577 578 return nStyle; 579 } 580 581 void LineListBox::ImpGetLine( tools::Long nLine1, tools::Long nLine2, tools::Long nDistance, 582 Color aColor1, Color aColor2, Color aColorDist, 583 SvxBorderLineStyle nStyle, BitmapEx& rBmp ) 584 { 585 auto nMinWidth = GetDrawingArea()->get_ref_device().approximate_digit_width() * COMBO_WIDTH_IN_CHARS; 586 Size aSize(nMinWidth, aTxtSize.Height()); 587 aSize.AdjustWidth( -(aTxtSize.Width()) ); 588 aSize.AdjustWidth( -6 ); 589 590 // SourceUnit to Twips 591 if ( eSourceUnit == FieldUnit::POINT ) 592 { 593 nLine1 /= 5; 594 nLine2 /= 5; 595 nDistance /= 5; 596 } 597 598 // Paint the lines 599 aSize = aVirDev->PixelToLogic( aSize ); 600 tools::Long nPix = aVirDev->PixelToLogic( Size( 0, 1 ) ).Height(); 601 sal_uInt32 n1 = nLine1; 602 sal_uInt32 n2 = nLine2; 603 tools::Long nDist = nDistance; 604 n1 += nPix-1; 605 n1 -= n1%nPix; 606 if ( n2 ) 607 { 608 nDist += nPix-1; 609 nDist -= nDist%nPix; 610 n2 += nPix-1; 611 n2 -= n2%nPix; 612 } 613 tools::Long nVirHeight = n1+nDist+n2; 614 if ( nVirHeight > aSize.Height() ) 615 aSize.setHeight( nVirHeight ); 616 // negative width should not be drawn 617 if ( aSize.Width() <= 0 ) 618 return; 619 620 Size aVirSize = aVirDev->LogicToPixel( aSize ); 621 if ( aVirDev->GetOutputSizePixel() != aVirSize ) 622 aVirDev->SetOutputSizePixel( aVirSize ); 623 aVirDev->SetFillColor( aColorDist ); 624 aVirDev->DrawRect( tools::Rectangle( Point(), aSize ) ); 625 626 aVirDev->SetFillColor( aColor1 ); 627 628 double y1 = double( n1 ) / 2; 629 svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y1 ), basegfx::B2DPoint( aSize.Width( ), y1 ), n1, nStyle ); 630 631 if ( n2 ) 632 { 633 double y2 = n1 + nDist + double( n2 ) / 2; 634 aVirDev->SetFillColor( aColor2 ); 635 svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y2 ), basegfx::B2DPoint( aSize.Width(), y2 ), n2, SvxBorderLineStyle::SOLID ); 636 } 637 rBmp = aVirDev->GetBitmapEx( Point(), Size( aSize.Width(), n1+nDist+n2 ) ); 638 } 639 640 LineListBox::LineListBox() 641 : ValueSet(nullptr) 642 , m_nWidth( 5 ) 643 , aVirDev(VclPtr<VirtualDevice>::Create()) 644 , aColor(Application::GetSettings().GetStyleSettings().GetWindowTextColor()) 645 , maPaintCol(COL_BLACK) 646 , eSourceUnit(FieldUnit::POINT) 647 { 648 aVirDev->SetLineColor(); 649 aVirDev->SetMapMode( MapMode( MapUnit::MapTwip ) ); 650 } 651 652 void LineListBox::SetDrawingArea(weld::DrawingArea* pDrawingArea) 653 { 654 ValueSet::SetDrawingArea(pDrawingArea); 655 656 OutputDevice& rDevice = pDrawingArea->get_ref_device(); 657 658 aTxtSize.setWidth( rDevice.approximate_digit_width() ); 659 aTxtSize.setHeight( rDevice.GetTextHeight() ); 660 661 UpdatePaintLineColor(); 662 } 663 664 sal_Int32 LineListBox::GetStylePos( sal_Int32 nListPos, tools::Long nWidth ) 665 { 666 sal_Int32 nPos = -1; 667 if (!m_sNone.isEmpty()) 668 nListPos--; 669 670 sal_Int32 n = 0; 671 size_t i = 0; 672 size_t nCount = m_vLineList.size(); 673 while ( nPos == -1 && i < nCount ) 674 { 675 auto& pData = m_vLineList[ i ]; 676 if ( pData->GetMinWidth() <= nWidth ) 677 { 678 if ( nListPos == n ) 679 nPos = static_cast<sal_Int32>(i); 680 n++; 681 } 682 i++; 683 } 684 685 return nPos; 686 } 687 688 void LineListBox::InsertEntry( 689 const BorderWidthImpl& rWidthImpl, SvxBorderLineStyle nStyle, tools::Long nMinWidth, 690 ColorFunc pColor1Fn, ColorFunc pColor2Fn, ColorDistFunc pColorDistFn ) 691 { 692 m_vLineList.emplace_back(new ImpLineListData( 693 rWidthImpl, nStyle, nMinWidth, pColor1Fn, pColor2Fn, pColorDistFn)); 694 } 695 696 SvxBorderLineStyle LineListBox::GetEntryStyle( sal_Int32 nPos ) const 697 { 698 ImpLineListData* pData = (0 <= nPos && o3tl::make_unsigned(nPos) < m_vLineList.size()) ? m_vLineList[ nPos ].get() : nullptr; 699 return pData ? pData->GetStyle() : SvxBorderLineStyle::NONE; 700 } 701 702 void LineListBox::UpdatePaintLineColor() 703 { 704 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); 705 Color aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor ); 706 707 bool bRet = aNewCol != maPaintCol; 708 709 if( bRet ) 710 maPaintCol = aNewCol; 711 } 712 713 Size LineListBox::UpdateEntries( tools::Long nOldWidth ) 714 { 715 Size aSize; 716 717 UpdatePaintLineColor( ); 718 719 sal_Int32 nSelEntry = GetSelectItemPos(); 720 sal_Int32 nTypePos = GetStylePos( nSelEntry, nOldWidth ); 721 722 // Remove the old entries 723 Clear(); 724 725 sal_uInt16 nId(1); 726 727 // Add the new entries based on the defined width 728 if (!m_sNone.isEmpty()) 729 InsertItem(nId++, Image(), m_sNone); 730 731 sal_uInt16 n = 0; 732 sal_uInt16 nCount = m_vLineList.size( ); 733 while ( n < nCount ) 734 { 735 auto& pData = m_vLineList[ n ]; 736 if ( pData->GetMinWidth() <= m_nWidth ) 737 { 738 BitmapEx aBmp; 739 ImpGetLine( pData->GetLine1ForWidth( m_nWidth ), 740 pData->GetLine2ForWidth( m_nWidth ), 741 pData->GetDistForWidth( m_nWidth ), 742 GetColorLine1( GetItemCount( ) ), 743 GetColorLine2( GetItemCount( ) ), 744 GetColorDist( GetItemCount( ) ), 745 pData->GetStyle(), aBmp ); 746 InsertItem(nId, Image(aBmp), SvtLineListBox::GetLineStyleName(pData->GetStyle())); 747 Size aBmpSize = aBmp.GetSizePixel(); 748 if (aBmpSize.Width() > aSize.Width()) 749 aSize.setWidth(aBmpSize.getWidth()); 750 if (aBmpSize.Height() > aSize.Height()) 751 aSize.setHeight(aBmpSize.getHeight()); 752 if ( n == nTypePos ) 753 SelectItem(nId); 754 } 755 else if ( n == nTypePos ) 756 SetNoSelection(); 757 n++; 758 ++nId; 759 } 760 761 Invalidate(); 762 763 return aSize; 764 } 765 766 Color LineListBox::GetColorLine1( sal_Int32 nPos ) 767 { 768 sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); 769 if (nStyle == -1) 770 return GetPaintColor( ); 771 auto& pData = m_vLineList[ nStyle ]; 772 return pData->GetColorLine1( GetColor( ) ); 773 } 774 775 Color LineListBox::GetColorLine2( sal_Int32 nPos ) 776 { 777 sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); 778 if (nStyle == -1) 779 return GetPaintColor( ); 780 auto& pData = m_vLineList[ nStyle ]; 781 return pData->GetColorLine2( GetColor( ) ); 782 } 783 784 Color LineListBox::GetColorDist( sal_Int32 nPos ) 785 { 786 Color rResult = Application::GetSettings().GetStyleSettings().GetFieldColor(); 787 788 sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); 789 if (nStyle == -1) 790 return rResult; 791 auto& pData = m_vLineList[ nStyle ]; 792 return pData->GetColorDist( GetColor( ), rResult ); 793 } 794 } 795 796 namespace { 797 798 class SvxLineWindow_Impl final : public WeldToolbarPopup 799 { 800 private: 801 rtl::Reference<SvxFrameToolBoxControl> m_xControl; 802 std::unique_ptr<LineListBox> m_xLineStyleLb; 803 std::unique_ptr<weld::CustomWeld> m_xLineStyleLbWin; 804 bool m_bIsWriter; 805 806 DECL_LINK( SelectHdl, ValueSet*, void ); 807 808 public: 809 SvxLineWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent); 810 virtual void GrabFocus() override 811 { 812 m_xLineStyleLb->GrabFocus(); 813 } 814 }; 815 816 } 817 818 class SvxStyleToolBoxControl; 819 820 class SfxStyleControllerItem_Impl : public SfxStatusListener 821 { 822 public: 823 SfxStyleControllerItem_Impl( const Reference< XDispatchProvider >& rDispatchProvider, 824 sal_uInt16 nSlotId, 825 const OUString& rCommand, 826 SvxStyleToolBoxControl& rTbxCtl ); 827 828 protected: 829 virtual void StateChangedAtStatusListener( SfxItemState eState, const SfxPoolItem* pState ) override; 830 831 private: 832 SvxStyleToolBoxControl& rControl; 833 }; 834 835 #define BUTTON_PADDING 10 836 #define ITEM_HEIGHT 30 837 838 SvxStyleBox_Base::SvxStyleBox_Base(std::unique_ptr<weld::ComboBox> xWidget, 839 const OUString& rCommand, 840 SfxStyleFamily eFamily, 841 const Reference< XDispatchProvider >& rDispatchProvider, 842 const Reference< XFrame >& _xFrame, 843 const OUString& rClearFormatKey, 844 const OUString& rMoreKey, 845 bool bInSpec, SvxStyleToolBoxControl& rCtrl) 846 : m_rCtrl(rCtrl) 847 , m_xMenuBuilder(Application::CreateBuilder(nullptr, "svx/ui/stylemenu.ui")) 848 , m_xMenu(m_xMenuBuilder->weld_menu("menu")) 849 , m_xWidget(std::move(xWidget)) 850 , eStyleFamily( eFamily ) 851 , m_nMaxUserDrawFontWidth(0) 852 , m_nLastItemWithMenu(-1) 853 , bRelease( true ) 854 , m_xDispatchProvider( rDispatchProvider ) 855 , m_xFrame(_xFrame) 856 , m_aCommand( rCommand ) 857 , aClearFormatKey( rClearFormatKey ) 858 , aMoreKey( rMoreKey ) 859 , bInSpecialMode( bInSpec ) 860 { 861 m_xWidget->connect_changed(LINK(this, SvxStyleBox_Base, SelectHdl)); 862 m_xWidget->connect_key_press(LINK(this, SvxStyleBox_Base, KeyInputHdl)); 863 m_xWidget->connect_entry_activate(LINK(this, SvxStyleBox_Base, ActivateHdl)); 864 m_xWidget->connect_focus_out(LINK(this, SvxStyleBox_Base, FocusOutHdl)); 865 m_xWidget->connect_get_property_tree(LINK(this, SvxStyleBox_Base, DumpAsPropertyTreeHdl)); 866 m_xWidget->set_help_id(HID_STYLE_LISTBOX); 867 m_xWidget->set_entry_completion(true); 868 m_xMenu->connect_activate(LINK(this, SvxStyleBox_Base, MenuSelectHdl)); 869 870 m_xWidget->connect_custom_get_size(LINK(this, SvxStyleBox_Base, CustomGetSizeHdl)); 871 m_xWidget->connect_custom_render(LINK(this, SvxStyleBox_Base, CustomRenderHdl)); 872 m_xWidget->set_custom_renderer(true); 873 874 m_xWidget->set_entry_width_chars(COMBO_WIDTH_IN_CHARS + 3); 875 } 876 877 IMPL_LINK(SvxStyleBox_Base, CustomGetSizeHdl, OutputDevice&, rArg, Size) 878 { 879 CalcOptimalExtraUserWidth(rArg); 880 return Size(m_nMaxUserDrawFontWidth, ITEM_HEIGHT); 881 } 882 883 SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent, 884 const OUString& rCommand, 885 SfxStyleFamily eFamily, 886 const Reference< XDispatchProvider >& rDispatchProvider, 887 const Reference< XFrame >& _xFrame, 888 const OUString& rClearFormatKey, 889 const OUString& rMoreKey, 890 bool bInSpec, SvxStyleToolBoxControl& rCtrl) 891 : InterimItemWindow(pParent, "svx/ui/applystylebox.ui", "ApplyStyleBox") 892 , SvxStyleBox_Base(m_xBuilder->weld_combo_box("applystyle"), rCommand, eFamily, 893 rDispatchProvider, _xFrame, rClearFormatKey, rMoreKey, bInSpec, rCtrl) 894 { 895 InitControlBase(m_xWidget.get()); 896 897 set_id("applystyle"); 898 SetOptimalSize(); 899 } 900 901 void SvxStyleBox_Base::ReleaseFocus() 902 { 903 if ( !bRelease ) 904 { 905 bRelease = true; 906 return; 907 } 908 if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) 909 m_xFrame->getContainerWindow()->setFocus(); 910 } 911 912 IMPL_LINK(SvxStyleBox_Base, MenuSelectHdl, const OString&, rMenuIdent, void) 913 { 914 if (m_nLastItemWithMenu < 0 || m_nLastItemWithMenu >= m_xWidget->get_count()) 915 return; 916 917 OUString sEntry = m_xWidget->get_text(m_nLastItemWithMenu); 918 919 ReleaseFocus(); // It must be after getting entry pos! 920 Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue("Param", sEntry), 921 comphelper::makePropertyValue("Family", 922 sal_Int16( eStyleFamily )) }; 923 924 if (rMenuIdent == "update") 925 { 926 SfxToolBoxControl::Dispatch( m_xDispatchProvider, 927 ".uno:StyleUpdateByExample", aArgs ); 928 } 929 else if (rMenuIdent == "edit") 930 { 931 SfxToolBoxControl::Dispatch( m_xDispatchProvider, 932 ".uno:EditStyle", aArgs ); 933 } 934 } 935 936 IMPL_STATIC_LINK_NOARG(SvxStyleBox_Base, ShowMoreHdl, void*, void) 937 { 938 SfxViewFrame* pViewFrm = SfxViewFrame::Current(); 939 DBG_ASSERT( pViewFrm, "SvxStyleBox_Base::Select(): no viewframe" ); 940 if (!pViewFrm) 941 return; 942 pViewFrm->ShowChildWindow(SID_SIDEBAR); 943 ::sfx2::sidebar::Sidebar::ShowPanel(u"StyleListPanel", pViewFrm->GetFrame().GetFrameInterface(), true); 944 } 945 946 IMPL_LINK(SvxStyleBox_Base, SelectHdl, weld::ComboBox&, rCombo, void) 947 { 948 Select(rCombo.changed_by_direct_pick()); // only when picked from the list 949 } 950 951 IMPL_LINK_NOARG(SvxStyleBox_Base, ActivateHdl, weld::ComboBox&, bool) 952 { 953 Select(true); 954 return true; 955 } 956 957 void SvxStyleBox_Base::Select(bool bNonTravelSelect) 958 { 959 if (!bNonTravelSelect) 960 return; 961 962 OUString aSearchEntry(m_xWidget->get_active_text()); 963 bool bDoIt = true, bClear = false; 964 if( bInSpecialMode ) 965 { 966 if( aSearchEntry == aClearFormatKey && m_xWidget->get_active() == 0 ) 967 { 968 aSearchEntry = sDefaultStyle; 969 bClear = true; 970 //not only apply default style but also call 'ClearFormatting' 971 Sequence< PropertyValue > aEmptyVals; 972 SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:ResetAttributes", 973 aEmptyVals); 974 } 975 else if (aSearchEntry == aMoreKey && m_xWidget->get_active() == (m_xWidget->get_count() - 1)) 976 { 977 Application::PostUserEvent(LINK(nullptr, SvxStyleBox_Base, ShowMoreHdl)); 978 //tdf#113214 change text back to previous entry 979 set_active_or_entry_text(m_xWidget->get_saved_value()); 980 bDoIt = false; 981 } 982 } 983 984 //Do we need to create a new style? 985 SfxObjectShell *pShell = SfxObjectShell::Current(); 986 SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); 987 SfxStyleSheetBase* pStyle = nullptr; 988 989 bool bCreateNew = false; 990 991 if ( pPool ) 992 { 993 pStyle = pPool->First(eStyleFamily); 994 while ( pStyle && pStyle->GetName() != aSearchEntry ) 995 pStyle = pPool->Next(); 996 } 997 998 if ( !pStyle ) 999 { 1000 // cannot find the style for whatever reason 1001 // therefore create a new style 1002 bCreateNew = true; 1003 } 1004 1005 /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. 1006 This instance may be deleted in the meantime (i.e. when a dialog is opened 1007 while in Dispatch()), accessing members will crash in this case. */ 1008 ReleaseFocus(); 1009 1010 if( !bDoIt ) 1011 return; 1012 1013 if ( bClear ) 1014 set_active_or_entry_text(aSearchEntry); 1015 m_xWidget->save_value(); 1016 1017 Sequence< PropertyValue > aArgs( 2 ); 1018 auto pArgs = aArgs.getArray(); 1019 pArgs[0].Value <<= aSearchEntry; 1020 pArgs[1].Name = "Family"; 1021 pArgs[1].Value <<= sal_Int16( eStyleFamily ); 1022 if( bCreateNew ) 1023 { 1024 pArgs[0].Name = "Param"; 1025 SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:StyleNewByExample", aArgs); 1026 } 1027 else 1028 { 1029 pArgs[0].Name = "Template"; 1030 SfxToolBoxControl::Dispatch( m_xDispatchProvider, m_aCommand, aArgs ); 1031 } 1032 } 1033 1034 void SvxStyleBox_Base::SetFamily( SfxStyleFamily eNewFamily ) 1035 { 1036 eStyleFamily = eNewFamily; 1037 } 1038 1039 IMPL_LINK_NOARG(SvxStyleBox_Base, FocusOutHdl, weld::Widget&, void) 1040 { 1041 if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus 1042 set_active_or_entry_text(m_xWidget->get_saved_value()); 1043 } 1044 1045 IMPL_LINK(SvxStyleBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) 1046 { 1047 return DoKeyInput(rKEvt); 1048 } 1049 1050 bool SvxStyleBox_Base::DoKeyInput(const KeyEvent& rKEvt) 1051 { 1052 bool bHandled = false; 1053 1054 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); 1055 1056 switch (nCode) 1057 { 1058 case KEY_TAB: 1059 bRelease = false; 1060 Select(true); 1061 break; 1062 case KEY_ESCAPE: 1063 set_active_or_entry_text(m_xWidget->get_saved_value()); 1064 if (!m_rCtrl.IsInSidebar()) 1065 { 1066 ReleaseFocus(); 1067 bHandled = true; 1068 } 1069 break; 1070 } 1071 1072 return bHandled; 1073 } 1074 1075 bool SvxStyleBox_Impl::DoKeyInput(const KeyEvent& rKEvt) 1076 { 1077 return SvxStyleBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt); 1078 } 1079 1080 void SvxStyleBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) 1081 { 1082 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && 1083 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) 1084 { 1085 SetOptimalSize(); 1086 } 1087 1088 InterimItemWindow::DataChanged( rDCEvt ); 1089 } 1090 1091 bool SvxStyleBox_Base::AdjustFontForItemHeight(OutputDevice& rDevice, tools::Rectangle const & rTextRect, tools::Long nHeight) 1092 { 1093 if (rTextRect.Bottom() > nHeight) 1094 { 1095 // the text does not fit, adjust the font size 1096 double ratio = static_cast< double >( nHeight ) / rTextRect.Bottom(); 1097 vcl::Font aFont(rDevice.GetFont()); 1098 Size aPixelSize(aFont.GetFontSize()); 1099 aPixelSize.setWidth( aPixelSize.Width() * ratio ); 1100 aPixelSize.setHeight( aPixelSize.Height() * ratio ); 1101 aFont.SetFontSize(aPixelSize); 1102 rDevice.SetFont(aFont); 1103 return true; 1104 } 1105 return false; 1106 } 1107 1108 void SvxStyleBox_Impl::SetOptimalSize() 1109 { 1110 // set width in chars low so the size request will not be overridden 1111 m_xWidget->set_entry_width_chars(1); 1112 // tdf#132338 purely using this calculation to keep things their traditional width 1113 Size aSize(LogicToPixel(Size((COMBO_WIDTH_IN_CHARS + 3) * 4, 0), MapMode(MapUnit::MapAppFont))); 1114 m_xWidget->set_size_request(aSize.Width(), -1); 1115 1116 SetSizePixel(get_preferred_size()); 1117 } 1118 1119 void SvxStyleBox_Base::UserDrawEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const OUString &rStyleName) 1120 { 1121 // IMG_TXT_DISTANCE in ilstbox.hxx is 6, then 1 is added as 1122 // nBorder, and we are adding 1 in order to look better when 1123 // italics is present 1124 const int nLeftDistance = 8; 1125 1126 tools::Rectangle aTextRect; 1127 rRenderContext.GetTextBoundRect(aTextRect, rStyleName); 1128 1129 Point aPos(rRect.TopLeft()); 1130 aPos.AdjustX(nLeftDistance ); 1131 1132 if (!AdjustFontForItemHeight(rRenderContext, aTextRect, rRect.GetHeight())) 1133 aPos.AdjustY((rRect.GetHeight() - aTextRect.Bottom() ) / 2); 1134 1135 rRenderContext.DrawText(aPos, rStyleName); 1136 } 1137 1138 void SvxStyleBox_Base::SetupEntry(vcl::RenderContext& rRenderContext, sal_Int32 nItem, const tools::Rectangle& rRect, std::u16string_view rStyleName, bool bIsNotSelected) 1139 { 1140 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 1141 if (!bIsNotSelected) 1142 rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor()); 1143 else 1144 rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor()); 1145 1146 // handle the push-button 1147 if (!bIsNotSelected) 1148 { 1149 if (nItem == 0 || nItem == m_xWidget->get_count() - 1) 1150 m_xWidget->set_item_menu(OString::number(nItem), nullptr); 1151 else 1152 { 1153 m_nLastItemWithMenu = nItem; 1154 m_xWidget->set_item_menu(OString::number(nItem), m_xMenu.get()); 1155 } 1156 } 1157 1158 if (nItem <= 0 || nItem >= m_xWidget->get_count() - 1) 1159 return; 1160 1161 SfxObjectShell *pShell = SfxObjectShell::Current(); 1162 SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); 1163 SfxStyleSheetBase* pStyle = nullptr; 1164 1165 if ( pPool ) 1166 { 1167 pStyle = pPool->First(eStyleFamily); 1168 while (pStyle && pStyle->GetName() != rStyleName) 1169 pStyle = pPool->Next(); 1170 } 1171 1172 if (!pStyle ) 1173 return; 1174 1175 std::optional<SfxItemSet> const pItemSet(pStyle->GetItemSetForPreview()); 1176 if (!pItemSet) return; 1177 1178 const SvxFontItem * const pFontItem = 1179 pItemSet->GetItem<SvxFontItem>(SID_ATTR_CHAR_FONT); 1180 const SvxFontHeightItem * const pFontHeightItem = 1181 pItemSet->GetItem<SvxFontHeightItem>(SID_ATTR_CHAR_FONTHEIGHT); 1182 1183 if ( !(pFontItem && pFontHeightItem) ) 1184 return; 1185 1186 Size aFontSize( 0, pFontHeightItem->GetHeight() ); 1187 Size aPixelSize(rRenderContext.LogicToPixel(aFontSize, MapMode(pShell->GetMapUnit()))); 1188 1189 // setup the font properties 1190 SvxFont aFont; 1191 aFont.SetFamilyName(pFontItem->GetFamilyName()); 1192 aFont.SetStyleName(pFontItem->GetStyleName()); 1193 aFont.SetFontSize(aPixelSize); 1194 1195 const SfxPoolItem *pItem = pItemSet->GetItem( SID_ATTR_CHAR_WEIGHT ); 1196 if ( pItem ) 1197 aFont.SetWeight( static_cast< const SvxWeightItem* >( pItem )->GetWeight() ); 1198 1199 pItem = pItemSet->GetItem( SID_ATTR_CHAR_POSTURE ); 1200 if ( pItem ) 1201 aFont.SetItalic( static_cast< const SvxPostureItem* >( pItem )->GetPosture() ); 1202 1203 pItem = pItemSet->GetItem( SID_ATTR_CHAR_CONTOUR ); 1204 if ( pItem ) 1205 aFont.SetOutline( static_cast< const SvxContourItem* >( pItem )->GetValue() ); 1206 1207 pItem = pItemSet->GetItem( SID_ATTR_CHAR_SHADOWED ); 1208 if ( pItem ) 1209 aFont.SetShadow( static_cast< const SvxShadowedItem* >( pItem )->GetValue() ); 1210 1211 pItem = pItemSet->GetItem( SID_ATTR_CHAR_RELIEF ); 1212 if ( pItem ) 1213 aFont.SetRelief( static_cast< const SvxCharReliefItem* >( pItem )->GetValue() ); 1214 1215 pItem = pItemSet->GetItem( SID_ATTR_CHAR_UNDERLINE ); 1216 if ( pItem ) 1217 aFont.SetUnderline( static_cast< const SvxUnderlineItem* >( pItem )->GetLineStyle() ); 1218 1219 pItem = pItemSet->GetItem( SID_ATTR_CHAR_OVERLINE ); 1220 if ( pItem ) 1221 aFont.SetOverline( static_cast< const SvxOverlineItem* >( pItem )->GetValue() ); 1222 1223 pItem = pItemSet->GetItem( SID_ATTR_CHAR_STRIKEOUT ); 1224 if ( pItem ) 1225 aFont.SetStrikeout( static_cast< const SvxCrossedOutItem* >( pItem )->GetStrikeout() ); 1226 1227 pItem = pItemSet->GetItem( SID_ATTR_CHAR_CASEMAP ); 1228 if ( pItem ) 1229 aFont.SetCaseMap(static_cast<const SvxCaseMapItem*>(pItem)->GetCaseMap()); 1230 1231 pItem = pItemSet->GetItem( SID_ATTR_CHAR_EMPHASISMARK ); 1232 if ( pItem ) 1233 aFont.SetEmphasisMark( static_cast< const SvxEmphasisMarkItem* >( pItem )->GetEmphasisMark() ); 1234 1235 // setup the device & draw 1236 Color aFontCol = COL_AUTO, aBackCol = COL_AUTO; 1237 1238 rRenderContext.SetFont(aFont); 1239 1240 pItem = pItemSet->GetItem( SID_ATTR_CHAR_COLOR ); 1241 // text color, when nothing is selected 1242 if ( (nullptr != pItem) && bIsNotSelected) 1243 aFontCol = static_cast< const SvxColorItem* >( pItem )->GetValue(); 1244 1245 drawing::FillStyle style = drawing::FillStyle_NONE; 1246 // which kind of Fill style is selected 1247 pItem = pItemSet->GetItem( XATTR_FILLSTYLE ); 1248 // only when ok and not selected 1249 if ( (nullptr != pItem) && bIsNotSelected) 1250 style = static_cast< const XFillStyleItem* >( pItem )->GetValue(); 1251 1252 switch(style) 1253 { 1254 case drawing::FillStyle_SOLID: 1255 { 1256 // set background color 1257 pItem = pItemSet->GetItem( XATTR_FILLCOLOR ); 1258 if ( nullptr != pItem ) 1259 aBackCol = static_cast< const XFillColorItem* >( pItem )->GetColorValue(); 1260 1261 if ( aBackCol != COL_AUTO ) 1262 { 1263 rRenderContext.SetFillColor(aBackCol); 1264 rRenderContext.DrawRect(rRect); 1265 } 1266 } 1267 break; 1268 1269 default: break; 1270 //TODO Draw the other background styles: gradient, hatching and bitmap 1271 } 1272 1273 // when the font and background color are too similar, adjust the Font-Color 1274 if( (aFontCol != COL_AUTO) || (aBackCol != COL_AUTO) ) 1275 aFontCol = TestColorsVisible(aFontCol, (aBackCol != COL_AUTO) ? aBackCol : rRenderContext.GetBackground().GetColor()); 1276 1277 // set text color 1278 if ( aFontCol != COL_AUTO ) 1279 rRenderContext.SetTextColor(aFontCol); 1280 } 1281 1282 IMPL_LINK(SvxStyleBox_Base, CustomRenderHdl, weld::ComboBox::render_args, aPayload, void) 1283 { 1284 vcl::RenderContext& rRenderContext = std::get<0>(aPayload); 1285 const ::tools::Rectangle& rRect = std::get<1>(aPayload); 1286 bool bSelected = std::get<2>(aPayload); 1287 const OUString& rId = std::get<3>(aPayload); 1288 1289 sal_uInt32 nIndex = rId.toUInt32(); 1290 1291 OUString aStyleName(m_xWidget->get_text(nIndex)); 1292 1293 rRenderContext.Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::FONT | vcl::PushFlags::TEXTCOLOR); 1294 1295 SetupEntry(rRenderContext, nIndex, rRect, aStyleName, !bSelected); 1296 1297 UserDrawEntry(rRenderContext, rRect, aStyleName); 1298 1299 rRenderContext.Pop(); 1300 } 1301 1302 void SvxStyleBox_Base::CalcOptimalExtraUserWidth(vcl::RenderContext& rRenderContext) 1303 { 1304 if (m_nMaxUserDrawFontWidth) 1305 return; 1306 1307 tools::Long nMaxNormalFontWidth = 0; 1308 sal_Int32 nEntryCount = m_xWidget->get_count(); 1309 for (sal_Int32 i = 0; i < nEntryCount; ++i) 1310 { 1311 OUString sStyleName(get_text(i)); 1312 tools::Rectangle aTextRectForDefaultFont; 1313 rRenderContext.GetTextBoundRect(aTextRectForDefaultFont, sStyleName); 1314 1315 const tools::Long nWidth = aTextRectForDefaultFont.GetWidth(); 1316 1317 nMaxNormalFontWidth = std::max(nWidth, nMaxNormalFontWidth); 1318 } 1319 1320 m_nMaxUserDrawFontWidth = nMaxNormalFontWidth; 1321 for (sal_Int32 i = 1; i < nEntryCount-1; ++i) 1322 { 1323 OUString sStyleName(get_text(i)); 1324 1325 rRenderContext.Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::FONT | vcl::PushFlags::TEXTCOLOR); 1326 SetupEntry(rRenderContext, i, tools::Rectangle(0, 0, RECT_MAX, ITEM_HEIGHT), sStyleName, true); 1327 tools::Rectangle aTextRectForActualFont; 1328 rRenderContext.GetTextBoundRect(aTextRectForActualFont, sStyleName); 1329 if (AdjustFontForItemHeight(rRenderContext, aTextRectForActualFont, ITEM_HEIGHT)) 1330 { 1331 //Font didn't fit, so it was changed, refetch with final font size 1332 rRenderContext.GetTextBoundRect(aTextRectForActualFont, sStyleName); 1333 } 1334 rRenderContext.Pop(); 1335 1336 const int nWidth = aTextRectForActualFont.GetWidth() + m_xWidget->get_menu_button_width() + BUTTON_PADDING; 1337 1338 m_nMaxUserDrawFontWidth = std::max(nWidth, m_nMaxUserDrawFontWidth); 1339 } 1340 } 1341 1342 // test is the color between Font- and background-color to be identify 1343 // return is always the Font-Color 1344 // when both light or dark, change the Contrast 1345 // in other case do not change the origin color 1346 // when the color is R=G=B=128 the DecreaseContrast make 128 the need an exception 1347 Color SvxStyleBox_Base::TestColorsVisible(const Color &FontCol, const Color &BackCol) 1348 { 1349 constexpr sal_uInt8 ChgVal = 60; // increase/decrease the Contrast 1350 1351 Color retCol = FontCol; 1352 if ((FontCol.IsDark() == BackCol.IsDark()) && (FontCol.IsBright() == BackCol.IsBright())) 1353 { 1354 sal_uInt8 lumi = retCol.GetLuminance(); 1355 1356 if((lumi > 120) && (lumi < 140)) 1357 retCol.DecreaseLuminance(ChgVal / 2); 1358 else 1359 retCol.DecreaseContrast(ChgVal); 1360 } 1361 1362 return retCol; 1363 } 1364 1365 IMPL_LINK(SvxStyleBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void) 1366 { 1367 { 1368 auto entriesNode = rJsonWriter.startNode("entries"); 1369 for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i) 1370 { 1371 auto entryNode = rJsonWriter.startNode(""); 1372 rJsonWriter.put("", m_xWidget->get_text(i)); 1373 } 1374 } 1375 1376 int nActive = m_xWidget->get_active(); 1377 rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nActive == -1 ? 0 : 1)); 1378 1379 { 1380 auto selectedNode = rJsonWriter.startNode("selectedEntries"); 1381 if (nActive != -1) 1382 { 1383 auto node = rJsonWriter.startNode(""); 1384 rJsonWriter.put("", static_cast<sal_Int32>(nActive)); 1385 } 1386 } 1387 1388 rJsonWriter.put("command", ".uno:StyleApply"); 1389 } 1390 1391 static bool lcl_GetDocFontList(const FontList** ppFontList, SvxFontNameBox_Base* pBox) 1392 { 1393 bool bChanged = false; 1394 const SfxObjectShell* pDocSh = SfxObjectShell::Current(); 1395 const SvxFontListItem* pFontListItem = nullptr; 1396 1397 if ( pDocSh ) 1398 pFontListItem = 1399 static_cast<const SvxFontListItem*>(pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST )); 1400 else 1401 { 1402 ::std::unique_ptr<FontList> aFontList(new FontList(Application::GetDefaultDevice())); 1403 *ppFontList = aFontList.get(); 1404 pBox->SetOwnFontList(std::move(aFontList)); 1405 bChanged = true; 1406 } 1407 1408 if ( pFontListItem ) 1409 { 1410 const FontList* pNewFontList = pFontListItem->GetFontList(); 1411 DBG_ASSERT( pNewFontList, "Doc-FontList not available!" ); 1412 1413 // No old list, but a new list 1414 if ( !*ppFontList && pNewFontList ) 1415 { 1416 // => take over 1417 *ppFontList = pNewFontList; 1418 bChanged = true; 1419 } 1420 else 1421 { 1422 // Comparing the font lists is not perfect. 1423 // When you change the font list in the Doc, you can track 1424 // changes here only on the Listbox, because ppFontList 1425 // has already been updated. 1426 bChanged = 1427 ( ( *ppFontList != pNewFontList ) || 1428 pBox->GetListCount() != pNewFontList->GetFontNameCount() ); 1429 // HACK: Comparing is incomplete 1430 1431 if ( bChanged ) 1432 *ppFontList = pNewFontList; 1433 } 1434 1435 if ( pBox ) 1436 pBox->set_sensitive(true); 1437 } 1438 else if ( pBox && ( pDocSh || !ppFontList )) 1439 { 1440 // Disable box only when we have a SfxObjectShell and didn't get a font list OR 1441 // we don't have a SfxObjectShell and no current font list. 1442 // It's possible that we currently have no SfxObjectShell, but a current font list. 1443 // See #i58471: When a user set the focus into the font name combo box and opens 1444 // the help window with F1. After closing the help window, we disable the font name 1445 // combo box. The SfxObjectShell::Current() method returns in that case zero. But the 1446 // font list hasn't changed and therefore the combo box shouldn't be disabled! 1447 pBox->set_sensitive(false); 1448 } 1449 1450 // Fill the FontBox, also the new list if necessary 1451 if ( pBox && bChanged ) 1452 { 1453 if ( *ppFontList ) 1454 pBox->Fill( *ppFontList ); 1455 else 1456 pBox->Clear(); 1457 } 1458 return bChanged; 1459 } 1460 1461 SvxFontNameBox_Base::SvxFontNameBox_Base(std::unique_ptr<weld::ComboBox> xWidget, 1462 const Reference<XDispatchProvider>& rDispatchProvider, 1463 const Reference<XFrame>& rFrame, 1464 SvxFontNameToolBoxControl& rCtrl) 1465 : m_xListener(new comphelper::ConfigurationListener("/org.openoffice.Office.Common/Font/View")) 1466 , m_aWYSIWYG(m_xListener, "ShowFontBoxWYSIWYG", *this) 1467 , m_aHistory(m_xListener, "History", *this) 1468 , m_rCtrl(rCtrl) 1469 , m_xWidget(new FontNameBox(std::move(xWidget))) 1470 , pFontList(nullptr) 1471 , nFtCount(0) 1472 , bRelease(true) 1473 , m_xDispatchProvider(rDispatchProvider) 1474 , m_xFrame(rFrame) 1475 , mbCheckingUnknownFont(false) 1476 { 1477 EnableControls(); 1478 1479 m_xWidget->connect_changed(LINK(this, SvxFontNameBox_Base, SelectHdl)); 1480 m_xWidget->connect_key_press(LINK(this, SvxFontNameBox_Base, KeyInputHdl)); 1481 m_xWidget->connect_entry_activate(LINK(this, SvxFontNameBox_Base, ActivateHdl)); 1482 m_xWidget->connect_focus_in(LINK(this, SvxFontNameBox_Base, FocusInHdl)); 1483 m_xWidget->connect_focus_out(LINK(this, SvxFontNameBox_Base, FocusOutHdl)); 1484 m_xWidget->connect_get_property_tree(LINK(this, SvxFontNameBox_Base, DumpAsPropertyTreeHdl)); 1485 1486 m_xWidget->set_entry_width_chars(COMBO_WIDTH_IN_CHARS + 5); 1487 } 1488 1489 SvxFontNameBox_Impl::SvxFontNameBox_Impl(vcl::Window* pParent, const Reference<XDispatchProvider>& rDispatchProvider, 1490 const Reference<XFrame>& rFrame, SvxFontNameToolBoxControl& rCtrl) 1491 : InterimItemWindow(pParent, "svx/ui/fontnamebox.ui", "FontNameBox") 1492 , SvxFontNameBox_Base(m_xBuilder->weld_combo_box("fontnamecombobox"), rDispatchProvider, rFrame, rCtrl) 1493 { 1494 set_id("fontnamecombobox"); 1495 SetOptimalSize(); 1496 } 1497 1498 void SvxFontNameBox_Base::FillList() 1499 { 1500 if (!m_xWidget) // e.g. disposed 1501 return; 1502 // Save old Selection, set back in the end 1503 int nStartPos, nEndPos; 1504 m_xWidget->get_entry_selection_bounds(nStartPos, nEndPos); 1505 1506 // Did Doc-Fontlist change? 1507 lcl_GetDocFontList(&pFontList, this); 1508 1509 m_xWidget->select_entry_region(nStartPos, nEndPos); 1510 } 1511 1512 void SvxFontNameBox_Base::CheckAndMarkUnknownFont() 1513 { 1514 if (mbCheckingUnknownFont) //tdf#117537 block rentry 1515 return; 1516 mbCheckingUnknownFont = true; 1517 OUString fontname = m_xWidget->get_active_text(); 1518 lcl_GetDocFontList( &pFontList, this ); 1519 // If the font is unknown, show it in italic. 1520 vcl::Font font = m_xWidget->get_entry_font(); 1521 if( pFontList != nullptr && pFontList->IsAvailable( fontname )) 1522 { 1523 if( font.GetItalic() != ITALIC_NONE ) 1524 { 1525 font.SetItalic( ITALIC_NONE ); 1526 m_xWidget->set_entry_font(font); 1527 m_xWidget->set_tooltip_text(SvxResId(RID_SVXSTR_CHARFONTNAME)); 1528 } 1529 } 1530 else 1531 { 1532 if( font.GetItalic() != ITALIC_NORMAL ) 1533 { 1534 font.SetItalic( ITALIC_NORMAL ); 1535 m_xWidget->set_entry_font(font); 1536 m_xWidget->set_tooltip_text(SvxResId(RID_SVXSTR_CHARFONTNAME_NOTAVAILABLE)); 1537 } 1538 } 1539 mbCheckingUnknownFont = false; 1540 } 1541 1542 void SvxFontNameBox_Base::Update( const css::awt::FontDescriptor* pFontDesc ) 1543 { 1544 if ( pFontDesc ) 1545 { 1546 aCurFont.SetFamilyName ( pFontDesc->Name ); 1547 aCurFont.SetFamily ( FontFamily( pFontDesc->Family ) ); 1548 aCurFont.SetStyleName ( pFontDesc->StyleName ); 1549 aCurFont.SetPitch ( FontPitch( pFontDesc->Pitch ) ); 1550 aCurFont.SetCharSet ( rtl_TextEncoding( pFontDesc->CharSet ) ); 1551 } 1552 OUString aCurName = aCurFont.GetFamilyName(); 1553 OUString aText = m_xWidget->get_active_text(); 1554 if (aText != aCurName) 1555 set_active_or_entry_text(aCurName); 1556 } 1557 1558 void SvxFontNameBox_Base::set_active_or_entry_text(const OUString& rText) 1559 { 1560 m_xWidget->set_active_or_entry_text(rText); 1561 CheckAndMarkUnknownFont(); 1562 } 1563 1564 IMPL_LINK_NOARG(SvxFontNameBox_Base, FocusInHdl, weld::Widget&, void) 1565 { 1566 FillList(); 1567 } 1568 1569 IMPL_LINK(SvxFontNameBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) 1570 { 1571 return DoKeyInput(rKEvt); 1572 } 1573 1574 bool SvxFontNameBox_Base::DoKeyInput(const KeyEvent& rKEvt) 1575 { 1576 bool bHandled = false; 1577 1578 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); 1579 1580 switch (nCode) 1581 { 1582 case KEY_TAB: 1583 bRelease = false; 1584 Select(true); 1585 break; 1586 1587 case KEY_ESCAPE: 1588 set_active_or_entry_text(m_xWidget->get_saved_value()); 1589 if (!m_rCtrl.IsInSidebar()) 1590 { 1591 ReleaseFocus_Impl(); 1592 bHandled = true; 1593 } 1594 EndPreview(); 1595 break; 1596 } 1597 1598 return bHandled; 1599 } 1600 1601 bool SvxFontNameBox_Impl::DoKeyInput(const KeyEvent& rKEvt) 1602 { 1603 return SvxFontNameBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt); 1604 } 1605 1606 IMPL_LINK_NOARG(SvxFontNameBox_Base, FocusOutHdl, weld::Widget&, void) 1607 { 1608 if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus 1609 { 1610 set_active_or_entry_text(m_xWidget->get_saved_value()); 1611 // send EndPreview 1612 EndPreview(); 1613 } 1614 } 1615 1616 void SvxFontNameBox_Impl::SetOptimalSize() 1617 { 1618 // set width in chars low so the size request will not be overridden 1619 m_xWidget->set_entry_width_chars(1); 1620 // tdf#132338 purely using this calculation to keep things their traditional width 1621 Size aSize(LogicToPixel(Size((COMBO_WIDTH_IN_CHARS +5) * 4, 0), MapMode(MapUnit::MapAppFont))); 1622 m_xWidget->set_size_request(aSize.Width(), -1); 1623 1624 SetSizePixel(get_preferred_size()); 1625 } 1626 1627 void SvxFontNameBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) 1628 { 1629 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && 1630 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) 1631 { 1632 SetOptimalSize(); 1633 } 1634 else if ( ( rDCEvt.GetType() == DataChangedEventType::FONTS ) || 1635 ( rDCEvt.GetType() == DataChangedEventType::DISPLAY ) ) 1636 { 1637 // The old font list in shell has likely been destroyed at this point, so we need to get 1638 // the new one before doing anything further. 1639 lcl_GetDocFontList( &pFontList, this ); 1640 } 1641 } 1642 1643 void SvxFontNameBox_Base::ReleaseFocus_Impl() 1644 { 1645 if ( !bRelease ) 1646 { 1647 bRelease = true; 1648 return; 1649 } 1650 if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) 1651 m_xFrame->getContainerWindow()->setFocus(); 1652 } 1653 1654 void SvxFontNameBox_Base::EnableControls() 1655 { 1656 bool bEnableMRU = m_aHistory.get(); 1657 sal_uInt16 nEntries = bEnableMRU ? MAX_MRU_FONTNAME_ENTRIES : 0; 1658 1659 bool bNewWYSIWYG = m_aWYSIWYG.get(); 1660 bool bOldWYSIWYG = m_xWidget->IsWYSIWYGEnabled(); 1661 1662 if (m_xWidget->get_max_mru_count() != nEntries || bNewWYSIWYG != bOldWYSIWYG) 1663 { 1664 // refill in the next GetFocus-Handler 1665 pFontList = nullptr; 1666 Clear(); 1667 m_xWidget->set_max_mru_count(nEntries); 1668 } 1669 1670 if (bNewWYSIWYG != bOldWYSIWYG) 1671 m_xWidget->EnableWYSIWYG(bNewWYSIWYG); 1672 } 1673 1674 IMPL_LINK(SvxFontNameBox_Base, SelectHdl, weld::ComboBox&, rCombo, void) 1675 { 1676 Select(rCombo.changed_by_direct_pick()); // only when picked from the list 1677 } 1678 1679 IMPL_LINK_NOARG(SvxFontNameBox_Base, ActivateHdl, weld::ComboBox&, bool) 1680 { 1681 Select(true); 1682 return true; 1683 } 1684 1685 void SvxFontNameBox_Base::Select(bool bNonTravelSelect) 1686 { 1687 Sequence< PropertyValue > aArgs( 1 ); 1688 auto pArgs = aArgs.getArray(); 1689 std::unique_ptr<SvxFontItem> pFontItem; 1690 if ( pFontList ) 1691 { 1692 FontMetric aFontMetric( pFontList->Get(m_xWidget->get_active_text(), 1693 aCurFont.GetWeight(), 1694 aCurFont.GetItalic() ) ); 1695 aCurFont = aFontMetric; 1696 1697 pFontItem.reset( new SvxFontItem( aFontMetric.GetFamilyType(), 1698 aFontMetric.GetFamilyName(), 1699 aFontMetric.GetStyleName(), 1700 aFontMetric.GetPitch(), 1701 aFontMetric.GetCharSet(), 1702 SID_ATTR_CHAR_FONT ) ); 1703 1704 Any a; 1705 pFontItem->QueryValue( a ); 1706 pArgs[0].Value = a; 1707 } 1708 1709 if (bNonTravelSelect) 1710 { 1711 CheckAndMarkUnknownFont(); 1712 // #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. 1713 // This instance may be deleted in the meantime (i.e. when a dialog is opened 1714 // while in Dispatch()), accessing members will crash in this case. 1715 ReleaseFocus_Impl(); 1716 EndPreview(); 1717 if (pFontItem) 1718 { 1719 pArgs[0].Name = "CharFontName"; 1720 SfxToolBoxControl::Dispatch( m_xDispatchProvider, 1721 ".uno:CharFontName", 1722 aArgs ); 1723 } 1724 } 1725 else 1726 { 1727 if (pFontItem) 1728 { 1729 pArgs[0].Name = "CharPreviewFontName"; 1730 SfxToolBoxControl::Dispatch( m_xDispatchProvider, 1731 ".uno:CharPreviewFontName", 1732 aArgs ); 1733 } 1734 } 1735 } 1736 1737 IMPL_LINK(SvxFontNameBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void) 1738 { 1739 { 1740 auto entriesNode = rJsonWriter.startNode("entries"); 1741 for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i) 1742 { 1743 auto entryNode = rJsonWriter.startNode(""); 1744 rJsonWriter.put("", m_xWidget->get_text(i)); 1745 } 1746 } 1747 1748 int nSelectedEntry = m_xWidget->get_active(); 1749 rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nSelectedEntry == -1 ? 0 : 1)); 1750 1751 { 1752 auto selectedNode = rJsonWriter.startNode("selectedEntries"); 1753 if (nSelectedEntry != -1) 1754 { 1755 auto entryNode = rJsonWriter.startNode(""); 1756 rJsonWriter.put("", m_xWidget->get_text(nSelectedEntry)); 1757 } 1758 } 1759 1760 rJsonWriter.put("command", ".uno:CharFontName"); 1761 } 1762 1763 ColorWindow::ColorWindow(const OUString& rCommand, 1764 std::shared_ptr<PaletteManager> const & rPaletteManager, 1765 ColorStatus& rColorStatus, 1766 sal_uInt16 nSlotId, 1767 const Reference< XFrame >& rFrame, 1768 const MenuOrToolMenuButton& rMenuButton, 1769 TopLevelParentFunction const& rTopLevelParentFunction, 1770 ColorSelectFunction const & rColorSelectFunction) 1771 : WeldToolbarPopup(rFrame, rMenuButton.get_widget(), "svx/ui/colorwindow.ui", "palette_popup_window") 1772 , theSlotId(nSlotId) 1773 , maCommand(rCommand) 1774 , maMenuButton(rMenuButton) 1775 , mxPaletteManager(rPaletteManager) 1776 , mrColorStatus(rColorStatus) 1777 , maTopLevelParentFunction(rTopLevelParentFunction) 1778 , maColorSelectFunction(rColorSelectFunction) 1779 , mxColorSet(new SvxColorValueSet(m_xBuilder->weld_scrolled_window("colorsetwin", true))) 1780 , mxRecentColorSet(new SvxColorValueSet(nullptr)) 1781 , mxPaletteListBox(m_xBuilder->weld_combo_box("palette_listbox")) 1782 , mxButtonAutoColor(m_xBuilder->weld_button("auto_color_button")) 1783 , mxButtonNoneColor(m_xBuilder->weld_button("none_color_button")) 1784 , mxButtonPicker(m_xBuilder->weld_button("color_picker_button")) 1785 , mxAutomaticSeparator(m_xBuilder->weld_widget("separator4")) 1786 , mxColorSetWin(new weld::CustomWeld(*m_xBuilder, "colorset", *mxColorSet)) 1787 , mxRecentColorSetWin(new weld::CustomWeld(*m_xBuilder, "recent_colorset", *mxRecentColorSet)) 1788 , mpDefaultButton(nullptr) 1789 { 1790 mxColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); 1791 mxRecentColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); 1792 1793 switch ( theSlotId ) 1794 { 1795 case SID_ATTR_CHAR_COLOR_BACKGROUND: 1796 case SID_BACKGROUND_COLOR: 1797 case SID_ATTR_CHAR_BACK_COLOR: 1798 case SID_TABLE_CELL_BACKGROUND_COLOR: 1799 { 1800 mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_NOFILL ) ); 1801 break; 1802 } 1803 case SID_AUTHOR_COLOR: 1804 { 1805 mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_BY_AUTHOR ) ); 1806 break; 1807 } 1808 case SID_BMPMASK_COLOR: 1809 { 1810 mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_TRANSPARENT ) ); 1811 break; 1812 } 1813 case SID_ATTR_CHAR_COLOR: 1814 case SID_ATTR_CHAR_COLOR2: 1815 case SID_EXTRUSION_3D_COLOR: 1816 { 1817 mxButtonAutoColor->set_label(EditResId(RID_SVXSTR_AUTOMATIC)); 1818 break; 1819 } 1820 case SID_FM_CTL_PROPERTIES: 1821 { 1822 mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_DEFAULT ) ); 1823 break; 1824 } 1825 default: 1826 { 1827 mxButtonAutoColor->hide(); 1828 mxAutomaticSeparator->hide(); 1829 break; 1830 } 1831 } 1832 1833 mxPaletteListBox->connect_changed(LINK(this, ColorWindow, SelectPaletteHdl)); 1834 std::vector<OUString> aPaletteList = mxPaletteManager->GetPaletteList(); 1835 mxPaletteListBox->freeze(); 1836 for (const auto& rPalette : aPaletteList) 1837 mxPaletteListBox->append_text(rPalette); 1838 mxPaletteListBox->thaw(); 1839 OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() ); 1840 mxPaletteListBox->set_active_text(aPaletteName); 1841 const int nSelectedEntry(mxPaletteListBox->get_active()); 1842 if (nSelectedEntry != -1) 1843 mxPaletteManager->SetPalette(nSelectedEntry); 1844 1845 mxButtonAutoColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl)); 1846 mxButtonNoneColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl)); 1847 mxButtonPicker->connect_clicked(LINK(this, ColorWindow, OpenPickerClickHdl)); 1848 1849 mxColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl)); 1850 mxRecentColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl)); 1851 m_xTopLevel->set_help_id(HID_POPUP_COLOR); 1852 mxColorSet->SetHelpId(HID_POPUP_COLOR_CTRL); 1853 1854 mxPaletteManager->ReloadColorSet(*mxColorSet); 1855 const sal_uInt32 nMaxItems(SvxColorValueSet::getMaxRowCount() * SvxColorValueSet::getColumnCount()); 1856 Size aSize = mxColorSet->layoutAllVisible(nMaxItems); 1857 mxColorSet->set_size_request(aSize.Width(), aSize.Height()); 1858 1859 mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); 1860 aSize = mxRecentColorSet->layoutAllVisible(mxPaletteManager->GetRecentColorCount()); 1861 mxRecentColorSet->set_size_request(aSize.Width(), aSize.Height()); 1862 1863 AddStatusListener( ".uno:ColorTableState" ); 1864 AddStatusListener( maCommand ); 1865 if ( maCommand == ".uno:FrameLineColor" ) 1866 { 1867 AddStatusListener( ".uno:BorderTLBR" ); 1868 AddStatusListener( ".uno:BorderBLTR" ); 1869 } 1870 } 1871 1872 void ColorWindow::GrabFocus() 1873 { 1874 if (mxColorSet->IsNoSelection() && mpDefaultButton) 1875 mpDefaultButton->grab_focus(); 1876 else 1877 mxColorSet->GrabFocus(); 1878 } 1879 1880 void ColorWindow::ShowNoneButton() 1881 { 1882 mxButtonNoneColor->show(); 1883 } 1884 1885 ColorWindow::~ColorWindow() 1886 { 1887 } 1888 1889 NamedColor ColorWindow::GetSelectEntryColor(ValueSet const * pColorSet) 1890 { 1891 Color aColor = pColorSet->GetItemColor(pColorSet->GetSelectedItemId()); 1892 OUString sColorName = pColorSet->GetItemText(pColorSet->GetSelectedItemId()); 1893 return std::make_pair(aColor, sColorName); 1894 } 1895 1896 namespace 1897 { 1898 NamedColor GetAutoColor(sal_uInt16 nSlotId) 1899 { 1900 Color aColor; 1901 OUString sColorName; 1902 switch (nSlotId) 1903 { 1904 case SID_ATTR_CHAR_COLOR_BACKGROUND: 1905 case SID_BACKGROUND_COLOR: 1906 case SID_ATTR_CHAR_BACK_COLOR: 1907 case SID_TABLE_CELL_BACKGROUND_COLOR: 1908 aColor = COL_TRANSPARENT; 1909 sColorName = SvxResId(RID_SVXSTR_NOFILL); 1910 break; 1911 case SID_AUTHOR_COLOR: 1912 aColor = COL_TRANSPARENT; 1913 sColorName = SvxResId(RID_SVXSTR_BY_AUTHOR); 1914 break; 1915 case SID_BMPMASK_COLOR: 1916 aColor = COL_TRANSPARENT; 1917 sColorName = SvxResId(RID_SVXSTR_TRANSPARENT); 1918 break; 1919 case SID_FM_CTL_PROPERTIES: 1920 aColor = COL_TRANSPARENT; 1921 sColorName = SvxResId(RID_SVXSTR_DEFAULT); 1922 break; 1923 case SID_ATTR_CHAR_COLOR: 1924 case SID_ATTR_CHAR_COLOR2: 1925 case SID_EXTRUSION_3D_COLOR: 1926 default: 1927 aColor = COL_AUTO; 1928 sColorName = EditResId(RID_SVXSTR_AUTOMATIC); 1929 break; 1930 } 1931 1932 return std::make_pair(aColor, sColorName); 1933 } 1934 1935 NamedColor GetNoneColor() 1936 { 1937 return std::make_pair(COL_NONE_COLOR, comphelper::LibreOfficeKit::isActive() ? SvxResId(RID_SVXSTR_INVISIBLE) 1938 : SvxResId(RID_SVXSTR_NONE)); 1939 } 1940 } 1941 1942 NamedColor ColorWindow::GetSelectEntryColor() const 1943 { 1944 if (!mxColorSet->IsNoSelection()) 1945 return GetSelectEntryColor(mxColorSet.get()); 1946 if (!mxRecentColorSet->IsNoSelection()) 1947 return GetSelectEntryColor(mxRecentColorSet.get()); 1948 if (mxButtonNoneColor.get() == mpDefaultButton) 1949 return GetNoneColor(); 1950 return GetAutoColor(); 1951 } 1952 1953 IMPL_LINK(ColorWindow, SelectHdl, ValueSet*, pColorSet, void) 1954 { 1955 NamedColor aNamedColor = GetSelectEntryColor(pColorSet); 1956 1957 if (pColorSet != mxRecentColorSet.get()) 1958 { 1959 mxPaletteManager->AddRecentColor(aNamedColor.first, aNamedColor.second); 1960 if (!maMenuButton.get_active()) 1961 mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); 1962 } 1963 1964 maSelectedLink.Call(aNamedColor); 1965 1966 // deliberate take a copy here in case maMenuButton.set_inactive 1967 // triggers a callback that destroys ourself 1968 ColorSelectFunction aColorSelectFunction(maColorSelectFunction); 1969 OUString sCommand(maCommand); 1970 // Same for querying IsTheme early. 1971 bool bThemePaletteSelected = mxPaletteManager->IsThemePaletteSelected(); 1972 sal_uInt16 nSelectedItemId = pColorSet->GetSelectedItemId(); 1973 1974 maMenuButton.set_inactive(); 1975 1976 auto aNamedThemedColor = svx::NamedThemedColor::FromNamedColor(aNamedColor); 1977 if (bThemePaletteSelected) 1978 { 1979 PaletteManager::GetThemeIndexLumModOff(nSelectedItemId, aNamedThemedColor.m_nThemeIndex, 1980 aNamedThemedColor.m_nLumMod, 1981 aNamedThemedColor.m_nLumOff); 1982 } 1983 aColorSelectFunction(sCommand, aNamedThemedColor); 1984 } 1985 1986 IMPL_LINK_NOARG(ColorWindow, SelectPaletteHdl, weld::ComboBox&, void) 1987 { 1988 int nPos = mxPaletteListBox->get_active(); 1989 mxPaletteManager->SetPalette( nPos ); 1990 mxPaletteManager->ReloadColorSet(*mxColorSet); 1991 mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount()); 1992 } 1993 1994 NamedColor ColorWindow::GetAutoColor() const 1995 { 1996 return ::GetAutoColor(theSlotId); 1997 } 1998 1999 IMPL_LINK(ColorWindow, AutoColorClickHdl, weld::Button&, rButton, void) 2000 { 2001 NamedColor aNamedColor = &rButton == mxButtonAutoColor.get() ? GetAutoColor() : GetNoneColor(); 2002 2003 mxColorSet->SetNoSelection(); 2004 mxRecentColorSet->SetNoSelection(); 2005 mpDefaultButton = &rButton; 2006 2007 maSelectedLink.Call(aNamedColor); 2008 2009 // deliberate take a copy here in case maMenuButton.set_inactive 2010 // triggers a callback that destroys ourself 2011 ColorSelectFunction aColorSelectFunction(maColorSelectFunction); 2012 OUString sCommand(maCommand); 2013 2014 maMenuButton.set_inactive(); 2015 2016 aColorSelectFunction(sCommand, svx::NamedThemedColor::FromNamedColor(aNamedColor)); 2017 } 2018 2019 IMPL_LINK_NOARG(ColorWindow, OpenPickerClickHdl, weld::Button&, void) 2020 { 2021 // copy before set_inactive 2022 auto nColor = GetSelectEntryColor().first; 2023 auto pParentWindow = maTopLevelParentFunction(); 2024 OUString sCommand = maCommand; 2025 std::shared_ptr<PaletteManager> xPaletteManager(mxPaletteManager); 2026 2027 maMenuButton.set_inactive(); 2028 2029 xPaletteManager->PopupColorPicker(pParentWindow, sCommand, nColor); 2030 } 2031 2032 void ColorWindow::SetNoSelection() 2033 { 2034 mxColorSet->SetNoSelection(); 2035 mxRecentColorSet->SetNoSelection(); 2036 mpDefaultButton = nullptr; 2037 } 2038 2039 bool ColorWindow::IsNoSelection() const 2040 { 2041 if (!mxColorSet->IsNoSelection()) 2042 return false; 2043 if (!mxRecentColorSet->IsNoSelection()) 2044 return false; 2045 return !mxButtonAutoColor->get_visible() && !mxButtonNoneColor->get_visible(); 2046 } 2047 2048 void ColorWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent ) 2049 { 2050 if (rEvent.FeatureURL.Complete == ".uno:ColorTableState") 2051 { 2052 if (rEvent.IsEnabled && mxPaletteManager->GetPalette() == 0) 2053 { 2054 mxPaletteManager->ReloadColorSet(*mxColorSet); 2055 mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount()); 2056 } 2057 } 2058 else 2059 { 2060 mrColorStatus.statusChanged(rEvent); 2061 SelectEntry(mrColorStatus.GetColor()); 2062 } 2063 } 2064 2065 bool ColorWindow::SelectValueSetEntry(SvxColorValueSet* pColorSet, const Color& rColor) 2066 { 2067 for (size_t i = 1; i <= pColorSet->GetItemCount(); ++i) 2068 { 2069 if (rColor == pColorSet->GetItemColor(i)) 2070 { 2071 pColorSet->SelectItem(i); 2072 return true; 2073 } 2074 } 2075 return false; 2076 } 2077 2078 void ColorWindow::SelectEntry(const NamedColor& rNamedColor) 2079 { 2080 SetNoSelection(); 2081 2082 const Color &rColor = rNamedColor.first; 2083 2084 if (mxButtonAutoColor->get_visible() && (rColor == COL_TRANSPARENT || rColor == COL_AUTO)) 2085 { 2086 mpDefaultButton = mxButtonAutoColor.get(); 2087 return; 2088 } 2089 2090 if (mxButtonNoneColor->get_visible() && rColor == COL_NONE_COLOR) 2091 { 2092 mpDefaultButton = mxButtonNoneColor.get(); 2093 return; 2094 } 2095 2096 // try current palette 2097 bool bFoundColor = SelectValueSetEntry(mxColorSet.get(), rColor); 2098 // try recently used 2099 if (!bFoundColor) 2100 bFoundColor = SelectValueSetEntry(mxRecentColorSet.get(), rColor); 2101 // if it's not there, add it there now to the end of the recently used 2102 // so its available somewhere handy, but not without trashing the 2103 // whole recently used 2104 if (!bFoundColor) 2105 { 2106 const OUString& rColorName = rNamedColor.second; 2107 mxPaletteManager->AddRecentColor(rColor, rColorName, false); 2108 mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); 2109 SelectValueSetEntry(mxRecentColorSet.get(), rColor); 2110 } 2111 } 2112 2113 void ColorWindow::SelectEntry(const Color& rColor) 2114 { 2115 OUString sColorName = "#" + rColor.AsRGBHexString().toAsciiUpperCase(); 2116 ColorWindow::SelectEntry(std::make_pair(rColor, sColorName)); 2117 } 2118 2119 ColorStatus::ColorStatus() : 2120 maColor( COL_TRANSPARENT ), 2121 maTLBRColor( COL_TRANSPARENT ), 2122 maBLTRColor( COL_TRANSPARENT ) 2123 { 2124 } 2125 2126 void ColorStatus::statusChanged( const css::frame::FeatureStateEvent& rEvent ) 2127 { 2128 Color aColor( COL_TRANSPARENT ); 2129 css::table::BorderLine2 aTable; 2130 2131 if ( rEvent.State >>= aTable ) 2132 { 2133 SvxBorderLine aLine; 2134 SvxBoxItem::LineToSvxLine( aTable, aLine, false ); 2135 if ( !aLine.isEmpty() ) 2136 aColor = aLine.GetColor(); 2137 } 2138 else 2139 rEvent.State >>= aColor; 2140 2141 if ( rEvent.FeatureURL.Path == "BorderTLBR" ) 2142 maTLBRColor = aColor; 2143 else if ( rEvent.FeatureURL.Path == "BorderBLTR" ) 2144 maBLTRColor = aColor; 2145 else 2146 maColor = aColor; 2147 } 2148 2149 Color ColorStatus::GetColor() 2150 { 2151 Color aColor( maColor ); 2152 2153 if ( maTLBRColor != COL_TRANSPARENT ) 2154 { 2155 if ( aColor != maTLBRColor && aColor != COL_TRANSPARENT ) 2156 return COL_TRANSPARENT; 2157 aColor = maTLBRColor; 2158 } 2159 2160 if ( maBLTRColor != COL_TRANSPARENT ) 2161 { 2162 if ( aColor != maBLTRColor && aColor != COL_TRANSPARENT ) 2163 return COL_TRANSPARENT; 2164 return maBLTRColor; 2165 } 2166 2167 return aColor; 2168 } 2169 2170 2171 SvxFrameWindow_Impl::SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent) 2172 : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/floatingframeborder.ui", "FloatingFrameBorder") 2173 , mxControl(pControl) 2174 , mxFrameSet(new SvxFrmValueSet_Impl) 2175 , mxFrameSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxFrameSet)) 2176 , bParagraphMode(false) 2177 , m_bIsWriter(false) 2178 { 2179 2180 // check whether the document is Writer or not 2181 if (Reference<lang::XServiceInfo> xSI{ m_xFrame->getController()->getModel(), UNO_QUERY }) 2182 m_bIsWriter = xSI->supportsService("com.sun.star.text.TextDocument"); 2183 2184 mxFrameSet->SetStyle(WB_ITEMBORDER | WB_DOUBLEBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT); 2185 AddStatusListener(".uno:BorderReducedMode"); 2186 InitImageList(); 2187 2188 /* 2189 * 1 2 3 4 5 2190 * ------------------------------------------------------ 2191 * NONE LEFT RIGHT LEFTRIGHT DIAGONALDOWN 2192 * TOP BOTTOM TOPBOTTOM OUTER DIAGONALUP 2193 * ------------------------------------------------------ 2194 * HOR HORINNER VERINNER ALL CRISSCROSS <- can be switched of via bParagraphMode 2195 */ 2196 2197 sal_uInt16 i = 0; 2198 2199 // diagonal borders available only for Calc. 2200 // Therefore, Calc uses 10 border types while 2201 // Writer uses 8 of them - for a single cell. 2202 for ( i=1; i < (m_bIsWriter ? 9 : 11); i++ ) 2203 mxFrameSet->InsertItem(i, Image(aImgVec[i-1].first), aImgVec[i-1].second); 2204 2205 //bParagraphMode should have been set in StateChanged 2206 if ( !bParagraphMode ) 2207 // when multiple cell selected: 2208 // Writer has 12 border types and Calc has 15 of them. 2209 for ( i = (m_bIsWriter ? 9 : 11); i < (m_bIsWriter ? 13 : 16); i++ ) 2210 mxFrameSet->InsertItem(i, Image(aImgVec[i-1].first), aImgVec[i-1].second); 2211 2212 // adjust frame column for Writer 2213 sal_uInt16 colCount = m_bIsWriter ? 4 : 5; 2214 mxFrameSet->SetColCount( colCount ); 2215 mxFrameSet->SetSelectHdl( LINK( this, SvxFrameWindow_Impl, SelectHdl ) ); 2216 CalcSizeValueSet(); 2217 2218 mxFrameSet->SetHelpId( HID_POPUP_FRAME ); 2219 mxFrameSet->SetAccessibleName( SvxResId(RID_SVXSTR_FRAME) ); 2220 } 2221 2222 namespace { 2223 2224 enum class FrmValidFlags { 2225 NONE = 0x00, 2226 Left = 0x01, 2227 Right = 0x02, 2228 Top = 0x04, 2229 Bottom = 0x08, 2230 HInner = 0x10, 2231 VInner = 0x20, 2232 AllMask = 0x3f, 2233 }; 2234 2235 } 2236 2237 namespace o3tl { 2238 template<> struct typed_flags<FrmValidFlags> : is_typed_flags<FrmValidFlags, 0x3f> {}; 2239 } 2240 2241 // By default unset lines remain unchanged. 2242 // Via Shift unset lines are reset 2243 2244 IMPL_LINK_NOARG(SvxFrameWindow_Impl, SelectHdl, ValueSet*, void) 2245 { 2246 SvxBoxItem aBorderOuter( SID_ATTR_BORDER_OUTER ); 2247 SvxBoxInfoItem aBorderInner( SID_ATTR_BORDER_INNER ); 2248 SvxBorderLine theDefLine; 2249 2250 // diagonal down border 2251 SvxBorderLine dDownBorderLine(nullptr, SvxBorderLineWidth::Hairline); 2252 SvxLineItem dDownLineItem(SID_ATTR_BORDER_DIAG_TLBR); 2253 2254 // diagonal up border 2255 SvxBorderLine dUpBorderLine(nullptr, SvxBorderLineWidth::Hairline); 2256 SvxLineItem dUpLineItem(SID_ATTR_BORDER_DIAG_BLTR); 2257 2258 bool bIsDiagonalBorder = false; 2259 2260 SvxBorderLine *pLeft = nullptr, 2261 *pRight = nullptr, 2262 *pTop = nullptr, 2263 *pBottom = nullptr; 2264 sal_uInt16 nSel = mxFrameSet->GetSelectedItemId(); 2265 sal_uInt16 nModifier = mxFrameSet->GetModifier(); 2266 FrmValidFlags nValidFlags = FrmValidFlags::NONE; 2267 2268 // tdf#48622, tdf#145828 use correct default to create intended 0.75pt 2269 // cell border using the border formatting tool in the standard toolbar 2270 theDefLine.GuessLinesWidths(theDefLine.GetBorderLineStyle(), SvxBorderLineWidth::Thin); 2271 2272 // nSel has 15 cases which means 15 border 2273 // types for Calc. But Writer uses only 12 2274 // of them - when diagonal borders excluded. 2275 if (m_bIsWriter) 2276 { 2277 // add appropriate increments 2278 // to match the correct borders. 2279 if (nSel > 8) { nSel += 2; } 2280 else if (nSel > 4) { nSel++; } 2281 } 2282 2283 switch ( nSel ) 2284 { 2285 case 1: nValidFlags |= FrmValidFlags::AllMask; 2286 // set nullptr to remove diagonal lines 2287 dDownLineItem.SetLine(nullptr); 2288 dUpLineItem.SetLine(nullptr); 2289 SetDiagonalDownBorder(dDownLineItem); 2290 SetDiagonalUpBorder(dUpLineItem); 2291 break; // NONE 2292 case 2: pLeft = &theDefLine; 2293 nValidFlags |= FrmValidFlags::Left; 2294 break; // LEFT 2295 case 3: pRight = &theDefLine; 2296 nValidFlags |= FrmValidFlags::Right; 2297 break; // RIGHT 2298 case 4: pLeft = pRight = &theDefLine; 2299 nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left; 2300 break; // LEFTRIGHT 2301 case 5: dDownLineItem.SetLine(&dDownBorderLine); 2302 SetDiagonalDownBorder(dDownLineItem); 2303 bIsDiagonalBorder = true; 2304 break; // DIAGONAL DOWN 2305 case 6: pTop = &theDefLine; 2306 nValidFlags |= FrmValidFlags::Top; 2307 break; // TOP 2308 case 7: pBottom = &theDefLine; 2309 nValidFlags |= FrmValidFlags::Bottom; 2310 break; // BOTTOM 2311 case 8: pTop = pBottom = &theDefLine; 2312 nValidFlags |= FrmValidFlags::Bottom|FrmValidFlags::Top; 2313 break; // TOPBOTTOM 2314 case 9: pLeft = pRight = pTop = pBottom = &theDefLine; 2315 nValidFlags |= FrmValidFlags::Left | FrmValidFlags::Right | FrmValidFlags::Top | FrmValidFlags::Bottom; 2316 break; // OUTER 2317 case 10: 2318 dUpLineItem.SetLine(&dUpBorderLine); 2319 SetDiagonalUpBorder(dUpLineItem); 2320 bIsDiagonalBorder = true; 2321 break; // DIAGONAL UP 2322 2323 // Inner Table: 2324 case 11: // HOR 2325 pTop = pBottom = &theDefLine; 2326 aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); 2327 aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); 2328 nValidFlags |= FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom; 2329 break; 2330 2331 case 12: // HORINNER 2332 pLeft = pRight = pTop = pBottom = &theDefLine; 2333 aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); 2334 aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); 2335 nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom; 2336 break; 2337 2338 case 13: // VERINNER 2339 pLeft = pRight = pTop = pBottom = &theDefLine; 2340 aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::HORI ); 2341 aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT ); 2342 nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::VInner|FrmValidFlags::Top|FrmValidFlags::Bottom; 2343 break; 2344 2345 case 14: // ALL 2346 pLeft = pRight = pTop = pBottom = &theDefLine; 2347 aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); 2348 aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT ); 2349 nValidFlags |= FrmValidFlags::AllMask; 2350 break; 2351 2352 case 15: 2353 // set both diagonal lines to draw criss-cross line 2354 dDownLineItem.SetLine(&dDownBorderLine); 2355 dUpLineItem.SetLine(&dUpBorderLine); 2356 2357 SetDiagonalDownBorder(dDownLineItem); 2358 SetDiagonalUpBorder(dUpLineItem); 2359 bIsDiagonalBorder = true; 2360 break; // CRISS-CROSS 2361 2362 default: 2363 break; 2364 } 2365 2366 // if diagonal borders selected, 2367 // no need to execute this block 2368 if (!bIsDiagonalBorder) 2369 { 2370 aBorderOuter.SetLine( pLeft, SvxBoxItemLine::LEFT ); 2371 aBorderOuter.SetLine( pRight, SvxBoxItemLine::RIGHT ); 2372 aBorderOuter.SetLine( pTop, SvxBoxItemLine::TOP ); 2373 aBorderOuter.SetLine( pBottom, SvxBoxItemLine::BOTTOM ); 2374 2375 if(nModifier == KEY_SHIFT) 2376 nValidFlags |= FrmValidFlags::AllMask; 2377 aBorderInner.SetValid( SvxBoxInfoItemValidFlags::TOP, bool(nValidFlags&FrmValidFlags::Top )); 2378 aBorderInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, bool(nValidFlags&FrmValidFlags::Bottom )); 2379 aBorderInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, bool(nValidFlags&FrmValidFlags::Left)); 2380 aBorderInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, bool(nValidFlags&FrmValidFlags::Right )); 2381 aBorderInner.SetValid( SvxBoxInfoItemValidFlags::HORI, bool(nValidFlags&FrmValidFlags::HInner )); 2382 aBorderInner.SetValid( SvxBoxInfoItemValidFlags::VERT, bool(nValidFlags&FrmValidFlags::VInner)); 2383 aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE ); 2384 aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISABLE, false ); 2385 2386 Any a1, a2; 2387 aBorderOuter.QueryValue( a1 ); 2388 aBorderInner.QueryValue( a2 ); 2389 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("OuterBorder", a1), 2390 comphelper::makePropertyValue("InnerBorder", a2) }; 2391 2392 mxControl->dispatchCommand( ".uno:SetBorderStyle", aArgs ); 2393 } 2394 2395 if (mxFrameSet) 2396 { 2397 /* #i33380# Moved the following line above the Dispatch() call. 2398 This instance may be deleted in the meantime (i.e. when a dialog is opened 2399 while in Dispatch()), accessing members will crash in this case. */ 2400 mxFrameSet->SetNoSelection(); 2401 } 2402 2403 mxControl->EndPopupMode(); 2404 } 2405 2406 void SvxFrameWindow_Impl::SetDiagonalDownBorder(const SvxLineItem& dDownLineItem) 2407 { 2408 // apply diagonal down border 2409 Any a; 2410 dDownLineItem.QueryValue(a); 2411 Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue("BorderTLBR", a) }; 2412 2413 mxControl->dispatchCommand(".uno:BorderTLBR", aArgs); 2414 } 2415 2416 void SvxFrameWindow_Impl::SetDiagonalUpBorder(const SvxLineItem& dUpLineItem) 2417 { 2418 // apply diagonal up border 2419 Any a; 2420 dUpLineItem.QueryValue(a); 2421 Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue("BorderBLTR", a) }; 2422 2423 mxControl->dispatchCommand(".uno:BorderBLTR", aArgs); 2424 } 2425 2426 void SvxFrameWindow_Impl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) 2427 { 2428 if ( rEvent.FeatureURL.Complete != ".uno:BorderReducedMode" ) 2429 return; 2430 2431 bool bValue; 2432 if ( !(rEvent.State >>= bValue) ) 2433 return; 2434 2435 bParagraphMode = bValue; 2436 //initial calls mustn't insert or remove elements 2437 if(!mxFrameSet->GetItemCount()) 2438 return; 2439 2440 // set 12 border types for Writer, otherwise 15 for Calc. 2441 bool bTableMode = ( mxFrameSet->GetItemCount() == static_cast<size_t>(m_bIsWriter ? 12 : 15) ); 2442 bool bResize = false; 2443 2444 if ( bTableMode && bParagraphMode ) 2445 { 2446 for ( sal_uInt16 i = (m_bIsWriter ? 9 : 11); i < (m_bIsWriter ? 13 : 16); i++ ) 2447 mxFrameSet->RemoveItem(i); 2448 bResize = true; 2449 } 2450 else if ( !bTableMode && !bParagraphMode ) 2451 { 2452 for ( sal_uInt16 i = (m_bIsWriter ? 9 : 11); i < (m_bIsWriter ? 13 : 16); i++ ) 2453 mxFrameSet->InsertItem(i, Image(aImgVec[i-1].first), aImgVec[i-1].second); 2454 bResize = true; 2455 } 2456 2457 if ( bResize ) 2458 { 2459 CalcSizeValueSet(); 2460 } 2461 } 2462 2463 void SvxFrameWindow_Impl::CalcSizeValueSet() 2464 { 2465 weld::DrawingArea* pDrawingArea = mxFrameSet->GetDrawingArea(); 2466 const OutputDevice& rDevice = pDrawingArea->get_ref_device(); 2467 Size aItemSize( 20 * rDevice.GetDPIScaleFactor(), 20 * rDevice.GetDPIScaleFactor() ); 2468 Size aSize = mxFrameSet->CalcWindowSizePixel( aItemSize ); 2469 pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); 2470 mxFrameSet->SetOutputSizePixel(aSize); 2471 } 2472 2473 void SvxFrameWindow_Impl::InitImageList() 2474 { 2475 if (m_bIsWriter) 2476 { 2477 // Writer-specific aImgVec. 2478 // Since Writer doesn't have diagonal borders, 2479 // we have to use 12 border types here. 2480 aImgVec = { 2481 {BitmapEx(RID_SVXBMP_FRAME1), SvxResId(RID_SVXSTR_TABLE_PRESET_NONE)}, 2482 {BitmapEx(RID_SVXBMP_FRAME2), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYLEFT)}, 2483 {BitmapEx(RID_SVXBMP_FRAME3), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYRIGHT)}, 2484 {BitmapEx(RID_SVXBMP_FRAME4), SvxResId(RID_SVXSTR_PARA_PRESET_LEFTRIGHT)}, 2485 2486 {BitmapEx(RID_SVXBMP_FRAME5), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYTOP)}, 2487 {BitmapEx(RID_SVXBMP_FRAME6), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYTBOTTOM)}, 2488 {BitmapEx(RID_SVXBMP_FRAME7), SvxResId(RID_SVXSTR_PARA_PRESET_TOPBOTTOM)}, 2489 {BitmapEx(RID_SVXBMP_FRAME8), SvxResId(RID_SVXSTR_TABLE_PRESET_ONLYOUTER)}, 2490 2491 {BitmapEx(RID_SVXBMP_FRAME9), SvxResId(RID_SVXSTR_PARA_PRESET_TOPBOTTOMHORI)}, 2492 {BitmapEx(RID_SVXBMP_FRAME10), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERHORI)}, 2493 {BitmapEx(RID_SVXBMP_FRAME11), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERVERI)}, 2494 {BitmapEx(RID_SVXBMP_FRAME12), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERALL)} 2495 }; 2496 } 2497 else 2498 { 2499 // Calc has diagonal borders feature. 2500 // Therefore use additional 3 diagonal border types, 2501 // which make border types 15 in total. 2502 aImgVec = { 2503 {BitmapEx(RID_SVXBMP_FRAME1), SvxResId(RID_SVXSTR_TABLE_PRESET_NONE)}, 2504 {BitmapEx(RID_SVXBMP_FRAME2), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYLEFT)}, 2505 {BitmapEx(RID_SVXBMP_FRAME3), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYRIGHT)}, 2506 {BitmapEx(RID_SVXBMP_FRAME4), SvxResId(RID_SVXSTR_PARA_PRESET_LEFTRIGHT)}, 2507 {BitmapEx(RID_SVXBMP_FRAME14), SvxResId(RID_SVXSTR_PARA_PRESET_DIAGONALDOWN)}, // diagonal down border 2508 2509 {BitmapEx(RID_SVXBMP_FRAME5), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYTOP)}, 2510 {BitmapEx(RID_SVXBMP_FRAME6), SvxResId(RID_SVXSTR_PARA_PRESET_ONLYTBOTTOM)}, 2511 {BitmapEx(RID_SVXBMP_FRAME7), SvxResId(RID_SVXSTR_PARA_PRESET_TOPBOTTOM)}, 2512 {BitmapEx(RID_SVXBMP_FRAME8), SvxResId(RID_SVXSTR_TABLE_PRESET_ONLYOUTER)}, 2513 {BitmapEx(RID_SVXBMP_FRAME13), SvxResId(RID_SVXSTR_PARA_PRESET_DIAGONALUP)}, // diagonal up border 2514 2515 {BitmapEx(RID_SVXBMP_FRAME9), SvxResId(RID_SVXSTR_PARA_PRESET_TOPBOTTOMHORI)}, 2516 {BitmapEx(RID_SVXBMP_FRAME10), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERHORI)}, 2517 {BitmapEx(RID_SVXBMP_FRAME11), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERVERI)}, 2518 {BitmapEx(RID_SVXBMP_FRAME12), SvxResId(RID_SVXSTR_TABLE_PRESET_OUTERALL)}, 2519 {BitmapEx(RID_SVXBMP_FRAME15), SvxResId(RID_SVXSTR_PARA_PRESET_CRISSCROSS)} // criss-cross border 2520 }; 2521 } 2522 } 2523 2524 static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ ) 2525 { 2526 return SvxBorderLine::threeDMediumColor( aMain ); 2527 } 2528 2529 SvxLineWindow_Impl::SvxLineWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent) 2530 : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/floatingframeborder.ui", "FloatingFrameBorder") 2531 , m_xControl(pControl) 2532 , m_xLineStyleLb(new LineListBox) 2533 , m_xLineStyleLbWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xLineStyleLb)) 2534 , m_bIsWriter(false) 2535 { 2536 try 2537 { 2538 Reference< lang::XServiceInfo > xServices(m_xFrame->getController()->getModel(), UNO_QUERY_THROW); 2539 m_bIsWriter = xServices->supportsService("com.sun.star.text.TextDocument"); 2540 } 2541 catch(const uno::Exception& ) 2542 { 2543 } 2544 2545 m_xLineStyleLb->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); 2546 2547 m_xLineStyleLb->SetSourceUnit( FieldUnit::TWIP ); 2548 m_xLineStyleLb->SetNone( comphelper::LibreOfficeKit::isActive() ? SvxResId(RID_SVXSTR_INVISIBLE) 2549 :SvxResId(RID_SVXSTR_NONE) ); 2550 2551 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::SOLID ), SvxBorderLineStyle::SOLID ); 2552 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOTTED ), SvxBorderLineStyle::DOTTED ); 2553 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DASHED ), SvxBorderLineStyle::DASHED ); 2554 2555 // Double lines 2556 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOUBLE ), SvxBorderLineStyle::DOUBLE ); 2557 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_SMALLGAP ), SvxBorderLineStyle::THINTHICK_SMALLGAP, 20 ); 2558 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_MEDIUMGAP ), SvxBorderLineStyle::THINTHICK_MEDIUMGAP ); 2559 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_LARGEGAP ), SvxBorderLineStyle::THINTHICK_LARGEGAP ); 2560 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_SMALLGAP ), SvxBorderLineStyle::THICKTHIN_SMALLGAP, 20 ); 2561 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ), SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ); 2562 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_LARGEGAP ), SvxBorderLineStyle::THICKTHIN_LARGEGAP ); 2563 2564 // Engraved / Embossed 2565 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::EMBOSSED ), SvxBorderLineStyle::EMBOSSED, 15, 2566 &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor, 2567 &lcl_mediumColor ); 2568 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::ENGRAVED ), SvxBorderLineStyle::ENGRAVED, 15, 2569 &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor, 2570 &lcl_mediumColor ); 2571 2572 // Inset / Outset 2573 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::OUTSET ), SvxBorderLineStyle::OUTSET, 10, 2574 &SvxBorderLine::lightColor, &SvxBorderLine::darkColor ); 2575 m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::INSET ), SvxBorderLineStyle::INSET, 10, 2576 &SvxBorderLine::darkColor, &SvxBorderLine::lightColor ); 2577 Size aSize = m_xLineStyleLb->SetWidth( 20 ); // 1pt by default 2578 2579 m_xLineStyleLb->SetSelectHdl( LINK( this, SvxLineWindow_Impl, SelectHdl ) ); 2580 2581 m_xContainer->set_help_id(HID_POPUP_LINE); 2582 2583 aSize.AdjustWidth(6); 2584 aSize.AdjustHeight(6); 2585 aSize = m_xLineStyleLb->CalcWindowSizePixel(aSize); 2586 m_xLineStyleLb->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); 2587 m_xLineStyleLb->SetOutputSizePixel(aSize); 2588 } 2589 2590 IMPL_LINK_NOARG(SvxLineWindow_Impl, SelectHdl, ValueSet*, void) 2591 { 2592 SvxLineItem aLineItem( SID_FRAME_LINESTYLE ); 2593 SvxBorderLineStyle nStyle = m_xLineStyleLb->GetSelectEntryStyle(); 2594 2595 if ( m_xLineStyleLb->GetSelectItemPos( ) > 0 ) 2596 { 2597 SvxBorderLine aTmp; 2598 aTmp.SetBorderLineStyle( nStyle ); 2599 aTmp.SetWidth( SvxBorderLineWidth::Thin ); // TODO Make it depend on a width field 2600 aLineItem.SetLine( &aTmp ); 2601 } 2602 else 2603 aLineItem.SetLine( nullptr ); 2604 2605 Any a; 2606 aLineItem.QueryValue( a, m_bIsWriter ? CONVERT_TWIPS : 0 ); 2607 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("LineStyle", a) }; 2608 2609 m_xControl->dispatchCommand( ".uno:LineStyle", aArgs ); 2610 2611 m_xControl->EndPopupMode(); 2612 } 2613 2614 SfxStyleControllerItem_Impl::SfxStyleControllerItem_Impl( 2615 const Reference< XDispatchProvider >& rDispatchProvider, 2616 sal_uInt16 nSlotId, // Family-ID 2617 const OUString& rCommand, // .uno: command bound to this item 2618 SvxStyleToolBoxControl& rTbxCtl ) // controller instance, which the item is assigned to. 2619 : SfxStatusListener( rDispatchProvider, nSlotId, rCommand ), 2620 rControl( rTbxCtl ) 2621 { 2622 } 2623 2624 void SfxStyleControllerItem_Impl::StateChangedAtStatusListener( 2625 SfxItemState eState, const SfxPoolItem* pState ) 2626 { 2627 switch ( GetId() ) 2628 { 2629 case SID_STYLE_FAMILY1: 2630 case SID_STYLE_FAMILY2: 2631 case SID_STYLE_FAMILY3: 2632 case SID_STYLE_FAMILY4: 2633 case SID_STYLE_FAMILY5: 2634 { 2635 const sal_uInt16 nIdx = GetId() - SID_STYLE_FAMILY_START; 2636 2637 if ( SfxItemState::DEFAULT == eState ) 2638 { 2639 const SfxTemplateItem* pStateItem = 2640 dynamic_cast<const SfxTemplateItem*>( pState ); 2641 DBG_ASSERT( pStateItem != nullptr, "SfxTemplateItem expected" ); 2642 rControl.SetFamilyState( nIdx, pStateItem ); 2643 } 2644 else 2645 rControl.SetFamilyState( nIdx, nullptr ); 2646 break; 2647 } 2648 } 2649 } 2650 2651 struct SvxStyleToolBoxControl::Impl 2652 { 2653 OUString aClearForm; 2654 OUString aMore; 2655 ::std::vector< std::pair< OUString, OUString > > aDefaultStyles; 2656 bool bSpecModeWriter; 2657 bool bSpecModeCalc; 2658 2659 VclPtr<SvxStyleBox_Impl> m_xVclBox; 2660 std::unique_ptr<SvxStyleBox_Base> m_xWeldBox; 2661 SvxStyleBox_Base* m_pBox; 2662 2663 Impl() 2664 :aClearForm ( SvxResId( RID_SVXSTR_CLEARFORM ) ) 2665 ,aMore ( SvxResId( RID_SVXSTR_MORE_STYLES ) ) 2666 ,bSpecModeWriter ( false ) 2667 ,bSpecModeCalc ( false ) 2668 ,m_pBox ( nullptr ) 2669 { 2670 2671 2672 } 2673 void InitializeStyles(const Reference < frame::XModel >& xModel) 2674 { 2675 aDefaultStyles.clear(); 2676 2677 //now convert the default style names to the localized names 2678 try 2679 { 2680 Reference< style::XStyleFamiliesSupplier > xStylesSupplier( xModel, UNO_QUERY_THROW ); 2681 Reference< lang::XServiceInfo > xServices( xModel, UNO_QUERY_THROW ); 2682 bSpecModeWriter = xServices->supportsService("com.sun.star.text.TextDocument"); 2683 if(bSpecModeWriter) 2684 { 2685 Reference<container::XNameAccess> xParaStyles; 2686 xStylesSupplier->getStyleFamilies()->getByName("ParagraphStyles") >>= 2687 xParaStyles; 2688 static const std::vector<OUString> aWriterStyles = 2689 { 2690 "Standard", 2691 "Text body", 2692 "Title", 2693 "Subtitle", 2694 "Heading 1", 2695 "Heading 2", 2696 "Heading 3", 2697 "Heading 4", 2698 "Quotations", 2699 "Preformatted Text" 2700 }; 2701 for( const OUString& aStyle: aWriterStyles ) 2702 { 2703 try 2704 { 2705 Reference< beans::XPropertySet > xStyle; 2706 xParaStyles->getByName( aStyle ) >>= xStyle; 2707 OUString sName; 2708 xStyle->getPropertyValue("DisplayName") >>= sName; 2709 if( !sName.isEmpty() ) 2710 aDefaultStyles.push_back( 2711 std::pair<OUString, OUString>(aStyle, sName) ); 2712 } 2713 catch( const uno::Exception& ) 2714 {} 2715 } 2716 2717 } 2718 else if( ( 2719 bSpecModeCalc = xServices->supportsService( 2720 "com.sun.star.sheet.SpreadsheetDocument"))) 2721 { 2722 static const char* aCalcStyles[] = 2723 { 2724 "Default", 2725 "Accent 1", 2726 "Accent 2", 2727 "Accent 3", 2728 "Heading 1", 2729 "Heading 2", 2730 "Result" 2731 }; 2732 Reference<container::XNameAccess> xCellStyles; 2733 xStylesSupplier->getStyleFamilies()->getByName("CellStyles") >>= xCellStyles; 2734 for(const char* pCalcStyle : aCalcStyles) 2735 { 2736 try 2737 { 2738 const OUString sStyleName( OUString::createFromAscii( pCalcStyle ) ); 2739 if( xCellStyles->hasByName( sStyleName ) ) 2740 { 2741 Reference< beans::XPropertySet > xStyle( xCellStyles->getByName( sStyleName), UNO_QUERY_THROW ); 2742 OUString sName; 2743 xStyle->getPropertyValue("DisplayName") >>= sName; 2744 if( !sName.isEmpty() ) 2745 aDefaultStyles.push_back( 2746 std::pair<OUString, OUString>(sStyleName, sName) ); 2747 } 2748 } 2749 catch( const uno::Exception& ) 2750 {} 2751 } 2752 } 2753 } 2754 catch(const uno::Exception& ) 2755 { 2756 OSL_FAIL("error while initializing style names"); 2757 } 2758 } 2759 }; 2760 2761 // mapping table from bound items. BE CAREFUL this table must be in the 2762 // same order as the uno commands bound to the slots SID_STYLE_FAMILY1..n 2763 // MAX_FAMILIES must also be correctly set! 2764 static const char* StyleSlotToStyleCommand[MAX_FAMILIES] = 2765 { 2766 ".uno:CharStyle", 2767 ".uno:ParaStyle", 2768 ".uno:FrameStyle", 2769 ".uno:PageStyle", 2770 ".uno:TemplateFamily5" 2771 }; 2772 2773 SvxStyleToolBoxControl::SvxStyleToolBoxControl() 2774 : pImpl(new Impl) 2775 , pStyleSheetPool(nullptr) 2776 , nActFamily(0xffff) 2777 { 2778 for (sal_uInt16 i = 0; i < MAX_FAMILIES; ++i) 2779 { 2780 m_xBoundItems[i].clear(); 2781 pFamilyState[i] = nullptr; 2782 } 2783 } 2784 2785 SvxStyleToolBoxControl::~SvxStyleToolBoxControl() 2786 { 2787 } 2788 2789 void SAL_CALL SvxStyleToolBoxControl::initialize(const Sequence<Any>& rArguments) 2790 { 2791 svt::ToolboxController::initialize(rArguments); 2792 2793 // After initialize we should have a valid frame member where we can retrieve our 2794 // dispatch provider. 2795 if ( !m_xFrame.is() ) 2796 return; 2797 2798 pImpl->InitializeStyles(m_xFrame->getController()->getModel()); 2799 Reference< XDispatchProvider > xDispatchProvider( m_xFrame->getController(), UNO_QUERY ); 2800 for ( sal_uInt16 i=0; i<MAX_FAMILIES; i++ ) 2801 { 2802 m_xBoundItems[i] = new SfxStyleControllerItem_Impl( xDispatchProvider, 2803 SID_STYLE_FAMILY_START + i, 2804 OUString::createFromAscii( StyleSlotToStyleCommand[i] ), 2805 *this ); 2806 pFamilyState[i] = nullptr; 2807 } 2808 } 2809 2810 // XComponent 2811 void SAL_CALL SvxStyleToolBoxControl::dispose() 2812 { 2813 svt::ToolboxController::dispose(); 2814 2815 SolarMutexGuard aSolarMutexGuard; 2816 pImpl->m_xVclBox.disposeAndClear(); 2817 pImpl->m_xWeldBox.reset(); 2818 pImpl->m_pBox = nullptr; 2819 2820 for (rtl::Reference<SfxStyleControllerItem_Impl>& pBoundItem : m_xBoundItems) 2821 { 2822 if (!pBoundItem) 2823 continue; 2824 pBoundItem->UnBind(); 2825 } 2826 unbindListener(); 2827 2828 for( sal_uInt16 i=0; i<MAX_FAMILIES; i++ ) 2829 { 2830 if ( m_xBoundItems[i].is() ) 2831 { 2832 try 2833 { 2834 m_xBoundItems[i]->dispose(); 2835 } 2836 catch ( Exception& ) 2837 { 2838 } 2839 2840 m_xBoundItems[i].clear(); 2841 } 2842 pFamilyState[i].reset(); 2843 } 2844 pStyleSheetPool = nullptr; 2845 pImpl.reset(); 2846 } 2847 2848 OUString SvxStyleToolBoxControl::getImplementationName() 2849 { 2850 return "com.sun.star.comp.svx.StyleToolBoxControl"; 2851 } 2852 2853 sal_Bool SvxStyleToolBoxControl::supportsService( const OUString& rServiceName ) 2854 { 2855 return cppu::supportsService( this, rServiceName ); 2856 } 2857 2858 css::uno::Sequence< OUString > SvxStyleToolBoxControl::getSupportedServiceNames() 2859 { 2860 return { "com.sun.star.frame.ToolbarController" }; 2861 } 2862 2863 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * 2864 com_sun_star_comp_svx_StyleToolBoxControl_get_implementation( 2865 css::uno::XComponentContext*, 2866 css::uno::Sequence<css::uno::Any> const & ) 2867 { 2868 return cppu::acquire( new SvxStyleToolBoxControl() ); 2869 } 2870 2871 void SAL_CALL SvxStyleToolBoxControl::update() 2872 { 2873 for (rtl::Reference<SfxStyleControllerItem_Impl>& pBoundItem : m_xBoundItems) 2874 pBoundItem->ReBind(); 2875 bindListener(); 2876 } 2877 2878 SfxStyleFamily SvxStyleToolBoxControl::GetActFamily() const 2879 { 2880 switch ( nActFamily-1 + SID_STYLE_FAMILY_START ) 2881 { 2882 case SID_STYLE_FAMILY1: return SfxStyleFamily::Char; 2883 case SID_STYLE_FAMILY2: return SfxStyleFamily::Para; 2884 case SID_STYLE_FAMILY3: return SfxStyleFamily::Frame; 2885 case SID_STYLE_FAMILY4: return SfxStyleFamily::Page; 2886 case SID_STYLE_FAMILY5: return SfxStyleFamily::Pseudo; 2887 default: 2888 OSL_FAIL( "unknown style family" ); 2889 break; 2890 } 2891 return SfxStyleFamily::Para; 2892 } 2893 2894 void SvxStyleToolBoxControl::FillStyleBox() 2895 { 2896 SvxStyleBox_Base* pBox = pImpl->m_pBox; 2897 2898 DBG_ASSERT( pStyleSheetPool, "StyleSheetPool not found!" ); 2899 DBG_ASSERT( pBox, "Control not found!" ); 2900 2901 if ( !(pStyleSheetPool && pBox && nActFamily!=0xffff) ) 2902 return; 2903 2904 const SfxStyleFamily eFamily = GetActFamily(); 2905 SfxStyleSheetBase* pStyle = nullptr; 2906 bool bDoFill = false; 2907 2908 auto xIter = pStyleSheetPool->CreateIterator(eFamily, SfxStyleSearchBits::Used); 2909 sal_uInt16 nCount = xIter->Count(); 2910 2911 // Check whether fill is necessary 2912 pStyle = xIter->First(); 2913 //!!! TODO: This condition isn't right any longer, because we always show some default entries 2914 //!!! so the list doesn't show the count 2915 if ( nCount != pBox->get_count() ) 2916 { 2917 bDoFill = true; 2918 } 2919 else 2920 { 2921 sal_uInt16 i= 0; 2922 while ( pStyle && !bDoFill ) 2923 { 2924 bDoFill = ( pBox->get_text(i) != pStyle->GetName() ); 2925 pStyle = xIter->Next(); 2926 i++; 2927 } 2928 } 2929 2930 if ( !bDoFill ) 2931 return; 2932 2933 OUString aStrSel(pBox->get_active_text()); 2934 pBox->freeze(); 2935 pBox->clear(); 2936 2937 std::vector<OUString> aStyles; 2938 2939 { 2940 pStyle = xIter->Next(); 2941 2942 if( pImpl->bSpecModeWriter || pImpl->bSpecModeCalc ) 2943 { 2944 while ( pStyle ) 2945 { 2946 // sort out default styles 2947 bool bInsert = true; 2948 OUString aName( pStyle->GetName() ); 2949 for( auto const & _i: pImpl->aDefaultStyles ) 2950 { 2951 if( _i.first == aName || _i.second == aName ) 2952 { 2953 bInsert = false; 2954 break; 2955 } 2956 } 2957 2958 if( bInsert ) 2959 aStyles.push_back(aName); 2960 pStyle = xIter->Next(); 2961 } 2962 } 2963 else 2964 { 2965 while ( pStyle ) 2966 { 2967 aStyles.push_back(pStyle->GetName()); 2968 pStyle = xIter->Next(); 2969 } 2970 } 2971 } 2972 2973 if (pImpl->bSpecModeWriter || pImpl->bSpecModeCalc) 2974 { 2975 pBox->append_text(pImpl->aClearForm); 2976 pBox->insert_separator(1, "separator"); 2977 2978 // insert default styles 2979 for (const auto &rStyle : pImpl->aDefaultStyles) 2980 pBox->append_text(rStyle.second); 2981 } 2982 2983 std::sort(aStyles.begin(), aStyles.end()); 2984 2985 for (const auto& rStyle : aStyles) 2986 pBox->append_text(rStyle); 2987 2988 if ((pImpl->bSpecModeWriter || pImpl->bSpecModeCalc) && !comphelper::LibreOfficeKit::isActive()) 2989 pBox->append_text(pImpl->aMore); 2990 2991 pBox->thaw(); 2992 pBox->set_active_or_entry_text(aStrSel); 2993 pBox->SetFamily( eFamily ); 2994 } 2995 2996 void SvxStyleToolBoxControl::SelectStyle( const OUString& rStyleName ) 2997 { 2998 SvxStyleBox_Base* pBox = pImpl->m_pBox; 2999 DBG_ASSERT( pBox, "Control not found!" ); 3000 3001 if ( !pBox ) 3002 return; 3003 3004 OUString aStrSel(pBox->get_active_text()); 3005 3006 if ( !rStyleName.isEmpty() ) 3007 { 3008 OUString aNewStyle = rStyleName; 3009 3010 auto aFound = std::find_if(pImpl->aDefaultStyles.begin(), pImpl->aDefaultStyles.end(), 3011 [rStyleName] (auto it) { return it.first == rStyleName || it.second == rStyleName; } 3012 ); 3013 3014 if (aFound != pImpl->aDefaultStyles.end()) 3015 aNewStyle = aFound->second; 3016 3017 if ( aNewStyle != aStrSel ) 3018 pBox->set_active_or_entry_text( aNewStyle ); 3019 } 3020 else 3021 pBox->set_active(-1); 3022 pBox->save_value(); 3023 } 3024 3025 void SvxStyleToolBoxControl::Update() 3026 { 3027 SfxStyleSheetBasePool* pPool = nullptr; 3028 SfxObjectShell* pDocShell = SfxObjectShell::Current(); 3029 3030 if ( pDocShell ) 3031 pPool = pDocShell->GetStyleSheetPool(); 3032 3033 sal_uInt16 i; 3034 for ( i=0; i<MAX_FAMILIES; i++ ) 3035 if( pFamilyState[i] ) 3036 break; 3037 3038 if ( i==MAX_FAMILIES || !pPool ) 3039 { 3040 pStyleSheetPool = pPool; 3041 return; 3042 } 3043 3044 3045 const SfxTemplateItem* pItem = nullptr; 3046 3047 if ( nActFamily == 0xffff || nullptr == (pItem = pFamilyState[nActFamily-1].get()) ) 3048 // Current range not within allowed ranges or default 3049 { 3050 pStyleSheetPool = pPool; 3051 nActFamily = 2; 3052 3053 pItem = pFamilyState[nActFamily-1].get(); 3054 if ( !pItem ) 3055 { 3056 nActFamily++; 3057 pItem = pFamilyState[nActFamily-1].get(); 3058 } 3059 } 3060 else if ( pPool != pStyleSheetPool ) 3061 pStyleSheetPool = pPool; 3062 3063 FillStyleBox(); // Decides by itself whether Fill is needed 3064 3065 if ( pItem ) 3066 SelectStyle( pItem->GetStyleName() ); 3067 } 3068 3069 void SvxStyleToolBoxControl::SetFamilyState( sal_uInt16 nIdx, 3070 const SfxTemplateItem* pItem ) 3071 { 3072 pFamilyState[nIdx].reset( pItem == nullptr ? nullptr : new SfxTemplateItem( *pItem ) ); 3073 Update(); 3074 } 3075 3076 void SvxStyleToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) 3077 { 3078 SolarMutexGuard aGuard; 3079 3080 if (m_pToolbar) 3081 m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled); 3082 else 3083 { 3084 ToolBox* pToolBox = nullptr; 3085 ToolBoxItemId nId; 3086 if (!getToolboxId( nId, &pToolBox ) ) 3087 return; 3088 pToolBox->EnableItem( nId, rEvent.IsEnabled ); 3089 } 3090 3091 if (rEvent.IsEnabled) 3092 Update(); 3093 } 3094 3095 css::uno::Reference<css::awt::XWindow> SvxStyleToolBoxControl::createItemWindow(const css::uno::Reference< css::awt::XWindow>& rParent) 3096 { 3097 uno::Reference< awt::XWindow > xItemWindow; 3098 3099 if (m_pBuilder) 3100 { 3101 SolarMutexGuard aSolarMutexGuard; 3102 3103 std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("applystyle")); 3104 3105 xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get())); 3106 3107 pImpl->m_xWeldBox.reset(new SvxStyleBox_Base(std::move(xWidget), 3108 ".uno:StyleApply", 3109 SfxStyleFamily::Para, 3110 Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ), 3111 m_xFrame, 3112 pImpl->aClearForm, 3113 pImpl->aMore, 3114 pImpl->bSpecModeWriter || pImpl->bSpecModeCalc, *this)); 3115 pImpl->m_pBox = pImpl->m_xWeldBox.get(); 3116 } 3117 else 3118 { 3119 VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent); 3120 if ( pParent ) 3121 { 3122 SolarMutexGuard aSolarMutexGuard; 3123 3124 pImpl->m_xVclBox = VclPtr<SvxStyleBox_Impl>::Create(pParent, 3125 ".uno:StyleApply", 3126 SfxStyleFamily::Para, 3127 Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ), 3128 m_xFrame, 3129 pImpl->aClearForm, 3130 pImpl->aMore, 3131 pImpl->bSpecModeWriter || pImpl->bSpecModeCalc, *this); 3132 pImpl->m_pBox = pImpl->m_xVclBox.get(); 3133 xItemWindow = VCLUnoHelper::GetInterface(pImpl->m_xVclBox); 3134 } 3135 } 3136 3137 if (pImpl->m_pBox && !pImpl->aDefaultStyles.empty()) 3138 pImpl->m_pBox->SetDefaultStyle(pImpl->aDefaultStyles[0].second); 3139 3140 return xItemWindow; 3141 } 3142 3143 SvxFontNameToolBoxControl::SvxFontNameToolBoxControl() 3144 : m_pBox(nullptr) 3145 { 3146 } 3147 3148 void SvxFontNameBox_Base::statusChanged_Impl( const css::frame::FeatureStateEvent& rEvent ) 3149 { 3150 if ( !rEvent.IsEnabled ) 3151 { 3152 set_sensitive(false); 3153 Update( nullptr ); 3154 } 3155 else 3156 { 3157 set_sensitive(true); 3158 3159 css::awt::FontDescriptor aFontDesc; 3160 if ( rEvent.State >>= aFontDesc ) 3161 Update(&aFontDesc); 3162 else { 3163 // no active element; delete value in the display 3164 m_xWidget->set_active(-1); 3165 set_active_or_entry_text(""); 3166 } 3167 m_xWidget->save_value(); 3168 } 3169 } 3170 3171 void SvxFontNameToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) 3172 { 3173 SolarMutexGuard aGuard; 3174 m_pBox->statusChanged_Impl(rEvent); 3175 3176 if (m_pToolbar) 3177 m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled); 3178 else 3179 { 3180 ToolBox* pToolBox = nullptr; 3181 ToolBoxItemId nId; 3182 if (!getToolboxId( nId, &pToolBox ) ) 3183 return; 3184 pToolBox->EnableItem( nId, rEvent.IsEnabled ); 3185 } 3186 } 3187 3188 css::uno::Reference<css::awt::XWindow> SvxFontNameToolBoxControl::createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) 3189 { 3190 uno::Reference< awt::XWindow > xItemWindow; 3191 3192 if (m_pBuilder) 3193 { 3194 SolarMutexGuard aSolarMutexGuard; 3195 3196 std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("fontnamecombobox")); 3197 3198 xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get())); 3199 3200 m_xWeldBox.reset(new SvxFontNameBox_Base(std::move(xWidget), 3201 Reference<XDispatchProvider>(m_xFrame->getController(), UNO_QUERY), 3202 m_xFrame, *this)); 3203 m_pBox = m_xWeldBox.get(); 3204 } 3205 else 3206 { 3207 VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent); 3208 if ( pParent ) 3209 { 3210 SolarMutexGuard aSolarMutexGuard; 3211 m_xVclBox = VclPtr<SvxFontNameBox_Impl>::Create(pParent, 3212 Reference<XDispatchProvider>(m_xFrame->getController(), UNO_QUERY), 3213 m_xFrame, *this); 3214 m_pBox = m_xVclBox.get(); 3215 xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox); 3216 } 3217 } 3218 3219 return xItemWindow; 3220 } 3221 3222 void SvxFontNameToolBoxControl::dispose() 3223 { 3224 ToolboxController::dispose(); 3225 3226 SolarMutexGuard aSolarMutexGuard; 3227 m_xVclBox.disposeAndClear(); 3228 m_xWeldBox.reset(); 3229 m_pBox = nullptr; 3230 } 3231 3232 OUString SvxFontNameToolBoxControl::getImplementationName() 3233 { 3234 return "com.sun.star.comp.svx.FontNameToolBoxControl"; 3235 } 3236 3237 sal_Bool SvxFontNameToolBoxControl::supportsService( const OUString& rServiceName ) 3238 { 3239 return cppu::supportsService( this, rServiceName ); 3240 } 3241 3242 css::uno::Sequence< OUString > SvxFontNameToolBoxControl::getSupportedServiceNames() 3243 { 3244 return { "com.sun.star.frame.ToolbarController" }; 3245 } 3246 3247 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * 3248 com_sun_star_comp_svx_FontNameToolBoxControl_get_implementation( 3249 css::uno::XComponentContext*, 3250 css::uno::Sequence<css::uno::Any> const & ) 3251 { 3252 return cppu::acquire( new SvxFontNameToolBoxControl() ); 3253 } 3254 3255 SvxColorToolBoxControl::SvxColorToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) : 3256 ImplInheritanceHelper( rContext, nullptr, OUString() ), 3257 m_bSplitButton(true), 3258 m_nSlotId(0), 3259 m_aColorSelectFunction(PaletteManager::DispatchColorCommand) 3260 { 3261 } 3262 3263 namespace { 3264 3265 sal_uInt16 MapCommandToSlotId(const OUString& rCommand) 3266 { 3267 if (rCommand == ".uno:Color") 3268 return SID_ATTR_CHAR_COLOR; 3269 else if (rCommand == ".uno:FontColor") 3270 return SID_ATTR_CHAR_COLOR2; 3271 else if (rCommand == ".uno:BackColor") 3272 return SID_ATTR_CHAR_COLOR_BACKGROUND; 3273 else if (rCommand == ".uno:CharBackColor") 3274 return SID_ATTR_CHAR_BACK_COLOR; 3275 else if (rCommand == ".uno:BackgroundColor") 3276 return SID_BACKGROUND_COLOR; 3277 else if (rCommand == ".uno:TableCellBackgroundColor") 3278 return SID_TABLE_CELL_BACKGROUND_COLOR; 3279 else if (rCommand == ".uno:Extrusion3DColor") 3280 return SID_EXTRUSION_3D_COLOR; 3281 else if (rCommand == ".uno:XLineColor") 3282 return SID_ATTR_LINE_COLOR; 3283 else if (rCommand == ".uno:FillColor") 3284 return SID_ATTR_FILL_COLOR; 3285 else if (rCommand == ".uno:FrameLineColor") 3286 return SID_FRAME_LINECOLOR; 3287 3288 SAL_WARN("svx.tbxcrtls", "Unknown color command: " << rCommand); 3289 return 0; 3290 } 3291 3292 } 3293 3294 void SvxColorToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>& rArguments ) 3295 { 3296 PopupWindowController::initialize( rArguments ); 3297 3298 m_nSlotId = MapCommandToSlotId( m_aCommandURL ); 3299 3300 if ( m_nSlotId == SID_ATTR_LINE_COLOR || m_nSlotId == SID_ATTR_FILL_COLOR || 3301 m_nSlotId == SID_FRAME_LINECOLOR || m_nSlotId == SID_BACKGROUND_COLOR ) 3302 { 3303 // Sidebar uses wide buttons for those. 3304 m_bSplitButton = !m_bSidebar; 3305 } 3306 3307 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(getCommandURL(), getModuleName()); 3308 OUString aCommandLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties); 3309 3310 OString aId(m_aCommandURL.toUtf8()); 3311 3312 if (m_pToolbar) 3313 { 3314 mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); 3315 m_pToolbar->set_item_popover(aId, mxPopoverContainer->getTopLevel()); 3316 m_xBtnUpdater.reset(new svx::ToolboxButtonColorUpdater(m_nSlotId, aId, m_pToolbar, !m_bSplitButton, aCommandLabel, m_xFrame)); 3317 return; 3318 } 3319 3320 ToolBox* pToolBox = nullptr; 3321 ToolBoxItemId nId; 3322 if (getToolboxId(nId, &pToolBox)) 3323 { 3324 m_xBtnUpdater.reset( new svx::VclToolboxButtonColorUpdater( m_nSlotId, nId, pToolBox, !m_bSplitButton, aCommandLabel, m_aCommandURL, m_xFrame ) ); 3325 pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ( m_bSplitButton ? ToolBoxItemBits::DROPDOWN : ToolBoxItemBits::DROPDOWNONLY ) ); 3326 } 3327 } 3328 3329 void SvxColorToolBoxControl::update() 3330 { 3331 PopupWindowController::update(); 3332 3333 switch( m_nSlotId ) 3334 { 3335 case SID_ATTR_CHAR_COLOR2: 3336 addStatusListener( ".uno:CharColorExt"); 3337 break; 3338 3339 case SID_ATTR_CHAR_COLOR_BACKGROUND: 3340 addStatusListener( ".uno:CharBackgroundExt"); 3341 break; 3342 3343 case SID_FRAME_LINECOLOR: 3344 addStatusListener( ".uno:BorderTLBR"); 3345 addStatusListener( ".uno:BorderBLTR"); 3346 break; 3347 } 3348 } 3349 3350 void SvxColorToolBoxControl::EnsurePaletteManager() 3351 { 3352 if (!m_xPaletteManager) 3353 { 3354 m_xPaletteManager = std::make_shared<PaletteManager>(); 3355 m_xPaletteManager->SetBtnUpdater(m_xBtnUpdater.get()); 3356 } 3357 } 3358 3359 SvxColorToolBoxControl::~SvxColorToolBoxControl() 3360 { 3361 if (m_xPaletteManager) 3362 m_xPaletteManager->SetBtnUpdater(nullptr); 3363 } 3364 3365 void SvxColorToolBoxControl::setColorSelectFunction(const ColorSelectFunction& aColorSelectFunction) 3366 { 3367 m_aColorSelectFunction = aColorSelectFunction; 3368 if (m_xPaletteManager) 3369 m_xPaletteManager->SetColorSelectFunction(aColorSelectFunction); 3370 } 3371 3372 weld::Window* SvxColorToolBoxControl::GetParentFrame() const 3373 { 3374 const css::uno::Reference<css::awt::XWindow> xParent = m_xFrame->getContainerWindow(); 3375 return Application::GetFrameWeld(xParent); 3376 } 3377 3378 std::unique_ptr<WeldToolbarPopup> SvxColorToolBoxControl::weldPopupWindow() 3379 { 3380 EnsurePaletteManager(); 3381 3382 const OString aId(m_aCommandURL.toUtf8()); 3383 3384 auto xPopover = std::make_unique<ColorWindow>( 3385 m_aCommandURL, 3386 m_xPaletteManager, 3387 m_aColorStatus, 3388 m_nSlotId, 3389 m_xFrame, 3390 MenuOrToolMenuButton(m_pToolbar, aId), 3391 [this] { return GetParentFrame(); }, 3392 m_aColorSelectFunction); 3393 3394 if ( m_bSplitButton ) 3395 xPopover->SetSelectedHdl( LINK( this, SvxColorToolBoxControl, SelectedHdl ) ); 3396 3397 return xPopover; 3398 } 3399 3400 VclPtr<vcl::Window> SvxColorToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) 3401 { 3402 ToolBox* pToolBox = nullptr; 3403 ToolBoxItemId nId; 3404 if (!getToolboxId(nId, &pToolBox)) 3405 return nullptr; 3406 3407 EnsurePaletteManager(); 3408 3409 auto xPopover = std::make_unique<ColorWindow>( 3410 m_aCommandURL, 3411 m_xPaletteManager, 3412 m_aColorStatus, 3413 m_nSlotId, 3414 m_xFrame, 3415 MenuOrToolMenuButton(this, pToolBox, nId), 3416 [this] { return GetParentFrame(); }, 3417 m_aColorSelectFunction); 3418 3419 if ( m_bSplitButton ) 3420 xPopover->SetSelectedHdl( LINK( this, SvxColorToolBoxControl, SelectedHdl ) ); 3421 3422 mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, 3423 std::move(xPopover), true); 3424 3425 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(m_aCommandURL, m_sModuleName); 3426 OUString aWindowTitle = vcl::CommandInfoProvider::GetLabelForCommand(aProperties); 3427 mxInterimPopover->SetText(aWindowTitle); 3428 3429 mxInterimPopover->Show(); 3430 3431 return mxInterimPopover; 3432 } 3433 3434 IMPL_LINK(SvxColorToolBoxControl, SelectedHdl, const NamedColor&, rColor, void) 3435 { 3436 m_xBtnUpdater->Update(rColor); 3437 } 3438 3439 void SvxColorToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) 3440 { 3441 ToolBox* pToolBox = nullptr; 3442 ToolBoxItemId nId; 3443 if (!getToolboxId(nId, &pToolBox) && !m_pToolbar) 3444 return; 3445 3446 if ( rEvent.FeatureURL.Complete == m_aCommandURL ) 3447 { 3448 if (m_pToolbar) 3449 m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled); 3450 else 3451 pToolBox->EnableItem( nId, rEvent.IsEnabled ); 3452 } 3453 3454 bool bValue; 3455 if ( !m_bSplitButton ) 3456 { 3457 m_aColorStatus.statusChanged( rEvent ); 3458 m_xBtnUpdater->Update( m_aColorStatus.GetColor() ); 3459 } 3460 else if ( rEvent.State >>= bValue ) 3461 { 3462 if (m_pToolbar) 3463 m_pToolbar->set_item_active(m_aCommandURL.toUtf8(), bValue); 3464 else if (pToolBox) 3465 pToolBox->CheckItem( nId, bValue ); 3466 } 3467 } 3468 3469 void SvxColorToolBoxControl::execute(sal_Int16 /*nSelectModifier*/) 3470 { 3471 if ( !m_bSplitButton ) 3472 { 3473 if (m_pToolbar) 3474 { 3475 // Toggle the popup also when toolbutton is activated 3476 const OString aId(m_aCommandURL.toUtf8()); 3477 m_pToolbar->set_menu_item_active(aId, !m_pToolbar->get_menu_item_active(aId)); 3478 } 3479 else 3480 { 3481 // Open the popup also when Enter key is pressed. 3482 createPopupWindow(); 3483 } 3484 return; 3485 } 3486 3487 OUString aCommand = m_aCommandURL; 3488 Color aColor = m_xBtnUpdater->GetCurrentColor(); 3489 3490 switch( m_nSlotId ) 3491 { 3492 case SID_ATTR_CHAR_COLOR2 : 3493 aCommand = ".uno:CharColorExt"; 3494 break; 3495 3496 case SID_ATTR_CHAR_COLOR_BACKGROUND : 3497 aCommand = ".uno:CharBackgroundExt"; 3498 break; 3499 } 3500 3501 auto aArgs( comphelper::InitPropertySequence( { 3502 { m_aCommandURL.copy(5), css::uno::Any(aColor) } 3503 } ) ); 3504 dispatchCommand( aCommand, aArgs ); 3505 3506 EnsurePaletteManager(); 3507 OUString sColorName = m_xBtnUpdater->GetCurrentColorName(); 3508 m_xPaletteManager->AddRecentColor(aColor, sColorName); 3509 } 3510 3511 sal_Bool SvxColorToolBoxControl::opensSubToolbar() 3512 { 3513 // We mark this controller as a sub-toolbar controller, so we get notified 3514 // (through updateImage method) on button image changes, and could redraw 3515 // the last used color on top of it. 3516 return true; 3517 } 3518 3519 void SvxColorToolBoxControl::updateImage() 3520 { 3521 m_xBtnUpdater->Update(m_xBtnUpdater->GetCurrentColor(), true); 3522 } 3523 3524 OUString SvxColorToolBoxControl::getSubToolbarName() 3525 { 3526 return OUString(); 3527 } 3528 3529 void SvxColorToolBoxControl::functionSelected( const OUString& /*rCommand*/ ) 3530 { 3531 } 3532 3533 OUString SvxColorToolBoxControl::getImplementationName() 3534 { 3535 return "com.sun.star.comp.svx.ColorToolBoxControl"; 3536 } 3537 3538 css::uno::Sequence<OUString> SvxColorToolBoxControl::getSupportedServiceNames() 3539 { 3540 return { "com.sun.star.frame.ToolbarController" }; 3541 } 3542 3543 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * 3544 com_sun_star_comp_svx_ColorToolBoxControl_get_implementation( 3545 css::uno::XComponentContext* rContext, 3546 css::uno::Sequence<css::uno::Any> const & ) 3547 { 3548 return cppu::acquire( new SvxColorToolBoxControl( rContext ) ); 3549 } 3550 3551 SvxFrameToolBoxControl::SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext ) 3552 : svt::PopupWindowController( rContext, nullptr, OUString() ) 3553 { 3554 } 3555 3556 void SAL_CALL SvxFrameToolBoxControl::execute(sal_Int16 /*KeyModifier*/) 3557 { 3558 if (m_pToolbar) 3559 { 3560 // Toggle the popup also when toolbutton is activated 3561 const OString aId(m_aCommandURL.toUtf8()); 3562 m_pToolbar->set_menu_item_active(aId, !m_pToolbar->get_menu_item_active(aId)); 3563 } 3564 else 3565 { 3566 // Open the popup also when Enter key is pressed. 3567 createPopupWindow(); 3568 } 3569 } 3570 3571 void SvxFrameToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) 3572 { 3573 svt::PopupWindowController::initialize( rArguments ); 3574 3575 if (m_pToolbar) 3576 { 3577 mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); 3578 m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); 3579 } 3580 3581 ToolBox* pToolBox = nullptr; 3582 ToolBoxItemId nId; 3583 if (getToolboxId(nId, &pToolBox)) 3584 pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); 3585 } 3586 3587 std::unique_ptr<WeldToolbarPopup> SvxFrameToolBoxControl::weldPopupWindow() 3588 { 3589 if ( m_aCommandURL == ".uno:LineStyle" ) 3590 return std::make_unique<SvxLineWindow_Impl>(this, m_pToolbar); 3591 return std::make_unique<SvxFrameWindow_Impl>(this, m_pToolbar); 3592 } 3593 3594 VclPtr<vcl::Window> SvxFrameToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) 3595 { 3596 if ( m_aCommandURL == ".uno:LineStyle" ) 3597 { 3598 mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, 3599 std::make_unique<SvxLineWindow_Impl>(this, pParent->GetFrameWeld())); 3600 3601 mxInterimPopover->Show(); 3602 3603 mxInterimPopover->SetText(SvxResId(RID_SVXSTR_FRAME_STYLE)); 3604 3605 return mxInterimPopover; 3606 } 3607 3608 mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, 3609 std::make_unique<SvxFrameWindow_Impl>(this, pParent->GetFrameWeld())); 3610 3611 mxInterimPopover->Show(); 3612 3613 mxInterimPopover->SetText(SvxResId(RID_SVXSTR_FRAME)); 3614 3615 return mxInterimPopover; 3616 } 3617 3618 OUString SvxFrameToolBoxControl::getImplementationName() 3619 { 3620 return "com.sun.star.comp.svx.FrameToolBoxControl"; 3621 } 3622 3623 css::uno::Sequence< OUString > SvxFrameToolBoxControl::getSupportedServiceNames() 3624 { 3625 return { "com.sun.star.frame.ToolbarController" }; 3626 } 3627 3628 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * 3629 com_sun_star_comp_svx_FrameToolBoxControl_get_implementation( 3630 css::uno::XComponentContext* rContext, 3631 css::uno::Sequence<css::uno::Any> const & ) 3632 { 3633 return cppu::acquire( new SvxFrameToolBoxControl( rContext ) ); 3634 } 3635 3636 SvxCurrencyToolBoxControl::SvxCurrencyToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) : 3637 PopupWindowController( rContext, nullptr, OUString() ), 3638 m_eLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ), 3639 m_nFormatKey( NUMBERFORMAT_ENTRY_NOT_FOUND ) 3640 { 3641 } 3642 3643 SvxCurrencyToolBoxControl::~SvxCurrencyToolBoxControl() {} 3644 3645 namespace 3646 { 3647 class SvxCurrencyList_Impl : public WeldToolbarPopup 3648 { 3649 private: 3650 rtl::Reference<SvxCurrencyToolBoxControl> m_xControl; 3651 std::unique_ptr<weld::Label> m_xLabel; 3652 std::unique_ptr<weld::TreeView> m_xCurrencyLb; 3653 std::unique_ptr<weld::Button> m_xOkBtn; 3654 OUString& m_rSelectedFormat; 3655 LanguageType& m_eSelectedLanguage; 3656 3657 std::vector<OUString> m_aFormatEntries; 3658 LanguageType m_eFormatLanguage; 3659 DECL_LINK(RowActivatedHdl, weld::TreeView&, bool); 3660 DECL_LINK(OKHdl, weld::Button&, void); 3661 3662 virtual void GrabFocus() override; 3663 3664 public: 3665 SvxCurrencyList_Impl(SvxCurrencyToolBoxControl* pControl, weld::Widget* pParent, OUString& rSelectedFormat, LanguageType& eSelectedLanguage) 3666 : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/currencywindow.ui", "CurrencyWindow") 3667 , m_xControl(pControl) 3668 , m_xLabel(m_xBuilder->weld_label("label")) 3669 , m_xCurrencyLb(m_xBuilder->weld_tree_view("currency")) 3670 , m_xOkBtn(m_xBuilder->weld_button("ok")) 3671 , m_rSelectedFormat(rSelectedFormat) 3672 , m_eSelectedLanguage(eSelectedLanguage) 3673 { 3674 std::vector< OUString > aList; 3675 std::vector< sal_uInt16 > aCurrencyList; 3676 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable(); 3677 sal_uInt16 nLen = rCurrencyTable.size(); 3678 3679 SvNumberFormatter aFormatter( m_xControl->getContext(), LANGUAGE_SYSTEM ); 3680 m_eFormatLanguage = aFormatter.GetLanguage(); 3681 3682 SvxCurrencyToolBoxControl::GetCurrencySymbols( aList, true, aCurrencyList ); 3683 3684 sal_uInt16 nPos = 0, nCount = 0; 3685 sal_Int32 nSelectedPos = -1; 3686 bool bIsSymbol; 3687 NfWSStringsDtor aStringsDtor; 3688 3689 OUString sLongestString; 3690 3691 m_xCurrencyLb->freeze(); 3692 for( const auto& rItem : aList ) 3693 { 3694 sal_uInt16& rCurrencyIndex = aCurrencyList[ nCount ]; 3695 if ( rCurrencyIndex < nLen ) 3696 { 3697 m_xCurrencyLb->append_text(rItem); 3698 3699 if (rItem.getLength() > sLongestString.getLength()) 3700 sLongestString = rItem; 3701 3702 bIsSymbol = nPos >= nLen; 3703 3704 sal_uInt16 nDefaultFormat; 3705 const NfCurrencyEntry& rCurrencyEntry = rCurrencyTable[ rCurrencyIndex ]; 3706 if (rCurrencyIndex == 0) 3707 { 3708 // Stored with system locale, but we want the resolved 3709 // full LCID format string. For example 3710 // "[$$-409]#,##0.00" instead of "[$$]#,##0.00". 3711 NfCurrencyEntry aCurrencyEntry( rCurrencyEntry); 3712 aCurrencyEntry.SetLanguage( LanguageTag( aCurrencyEntry.GetLanguage()).getLanguageType()); 3713 nDefaultFormat = aFormatter.GetCurrencyFormatStrings( aStringsDtor, aCurrencyEntry, bIsSymbol); 3714 } 3715 else 3716 { 3717 nDefaultFormat = aFormatter.GetCurrencyFormatStrings( aStringsDtor, rCurrencyEntry, bIsSymbol); 3718 } 3719 const OUString& rFormatStr = aStringsDtor[ nDefaultFormat ]; 3720 m_aFormatEntries.push_back( rFormatStr ); 3721 if( rFormatStr == m_rSelectedFormat ) 3722 nSelectedPos = nPos; 3723 ++nPos; 3724 } 3725 ++nCount; 3726 } 3727 m_xCurrencyLb->thaw(); 3728 // enable multiple selection enabled so we can start with nothing selected 3729 m_xCurrencyLb->set_selection_mode(SelectionMode::Multiple); 3730 m_xCurrencyLb->connect_row_activated( LINK( this, SvxCurrencyList_Impl, RowActivatedHdl ) ); 3731 m_xLabel->set_label(SvxResId(RID_SVXSTR_TBLAFMT_CURRENCY)); 3732 m_xCurrencyLb->select( nSelectedPos ); 3733 m_xOkBtn->connect_clicked(LINK(this, SvxCurrencyList_Impl, OKHdl)); 3734 3735 // gtk will initially make a best guess depending on the first few entries, so copy the probable 3736 // longest entry to the start temporarily and force in the width at this point 3737 m_xCurrencyLb->insert_text(0, sLongestString); 3738 m_xCurrencyLb->set_size_request(m_xCurrencyLb->get_preferred_size().Width(), m_xCurrencyLb->get_height_rows(12)); 3739 m_xCurrencyLb->remove(0); 3740 } 3741 }; 3742 3743 void SvxCurrencyList_Impl::GrabFocus() 3744 { 3745 m_xCurrencyLb->grab_focus(); 3746 } 3747 3748 IMPL_LINK_NOARG(SvxCurrencyList_Impl, OKHdl, weld::Button&, void) 3749 { 3750 RowActivatedHdl(*m_xCurrencyLb); 3751 } 3752 3753 IMPL_LINK_NOARG(SvxCurrencyList_Impl, RowActivatedHdl, weld::TreeView&, bool) 3754 { 3755 if (!m_xControl.is()) 3756 return true; 3757 3758 // multiple selection enabled so we can start with nothing selected, 3759 // so force single selection after something is picked 3760 int nSelected = m_xCurrencyLb->get_selected_index(); 3761 if (nSelected == -1) 3762 return true; 3763 3764 m_xCurrencyLb->set_selection_mode(SelectionMode::Single); 3765 3766 m_rSelectedFormat = m_aFormatEntries[nSelected]; 3767 m_eSelectedLanguage = m_eFormatLanguage; 3768 3769 m_xControl->execute(nSelected + 1); 3770 3771 m_xControl->EndPopupMode(); 3772 3773 return true; 3774 } 3775 } 3776 3777 void SvxCurrencyToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) 3778 { 3779 PopupWindowController::initialize(rArguments); 3780 3781 if (m_pToolbar) 3782 { 3783 mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); 3784 m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); 3785 return; 3786 } 3787 3788 ToolBox* pToolBox = nullptr; 3789 ToolBoxItemId nId; 3790 if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) 3791 pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWN | pToolBox->GetItemBits(nId)); 3792 } 3793 3794 std::unique_ptr<WeldToolbarPopup> SvxCurrencyToolBoxControl::weldPopupWindow() 3795 { 3796 return std::make_unique<SvxCurrencyList_Impl>(this, m_pToolbar, m_aFormatString, m_eLanguage); 3797 } 3798 3799 VclPtr<vcl::Window> SvxCurrencyToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) 3800 { 3801 mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, 3802 std::make_unique<SvxCurrencyList_Impl>(this, pParent->GetFrameWeld(), m_aFormatString, m_eLanguage)); 3803 3804 mxInterimPopover->Show(); 3805 3806 return mxInterimPopover; 3807 } 3808 3809 void SvxCurrencyToolBoxControl::execute( sal_Int16 nSelectModifier ) 3810 { 3811 sal_uInt32 nFormatKey; 3812 if (m_aFormatString.isEmpty()) 3813 nFormatKey = NUMBERFORMAT_ENTRY_NOT_FOUND; 3814 else 3815 { 3816 if ( nSelectModifier > 0 ) 3817 { 3818 try 3819 { 3820 uno::Reference< util::XNumberFormatsSupplier > xRef( m_xFrame->getController()->getModel(), uno::UNO_QUERY ); 3821 uno::Reference< util::XNumberFormats > rxNumberFormats( xRef->getNumberFormats(), uno::UNO_SET_THROW ); 3822 css::lang::Locale aLocale = LanguageTag::convertToLocale( m_eLanguage ); 3823 nFormatKey = rxNumberFormats->queryKey( m_aFormatString, aLocale, false ); 3824 if ( nFormatKey == NUMBERFORMAT_ENTRY_NOT_FOUND ) 3825 nFormatKey = rxNumberFormats->addNew( m_aFormatString, aLocale ); 3826 } 3827 catch( const uno::Exception& ) 3828 { 3829 nFormatKey = m_nFormatKey; 3830 } 3831 } 3832 else 3833 nFormatKey = m_nFormatKey; 3834 } 3835 3836 if( nFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND ) 3837 { 3838 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("NumberFormatCurrency", 3839 nFormatKey) }; 3840 dispatchCommand( m_aCommandURL, aArgs ); 3841 m_nFormatKey = nFormatKey; 3842 } 3843 else 3844 PopupWindowController::execute( nSelectModifier ); 3845 } 3846 3847 OUString SvxCurrencyToolBoxControl::getImplementationName() 3848 { 3849 return "com.sun.star.comp.svx.CurrencyToolBoxControl"; 3850 } 3851 3852 css::uno::Sequence<OUString> SvxCurrencyToolBoxControl::getSupportedServiceNames() 3853 { 3854 return { "com.sun.star.frame.ToolbarController" }; 3855 } 3856 3857 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * 3858 com_sun_star_comp_svx_CurrencyToolBoxControl_get_implementation( 3859 css::uno::XComponentContext* rContext, 3860 css::uno::Sequence<css::uno::Any> const & ) 3861 { 3862 return cppu::acquire( new SvxCurrencyToolBoxControl( rContext ) ); 3863 } 3864 3865 Reference< css::accessibility::XAccessible > SvxFontNameBox_Impl::CreateAccessible() 3866 { 3867 FillList(); 3868 return InterimItemWindow::CreateAccessible(); 3869 } 3870 3871 //static 3872 void SvxCurrencyToolBoxControl::GetCurrencySymbols( std::vector<OUString>& rList, bool bFlag, 3873 std::vector<sal_uInt16>& rCurrencyList ) 3874 { 3875 rCurrencyList.clear(); 3876 3877 const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable(); 3878 sal_uInt16 nCount = rCurrencyTable.size(); 3879 3880 sal_uInt16 nStart = 1; 3881 3882 OUString aString( ApplyLreOrRleEmbedding( rCurrencyTable[0].GetSymbol() ) + " " ); 3883 aString += ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( 3884 rCurrencyTable[0].GetLanguage() ) ); 3885 3886 rList.push_back( aString ); 3887 rCurrencyList.push_back( sal_uInt16(-1) ); // nAuto 3888 3889 if( bFlag ) 3890 { 3891 rList.push_back( aString ); 3892 rCurrencyList.push_back( 0 ); 3893 ++nStart; 3894 } 3895 3896 CollatorWrapper aCollator( ::comphelper::getProcessComponentContext() ); 3897 aCollator.loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 ); 3898 3899 static const OUStringLiteral aTwoSpace(u" "); 3900 3901 for( sal_uInt16 i = 1; i < nCount; ++i ) 3902 { 3903 OUString aStr( ApplyLreOrRleEmbedding( rCurrencyTable[i].GetBankSymbol() ) ); 3904 aStr += aTwoSpace; 3905 aStr += ApplyLreOrRleEmbedding( rCurrencyTable[i].GetSymbol() ); 3906 aStr += aTwoSpace; 3907 aStr += ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( 3908 rCurrencyTable[i].GetLanguage() ) ); 3909 3910 std::vector<OUString>::size_type j = nStart; 3911 for( ; j < rList.size(); ++j ) 3912 if ( aCollator.compareString( aStr, rList[j] ) < 0 ) 3913 break; // insert before first greater than 3914 3915 rList.insert( rList.begin() + j, aStr ); 3916 rCurrencyList.insert( rCurrencyList.begin() + j, i ); 3917 } 3918 3919 // Append ISO codes to symbol list. 3920 // XXX If this is to be changed, various other places would had to be 3921 // adapted that assume this order! 3922 std::vector<OUString>::size_type nCont = rList.size(); 3923 3924 for ( sal_uInt16 i = 1; i < nCount; ++i ) 3925 { 3926 bool bInsert = true; 3927 OUString aStr( ApplyLreOrRleEmbedding( rCurrencyTable[i].GetBankSymbol() ) ); 3928 3929 std::vector<OUString>::size_type j = nCont; 3930 for ( ; j < rList.size() && bInsert; ++j ) 3931 { 3932 if( rList[j] == aStr ) 3933 bInsert = false; 3934 else if ( aCollator.compareString( aStr, rList[j] ) < 0 ) 3935 break; // insert before first greater than 3936 } 3937 if ( bInsert ) 3938 { 3939 rList.insert( rList.begin() + j, aStr ); 3940 rCurrencyList.insert( rCurrencyList.begin() + j, i ); 3941 } 3942 } 3943 } 3944 3945 ListBoxColorWrapper::ListBoxColorWrapper(ColorListBox* pControl) 3946 : mpControl(pControl) 3947 { 3948 } 3949 3950 void ListBoxColorWrapper::operator()( 3951 [[maybe_unused]] const OUString& /*rCommand*/, const svx::NamedThemedColor& rColor) 3952 { 3953 mpControl->Selected(rColor); 3954 } 3955 3956 void ColorListBox::EnsurePaletteManager() 3957 { 3958 if (!m_xPaletteManager) 3959 { 3960 m_xPaletteManager = std::make_shared<PaletteManager>(); 3961 m_xPaletteManager->SetColorSelectFunction(std::ref(m_aColorWrapper)); 3962 } 3963 } 3964 3965 void ColorListBox::SetSlotId(sal_uInt16 nSlotId, bool bShowNoneButton) 3966 { 3967 m_nSlotId = nSlotId; 3968 m_bShowNoneButton = bShowNoneButton; 3969 m_xButton->set_popover(nullptr); 3970 m_xColorWindow.reset(); 3971 m_aSelectedColor = svx::NamedThemedColor::FromNamedColor(bShowNoneButton ? GetNoneColor() : GetAutoColor(m_nSlotId)); 3972 ShowPreview(m_aSelectedColor.ToNamedColor()); 3973 createColorWindow(); 3974 } 3975 3976 ColorListBox::ColorListBox(std::unique_ptr<weld::MenuButton> pControl, TopLevelParentFunction const& rTopLevelParentFunction) 3977 : m_xButton(std::move(pControl)) 3978 , m_aColorWrapper(this) 3979 , m_aAutoDisplayColor(Application::GetSettings().GetStyleSettings().GetDialogColor()) 3980 , m_nSlotId(0) 3981 , m_bShowNoneButton(false) 3982 , m_aTopLevelParentFunction(rTopLevelParentFunction) 3983 { 3984 m_xButton->connect_toggled(LINK(this, ColorListBox, ToggleHdl)); 3985 m_aSelectedColor = svx::NamedThemedColor::FromNamedColor(GetAutoColor(m_nSlotId)); 3986 LockWidthRequest(); 3987 ShowPreview(m_aSelectedColor.ToNamedColor()); 3988 } 3989 3990 IMPL_LINK(ColorListBox, ToggleHdl, weld::Toggleable&, rButton, void) 3991 { 3992 if (rButton.get_active()) 3993 { 3994 ColorWindow* pColorWindow = getColorWindow(); 3995 if (pColorWindow && !comphelper::LibreOfficeKit::isActive()) 3996 pColorWindow->GrabFocus(); 3997 } 3998 } 3999 4000 ColorListBox::~ColorListBox() 4001 { 4002 } 4003 4004 ColorWindow* ColorListBox::getColorWindow() const 4005 { 4006 if (!m_xColorWindow) 4007 const_cast<ColorListBox*>(this)->createColorWindow(); 4008 return m_xColorWindow.get(); 4009 } 4010 4011 void ColorListBox::createColorWindow() 4012 { 4013 const SfxViewFrame* pViewFrame = SfxViewFrame::Current(); 4014 const SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr; 4015 css::uno::Reference<css::frame::XFrame> xFrame(pFrame ? pFrame->GetFrameInterface() : uno::Reference<css::frame::XFrame>()); 4016 4017 EnsurePaletteManager(); 4018 4019 m_xColorWindow.reset(new ColorWindow( 4020 OUString() /*m_aCommandURL*/, 4021 m_xPaletteManager, 4022 m_aColorStatus, 4023 m_nSlotId, 4024 xFrame, 4025 m_xButton.get(), 4026 m_aTopLevelParentFunction, 4027 m_aColorWrapper)); 4028 4029 SetNoSelection(); 4030 m_xButton->set_popover(m_xColorWindow->getTopLevel()); 4031 if (m_bShowNoneButton) 4032 m_xColorWindow->ShowNoneButton(); 4033 m_xColorWindow->SelectEntry(m_aSelectedColor.ToNamedColor()); 4034 } 4035 4036 void ColorListBox::SelectEntry(const NamedColor& rColor) 4037 { 4038 if (rColor.second.trim().isEmpty()) 4039 { 4040 SelectEntry(rColor.first); 4041 return; 4042 } 4043 ColorWindow* pColorWindow = getColorWindow(); 4044 pColorWindow->SelectEntry(rColor); 4045 m_aSelectedColor = svx::NamedThemedColor::FromNamedColor(pColorWindow->GetSelectEntryColor()); 4046 ShowPreview(m_aSelectedColor.ToNamedColor()); 4047 } 4048 4049 void ColorListBox::SelectEntry(const Color& rColor) 4050 { 4051 ColorWindow* pColorWindow = getColorWindow(); 4052 pColorWindow->SelectEntry(rColor); 4053 m_aSelectedColor = svx::NamedThemedColor::FromNamedColor(pColorWindow->GetSelectEntryColor()); 4054 ShowPreview(m_aSelectedColor.ToNamedColor()); 4055 } 4056 4057 void ColorListBox::Selected(const svx::NamedThemedColor& rColor) 4058 { 4059 ShowPreview(rColor.ToNamedColor()); 4060 m_aSelectedColor = rColor; 4061 if (m_aSelectedLink.IsSet()) 4062 m_aSelectedLink.Call(*this); 4063 } 4064 4065 //to avoid the box resizing every time the color is changed to 4066 //the optimal size of the individual color, get the longest 4067 //standard color and stick with that as the size for all 4068 void ColorListBox::LockWidthRequest() 4069 { 4070 NamedColor aLongestColor; 4071 tools::Long nMaxStandardColorTextWidth = 0; 4072 XColorListRef const xColorTable = XColorList::CreateStdColorList(); 4073 for (tools::Long i = 0; i != xColorTable->Count(); ++i) 4074 { 4075 XColorEntry& rEntry = *xColorTable->GetColor(i); 4076 auto nColorTextWidth = m_xButton->get_pixel_size(rEntry.GetName()).Width(); 4077 if (nColorTextWidth > nMaxStandardColorTextWidth) 4078 { 4079 nMaxStandardColorTextWidth = nColorTextWidth; 4080 aLongestColor.second = rEntry.GetName(); 4081 } 4082 } 4083 ShowPreview(aLongestColor); 4084 m_xButton->set_size_request(m_xButton->get_preferred_size().Width(), -1); 4085 } 4086 4087 void ColorListBox::ShowPreview(const NamedColor &rColor) 4088 { 4089 // ScGridWindow::UpdateAutoFilterFromMenu is similar 4090 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 4091 Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize()); 4092 4093 ScopedVclPtrInstance<VirtualDevice> xDevice; 4094 xDevice->SetOutputSize(aImageSize); 4095 const tools::Rectangle aRect(Point(0, 0), aImageSize); 4096 if (m_bShowNoneButton && rColor.first == COL_NONE_COLOR) 4097 { 4098 const Color aW(COL_WHITE); 4099 const Color aG(0xef, 0xef, 0xef); 4100 int nMinDim = std::min(aImageSize.Width(), aImageSize.Height()) + 1; 4101 int nCheckSize = nMinDim / 3; 4102 xDevice->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), std::min(nCheckSize, 8), aW, aG); 4103 xDevice->SetFillColor(); 4104 } 4105 else 4106 { 4107 if (rColor.first == COL_AUTO) 4108 xDevice->SetFillColor(m_aAutoDisplayColor); 4109 else 4110 xDevice->SetFillColor(rColor.first); 4111 } 4112 4113 xDevice->SetLineColor(rStyleSettings.GetDisableColor()); 4114 xDevice->DrawRect(aRect); 4115 4116 m_xButton->set_image(xDevice.get()); 4117 m_xButton->set_label(rColor.second); 4118 } 4119 4120 MenuOrToolMenuButton::MenuOrToolMenuButton(weld::MenuButton* pMenuButton) 4121 : m_pMenuButton(pMenuButton) 4122 , m_pToolbar(nullptr) 4123 , m_pControl(nullptr) 4124 , m_nId(0) 4125 { 4126 } 4127 4128 MenuOrToolMenuButton::MenuOrToolMenuButton(weld::Toolbar* pToolbar, const OString& rIdent) 4129 : m_pMenuButton(nullptr) 4130 , m_pToolbar(pToolbar) 4131 , m_aIdent(rIdent) 4132 , m_pControl(nullptr) 4133 , m_nId(0) 4134 { 4135 } 4136 4137 MenuOrToolMenuButton::MenuOrToolMenuButton(SvxColorToolBoxControl* pControl, ToolBox* pToolbar, ToolBoxItemId nId) 4138 : m_pMenuButton(nullptr) 4139 , m_pToolbar(nullptr) 4140 , m_pControl(pControl) 4141 , m_xToolBox(pToolbar) 4142 , m_nId(nId) 4143 { 4144 } 4145 4146 MenuOrToolMenuButton::~MenuOrToolMenuButton() 4147 { 4148 } 4149 4150 bool MenuOrToolMenuButton::get_active() const 4151 { 4152 if (m_pMenuButton) 4153 return m_pMenuButton->get_active(); 4154 if (m_pToolbar) 4155 return m_pToolbar->get_menu_item_active(m_aIdent); 4156 return m_xToolBox->GetDownItemId() == m_nId; 4157 } 4158 4159 void MenuOrToolMenuButton::set_inactive() const 4160 { 4161 if (m_pMenuButton) 4162 { 4163 if (m_pMenuButton->get_active()) 4164 m_pMenuButton->set_active(false); 4165 return; 4166 } 4167 if (m_pToolbar) 4168 { 4169 if (m_pToolbar->get_menu_item_active(m_aIdent)) 4170 m_pToolbar->set_menu_item_active(m_aIdent, false); 4171 return; 4172 } 4173 m_pControl->EndPopupMode(); 4174 } 4175 4176 weld::Widget* MenuOrToolMenuButton::get_widget() const 4177 { 4178 if (m_pMenuButton) 4179 return m_pMenuButton; 4180 if (m_pToolbar) 4181 return m_pToolbar; 4182 return m_xToolBox->GetFrameWeld(); 4183 } 4184 4185 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 4186
