xref: /core/sw/source/uibase/sidebar/StylePresetsPanel.cxx (revision 09ac3cf793129a3cddfbb798419c2e309ad755eb)
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 "StylePresetsPanel.hxx"
14 
15 #include <vcl/image.hxx>
16 #include <vcl/settings.hxx>
17 #include <vcl/svapp.hxx>
18 #include <vcl/virdev.hxx>
19 
20 #include <sfx2/objsh.hxx>
21 #include <sfx2/StylePreviewRenderer.hxx>
22 
23 #include <com/sun/star/lang/IllegalArgumentException.hpp>
24 
25 #include <sfx2/doctempl.hxx>
26 
27 #include <shellio.hxx>
28 #include <docsh.hxx>
29 
30 #include <sfx2/docfile.hxx>
31 
32 namespace sw::sidebar {
33 
34 namespace {
35 
renderPreview(sfx2::StyleManager * pStyleManager,OutputDevice & aOutputDevice,std::u16string_view sName,sal_Int32 nHeight,tools::Rectangle const & aRect)36 void renderPreview(sfx2::StyleManager* pStyleManager, OutputDevice& aOutputDevice,
37                    std::u16string_view sName, sal_Int32 nHeight, tools::Rectangle const & aRect)
38 {
39     SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(sName, SfxStyleFamily::Para);
40 
41     if (pStyleSheet)
42     {
43         std::unique_ptr<sfx2::StylePreviewRenderer> pStylePreviewRenderer
44             = pStyleManager->CreateStylePreviewRenderer(aOutputDevice, pStyleSheet, nHeight);
45         pStylePreviewRenderer->recalculate();
46         pStylePreviewRenderer->render(aRect, sfx2::StylePreviewRenderer::RenderAlign::TOP);
47     }
48 }
49 
GenerateStylePreview(SfxObjectShell & rSource,OUString const & aName)50 Bitmap GenerateStylePreview(SfxObjectShell& rSource, OUString const & aName)
51 {
52     sfx2::StyleManager* pStyleManager = rSource.GetStyleManager();
53 
54     ScopedVclPtrInstance<VirtualDevice> pVirtualDev(*Application::GetDefaultDevice());
55 
56     float fScalingFactor = pVirtualDev->GetDPIScaleFactor();
57 
58     sal_Int32 nMargin = 6 * fScalingFactor;
59 
60     sal_Int32 nPreviewWidth = 144 * fScalingFactor;
61 
62     sal_Int32 nNameHeight = 16 * fScalingFactor;
63     sal_Int32 nTitleHeight = 32 * fScalingFactor;
64     sal_Int32 nHeadingHeight = 24 * fScalingFactor;
65     sal_Int32 nTextBodyHeight = 16 * fScalingFactor;
66     sal_Int32 nBottomMargin = 2 * fScalingFactor;
67 
68     sal_Int32 nNameFontSize = 12 * fScalingFactor;
69 
70     sal_Int32 nPreviewHeight = nNameHeight + nTitleHeight + nHeadingHeight + nTextBodyHeight + nBottomMargin;
71 
72     Size aSize(nPreviewWidth, nPreviewHeight);
73 
74     pVirtualDev->SetOutputSizePixel(aSize);
75 
76     pVirtualDev->SetLineColor(COL_LIGHTGRAY);
77     pVirtualDev->SetFillColor();
78 
79     tools::Long y = 0;
80     {
81         pVirtualDev->SetFillColor(COL_LIGHTGRAY);
82         tools::Rectangle aNameRect(0, y, nPreviewWidth, nNameHeight);
83         pVirtualDev->DrawRect(aNameRect);
84 
85         vcl::Font aFont;
86         aFont.SetFontSize(Size(0, nNameFontSize));
87 
88         pVirtualDev->SetFont(aFont);
89 
90         Size aTextSize(pVirtualDev->GetTextWidth(aName), pVirtualDev->GetTextHeight());
91 
92         Point aPoint((aNameRect.GetWidth()  / 2.0) - (aTextSize.Width()  / 2.0),
93                      y + (aNameRect.GetHeight() / 2.0) - (aTextSize.Height() / 2.0));
94 
95         pVirtualDev->DrawText(aPoint, aName);
96 
97         y += nNameHeight;
98     }
99 
100     {
101         tools::Rectangle aRenderRect(Point(nMargin, y), aSize);
102         renderPreview(pStyleManager, *pVirtualDev, u"Title", nTitleHeight, aRenderRect);
103         y += nTitleHeight;
104     }
105 
106     {
107         tools::Rectangle aRenderRect(Point(nMargin, y), aSize);
108         renderPreview(pStyleManager, *pVirtualDev, u"Heading 1", nHeadingHeight, aRenderRect);
109         y += nHeadingHeight;
110     }
111     {
112         tools::Rectangle aRenderRect(Point(nMargin, y), aSize);
113         renderPreview(pStyleManager, *pVirtualDev, u"Body Text", nTextBodyHeight, aRenderRect);
114     }
115 
116     return pVirtualDev->GetBitmap(Point(), aSize);
117 }
118 
CreatePreview(OUString const & aUrl,OUString const & aName)119 Bitmap CreatePreview(OUString const & aUrl, OUString const & aName)
120 {
121     if (SfxObjectShell* pObjectShell = SfxObjectShell::Current())
122     {
123         SfxMedium aMedium(aUrl, StreamMode::STD_READWRITE);
124         SfxObjectShellLock xTemplDoc = SfxObjectShell::CreateObjectByFactoryName(pObjectShell->GetFactory().GetFactoryName(), SfxObjectCreateMode::ORGANIZER);
125         xTemplDoc->DoInitNew();
126         if (xTemplDoc->LoadFrom(aMedium))
127             return GenerateStylePreview(*xTemplDoc, aName);
128     }
129     return Bitmap();
130 }
131 
132 }
133 
Create(weld::Widget * pParent)134 std::unique_ptr<PanelLayout> StylePresetsPanel::Create(weld::Widget* pParent)
135 {
136     if (pParent == nullptr)
137         throw css::lang::IllegalArgumentException(u"no parent Window given to StylePresetsPanel::Create"_ustr, nullptr, 0);
138 
139     return std::make_unique<StylePresetsPanel>(pParent);
140 }
141 
StylePresetsPanel(weld::Widget * pParent)142 StylePresetsPanel::StylePresetsPanel(weld::Widget* pParent)
143     : PanelLayout(pParent, u"StylePresetsPanel"_ustr, u"modules/swriter/ui/sidebarstylepresets.ui"_ustr)
144     , mxValueSet(new ValueSet(nullptr))
145     , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *mxValueSet))
146 {
147     mxValueSet->SetColCount(2);
148 
149     mxValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFaceColor());
150     mxValueSet->SetDoubleClickHdl(LINK(this, StylePresetsPanel, DoubleClickHdl));
151 
152     RefreshList();
153 }
154 
RefreshList()155 void StylePresetsPanel::RefreshList()
156 {
157     SfxDocumentTemplates aTemplates;
158     sal_uInt16 nCount = aTemplates.GetRegionCount();
159     for (sal_uInt16 i = 0; i < nCount; ++i)
160     {
161         OUString aRegionName(aTemplates.GetFullRegionName(i));
162         if (aRegionName == "Styles")
163         {
164             for (sal_uInt16 j = 0; j < aTemplates.GetCount(i); ++j)
165             {
166                 OUString aName = aTemplates.GetName(i,j);
167                 OUString aURL = aTemplates.GetPath(i,j);
168                 Bitmap aPreview = CreatePreview(aURL, aName);
169                 sal_uInt16 nId = j + 1;
170                 mxValueSet->InsertItem(nId, Image(aPreview), aName);
171                 maTemplateEntries.push_back(std::make_unique<TemplateEntry>(aURL));
172                 mxValueSet->SetItemData(nId, maTemplateEntries.back().get());
173             }
174             mxValueSet->SetOptimalSize();
175         }
176     }
177 }
178 
~StylePresetsPanel()179 StylePresetsPanel::~StylePresetsPanel()
180 {
181 }
182 
IMPL_LINK_NOARG(StylePresetsPanel,DoubleClickHdl,ValueSet *,void)183 IMPL_LINK_NOARG(StylePresetsPanel, DoubleClickHdl, ValueSet*, void)
184 {
185     sal_Int32 nItemId = mxValueSet->GetSelectedItemId();
186     TemplateEntry* pEntry = static_cast<TemplateEntry*>(mxValueSet->GetItemData(nItemId));
187 
188     if (SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current()))
189     {
190         SwgReaderOption aOption;
191         aOption.SetTextFormats(true);
192         aOption.SetNumRules(true);
193         pDocSh->LoadStylesFromFile(pEntry->maURL, aOption, false);
194     }
195 }
196 
NotifyItemUpdate(const sal_uInt16,const SfxItemState,const SfxPoolItem *)197 void StylePresetsPanel::NotifyItemUpdate(const sal_uInt16 /*nSId*/,
198                                          const SfxItemState /*eState*/,
199                                          const SfxPoolItem* /*pState*/)
200 {
201 }
202 
203 } // end of namespace ::sw::sidebar
204 
205 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
206