Use correct object
[LibreOffice.git] / cui / source / options / optcolor.cxx
blob1f2d455a1cf00b67491f65628762d59a4e8d4594
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <bitset>
24 #include <com/sun/star/configuration/ReadWriteAccess.hpp>
25 #include <com/sun/star/beans/PropertyAttribute.hpp>
26 #include <tools/debug.hxx>
27 #include <editeng/editids.hrc>
28 #include <svtools/colorcfg.hxx>
29 #include <svtools/extcolorcfg.hxx>
30 #include <svx/colorbox.hxx>
31 #include <unotools/moduleoptions.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/weld.hxx>
34 #include <svx/svxdlg.hxx>
35 #include <helpids.h>
36 #include <dialmgr.hxx>
37 #include "optcolor.hxx"
38 #include <svtools/restartdialog.hxx>
39 #include <strings.hrc>
40 #include <svtools/miscopt.hxx>
41 #include <officecfg/Office/Common.hxx>
42 #include <officecfg/Office/ExtendedColorScheme.hxx>
43 #include <officecfg/Office/UI.hxx>
44 using namespace ::com::sun::star;
45 using namespace ::svtools;
47 namespace
50 // list of default groups
51 enum Group
53 Group_General,
54 Group_Writer,
55 Group_Html,
56 Group_Calc,
57 Group_Draw,
58 Group_Comment,
59 Group_Basic,
60 Group_Sql,
62 nGroupCount
65 // group data
66 struct
68 // group
69 Group eGroup;
70 // .ui group name
71 OUString pGroup;
73 const vGroupInfo[] =
75 // the groups are in the same order as in enum Group above
76 { Group_General, u"general"_ustr },
77 { Group_Writer, u"writer"_ustr },
78 { Group_Html, u"html"_ustr },
79 { Group_Calc, u"calc"_ustr },
80 { Group_Draw, u"draw"_ustr },
81 { Group_Comment, u"comment"_ustr },
82 { Group_Basic, u"basic"_ustr },
83 { Group_Sql, u"sql"_ustr },
86 // color config entry data (see ColorConfigWindow_Impl::Entry below)
87 struct
89 // group
90 Group eGroup;
91 //checkbox (or simple text)
92 OUString pText;
93 //color listbox
94 OUString pColor;
95 // has checkbox?
96 bool bCheckBox;
97 //prop name
98 std::u16string_view sPropName;
100 const vEntryInfo[] =
102 #define IDS(Name) \
103 u"" SAL_STRINGIFY(Name) ""_ustr, u"" SAL_STRINGIFY(Name##_lb) ""_ustr, false
105 #define IDS_CB(Name) \
106 u"" SAL_STRINGIFY(Name) ""_ustr, u"" SAL_STRINGIFY(Name##_lb) ""_ustr, true
108 // The list of these entries (enum ColorConfigEntry) are in colorcfg.hxx.
110 { Group_General, IDS(doccolor), std::u16string_view(u"/DocColor") },
111 { Group_General, IDS(docboundaries), std::u16string_view(u"/DocBoundaries") },
112 { Group_General, IDS(appback), std::u16string_view(u"/AppBackground") },
113 { Group_General, IDS(tblboundaries), std::u16string_view(u"/TableBoundaries") },
114 { Group_General, IDS(font), std::u16string_view(u"/FontColor") },
115 { Group_General, IDS_CB(unvisitedlinks), std::u16string_view(u"/Links") },
116 { Group_General, IDS_CB(visitedlinks), std::u16string_view(u"/LinksVisited") },
117 { Group_General, IDS(autospellcheck), std::u16string_view(u"/Spell") },
118 { Group_General, IDS(grammarcheck), std::u16string_view(u"/Grammar") },
119 { Group_General, IDS(smarttags), std::u16string_view(u"/SmartTags") },
120 { Group_General, IDS_CB(shadows), std::u16string_view(u"/Shadow") },
122 { Group_Writer, IDS(writergrid), std::u16string_view(u"/WriterTextGrid") },
123 { Group_Writer, IDS_CB(field), std::u16string_view(u"/WriterFieldShadings") },
124 { Group_Writer, IDS_CB(index), std::u16string_view(u"/WriterIdxShadings") },
125 { Group_Writer, IDS(direct), std::u16string_view(u"/WriterDirectCursor") },
126 { Group_Writer, IDS(script), std::u16string_view(u"/WriterScriptIndicator") },
127 { Group_Writer, IDS(section), std::u16string_view(u"/WriterSectionBoundaries") },
128 { Group_Writer, IDS(hdft), std::u16string_view(u"/WriterHeaderFooterMark") },
129 { Group_Writer, IDS(pagebreak), std::u16string_view(u"/WriterPageBreaks") },
130 { Group_Writer, IDS(nonprintchars), std::u16string_view(u"/WriterNonPrintChars") },
132 { Group_Html, IDS(sgml), std::u16string_view(u"/HTMLSGML") },
133 { Group_Html, IDS(htmlcomment), std::u16string_view(u"/HTMLComment") },
134 { Group_Html, IDS(htmlkeyword), std::u16string_view(u"/HTMLKeyword") },
135 { Group_Html, IDS(unknown), std::u16string_view(u"/HTMLUnknown") },
137 { Group_Calc, IDS(calcgrid), std::u16string_view(u"/CalcGrid") },
138 { Group_Calc, IDS(calccellfocus), std::u16string_view(u"/CalcCellFocus") },
139 { Group_Calc, IDS(brk), std::u16string_view(u"/CalcPageBreak") },
140 { Group_Calc, IDS(brkmanual), std::u16string_view(u"/CalcPageBreakManual") },
141 { Group_Calc, IDS(brkauto), std::u16string_view(u"/CalcPageBreakAutomatic") },
142 { Group_Calc, IDS_CB(hiddencolrow), std::u16string_view(u"/CalcHiddenColRow") },
143 { Group_Calc, IDS_CB(textoverflow), std::u16string_view(u"/CalcTextOverflow") },
144 { Group_Calc, IDS(comments), std::u16string_view(u"/CalcComments") },
145 { Group_Calc, IDS(det), std::u16string_view(u"/CalcDetective") },
146 { Group_Calc, IDS(deterror), std::u16string_view(u"/CalcDetectiveError") },
147 { Group_Calc, IDS(ref), std::u16string_view(u"/CalcReference") },
148 { Group_Calc, IDS(notes), std::u16string_view(u"/CalcNotesBackground") },
149 { Group_Calc, IDS(values), std::u16string_view(u"/CalcValue") },
150 { Group_Calc, IDS(formulas), std::u16string_view(u"/CalcFormula") },
151 { Group_Calc, IDS(text), std::u16string_view(u"/CalcText") },
152 { Group_Calc, IDS(protectedcells), std::u16string_view(u"/CalcProtectedBackground") },
154 { Group_Draw, IDS(drawgrid), std::u16string_view(u"/DrawGrid") },
156 { Group_Comment, IDS(author1), std::u16string_view(u"/Author1") },
157 { Group_Comment, IDS(author2), std::u16string_view(u"/Author2") },
158 { Group_Comment, IDS(author3), std::u16string_view(u"/Author3") },
159 { Group_Comment, IDS(author4), std::u16string_view(u"/Author4") },
160 { Group_Comment, IDS(author5), std::u16string_view(u"/Author5") },
161 { Group_Comment, IDS(author6), std::u16string_view(u"/Author6") },
162 { Group_Comment, IDS(author7), std::u16string_view(u"/Author7") },
163 { Group_Comment, IDS(author8), std::u16string_view(u"/Author8") },
164 { Group_Comment, IDS(author9), std::u16string_view(u"/Author9") },
166 { Group_Basic, IDS(basiceditor), std::u16string_view(u"/BASICEditor") },
167 { Group_Basic, IDS(basicid), std::u16string_view(u"/BASICIdentifier") },
168 { Group_Basic, IDS(basiccomment), std::u16string_view(u"/BASICComment") },
169 { Group_Basic, IDS(basicnumber), std::u16string_view(u"/BASICNumber") },
170 { Group_Basic, IDS(basicstring), std::u16string_view(u"/BASICString") },
171 { Group_Basic, IDS(basicop), std::u16string_view(u"/BASICOperator") },
172 { Group_Basic, IDS(basickeyword), std::u16string_view(u"/BASICKeyword") },
173 { Group_Basic, IDS(error), std::u16string_view(u"/BASICError") },
175 { Group_Sql, IDS(sqlid), std::u16string_view(u"/SQLIdentifier") },
176 { Group_Sql, IDS(sqlnumber), std::u16string_view(u"/SQLNumber") },
177 { Group_Sql, IDS(sqlstring), std::u16string_view(u"/SQLString") },
178 { Group_Sql, IDS(sqlop), std::u16string_view(u"/SQLOperator") },
179 { Group_Sql, IDS(sqlkeyword), std::u16string_view(u"/SQLKeyword") },
180 { Group_Sql, IDS(sqlparam), std::u16string_view(u"/SQLParameter") },
181 { Group_Sql, IDS(sqlcomment), std::u16string_view(u"/SQLComment") }
183 #undef IDS
186 // Maps the names of default color schemes to the corresponding TranslateId
187 const std::map<OUString, OUString> &getColorSchemes()
189 static std::map<OUString, OUString> const vColorSchemes = {
190 {"COLOR_SCHEME_LIBREOFFICE_AUTOMATIC", CuiResId(RID_COLOR_SCHEME_LIBREOFFICE_AUTOMATIC)},
192 return vColorSchemes;
195 // If the color scheme name has a translated string, then return the translation
196 // Or else simply return the input string
197 // For non-translatable color schemes, the ID and the name are the same
198 OUString lcl_SchemeIdToTranslatedName(const OUString& sSchemeId)
200 auto it = getColorSchemes().find(sSchemeId);
201 if (it != getColorSchemes().end())
202 return it->second;
203 return sSchemeId;
206 // Given a translated color scheme name, return the scheme ID used in the UI.xcu file
207 // For non-translatable color schemes, the ID and the name are the same
208 OUString lcl_TranslatedNameToSchemeId(const OUString& sName)
210 for (auto it = getColorSchemes().begin(); it != getColorSchemes().end(); ++it)
211 if (it->second == sName)
212 return it->first;
213 return sName;
216 // ColorConfigWindow_Impl
218 class ColorConfigWindow_Impl
220 public:
221 explicit ColorConfigWindow_Impl(weld::Window* pTopLevel, weld::Container* pParent);
223 public:
224 void SetLinks(Link<weld::Toggleable&,void> const&,
225 Link<ColorListBox&,void> const&,
226 Link<weld::Widget&,void> const&,
227 weld::ScrolledWindow& rScroll);
228 void Update(EditableColorConfig const*, EditableExtendedColorConfig const*);
229 void UpdateEntries();
230 void ClickHdl(EditableColorConfig*, const weld::Toggleable&);
231 void ColorHdl(EditableColorConfig*, EditableExtendedColorConfig*, const ColorListBox*);
233 weld::Widget& GetWidget1()
235 return *m_xWidget1;
238 weld::Widget& GetWidget2()
240 return *m_xWidget2;
243 weld::Widget& GetBody()
245 return *m_xBox;
248 int GetLabelIndent() const
250 return m_nCheckBoxLabelOffset;
253 private:
254 // Chapter -- horizontal group separator stripe with text
255 class Chapter
257 // text
258 std::unique_ptr<weld::Label> m_xText;
259 public:
260 Chapter(weld::Builder& rBuilder, const OUString& pLabelWidget, bool bShow);
261 void SetText(const OUString& rLabel) { m_xText->set_label(rLabel); }
264 // Entry -- a color config entry:
265 // text (checkbox) + color list box
266 struct Entry
268 Entry(weld::Window* pTopLevel, weld::Builder& rBuilder, const OUString& pTextWidget, const OUString& pColorWidget,
269 const Color& rColor, int nCheckBoxLabelOffset, const ColorListBox* pCache, bool bCheckBox, bool bShow);
270 void SetText(const OUString& rLabel) { dynamic_cast<weld::Label&>(*m_xText).set_label(rLabel); }
271 int get_height_request() const
273 return std::max(m_xText->get_preferred_size().Height(),
274 m_xColorList->get_widget().get_preferred_size().Height());
276 void Hide();
278 void SetLinks(Link<weld::Toggleable&,void> const&,
279 Link<ColorListBox&,void> const&,
280 Link<weld::Widget&,void> const&);
281 void Update (ColorConfigValue const&, std::u16string_view,
282 css::uno::Reference<css::configuration::XReadWriteAccess> const&);
283 void Update (ExtendedColorConfigValue const&, std::u16string_view,
284 css::uno::Reference<css::configuration::XReadWriteAccess> const&);
285 void ColorChanged (ColorConfigValue&);
286 void ColorChanged (ExtendedColorConfigValue&);
288 bool Is(const weld::Toggleable* pBox) const { return m_xText.get() == pBox; }
289 bool Is(const ColorListBox* pBox) const { return m_xColorList.get() == pBox; }
291 // checkbox (CheckBox) or simple text (FixedText)
292 std::unique_ptr<weld::Widget> m_xText;
293 // color list box
294 std::unique_ptr<ColorListBox> m_xColorList;
295 // default color
296 Color m_aDefaultColor;
299 css::uno::Reference<css::configuration::XReadWriteAccess> m_xReadWriteAccess;
301 private:
302 weld::Window* m_pTopLevel;
303 int m_nCheckBoxLabelOffset;
304 std::unique_ptr<weld::Builder> m_xBuilder;
305 std::unique_ptr<weld::Box> m_xBox;
306 std::unique_ptr<weld::Widget> m_xWidget1;
307 std::unique_ptr<weld::Widget> m_xWidget2;
309 std::vector<std::unique_ptr<weld::Builder>> vExtBuilders;
310 std::vector<std::unique_ptr<weld::Container>> vExtContainers;
311 // vChapters -- groups (group headers)
312 std::vector<std::shared_ptr<Chapter> > vChapters;
313 // vEntries -- color options
314 std::vector<std::shared_ptr<Entry> > vEntries;
316 // module options
317 SvtModuleOptions aModuleOptions;
319 // initialization
320 void CreateEntries();
322 private:
324 bool IsGroupVisible (Group) const;
327 } // namespace
329 // ColorConfigWindow_Impl::Chapter
331 // ctor for default groups
332 // rParent: parent window (ColorConfigWindow_Impl)
333 // eGroup: which group is this?
334 ColorConfigWindow_Impl::Chapter::Chapter(weld::Builder& rBuilder, const OUString& pLabelWidget, bool bShow)
335 : m_xText(rBuilder.weld_label(pLabelWidget))
337 if (!bShow)
338 m_xText->hide();
341 // ColorConfigWindow_Impl::Entry
342 ColorConfigWindow_Impl::Entry::Entry(weld::Window* pTopLevel, weld::Builder& rBuilder,
343 const OUString& pTextWidget, const OUString& pColorWidget,
344 const Color& rColor, int nCheckBoxLabelOffset,
345 const ColorListBox* pCache, bool bCheckBox, bool bShow)
346 : m_xColorList(new ColorListBox(rBuilder.weld_menu_button(pColorWidget),
347 [pTopLevel]{ return pTopLevel; }, pCache))
348 , m_aDefaultColor(rColor)
350 if (bCheckBox)
351 m_xText = rBuilder.weld_check_button(pTextWidget);
352 else
353 m_xText = rBuilder.weld_label(pTextWidget);
355 // color list
356 m_xColorList->SetSlotId(SID_ATTR_CHAR_COLOR);
357 m_xColorList->SetAutoDisplayColor(m_aDefaultColor);
359 if (!bCheckBox)
361 m_xText->set_margin_start(m_xText->get_margin_start() +
362 nCheckBoxLabelOffset);
365 if (!bShow)
366 Hide();
369 void ColorConfigWindow_Impl::Entry::Hide()
371 m_xText->hide();
372 m_xColorList->hide();
375 // SetLinks()
376 void ColorConfigWindow_Impl::Entry::SetLinks(Link<weld::Toggleable&,void> const& rCheckLink,
377 Link<ColorListBox&,void> const& rColorLink,
378 Link<weld::Widget&,void> const& rGetFocusLink)
380 m_xColorList->SetSelectHdl(rColorLink);
381 m_xColorList->connect_focus_in(rGetFocusLink);
382 if (weld::Toggleable* pCheckBox = dynamic_cast<weld::Toggleable*>(m_xText.get()))
384 pCheckBox->connect_toggled(rCheckLink);
385 pCheckBox->connect_focus_in(rGetFocusLink);
389 // updates a default color config entry
390 void ColorConfigWindow_Impl::Entry::Update(ColorConfigValue const& rValue, std::u16string_view rConfigPath,
391 css::uno::Reference<css::configuration::XReadWriteAccess> const& xReadWriteAccess)
393 Color aColor(rValue.nColor);
394 m_xColorList->SelectEntry(aColor);
396 bool bReadOnly = false;
397 OUString aConfigPath = OUString::Concat(rConfigPath) + "/Color";
398 if (xReadWriteAccess->hasPropertyByHierarchicalName(aConfigPath))
400 css::beans::Property aProperty = xReadWriteAccess->getPropertyByHierarchicalName(aConfigPath);
401 bReadOnly = (aProperty.Attributes & css::beans::PropertyAttribute::READONLY) != 0;
403 m_xColorList->set_sensitive(!bReadOnly);
405 if (weld::Toggleable* pCheckBox = dynamic_cast<weld::Toggleable*>(m_xText.get()))
407 bReadOnly = false;
408 pCheckBox->set_active(rValue.bIsVisible);
410 aConfigPath = OUString::Concat(rConfigPath) + "/IsVisible";
411 if (xReadWriteAccess->hasPropertyByHierarchicalName(aConfigPath))
413 css::beans::Property aProperty = xReadWriteAccess->getPropertyByHierarchicalName(aConfigPath);
414 bReadOnly = (aProperty.Attributes & css::beans::PropertyAttribute::READONLY) != 0;
416 pCheckBox->set_sensitive(!bReadOnly);
420 // updates an extended color config entry
421 void ColorConfigWindow_Impl::Entry::Update(ExtendedColorConfigValue const& rValue, std::u16string_view rConfigPath,
422 css::uno::Reference<css::configuration::XReadWriteAccess> const& xReadWriteAccess)
424 Color aColor(rValue.getColor());
425 if (rValue.getColor() == rValue.getDefaultColor())
426 m_xColorList->SelectEntry(COL_AUTO);
427 else
428 m_xColorList->SelectEntry(aColor);
430 bool bReadOnly = false;
431 OUString aConfigPath = OUString::Concat(rConfigPath) + rValue.getName() + "/Color";
432 if (xReadWriteAccess->hasPropertyByHierarchicalName(aConfigPath))
434 css::beans::Property aProperty = xReadWriteAccess->getPropertyByHierarchicalName(aConfigPath);
435 bReadOnly = (aProperty.Attributes & css::beans::PropertyAttribute::READONLY) != 0;
437 m_xColorList->set_sensitive(!bReadOnly);
440 // color of a default entry has changed
441 void ColorConfigWindow_Impl::Entry::ColorChanged(ColorConfigValue& rValue)
443 Color aColor = m_xColorList->GetSelectEntryColor();
444 rValue.nColor = aColor;
447 // color of an extended entry has changed
448 void ColorConfigWindow_Impl::Entry::ColorChanged(ExtendedColorConfigValue& rValue)
450 Color aColor = m_xColorList->GetSelectEntryColor();
451 rValue.setColor(aColor);
452 if (aColor == COL_AUTO)
454 rValue.setColor(rValue.getDefaultColor());
458 // ColorConfigWindow_Impl
459 ColorConfigWindow_Impl::ColorConfigWindow_Impl(weld::Window* pTopLevel, weld::Container* pParent)
460 : m_pTopLevel(pTopLevel)
461 , m_xBuilder(Application::CreateBuilder(pParent, u"cui/ui/colorconfigwin.ui"_ustr))
462 , m_xBox(m_xBuilder->weld_box(u"ColorConfigWindow"_ustr))
463 , m_xWidget1(m_xBuilder->weld_widget(u"docboundaries"_ustr))
464 , m_xWidget2(m_xBuilder->weld_widget(u"docboundaries_lb"_ustr))
466 const css::uno::Reference < css::uno::XComponentContext >& xContext(::comphelper::getProcessComponentContext());
467 m_xReadWriteAccess = css::configuration::ReadWriteAccess::create(xContext, u"*"_ustr);
469 CreateEntries();
472 void ColorConfigWindow_Impl::CreateEntries()
474 std::bitset<nGroupCount> aModulesInstalled;
475 // creating group headers
476 vChapters.reserve(nGroupCount);
477 for (unsigned i = 0; i != nGroupCount; ++i)
479 aModulesInstalled[i] = IsGroupVisible(vGroupInfo[i].eGroup);
480 vChapters.push_back(std::make_shared<Chapter>(*m_xBuilder, vGroupInfo[i].pGroup, aModulesInstalled[i]));
483 // Here we want to get the amount to add to the position of a FixedText to
484 // get it to align its contents with that of a CheckBox
486 OUString sSampleText(u"XXXXXX"_ustr);
487 std::unique_ptr<weld::CheckButton> xCheckBox(m_xBuilder->weld_check_button(u"unvisitedlinks"_ustr));
488 std::unique_ptr<weld::Label> xFixedText(m_xBuilder->weld_label(u"doccolor"_ustr));
489 OUString sOrigCheck(xCheckBox->get_label());
490 OUString sOrigFixed(xFixedText->get_label());
491 xCheckBox->set_label(sSampleText);
492 xFixedText->set_label(sSampleText);
493 Size aCheckSize(xCheckBox->get_preferred_size());
494 Size aFixedSize(xFixedText->get_preferred_size());
495 xCheckBox->set_label(sOrigCheck);
496 xFixedText->set_label(sOrigFixed);
497 m_nCheckBoxLabelOffset = aCheckSize.Width() - aFixedSize.Width();
500 const ColorListBox* pCache = nullptr;
502 // creating entries
503 vEntries.reserve(ColorConfigEntryCount - THEME_APPLICATION_COLORS_COUNT);
504 for (size_t i = 0; i < std::size(vEntryInfo); ++i)
506 vEntries.push_back(std::make_shared<Entry>(m_pTopLevel, *m_xBuilder,
507 vEntryInfo[i].pText, vEntryInfo[i].pColor,
508 ColorConfig::GetDefaultColor(static_cast<ColorConfigEntry>(i)),
509 m_nCheckBoxLabelOffset, pCache,
510 vEntryInfo[i].bCheckBox,
511 aModulesInstalled[vEntryInfo[i].eGroup]));
512 if (!pCache)
513 pCache = vEntries.back()->m_xColorList.get();
516 // extended entries
517 ExtendedColorConfig aExtConfig;
518 unsigned const nExtGroupCount = aExtConfig.GetComponentCount();
519 if (!nExtGroupCount)
520 return;
522 for (unsigned j = 0; j != nExtGroupCount; ++j)
524 vExtBuilders.emplace_back(Application::CreateBuilder(m_xBox.get(), u"cui/ui/chapterfragment.ui"_ustr));
525 vExtContainers.emplace_back(vExtBuilders.back()->weld_frame(u"ChapterFragment"_ustr));
527 OUString const sComponentName = aExtConfig.GetComponentName(j);
528 vChapters.push_back(std::make_shared<Chapter>(
529 *vExtBuilders.back(), "chapter", true));
530 vChapters.back()->SetText(aExtConfig.GetComponentDisplayName(sComponentName));
532 vExtContainers.emplace_back(vExtBuilders.back()->weld_box(u"contents"_ustr));
533 weld::Container* pChapterBox = vExtContainers.back().get();
535 unsigned nColorCount = aExtConfig.GetComponentColorCount(sComponentName);
536 for (unsigned i = 0; i != nColorCount; ++i)
538 vExtBuilders.emplace_back(Application::CreateBuilder(pChapterBox, u"cui/ui/colorfragment.ui"_ustr));
539 vExtContainers.emplace_back(vExtBuilders.back()->weld_container(u"ColorFragment"_ustr));
541 ExtendedColorConfigValue const aColorEntry =
542 aExtConfig.GetComponentColorConfigValue(sComponentName, i);
543 vEntries.push_back(std::make_shared<Entry>(m_pTopLevel, *vExtBuilders.back(),
544 "label", "button", aColorEntry.getDefaultColor(),
545 m_nCheckBoxLabelOffset, pCache, false, true));
546 vEntries.back()->SetText(aColorEntry.getDisplayName());
551 // SetLinks()
552 void ColorConfigWindow_Impl::SetLinks(Link<weld::Toggleable&,void> const& aCheckLink,
553 Link<ColorListBox&,void> const& aColorLink,
554 Link<weld::Widget&,void> const& rGetFocusLink,
555 weld::ScrolledWindow& rScroll)
557 if (vEntries.empty())
558 return;
559 for (auto const & i: vEntries)
560 i->SetLinks(aCheckLink, aColorLink, rGetFocusLink);
561 // 6 is the spacing set on ColorConfigWindow
562 rScroll.vadjustment_set_step_increment(vEntries[0]->get_height_request() + 6);
565 // Update()
566 void ColorConfigWindow_Impl::Update (
567 EditableColorConfig const* pConfig,
568 EditableExtendedColorConfig const* pExtConfig)
570 // updating default entries
571 std::optional<OUString> aUIColorSchemeName = officecfg::Office::UI::ColorScheme::CurrentColorScheme::get();
572 OUString aUIColorSchemePath = officecfg::Office::UI::ColorScheme::ColorSchemes::path() + u"/" + aUIColorSchemeName.value();
574 for (unsigned i = 0; i != ColorConfigEntryCount - THEME_APPLICATION_COLORS_COUNT; ++i)
576 OUString sPath = aUIColorSchemePath + vEntryInfo[i].sPropName;
577 ColorConfigEntry const aColorEntry = static_cast<ColorConfigEntry>(i);
578 vEntries[i]->Update(
579 pConfig->GetColorValue(aColorEntry),
580 sPath,
581 m_xReadWriteAccess
585 // updating extended entries
586 decltype(vEntries)::size_type i = ColorConfigEntryCount - THEME_APPLICATION_COLORS_COUNT;
587 unsigned const nExtCount = pExtConfig->GetComponentCount();
588 for (unsigned j = 0; j != nExtCount; ++j)
590 OUString sComponentName = pExtConfig->GetComponentName(j);
591 aUIColorSchemePath = officecfg::Office::ExtendedColorScheme::ExtendedColorScheme::ColorSchemes::path() + u"/" +
592 aUIColorSchemeName.value() + u"/" + sComponentName + u"/Entries/";
593 unsigned const nColorCount = pExtConfig->GetComponentColorCount(sComponentName);
594 for (unsigned k = 0; i != vEntries.size() && k != nColorCount; ++i, ++k)
595 vEntries[i]->Update(
596 pExtConfig->GetComponentColorConfigValue(sComponentName, k),
597 aUIColorSchemePath,
598 m_xReadWriteAccess
603 void ColorConfigWindow_Impl::UpdateEntries()
605 for (unsigned i = 0; i != ColorConfigEntryCount - THEME_APPLICATION_COLORS_COUNT; ++i)
607 ColorConfigEntry const aEntry = static_cast<ColorConfigEntry>(i);
608 Color aColor = ColorConfig::GetDefaultColor(aEntry);
609 vEntries[i]->m_xColorList->SetAutoDisplayColor(aColor);
613 // ClickHdl()
614 void ColorConfigWindow_Impl::ClickHdl(EditableColorConfig* pConfig, const weld::Toggleable& rBox)
616 for (unsigned i = 0; i != ColorConfigEntryCount - THEME_APPLICATION_COLORS_COUNT; ++i)
618 if (vEntries[i]->Is(&rBox))
620 ColorConfigEntry const aEntry = static_cast<ColorConfigEntry>(i);
621 ColorConfigValue aValue = pConfig->GetColorValue(aEntry);
622 aValue.bIsVisible = rBox.get_active();
623 pConfig->SetColorValue(aEntry, aValue);
624 break;
629 // ColorHdl()
630 void ColorConfigWindow_Impl::ColorHdl(
631 EditableColorConfig* pConfig, EditableExtendedColorConfig* pExtConfig,
632 const ColorListBox* pBox)
634 unsigned i = 0;
636 // default entries
637 for ( ; i != ColorConfigEntryCount - THEME_APPLICATION_COLORS_COUNT; ++i)
639 if (pBox && vEntries[i]->Is(pBox))
641 ColorConfigEntry const aColorEntry = static_cast<ColorConfigEntry>(i);
642 ColorConfigValue aValue = pConfig->GetColorValue(aColorEntry);
643 vEntries[i]->ColorChanged(aValue);
644 pConfig->SetColorValue(aColorEntry, aValue);
645 break;
649 // extended entries
650 unsigned const nExtCount = pExtConfig->GetComponentCount();
651 i = ColorConfigEntryCount - THEME_APPLICATION_COLORS_COUNT;
652 for (unsigned j = 0; j != nExtCount; ++j)
654 OUString sComponentName = pExtConfig->GetComponentName(j);
655 unsigned const nColorCount = pExtConfig->GetComponentColorCount(sComponentName);
656 unsigned const nCount = vEntries.size();
657 for (unsigned k = 0; i != nCount && k != nColorCount; ++i, ++k)
659 if (pBox && vEntries[i]->Is(pBox))
661 ExtendedColorConfigValue aValue =
662 pExtConfig->GetComponentColorConfigValue(sComponentName, k);
663 vEntries[i]->ColorChanged(aValue);
664 pExtConfig->SetColorValue(sComponentName, aValue);
665 break;
672 // IsGroupVisible()
673 bool ColorConfigWindow_Impl::IsGroupVisible (Group eGroup) const
675 switch (eGroup)
677 case Group_Writer:
678 case Group_Html:
679 return aModuleOptions.IsWriterInstalled();
680 case Group_Calc:
681 return aModuleOptions.IsCalcInstalled();
682 case Group_Draw:
683 return
684 aModuleOptions.IsDrawInstalled() ||
685 aModuleOptions.IsImpressInstalled();
686 case Group_Sql:
687 return aModuleOptions.IsDataBaseInstalled();
688 default:
689 return true;
693 class ColorConfigCtrl_Impl
695 std::unique_ptr<weld::ScrolledWindow> m_xVScroll;
696 std::unique_ptr<weld::Container> m_xBody;
697 std::unique_ptr<ColorConfigWindow_Impl> m_xScrollWindow;
699 EditableColorConfig* pColorConfig;
700 EditableExtendedColorConfig* pExtColorConfig;
702 DECL_LINK(ClickHdl, weld::Toggleable&, void);
703 DECL_LINK(ColorHdl, ColorListBox&, void);
704 DECL_LINK(ControlFocusHdl, weld::Widget&, void);
706 public:
707 explicit ColorConfigCtrl_Impl(weld::Window* pTopLevel, weld::Builder& rbuilder);
709 void SetConfig (EditableColorConfig& rConfig) { pColorConfig = &rConfig; }
710 void SetExtendedConfig (EditableExtendedColorConfig& rConfig) { pExtColorConfig = &rConfig; }
711 void Update();
712 void UpdateEntries();
713 tools::Long GetScrollPosition() const
715 return m_xVScroll->vadjustment_get_value();
717 void SetScrollPosition(tools::Long nSet)
719 m_xVScroll->vadjustment_set_value(nSet);
721 weld::Widget& GetWidget1()
723 return m_xScrollWindow->GetWidget1();
725 weld::Widget& GetWidget2()
727 return m_xScrollWindow->GetWidget2();
729 int GetLabelIndent() const
731 return m_xScrollWindow->GetLabelIndent();
735 ColorConfigCtrl_Impl::ColorConfigCtrl_Impl(weld::Window* pTopLevel, weld::Builder& rBuilder)
736 : m_xVScroll(rBuilder.weld_scrolled_window(u"scroll"_ustr))
737 , m_xBody(rBuilder.weld_container(u"colorconfig"_ustr))
738 , m_xScrollWindow(std::make_unique<ColorConfigWindow_Impl>(pTopLevel, m_xBody.get()))
739 , pColorConfig(nullptr)
740 , pExtColorConfig(nullptr)
742 m_xBody->set_stack_background();
744 Link<weld::Toggleable&,void> aCheckLink = LINK(this, ColorConfigCtrl_Impl, ClickHdl);
745 Link<ColorListBox&,void> aColorLink = LINK(this, ColorConfigCtrl_Impl, ColorHdl);
746 Link<weld::Widget&,void> const aGetFocusLink = LINK(this, ColorConfigCtrl_Impl, ControlFocusHdl);
747 m_xScrollWindow->SetLinks(aCheckLink, aColorLink, aGetFocusLink, *m_xVScroll);
750 void ColorConfigCtrl_Impl::Update ()
752 DBG_ASSERT(pColorConfig, "Configuration not set");
753 m_xScrollWindow->Update(pColorConfig, pExtColorConfig);
756 void ColorConfigCtrl_Impl::UpdateEntries()
758 m_xScrollWindow->UpdateEntries();
761 IMPL_LINK(ColorConfigCtrl_Impl, ClickHdl, weld::Toggleable&, rBox, void)
763 DBG_ASSERT(pColorConfig, "Configuration not set");
764 m_xScrollWindow->ClickHdl(pColorConfig, rBox);
767 // a color list has changed
768 IMPL_LINK(ColorConfigCtrl_Impl, ColorHdl, ColorListBox&, rBox, void)
770 DBG_ASSERT(pColorConfig, "Configuration not set" );
771 m_xScrollWindow->ColorHdl(pColorConfig, pExtColorConfig, &rBox);
774 IMPL_LINK(ColorConfigCtrl_Impl, ControlFocusHdl, weld::Widget&, rCtrl, void)
776 // determine whether a control is completely visible
777 // and make it visible
778 unsigned const nWinHeight = m_xVScroll->vadjustment_get_page_size();
780 // calc visible area
781 auto nThumbPos = m_xVScroll->vadjustment_get_value();
782 int const nWinTop = nThumbPos;
783 int const nWinBottom = nWinTop + nWinHeight;
785 int x, nCtrlPosY, width, nHeight;
786 rCtrl.get_extents_relative_to(m_xScrollWindow->GetBody(), x, nCtrlPosY, width, nHeight);
788 int const nSelectedItemTop = nCtrlPosY;
789 int const nSelectedItemBottom = nCtrlPosY + nHeight;
790 bool const shouldScrollDown = nSelectedItemBottom >= nWinBottom;
791 bool const shouldScrollUp = nSelectedItemTop <= nWinTop;
792 bool const isNeedToScroll = shouldScrollDown || shouldScrollUp || nCtrlPosY < 0;
794 if (!isNeedToScroll)
795 return;
797 if (shouldScrollDown)
799 int nOffset = nSelectedItemBottom - nWinBottom;
800 nThumbPos += nOffset + 2;
802 else
804 int nOffset = nWinTop - nSelectedItemTop;
805 nThumbPos -= nOffset + 2;
806 if(nThumbPos < 0)
807 nThumbPos = 0;
809 m_xVScroll->vadjustment_set_value(nThumbPos);
812 // SvxColorOptionsTabPage
813 SvxColorOptionsTabPage::SvxColorOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
814 : SfxTabPage(pPage, pController, u"cui/ui/optappearancepage.ui"_ustr, u"OptAppearancePage"_ustr, &rCoreSet)
815 , bFillItemSetCalled(false)
816 , m_bShowRestartDialog(false)
817 , m_nSizeAllocEventId(nullptr)
818 , m_xAutoColorLB(m_xBuilder->weld_combo_box(u"autocolorlb"_ustr))
819 , m_xAutoColorImg(m_xBuilder->weld_widget(u"lockautocolorlb"_ustr))
820 , m_xColorSchemeLB(m_xBuilder->weld_combo_box(u"colorschemelb"_ustr))
821 , m_xColorSchemeImg(m_xBuilder->weld_widget(u"lockcolorschemelb"_ustr))
822 , m_xSaveSchemePB(m_xBuilder->weld_button(u"save"_ustr))
823 , m_xDeleteSchemePB(m_xBuilder->weld_button(u"delete"_ustr))
824 , m_xColorConfigCT(new ColorConfigCtrl_Impl(pController->getDialog(), *m_xBuilder))
825 , m_xTable(m_xBuilder->weld_widget(u"table"_ustr))
826 , m_xOnFT(m_xBuilder->weld_label(u"on"_ustr))
827 , m_xColorFT(m_xBuilder->weld_label(u"colorsetting"_ustr))
828 , m_rWidget1(m_xColorConfigCT->GetWidget1())
829 , m_rWidget2(m_xColorConfigCT->GetWidget2())
831 m_xColorSchemeLB->make_sorted();
832 m_xColorSchemeLB->connect_changed(LINK(this, SvxColorOptionsTabPage, SchemeChangedHdl_Impl));
833 m_xAutoColorLB->connect_changed(LINK(this, SvxColorOptionsTabPage, onAutoColorChanged));
834 Link<weld::Button&,void> aLk = LINK(this, SvxColorOptionsTabPage, SaveDeleteHdl_Impl );
835 m_xSaveSchemePB->connect_clicked(aLk);
836 m_xDeleteSchemePB->connect_clicked(aLk);
838 m_rWidget1.connect_size_allocate(LINK(this, SvxColorOptionsTabPage, AdjustHeaderBar));
839 m_rWidget2.connect_size_allocate(LINK(this, SvxColorOptionsTabPage, AdjustHeaderBar));
842 SvxColorOptionsTabPage::~SvxColorOptionsTabPage()
844 if (pColorConfig)
846 //when the dialog is cancelled but the color scheme ListBox has been changed these
847 //changes need to be undone
848 if (!bFillItemSetCalled && m_xColorSchemeLB->get_value_changed_from_saved())
850 OUString sOldScheme = m_xColorSchemeLB->get_saved_value();
851 if(!sOldScheme.isEmpty())
853 pColorConfig->SetCurrentSchemeName(sOldScheme);
854 pExtColorConfig->SetCurrentSchemeName(sOldScheme);
857 pColorConfig->ClearModified();
858 pColorConfig->EnableBroadcast();
859 pColorConfig.reset();
861 pExtColorConfig->ClearModified();
862 pExtColorConfig->EnableBroadcast();
863 pExtColorConfig.reset();
865 m_xColorConfigCT.reset();
866 if (m_nSizeAllocEventId)
867 Application::RemoveUserEvent(m_nSizeAllocEventId);
869 if (m_bShowRestartDialog)
871 ::svtools::executeRestartDialog(comphelper::getProcessComponentContext(), GetFrameWeld(),
872 svtools::RESTART_REASON_THEME_CHANGE);
876 std::unique_ptr<SfxTabPage> SvxColorOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
878 return std::make_unique<SvxColorOptionsTabPage>(pPage, pController, *rAttrSet);
881 OUString SvxColorOptionsTabPage::GetAllStrings()
883 // buttons are excluded
884 OUString sAllStrings;
885 OUString labels[] = { u"label2"_ustr, u"label3"_ustr, u"autocolor"_ustr, u"uielements"_ustr, u"colorsetting"_ustr };
887 for (const auto& label : labels)
889 if (const auto pString = m_xBuilder->weld_label(label))
890 sAllStrings += pString->get_label() + " ";
893 return sAllStrings.replaceAll("_", "");
896 bool SvxColorOptionsTabPage::FillItemSet( SfxItemSet* )
898 bFillItemSetCalled = true;
899 if (m_xColorSchemeLB->get_value_changed_from_saved())
901 pColorConfig->SetModified();
902 pExtColorConfig->SetModified();
904 if (pColorConfig->IsModified())
905 pColorConfig->Commit();
906 if (pExtColorConfig->IsModified())
907 pExtColorConfig->Commit();
908 return true;
911 void SvxColorOptionsTabPage::Reset( const SfxItemSet* )
913 if(pColorConfig)
915 pColorConfig->ClearModified();
916 pColorConfig->DisableBroadcast();
918 pColorConfig.reset(new EditableColorConfig);
919 m_xColorConfigCT->SetConfig(*pColorConfig);
921 if(pExtColorConfig)
923 pExtColorConfig->ClearModified();
924 pExtColorConfig->DisableBroadcast();
926 pExtColorConfig.reset(new EditableExtendedColorConfig);
927 m_xColorConfigCT->SetExtendedConfig(*pExtColorConfig);
929 m_xAutoColorLB->set_active( MiscSettings::GetAppColorMode() );
931 bool bReadOnly = officecfg::Office::ExtendedColorScheme::ExtendedColorScheme::CurrentColorScheme::isReadOnly() ||
932 officecfg::Office::UI::ColorScheme::CurrentColorScheme::isReadOnly();
933 m_xAutoColorLB->set_sensitive(!bReadOnly);
934 m_xSaveSchemePB->set_sensitive(!bReadOnly);
935 m_xDeleteSchemePB->set_sensitive(!bReadOnly);
936 m_xAutoColorImg->set_visible(bReadOnly);
938 OUString sUser = GetUserData();
939 //has to be called always to speed up accessibility tools
940 m_xColorConfigCT->SetScrollPosition(sUser.toInt32());
941 m_xColorSchemeLB->clear();
942 const uno::Sequence< OUString > aSchemes = pColorConfig->GetSchemeNames();
943 for(const OUString& s : aSchemes)
944 m_xColorSchemeLB->append_text(lcl_SchemeIdToTranslatedName(s));
946 m_xColorSchemeLB->set_active_text(lcl_SchemeIdToTranslatedName(pColorConfig->GetCurrentSchemeName()));
947 m_xColorSchemeLB->set_sensitive(!officecfg::Office::Common::Misc::ApplicationAppearance::isReadOnly());
948 m_xColorSchemeImg->set_visible(officecfg::Office::Common::Misc::ApplicationAppearance::isReadOnly());
949 m_xColorSchemeLB->save_value();
951 m_xDeleteSchemePB->set_sensitive( aSchemes.getLength() > 1 &&
952 !officecfg::Office::ExtendedColorScheme::ExtendedColorScheme::CurrentColorScheme::isReadOnly() );
953 UpdateColorConfig();
956 DeactivateRC SvxColorOptionsTabPage::DeactivatePage( SfxItemSet* pSet_ )
958 if ( pSet_ )
959 FillItemSet( pSet_ );
960 return DeactivateRC::LeavePage;
963 void SvxColorOptionsTabPage::UpdateColorConfig()
965 //update the color config control
966 m_xColorConfigCT->Update();
969 IMPL_LINK_NOARG(SvxColorOptionsTabPage, onAutoColorChanged, weld::ComboBox&, void)
971 MiscSettings::SetAppColorMode( m_xAutoColorLB->get_active() );
973 m_xColorConfigCT->UpdateEntries();
975 pColorConfig->LoadScheme(lcl_TranslatedNameToSchemeId(m_xColorSchemeLB->get_active_text()));
976 pExtColorConfig->LoadScheme(lcl_TranslatedNameToSchemeId(m_xColorSchemeLB->get_active_text()));
977 UpdateColorConfig();
980 IMPL_LINK(SvxColorOptionsTabPage, SchemeChangedHdl_Impl, weld::ComboBox&, rBox, void)
982 pColorConfig->LoadScheme(lcl_TranslatedNameToSchemeId(rBox.get_active_text()));
983 pExtColorConfig->LoadScheme(lcl_TranslatedNameToSchemeId(rBox.get_active_text()));
984 UpdateColorConfig();
986 // show restart dialog only when LibreOffice Theme is enabled and
987 // the theme was changed.
988 if (officecfg::Office::Common::Misc::LibreOfficeTheme::get()
989 && rBox.get_value_changed_from_saved())
990 m_bShowRestartDialog = true;
993 IMPL_LINK(SvxColorOptionsTabPage, SaveDeleteHdl_Impl, weld::Button&, rButton, void)
995 if (m_xSaveSchemePB.get() == &rButton)
997 OUString sName;
999 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1000 ScopedVclPtr<AbstractSvxNameDialog> aNameDlg(pFact->CreateSvxNameDialog(GetFrameWeld(),
1001 sName, CuiResId(RID_CUISTR_COLOR_CONFIG_SAVE2) ));
1002 aNameDlg->SetCheckNameHdl( LINK(this, SvxColorOptionsTabPage, CheckNameHdl_Impl));
1003 aNameDlg->SetText(CuiResId(RID_CUISTR_COLOR_CONFIG_SAVE1));
1004 aNameDlg->SetHelpId(HID_OPTIONS_COLORCONFIG_SAVE_SCHEME);
1005 aNameDlg->SetCheckNameHdl( LINK(this, SvxColorOptionsTabPage, CheckNameHdl_Impl));
1006 if(RET_OK == aNameDlg->Execute())
1008 sName = aNameDlg->GetName();
1009 pColorConfig->AddScheme(sName);
1010 pExtColorConfig->AddScheme(sName);
1011 m_xColorSchemeLB->append_text(sName);
1012 m_xColorSchemeLB->set_active_text(sName);
1013 SchemeChangedHdl_Impl(*m_xColorSchemeLB);
1016 else
1018 DBG_ASSERT(m_xColorSchemeLB->get_count() > 1, "don't delete the last scheme");
1019 std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(GetFrameWeld(),
1020 VclMessageType::Question, VclButtonsType::YesNo,
1021 CuiResId(RID_CUISTR_COLOR_CONFIG_DELETE)));
1022 xQuery->set_title(CuiResId(RID_CUISTR_COLOR_CONFIG_DELETE_TITLE));
1023 if (RET_YES == xQuery->run())
1025 OUString sDeleteScheme(m_xColorSchemeLB->get_active_text());
1026 m_xColorSchemeLB->remove(m_xColorSchemeLB->get_active());
1027 m_xColorSchemeLB->set_active(0);
1028 SchemeChangedHdl_Impl(*m_xColorSchemeLB);
1029 //first select the new scheme and then delete the old one
1030 pColorConfig->DeleteScheme(sDeleteScheme);
1031 pExtColorConfig->DeleteScheme(sDeleteScheme);
1034 m_xDeleteSchemePB->set_sensitive(m_xColorSchemeLB->get_count() > 1);
1037 IMPL_LINK(SvxColorOptionsTabPage, CheckNameHdl_Impl, AbstractSvxNameDialog&, rDialog, bool )
1039 OUString sName = rDialog.GetName();
1040 return !sName.isEmpty() && m_xColorSchemeLB->find_text(sName) == -1;
1043 void SvxColorOptionsTabPage::FillUserData()
1045 SetUserData(OUString::number(m_xColorConfigCT->GetScrollPosition()));
1048 IMPL_LINK_NOARG(SvxColorOptionsTabPage, AdjustHeaderBar, const Size&, void)
1050 if (m_nSizeAllocEventId)
1051 return;
1052 m_nSizeAllocEventId = Application::PostUserEvent(LINK(this, SvxColorOptionsTabPage, PostAdjustHeaderBar));
1055 IMPL_LINK_NOARG(SvxColorOptionsTabPage, PostAdjustHeaderBar, void*, void)
1057 m_nSizeAllocEventId = nullptr;
1059 // horizontal positions
1060 int nX1, nX2, nX3, y, width, height;
1061 if (!m_rWidget1.get_extents_relative_to(*m_xTable, nX1, y, width, height))
1062 return;
1063 if (!m_rWidget2.get_extents_relative_to(*m_xTable, nX2, y, width, height))
1064 return;
1065 if (!m_xTable->get_extents_relative_to(*m_xTable, nX3, y, width, height))
1066 return;
1068 // 6 is the column-spacing of the parent grid of these labels
1069 auto nTextWidth1 = nX1 + m_xColorConfigCT->GetLabelIndent() - 6;
1070 m_xOnFT->set_size_request(nTextWidth1, -1);
1071 auto nTextWidth3 = width - nX2;
1072 m_xColorFT->set_size_request(nTextWidth3, -1);
1075 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */