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