LibreOffice Module sw (master) 1
ThemePanel.cxx
Go to the documentation of this file.
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 */
10
11#include <sal/config.h>
12
13#include "ThemePanel.hxx"
14
15#include <sfx2/objsh.hxx>
16
17#include <com/sun/star/lang/IllegalArgumentException.hpp>
18
19#include <editeng/fontitem.hxx>
20#include <vcl/bitmapex.hxx>
21#include <vcl/image.hxx>
22#include <vcl/settings.hxx>
23#include <vcl/svapp.hxx>
24#include <vcl/virdev.hxx>
25#include <charatr.hxx>
26#include <charfmt.hxx>
27#include <docsh.hxx>
28#include <docstyle.hxx>
29#include <fmtcol.hxx>
30#include <format.hxx>
31
32namespace
33{
34
35class FontSet
36{
37public:
38 OUString maName;
39 OUString msMonoFont;
40 OUString msHeadingFont;
41 OUString msBaseFont;
42};
43
44class ColorVariable
45{
46public:
48 sal_Int16 mnTintShade;
49
50 ColorVariable()
51 : mnIndex(-1)
52 , mnTintShade()
53 {}
54
55 ColorVariable(tools::Long nIndex, sal_Int16 nTintShade)
57 , mnTintShade(nTintShade)
58 {}
59};
60
61class StyleRedefinition
62{
63 ColorVariable maVariable;
64
65public:
66 OUString maElementName;
67
68public:
69 explicit StyleRedefinition(const OUString& aElementName)
70 : maElementName(aElementName)
71 {}
72
73 void setColorVariable(ColorVariable aVariable)
74 {
75 maVariable = aVariable;
76 }
77
78 Color getColor(svx::ColorSet const & rColorSet)
79 {
80 Color aColor;
81 if (maVariable.mnIndex > -1)
82 {
83 aColor = rColorSet.getColor(maVariable.mnIndex);
84 aColor.ApplyTintOrShade(maVariable.mnTintShade);
85 }
86 else
87 {
88 aColor = COL_BLACK;
89 }
90 return aColor;
91 }
92};
93
94class StyleSet
95{
96 std::vector<StyleRedefinition> maStyles;
97
98public:
99 explicit StyleSet()
100 {}
101
102 void add(StyleRedefinition const & aRedefinition)
103 {
104 maStyles.push_back(aRedefinition);
105 }
106
107 StyleRedefinition* get(std::u16string_view aString)
108 {
109 for (StyleRedefinition & rStyle : maStyles)
110 {
111 if (rStyle.maElementName == aString)
112 {
113 return &rStyle;
114 }
115 }
116 return nullptr;
117 }
118};
119
120StyleSet setupThemes()
121{
122 StyleSet aSet;
123
124 {
125 StyleRedefinition aRedefinition("Heading 1");
126 aRedefinition.setColorVariable(ColorVariable(10, -1000));
127 aSet.add(aRedefinition);
128 }
129
130 {
131 StyleRedefinition aRedefinition("Heading 2");
132 aRedefinition.setColorVariable(ColorVariable(7, -500));
133 aSet.add(aRedefinition);
134 }
135
136 {
137 StyleRedefinition aRedefinition("Heading 3");
138 aRedefinition.setColorVariable(ColorVariable(5, 0));
139 aSet.add(aRedefinition);
140 }
141
142 {
143 StyleRedefinition aRedefinition("Heading 4");
144 aRedefinition.setColorVariable(ColorVariable(6, -1000));
145 aSet.add(aRedefinition);
146 }
147
148 {
149 StyleRedefinition aRedefinition("Heading 5");
150 aRedefinition.setColorVariable(ColorVariable(4, -1500));
151 aSet.add(aRedefinition);
152 }
153
154 {
155 StyleRedefinition aRedefinition("Heading 6");
156 aRedefinition.setColorVariable(ColorVariable(3, -2500));
157 aSet.add(aRedefinition);
158 }
159
160 {
161 StyleRedefinition aRedefinition("Heading 7");
162 aRedefinition.setColorVariable(ColorVariable(3, -2500));
163 aSet.add(aRedefinition);
164 }
165
166 {
167 StyleRedefinition aRedefinition("Heading 8");
168 aRedefinition.setColorVariable(ColorVariable(2, 0));
169 aSet.add(aRedefinition);
170 }
171
172 {
173 StyleRedefinition aRedefinition("Heading 9");
174 aRedefinition.setColorVariable(ColorVariable(2, 0));
175 aSet.add(aRedefinition);
176 }
177
178 {
179 StyleRedefinition aRedefinition("Heading 10");
180 aRedefinition.setColorVariable(ColorVariable(0, 0));
181 aSet.add(aRedefinition);
182 }
183
184 return aSet;
185}
186
187void changeFont(SwFormat* pFormat, SwDocStyleSheet const * pStyle, FontSet const & rFontSet)
188{
189 if (pStyle->GetName() != "Default Style" && pFormat->GetAttrSet().GetItem(RES_CHRATR_FONT, false) == nullptr)
190 {
191 return;
192 }
193
194 SvxFontItem aFontItem(pFormat->GetFont(false));
195
196 FontPitch ePitch = aFontItem.GetPitch();
197
198 if (ePitch == PITCH_FIXED)
199 {
200 aFontItem.SetFamilyName(rFontSet.msMonoFont);
201 }
202 else
203 {
204 if (pStyle->GetName() == "Heading")
205 {
206 aFontItem.SetFamilyName(rFontSet.msHeadingFont);
207 }
208 else
209 {
210 aFontItem.SetFamilyName(rFontSet.msBaseFont);
211 }
212 }
213
214 pFormat->SetFormatAttr(aFontItem);
215}
216
217/*void changeBorder(SwTextFormatColl* pCollection, SwDocStyleSheet* pStyle, StyleSet& rStyleSet)
218{
219 if (pStyle->GetName() == "Heading")
220 {
221 SvxBoxItem aBoxItem(pCollection->GetBox());
222 editeng::SvxBorderLine aBorderLine;
223 aBorderLine.SetWidth(40); //20 = 1pt
224 aBorderLine.SetColor(rColorSet.mBaseColors[0]);
225 aBoxItem.SetLine(&aBorderLine, SvxBoxItemLine::BOTTOM);
226
227 pCollection->SetFormatAttr(aBoxItem);
228 }
229}*/
230
231void changeColor(SwTextFormatColl* pCollection, svx::ColorSet const & rColorSet, StyleRedefinition* pRedefinition)
232{
233 Color aColor = pRedefinition->getColor(rColorSet);
234
235 SvxColorItem aColorItem(pCollection->GetColor());
236 aColorItem.SetValue(aColor);
237 pCollection->SetFormatAttr(aColorItem);
238}
239
240std::vector<FontSet> initFontSets()
241{
242 std::vector<FontSet> aFontSets;
243 {
244 FontSet aFontSet;
245 aFontSet.maName = "Liberation Family";
246 aFontSet.msHeadingFont = "Liberation Sans";
247 aFontSet.msBaseFont = "Liberation Serif";
248 aFontSet.msMonoFont = "Liberation Mono";
249 aFontSets.push_back(aFontSet);
250 }
251 {
252 FontSet aFontSet;
253 aFontSet.maName = "DejaVu Family";
254 aFontSet.msHeadingFont = "DejaVu Sans";
255 aFontSet.msBaseFont = "DejaVu Serif";
256 aFontSet.msMonoFont = "DejaVu Sans Mono";
257 aFontSets.push_back(aFontSet);
258 }
259 {
260 FontSet aFontSet;
261 aFontSet.maName = "Croscore Modern";
262 aFontSet.msHeadingFont = "Caladea";
263 aFontSet.msBaseFont = "Carlito";
264 aFontSet.msMonoFont = "Liberation Mono";
265 aFontSets.push_back(aFontSet);
266 }
267 {
268 FontSet aFontSet;
269 aFontSet.maName = "Carlito";
270 aFontSet.msHeadingFont = "Carlito";
271 aFontSet.msBaseFont = "Carlito";
272 aFontSet.msMonoFont = "Liberation Mono";
273 aFontSets.push_back(aFontSet);
274 }
275 {
276 FontSet aFontSet;
277 aFontSet.maName = "Source Sans Family";
278 aFontSet.msHeadingFont = "Source Sans Pro";
279 aFontSet.msBaseFont = "Source Sans Pro";
280 aFontSet.msMonoFont = "Source Code Pro";
281 aFontSets.push_back(aFontSet);
282 }
283 {
284 FontSet aFontSet;
285 aFontSet.maName = "Source Sans Family 2";
286 aFontSet.msHeadingFont = "Source Sans Pro";
287 aFontSet.msBaseFont = "Source Sans Pro Light";
288 aFontSet.msMonoFont = "Source Code Pro";
289 aFontSets.push_back(aFontSet);
290 }
291 {
292 FontSet aFontSet;
293 aFontSet.maName = "Libertine Family";
294 aFontSet.msHeadingFont = "Linux Biolinum G";
295 aFontSet.msBaseFont = "Linux Libertine G";
296 aFontSet.msMonoFont = "Liberation Mono";
297 aFontSets.push_back(aFontSet);
298 }
299 {
300 FontSet aFontSet;
301 aFontSet.maName = "Noto Sans";
302 aFontSet.msHeadingFont = "Noto Sans";
303 aFontSet.msBaseFont = "Noto Sans";
304 aFontSet.msMonoFont = "Noto Mono";
305 aFontSets.push_back(aFontSet);
306 }
307 {
308 FontSet aFontSet;
309 aFontSet.maName = "Droid Sans";
310 aFontSet.msHeadingFont = "Droid Sans";
311 aFontSet.msBaseFont = "Droid Sans";
312 aFontSet.msMonoFont = "Droid Sans Mono";
313 aFontSets.push_back(aFontSet);
314 }
315 return aFontSets;
316}
317
318FontSet getFontSet(std::u16string_view rFontVariant, std::vector<FontSet>& aFontSets)
319{
320 for (const FontSet & rFontSet : aFontSets)
321 {
322 if (rFontSet.maName == rFontVariant)
323 return rFontSet;
324 }
325 return aFontSets[0];
326}
327
328void applyTheme(SfxStyleSheetBasePool* pPool, std::u16string_view sFontSetName, std::u16string_view sColorSetName,
329 StyleSet& rStyleSet, svx::ColorSets& rColorSets)
330{
331 SwDocStyleSheet* pStyle;
332
333 std::vector<FontSet> aFontSets = initFontSets();
334 FontSet aFontSet = getFontSet(sFontSetName, aFontSets);
335
336 svx::ColorSet aColorSet = rColorSets.getColorSet(sColorSetName);
337
338 pStyle = static_cast<SwDocStyleSheet*>(pPool->First(SfxStyleFamily::Para));
339 while (pStyle)
340 {
341 SwTextFormatColl* pCollection = pStyle->GetCollection();
342
343 changeFont(pCollection, pStyle, aFontSet);
344
345 StyleRedefinition* pRedefinition = rStyleSet.get(pStyle->GetName());
346
347 if (pRedefinition)
348 {
349 changeColor(pCollection, aColorSet, pRedefinition);
350 }
351
352 pStyle = static_cast<SwDocStyleSheet*>(pPool->Next());
353 }
354
355 pStyle = static_cast<SwDocStyleSheet*>(pPool->First(SfxStyleFamily::Char));
356 while (pStyle)
357 {
358 SwCharFormat* pCharFormat = pStyle->GetCharFormat();
359
360 changeFont(static_cast<SwFormat*>(pCharFormat), pStyle, aFontSet);
361
362 pStyle = static_cast<SwDocStyleSheet*>(pPool->Next());
363 }
364}
365
366BitmapEx GenerateColorPreview(const svx::ColorSet& rColorSet)
367{
369 float fScaleFactor = pVirtualDev->GetDPIScaleFactor();
370 tools::Long BORDER = 3 * fScaleFactor;
371 tools::Long SIZE = 14 * fScaleFactor;
372 tools::Long LABEL_HEIGHT = 16 * fScaleFactor;
373 tools::Long LABEL_TEXT_HEIGHT = 14 * fScaleFactor;
374
375 Size aSize(BORDER * 7 + SIZE * 6 + BORDER * 2, BORDER * 3 + SIZE * 2 + LABEL_HEIGHT);
376 pVirtualDev->SetOutputSizePixel(aSize);
377 pVirtualDev->SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetFaceColor()));
378 pVirtualDev->Erase();
379
382 tools::Long y2 = y1 + SIZE + BORDER;
383
384 pVirtualDev->SetLineColor(COL_LIGHTGRAY);
385 pVirtualDev->SetFillColor(COL_LIGHTGRAY);
386 tools::Rectangle aNameRect(Point(0, 0), Size(aSize.Width(), LABEL_HEIGHT));
387 pVirtualDev->DrawRect(aNameRect);
388
389 vcl::Font aFont;
390 OUString aName = rColorSet.getName();
391 aFont.SetFontHeight(LABEL_TEXT_HEIGHT);
392 pVirtualDev->SetFont(aFont);
393
394 Size aTextSize(pVirtualDev->GetTextWidth(aName), pVirtualDev->GetTextHeight());
395
396 Point aPoint((aNameRect.GetWidth() / 2.0) - (aTextSize.Width() / 2.0),
397 (aNameRect.GetHeight() / 2.0) - (aTextSize.Height() / 2.0));
398
399 pVirtualDev->DrawText(aPoint, aName);
400
401 pVirtualDev->SetLineColor(COL_LIGHTGRAY);
402 pVirtualDev->SetFillColor();
403
404 for (sal_uInt32 i = 0; i < 12; i += 2)
405 {
406 pVirtualDev->SetFillColor(rColorSet.getColor(i));
407 pVirtualDev->DrawRect(tools::Rectangle(x, y1, x + SIZE, y1 + SIZE));
408
409 pVirtualDev->SetFillColor(rColorSet.getColor(i + 1));
410 pVirtualDev->DrawRect(tools::Rectangle(x, y2, x + SIZE, y2 + SIZE));
411
412 x += SIZE + BORDER;
413 if (i == 2 || i == 8)
414 x += BORDER;
415 }
416
417 return pVirtualDev->GetBitmapEx(Point(), aSize);
418}
419
420} // end anonymous namespace
421
422namespace sw::sidebar {
423
424std::unique_ptr<PanelLayout> ThemePanel::Create(weld::Widget* pParent)
425{
426 if (pParent == nullptr)
427 throw css::lang::IllegalArgumentException("no parent Window given to PagePropertyPanel::Create", nullptr, 0);
428
429 return std::make_unique<ThemePanel>(pParent);
430}
431
433 : PanelLayout(pParent, "ThemePanel", "modules/swriter/ui/sidebartheme.ui")
434 , mxListBoxFonts(m_xBuilder->weld_tree_view("listbox_fonts"))
435 , mxValueSetColors(new ValueSet(nullptr))
436 , mxValueSetColorsWin(new weld::CustomWeld(*m_xBuilder, "valueset_colors", *mxValueSetColors))
437 , mxApplyButton(m_xBuilder->weld_button("apply"))
438{
439 mxValueSetColors->SetColCount(2);
440 mxValueSetColors->SetLineCount(3);
441 mxValueSetColors->SetColor(Application::GetSettings().GetStyleSettings().GetFaceColor());
442
443 mxApplyButton->connect_clicked(LINK(this, ThemePanel, ClickHdl));
444 mxListBoxFonts->connect_row_activated(LINK(this, ThemePanel, DoubleClickHdl));
445 mxValueSetColors->SetDoubleClickHdl(LINK(this, ThemePanel, DoubleClickValueSetHdl));
446
447 std::vector<FontSet> aFontSets = initFontSets();
448 for (const FontSet & rFontSet : aFontSets)
449 mxListBoxFonts->append_text(rFontSet.maName);
450 mxListBoxFonts->set_size_request(-1, mxListBoxFonts->get_height_rows(aFontSets.size()));
451
453
454 const std::vector<svx::ColorSet>& aColorSets = maColorSets.getColorSets();
455 for (size_t i = 0; i < aColorSets.size(); ++i)
456 {
457 const svx::ColorSet& rColorSet = aColorSets[i];
458
459 const OUString& aName = rColorSet.getName();
460 BitmapEx aPreview = GenerateColorPreview(rColorSet);
461
462 sal_uInt16 nId = i + 1;
463 mxValueSetColors->InsertItem(nId, Image(aPreview), aName);
464 }
465
466 mxValueSetColors->SetOptimalSize();
467
468 if (!aColorSets.empty())
469 mxValueSetColors->SelectItem(1); // ItemId 1, position 0
470}
471
473{
474 mxListBoxFonts.reset();
475 mxValueSetColorsWin.reset();
476 mxValueSetColors.reset();
477 mxApplyButton.reset();
478}
479
481{
482 DoubleClickHdl();
483}
484
485IMPL_LINK_NOARG(ThemePanel, DoubleClickValueSetHdl, ValueSet*, void)
486{
487 DoubleClickHdl();
488}
489
491{
492 DoubleClickHdl();
493 return true;
494}
495
497{
498 SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current());
499 if (!pDocSh)
500 return;
501
502 sal_uInt32 nItemId = mxValueSetColors->GetSelectedItemId();
503 if (!nItemId)
504 return;
505 OUString sEntryFonts = mxListBoxFonts->get_selected_text();
506 sal_uInt32 nIndex = nItemId - 1;
507 OUString sEntryColors = maColorSets.getColorSet(nIndex).getName();
508
509 StyleSet aStyleSet = setupThemes();
510
511 applyTheme(pDocSh->GetStyleSheetPool(), sEntryFonts, sEntryColors, aStyleSet, maColorSets);
512}
513
514void ThemePanel::NotifyItemUpdate(const sal_uInt16 /*nSId*/,
515 const SfxItemState /*eState*/,
516 const SfxPoolItem* /*pState*/)
517{
518}
519
520} // end of namespace ::sw::sidebar
521
522/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
int mnIndex
OUString maName
static OutputDevice * GetDefaultDevice()
static const AllSettings & GetSettings()
void ApplyTintOrShade(sal_Int16 n100thPercent)
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
static SfxObjectShell * Current()
SfxStyleSheetBase * First(SfxStyleFamily eFamily, SfxStyleSearchBits eMask=SfxStyleSearchBits::All)
SfxStyleSheetBase * Next()
const OUString & GetName() const
Represents the style of a text portion.
Definition: charfmt.hxx:27
virtual SfxStyleSheetBasePool * GetStyleSheetPool() override
For Style PI.
Definition: docsh.cxx:1154
SwCharFormat * GetCharFormat()
Definition: docstyle.cxx:2173
SwTextFormatColl * GetCollection()
Definition: docstyle.cxx:2180
Base class for various Writer styles.
Definition: format.hxx:47
const SvxFontItem & GetFont(bool=true) const
Definition: charatr.hxx:122
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:448
const SvxColorItem & GetColor(bool=true) const
Definition: charatr.hxx:128
Represents the style of a paragraph.
Definition: fmtcol.hxx:59
virtual bool SetFormatAttr(const SfxPoolItem &rAttr) override
Override to recognize changes on the <SwNumRuleItem> and register/unregister the paragragh style at t...
Definition: fmtcol.cxx:334
const OUString & getName() const
const Color & getColor(sal_uInt32 nIndex) const
const std::vector< ColorSet > & getColorSets() const
const ColorSet & getColorSet(sal_uInt32 nIndex)
std::unique_ptr< weld::TreeView > mxListBoxFonts
Definition: ThemePanel.hxx:35
virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, const SfxPoolItem *pState) override
Definition: ThemePanel.cxx:514
virtual ~ThemePanel() override
Definition: ThemePanel.cxx:472
svx::ColorSets maColorSets
Definition: ThemePanel.hxx:43
std::unique_ptr< weld::CustomWeld > mxValueSetColorsWin
Definition: ThemePanel.hxx:40
std::unique_ptr< ValueSet > mxValueSetColors
Definition: ThemePanel.hxx:39
std::unique_ptr< weld::Button > mxApplyButton
Definition: ThemePanel.hxx:41
static std::unique_ptr< PanelLayout > Create(weld::Widget *pParent)
Definition: ThemePanel.cxx:424
ThemePanel(weld::Widget *pParent)
Definition: ThemePanel.cxx:432
void SetFontHeight(tools::Long nHeight)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
#define BORDER
Definition: drpcps.cxx:170
float x
FontPitch
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
sal_Int32 nIndex
OUString aName
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
IMPL_LINK_NOARG(PageColumnControl, MoreButtonClickHdl_Impl, weld::Button &, void)
long Long
sal_Int16 nId
OUString maElementName
SfxItemState
#define LABEL_HEIGHT