tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / cui / source / dialogs / FontFeaturesDialog.cxx
blobfeb7f401025c5c6734839eb3ed258b948f0ab222
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, u"cui/ui/fontfeaturesdialog.ui"_ustr,
24 u"FontFeaturesDialog"_ustr)
25 , m_sFontName(std::move(aFontName))
26 , m_xContentWindow(m_xBuilder->weld_scrolled_window(u"contentWindow"_ustr))
27 , m_xContentBox(m_xBuilder->weld_container(u"contentBox"_ustr))
28 , m_xContentGrid(m_xBuilder->weld_container(u"contentGrid"_ustr))
29 , m_xStylisticSetsBox(m_xBuilder->weld_container(u"stylisticSetsBox"_ustr))
30 , m_xStylisticSetsGrid(m_xBuilder->weld_container(u"stylisticSetsGrid"_ustr))
31 , m_xCharacterVariantsBox(m_xBuilder->weld_container(u"characterVariantsBox"_ustr))
32 , m_xCharacterVariantsGrid(m_xBuilder->weld_container(u"characterVariantsGrid"_ustr))
33 , m_xPreviewWindow(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWindow))
35 initialize();
38 FontFeaturesDialog::~FontFeaturesDialog() {}
40 static sal_Int32 makeEnumComboBox(weld::ComboBox& rNameBox,
41 vcl::font::FeatureDefinition const& rFeatureDefinition,
42 uint32_t nDefault)
44 sal_Int32 nRes = 0;
45 int count = 0;
46 for (vcl::font::FeatureParameter const& rParameter : rFeatureDefinition.getEnumParameters())
48 rNameBox.append(OUString::number(rParameter.getCode()), rParameter.getDescription());
49 if (rParameter.getCode() == nDefault)
50 nRes = count;
51 ++count;
53 return nRes;
56 void FontFeaturesDialog::initialize()
58 ScopedVclPtrInstance<VirtualDevice> aVDev(*Application::GetDefaultDevice(),
59 DeviceFormat::WITH_ALPHA);
60 std::vector<vcl::font::Feature> rFontFeatures = getFontFeatureList(m_sFontName, *aVDev);
62 std::unordered_set<sal_uInt32> aDoneFeatures;
63 std::vector<vcl::font::Feature> rFilteredFontFeatures;
65 for (vcl::font::Feature const& rFontFeature : rFontFeatures)
67 sal_uInt32 nFontFeatureCode = rFontFeature.m_nCode;
68 if (!aDoneFeatures.insert(nFontFeatureCode).second)
69 continue;
70 rFilteredFontFeatures.push_back(rFontFeature);
73 int nRowHeight = fillGrid(rFilteredFontFeatures);
75 auto nFeaturesHeight = m_xContentBox->get_preferred_size().Height()
76 + m_xStylisticSetsBox->get_preferred_size().Height()
77 + m_xCharacterVariantsBox->get_preferred_size().Height();
78 m_xContentWindow->set_size_request(
79 -1, std::min(std::max(m_xContentWindow->get_preferred_size().Height(), nFeaturesHeight),
80 static_cast<tools::Long>(300L)));
82 if (nRowHeight)
84 // tdf#141333 use row height + the 6 px spacing of contentGrid
85 m_xContentWindow->vadjustment_set_step_increment(nRowHeight + 6);
88 updateFontPreview();
91 int FontFeaturesDialog::fillGrid(std::vector<vcl::font::Feature> const& rFontFeatures)
93 int nRowHeight(0);
95 vcl::font::FeatureParser aParser(m_sFontName);
96 auto aExistingFeatures = aParser.getFeaturesMap();
98 sal_Int32 nIdx, nStylisticSets(0), nCharacterVariants(0), nOtherFeatures(0);
99 for (vcl::font::Feature const& rFontFeature : rFontFeatures)
101 sal_uInt32 nFontFeatureCode = rFontFeature.m_nCode;
103 vcl::font::FeatureDefinition aDefinition;
104 if (rFontFeature.m_aDefinition)
105 aDefinition = rFontFeature.m_aDefinition;
106 if (!aDefinition)
107 aDefinition = { nFontFeatureCode, u""_ustr };
109 if (rFontFeature.isStylisticSet())
111 nIdx = nStylisticSets++;
112 m_xStylisticSetsBox->set_visible(true);
113 m_aFeatureItems.emplace_back(
114 std::make_unique<FontFeatureItem>(m_xStylisticSetsGrid.get()));
116 else if (rFontFeature.isCharacterVariant())
118 nIdx = nCharacterVariants++;
119 m_xCharacterVariantsBox->set_visible(true);
120 m_aFeatureItems.emplace_back(
121 std::make_unique<FontFeatureItem>(m_xCharacterVariantsGrid.get()));
123 else
125 nIdx = nOtherFeatures++;
126 m_xContentBox->set_visible(true);
127 m_aFeatureItems.emplace_back(std::make_unique<FontFeatureItem>(m_xContentGrid.get()));
130 int32_t nValue = 0;
131 if (aExistingFeatures.find(nFontFeatureCode) != aExistingFeatures.end())
132 nValue = aExistingFeatures.at(nFontFeatureCode);
133 else
134 nValue = aDefinition.getDefault();
136 FontFeatureItem& aCurrentItem = *m_aFeatureItems.back();
137 aCurrentItem.m_aFeatureCode = nFontFeatureCode;
138 aCurrentItem.m_nDefault = aDefinition.getDefault();
140 sal_Int32 nGridPositionX = (nIdx % 2) * 2;
141 sal_Int32 nGridPositionY = nIdx / 2;
142 aCurrentItem.m_xContainer->set_grid_left_attach(nGridPositionX);
143 aCurrentItem.m_xContainer->set_grid_top_attach(nGridPositionY);
145 Link<weld::ComboBox&, void> aComboBoxSelectHandler
146 = LINK(this, FontFeaturesDialog, ComboBoxSelectedHdl);
147 Link<weld::Toggleable&, void> aCheckBoxToggleHandler
148 = LINK(this, FontFeaturesDialog, CheckBoxToggledHdl);
150 if (aDefinition.getType() == vcl::font::FeatureParameterType::ENUM)
152 aCurrentItem.m_xText->set_label(aDefinition.getDescription());
153 aCurrentItem.m_xText->show();
155 sal_Int32 nInit = makeEnumComboBox(*aCurrentItem.m_xCombo, aDefinition, nValue);
157 aCurrentItem.m_xCombo->set_active(nInit);
158 aCurrentItem.m_xCombo->connect_changed(aComboBoxSelectHandler);
159 aCurrentItem.m_xCombo->show();
161 else
163 if (nValue < 0)
165 aCurrentItem.m_xCheck->set_state(TRISTATE_INDET);
166 aCurrentItem.m_aTriStateEnabled.bTriStateEnabled = true;
167 aCurrentItem.m_aTriStateEnabled.eState = TRISTATE_INDET;
169 else
171 aCurrentItem.m_xCheck->set_state(nValue > 0 ? TRISTATE_TRUE : TRISTATE_FALSE);
172 aCurrentItem.m_aTriStateEnabled.bTriStateEnabled = false;
173 aCurrentItem.m_aTriStateEnabled.eState = aCurrentItem.m_xCheck->get_state();
175 aCurrentItem.m_xCheck->set_label(aDefinition.getDescription());
176 aCurrentItem.m_aToggleHdl = aCheckBoxToggleHandler;
177 aCurrentItem.m_xCheck->show();
180 nRowHeight
181 = std::max<int>(nRowHeight, aCurrentItem.m_xContainer->get_preferred_size().Height());
184 return nRowHeight;
187 void FontFeaturesDialog::updateFontPreview()
189 vcl::Font rPreviewFont = m_aPreviewWindow.GetFont();
190 vcl::Font rPreviewFontCJK = m_aPreviewWindow.GetCJKFont();
191 vcl::Font rPreviewFontCTL = m_aPreviewWindow.GetCTLFont();
193 OUString sNewFontName = createFontNameWithFeatures();
195 rPreviewFont.SetFamilyName(sNewFontName);
196 rPreviewFontCJK.SetFamilyName(sNewFontName);
197 rPreviewFontCTL.SetFamilyName(sNewFontName);
199 m_aPreviewWindow.SetFont(rPreviewFont, rPreviewFontCJK, rPreviewFontCTL);
202 IMPL_LINK(FontFeatureItem, CheckBoxToggledHdl, weld::Toggleable&, rToggle, void)
204 m_aTriStateEnabled.ButtonToggled(rToggle);
205 m_aTriStateEnabled.bTriStateEnabled = false;
206 m_aToggleHdl.Call(rToggle);
209 IMPL_LINK_NOARG(FontFeaturesDialog, CheckBoxToggledHdl, weld::Toggleable&, void)
211 updateFontPreview();
214 IMPL_LINK_NOARG(FontFeaturesDialog, ComboBoxSelectedHdl, weld::ComboBox&, void)
216 updateFontPreview();
219 OUString FontFeaturesDialog::createFontNameWithFeatures()
221 OUString sResultFontName;
222 OUStringBuffer sNameSuffix;
223 bool bFirst = true;
225 for (const auto& rEntry : m_aFeatureItems)
227 const FontFeatureItem& rItem(*rEntry);
228 if (rItem.m_xCheck->get_visible())
230 if (rItem.m_xCheck->get_state() != TRISTATE_INDET)
232 if (!bFirst)
233 sNameSuffix.append(vcl::font::FeatureSeparator);
234 else
235 bFirst = false;
237 sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode));
238 if (rItem.m_xCheck->get_state() == TRISTATE_FALSE)
239 sNameSuffix.append("=0");
242 else if (rItem.m_xCombo->get_visible() && rItem.m_xText->get_visible())
244 sal_Int32 nSelection = rItem.m_xCombo->get_active_id().toInt32();
245 if (nSelection != int(rItem.m_nDefault))
247 if (!bFirst)
248 sNameSuffix.append(vcl::font::FeatureSeparator);
249 else
250 bFirst = false;
252 sNameSuffix.append(vcl::font::featureCodeAsString(rItem.m_aFeatureCode) + "="
253 + OUString::number(nSelection));
257 sResultFontName = vcl::font::trimFontNameFeatures(m_sFontName);
258 if (!sNameSuffix.isEmpty())
259 sResultFontName += OUStringChar(vcl::font::FeaturePrefix) + sNameSuffix;
260 return sResultFontName;
263 short FontFeaturesDialog::run()
265 short nResult = GenericDialogController::run();
266 if (nResult == RET_OK)
268 m_sResultFontName = createFontNameWithFeatures();
270 return nResult;
273 } // end svx namespace
275 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */