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