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  * 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 <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <cassert>
24 
25 #include <comphelper/string.hxx>
26 #include <svl/eitem.hxx>
27 #include <svl/intitem.hxx>
28 #include <svl/stritem.hxx>
29 #include <vcl/event.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/virdev.hxx>
32 #include <vcl/weld.hxx>
33 #include <svtools/ctrltool.hxx>
34 #include <vcl/settings.hxx>
35 #include <vcl/wall.hxx>
36 #include <vcl/fontcharmap.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <svx/charmap.hxx>
39 #include <svx/ucsubset.hxx>
40 
41 #include <dialog.hxx>
42 #include <starmath.hrc>
43 #include <strings.hrc>
44 #include <helpids.h>
45 #include "cfgitem.hxx"
46 #include <smmod.hxx>
47 #include <symbol.hxx>
48 #include <view.hxx>
49 
50 #include <algorithm>
51 
52 namespace
53 {
54 
lclGetSettingColors(Color & rBackgroundColor,Color & rTextColor)55 void lclGetSettingColors(Color& rBackgroundColor, Color& rTextColor)
56 {
57     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
58     if (rStyleSettings.GetHighContrastMode())
59     {
60         rBackgroundColor = rStyleSettings.GetFieldColor();
61         rTextColor = rStyleSettings.GetFieldTextColor();
62     }
63     else
64     {
65         rBackgroundColor = COL_WHITE;
66         rTextColor = COL_BLACK;
67     }
68 }
69 
70 } // end anonymous namespace
71 
72 // Since it's better to set/query the FontStyle via its attributes rather
73 // than via the StyleName we create a way to translate
74 // Attribute <-> StyleName
75 
76 class SmFontStyles
77 {
78     OUString const aNormal;
79     OUString const aBold;
80     OUString const aItalic;
81     OUString aBoldItalic;
82 
83 public:
84     SmFontStyles();
85 
GetCount()86     static sal_uInt16 GetCount() { return 4; }
87     const OUString& GetStyleName(const vcl::Font& rFont) const;
88     const OUString& GetStyleName(sal_uInt16 nIdx) const;
89 };
90 
SmFontStyles()91 SmFontStyles::SmFontStyles()
92     : aNormal(SmResId(RID_FONTREGULAR))
93     , aBold(SmResId(RID_FONTBOLD))
94     , aItalic(SmResId(RID_FONTITALIC))
95 {
96     aBoldItalic = aBold;
97     aBoldItalic += ", ";
98     aBoldItalic += aItalic;
99 }
100 
GetStyleName(const vcl::Font & rFont) const101 const OUString& SmFontStyles::GetStyleName(const vcl::Font& rFont) const
102 {
103     //! compare also SmSpecialNode::Prepare
104     bool bBold   = IsBold( rFont ),
105          bItalic = IsItalic( rFont );
106 
107     if (bBold && bItalic)
108         return aBoldItalic;
109     else if (bItalic)
110         return aItalic;
111     else if (bBold)
112         return aBold;
113     return aNormal;
114 }
115 
GetStyleName(sal_uInt16 nIdx) const116 const OUString& SmFontStyles::GetStyleName( sal_uInt16 nIdx ) const
117 {
118     // 0 = "normal",  1 = "italic",
119     // 2 = "bold",    3 = "bold italic"
120 
121     assert( nIdx < GetCount() );
122     switch (nIdx)
123     {
124         case 0 : return aNormal;
125         case 1 : return aItalic;
126         case 2 : return aBold;
127         default: /*case 3:*/ return aBoldItalic;
128     }
129 }
130 
GetFontStyles()131 static const SmFontStyles & GetFontStyles()
132 {
133     static const SmFontStyles aImpl;
134     return aImpl;
135 }
136 
SetFontStyle(const OUString & rStyleName,vcl::Font & rFont)137 void SetFontStyle(const OUString &rStyleName, vcl::Font &rFont)
138 {
139     // Find index related to StyleName. For an empty StyleName it's assumed to be
140     // 0 (neither bold nor italic).
141     sal_uInt16  nIndex = 0;
142     if (!rStyleName.isEmpty())
143     {
144         sal_uInt16 i;
145         const SmFontStyles &rStyles = GetFontStyles();
146         for (i = 0;  i < SmFontStyles::GetCount(); ++i)
147             if (rStyleName == rStyles.GetStyleName(i))
148                 break;
149         assert(i < SmFontStyles::GetCount() && "style-name unknown");
150         nIndex = i;
151     }
152 
153     rFont.SetItalic((nIndex & 0x1) ? ITALIC_NORMAL : ITALIC_NONE);
154     rFont.SetWeight((nIndex & 0x2) ? WEIGHT_BOLD : WEIGHT_NORMAL);
155 }
156 
IMPL_LINK_NOARG(SmPrintOptionsTabPage,SizeButtonClickHdl,weld::ToggleButton &,void)157 IMPL_LINK_NOARG(SmPrintOptionsTabPage, SizeButtonClickHdl, weld::ToggleButton&, void)
158 {
159     m_xZoom->set_sensitive(m_xSizeZoomed->get_active());
160 }
161 
SmPrintOptionsTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rOptions)162 SmPrintOptionsTabPage::SmPrintOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rOptions)
163     : SfxTabPage(pPage, pController, "modules/smath/ui/smathsettings.ui", "SmathSettings", &rOptions)
164     , m_xTitle(m_xBuilder->weld_check_button("title"))
165     , m_xText(m_xBuilder->weld_check_button("text"))
166     , m_xFrame(m_xBuilder->weld_check_button("frame"))
167     , m_xSizeNormal(m_xBuilder->weld_radio_button("sizenormal"))
168     , m_xSizeScaled(m_xBuilder->weld_radio_button("sizescaled"))
169     , m_xSizeZoomed(m_xBuilder->weld_radio_button("sizezoomed"))
170     , m_xZoom(m_xBuilder->weld_metric_spin_button("zoom", FieldUnit::PERCENT))
171     , m_xNoRightSpaces(m_xBuilder->weld_check_button("norightspaces"))
172     , m_xSaveOnlyUsedSymbols(m_xBuilder->weld_check_button("saveonlyusedsymbols"))
173     , m_xAutoCloseBrackets(m_xBuilder->weld_check_button("autoclosebrackets"))
174 {
175     m_xSizeNormal->connect_toggled(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl));
176     m_xSizeScaled->connect_toggled(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl));
177     m_xSizeZoomed->connect_toggled(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl));
178 
179     Reset(&rOptions);
180 }
181 
~SmPrintOptionsTabPage()182 SmPrintOptionsTabPage::~SmPrintOptionsTabPage()
183 {
184 }
185 
FillItemSet(SfxItemSet * rSet)186 bool SmPrintOptionsTabPage::FillItemSet(SfxItemSet* rSet)
187 {
188     sal_uInt16  nPrintSize;
189     if (m_xSizeNormal->get_active())
190         nPrintSize = PRINT_SIZE_NORMAL;
191     else if (m_xSizeScaled->get_active())
192         nPrintSize = PRINT_SIZE_SCALED;
193     else
194         nPrintSize = PRINT_SIZE_ZOOMED;
195 
196     rSet->Put(SfxUInt16Item(GetWhich(SID_PRINTSIZE), nPrintSize));
197     rSet->Put(SfxUInt16Item(GetWhich(SID_PRINTZOOM), sal::static_int_cast<sal_uInt16>(m_xZoom->get_value(FieldUnit::PERCENT))));
198     rSet->Put(SfxBoolItem(GetWhich(SID_PRINTTITLE), m_xTitle->get_active()));
199     rSet->Put(SfxBoolItem(GetWhich(SID_PRINTTEXT), m_xText->get_active()));
200     rSet->Put(SfxBoolItem(GetWhich(SID_PRINTFRAME), m_xFrame->get_active()));
201     rSet->Put(SfxBoolItem(GetWhich(SID_NO_RIGHT_SPACES), m_xNoRightSpaces->get_active()));
202     rSet->Put(SfxBoolItem(GetWhich(SID_SAVE_ONLY_USED_SYMBOLS), m_xSaveOnlyUsedSymbols->get_active()));
203     rSet->Put(SfxBoolItem(GetWhich(SID_AUTO_CLOSE_BRACKETS), m_xAutoCloseBrackets->get_active()));
204 
205     return true;
206 }
207 
Reset(const SfxItemSet * rSet)208 void SmPrintOptionsTabPage::Reset(const SfxItemSet* rSet)
209 {
210     SmPrintSize ePrintSize = static_cast<SmPrintSize>(static_cast<const SfxUInt16Item &>(rSet->Get(GetWhich(SID_PRINTSIZE))).GetValue());
211 
212     m_xSizeNormal->set_active(ePrintSize == PRINT_SIZE_NORMAL);
213     m_xSizeScaled->set_active(ePrintSize == PRINT_SIZE_SCALED);
214     m_xSizeZoomed->set_active(ePrintSize == PRINT_SIZE_ZOOMED);
215 
216     m_xZoom->set_sensitive(m_xSizeZoomed->get_active());
217 
218     m_xZoom->set_value(static_cast<const SfxUInt16Item &>(rSet->Get(GetWhich(SID_PRINTZOOM))).GetValue(), FieldUnit::PERCENT);
219 
220     m_xTitle->set_active(static_cast<const SfxBoolItem &>(rSet->Get(GetWhich(SID_PRINTTITLE))).GetValue());
221     m_xNoRightSpaces->set_active(static_cast<const SfxBoolItem &>(rSet->Get(GetWhich(SID_NO_RIGHT_SPACES))).GetValue());
222     m_xSaveOnlyUsedSymbols->set_active(static_cast<const SfxBoolItem &>(rSet->Get(GetWhich(SID_SAVE_ONLY_USED_SYMBOLS))).GetValue());
223     m_xAutoCloseBrackets->set_active(static_cast<const SfxBoolItem &>(rSet->Get(GetWhich(SID_AUTO_CLOSE_BRACKETS))).GetValue());
224 }
225 
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)226 std::unique_ptr<SfxTabPage> SmPrintOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
227 {
228     return std::make_unique<SmPrintOptionsTabPage>(pPage, pController, rSet);
229 }
230 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)231 void SmShowFont::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
232 {
233     Color aBackColor;
234     Color aTextColor;
235     lclGetSettingColors(aBackColor, aTextColor);
236 
237     rRenderContext.SetBackground(Wallpaper(aBackColor));
238 
239     vcl::Font aFont(maFont);
240     aFont.SetFontSize(Size(0, 24 * rRenderContext.GetDPIScaleFactor()));
241     aFont.SetAlignment(ALIGN_TOP);
242     rRenderContext.SetFont(aFont);
243     rRenderContext.SetTextColor(aTextColor);
244 
245     OUString sText(rRenderContext.GetFont().GetFamilyName());
246     Size aTextSize(rRenderContext.GetTextWidth(sText), rRenderContext.GetTextHeight());
247 
248     rRenderContext.DrawText(Point((rRenderContext.GetOutputSize().Width()  - aTextSize.Width())  / 2,
249                                   (rRenderContext.GetOutputSize().Height() - aTextSize.Height()) / 2), sText);
250 }
251 
SetDrawingArea(weld::DrawingArea * pDrawingArea)252 void SmShowFont::SetDrawingArea(weld::DrawingArea* pDrawingArea)
253 {
254     CustomWidgetController::SetDrawingArea(pDrawingArea);
255     Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(111 , 31), MapMode(MapUnit::MapAppFont)));
256     pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
257 }
258 
SetFont(const vcl::Font & rFont)259 void SmShowFont::SetFont(const vcl::Font& rFont)
260 {
261     maFont = rFont;
262     Invalidate();
263 }
264 
IMPL_LINK(SmFontDialog,FontSelectHdl,weld::ComboBox &,rComboBox,void)265 IMPL_LINK( SmFontDialog, FontSelectHdl, weld::ComboBox&, rComboBox, void )
266 {
267     maFont.SetFamilyName(rComboBox.get_active_text());
268     m_aShowFont.SetFont(maFont);
269 }
270 
IMPL_LINK_NOARG(SmFontDialog,AttrChangeHdl,weld::ToggleButton &,void)271 IMPL_LINK_NOARG(SmFontDialog, AttrChangeHdl, weld::ToggleButton&, void)
272 {
273     if (m_xBoldCheckBox->get_active())
274         maFont.SetWeight(WEIGHT_BOLD);
275     else
276         maFont.SetWeight(WEIGHT_NORMAL);
277 
278     if (m_xItalicCheckBox->get_active())
279         maFont.SetItalic(ITALIC_NORMAL);
280     else
281         maFont.SetItalic(ITALIC_NONE);
282 
283     m_aShowFont.SetFont(maFont);
284 }
285 
SetFont(const vcl::Font & rFont)286 void SmFontDialog::SetFont(const vcl::Font &rFont)
287 {
288     maFont = rFont;
289 
290     m_xFontBox->set_active_text(maFont.GetFamilyName());
291     m_xBoldCheckBox->set_active(IsBold(maFont));
292     m_xItalicCheckBox->set_active(IsItalic(maFont));
293     m_aShowFont.SetFont(maFont);
294 }
295 
SmFontDialog(weld::Window * pParent,OutputDevice * pFntListDevice,bool bHideCheckboxes)296 SmFontDialog::SmFontDialog(weld::Window * pParent, OutputDevice *pFntListDevice, bool bHideCheckboxes)
297     : GenericDialogController(pParent, "modules/smath/ui/fontdialog.ui", "FontDialog")
298     , m_xFontBox(m_xBuilder->weld_entry_tree_view("fontgrid", "font", "fonts"))
299     , m_xAttrFrame(m_xBuilder->weld_widget("attrframe"))
300     , m_xBoldCheckBox(m_xBuilder->weld_check_button("bold"))
301     , m_xItalicCheckBox(m_xBuilder->weld_check_button("italic"))
302     , m_xShowFont(new weld::CustomWeld(*m_xBuilder, "preview", m_aShowFont))
303 {
304     m_xFontBox->set_height_request_by_rows(8);
305 
306     {
307         weld::WaitObject aWait(pParent);
308 
309         FontList aFontList( pFntListDevice );
310 
311         sal_uInt16  nCount = aFontList.GetFontNameCount();
312         for (sal_uInt16 i = 0;  i < nCount; ++i)
313         {
314             m_xFontBox->append_text(aFontList.GetFontName(i).GetFamilyName());
315         }
316         maFont.SetFontSize(Size(0, 24));
317         maFont.SetWeight(WEIGHT_NORMAL);
318         maFont.SetItalic(ITALIC_NONE);
319         maFont.SetFamily(FAMILY_DONTKNOW);
320         maFont.SetPitch(PITCH_DONTKNOW);
321         maFont.SetCharSet(RTL_TEXTENCODING_DONTKNOW);
322         maFont.SetTransparent(true);
323     }
324 
325     m_xFontBox->connect_changed(LINK(this, SmFontDialog, FontSelectHdl));
326     m_xBoldCheckBox->connect_toggled(LINK(this, SmFontDialog, AttrChangeHdl));
327     m_xItalicCheckBox->connect_toggled(LINK(this, SmFontDialog, AttrChangeHdl));
328 
329     if (bHideCheckboxes)
330     {
331         m_xBoldCheckBox->set_active(false);
332         m_xBoldCheckBox->set_sensitive(false);
333         m_xItalicCheckBox->set_active(false);
334         m_xItalicCheckBox->set_sensitive(false);
335         m_xAttrFrame->hide();
336     }
337 }
338 
~SmFontDialog()339 SmFontDialog::~SmFontDialog()
340 {
341 }
342 
343 class SaveDefaultsQuery : public weld::MessageDialogController
344 {
345 public:
SaveDefaultsQuery(weld::Widget * pParent)346     explicit SaveDefaultsQuery(weld::Widget* pParent)
347         : MessageDialogController(pParent, "modules/smath/ui/savedefaultsdialog.ui",
348                 "SaveDefaultsDialog")
349     {
350     }
351 };
352 
IMPL_LINK_NOARG(SmFontSizeDialog,DefaultButtonClickHdl,weld::Button &,void)353 IMPL_LINK_NOARG( SmFontSizeDialog, DefaultButtonClickHdl, weld::Button&, void )
354 {
355     SaveDefaultsQuery aQuery(m_xDialog.get());
356     if (aQuery.run() == RET_YES)
357     {
358         SmModule *pp = SM_MOD();
359         SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
360         WriteTo( aFmt );
361         pp->GetConfig()->SetStandardFormat( aFmt );
362     }
363 }
364 
SmFontSizeDialog(weld::Window * pParent)365 SmFontSizeDialog::SmFontSizeDialog(weld::Window* pParent)
366     : GenericDialogController(pParent, "modules/smath/ui/fontsizedialog.ui", "FontSizeDialog")
367     , m_xBaseSize(m_xBuilder->weld_metric_spin_button("spinB_baseSize", FieldUnit::POINT))
368     , m_xTextSize(m_xBuilder->weld_metric_spin_button("spinB_text", FieldUnit::PERCENT))
369     , m_xIndexSize(m_xBuilder->weld_metric_spin_button("spinB_index", FieldUnit::PERCENT))
370     , m_xFunctionSize(m_xBuilder->weld_metric_spin_button("spinB_function", FieldUnit::PERCENT))
371     , m_xOperatorSize(m_xBuilder->weld_metric_spin_button("spinB_operator", FieldUnit::PERCENT))
372     , m_xBorderSize(m_xBuilder->weld_metric_spin_button("spinB_limit", FieldUnit::PERCENT))
373     , m_xDefaultButton(m_xBuilder->weld_button("default"))
374 {
375     m_xDefaultButton->connect_clicked(LINK(this, SmFontSizeDialog, DefaultButtonClickHdl));
376 }
377 
~SmFontSizeDialog()378 SmFontSizeDialog::~SmFontSizeDialog()
379 {
380 }
381 
ReadFrom(const SmFormat & rFormat)382 void SmFontSizeDialog::ReadFrom(const SmFormat &rFormat)
383 {
384     //! watch out: round properly!
385     m_xBaseSize->set_value( SmRoundFraction(
386         Sm100th_mmToPts( rFormat.GetBaseSize().Height() ) ), FieldUnit::NONE );
387 
388     m_xTextSize->set_value( rFormat.GetRelSize(SIZ_TEXT), FieldUnit::NONE );
389     m_xIndexSize->set_value( rFormat.GetRelSize(SIZ_INDEX), FieldUnit::NONE );
390     m_xFunctionSize->set_value( rFormat.GetRelSize(SIZ_FUNCTION), FieldUnit::NONE );
391     m_xOperatorSize->set_value( rFormat.GetRelSize(SIZ_OPERATOR), FieldUnit::NONE );
392     m_xBorderSize->set_value( rFormat.GetRelSize(SIZ_LIMITS), FieldUnit::NONE );
393 }
394 
WriteTo(SmFormat & rFormat) const395 void SmFontSizeDialog::WriteTo(SmFormat &rFormat) const
396 {
397     rFormat.SetBaseSize( Size(0, SmPtsTo100th_mm( static_cast< long >(m_xBaseSize->get_value(FieldUnit::NONE)))) );
398 
399     rFormat.SetRelSize(SIZ_TEXT,     sal::static_int_cast<sal_uInt16>(m_xTextSize->get_value(FieldUnit::NONE)));
400     rFormat.SetRelSize(SIZ_INDEX,    sal::static_int_cast<sal_uInt16>(m_xIndexSize->get_value(FieldUnit::NONE)));
401     rFormat.SetRelSize(SIZ_FUNCTION, sal::static_int_cast<sal_uInt16>(m_xFunctionSize->get_value(FieldUnit::NONE)));
402     rFormat.SetRelSize(SIZ_OPERATOR, sal::static_int_cast<sal_uInt16>(m_xOperatorSize->get_value(FieldUnit::NONE)));
403     rFormat.SetRelSize(SIZ_LIMITS,   sal::static_int_cast<sal_uInt16>(m_xBorderSize->get_value(FieldUnit::NONE)));
404 
405     const Size aTmp (rFormat.GetBaseSize());
406     for (sal_uInt16  i = FNT_BEGIN;  i <= FNT_END;  i++)
407         rFormat.SetFontSize(i, aTmp);
408 
409     rFormat.RequestApplyChanges();
410 }
411 
IMPL_LINK(SmFontTypeDialog,MenuSelectHdl,const OString &,rIdent,void)412 IMPL_LINK(SmFontTypeDialog, MenuSelectHdl, const OString&, rIdent, void)
413 {
414     SmFontPickListBox *pActiveListBox;
415 
416     bool bHideCheckboxes = false;
417     if (rIdent == "variables")
418         pActiveListBox = m_xVariableFont.get();
419     else if (rIdent == "functions")
420         pActiveListBox = m_xFunctionFont.get();
421     else if (rIdent == "numbers")
422         pActiveListBox = m_xNumberFont.get();
423     else if (rIdent == "text")
424         pActiveListBox = m_xTextFont.get();
425     else if (rIdent == "serif")
426     {
427         pActiveListBox = m_xSerifFont.get();
428         bHideCheckboxes = true;
429     }
430     else if (rIdent == "sansserif")
431     {
432         pActiveListBox = m_xSansFont.get();
433         bHideCheckboxes = true;
434     }
435     else if (rIdent == "fixedwidth")
436     {
437         pActiveListBox = m_xFixedFont.get();
438         bHideCheckboxes = true;
439     }
440     else
441         pActiveListBox = nullptr;
442 
443     if (pActiveListBox)
444     {
445         SmFontDialog aFontDialog(m_xDialog.get(), pFontListDev, bHideCheckboxes);
446 
447         pActiveListBox->WriteTo(aFontDialog);
448         if (aFontDialog.run() == RET_OK)
449             pActiveListBox->ReadFrom(aFontDialog);
450     }
451 }
452 
IMPL_LINK_NOARG(SmFontTypeDialog,DefaultButtonClickHdl,weld::Button &,void)453 IMPL_LINK_NOARG(SmFontTypeDialog, DefaultButtonClickHdl, weld::Button&, void)
454 {
455     SaveDefaultsQuery aQuery(m_xDialog.get());
456     if (aQuery.run() == RET_YES)
457     {
458         SmModule *pp = SM_MOD();
459         SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
460         WriteTo( aFmt );
461         pp->GetConfig()->SetStandardFormat( aFmt, true );
462     }
463 }
464 
SmFontTypeDialog(weld::Window * pParent,OutputDevice * pFntListDevice)465 SmFontTypeDialog::SmFontTypeDialog(weld::Window* pParent, OutputDevice *pFntListDevice)
466     : GenericDialogController(pParent, "modules/smath/ui/fonttypedialog.ui", "FontsDialog")
467     , pFontListDev(pFntListDevice)
468     , m_xVariableFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("variableCB")))
469     , m_xFunctionFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("functionCB")))
470     , m_xNumberFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("numberCB")))
471     , m_xTextFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("textCB")))
472     , m_xSerifFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("serifCB")))
473     , m_xSansFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("sansCB")))
474     , m_xFixedFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("fixedCB")))
475     , m_xMenuButton(m_xBuilder->weld_menu_button("modify"))
476     , m_xDefaultButton(m_xBuilder->weld_button("default"))
477 {
478     m_xDefaultButton->connect_clicked(LINK(this, SmFontTypeDialog, DefaultButtonClickHdl));
479     m_xMenuButton->connect_selected(LINK(this, SmFontTypeDialog, MenuSelectHdl));
480 }
481 
~SmFontTypeDialog()482 SmFontTypeDialog::~SmFontTypeDialog()
483 {
484 }
485 
ReadFrom(const SmFormat & rFormat)486 void SmFontTypeDialog::ReadFrom(const SmFormat &rFormat)
487 {
488     SmModule *pp = SM_MOD();
489 
490     *m_xVariableFont = pp->GetConfig()->GetFontPickList(FNT_VARIABLE);
491     *m_xFunctionFont = pp->GetConfig()->GetFontPickList(FNT_FUNCTION);
492     *m_xNumberFont   = pp->GetConfig()->GetFontPickList(FNT_NUMBER);
493     *m_xTextFont     = pp->GetConfig()->GetFontPickList(FNT_TEXT);
494     *m_xSerifFont    = pp->GetConfig()->GetFontPickList(FNT_SERIF);
495     *m_xSansFont     = pp->GetConfig()->GetFontPickList(FNT_SANS);
496     *m_xFixedFont    = pp->GetConfig()->GetFontPickList(FNT_FIXED);
497 
498     m_xVariableFont->Insert( rFormat.GetFont(FNT_VARIABLE) );
499     m_xFunctionFont->Insert( rFormat.GetFont(FNT_FUNCTION) );
500     m_xNumberFont->Insert( rFormat.GetFont(FNT_NUMBER) );
501     m_xTextFont->Insert( rFormat.GetFont(FNT_TEXT) );
502     m_xSerifFont->Insert( rFormat.GetFont(FNT_SERIF) );
503     m_xSansFont->Insert( rFormat.GetFont(FNT_SANS) );
504     m_xFixedFont->Insert( rFormat.GetFont(FNT_FIXED) );
505 }
506 
507 
WriteTo(SmFormat & rFormat) const508 void SmFontTypeDialog::WriteTo(SmFormat &rFormat) const
509 {
510     SmModule *pp = SM_MOD();
511 
512     pp->GetConfig()->GetFontPickList(FNT_VARIABLE) = *m_xVariableFont;
513     pp->GetConfig()->GetFontPickList(FNT_FUNCTION) = *m_xFunctionFont;
514     pp->GetConfig()->GetFontPickList(FNT_NUMBER)   = *m_xNumberFont;
515     pp->GetConfig()->GetFontPickList(FNT_TEXT)     = *m_xTextFont;
516     pp->GetConfig()->GetFontPickList(FNT_SERIF)    = *m_xSerifFont;
517     pp->GetConfig()->GetFontPickList(FNT_SANS)     = *m_xSansFont;
518     pp->GetConfig()->GetFontPickList(FNT_FIXED)    = *m_xFixedFont;
519 
520     rFormat.SetFont( FNT_VARIABLE, m_xVariableFont->Get() );
521     rFormat.SetFont( FNT_FUNCTION, m_xFunctionFont->Get() );
522     rFormat.SetFont( FNT_NUMBER,   m_xNumberFont->Get() );
523     rFormat.SetFont( FNT_TEXT,     m_xTextFont->Get() );
524     rFormat.SetFont( FNT_SERIF,    m_xSerifFont->Get() );
525     rFormat.SetFont( FNT_SANS,     m_xSansFont->Get() );
526     rFormat.SetFont( FNT_FIXED,    m_xFixedFont->Get() );
527 
528     rFormat.RequestApplyChanges();
529 }
530 
531 /**************************************************************************/
532 
533 struct FieldMinMax
534 {
535     sal_uInt16 nMin, nMax;
536 };
537 
538 // Data for min and max values of the 4 metric fields
539 // for each of the 10 categories
540 static const FieldMinMax pMinMaxData[10][4] =
541 {
542     // 0
543     {{ 0, 200 },    { 0, 200 },     { 0, 100 },     { 0, 0 }},
544     // 1
545     {{ 0, 100 },    { 0, 100 },     { 0, 0 },       { 0, 0 }},
546     // 2
547     {{ 0, 100 },    { 0, 100 },     { 0, 0 },       { 0, 0 }},
548     // 3
549     {{ 0, 100 },    { 1, 100 },     { 0, 0 },       { 0, 0 }},
550     // 4
551     {{ 0, 100 },    { 0, 100 },     { 0, 0 },       { 0, 0 }},
552     // 5
553     {{ 0, 100 },    { 0, 100 },     { 0, 0 },       { 0, 100 }},
554     // 6
555     {{ 0, 300 },    { 0, 300 },     { 0, 0 },       { 0, 0 }},
556     // 7
557     {{ 0, 100 },    { 0, 100 },     { 0, 0 },       { 0, 0 }},
558     // 8
559     {{ 0, 100 },    { 0, 100 },     { 0, 0 },       { 0, 0 }},
560     // 9
561     {{ 0, 10000 },  { 0, 10000 },   { 0, 10000 },   { 0, 10000 }}
562 };
563 
SmCategoryDesc(weld::Builder & rBuilder,sal_uInt16 nCategoryIdx)564 SmCategoryDesc::SmCategoryDesc(weld::Builder& rBuilder, sal_uInt16 nCategoryIdx)
565 {
566     ++nCategoryIdx;
567     std::unique_ptr<weld::Label> xTitle(rBuilder.weld_label(OString::number(nCategoryIdx)+"title"));
568     if (xTitle)
569     {
570         Name = xTitle->get_label();
571     }
572     for (int i = 0; i < 4; ++i)
573     {
574         std::unique_ptr<weld::Label> xLabel(rBuilder.weld_label(OString::number(nCategoryIdx)+"label"+OString::number(i+1)));
575 
576         if (xLabel)
577         {
578             Strings[i] = xLabel->get_label();
579             Graphics[i] = rBuilder.weld_widget(OString::number(nCategoryIdx)+"image"+OString::number(i+1));
580         }
581         else
582         {
583             Strings[i].clear();
584             Graphics[i].reset();
585         }
586 
587         const FieldMinMax& rMinMax = pMinMaxData[ nCategoryIdx-1 ][i];
588         Value[i] = Minimum[i] = rMinMax.nMin;
589         Maximum[i] = rMinMax.nMax;
590     }
591 }
592 
~SmCategoryDesc()593 SmCategoryDesc::~SmCategoryDesc()
594 {
595 }
596 
597 /**************************************************************************/
598 
IMPL_LINK(SmDistanceDialog,GetFocusHdl,weld::Widget &,rControl,void)599 IMPL_LINK( SmDistanceDialog, GetFocusHdl, weld::Widget&, rControl, void )
600 {
601     if (!m_xCategories[nActiveCategory])
602         return;
603 
604     sal_uInt16  i;
605 
606     if (&rControl == &m_xMetricField1->get_widget())
607         i = 0;
608     else if (&rControl == &m_xMetricField2->get_widget())
609         i = 1;
610     else if (&rControl == &m_xMetricField3->get_widget())
611         i = 2;
612     else if (&rControl == &m_xMetricField4->get_widget())
613         i = 3;
614     else
615         return;
616     if (m_pCurrentImage)
617         m_pCurrentImage->hide();
618     m_pCurrentImage = m_xCategories[nActiveCategory]->GetGraphic(i);
619     m_pCurrentImage->show();
620 }
621 
IMPL_LINK(SmDistanceDialog,MenuSelectHdl,const OString &,rId,void)622 IMPL_LINK(SmDistanceDialog, MenuSelectHdl, const OString&, rId, void)
623 {
624     assert(rId.startsWith("menuitem"));
625     SetCategory(rId.replaceFirst("menuitem", "").toInt32() - 1);
626 }
627 
IMPL_LINK_NOARG(SmDistanceDialog,DefaultButtonClickHdl,weld::Button &,void)628 IMPL_LINK_NOARG( SmDistanceDialog, DefaultButtonClickHdl, weld::Button&, void )
629 {
630     SaveDefaultsQuery aQuery(m_xDialog.get());
631     if (aQuery.run() == RET_YES)
632     {
633         SmModule *pp = SM_MOD();
634         SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
635         WriteTo( aFmt );
636         pp->GetConfig()->SetStandardFormat( aFmt );
637     }
638 }
639 
IMPL_LINK(SmDistanceDialog,CheckBoxClickHdl,weld::ToggleButton &,rCheckBox,void)640 IMPL_LINK( SmDistanceDialog, CheckBoxClickHdl, weld::ToggleButton&, rCheckBox, void )
641 {
642     if (&rCheckBox == m_xCheckBox1.get())
643     {
644         bool bChecked = m_xCheckBox1->get_active();
645         m_xFixedText4->set_sensitive( bChecked );
646         m_xMetricField4->set_sensitive( bChecked );
647     }
648 }
649 
SetCategory(sal_uInt16 nCategory)650 void SmDistanceDialog::SetCategory(sal_uInt16 nCategory)
651 {
652     assert(nCategory < NOCATEGORIES && "Sm: wrong category number in SmDistanceDialog");
653 
654     // array to convert category- and metricfield-number in help ids.
655     // 0 is used in case of unused combinations.
656     assert(NOCATEGORIES == 10 && "Sm : array doesn't fit into the number of categories");
657     static const char * aCatMf2Hid[10][4] =
658     {
659         { HID_SMA_DEFAULT_DIST,         HID_SMA_LINE_DIST,          HID_SMA_ROOT_DIST, nullptr },
660         { HID_SMA_SUP_DIST,             HID_SMA_SUB_DIST ,          nullptr, nullptr },
661         { HID_SMA_NUMERATOR_DIST,       HID_SMA_DENOMINATOR_DIST,   nullptr, nullptr },
662         { HID_SMA_FRACLINE_EXCWIDTH,    HID_SMA_FRACLINE_LINEWIDTH, nullptr, nullptr },
663         { HID_SMA_UPPERLIMIT_DIST,      HID_SMA_LOWERLIMIT_DIST,    nullptr, nullptr },
664         { HID_SMA_BRACKET_EXCHEIGHT,    HID_SMA_BRACKET_DIST,       nullptr, HID_SMA_BRACKET_EXCHEIGHT2 },
665         { HID_SMA_MATRIXROW_DIST,       HID_SMA_MATRIXCOL_DIST,     nullptr, nullptr },
666         { HID_SMA_ATTRIBUT_DIST,        HID_SMA_INTERATTRIBUT_DIST, nullptr, nullptr },
667         { HID_SMA_OPERATOR_EXCHEIGHT,   HID_SMA_OPERATOR_DIST,      nullptr, nullptr },
668         { HID_SMA_LEFTBORDER_DIST,      HID_SMA_RIGHTBORDER_DIST,   HID_SMA_UPPERBORDER_DIST, HID_SMA_LOWERBORDER_DIST }
669     };
670 
671     // array to help iterate over the controls
672     std::pair<weld::Label*, weld::MetricSpinButton*> const aWin[4] =
673     {
674         { m_xFixedText1.get(), m_xMetricField1.get() },
675         { m_xFixedText2.get(), m_xMetricField2.get() },
676         { m_xFixedText3.get(), m_xMetricField3.get() },
677         { m_xFixedText4.get(), m_xMetricField4.get() }
678     };
679 
680     SmCategoryDesc *pCat;
681 
682     // remember the (maybe new) settings of the active SmCategoryDesc
683     // before switching to the new one
684     if (nActiveCategory != CATEGORY_NONE)
685     {
686         pCat = m_xCategories[nActiveCategory].get();
687         pCat->SetValue(0, sal::static_int_cast<sal_uInt16>(m_xMetricField1->get_value(FieldUnit::NONE)));
688         pCat->SetValue(1, sal::static_int_cast<sal_uInt16>(m_xMetricField2->get_value(FieldUnit::NONE)));
689         pCat->SetValue(2, sal::static_int_cast<sal_uInt16>(m_xMetricField3->get_value(FieldUnit::NONE)));
690         pCat->SetValue(3, sal::static_int_cast<sal_uInt16>(m_xMetricField4->get_value(FieldUnit::NONE)));
691 
692         if (nActiveCategory == 5)
693             bScaleAllBrackets = m_xCheckBox1->get_active();
694 
695         m_xMenuButton->set_item_active("menuitem" + OString::number(nActiveCategory + 1), false);
696     }
697 
698     // activation/deactivation of the associated controls depending on the chosen category
699     bool  bActive;
700     for (sal_uInt16 i = 0;  i < 4;  i++)
701     {
702         weld::Label *pFT = aWin[i].first;
703         weld::MetricSpinButton *pMF = aWin[i].second;
704 
705         // To determine which Controls should be active, the existence
706         // of an associated HelpID is checked
707         bActive = aCatMf2Hid[nCategory][i] != nullptr;
708 
709         pFT->set_visible(bActive);
710         pFT->set_sensitive(bActive);
711         pMF->set_visible(bActive);
712         pMF->set_sensitive(bActive);
713 
714         // set measurement unit and number of decimal places
715         FieldUnit  eUnit;
716         sal_uInt16     nDigits;
717         if (nCategory < 9)
718         {
719             eUnit = FieldUnit::PERCENT;
720             nDigits = 0;
721         }
722         else
723         {
724             eUnit   = FieldUnit::MM_100TH;
725             nDigits = 2;
726         }
727         pMF->set_unit(eUnit);            // changes the value
728         pMF->set_digits(nDigits);
729 
730         if (bActive)
731         {
732             pCat = m_xCategories[nCategory].get();
733             pFT->set_label(pCat->GetString(i));
734 
735             pMF->set_range(pCat->GetMinimum(i), pCat->GetMaximum(i), FieldUnit::NONE);
736             pMF->set_value(pCat->GetValue(i), FieldUnit::NONE);
737 
738             pMF->set_help_id(aCatMf2Hid[nCategory][i]);
739         }
740     }
741     // activate the CheckBox and the associated MetricField if we're dealing with the brackets menu
742     bActive = nCategory == 5;
743     m_xCheckBox1->set_visible(bActive);
744     m_xCheckBox1->set_sensitive(bActive);
745     if (bActive)
746     {
747         m_xCheckBox1->set_active(bScaleAllBrackets);
748 
749         bool bChecked = m_xCheckBox1->get_active();
750         m_xFixedText4->set_sensitive( bChecked );
751         m_xMetricField4->set_sensitive( bChecked );
752     }
753 
754     m_xMenuButton->set_item_active("menuitem" + OString::number(nCategory + 1), true);
755     m_xFrame->set_label(m_xCategories[nCategory]->GetName());
756 
757     nActiveCategory = nCategory;
758 
759     m_xMetricField1->grab_focus();
760 }
761 
SmDistanceDialog(weld::Window * pParent)762 SmDistanceDialog::SmDistanceDialog(weld::Window *pParent)
763     : GenericDialogController(pParent, "modules/smath/ui/spacingdialog.ui", "SpacingDialog")
764     , m_xFrame(m_xBuilder->weld_frame("template"))
765     , m_xFixedText1(m_xBuilder->weld_label("label1"))
766     , m_xMetricField1(m_xBuilder->weld_metric_spin_button("spinbutton1", FieldUnit::CM))
767     , m_xFixedText2(m_xBuilder->weld_label("label2"))
768     , m_xMetricField2(m_xBuilder->weld_metric_spin_button("spinbutton2", FieldUnit::CM))
769     , m_xFixedText3(m_xBuilder->weld_label("label3"))
770     , m_xMetricField3(m_xBuilder->weld_metric_spin_button("spinbutton3", FieldUnit::CM))
771     , m_xCheckBox1(m_xBuilder->weld_check_button("checkbutton"))
772     , m_xFixedText4(m_xBuilder->weld_label("label4"))
773     , m_xMetricField4(m_xBuilder->weld_metric_spin_button("spinbutton4", FieldUnit::CM))
774     , m_xMenuButton(m_xBuilder->weld_menu_button("category"))
775     , m_xDefaultButton(m_xBuilder->weld_button("default"))
776     , m_xBitmap(m_xBuilder->weld_widget("image"))
777     , m_pCurrentImage(m_xBitmap.get())
778 {
779     for (sal_uInt16 i = 0; i < NOCATEGORIES; ++i)
780         m_xCategories[i].reset( new SmCategoryDesc(*m_xBuilder, i) );
781     nActiveCategory   = CATEGORY_NONE;
782     bScaleAllBrackets = false;
783 
784     m_xMetricField1->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
785     m_xMetricField2->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
786     m_xMetricField3->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
787     m_xMetricField4->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
788     m_xCheckBox1->connect_toggled(LINK(this, SmDistanceDialog, CheckBoxClickHdl));
789     m_xMenuButton->connect_selected(LINK(this, SmDistanceDialog, MenuSelectHdl));
790     m_xDefaultButton->connect_clicked(LINK(this, SmDistanceDialog, DefaultButtonClickHdl));
791 
792     //set the initial size, with max visible widgets visible, as preferred size
793     m_xDialog->set_size_request(-1, m_xDialog->get_preferred_size().Height());
794 }
795 
~SmDistanceDialog()796 SmDistanceDialog::~SmDistanceDialog()
797 {
798 }
799 
ReadFrom(const SmFormat & rFormat)800 void SmDistanceDialog::ReadFrom(const SmFormat &rFormat)
801 {
802     m_xCategories[0]->SetValue(0, rFormat.GetDistance(DIS_HORIZONTAL));
803     m_xCategories[0]->SetValue(1, rFormat.GetDistance(DIS_VERTICAL));
804     m_xCategories[0]->SetValue(2, rFormat.GetDistance(DIS_ROOT));
805     m_xCategories[1]->SetValue(0, rFormat.GetDistance(DIS_SUPERSCRIPT));
806     m_xCategories[1]->SetValue(1, rFormat.GetDistance(DIS_SUBSCRIPT));
807     m_xCategories[2]->SetValue(0, rFormat.GetDistance(DIS_NUMERATOR));
808     m_xCategories[2]->SetValue(1, rFormat.GetDistance(DIS_DENOMINATOR));
809     m_xCategories[3]->SetValue(0, rFormat.GetDistance(DIS_FRACTION));
810     m_xCategories[3]->SetValue(1, rFormat.GetDistance(DIS_STROKEWIDTH));
811     m_xCategories[4]->SetValue(0, rFormat.GetDistance(DIS_UPPERLIMIT));
812     m_xCategories[4]->SetValue(1, rFormat.GetDistance(DIS_LOWERLIMIT));
813     m_xCategories[5]->SetValue(0, rFormat.GetDistance(DIS_BRACKETSIZE));
814     m_xCategories[5]->SetValue(1, rFormat.GetDistance(DIS_BRACKETSPACE));
815     m_xCategories[5]->SetValue(3, rFormat.GetDistance(DIS_NORMALBRACKETSIZE));
816     m_xCategories[6]->SetValue(0, rFormat.GetDistance(DIS_MATRIXROW));
817     m_xCategories[6]->SetValue(1, rFormat.GetDistance(DIS_MATRIXCOL));
818     m_xCategories[7]->SetValue(0, rFormat.GetDistance(DIS_ORNAMENTSIZE));
819     m_xCategories[7]->SetValue(1, rFormat.GetDistance(DIS_ORNAMENTSPACE));
820     m_xCategories[8]->SetValue(0, rFormat.GetDistance(DIS_OPERATORSIZE));
821     m_xCategories[8]->SetValue(1, rFormat.GetDistance(DIS_OPERATORSPACE));
822     m_xCategories[9]->SetValue(0, rFormat.GetDistance(DIS_LEFTSPACE));
823     m_xCategories[9]->SetValue(1, rFormat.GetDistance(DIS_RIGHTSPACE));
824     m_xCategories[9]->SetValue(2, rFormat.GetDistance(DIS_TOPSPACE));
825     m_xCategories[9]->SetValue(3, rFormat.GetDistance(DIS_BOTTOMSPACE));
826 
827     bScaleAllBrackets = rFormat.IsScaleNormalBrackets();
828 
829     // force update (even of category 0) by setting nActiveCategory to a
830     // non-existent category number
831     nActiveCategory = CATEGORY_NONE;
832     SetCategory(0);
833 }
834 
835 
WriteTo(SmFormat & rFormat)836 void SmDistanceDialog::WriteTo(SmFormat &rFormat) /*const*/
837 {
838     // TODO can they actually be different?
839     // if that's not the case 'const' could be used above!
840     SetCategory(nActiveCategory);
841 
842     rFormat.SetDistance( DIS_HORIZONTAL,        m_xCategories[0]->GetValue(0) );
843     rFormat.SetDistance( DIS_VERTICAL,          m_xCategories[0]->GetValue(1) );
844     rFormat.SetDistance( DIS_ROOT,              m_xCategories[0]->GetValue(2) );
845     rFormat.SetDistance( DIS_SUPERSCRIPT,       m_xCategories[1]->GetValue(0) );
846     rFormat.SetDistance( DIS_SUBSCRIPT,         m_xCategories[1]->GetValue(1) );
847     rFormat.SetDistance( DIS_NUMERATOR,         m_xCategories[2]->GetValue(0) );
848     rFormat.SetDistance( DIS_DENOMINATOR,       m_xCategories[2]->GetValue(1) );
849     rFormat.SetDistance( DIS_FRACTION,          m_xCategories[3]->GetValue(0) );
850     rFormat.SetDistance( DIS_STROKEWIDTH,       m_xCategories[3]->GetValue(1) );
851     rFormat.SetDistance( DIS_UPPERLIMIT,        m_xCategories[4]->GetValue(0) );
852     rFormat.SetDistance( DIS_LOWERLIMIT,        m_xCategories[4]->GetValue(1) );
853     rFormat.SetDistance( DIS_BRACKETSIZE,       m_xCategories[5]->GetValue(0) );
854     rFormat.SetDistance( DIS_BRACKETSPACE,      m_xCategories[5]->GetValue(1) );
855     rFormat.SetDistance( DIS_MATRIXROW,         m_xCategories[6]->GetValue(0) );
856     rFormat.SetDistance( DIS_MATRIXCOL,         m_xCategories[6]->GetValue(1) );
857     rFormat.SetDistance( DIS_ORNAMENTSIZE,      m_xCategories[7]->GetValue(0) );
858     rFormat.SetDistance( DIS_ORNAMENTSPACE,     m_xCategories[7]->GetValue(1) );
859     rFormat.SetDistance( DIS_OPERATORSIZE,      m_xCategories[8]->GetValue(0) );
860     rFormat.SetDistance( DIS_OPERATORSPACE,     m_xCategories[8]->GetValue(1) );
861     rFormat.SetDistance( DIS_LEFTSPACE,         m_xCategories[9]->GetValue(0) );
862     rFormat.SetDistance( DIS_RIGHTSPACE,        m_xCategories[9]->GetValue(1) );
863     rFormat.SetDistance( DIS_TOPSPACE,          m_xCategories[9]->GetValue(2) );
864     rFormat.SetDistance( DIS_BOTTOMSPACE,       m_xCategories[9]->GetValue(3) );
865     rFormat.SetDistance( DIS_NORMALBRACKETSIZE, m_xCategories[5]->GetValue(3) );
866 
867     rFormat.SetScaleNormalBrackets( bScaleAllBrackets );
868 
869     rFormat.RequestApplyChanges();
870 }
871 
IMPL_LINK_NOARG(SmAlignDialog,DefaultButtonClickHdl,weld::Button &,void)872 IMPL_LINK_NOARG( SmAlignDialog, DefaultButtonClickHdl, weld::Button&, void )
873 {
874     SaveDefaultsQuery aQuery(m_xDialog.get());
875     if (aQuery.run() == RET_YES)
876     {
877         SmModule *pp = SM_MOD();
878         SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
879         WriteTo( aFmt );
880         pp->GetConfig()->SetStandardFormat( aFmt );
881     }
882 }
883 
SmAlignDialog(weld::Window * pParent)884 SmAlignDialog::SmAlignDialog(weld::Window* pParent)
885     : GenericDialogController(pParent, "modules/smath/ui/alignmentdialog.ui", "AlignmentDialog")
886     , m_xLeft(m_xBuilder->weld_radio_button("left"))
887     , m_xCenter(m_xBuilder->weld_radio_button("center"))
888     , m_xRight(m_xBuilder->weld_radio_button("right"))
889     , m_xDefaultButton(m_xBuilder->weld_button("default"))
890 {
891     m_xDefaultButton->connect_clicked(LINK(this, SmAlignDialog, DefaultButtonClickHdl));
892 }
893 
~SmAlignDialog()894 SmAlignDialog::~SmAlignDialog()
895 {
896 }
897 
ReadFrom(const SmFormat & rFormat)898 void SmAlignDialog::ReadFrom(const SmFormat &rFormat)
899 {
900     switch (rFormat.GetHorAlign())
901     {
902         case SmHorAlign::Left:
903             m_xLeft->set_active(true);
904             break;
905         case SmHorAlign::Center:
906             m_xCenter->set_active(true);
907             break;
908         case SmHorAlign::Right:
909             m_xRight->set_active(true);
910             break;
911     }
912 }
913 
WriteTo(SmFormat & rFormat) const914 void SmAlignDialog::WriteTo(SmFormat &rFormat) const
915 {
916     if (m_xLeft->get_active())
917         rFormat.SetHorAlign(SmHorAlign::Left);
918     else if (m_xRight->get_active())
919         rFormat.SetHorAlign(SmHorAlign::Right);
920     else
921         rFormat.SetHorAlign(SmHorAlign::Center);
922 
923     rFormat.RequestApplyChanges();
924 }
925 
SmShowSymbolSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow)926 SmShowSymbolSet::SmShowSymbolSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow)
927     : nLen(0)
928     , nRows(0)
929     , nColumns(0)
930     , nXOffset(0)
931     , nYOffset(0)
932     , nSelectSymbol(SYMBOL_NONE)
933     , m_xScrolledWindow(std::move(pScrolledWindow))
934 {
935     m_xScrolledWindow->set_user_managed_scrolling();
936     m_xScrolledWindow->connect_vadjustment_changed(LINK(this, SmShowSymbolSet, ScrollHdl));
937 }
938 
OffsetPoint(const Point & rPoint) const939 Point SmShowSymbolSet::OffsetPoint(const Point &rPoint) const
940 {
941     return Point(rPoint.X() + nXOffset, rPoint.Y() + nYOffset);
942 }
943 
Resize()944 void SmShowSymbolSet::Resize()
945 {
946     CustomWidgetController::Resize();
947     Size aWinSize(GetOutputSizePixel());
948     if (aWinSize != m_aOldSize)
949     {
950         calccols(GetDrawingArea()->get_ref_device());
951         m_aOldSize = aWinSize;
952     }
953 }
954 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)955 void SmShowSymbolSet::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
956 {
957     Color aBackgroundColor;
958     Color aTextColor;
959     lclGetSettingColors(aBackgroundColor, aTextColor);
960 
961     rRenderContext.SetBackground(Wallpaper(aBackgroundColor));
962     rRenderContext.SetTextColor(aTextColor);
963 
964     rRenderContext.Push(PushFlags::MAPMODE);
965 
966     // set MapUnit for which 'nLen' has been calculated
967     rRenderContext.SetMapMode(MapMode(MapUnit::MapPixel));
968 
969     sal_uInt16 v = sal::static_int_cast< sal_uInt16 >(m_xScrolledWindow->vadjustment_get_value() * nColumns);
970     size_t nSymbols = aSymbolSet.size();
971 
972     Color aTxtColor(rRenderContext.GetTextColor());
973     for (size_t i = v; i < nSymbols ; i++)
974     {
975         SmSym aSymbol(*aSymbolSet[i]);
976         vcl::Font aFont(aSymbol.GetFace());
977         aFont.SetAlignment(ALIGN_TOP);
978 
979         // taking a FontSize which is a bit smaller (compared to nLen) in order to have a buffer
980         // (hopefully enough for left and right, too)
981         aFont.SetFontSize(Size(0, nLen - (nLen / 3)));
982         rRenderContext.SetFont(aFont);
983         // keep text color
984         rRenderContext.SetTextColor(aTxtColor);
985 
986         int nIV = i - v;
987         sal_UCS4 cChar = aSymbol.GetCharacter();
988         OUString aText(&cChar, 1);
989         Size  aSize(rRenderContext.GetTextWidth( aText ), rRenderContext.GetTextHeight());
990 
991         Point aPoint((nIV % nColumns) * nLen + (nLen - aSize.Width()) / 2,
992                      (nIV / nColumns) * nLen + (nLen - aSize.Height()) / 2);
993 
994         rRenderContext.DrawText(OffsetPoint(aPoint), aText);
995     }
996 
997     if (nSelectSymbol != SYMBOL_NONE)
998     {
999         Point aPoint(((nSelectSymbol - v) % nColumns) * nLen,
1000                                  ((nSelectSymbol - v) / nColumns) * nLen);
1001 
1002         rRenderContext.Invert(tools::Rectangle(OffsetPoint(aPoint), Size(nLen, nLen)));
1003 
1004     }
1005 
1006     rRenderContext.Pop();
1007 }
1008 
MouseButtonDown(const MouseEvent & rMEvt)1009 bool SmShowSymbolSet::MouseButtonDown(const MouseEvent& rMEvt)
1010 {
1011     GrabFocus();
1012 
1013     Size aOutputSize(nColumns * nLen, nRows * nLen);
1014     aOutputSize.AdjustWidth(nXOffset );
1015     aOutputSize.AdjustHeight(nYOffset );
1016     Point aPoint(rMEvt.GetPosPixel());
1017     aPoint.AdjustX( -nXOffset );
1018     aPoint.AdjustY( -nYOffset );
1019 
1020     if (rMEvt.IsLeft() && tools::Rectangle(Point(0, 0), aOutputSize).IsInside(rMEvt.GetPosPixel()))
1021     {
1022         long nPos = (aPoint.Y() / nLen) * nColumns + (aPoint.X() / nLen) +
1023                       m_xScrolledWindow->vadjustment_get_value() * nColumns;
1024         SelectSymbol( sal::static_int_cast< sal_uInt16 >(nPos) );
1025 
1026         aSelectHdlLink.Call(*this);
1027 
1028         if (rMEvt.GetClicks() > 1)
1029             aDblClickHdlLink.Call(*this);
1030     }
1031 
1032     return true;
1033 }
1034 
KeyInput(const KeyEvent & rKEvt)1035 bool SmShowSymbolSet::KeyInput(const KeyEvent& rKEvt)
1036 {
1037     sal_uInt16 n = nSelectSymbol;
1038 
1039     if (n != SYMBOL_NONE)
1040     {
1041         switch (rKEvt.GetKeyCode().GetCode())
1042         {
1043             case KEY_DOWN:      n = n + nColumns;   break;
1044             case KEY_UP:        n = n - nColumns;   break;
1045             case KEY_LEFT:      n -= 1; break;
1046             case KEY_RIGHT:     n += 1; break;
1047             case KEY_HOME:      n  = 0; break;
1048             case KEY_END:       n  = static_cast< sal_uInt16 >(aSymbolSet.size() - 1);   break;
1049             case KEY_PAGEUP:    n -= nColumns * nRows;  break;
1050             case KEY_PAGEDOWN:  n += nColumns * nRows;  break;
1051             default:
1052                 return false;
1053         }
1054     }
1055     else
1056         n = 0;
1057 
1058     if (n >= aSymbolSet.size())
1059         n = nSelectSymbol;
1060 
1061     // adjust scrollbar
1062     if ((n < sal::static_int_cast<sal_uInt16>(m_xScrolledWindow->vadjustment_get_value() * nColumns)) ||
1063         (n >= sal::static_int_cast<sal_uInt16>((m_xScrolledWindow->vadjustment_get_value() + nRows) * nColumns)))
1064     {
1065         m_xScrolledWindow->vadjustment_set_value(n / nColumns);
1066         Invalidate();
1067     }
1068 
1069     SelectSymbol(n);
1070     aSelectHdlLink.Call(*this);
1071 
1072     return true;
1073 }
1074 
calccols(const vcl::RenderContext & rRenderContext)1075 void SmShowSymbolSet::calccols(const vcl::RenderContext& rRenderContext)
1076 {
1077     // Height of 16pt in pixels (matching 'aOutputSize')
1078     nLen = rRenderContext.LogicToPixel(Size(0, 16), MapMode(MapUnit::MapPoint)).Height();
1079 
1080     Size aOutputSize(GetOutputSizePixel());
1081 
1082     nColumns = aOutputSize.Width() / nLen;
1083     nRows = aOutputSize.Height() / nLen;
1084     nColumns = std::max<long>(1, nColumns);
1085     nRows = std::max<long>(1, nRows);
1086 
1087     nXOffset = (aOutputSize.Width() - (nColumns * nLen)) / 2;
1088     nYOffset = (aOutputSize.Height() - (nRows * nLen)) / 2;
1089 
1090     SetScrollBarRange();
1091 }
1092 
SetSymbolSet(const SymbolPtrVec_t & rSymbolSet)1093 void SmShowSymbolSet::SetSymbolSet(const SymbolPtrVec_t& rSymbolSet)
1094 {
1095     aSymbolSet = rSymbolSet;
1096     SetScrollBarRange();
1097     Invalidate();
1098 }
1099 
SetScrollBarRange()1100 void SmShowSymbolSet::SetScrollBarRange()
1101 {
1102     const int nLastRow = (aSymbolSet.size() - 1 + nColumns) / nColumns;
1103     m_xScrolledWindow->vadjustment_configure(m_xScrolledWindow->vadjustment_get_value(), 0, nLastRow, 1, nRows - 1, nRows);
1104     Invalidate();
1105 }
1106 
SelectSymbol(sal_uInt16 nSymbol)1107 void SmShowSymbolSet::SelectSymbol(sal_uInt16 nSymbol)
1108 {
1109     int v = m_xScrolledWindow->vadjustment_get_value() * nColumns;
1110 
1111     if (nSelectSymbol != SYMBOL_NONE && nColumns)
1112     {
1113         Point aPoint(OffsetPoint(Point(((nSelectSymbol - v) % nColumns) * nLen,
1114                                        ((nSelectSymbol - v) / nColumns) * nLen)));
1115         Invalidate(tools::Rectangle(aPoint, Size(nLen, nLen)));
1116     }
1117 
1118     if (nSymbol < aSymbolSet.size())
1119         nSelectSymbol = nSymbol;
1120 
1121     if (aSymbolSet.empty())
1122         nSelectSymbol = SYMBOL_NONE;
1123 
1124     if (nSelectSymbol != SYMBOL_NONE && nColumns)
1125     {
1126         Point aPoint(OffsetPoint(Point(((nSelectSymbol - v) % nColumns) * nLen,
1127                                        ((nSelectSymbol - v) / nColumns) * nLen)));
1128         Invalidate(tools::Rectangle(aPoint, Size(nLen, nLen)));
1129     }
1130 
1131     if (!nColumns)
1132         Invalidate();
1133 }
1134 
IMPL_LINK_NOARG(SmShowSymbolSet,ScrollHdl,weld::ScrolledWindow &,void)1135 IMPL_LINK_NOARG(SmShowSymbolSet, ScrollHdl, weld::ScrolledWindow&, void)
1136 {
1137     Invalidate();
1138 }
1139 
SmShowSymbol()1140 SmShowSymbol::SmShowSymbol()
1141 {
1142 }
1143 
setFontSize(vcl::Font & rFont) const1144 void SmShowSymbol::setFontSize(vcl::Font &rFont) const
1145 {
1146     Size aSize(GetOutputSizePixel());
1147     rFont.SetFontSize(Size(0, aSize.Height() - aSize.Height() / 3));
1148 }
1149 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)1150 void SmShowSymbol::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
1151 {
1152     Color aBackgroundColor;
1153     Color aTextColor;
1154     lclGetSettingColors(aBackgroundColor, aTextColor);
1155     rRenderContext.SetBackground(Wallpaper(aBackgroundColor));
1156     rRenderContext.SetTextColor(aTextColor);
1157     rRenderContext.Erase();
1158 
1159     vcl::Font aFont(GetFont());
1160     setFontSize(aFont);
1161     rRenderContext.SetFont(aFont);
1162 
1163     const OUString &rText = GetText();
1164     Size aTextSize(rRenderContext.GetTextWidth(rText), rRenderContext.GetTextHeight());
1165 
1166     rRenderContext.DrawText(Point((rRenderContext.GetOutputSize().Width()  - aTextSize.Width())  / 2,
1167                                   (rRenderContext.GetOutputSize().Height() * 7 / 10)), rText);
1168 }
1169 
MouseButtonDown(const MouseEvent & rMEvt)1170 bool SmShowSymbol::MouseButtonDown(const MouseEvent& rMEvt)
1171 {
1172     if (rMEvt.GetClicks() > 1)
1173         aDblClickHdlLink.Call(*this);
1174     return true;
1175 }
1176 
SetSymbol(const SmSym * pSymbol)1177 void SmShowSymbol::SetSymbol(const SmSym *pSymbol)
1178 {
1179     if (pSymbol)
1180     {
1181         vcl::Font aFont(pSymbol->GetFace());
1182         aFont.SetAlignment(ALIGN_BASELINE);
1183         SetFont(aFont);
1184 
1185         sal_UCS4 cChar = pSymbol->GetCharacter();
1186         OUString aText(&cChar, 1);
1187         SetText( aText );
1188     }
1189 
1190     Invalidate();
1191 }
1192 
FillSymbolSets()1193 void SmSymbolDialog::FillSymbolSets()
1194     // populate the entries of possible SymbolsSets in the dialog with
1195     // current values of the SymbolSet manager but selects none of those
1196 {
1197     m_xSymbolSets->clear();
1198     m_xSymbolSets->set_active(-1);
1199 
1200     std::set< OUString >  aSymbolSetNames( rSymbolMgr.GetSymbolSetNames() );
1201     for (const auto& rSymbolSetName : aSymbolSetNames)
1202         m_xSymbolSets->append_text(rSymbolSetName);
1203 }
1204 
IMPL_LINK_NOARG(SmSymbolDialog,SymbolSetChangeHdl,weld::ComboBox &,void)1205 IMPL_LINK_NOARG( SmSymbolDialog, SymbolSetChangeHdl, weld::ComboBox&, void )
1206 {
1207     SelectSymbolSet(m_xSymbolSets->get_active_text());
1208 }
1209 
IMPL_LINK_NOARG(SmSymbolDialog,SymbolChangeHdl,SmShowSymbolSet &,void)1210 IMPL_LINK_NOARG( SmSymbolDialog, SymbolChangeHdl, SmShowSymbolSet&, void )
1211 {
1212     SelectSymbol(m_xSymbolSetDisplay->GetSelectSymbol());
1213 }
1214 
IMPL_LINK_NOARG(SmSymbolDialog,EditClickHdl,weld::Button &,void)1215 IMPL_LINK_NOARG(SmSymbolDialog, EditClickHdl, weld::Button&, void)
1216 {
1217     SmSymDefineDialog aDialog(m_xDialog.get(), pFontListDev, rSymbolMgr);
1218 
1219     // set current symbol and SymbolSet for the new dialog
1220     const OUString  aSymSetName (m_xSymbolSets->get_active_text()),
1221                     aSymName    (m_xSymbolName->get_label());
1222     aDialog.SelectOldSymbolSet(aSymSetName);
1223     aDialog.SelectOldSymbol(aSymName);
1224     aDialog.SelectSymbolSet(aSymSetName);
1225     aDialog.SelectSymbol(aSymName);
1226 
1227     // remember old SymbolSet
1228     OUString  aOldSymbolSet (m_xSymbolSets->get_active_text());
1229 
1230     sal_uInt16 nSymPos = m_xSymbolSetDisplay->GetSelectSymbol();
1231 
1232     // adapt dialog to data of the SymbolSet manager, which might have changed
1233     if (aDialog.run() == RET_OK && rSymbolMgr.IsModified())
1234     {
1235         rSymbolMgr.Save();
1236         FillSymbolSets();
1237     }
1238 
1239     // if the old SymbolSet doesn't exist anymore, go to the first one SymbolSet (if one exists)
1240     if (!SelectSymbolSet(aOldSymbolSet) && m_xSymbolSets->get_count() > 0)
1241         SelectSymbolSet(m_xSymbolSets->get_text(0));
1242     else
1243     {
1244         // just update display of current symbol set
1245         assert(aSymSetName == aSymSetName); //unexpected change in symbol set name
1246         aSymbolSet = rSymbolMgr.GetSymbolSet( aSymbolSetName );
1247         m_xSymbolSetDisplay->SetSymbolSet( aSymbolSet );
1248     }
1249 
1250     if (nSymPos >= aSymbolSet.size())
1251         nSymPos = static_cast< sal_uInt16 >(aSymbolSet.size()) - 1;
1252     SelectSymbol( nSymPos );
1253 }
1254 
IMPL_LINK_NOARG(SmSymbolDialog,SymbolDblClickHdl2,SmShowSymbolSet &,void)1255 IMPL_LINK_NOARG( SmSymbolDialog, SymbolDblClickHdl2, SmShowSymbolSet&, void )
1256 {
1257     SymbolDblClickHdl();
1258 }
1259 
IMPL_LINK_NOARG(SmSymbolDialog,SymbolDblClickHdl,SmShowSymbol &,void)1260 IMPL_LINK_NOARG( SmSymbolDialog, SymbolDblClickHdl, SmShowSymbol&, void )
1261 {
1262     SymbolDblClickHdl();
1263 }
1264 
SymbolDblClickHdl()1265 void SmSymbolDialog::SymbolDblClickHdl()
1266 {
1267     GetClickHdl(*m_xGetBtn);
1268     m_xDialog->response(RET_OK);
1269 }
1270 
IMPL_LINK_NOARG(SmSymbolDialog,GetClickHdl,weld::Button &,void)1271 IMPL_LINK_NOARG(SmSymbolDialog, GetClickHdl, weld::Button&, void)
1272 {
1273     const SmSym *pSym = GetSymbol();
1274     if (pSym)
1275     {
1276         OUString aText = "%" + pSym->GetName() + " ";
1277 
1278         rViewSh.GetViewFrame()->GetDispatcher()->ExecuteList(
1279                 SID_INSERTSPECIAL, SfxCallMode::RECORD,
1280                 { new SfxStringItem(SID_INSERTSPECIAL, aText) });
1281     }
1282 }
1283 
SmSymbolDialog(weld::Window * pParent,OutputDevice * pFntListDevice,SmSymbolManager & rMgr,SmViewShell & rViewShell)1284 SmSymbolDialog::SmSymbolDialog(weld::Window *pParent, OutputDevice *pFntListDevice,
1285                                SmSymbolManager &rMgr, SmViewShell &rViewShell)
1286     : GenericDialogController(pParent, "modules/smath/ui/catalogdialog.ui", "CatalogDialog")
1287     , rViewSh(rViewShell)
1288     , rSymbolMgr(rMgr)
1289     , pFontListDev(pFntListDevice)
1290     , m_xSymbolSets(m_xBuilder->weld_combo_box("symbolset"))
1291     , m_xSymbolSetDisplay(new SmShowSymbolSet(m_xBuilder->weld_scrolled_window("scrolledwindow")))
1292     , m_xSymbolSetDisplayArea(new weld::CustomWeld(*m_xBuilder, "symbolsetdisplay", *m_xSymbolSetDisplay))
1293     , m_xSymbolName(m_xBuilder->weld_label("symbolname"))
1294     , m_xSymbolDisplay(new weld::CustomWeld(*m_xBuilder, "preview", m_aSymbolDisplay))
1295     , m_xGetBtn(m_xBuilder->weld_button("ok"))
1296     , m_xEditBtn(m_xBuilder->weld_button("edit"))
1297 {
1298     m_xSymbolSets->make_sorted();
1299 
1300     aSymbolSetName.clear();
1301     aSymbolSet.clear();
1302     FillSymbolSets();
1303     if (m_xSymbolSets->get_count() > 0)
1304         SelectSymbolSet(m_xSymbolSets->get_text(0));
1305 
1306     m_xSymbolSets->connect_changed(LINK(this, SmSymbolDialog, SymbolSetChangeHdl));
1307     m_xSymbolSetDisplay->SetSelectHdl(LINK(this, SmSymbolDialog, SymbolChangeHdl));
1308     m_xSymbolSetDisplay->SetDblClickHdl(LINK(this, SmSymbolDialog, SymbolDblClickHdl2));
1309     m_aSymbolDisplay.SetDblClickHdl(LINK(this, SmSymbolDialog, SymbolDblClickHdl));
1310     m_xEditBtn->connect_clicked(LINK(this, SmSymbolDialog, EditClickHdl));
1311     m_xGetBtn->connect_clicked(LINK(this, SmSymbolDialog, GetClickHdl));
1312 }
1313 
~SmSymbolDialog()1314 SmSymbolDialog::~SmSymbolDialog()
1315 {
1316 }
1317 
SelectSymbolSet(const OUString & rSymbolSetName)1318 bool SmSymbolDialog::SelectSymbolSet(const OUString &rSymbolSetName)
1319 {
1320     bool bRet = false;
1321     sal_Int32 nPos = m_xSymbolSets->find_text(rSymbolSetName);
1322 
1323     aSymbolSetName.clear();
1324     aSymbolSet.clear();
1325     if (nPos != -1)
1326     {
1327         m_xSymbolSets->set_active(nPos);
1328 
1329         aSymbolSetName  = rSymbolSetName;
1330         aSymbolSet      = rSymbolMgr.GetSymbolSet( aSymbolSetName );
1331 
1332         // sort symbols by Unicode position (useful for displaying Greek characters alphabetically)
1333         std::sort( aSymbolSet.begin(), aSymbolSet.end(),
1334                    [](const SmSym *pSym1, const SmSym *pSym2)
1335                    {
1336                        return pSym1->GetCharacter() < pSym2->GetCharacter();
1337                    } );
1338 
1339         m_xSymbolSetDisplay->SetSymbolSet( aSymbolSet );
1340         if (!aSymbolSet.empty())
1341             SelectSymbol(0);
1342 
1343         bRet = true;
1344     }
1345     else
1346         m_xSymbolSets->set_active(-1);
1347 
1348     return bRet;
1349 }
1350 
SelectSymbol(sal_uInt16 nSymbolNo)1351 void SmSymbolDialog::SelectSymbol(sal_uInt16 nSymbolNo)
1352 {
1353     const SmSym *pSym = nullptr;
1354     if (!aSymbolSetName.isEmpty()  &&  nSymbolNo < static_cast< sal_uInt16 >(aSymbolSet.size()))
1355         pSym = aSymbolSet[ nSymbolNo ];
1356 
1357     m_xSymbolSetDisplay->SelectSymbol(nSymbolNo);
1358     m_aSymbolDisplay.SetSymbol(pSym);
1359     m_xSymbolName->set_label(pSym ? pSym->GetName() : OUString());
1360 }
1361 
GetSymbol() const1362 const SmSym* SmSymbolDialog::GetSymbol() const
1363 {
1364     sal_uInt16 nSymbolNo = m_xSymbolSetDisplay->GetSelectSymbol();
1365     bool bValid = !aSymbolSetName.isEmpty()  &&  nSymbolNo < static_cast< sal_uInt16 >(aSymbolSet.size());
1366     return bValid ? aSymbolSet[ nSymbolNo ] : nullptr;
1367 }
1368 
Resize()1369 void SmShowChar::Resize()
1370 {
1371     const OUString &rText = GetText();
1372     if (rText.isEmpty())
1373         return;
1374     sal_Int32 nStrIndex = 0;
1375     sal_UCS4 cChar = rText.iterateCodePoints(&nStrIndex);
1376     SetSymbol(cChar, GetFont()); //force recalculation of size
1377 }
1378 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)1379 void SmShowChar::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
1380 {
1381     Color aTextCol = rRenderContext.GetTextColor();
1382     Color aFillCol = rRenderContext.GetFillColor();
1383 
1384     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1385     const Color aWindowTextColor(rStyleSettings.GetDialogTextColor());
1386     const Color aWindowColor(rStyleSettings.GetWindowColor());
1387     rRenderContext.SetTextColor(aWindowTextColor);
1388     rRenderContext.SetFillColor(aWindowColor);
1389 
1390     Size aSize(GetOutputSizePixel());
1391     rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize));
1392 
1393     OUString aText(GetText());
1394     if (!aText.isEmpty())
1395     {
1396         vcl::Font aFont(m_aFont);
1397         aFont.SetAlignment(ALIGN_TOP);
1398         rRenderContext.SetFont(aFont);
1399 
1400         Size aTextSize(rRenderContext.GetTextWidth(aText), rRenderContext.GetTextHeight());
1401 
1402         rRenderContext.DrawText(Point((aSize.Width()  - aTextSize.Width()) / 2,
1403                                       (aSize.Height() - aTextSize.Height()) / 2), aText);
1404     }
1405 
1406     rRenderContext.SetTextColor(aTextCol);
1407     rRenderContext.SetFillColor(aFillCol);
1408 }
1409 
SetSymbol(const SmSym * pSym)1410 void SmShowChar::SetSymbol( const SmSym *pSym )
1411 {
1412     if (pSym)
1413         SetSymbol( pSym->GetCharacter(), pSym->GetFace() );
1414 }
1415 
1416 
SetSymbol(sal_UCS4 cChar,const vcl::Font & rFont)1417 void SmShowChar::SetSymbol( sal_UCS4 cChar, const vcl::Font &rFont )
1418 {
1419     vcl::Font aFont( rFont );
1420     Size aSize(GetOutputSizePixel());
1421     aFont.SetFontSize(Size(0, aSize.Height() - aSize.Height() / 3));
1422     aFont.SetAlignment(ALIGN_BASELINE);
1423     SetFont(aFont);
1424 
1425     OUString aText(&cChar, 1);
1426     SetText( aText );
1427 
1428     Invalidate();
1429 }
1430 
FillSymbols(weld::ComboBox & rComboBox,bool bDeleteText)1431 void SmSymDefineDialog::FillSymbols(weld::ComboBox& rComboBox, bool bDeleteText)
1432 {
1433     assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong ComboBox");
1434 
1435     rComboBox.clear();
1436     if (bDeleteText)
1437         rComboBox.set_entry_text(OUString());
1438 
1439     weld::ComboBox& rBox = &rComboBox == m_xOldSymbols.get() ? *m_xOldSymbolSets : *m_xSymbolSets;
1440     SymbolPtrVec_t aSymSet(m_aSymbolMgrCopy.GetSymbolSet(rBox.get_active_text()));
1441     for (const SmSym* i : aSymSet)
1442         rComboBox.append_text(i->GetName());
1443 }
1444 
FillSymbolSets(weld::ComboBox & rComboBox,bool bDeleteText)1445 void SmSymDefineDialog::FillSymbolSets(weld::ComboBox& rComboBox, bool bDeleteText)
1446 {
1447     assert((&rComboBox == m_xOldSymbolSets.get() || &rComboBox == m_xSymbolSets.get()) && "Sm : wrong ComboBox");
1448 
1449     rComboBox.clear();
1450     if (bDeleteText)
1451         rComboBox.set_entry_text(OUString());
1452 
1453     const std::set< OUString >  aSymbolSetNames( m_aSymbolMgrCopy.GetSymbolSetNames() );
1454     for (const auto& rSymbolSetName : aSymbolSetNames)
1455         rComboBox.append_text(rSymbolSetName);
1456 }
1457 
FillFonts()1458 void SmSymDefineDialog::FillFonts()
1459 {
1460     m_xFonts->clear();
1461     m_xFonts->set_active(-1);
1462 
1463     // Include all fonts of FontList into the font list.
1464     // If there are duplicates, only include one entry of each font since the style will be
1465     // already selected using the FontStyleBox.
1466     if (m_xFontList)
1467     {
1468         sal_uInt16  nCount = m_xFontList->GetFontNameCount();
1469         for (sal_uInt16 i = 0; i < nCount; ++i)
1470             m_xFonts->append_text(m_xFontList->GetFontName(i).GetFamilyName());
1471     }
1472 }
1473 
FillStyles()1474 void SmSymDefineDialog::FillStyles()
1475 {
1476     m_xStyles->clear();
1477 //    pStyles->SetText(OUString());
1478 
1479     OUString aText(m_xFonts->get_active_text());
1480     if (!aText.isEmpty())
1481     {
1482         // use own StyleNames
1483         const SmFontStyles &rStyles = GetFontStyles();
1484         for (sal_uInt16 i = 0; i < SmFontStyles::GetCount(); ++i)
1485             m_xStyles->append_text(rStyles.GetStyleName(i));
1486 
1487         assert(m_xStyles->get_count() > 0 && "Sm : no styles available");
1488         m_xStyles->set_active(0);
1489     }
1490 }
1491 
GetSymbol(const weld::ComboBox & rComboBox)1492 SmSym* SmSymDefineDialog::GetSymbol(const weld::ComboBox& rComboBox)
1493 {
1494     assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong combobox");
1495     return m_aSymbolMgrCopy.GetSymbolByName(rComboBox.get_active_text());
1496 }
1497 
IMPL_LINK(SmSymDefineDialog,OldSymbolChangeHdl,weld::ComboBox &,rComboBox,void)1498 IMPL_LINK(SmSymDefineDialog, OldSymbolChangeHdl, weld::ComboBox&, rComboBox, void)
1499 {
1500     (void) rComboBox;
1501     assert(&rComboBox == m_xOldSymbols.get() && "Sm : wrong argument");
1502     SelectSymbol(*m_xOldSymbols, m_xOldSymbols->get_active_text(), false);
1503 }
1504 
IMPL_LINK(SmSymDefineDialog,OldSymbolSetChangeHdl,weld::ComboBox &,rComboBox,void)1505 IMPL_LINK( SmSymDefineDialog, OldSymbolSetChangeHdl, weld::ComboBox&, rComboBox, void )
1506 {
1507     (void) rComboBox;
1508     assert(&rComboBox == m_xOldSymbolSets.get() && "Sm : wrong argument");
1509     SelectSymbolSet(*m_xOldSymbolSets, m_xOldSymbolSets->get_active_text(), false);
1510 }
1511 
IMPL_LINK(SmSymDefineDialog,ModifyHdl,weld::ComboBox &,rComboBox,void)1512 IMPL_LINK(SmSymDefineDialog, ModifyHdl, weld::ComboBox&, rComboBox, void)
1513 {
1514     // remember cursor position for later restoring of it
1515     int nStartPos, nEndPos;
1516     rComboBox.get_entry_selection_bounds(nStartPos, nEndPos);
1517 
1518     if (&rComboBox == m_xSymbols.get())
1519         SelectSymbol(*m_xSymbols, m_xSymbols->get_active_text(), false);
1520     else if (&rComboBox == m_xSymbolSets.get())
1521         SelectSymbolSet(*m_xSymbolSets, m_xSymbolSets->get_active_text(), false);
1522     else if (&rComboBox == m_xOldSymbols.get())
1523         // allow only names from the list
1524         SelectSymbol(*m_xOldSymbols, m_xOldSymbols->get_active_text(), true);
1525     else if (&rComboBox == m_xOldSymbolSets.get())
1526         // allow only names from the list
1527         SelectSymbolSet(*m_xOldSymbolSets, m_xOldSymbolSets->get_active_text(), true);
1528     else if (&rComboBox == m_xStyles.get())
1529         // allow only names from the list (that's the case here anyway)
1530         SelectStyle(m_xStyles->get_active_text(), true);
1531     else
1532         SAL_WARN("starmath", "wrong combobox argument");
1533 
1534     rComboBox.select_entry_region(nStartPos, nEndPos);
1535 
1536     UpdateButtons();
1537 }
1538 
IMPL_LINK(SmSymDefineDialog,FontChangeHdl,weld::ComboBox &,rListBox,void)1539 IMPL_LINK(SmSymDefineDialog, FontChangeHdl, weld::ComboBox&, rListBox, void)
1540 {
1541     (void) rListBox;
1542     assert(&rListBox == m_xFonts.get() && "Sm : wrong argument");
1543 
1544     SelectFont(m_xFonts->get_active_text());
1545 }
1546 
IMPL_LINK_NOARG(SmSymDefineDialog,SubsetChangeHdl,weld::ComboBox &,void)1547 IMPL_LINK_NOARG(SmSymDefineDialog, SubsetChangeHdl, weld::ComboBox&, void)
1548 {
1549     int nPos = m_xFontsSubsetLB->get_active();
1550     if (nPos != -1)
1551     {
1552         const Subset* pSubset = reinterpret_cast<const Subset*>(m_xFontsSubsetLB->get_active_id().toUInt64());
1553         if (pSubset)
1554         {
1555             m_xCharsetDisplay->SelectCharacter( pSubset->GetRangeMin() );
1556         }
1557     }
1558 }
1559 
IMPL_LINK(SmSymDefineDialog,StyleChangeHdl,weld::ComboBox &,rComboBox,void)1560 IMPL_LINK( SmSymDefineDialog, StyleChangeHdl, weld::ComboBox&, rComboBox, void )
1561 {
1562     (void) rComboBox;
1563     assert(&rComboBox == m_xStyles.get() && "Sm : wrong argument");
1564 
1565     SelectStyle(m_xStyles->get_active_text());
1566 }
1567 
IMPL_LINK_NOARG(SmSymDefineDialog,CharHighlightHdl,SvxShowCharSet *,void)1568 IMPL_LINK_NOARG(SmSymDefineDialog, CharHighlightHdl, SvxShowCharSet*, void)
1569 {
1570     sal_UCS4 cChar = m_xCharsetDisplay->GetSelectCharacter();
1571 
1572     if (m_xSubsetMap)
1573     {
1574         const Subset* pSubset = m_xSubsetMap->GetSubsetByUnicode(cChar);
1575         if (pSubset)
1576             m_xFontsSubsetLB->set_active_text(pSubset->GetName());
1577         else
1578             m_xFontsSubsetLB->set_active(-1);
1579     }
1580 
1581     m_aSymbolDisplay.SetSymbol(cChar, m_xCharsetDisplay->GetFont());
1582 
1583     UpdateButtons();
1584 
1585     // display Unicode position as symbol name while iterating over characters
1586     const OUString aHex(OUString::number(cChar, 16).toAsciiUpperCase());
1587     const OUString aPattern( (aHex.getLength() > 4) ? OUString("Ux000000") : OUString("Ux0000") );
1588     OUString aUnicodePos = aPattern.copy( 0, aPattern.getLength() - aHex.getLength() ) +
1589         aHex;
1590     m_xSymbols->set_entry_text(aUnicodePos);
1591     m_xSymbolName->set_label(aUnicodePos);
1592 }
1593 
IMPL_LINK(SmSymDefineDialog,AddClickHdl,weld::Button &,rButton,void)1594 IMPL_LINK( SmSymDefineDialog, AddClickHdl, weld::Button&, rButton, void )
1595 {
1596     (void) rButton;
1597     assert(&rButton == m_xAddBtn.get() && "Sm : wrong argument");
1598     assert(rButton.get_sensitive() && "Sm : requirements met ??");
1599 
1600     // add symbol
1601     const SmSym aNewSymbol(m_xSymbols->get_active_text(), m_xCharsetDisplay->GetFont(),
1602             m_xCharsetDisplay->GetSelectCharacter(), m_xSymbolSets->get_active_text());
1603     //OSL_ENSURE( m_aSymbolMgrCopy.GetSymbolByName(aTmpSymbolName) == NULL, "symbol already exists" );
1604     m_aSymbolMgrCopy.AddOrReplaceSymbol( aNewSymbol );
1605 
1606     // update display of new symbol
1607     m_aSymbolDisplay.SetSymbol( &aNewSymbol );
1608     m_xSymbolName->set_label(aNewSymbol.GetName());
1609     m_xSymbolSetName->set_label(aNewSymbol.GetSymbolSetName());
1610 
1611     // update list box entries
1612     FillSymbolSets(*m_xOldSymbolSets, false);
1613     FillSymbolSets(*m_xSymbolSets, false);
1614     FillSymbols(*m_xOldSymbols, false);
1615     FillSymbols(*m_xSymbols, false);
1616 
1617     UpdateButtons();
1618 }
1619 
IMPL_LINK(SmSymDefineDialog,ChangeClickHdl,weld::Button &,rButton,void)1620 IMPL_LINK( SmSymDefineDialog, ChangeClickHdl, weld::Button&, rButton, void )
1621 {
1622     (void) rButton;
1623     assert(&rButton == m_xChangeBtn.get() && "Sm : wrong argument");
1624     assert(m_xChangeBtn->get_sensitive() && "Sm : requirements met ??");
1625 
1626     // get new Symbol to use
1627     //! get font from symbol-disp lay since charset-display does not keep
1628     //! the bold attribute.
1629     const SmSym aNewSymbol(m_xSymbols->get_active_text(), m_xCharsetDisplay->GetFont(),
1630             m_xCharsetDisplay->GetSelectCharacter(), m_xSymbolSets->get_active_text());
1631 
1632     // remove old symbol if the name was changed then add new one
1633     const bool bNameChanged = m_xOldSymbols->get_active_text() != m_xSymbols->get_active_text();
1634     if (bNameChanged)
1635         m_aSymbolMgrCopy.RemoveSymbol(m_xOldSymbols->get_active_text());
1636     m_aSymbolMgrCopy.AddOrReplaceSymbol( aNewSymbol, true );
1637 
1638     // clear display for original symbol if necessary
1639     if (bNameChanged)
1640         SetOrigSymbol(nullptr, OUString());
1641 
1642     // update display of new symbol
1643     m_aSymbolDisplay.SetSymbol(&aNewSymbol);
1644     m_xSymbolName->set_label(aNewSymbol.GetName());
1645     m_xSymbolSetName->set_label(aNewSymbol.GetSymbolSetName());
1646 
1647     // update list box entries
1648     FillSymbolSets(*m_xOldSymbolSets, false);
1649     FillSymbolSets(*m_xSymbolSets, false);
1650     FillSymbols(*m_xOldSymbols, false);
1651     FillSymbols(*m_xSymbols, false);
1652 
1653     UpdateButtons();
1654 }
1655 
IMPL_LINK(SmSymDefineDialog,DeleteClickHdl,weld::Button &,rButton,void)1656 IMPL_LINK(SmSymDefineDialog, DeleteClickHdl, weld::Button&, rButton, void)
1657 {
1658     (void) rButton;
1659     assert(&rButton == m_xDeleteBtn.get() && "Sm : wrong argument");
1660     assert(m_xDeleteBtn->get_sensitive() && "Sm : requirements met ??");
1661 
1662     if (m_xOrigSymbol)
1663     {
1664         m_aSymbolMgrCopy.RemoveSymbol(m_xOrigSymbol->GetName());
1665 
1666         // clear display for original symbol
1667         SetOrigSymbol(nullptr, OUString());
1668 
1669         // update list box entries
1670         FillSymbolSets(*m_xOldSymbolSets, false);
1671         FillSymbolSets(*m_xSymbolSets,    false);
1672         FillSymbols(*m_xOldSymbols ,false);
1673         FillSymbols(*m_xSymbols    ,false);
1674     }
1675 
1676     UpdateButtons();
1677 }
1678 
UpdateButtons()1679 void SmSymDefineDialog::UpdateButtons()
1680 {
1681     bool  bAdd    = false,
1682           bChange = false,
1683           bDelete = false;
1684     OUString aTmpSymbolName(m_xSymbols->get_active_text()),
1685              aTmpSymbolSetName(m_xSymbolSets->get_active_text());
1686 
1687     if (!aTmpSymbolName.isEmpty() && !aTmpSymbolSetName.isEmpty())
1688     {
1689         // are all settings equal?
1690         //! (Font-, Style- and SymbolSet name comparison is not case sensitive)
1691         bool bEqual = m_xOrigSymbol
1692                     && aTmpSymbolSetName.equalsIgnoreAsciiCase(m_xOldSymbolSetName->get_label())
1693                     && aTmpSymbolName == m_xOrigSymbol->GetName()
1694                     && m_xFonts->get_active_text().equalsIgnoreAsciiCase(
1695                             m_xOrigSymbol->GetFace().GetFamilyName())
1696                     && m_xStyles->get_active_text().equalsIgnoreAsciiCase(
1697                             GetFontStyles().GetStyleName(m_xOrigSymbol->GetFace()))
1698                     && m_xCharsetDisplay->GetSelectCharacter() == m_xOrigSymbol->GetCharacter();
1699 
1700         // only add it if there isn't already a symbol with the same name
1701         bAdd    = m_aSymbolMgrCopy.GetSymbolByName(aTmpSymbolName) == nullptr;
1702 
1703         // only delete it if all settings are equal
1704         bDelete = bool(m_xOrigSymbol);
1705 
1706         // only change it if the old symbol exists and the new one is different
1707         bChange = m_xOrigSymbol && !bEqual;
1708     }
1709 
1710     m_xAddBtn->set_sensitive(bAdd);
1711     m_xChangeBtn->set_sensitive(bChange);
1712     m_xDeleteBtn->set_sensitive(bDelete);
1713 }
1714 
SmSymDefineDialog(weld::Window * pParent,OutputDevice * pFntListDevice,SmSymbolManager & rMgr)1715 SmSymDefineDialog::SmSymDefineDialog(weld::Window* pParent, OutputDevice *pFntListDevice, SmSymbolManager &rMgr)
1716     : GenericDialogController(pParent, "modules/smath/ui/symdefinedialog.ui", "EditSymbols")
1717     , m_xVirDev(VclPtr<VirtualDevice>::Create())
1718     , m_rSymbolMgr(rMgr)
1719     , m_xFontList(new FontList(pFntListDevice))
1720     , m_xOldSymbols(m_xBuilder->weld_combo_box("oldSymbols"))
1721     , m_xOldSymbolSets(m_xBuilder->weld_combo_box("oldSymbolSets"))
1722     , m_xSymbols(m_xBuilder->weld_combo_box("symbols"))
1723     , m_xSymbolSets(m_xBuilder->weld_combo_box("symbolSets"))
1724     , m_xFonts(m_xBuilder->weld_combo_box("fonts"))
1725     , m_xFontsSubsetLB(m_xBuilder->weld_combo_box("fontsSubsetLB"))
1726     , m_xStyles(m_xBuilder->weld_combo_box("styles"))
1727     , m_xOldSymbolName(m_xBuilder->weld_label("oldSymbolName"))
1728     , m_xOldSymbolSetName(m_xBuilder->weld_label("oldSymbolSetName"))
1729     , m_xSymbolName(m_xBuilder->weld_label("symbolName"))
1730     , m_xSymbolSetName(m_xBuilder->weld_label("symbolSetName"))
1731     , m_xAddBtn(m_xBuilder->weld_button("add"))
1732     , m_xChangeBtn(m_xBuilder->weld_button("modify"))
1733     , m_xDeleteBtn(m_xBuilder->weld_button("delete"))
1734     , m_xOldSymbolDisplay(new weld::CustomWeld(*m_xBuilder, "oldSymbolDisplay", m_aOldSymbolDisplay))
1735     , m_xSymbolDisplay(new weld::CustomWeld(*m_xBuilder, "symbolDisplay", m_aSymbolDisplay))
1736     , m_xCharsetDisplay(new SvxShowCharSet(m_xBuilder->weld_scrolled_window("showscroll"), m_xVirDev))
1737     , m_xCharsetDisplayArea(new weld::CustomWeld(*m_xBuilder, "charsetDisplay", *m_xCharsetDisplay))
1738 {
1739     // auto completion is troublesome since that symbols character also gets automatically selected in the
1740     // display and if the user previously selected a character to define/redefine that one this is bad
1741     m_xOldSymbols->set_entry_completion(false);
1742     m_xSymbols->set_entry_completion(false);
1743 
1744     FillFonts();
1745     if (m_xFonts->get_count() > 0)
1746         SelectFont(m_xFonts->get_text(0));
1747 
1748     SetSymbolSetManager(m_rSymbolMgr);
1749 
1750     m_xOldSymbols->connect_changed(LINK(this, SmSymDefineDialog, OldSymbolChangeHdl));
1751     m_xOldSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, OldSymbolSetChangeHdl));
1752     m_xSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1753     m_xOldSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1754     m_xSymbols->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1755     m_xOldSymbols->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1756     m_xStyles->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1757     m_xFonts->connect_changed(LINK(this, SmSymDefineDialog, FontChangeHdl));
1758     m_xFontsSubsetLB->connect_changed(LINK(this, SmSymDefineDialog, SubsetChangeHdl));
1759     m_xStyles->connect_changed(LINK(this, SmSymDefineDialog, StyleChangeHdl));
1760     m_xAddBtn->connect_clicked(LINK(this, SmSymDefineDialog, AddClickHdl));
1761     m_xChangeBtn->connect_clicked(LINK(this, SmSymDefineDialog, ChangeClickHdl));
1762     m_xDeleteBtn->connect_clicked(LINK(this, SmSymDefineDialog, DeleteClickHdl));
1763     m_xCharsetDisplay->SetHighlightHdl( LINK( this, SmSymDefineDialog, CharHighlightHdl ) );
1764 }
1765 
~SmSymDefineDialog()1766 SmSymDefineDialog::~SmSymDefineDialog()
1767 {
1768 }
1769 
run()1770 short SmSymDefineDialog::run()
1771 {
1772     short nResult = GenericDialogController::run();
1773 
1774     // apply changes if dialog was closed by clicking OK
1775     if (m_aSymbolMgrCopy.IsModified() && nResult == RET_OK)
1776         m_rSymbolMgr = m_aSymbolMgrCopy;
1777 
1778     return nResult;
1779 }
1780 
SetSymbolSetManager(const SmSymbolManager & rMgr)1781 void SmSymDefineDialog::SetSymbolSetManager(const SmSymbolManager &rMgr)
1782 {
1783     m_aSymbolMgrCopy = rMgr;
1784 
1785     // Set the modified flag of the copy to false so that
1786     // we can check later on if anything has been changed
1787     m_aSymbolMgrCopy.SetModified(false);
1788 
1789     FillSymbolSets(*m_xOldSymbolSets);
1790     if (m_xOldSymbolSets->get_count() > 0)
1791         SelectSymbolSet(m_xOldSymbolSets->get_text(0));
1792     FillSymbolSets(*m_xSymbolSets);
1793     if (m_xSymbolSets->get_count() > 0)
1794         SelectSymbolSet(m_xSymbolSets->get_text(0));
1795     FillSymbols(*m_xOldSymbols);
1796     if (m_xOldSymbols->get_count() > 0)
1797         SelectSymbol(m_xOldSymbols->get_text(0));
1798     FillSymbols(*m_xSymbols);
1799     if (m_xSymbols->get_count() > 0)
1800         SelectSymbol(m_xSymbols->get_text(0));
1801 
1802     UpdateButtons();
1803 }
1804 
SelectSymbolSet(weld::ComboBox & rComboBox,const OUString & rSymbolSetName,bool bDeleteText)1805 bool SmSymDefineDialog::SelectSymbolSet(weld::ComboBox& rComboBox,
1806         const OUString &rSymbolSetName, bool bDeleteText)
1807 {
1808     assert((&rComboBox == m_xOldSymbolSets.get() || &rComboBox == m_xSymbolSets.get()) && "Sm : wrong ComboBox");
1809 
1810     // trim SymbolName (no leading and trailing blanks)
1811     OUString aNormName = comphelper::string::stripStart(rSymbolSetName, ' ');
1812     aNormName = comphelper::string::stripEnd(aNormName, ' ');
1813     // and remove possible deviations within the input
1814     rComboBox.set_entry_text(aNormName);
1815 
1816     bool   bRet = false;
1817     int nPos = rComboBox.find_text(aNormName);
1818 
1819     if (nPos != -1)
1820     {
1821         rComboBox.set_active(nPos);
1822         bRet = true;
1823     }
1824     else if (bDeleteText)
1825         rComboBox.set_entry_text(OUString());
1826 
1827     bool  bIsOld = &rComboBox == m_xOldSymbolSets.get();
1828 
1829     // setting the SymbolSet name at the associated display
1830     weld::Label& rFT = bIsOld ? *m_xOldSymbolSetName : *m_xSymbolSetName;
1831     rFT.set_label(rComboBox.get_active_text());
1832 
1833     // set the symbol name which belongs to the SymbolSet at the associated combobox
1834     weld::ComboBox& rCB = bIsOld ? *m_xOldSymbols : *m_xSymbols;
1835     FillSymbols(rCB, false);
1836 
1837     // display a valid respectively no symbol when changing the SymbolSets
1838     if (bIsOld)
1839     {
1840         OUString aTmpOldSymbolName;
1841         if (m_xOldSymbols->get_count() > 0)
1842             aTmpOldSymbolName = m_xOldSymbols->get_text(0);
1843         SelectSymbol(*m_xOldSymbols, aTmpOldSymbolName, true);
1844     }
1845 
1846     UpdateButtons();
1847 
1848     return bRet;
1849 }
1850 
SetOrigSymbol(const SmSym * pSymbol,const OUString & rSymbolSetName)1851 void SmSymDefineDialog::SetOrigSymbol(const SmSym *pSymbol,
1852                                       const OUString &rSymbolSetName)
1853 {
1854     // clear old symbol
1855     m_xOrigSymbol.reset();
1856 
1857     OUString   aSymName,
1858                 aSymSetName;
1859     if (pSymbol)
1860     {
1861         // set new symbol
1862         m_xOrigSymbol.reset(new SmSym(*pSymbol));
1863 
1864         aSymName    = pSymbol->GetName();
1865         aSymSetName = rSymbolSetName;
1866         m_aOldSymbolDisplay.SetSymbol( pSymbol );
1867     }
1868     else
1869     {   // delete displayed symbols
1870         m_aOldSymbolDisplay.SetText(OUString());
1871         m_aOldSymbolDisplay.Invalidate();
1872     }
1873     m_xOldSymbolName->set_label(aSymName);
1874     m_xOldSymbolSetName->set_label(aSymSetName);
1875 }
1876 
1877 
SelectSymbol(weld::ComboBox & rComboBox,const OUString & rSymbolName,bool bDeleteText)1878 bool SmSymDefineDialog::SelectSymbol(weld::ComboBox& rComboBox,
1879         const OUString &rSymbolName, bool bDeleteText)
1880 {
1881     assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong ComboBox");
1882 
1883     // trim SymbolName (no blanks)
1884     OUString  aNormName = rSymbolName.replaceAll(" ", "");
1885     // and remove possible deviations within the input
1886     rComboBox.set_entry_text(aNormName);
1887 
1888     bool   bRet = false;
1889     int nPos = rComboBox.find_text(aNormName);
1890 
1891     bool  bIsOld = &rComboBox == m_xOldSymbols.get();
1892 
1893     if (nPos != -1)
1894     {
1895         rComboBox.set_active(nPos);
1896 
1897         if (!bIsOld)
1898         {
1899             const SmSym *pSymbol = GetSymbol(*m_xSymbols);
1900             if (pSymbol)
1901             {
1902                 // choose font and style accordingly
1903                 const vcl::Font &rFont = pSymbol->GetFace();
1904                 SelectFont(rFont.GetFamilyName(), false);
1905                 SelectStyle(GetFontStyles().GetStyleName(rFont), false);
1906 
1907                 // Since setting the Font via the Style name of the SymbolFonts doesn't
1908                 // work really well (e.g. it can be empty even though the font itself is
1909                 // bold or italic) we're manually setting the Font with respect to the Symbol
1910                 m_xCharsetDisplay->SetFont(rFont);
1911                 m_aSymbolDisplay.SetFont(rFont);
1912 
1913                 // select associated character
1914                 SelectChar(pSymbol->GetCharacter());
1915 
1916                 // since SelectChar will also set the unicode point as text in the
1917                 // symbols box, we have to set the symbol name again to get that one displayed
1918                 m_xSymbols->set_entry_text(pSymbol->GetName());
1919             }
1920         }
1921 
1922         bRet = true;
1923     }
1924     else if (bDeleteText)
1925         rComboBox.set_entry_text(OUString());
1926 
1927     if (bIsOld)
1928     {
1929         // if there's a change of the old symbol, show only the available ones, otherwise show none
1930         const SmSym *pOldSymbol = nullptr;
1931         OUString     aTmpOldSymbolSetName;
1932         if (nPos != -1)
1933         {
1934             pOldSymbol        = m_aSymbolMgrCopy.GetSymbolByName(aNormName);
1935             aTmpOldSymbolSetName = m_xOldSymbolSets->get_active_text();
1936         }
1937         SetOrigSymbol(pOldSymbol, aTmpOldSymbolSetName);
1938     }
1939     else
1940         m_xSymbolName->set_label(rComboBox.get_active_text());
1941 
1942     UpdateButtons();
1943 
1944     return bRet;
1945 }
1946 
1947 
SetFont(const OUString & rFontName,const OUString & rStyleName)1948 void SmSymDefineDialog::SetFont(const OUString &rFontName, const OUString &rStyleName)
1949 {
1950     // get Font (FontInfo) matching name and style
1951     FontMetric aFontMetric;
1952     if (m_xFontList)
1953         aFontMetric = m_xFontList->Get(rFontName, WEIGHT_NORMAL, ITALIC_NONE);
1954     SetFontStyle(rStyleName, aFontMetric);
1955 
1956     m_xCharsetDisplay->SetFont(aFontMetric);
1957     m_aSymbolDisplay.SetFont(aFontMetric);
1958 
1959     // update subset listbox for new font's unicode subsets
1960     FontCharMapRef xFontCharMap = m_xCharsetDisplay->GetFontCharMap();
1961     m_xSubsetMap.reset(new SubsetMap( xFontCharMap ));
1962 
1963     m_xFontsSubsetLB->clear();
1964     bool bFirst = true;
1965     for (auto & subset : m_xSubsetMap->GetSubsetMap())
1966     {
1967         m_xFontsSubsetLB->append(OUString::number(reinterpret_cast<sal_uInt64>(&subset)), subset.GetName());
1968         // subset must live at least as long as the selected font !!!
1969         if (bFirst)
1970             m_xFontsSubsetLB->set_active(0);
1971         bFirst = false;
1972     }
1973     if (bFirst)
1974         m_xFontsSubsetLB->set_active(-1);
1975     m_xFontsSubsetLB->set_sensitive(!bFirst);
1976 }
1977 
SelectFont(const OUString & rFontName,bool bApplyFont)1978 bool SmSymDefineDialog::SelectFont(const OUString &rFontName, bool bApplyFont)
1979 {
1980     bool   bRet = false;
1981     int nPos = m_xFonts->find_text(rFontName);
1982 
1983     if (nPos != -1)
1984     {
1985         m_xFonts->set_active(nPos);
1986         if (m_xStyles->get_count() > 0)
1987             SelectStyle(m_xStyles->get_text(0));
1988         if (bApplyFont)
1989         {
1990             SetFont(m_xFonts->get_active_text(), m_xStyles->get_active_text());
1991             m_aSymbolDisplay.SetSymbol(m_xCharsetDisplay->GetSelectCharacter(), m_xCharsetDisplay->GetFont());
1992         }
1993         bRet = true;
1994     }
1995     else
1996         m_xFonts->set_active(-1);
1997     FillStyles();
1998 
1999     UpdateButtons();
2000 
2001     return bRet;
2002 }
2003 
2004 
SelectStyle(const OUString & rStyleName,bool bApplyFont)2005 bool SmSymDefineDialog::SelectStyle(const OUString &rStyleName, bool bApplyFont)
2006 {
2007     bool   bRet = false;
2008     int nPos = m_xStyles->find_text(rStyleName);
2009 
2010     // if the style is not available take the first available one (if existent)
2011     if (nPos == -1 && m_xStyles->get_count() > 0)
2012         nPos = 0;
2013 
2014     if (nPos != -1)
2015     {
2016         m_xStyles->set_active(nPos);
2017         if (bApplyFont)
2018         {
2019             SetFont(m_xFonts->get_active_text(), m_xStyles->get_active_text());
2020             m_aSymbolDisplay.SetSymbol(m_xCharsetDisplay->GetSelectCharacter(), m_xCharsetDisplay->GetFont());
2021         }
2022         bRet = true;
2023     }
2024     else
2025         m_xStyles->set_entry_text(OUString());
2026 
2027     UpdateButtons();
2028 
2029     return bRet;
2030 }
2031 
SelectChar(sal_Unicode cChar)2032 void SmSymDefineDialog::SelectChar(sal_Unicode cChar)
2033 {
2034     m_xCharsetDisplay->SelectCharacter( cChar );
2035     m_aSymbolDisplay.SetSymbol(cChar, m_xCharsetDisplay->GetFont());
2036 
2037     UpdateButtons();
2038 }
2039 
2040 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2041