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
23 #include <sfx2/sidebar/ControlFactory.hxx>
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
ColorVariable()61 ColorVariable()
62 : mnIndex(-1)
63 , mnTintShade()
64 {}
65
ColorVariable(long nIndex,sal_Int16 nTintShade)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:
StyleRedefinition(const OUString & aElementName)80 explicit StyleRedefinition(const OUString& aElementName)
81 : maElementName(aElementName)
82 {}
83
setColorVariable(ColorVariable aVariable)84 void setColorVariable(ColorVariable aVariable)
85 {
86 maVariable = aVariable;
87 }
88
getColor(svx::ColorSet const & rColorSet)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:
StyleSet()110 explicit StyleSet()
111 : maStyles()
112 {}
113
add(StyleRedefinition const & aRedefinition)114 void add(StyleRedefinition const & aRedefinition)
115 {
116 maStyles.push_back(aRedefinition);
117 }
118
get(const OUString & aString)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
setupThemes()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
changeFont(SwFormat * pFormat,SwDocStyleSheet const * pStyle,FontSet const & rFontSet)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
changeColor(SwTextFormatColl * pCollection,svx::ColorSet const & rColorSet,StyleRedefinition * pRedefinition)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
initFontSets()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
getFontSet(const OUString & rFontVariant,std::vector<FontSet> & aFontSets)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
applyTheme(SfxStyleSheetBasePool * pPool,const OUString & sFontSetName,const OUString & sColorSetName,StyleSet & rStyleSet,svx::ColorSets & rColorSets)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
GenerateColorPreview(const svx::ColorSet & rColorSet)382 BitmapEx GenerateColorPreview(const svx::ColorSet& rColorSet)
383 {
384 ScopedVclPtrInstance<VirtualDevice> pVirtualDev(*Application::GetDefaultDevice());
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
Create(vcl::Window * pParent,const css::uno::Reference<css::frame::XFrame> & rxFrame)416 VclPtr<vcl::Window> ThemePanel::Create (vcl::Window* pParent,
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
ThemePanel(vcl::Window * pParent,const css::uno::Reference<css::frame::XFrame> & rxFrame)427 ThemePanel::ThemePanel(vcl::Window* pParent,
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
436 mpValueSetColors->SetColCount(2);
437 mpValueSetColors->SetLineCount(4);
438
439 mpApplyButton->SetClickHdl(LINK(this, ThemePanel, ClickHdl));
440 mpListBoxFonts->SetDoubleClickHdl(LINK(this, ThemePanel, DoubleClickHdl));
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
~ThemePanel()462 ThemePanel::~ThemePanel()
463 {
464 disposeOnce();
465 }
466
dispose()467 void ThemePanel::dispose()
468 {
469 mpListBoxFonts.clear();
470 mpValueSetColors.clear();
471 mpApplyButton.clear();
472
473 PanelLayout::dispose();
474 }
475
IMPL_LINK_NOARG(ThemePanel,ClickHdl,Button *,void)476 IMPL_LINK_NOARG(ThemePanel, ClickHdl, Button*, void)
477 {
478 DoubleClickHdl();
479 }
IMPL_LINK_NOARG(ThemePanel,DoubleClickValueSetHdl,ValueSet *,void)480 IMPL_LINK_NOARG(ThemePanel, DoubleClickValueSetHdl, ValueSet*, void)
481 {
482 DoubleClickHdl();
483 }
IMPL_LINK_NOARG(ThemePanel,DoubleClickHdl,ListBox &,void)484 IMPL_LINK_NOARG(ThemePanel, DoubleClickHdl, ListBox&, void)
485 {
486 DoubleClickHdl();
487 }
DoubleClickHdl()488 void ThemePanel::DoubleClickHdl()
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
NotifyItemUpdate(const sal_uInt16,const SfxItemState,const SfxPoolItem *)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: */
512