Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / cui / source / dialogs / FontFeaturesDialog.cxx
blobe9aba0a6e4097ce13c94b62369578791fc7cf658
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 */
11 #include <FontFeaturesDialog.hxx>
12 #include <rtl/ustrbuf.hxx>
13 #include <utility>
14 #include <vcl/font/FeatureParser.hxx>
15 #include <FontFeatures.hxx>
16 #include <unordered_set>
18 using namespace css;
20 namespace cui
22 FontFeaturesDialog::FontFeaturesDialog(weld::Window* pParent, OUString aFontName)
23 : GenericDialogController(pParent, "cui/ui/fontfeaturesdialog.ui", "FontFeaturesDialog")
24 , m_sFontName(std::move(aFontName))
25 , m_xContentWindow(m_xBuilder->weld_scrolled_window("contentWindow"))
26 , m_xContentBox(m_xBuilder->weld_container("contentBox"))
27 , m_xContentGrid(m_xBuilder->weld_container("contentGrid"))
28 , m_xStylisticSetsBox(m_xBuilder->weld_container("stylisticSetsBox"))
29 , m_xStylisticSetsGrid(m_xBuilder->weld_container("stylisticSetsGrid"))
30 , m_xCharacterVariantsBox(m_xBuilder->weld_container("characterVariantsBox"))
31 , m_xCharacterVariantsGrid(m_xBuilder->weld_container("characterVariantsGrid"))
32 , m_xPreviewWindow(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWindow))
34 initialize();
37 FontFeaturesDialog::~FontFeaturesDialog() {}
39 static sal_Int32 makeEnumComboBox(weld::ComboBox& rNameBox,
40 vcl::font::FeatureDefinition const& rFeatureDefinition,
41 uint32_t nDefault)
43 sal_Int32 nRes = 0;
44 int count = 0;
45 for (vcl::font::FeatureParameter const& rParameter : rFeatureDefinition.getEnumParameters())
47 rNameBox.append(OUString::number(rParameter.getCode()), rParameter.getDescription());
48 if (rParameter.getCode() == nDefault)
49 nRes = count;
50 ++count;
52 return nRes;
55 void FontFeaturesDialog::initialize()
57 ScopedVclPtrInstance<VirtualDevice> aVDev(*Application::GetDefaultDevice(),
58 DeviceFormat::WITH_ALPHA);
59 std::vector<vcl::font::Feature> rFontFeatures = getFontFeatureList(m_sFontName, *aVDev);
61 std::unordered_set<sal_uInt32> aDoneFeatures;
62 std::vector<vcl::font::Feature> rFilteredFontFeatures;
64 for (vcl::font::Feature const& rFontFeature : rFontFeatures)
66 sal_uInt32 nFontFeatureCode = rFontFeature.m_nCode;
67 if (!aDoneFeatures.insert(nFontFeatureCode).second)
68 continue;
69 rFilteredFontFeatures.push_back(rFontFeature);
72 int nRowHeight = fillGrid(rFilteredFontFeatures);
74 auto nFeaturesHeight = m_xContentBox->get_preferred_size().Height()
75 + m_xStylisticSetsBox->get_preferred_size().Height()
76 + m_xCharacterVariantsBox->get_preferred_size().Height();
77 m_xContentWindow->set_size_request(
78 -1, std::min(std::max(m_xContentWindow->get_preferred_size().Height(), nFeaturesHeight),
79 static_cast<tools::Long>(300L)));
81 if (nRowHeight)
83 // tdf#141333 use row height + the 6 px spacing of contentGrid
84 m_xContentWindow->vadjustment_set_step_increment(nRowHeight + 6);
87 updateFontPreview();
90 int FontFeaturesDialog::fillGrid(std::vector<vcl::font::Feature> const& rFontFeatures)
92 int nRowHeight(0);
94 vcl::font::FeatureParser aParser(m_sFontName);
95 auto aExistingFeatures = aParser.getFeaturesMap();
97 sal_Int32 nIdx, nStylisticSets(0), nCharacterVariants(0), nOtherFeatures(0);
98 for (vcl::font::Feature const& rFontFeature : rFontFeatures)
100 sal_uInt32 nFontFeatureCode = rFontFeature.m_nCode;
102 vcl::font::FeatureDefinition aDefinition;
103 if (rFontFeature.m_aDefinition)
104 aDefinition = rFontFeature.m_aDefinition;
105 if (!aDefinition)
106 aDefinition = { nFontFeatureCode, "" };
108 if (rFontFeature.isStylisticSet())
110 nIdx = nStylisticSets++;
111 m_xStylisticSetsBox->set_visible(true);
112 m_aFeatureItems.emplace_back(
113 std::make_unique<FontFeatureItem>(m_xStylisticSetsGrid.get()));
115 else if (rFontFeature.isCharacterVariant())
117 nIdx = nCharacterVariants++;
118 m_xCharacterVariantsBox->set_visible(true);
119 m_aFeatureItems.emplace_back(
120 std::make_unique<FontFeatureItem>(m_xCharacterVariantsGrid.get()));
122 else
124 nIdx = nOtherFeatures++;
125 m_xContentBox->set_visible(true);
126 m_aFeatureItems.emplace_back(std::make_unique<FontFeatureItem>(m_xContentGrid.get()));
129 int32_t nValue = 0;
130 if (aExistingFeatures.find(nFontFeatureCode) != aExistingFeatures.end())
131 nValue = aExistingFeatures.at(nFontFeatureCode);
132 else
133 nValue = aDefinition.getDefault();
135 FontFeatureItem& aCurrentItem = *m_aFeatureItems.back();
136 aCurrentItem.m_aFeatureCode = nFontFeatureCode;
137 aCurrentItem.m_nDefault = aDefinition.getDefault();
139 sal_Int32 nGridPositionX = (nIdx % 2) * 2;
140 sal_Int32 nGridPositionY = nIdx / 2;
141 aCurrentItem.m_xContainer->set_grid_left_attach(nGridPositionX);
142 aCurrentItem.m_xContainer->set_grid_top_attach(nGridPositionY);
144 Link<weld::ComboBox&, void> aComboBoxSelectHandler
145 = LINK(this, FontFeaturesDialog, ComboBoxSelectedHdl);
146 Link<weld::Toggleable&, void> aCheckBoxToggleHandler
147 = LINK(this, FontFeaturesDialog, CheckBoxToggledHdl);
149 if (aDefinition.getType() == vcl::font::FeatureParameterType::ENUM)
151 aCurrentItem.m_xText->set_label(aDefinition.getDescription());
152 aCurrentItem.m_xText->show();
154 sal_Int32 nInit = makeEnumComboBox(*aCurrentItem.m_xCombo, aDefinition, nValue);
156 aCurrentItem.m_xCombo->set_active(nInit);
157 aCurrentItem.m_xCombo->connect_changed(aComboBoxSelectHandler);
158 aCurrentItem.m_xCombo->show();
160 else
162 if (nValue < 0)
164 aCurrentItem.m_xCheck->set_state(TRISTATE_INDET);
165 aCurrentItem.m_aTriStateEnabled.bTriStateEnabled = true;
166 aCurrentItem.m_aTriStateEnabled.eState = TRISTATE_INDET;
168 else
170 aCurrentItem.m_xCheck->set_state(nValue > 0 ? TRISTATE_TRUE : TRISTATE_FALSE);
171 aCurrentItem.m_aTriStateEnabled.bTriStateEnabled = false;
172 aCurrentItem.m_aTriStateEnabled.eState = aCurrentItem.m_xCheck->get_state();
174 aCurrentItem.m_xCheck->set_label(aDefinition.getDescription());
175 aCurrentItem.m_aToggleHdl = aCheckBoxToggleHandler;
176 aCurrentItem.m_xCheck->show();
179 nRowHeight
180 = std::max<int>(nRowHeight, aCurrentItem.m_xContainer->get_preferred_size().Height());
183 return nRowHeight;
186 void FontFeaturesDialog::updateFontPreview()
188 vcl::Font rPreviewFont = m_aPreviewWindow.GetFont();
189 vcl::Font rPreviewFontCJK = m_aPreviewWindow.GetCJKFont();
190 vcl::Font rPreviewFontCTL = m_aPreviewWindow.GetCTLFont();
192 OUString sNewFontName = createFontNameWithFeatures();
194 rPreviewFont.SetFamilyName(sNewFontName);
195 rPreviewFontCJK.SetFamilyName(sNewFontName);
196 rPreviewFontCTL.SetFamilyName(sNewFontName);
198 m_aPreviewWindow.SetFont(rPreviewFont, rPreviewFontCJK, rPreviewFontCTL);
201 IMPL_LINK(FontFeatureItem, CheckBoxToggledHdl, weld::Toggleable&, rToggle, void)
203 m_aTriStateEnabled.ButtonToggled(rToggle);
204 m_aTriStateEnabled.bTriStateEnabled = false;
205 m_aToggleHdl.Call(rToggle);
208 IMPL_LINK_NOARG(FontFeaturesDialog, CheckBoxToggledHdl, weld::Toggleable&, void)
210 updateFontPreview();
213 IMPL_LINK_NOARG(FontFeaturesDialog, ComboBoxSelectedHdl, weld::ComboBox&, void)
215 updateFontPreview();
218 OUString FontFeaturesDialog::createFontNameWithFeatures()
220 OUString sResultFontName;
221 OUStringBuffer sNameSuffix;
222 bool bFirst = true;
224 for (const auto& rEntry : m_aFeatureItems)
226 const FontFeatureItem& rItem(*rEntry);
227 if (rItem.m_xCheck->get_visible())
229 if (rItem.m_xCheck->get_state() != TRISTATE_INDET)
231 if (!bFirst)
232 sNameSuffix.append(vcl::font::FeatureSeparator);
233 else
234 bFirst = false;
236 sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode));
237 if (rItem.m_xCheck->get_state() == TRISTATE_FALSE)
238 sNameSuffix.append("=0");
241 else if (rItem.m_xCombo->get_visible() && rItem.m_xText->get_visible())
243 sal_Int32 nSelection = rItem.m_xCombo->get_active_id().toInt32();
244 if (nSelection != int(rItem.m_nDefault))
246 if (!bFirst)
247 sNameSuffix.append(vcl::font::FeatureSeparator);
248 else
249 bFirst = false;
251 sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode) + "="
252 + OUString::number(nSelection));
256 sResultFontName = vcl::font::trimFontNameFeatures(m_sFontName);
257 if (!sNameSuffix.isEmpty())
258 sResultFontName += OUStringChar(vcl::font::FeaturePrefix) + sNameSuffix;
259 return sResultFontName;
262 short FontFeaturesDialog::run()
264 short nResult = GenericDialogController::run();
265 if (nResult == RET_OK)
267 m_sResultFontName = createFontNameWithFeatures();
269 return nResult;
272 } // end svx namespace
274 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */