LibreOffice Module svx (master)  1
StylesPreviewWindow.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <StylesPreviewWindow.hxx>
21 
22 #include <vcl/settings.hxx>
23 #include <vcl/svapp.hxx>
24 #include <sfx2/objsh.hxx>
25 #include <svl/itemset.hxx>
26 #include <sfx2/tbxctrl.hxx>
27 #include <sfx2/sfxsids.hrc>
28 #include <sfx2/tplpitem.hxx>
29 #include <sfx2/viewsh.hxx>
30 #include <vcl/virdev.hxx>
31 
32 #include <editeng/editids.hrc>
33 #include <editeng/fontitem.hxx>
34 #include <editeng/fhgtitem.hxx>
35 #include <editeng/svxfont.hxx>
36 #include <editeng/wghtitem.hxx>
37 #include <editeng/postitem.hxx>
38 #include <editeng/contouritem.hxx>
39 #include <editeng/shdditem.hxx>
41 #include <editeng/udlnitem.hxx>
43 #include <editeng/colritem.hxx>
44 #include <editeng/cmapitem.hxx>
46 #include <editeng/brushitem.hxx>
47 
48 #include <svx/xfillit0.hxx>
49 #include <svx/xdef.hxx>
50 #include <svx/xflclit.hxx>
51 
52 #include <com/sun/star/drawing/FillStyle.hpp>
53 #include <com/sun/star/uno/Sequence.hxx>
54 #include <cppuhelper/weak.hxx>
55 
56 #include <vcl/event.hxx>
57 #include <vcl/commandevent.hxx>
58 
60  StylesPreviewWindow_Base* pPreviewControl,
61  const css::uno::Reference<css::frame::XDispatchProvider>& xDispatchProvider)
62  : SfxStatusListener(xDispatchProvider, SID_STYLE_FAMILY2, ".uno:ParaStyle")
63  , m_pPreviewControl(pPreviewControl)
64 {
65  ReBind();
66 }
67 
69 {
70  const SfxTemplateItem* pStateItem = dynamic_cast<const SfxTemplateItem*>(pState);
71  if (pStateItem)
72  {
73  if (pStateItem->GetStyleIdentifier().isEmpty())
74  m_pPreviewControl->Select(pStateItem->GetStyleName());
75  else
77  }
78 }
79 
81  : SfxListener()
82  , m_pPreviewControl(pPreviewControl)
83 {
85 
86  m_pStyleSheetPool = pDocShell ? pDocShell->GetStyleSheetPool() : nullptr;
87 
89  {
91  }
92 }
93 
95 {
98 }
99 
101 {
103 }
104 
105 StyleItemController::StyleItemController(const std::pair<OUString, OUString>& aStyleName)
106  : m_eStyleFamily(SfxStyleFamily::Para)
107  , m_aStyleName(aStyleName)
108 {
109 }
110 
112 {
113  rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR);
114 
115  DrawEntry(rRenderContext);
116 
117  rRenderContext.Pop();
118 }
119 
121 {
122  if (rEvent.GetCommand() != CommandEventId::ContextMenu)
123  return false;
124 
125  std::unique_ptr<weld::Builder> xBuilder(
126  Application::CreateBuilder(m_xStylesView.get(), "svx/ui/stylemenu.ui"));
127  std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
128  std::string_view rIdent = xMenu->popup_at_rect(
129  m_xStylesView.get(), tools::Rectangle(rEvent.GetMousePosPixel(), Size(1, 1)));
130  if (rIdent == "update" || rIdent == "edit")
131  {
132  css::uno::Sequence<css::beans::PropertyValue> aArgs(0);
133 
135  rIdent == "update" ? OUString(".uno:StyleUpdateByExample")
136  : OUString(".uno:EditStyle"),
137  aArgs);
138 
139  return true;
140  }
141 
142  return false;
143 }
144 
145 static Color GetTextColorFromItemSet(std::unique_ptr<const SfxItemSet> const& pItemSet)
146 {
147  const SfxPoolItem* pItem = pItemSet->GetItem(SID_ATTR_CHAR_COLOR);
148  if (pItem)
149  return static_cast<const SvxColorItem*>(pItem)->GetValue();
150 
151  return COL_AUTO;
152 }
153 
154 static Color GetHighlightColorFromItemSet(std::unique_ptr<const SfxItemSet> const& pItemSet)
155 {
156  const SfxPoolItem* pItem = pItemSet->GetItem(SID_ATTR_BRUSH_CHAR);
157  if (pItem)
158  return static_cast<const SvxBrushItem*>(pItem)->GetColor();
159 
160  return COL_AUTO;
161 }
162 
163 static Color GetBackgroundColorFromItemSet(std::unique_ptr<const SfxItemSet> const& pItemSet)
164 {
165  const SfxPoolItem* pItem = pItemSet->GetItem(XATTR_FILLCOLOR);
166  if (pItem)
167  return static_cast<const XFillColorItem*>(pItem)->GetColorValue();
168 
169  return COL_AUTO;
170 }
171 
172 static css::drawing::FillStyle
173 GetFillStyleFromItemSet(std::unique_ptr<const SfxItemSet> const& pItemSet)
174 {
175  const SfxPoolItem* pItem = pItemSet->GetItem(XATTR_FILLSTYLE);
176  if (pItem)
177  return static_cast<const XFillStyleItem*>(pItem)->GetValue();
178 
179  return css::drawing::FillStyle_NONE;
180 }
181 
182 static SvxFont GetFontFromItems(const SvxFontItem* pFontItem, Size aPixelFontSize,
183  std::unique_ptr<const SfxItemSet> const& pItemSet)
184 {
185  SvxFont aFont;
186 
187  aFont.SetFamilyName(pFontItem->GetFamilyName());
188  aFont.SetStyleName(pFontItem->GetStyleName());
189  aFont.SetFontSize(aPixelFontSize);
190 
191  const SfxPoolItem* pItem = pItemSet->GetItem(SID_ATTR_CHAR_WEIGHT);
192  if (pItem)
193  aFont.SetWeight(static_cast<const SvxWeightItem*>(pItem)->GetWeight());
194 
195  pItem = pItemSet->GetItem(SID_ATTR_CHAR_POSTURE);
196  if (pItem)
197  aFont.SetItalic(static_cast<const SvxPostureItem*>(pItem)->GetPosture());
198 
199  pItem = pItemSet->GetItem(SID_ATTR_CHAR_CONTOUR);
200  if (pItem)
201  aFont.SetOutline(static_cast<const SvxContourItem*>(pItem)->GetValue());
202 
203  pItem = pItemSet->GetItem(SID_ATTR_CHAR_SHADOWED);
204  if (pItem)
205  aFont.SetShadow(static_cast<const SvxShadowedItem*>(pItem)->GetValue());
206 
207  pItem = pItemSet->GetItem(SID_ATTR_CHAR_RELIEF);
208  if (pItem)
209  aFont.SetRelief(static_cast<const SvxCharReliefItem*>(pItem)->GetValue());
210 
211  pItem = pItemSet->GetItem(SID_ATTR_CHAR_UNDERLINE);
212  if (pItem)
213  aFont.SetUnderline(static_cast<const SvxUnderlineItem*>(pItem)->GetLineStyle());
214 
215  pItem = pItemSet->GetItem(SID_ATTR_CHAR_OVERLINE);
216  if (pItem)
217  aFont.SetOverline(static_cast<const SvxOverlineItem*>(pItem)->GetValue());
218 
219  pItem = pItemSet->GetItem(SID_ATTR_CHAR_STRIKEOUT);
220  if (pItem)
221  aFont.SetStrikeout(static_cast<const SvxCrossedOutItem*>(pItem)->GetStrikeout());
222 
223  pItem = pItemSet->GetItem(SID_ATTR_CHAR_CASEMAP);
224  if (pItem)
225  aFont.SetCaseMap(static_cast<const SvxCaseMapItem*>(pItem)->GetCaseMap());
226 
227  pItem = pItemSet->GetItem(SID_ATTR_CHAR_EMPHASISMARK);
228  if (pItem)
229  aFont.SetEmphasisMark(static_cast<const SvxEmphasisMarkItem*>(pItem)->GetEmphasisMark());
230 
231  return aFont;
232 }
233 
235 {
237  if (!pShell)
238  return;
239 
240  SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool();
241  SfxStyleSheetBase* pStyle = nullptr;
242 
243  if (!pPool)
244  return;
245 
246  pStyle = pPool->First(m_eStyleFamily);
247  while (pStyle && pStyle->GetName() != m_aStyleName.first
248  && pStyle->GetName() != m_aStyleName.second)
249  pStyle = pPool->Next();
250 
251  if (!pStyle)
252  return;
253 
254  Size aSize(rRenderContext.GetOutputSizePixel());
255  tools::Rectangle aFullRect(Point(0, 0), aSize);
256  tools::Rectangle aContentRect(aFullRect);
257 
258  Color aOriginalColor = rRenderContext.GetFillColor();
259  Color aOriginalLineColor = rRenderContext.GetLineColor();
260 
261  DrawContentBackground(rRenderContext, aContentRect, aOriginalColor);
262 
263  std::unique_ptr<const SfxItemSet> const pItemSet(pStyle->GetItemSetForPreview());
264  if (!pItemSet)
265  return;
266 
267  Color aFontHighlight = COL_AUTO;
268 
269  const SvxFontItem* const pFontItem = pItemSet->GetItem<SvxFontItem>(SID_ATTR_CHAR_FONT);
270  const SvxFontHeightItem* const pFontHeightItem
271  = pItemSet->GetItem<SvxFontHeightItem>(SID_ATTR_CHAR_FONTHEIGHT);
272 
273  if (pFontItem && pFontHeightItem)
274  {
275  Size aFontSize(0, pFontHeightItem->GetHeight());
276  Size aPixelSize(rRenderContext.LogicToPixel(aFontSize, MapMode(pShell->GetMapUnit())));
277 
278  SvxFont aFont = GetFontFromItems(pFontItem, aPixelSize, pItemSet);
279  rRenderContext.SetFont(aFont);
280 
281  Color aFontCol = GetTextColorFromItemSet(pItemSet);
282  if (aFontCol != COL_AUTO)
283  rRenderContext.SetTextColor(aFontCol);
284 
285  aFontHighlight = GetHighlightColorFromItemSet(pItemSet);
286 
287  css::drawing::FillStyle style = GetFillStyleFromItemSet(pItemSet);
288 
289  switch (style)
290  {
291  case css::drawing::FillStyle_SOLID:
292  {
293  Color aBackCol = GetBackgroundColorFromItemSet(pItemSet);
294  if (aBackCol != COL_AUTO)
295  DrawContentBackground(rRenderContext, aContentRect, aBackCol);
296  }
297  break;
298 
299  default:
300  break;
301  //TODO Draw the other background styles: gradient, hatching and bitmap
302  }
303  }
304 
305  if (aFontHighlight != COL_AUTO)
306  DrawHighlight(rRenderContext, aFontHighlight);
307 
308  DrawText(rRenderContext);
309 
310  rRenderContext.SetFillColor(aOriginalColor);
311  rRenderContext.SetLineColor(aOriginalLineColor);
312 }
313 
315  const tools::Rectangle& aContentRect,
316  const Color& aColor)
317 {
318  rRenderContext.SetLineColor(aColor);
319  rRenderContext.SetFillColor(aColor);
320  rRenderContext.DrawRect(aContentRect);
321 }
322 
324 {
325  tools::Rectangle aTextRect;
326  rRenderContext.GetTextBoundRect(aTextRect, m_aStyleName.second);
327 
328  Size aSize = aTextRect.GetSize();
329  aSize.AdjustHeight(aSize.getHeight());
330  aTextRect.SetSize(aSize);
331 
332  Point aPos(0, 0);
333  aPos.AdjustX(LEFT_MARGIN);
334  aPos.AdjustY((rRenderContext.GetOutputHeightPixel() - aTextRect.Bottom()) / 2);
335  aTextRect.SetPos(aPos);
336 
337  rRenderContext.SetLineColor(aFontBack);
338  rRenderContext.SetFillColor(aFontBack);
339 
340  rRenderContext.DrawRect(aTextRect);
341 }
342 
344 {
345  tools::Rectangle aTextRect;
346  rRenderContext.GetTextBoundRect(aTextRect, m_aStyleName.second);
347 
348  Point aPos(0, 0);
349  aPos.AdjustX(LEFT_MARGIN);
350  aPos.AdjustY((rRenderContext.GetOutputHeightPixel() - aTextRect.Bottom()) / 2);
351 
352  rRenderContext.DrawText(aPos, m_aStyleName.second);
353 }
354 
356  weld::Builder& xBuilder, std::vector<std::pair<OUString, OUString>>& aDefaultStyles,
357  const css::uno::Reference<css::frame::XDispatchProvider>& xDispatchProvider)
358  : m_xDispatchProvider(xDispatchProvider)
359  , m_xStylesView(xBuilder.weld_icon_view("stylesview"))
360  , m_aDefaultStyles(aDefaultStyles)
361 {
362  m_xStylesView->connect_selection_changed(LINK(this, StylesPreviewWindow_Base, Selected));
363  m_xStylesView->connect_item_activated(LINK(this, StylesPreviewWindow_Base, DoubleClick));
364  m_xStylesView->connect_command(LINK(this, StylesPreviewWindow_Base, DoCommand));
365 
366  m_xStatusListener = new StyleStatusListener(this, xDispatchProvider);
367 
369 
371  Update();
372 }
373 
374 IMPL_LINK(StylesPreviewWindow_Base, Selected, weld::IconView&, rIconView, void)
375 {
376  OUString sStyleName = rIconView.get_selected_text();
377 
378  css::uno::Sequence<css::beans::PropertyValue> aArgs(2);
379  aArgs[0].Value <<= sStyleName;
380  aArgs[1].Name = "Family";
381  aArgs[1].Value <<= sal_Int16(SfxStyleFamily::Para);
382 
383  aArgs[0].Name = "Template";
384  SfxToolBoxControl::Dispatch(m_xDispatchProvider, ".uno:StyleApply", aArgs);
385 }
386 
387 IMPL_LINK(StylesPreviewWindow_Base, DoubleClick, weld::IconView&, rIconView, bool)
388 {
389  OUString sStyleName = rIconView.get_selected_text();
390 
391  css::uno::Sequence<css::beans::PropertyValue> aArgs(2);
392  aArgs[0].Name = "Param";
393  aArgs[0].Value <<= sStyleName;
394  aArgs[1].Name = "Family";
395  aArgs[1].Value <<= sal_Int16(SfxStyleFamily::Para);
396 
397  SfxToolBoxControl::Dispatch(m_xDispatchProvider, ".uno:EditStyle", aArgs);
398 
399  return true;
400 }
401 
402 IMPL_LINK(StylesPreviewWindow_Base, DoCommand, const CommandEvent&, rPos, bool)
403 {
404  return Command(rPos);
405 }
406 
408 {
409  m_xStatusListener->UnBind();
410 
411  try
412  {
413  m_xStatusListener->dispose();
414  }
415  catch (css::uno::Exception&)
416  {
417  }
418 
419  m_xStatusListener = nullptr;
420 }
421 
422 void StylesPreviewWindow_Base::Select(const OUString& rStyleName)
423 {
424  m_sSelectedStyle = rStyleName;
425 
426  Update();
427 }
428 
430 {
431  for (std::vector<std::pair<OUString, OUString>>::size_type i = 0; i < m_aAllStyles.size(); ++i)
432  {
434  {
435  m_xStylesView->select(i);
436  break;
437  }
438  }
439 }
440 
442 {
444 
446  SfxStyleSheetBasePool* pStyleSheetPool = nullptr;
447 
448  if (pDocShell)
449  pStyleSheetPool = pDocShell->GetStyleSheetPool();
450 
451  if (pStyleSheetPool)
452  {
453  auto xIter = pStyleSheetPool->CreateIterator(SfxStyleFamily::Para,
454  SfxStyleSearchBits::UserDefined);
455 
456  SfxStyleSheetBase* pStyle = xIter->First();
457 
458  while (pStyle)
459  {
460  m_aAllStyles.push_back(std::pair<OUString, OUString>("", pStyle->GetName()));
461  pStyle = xIter->Next();
462  }
463  }
464 
465  m_xStylesView->clear();
466  for (auto& rStyle : m_aAllStyles)
467  {
469  const Size aSize(100, 30);
470  pImg->SetOutputSizePixel(aSize);
471 
472  StyleItemController aStyleController(rStyle);
473  aStyleController.Paint(*pImg);
474 
475  m_xStylesView->append(rStyle.first, rStyle.second, pImg);
476  }
477 }
478 
480  vcl::Window* pParent, std::vector<std::pair<OUString, OUString>>& aDefaultStyles,
481  const css::uno::Reference<css::frame::XDispatchProvider>& xDispatchProvider)
482  : InterimItemWindow(pParent, "svx/ui/stylespreview.ui", "ApplyStyleBox",
483  reinterpret_cast<sal_uInt64>(SfxViewShell::Current()))
484  , StylesPreviewWindow_Base(*m_xBuilder, aDefaultStyles, xDispatchProvider)
485 {
486  SetOptimalSize();
487 }
488 
490 
492 {
493  m_xStylesView.reset();
494 
496 }
497 
499 
500 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
virtual std::unique_ptr< SfxStyleSheetIterator > CreateIterator(SfxStyleFamily, SfxStyleSearchBits nMask=SfxStyleSearchBits::All)
void SetPos(const Point &rPoint)
StyleStatusListener(StylesPreviewWindow_Base *pPreviewControl, const css::uno::Reference< css::frame::XDispatchProvider > &xDispatchProvider)
SfxStyleSheetBase * First(SfxStyleFamily eFamily, SfxStyleSearchBits eMask=SfxStyleSearchBits::All)
void DrawEntry(vcl::RenderContext &rRenderContext)
bool Command(const CommandEvent &rEvent)
std::vector< std::pair< OUString, OUString > > m_aDefaultStyles
StylesPreviewWindow_Impl(vcl::Window *pParent, std::vector< std::pair< OUString, OUString >> &aDefaultStyles, const css::uno::Reference< css::frame::XDispatchProvider > &xDispatchProvider)
std::string GetValue
std::unique_ptr< StylePoolChangeListener > m_pStylePoolChangeListener
Listener for style selection.
constexpr TypedWhichId< XFillStyleItem > XATTR_FILLSTYLE(XATTR_FILL_FIRST)
constexpr::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
virtual void SetSizePixel(const Size &rNewSize)
static weld::Builder * CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false)
static SfxObjectShell * Current()
static void DrawContentBackground(vcl::RenderContext &rRenderContext, const tools::Rectangle &aContentRect, const Color &aColor)
SfxStyleSheetBasePool * m_pStyleSheetPool
virtual SfxStyleSheetBasePool * GetStyleSheetPool()
const OUString & GetName() const
tools::Long Bottom() const
SfxStyleFamily
constexpr tools::Long getHeight() const
void DrawRect(const tools::Rectangle &rRect)
const OUString & GetStyleName() const
css::uno::Reference< css::frame::XDispatchProvider > m_xDispatchProvider
static SvxFont GetFontFromItems(const SvxFontItem *pFontItem, Size aPixelFontSize, std::unique_ptr< const SfxItemSet > const &pItemSet)
void SetLineColor()
std::vector< std::pair< OUString, OUString > > m_aAllStyles
int i
tools::Long GetOutputHeightPixel() const
static css::drawing::FillStyle GetFillStyleFromItemSet(std::unique_ptr< const SfxItemSet > const &pItemSet)
void SetSize(const Size &rSize)
void SetFillColor()
const Color & GetLineColor() const
static Color GetBackgroundColorFromItemSet(std::unique_ptr< const SfxItemSet > const &pItemSet)
CommandEventId GetCommand() const
void SetTextColor(const Color &rColor)
Size get_preferred_size() const
Size GetOutputSizePixel() const
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
SfxStyleFamily m_eStyleFamily
const OUString & GetStyleName() const
exports com.sun.star. style
const Point & GetMousePosPixel() const
Point LogicToPixel(const Point &rLogicPt) const
std::pair< OUString, OUString > m_aStyleName
void Paint(vcl::RenderContext &rRenderContext)
const OUString & GetFamilyName() const
constexpr TypedWhichId< XFillColorItem > XATTR_FILLCOLOR(XATTR_FILL_FIRST+1)
StylesPreviewWindow_Base * m_pPreviewControl
static constexpr unsigned LEFT_MARGIN
void SetCaseMap(const SvxCaseMap eNew)
void Select(const OUString &rStyleName)
constexpr Size GetSize() const
void DrawHighlight(vcl::RenderContext &rRenderContext, Color aFontBack)
SfxItemState
Listener for styles creation or modification.
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
void SetFont(const vcl::Font &rNewFont)
SfxStyleSheetBase * Next()
virtual void dispose() override
void DrawText(vcl::RenderContext &rRenderContext)
MapUnit GetMapUnit() const
std::unique_ptr< weld::IconView > m_xStylesView
const OUString & GetStyleIdentifier() const
void StateChanged(SfxItemState eState, const SfxPoolItem *pState) override
static VclPtr< reference_type > Create(Arg &&...arg)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
static Color GetTextColorFromItemSet(std::unique_ptr< const SfxItemSet > const &pItemSet)
StylesPreviewWindow_Base * m_pPreviewControl
static Color GetHighlightColorFromItemSet(std::unique_ptr< const SfxItemSet > const &pItemSet)
tools::Long AdjustHeight(tools::Long n)
IMPL_LINK(StylesPreviewWindow_Base, Selected, weld::IconView &, rIconView, void)
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, const tools::Long *pDXArray=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
virtual std::unique_ptr< SfxItemSet > GetItemSetForPreview()
rtl::Reference< StyleStatusListener > m_xStatusListener
StylePoolChangeListener(StylesPreviewWindow_Base *pPreviewControl)
constexpr OUStringLiteral first
void Push(PushFlags nFlags=PushFlags::ALL)
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
StylesPreviewWindow_Base(weld::Builder &xBuilder, std::vector< std::pair< OUString, OUString >> &aDefaultStyles, const css::uno::Reference< css::frame::XDispatchProvider > &xDispatchProvider)
StyleItemController(const std::pair< OUString, OUString > &aStyleName)
void Dispatch(const OUString &aCommand, css::uno::Sequence< css::beans::PropertyValue > const &aArgs)
sal_Int16 GetCaseMap(sal_Int32 nToken)
const Color & GetFillColor() const