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/svapp.hxx>
23 #include <vcl/virdev.hxx>
24 #include <charatr.hxx>
25 #include <charfmt.hxx>
26 #include <docsh.hxx>
27 #include <docstyle.hxx>
28 #include <fmtcol.hxx>
29 #include <format.hxx>
30 
31 namespace
32 {
33 
34 class FontSet
35 {
36 public:
37  OUString maName;
38  OUString msMonoFont;
39  OUString msHeadingFont;
40  OUString msBaseFont;
41 };
42 
43 class ColorVariable
44 {
45 public:
46  long mnIndex;
47  sal_Int16 mnTintShade;
48 
49  ColorVariable()
50  : mnIndex(-1)
51  , mnTintShade()
52  {}
53 
54  ColorVariable(long nIndex, sal_Int16 nTintShade)
55  : mnIndex(nIndex)
56  , mnTintShade(nTintShade)
57  {}
58 };
59 
60 class StyleRedefinition
61 {
62  ColorVariable maVariable;
63 
64 public:
65  OUString maElementName;
66 
67 public:
68  explicit StyleRedefinition(const OUString& aElementName)
69  : maElementName(aElementName)
70  {}
71 
72  void setColorVariable(ColorVariable aVariable)
73  {
74  maVariable = aVariable;
75  }
76 
77  Color getColor(svx::ColorSet const & rColorSet)
78  {
79  Color aColor;
80  if (maVariable.mnIndex > -1)
81  {
82  aColor = rColorSet.getColor(maVariable.mnIndex);
83  aColor.ApplyTintOrShade(maVariable.mnTintShade);
84  }
85  else
86  {
87  aColor = COL_BLACK;
88  }
89  return aColor;
90  }
91 };
92 
93 class StyleSet
94 {
95  std::vector<StyleRedefinition> maStyles;
96 
97 public:
98  explicit StyleSet()
99  : maStyles()
100  {}
101 
102  void add(StyleRedefinition const & aRedefinition)
103  {
104  maStyles.push_back(aRedefinition);
105  }
106 
107  StyleRedefinition* get(const OUString& 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 
120 StyleSet 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 
187 void 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 
231 void 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 
240 std::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 = "Open Sans";
302  aFontSet.msHeadingFont = "Open Sans";
303  aFontSet.msBaseFont = "Open Sans";
304  aFontSet.msMonoFont = "Droid Sans 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 
318 FontSet getFontSet(const OUString& 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 
328 void applyTheme(SfxStyleSheetBasePool* pPool, const OUString& sFontSetName, const OUString& 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 
366 BitmapEx GenerateColorPreview(const svx::ColorSet& rColorSet)
367 {
369  float fScaleFactor = pVirtualDev->GetDPIScaleFactor();
370  long BORDER = 2 * fScaleFactor;
371  long SIZE = 12 * fScaleFactor;
372 
373  Size aSize(BORDER * 7 + SIZE * 6, BORDER * 3 + SIZE * 2);
374  pVirtualDev->SetOutputSizePixel(aSize);
375 
376  long x = BORDER;
377  long y1 = BORDER;
378  long y2 = y1 + SIZE + BORDER;
379 
380  pVirtualDev->SetLineColor(COL_LIGHTGRAY);
381 
382  for (sal_uInt32 i = 0; i < 12; i += 2)
383  {
384  pVirtualDev->SetFillColor(rColorSet.getColor(i));
385  pVirtualDev->DrawRect(tools::Rectangle(x, y1, x + SIZE, y1 + SIZE));
386 
387  pVirtualDev->SetFillColor(rColorSet.getColor(i + 1));
388  pVirtualDev->DrawRect(tools::Rectangle(x, y2, x + SIZE, y2 + SIZE));
389 
390  x += SIZE + BORDER;
391  }
392 
393  return pVirtualDev->GetBitmapEx(Point(), aSize);
394 }
395 
396 } // end anonymous namespace
397 
398 namespace sw::sidebar {
399 
401  const css::uno::Reference<css::frame::XFrame>& rxFrame)
402 {
403  if (pParent == nullptr)
404  throw css::lang::IllegalArgumentException("no parent Window given to PagePropertyPanel::Create", nullptr, 0);
405  if (!rxFrame.is())
406  throw css::lang::IllegalArgumentException("no XFrame given to PagePropertyPanel::Create", nullptr, 1);
407 
408  return VclPtr<ThemePanel>::Create(pParent, rxFrame);
409 }
410 
412  const css::uno::Reference<css::frame::XFrame>& rxFrame)
413  : PanelLayout(pParent, "ThemePanel", "modules/swriter/ui/sidebartheme.ui", rxFrame)
414  , mxListBoxFonts(m_xBuilder->weld_tree_view("listbox_fonts"))
415  , mxValueSetColors(new ValueSet(nullptr))
416  , mxValueSetColorsWin(new weld::CustomWeld(*m_xBuilder, "valueset_colors", *mxValueSetColors))
417  , mxApplyButton(m_xBuilder->weld_button("apply"))
418  , maColorSets()
419 {
420  mxValueSetColors->SetColCount(2);
421  mxValueSetColors->SetLineCount(3);
422 
423  mxApplyButton->connect_clicked(LINK(this, ThemePanel, ClickHdl));
424  mxListBoxFonts->connect_row_activated(LINK(this, ThemePanel, DoubleClickHdl));
425  mxValueSetColors->SetDoubleClickHdl(LINK(this, ThemePanel, DoubleClickValueSetHdl));
426 
427  std::vector<FontSet> aFontSets = initFontSets();
428  for (const FontSet & rFontSet : aFontSets)
429  mxListBoxFonts->append_text(rFontSet.maName);
430  mxListBoxFonts->set_size_request(-1, mxListBoxFonts->get_height_rows(aFontSets.size()));
431 
432  maColorSets.init();
433 
434  const std::vector<svx::ColorSet>& aColorSets = maColorSets.getColorSets();
435  for (size_t i = 0; i < aColorSets.size(); ++i)
436  {
437  const svx::ColorSet& rColorSet = aColorSets[i];
438 
439  const OUString& aName = rColorSet.getName();
440  BitmapEx aPreview = GenerateColorPreview(rColorSet);
441 
442  sal_uInt16 nId = i + 1;
443  mxValueSetColors->InsertItem(nId, Image(aPreview), aName);
444  }
445 
446  mxValueSetColors->SetOptimalSize();
447 
448  if (!aColorSets.empty())
449  mxValueSetColors->SelectItem(1); // ItemId 1, position 0
450 }
451 
453 {
454  disposeOnce();
455 }
456 
458 {
459  mxListBoxFonts.reset();
460  mxValueSetColorsWin.reset();
461  mxValueSetColors.reset();
462  mxApplyButton.reset();
463 
465 }
466 
468 {
469  DoubleClickHdl();
470 }
471 
472 IMPL_LINK_NOARG(ThemePanel, DoubleClickValueSetHdl, ValueSet*, void)
473 {
474  DoubleClickHdl();
475 }
476 
477 IMPL_LINK_NOARG(ThemePanel, DoubleClickHdl, weld::TreeView&, bool)
478 {
479  DoubleClickHdl();
480  return true;
481 }
482 
484 {
485  SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current());
486  if (!pDocSh)
487  return;
488 
489  sal_uInt32 nItemId = mxValueSetColors->GetSelectedItemId();
490  if (!nItemId)
491  return;
492  OUString sEntryFonts = mxListBoxFonts->get_selected_text();
493  sal_uInt32 nIndex = nItemId - 1;
494  OUString sEntryColors = maColorSets.getColorSet(nIndex).getName();
495 
496  StyleSet aStyleSet = setupThemes();
497 
498  applyTheme(pDocSh->GetStyleSheetPool(), sEntryFonts, sEntryColors, aStyleSet, maColorSets);
499 }
500 
501 void ThemePanel::NotifyItemUpdate(const sal_uInt16 /*nSId*/,
502  const SfxItemState /*eState*/,
503  const SfxPoolItem* /*pState*/)
504 {
505 }
506 
507 } // end of namespace ::sw::sidebar
508 
509 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxStyleSheetBase * First(SfxStyleFamily eFamily, SfxStyleSearchBits eMask=SfxStyleSearchBits::All)
const SvxColorItem & GetColor(bool=true) const
Definition: charatr.hxx:129
sal_Int32 nIndex
Represents the style of a paragraph.
Definition: fmtcol.hxx:55
virtual ~ThemePanel() override
Definition: ThemePanel.cxx:452
static VclPtr< vcl::Window > Create(vcl::Window *pParent, const css::uno::Reference< css::frame::XFrame > &rxFrame)
Definition: ThemePanel.cxx:400
const SvxFontItem & GetFont(bool=true) const
Definition: charatr.hxx:123
sal_Int16 nId
static SfxObjectShell * Current()
std::unique_ptr< weld::Button > mxApplyButton
Definition: ThemePanel.hxx:48
virtual bool SetFormatAttr(const SfxPoolItem &rAttr) override
Override to recognize changes on the and register/unregister the paragragh style at t...
Definition: fmtcol.cxx:329
float x
FontPitch GetPitch() const
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
static OutputDevice * GetDefaultDevice()
const OUString & GetName() const
void ApplyTintOrShade(sal_Int16 n100thPercent)
virtual void dispose() override
Definition: ThemePanel.cxx:457
ThemePanel(vcl::Window *pParent, const css::uno::Reference< css::frame::XFrame > &rxFrame)
Definition: ThemePanel.cxx:411
SwCharFormat * GetCharFormat()
Definition: docstyle.cxx:2154
const ColorSet & getColorSet(sal_uInt32 nIndex)
Base class for various Writer styles.
Definition: format.hxx:43
#define BORDER
Definition: drpcps.cxx:172
int i
virtual SfxStyleSheetBasePool * GetStyleSheetPool() override
For Style PI.
Definition: docsh.cxx:1139
std::unique_ptr< weld::TreeView > mxListBoxFonts
Definition: ThemePanel.hxx:45
const OUString & getName() const
virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, const SfxPoolItem *pState) override
Definition: ThemePanel.cxx:501
std::unique_ptr< ValueSet > mxValueSetColors
Definition: ThemePanel.hxx:46
IMPL_LINK_NOARG(PageColumnControl, MoreButtonClickHdl_Impl, weld::Button &, void)
FontPitch
const std::vector< ColorSet > & getColorSets() const
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:458
virtual void dispose() override
SwTextFormatColl * GetCollection()
Definition: docstyle.cxx:2161
SfxItemState
std::unique_ptr< weld::CustomWeld > mxValueSetColorsWin
Definition: ThemePanel.hxx:47
svx::ColorSets maColorSets
Definition: ThemePanel.hxx:50
SfxStyleSheetBase * Next()
OUString maName
OUString aName
const Color & getColor(sal_uInt32 nIndex) const
static VclPtr< reference_type > Create(Arg &&...arg)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
OUString maElementName
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
int mnIndex
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
void SetValue(const Color &rNewColor)