use "Rubik" from more_fonts instead of "System" for consistent layout
[LibreOffice.git] / starmath / source / dialog.cxx
blob043739cf5c0d2a1552829bb4e854b983c51e653c
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 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <comphelper/string.hxx>
24 #include <o3tl/temporary.hxx>
25 #include <svl/eitem.hxx>
26 #include <svl/intitem.hxx>
27 #include <svl/stritem.hxx>
28 #include <vcl/event.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/virdev.hxx>
31 #include <vcl/weld.hxx>
32 #include <svtools/ctrltool.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/wall.hxx>
35 #include <vcl/fontcharmap.hxx>
36 #include <sfx2/dispatch.hxx>
37 #include <svx/charmap.hxx>
38 #include <svx/ucsubset.hxx>
40 #include <dialog.hxx>
41 #include <starmath.hrc>
42 #include <strings.hrc>
43 #include <helpids.h>
44 #include <cfgitem.hxx>
45 #include <smmod.hxx>
46 #include <symbol.hxx>
47 #include <view.hxx>
49 #include <algorithm>
51 namespace
54 void lclGetSettingColors(Color& rBackgroundColor, Color& rTextColor)
56 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
57 if (rStyleSettings.GetHighContrastMode())
59 rBackgroundColor = rStyleSettings.GetFieldColor();
60 rTextColor = rStyleSettings.GetFieldTextColor();
62 else
64 rBackgroundColor = COL_WHITE;
65 rTextColor = COL_BLACK;
69 // Since it's better to set/query the FontStyle via its attributes rather
70 // than via the StyleName we create a way to translate
71 // Attribute <-> StyleName
73 class SmFontStyles
75 OUString aNormal;
76 OUString aBold;
77 OUString aItalic;
78 OUString aBoldItalic;
80 public:
81 SmFontStyles();
83 static sal_uInt16 GetCount() { return 4; }
84 const OUString& GetStyleName(const vcl::Font& rFont) const;
85 const OUString& GetStyleName(sal_uInt16 nIdx) const;
88 } // end anonymous namespace
90 SmFontStyles::SmFontStyles()
91 : aNormal(SmResId(RID_FONTREGULAR))
92 , aBold(SmResId(RID_FONTBOLD))
93 , aItalic(SmResId(RID_FONTITALIC))
95 aBoldItalic = aBold;
96 aBoldItalic += ", ";
97 aBoldItalic += aItalic;
100 const OUString& SmFontStyles::GetStyleName(const vcl::Font& rFont) const
102 //! compare also SmSpecialNode::Prepare
103 bool bBold = IsBold( rFont ),
104 bItalic = IsItalic( rFont );
106 if (bBold && bItalic)
107 return aBoldItalic;
108 else if (bItalic)
109 return aItalic;
110 else if (bBold)
111 return aBold;
112 return aNormal;
115 const OUString& SmFontStyles::GetStyleName( sal_uInt16 nIdx ) const
117 // 0 = "normal", 1 = "italic",
118 // 2 = "bold", 3 = "bold italic"
120 assert( nIdx < GetCount() );
121 switch (nIdx)
123 case 0 : return aNormal;
124 case 1 : return aItalic;
125 case 2 : return aBold;
126 default: /*case 3:*/ return aBoldItalic;
130 static const SmFontStyles & GetFontStyles()
132 static const SmFontStyles aImpl;
133 return aImpl;
136 void SetFontStyle(std::u16string_view rStyleName, vcl::Font &rFont)
138 // Find index related to StyleName. For an empty StyleName it's assumed to be
139 // 0 (neither bold nor italic).
140 sal_uInt16 nIndex = 0;
141 if (!rStyleName.empty())
143 sal_uInt16 i;
144 const SmFontStyles &rStyles = GetFontStyles();
145 for (i = 0; i < SmFontStyles::GetCount(); ++i)
146 if (rStyleName == rStyles.GetStyleName(i))
147 break;
148 assert(i < SmFontStyles::GetCount() && "style-name unknown");
149 nIndex = i;
152 rFont.SetItalic((nIndex & 0x1) ? ITALIC_NORMAL : ITALIC_NONE);
153 rFont.SetWeight((nIndex & 0x2) ? WEIGHT_BOLD : WEIGHT_NORMAL);
156 IMPL_LINK_NOARG(SmPrintOptionsTabPage, SizeButtonClickHdl, weld::Toggleable&, void)
158 m_xZoom->set_sensitive(m_xSizeZoomed->get_active());
161 SmPrintOptionsTabPage::SmPrintOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rOptions)
162 : SfxTabPage(pPage, pController, "modules/smath/ui/smathsettings.ui", "SmathSettings", &rOptions)
163 , m_xTitle(m_xBuilder->weld_check_button("title"))
164 , m_xText(m_xBuilder->weld_check_button("text"))
165 , m_xFrame(m_xBuilder->weld_check_button("frame"))
166 , m_xSizeNormal(m_xBuilder->weld_radio_button("sizenormal"))
167 , m_xSizeScaled(m_xBuilder->weld_radio_button("sizescaled"))
168 , m_xSizeZoomed(m_xBuilder->weld_radio_button("sizezoomed"))
169 , m_xZoom(m_xBuilder->weld_metric_spin_button("zoom", FieldUnit::PERCENT))
170 , m_xNoRightSpaces(m_xBuilder->weld_check_button("norightspaces"))
171 , m_xSaveOnlyUsedSymbols(m_xBuilder->weld_check_button("saveonlyusedsymbols"))
172 , m_xAutoCloseBrackets(m_xBuilder->weld_check_button("autoclosebrackets"))
173 , m_xSmZoom(m_xBuilder->weld_metric_spin_button("smzoom", FieldUnit::PERCENT))
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));
179 Reset(&rOptions);
182 SmPrintOptionsTabPage::~SmPrintOptionsTabPage()
184 SmGetActiveView()->GetEditWindow()->UpdateStatus();
187 bool SmPrintOptionsTabPage::FillItemSet(SfxItemSet* rSet)
189 sal_uInt16 nPrintSize;
190 if (m_xSizeNormal->get_active())
191 nPrintSize = PRINT_SIZE_NORMAL;
192 else if (m_xSizeScaled->get_active())
193 nPrintSize = PRINT_SIZE_SCALED;
194 else
195 nPrintSize = PRINT_SIZE_ZOOMED;
197 rSet->Put(SfxUInt16Item(SID_PRINTSIZE, nPrintSize));
198 rSet->Put(SfxUInt16Item(SID_PRINTZOOM, sal::static_int_cast<sal_uInt16>(m_xZoom->get_value(FieldUnit::PERCENT))));
199 rSet->Put(SfxBoolItem(SID_PRINTTITLE, m_xTitle->get_active()));
200 rSet->Put(SfxBoolItem(SID_PRINTTEXT, m_xText->get_active()));
201 rSet->Put(SfxBoolItem(SID_PRINTFRAME, m_xFrame->get_active()));
202 rSet->Put(SfxBoolItem(SID_NO_RIGHT_SPACES, m_xNoRightSpaces->get_active()));
203 rSet->Put(SfxBoolItem(SID_SAVE_ONLY_USED_SYMBOLS, m_xSaveOnlyUsedSymbols->get_active()));
204 rSet->Put(SfxBoolItem(SID_AUTO_CLOSE_BRACKETS, m_xAutoCloseBrackets->get_active()));
205 rSet->Put(SfxUInt16Item(SID_SMEDITWINDOWZOOM, sal::static_int_cast<sal_uInt16>(m_xSmZoom->get_value(FieldUnit::PERCENT))));
207 SmGetActiveView()->GetEditWindow()->UpdateStatus();
208 return true;
211 void SmPrintOptionsTabPage::Reset(const SfxItemSet* rSet)
213 SmPrintSize ePrintSize = static_cast<SmPrintSize>(rSet->Get(SID_PRINTSIZE).GetValue());
215 m_xSizeNormal->set_active(ePrintSize == PRINT_SIZE_NORMAL);
216 m_xSizeScaled->set_active(ePrintSize == PRINT_SIZE_SCALED);
217 m_xSizeZoomed->set_active(ePrintSize == PRINT_SIZE_ZOOMED);
219 m_xZoom->set_sensitive(m_xSizeZoomed->get_active());
221 m_xZoom->set_value(rSet->Get(SID_PRINTZOOM).GetValue(), FieldUnit::PERCENT);
223 m_xSmZoom->set_sensitive(true);
224 m_xSmZoom->set_value(rSet->Get(SID_SMEDITWINDOWZOOM).GetValue(), FieldUnit::PERCENT);
226 m_xTitle->set_active(rSet->Get(SID_PRINTTITLE).GetValue());
227 m_xNoRightSpaces->set_active(rSet->Get(SID_NO_RIGHT_SPACES).GetValue());
228 m_xSaveOnlyUsedSymbols->set_active(rSet->Get(SID_SAVE_ONLY_USED_SYMBOLS).GetValue());
229 m_xAutoCloseBrackets->set_active(rSet->Get(SID_AUTO_CLOSE_BRACKETS).GetValue());
232 std::unique_ptr<SfxTabPage> SmPrintOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
234 return std::make_unique<SmPrintOptionsTabPage>(pPage, pController, rSet);
237 void SmShowFont::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
239 Color aBackColor;
240 Color aTextColor;
241 lclGetSettingColors(aBackColor, aTextColor);
243 rRenderContext.SetBackground(Wallpaper(aBackColor));
245 vcl::Font aFont(maFont);
246 aFont.SetFontSize(Size(0, 24 * rRenderContext.GetDPIScaleFactor()));
247 aFont.SetAlignment(ALIGN_TOP);
248 rRenderContext.SetFont(aFont);
249 rRenderContext.SetTextColor(aTextColor);
251 OUString sText(rRenderContext.GetFont().GetFamilyName());
252 Size aTextSize(rRenderContext.GetTextWidth(sText), rRenderContext.GetTextHeight());
254 rRenderContext.DrawText(Point((rRenderContext.GetOutputSize().Width() - aTextSize.Width()) / 2,
255 (rRenderContext.GetOutputSize().Height() - aTextSize.Height()) / 2), sText);
258 void SmShowFont::SetDrawingArea(weld::DrawingArea* pDrawingArea)
260 CustomWidgetController::SetDrawingArea(pDrawingArea);
261 Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(111 , 31), MapMode(MapUnit::MapAppFont)));
262 pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
265 void SmShowFont::SetFont(const vcl::Font& rFont)
267 maFont = rFont;
268 Invalidate();
271 IMPL_LINK( SmFontDialog, FontSelectHdl, weld::ComboBox&, rComboBox, void )
273 maFont.SetFamilyName(rComboBox.get_active_text());
274 m_aShowFont.SetFont(maFont);
277 IMPL_LINK_NOARG(SmFontDialog, AttrChangeHdl, weld::Toggleable&, void)
279 if (m_xBoldCheckBox->get_active())
280 maFont.SetWeight(WEIGHT_BOLD);
281 else
282 maFont.SetWeight(WEIGHT_NORMAL);
284 if (m_xItalicCheckBox->get_active())
285 maFont.SetItalic(ITALIC_NORMAL);
286 else
287 maFont.SetItalic(ITALIC_NONE);
289 m_aShowFont.SetFont(maFont);
292 void SmFontDialog::SetFont(const vcl::Font &rFont)
294 maFont = rFont;
296 m_xFontBox->set_active_text(maFont.GetFamilyName());
297 m_xBoldCheckBox->set_active(IsBold(maFont));
298 m_xItalicCheckBox->set_active(IsItalic(maFont));
299 m_aShowFont.SetFont(maFont);
302 SmFontDialog::SmFontDialog(weld::Window * pParent, OutputDevice *pFntListDevice, bool bHideCheckboxes)
303 : GenericDialogController(pParent, "modules/smath/ui/fontdialog.ui", "FontDialog")
304 , m_xFontBox(m_xBuilder->weld_entry_tree_view("fontgrid", "font", "fonts"))
305 , m_xAttrFrame(m_xBuilder->weld_widget("attrframe"))
306 , m_xBoldCheckBox(m_xBuilder->weld_check_button("bold"))
307 , m_xItalicCheckBox(m_xBuilder->weld_check_button("italic"))
308 , m_xShowFont(new weld::CustomWeld(*m_xBuilder, "preview", m_aShowFont))
310 m_xFontBox->set_height_request_by_rows(8);
313 weld::WaitObject aWait(pParent);
315 FontList aFontList( pFntListDevice );
317 sal_uInt16 nCount = aFontList.GetFontNameCount();
318 for (sal_uInt16 i = 0; i < nCount; ++i)
320 m_xFontBox->append_text(aFontList.GetFontName(i).GetFamilyName());
322 maFont.SetFontSize(Size(0, 24));
323 maFont.SetWeight(WEIGHT_NORMAL);
324 maFont.SetItalic(ITALIC_NONE);
325 maFont.SetFamily(FAMILY_DONTKNOW);
326 maFont.SetPitch(PITCH_DONTKNOW);
327 maFont.SetCharSet(RTL_TEXTENCODING_DONTKNOW);
328 maFont.SetTransparent(true);
331 m_xFontBox->connect_changed(LINK(this, SmFontDialog, FontSelectHdl));
332 m_xBoldCheckBox->connect_toggled(LINK(this, SmFontDialog, AttrChangeHdl));
333 m_xItalicCheckBox->connect_toggled(LINK(this, SmFontDialog, AttrChangeHdl));
335 if (bHideCheckboxes)
337 m_xBoldCheckBox->set_active(false);
338 m_xBoldCheckBox->set_sensitive(false);
339 m_xItalicCheckBox->set_active(false);
340 m_xItalicCheckBox->set_sensitive(false);
341 m_xAttrFrame->hide();
345 SmFontDialog::~SmFontDialog()
349 namespace {
351 class SaveDefaultsQuery : public weld::MessageDialogController
353 public:
354 explicit SaveDefaultsQuery(weld::Widget* pParent)
355 : MessageDialogController(pParent, "modules/smath/ui/savedefaultsdialog.ui",
356 "SaveDefaultsDialog")
363 IMPL_LINK_NOARG( SmFontSizeDialog, DefaultButtonClickHdl, weld::Button&, void )
365 SaveDefaultsQuery aQuery(m_xDialog.get());
366 if (aQuery.run() == RET_YES)
368 SmModule *pp = SM_MOD();
369 SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
370 WriteTo( aFmt );
371 pp->GetConfig()->SetStandardFormat( aFmt );
375 SmFontSizeDialog::SmFontSizeDialog(weld::Window* pParent)
376 : GenericDialogController(pParent, "modules/smath/ui/fontsizedialog.ui", "FontSizeDialog")
377 , m_xBaseSize(m_xBuilder->weld_metric_spin_button("spinB_baseSize", FieldUnit::POINT))
378 , m_xTextSize(m_xBuilder->weld_metric_spin_button("spinB_text", FieldUnit::PERCENT))
379 , m_xIndexSize(m_xBuilder->weld_metric_spin_button("spinB_index", FieldUnit::PERCENT))
380 , m_xFunctionSize(m_xBuilder->weld_metric_spin_button("spinB_function", FieldUnit::PERCENT))
381 , m_xOperatorSize(m_xBuilder->weld_metric_spin_button("spinB_operator", FieldUnit::PERCENT))
382 , m_xBorderSize(m_xBuilder->weld_metric_spin_button("spinB_limit", FieldUnit::PERCENT))
383 , m_xDefaultButton(m_xBuilder->weld_button("default"))
385 m_xDefaultButton->connect_clicked(LINK(this, SmFontSizeDialog, DefaultButtonClickHdl));
388 SmFontSizeDialog::~SmFontSizeDialog()
392 void SmFontSizeDialog::ReadFrom(const SmFormat &rFormat)
394 //! watch out: round properly!
395 m_xBaseSize->set_value( SmRoundFraction(
396 Sm100th_mmToPts( rFormat.GetBaseSize().Height() ) ), FieldUnit::NONE );
398 m_xTextSize->set_value( rFormat.GetRelSize(SIZ_TEXT), FieldUnit::NONE );
399 m_xIndexSize->set_value( rFormat.GetRelSize(SIZ_INDEX), FieldUnit::NONE );
400 m_xFunctionSize->set_value( rFormat.GetRelSize(SIZ_FUNCTION), FieldUnit::NONE );
401 m_xOperatorSize->set_value( rFormat.GetRelSize(SIZ_OPERATOR), FieldUnit::NONE );
402 m_xBorderSize->set_value( rFormat.GetRelSize(SIZ_LIMITS), FieldUnit::NONE );
405 void SmFontSizeDialog::WriteTo(SmFormat &rFormat) const
407 rFormat.SetBaseSize( Size(0, SmPtsTo100th_mm( static_cast< tools::Long >(m_xBaseSize->get_value(FieldUnit::NONE)))) );
409 rFormat.SetRelSize(SIZ_TEXT, sal::static_int_cast<sal_uInt16>(m_xTextSize->get_value(FieldUnit::NONE)));
410 rFormat.SetRelSize(SIZ_INDEX, sal::static_int_cast<sal_uInt16>(m_xIndexSize->get_value(FieldUnit::NONE)));
411 rFormat.SetRelSize(SIZ_FUNCTION, sal::static_int_cast<sal_uInt16>(m_xFunctionSize->get_value(FieldUnit::NONE)));
412 rFormat.SetRelSize(SIZ_OPERATOR, sal::static_int_cast<sal_uInt16>(m_xOperatorSize->get_value(FieldUnit::NONE)));
413 rFormat.SetRelSize(SIZ_LIMITS, sal::static_int_cast<sal_uInt16>(m_xBorderSize->get_value(FieldUnit::NONE)));
415 const Size aTmp (rFormat.GetBaseSize());
416 for (sal_uInt16 i = FNT_BEGIN; i <= FNT_END; i++)
417 rFormat.SetFontSize(i, aTmp);
419 rFormat.RequestApplyChanges();
422 IMPL_LINK(SmFontTypeDialog, MenuSelectHdl, const OString&, rIdent, void)
424 SmFontPickListBox *pActiveListBox;
426 bool bHideCheckboxes = false;
427 if (rIdent == "variables")
428 pActiveListBox = m_xVariableFont.get();
429 else if (rIdent == "functions")
430 pActiveListBox = m_xFunctionFont.get();
431 else if (rIdent == "numbers")
432 pActiveListBox = m_xNumberFont.get();
433 else if (rIdent == "text")
434 pActiveListBox = m_xTextFont.get();
435 else if (rIdent == "serif")
437 pActiveListBox = m_xSerifFont.get();
438 bHideCheckboxes = true;
440 else if (rIdent == "sansserif")
442 pActiveListBox = m_xSansFont.get();
443 bHideCheckboxes = true;
445 else if (rIdent == "fixedwidth")
447 pActiveListBox = m_xFixedFont.get();
448 bHideCheckboxes = true;
450 else
451 pActiveListBox = nullptr;
453 if (pActiveListBox)
455 SmFontDialog aFontDialog(m_xDialog.get(), pFontListDev, bHideCheckboxes);
457 pActiveListBox->WriteTo(aFontDialog);
458 if (aFontDialog.run() == RET_OK)
459 pActiveListBox->ReadFrom(aFontDialog);
463 IMPL_LINK_NOARG(SmFontTypeDialog, DefaultButtonClickHdl, weld::Button&, void)
465 SaveDefaultsQuery aQuery(m_xDialog.get());
466 if (aQuery.run() == RET_YES)
468 SmModule *pp = SM_MOD();
469 SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
470 WriteTo( aFmt );
471 pp->GetConfig()->SetStandardFormat( aFmt, true );
475 SmFontTypeDialog::SmFontTypeDialog(weld::Window* pParent, OutputDevice *pFntListDevice)
476 : GenericDialogController(pParent, "modules/smath/ui/fonttypedialog.ui", "FontsDialog")
477 , pFontListDev(pFntListDevice)
478 , m_xVariableFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("variableCB")))
479 , m_xFunctionFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("functionCB")))
480 , m_xNumberFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("numberCB")))
481 , m_xTextFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("textCB")))
482 , m_xSerifFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("serifCB")))
483 , m_xSansFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("sansCB")))
484 , m_xFixedFont(new SmFontPickListBox(m_xBuilder->weld_combo_box("fixedCB")))
485 , m_xMenuButton(m_xBuilder->weld_menu_button("modify"))
486 , m_xDefaultButton(m_xBuilder->weld_button("default"))
488 m_xDefaultButton->connect_clicked(LINK(this, SmFontTypeDialog, DefaultButtonClickHdl));
489 m_xMenuButton->connect_selected(LINK(this, SmFontTypeDialog, MenuSelectHdl));
492 SmFontTypeDialog::~SmFontTypeDialog()
496 void SmFontTypeDialog::ReadFrom(const SmFormat &rFormat)
498 SmModule *pp = SM_MOD();
500 *m_xVariableFont = pp->GetConfig()->GetFontPickList(FNT_VARIABLE);
501 *m_xFunctionFont = pp->GetConfig()->GetFontPickList(FNT_FUNCTION);
502 *m_xNumberFont = pp->GetConfig()->GetFontPickList(FNT_NUMBER);
503 *m_xTextFont = pp->GetConfig()->GetFontPickList(FNT_TEXT);
504 *m_xSerifFont = pp->GetConfig()->GetFontPickList(FNT_SERIF);
505 *m_xSansFont = pp->GetConfig()->GetFontPickList(FNT_SANS);
506 *m_xFixedFont = pp->GetConfig()->GetFontPickList(FNT_FIXED);
508 m_xVariableFont->Insert( rFormat.GetFont(FNT_VARIABLE) );
509 m_xFunctionFont->Insert( rFormat.GetFont(FNT_FUNCTION) );
510 m_xNumberFont->Insert( rFormat.GetFont(FNT_NUMBER) );
511 m_xTextFont->Insert( rFormat.GetFont(FNT_TEXT) );
512 m_xSerifFont->Insert( rFormat.GetFont(FNT_SERIF) );
513 m_xSansFont->Insert( rFormat.GetFont(FNT_SANS) );
514 m_xFixedFont->Insert( rFormat.GetFont(FNT_FIXED) );
518 void SmFontTypeDialog::WriteTo(SmFormat &rFormat) const
520 SmModule *pp = SM_MOD();
522 pp->GetConfig()->GetFontPickList(FNT_VARIABLE) = *m_xVariableFont;
523 pp->GetConfig()->GetFontPickList(FNT_FUNCTION) = *m_xFunctionFont;
524 pp->GetConfig()->GetFontPickList(FNT_NUMBER) = *m_xNumberFont;
525 pp->GetConfig()->GetFontPickList(FNT_TEXT) = *m_xTextFont;
526 pp->GetConfig()->GetFontPickList(FNT_SERIF) = *m_xSerifFont;
527 pp->GetConfig()->GetFontPickList(FNT_SANS) = *m_xSansFont;
528 pp->GetConfig()->GetFontPickList(FNT_FIXED) = *m_xFixedFont;
530 rFormat.SetFont( FNT_VARIABLE, m_xVariableFont->Get() );
531 rFormat.SetFont( FNT_FUNCTION, m_xFunctionFont->Get() );
532 rFormat.SetFont( FNT_NUMBER, m_xNumberFont->Get() );
533 rFormat.SetFont( FNT_TEXT, m_xTextFont->Get() );
534 rFormat.SetFont( FNT_SERIF, m_xSerifFont->Get() );
535 rFormat.SetFont( FNT_SANS, m_xSansFont->Get() );
536 rFormat.SetFont( FNT_FIXED, m_xFixedFont->Get() );
538 rFormat.RequestApplyChanges();
541 /**************************************************************************/
543 namespace {
545 struct FieldMinMax
547 sal_uInt16 nMin, nMax;
552 // Data for min and max values of the 4 metric fields
553 // for each of the 10 categories
554 const FieldMinMax pMinMaxData[10][4] =
556 // 0
557 {{ 0, 200 }, { 0, 200 }, { 0, 100 }, { 0, 0 }},
558 // 1
559 {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
560 // 2
561 {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
562 // 3
563 {{ 0, 100 }, { 1, 100 }, { 0, 0 }, { 0, 0 }},
564 // 4
565 {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
566 // 5
567 {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 100 }},
568 // 6
569 {{ 0, 300 }, { 0, 300 }, { 0, 0 }, { 0, 0 }},
570 // 7
571 {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
572 // 8
573 {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
574 // 9
575 {{ 0, 10000 }, { 0, 10000 }, { 0, 10000 }, { 0, 10000 }}
578 SmCategoryDesc::SmCategoryDesc(weld::Builder& rBuilder, sal_uInt16 nCategoryIdx)
580 ++nCategoryIdx;
581 std::unique_ptr<weld::Label> xTitle(rBuilder.weld_label(OString::number(nCategoryIdx)+"title"));
582 if (xTitle)
584 Name = xTitle->get_label();
586 for (int i = 0; i < 4; ++i)
588 std::unique_ptr<weld::Label> xLabel(rBuilder.weld_label(OString::number(nCategoryIdx)+"label"+OString::number(i+1)));
590 if (xLabel)
592 Strings[i] = xLabel->get_label();
593 Graphics[i] = rBuilder.weld_widget(OString::number(nCategoryIdx)+"image"+OString::number(i+1));
595 else
597 Strings[i].clear();
598 Graphics[i].reset();
601 const FieldMinMax& rMinMax = pMinMaxData[ nCategoryIdx-1 ][i];
602 Value[i] = Minimum[i] = rMinMax.nMin;
603 Maximum[i] = rMinMax.nMax;
607 SmCategoryDesc::~SmCategoryDesc()
611 /**************************************************************************/
613 IMPL_LINK( SmDistanceDialog, GetFocusHdl, weld::Widget&, rControl, void )
615 if (!m_xCategories[nActiveCategory])
616 return;
618 sal_uInt16 i;
620 if (&rControl == &m_xMetricField1->get_widget())
621 i = 0;
622 else if (&rControl == &m_xMetricField2->get_widget())
623 i = 1;
624 else if (&rControl == &m_xMetricField3->get_widget())
625 i = 2;
626 else if (&rControl == &m_xMetricField4->get_widget())
627 i = 3;
628 else
629 return;
630 if (m_pCurrentImage)
631 m_pCurrentImage->hide();
632 m_pCurrentImage = m_xCategories[nActiveCategory]->GetGraphic(i);
633 m_pCurrentImage->show();
636 IMPL_LINK(SmDistanceDialog, MenuSelectHdl, const OString&, rId, void)
638 assert(rId.startsWith("menuitem"));
639 SetCategory(rId.replaceFirst("menuitem", "").toInt32() - 1);
642 IMPL_LINK_NOARG( SmDistanceDialog, DefaultButtonClickHdl, weld::Button&, void )
644 SaveDefaultsQuery aQuery(m_xDialog.get());
645 if (aQuery.run() == RET_YES)
647 SmModule *pp = SM_MOD();
648 SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
649 WriteTo( aFmt );
650 pp->GetConfig()->SetStandardFormat( aFmt );
654 IMPL_LINK( SmDistanceDialog, CheckBoxClickHdl, weld::Toggleable&, rCheckBox, void )
656 if (&rCheckBox == m_xCheckBox1.get())
658 bool bChecked = m_xCheckBox1->get_active();
659 m_xFixedText4->set_sensitive( bChecked );
660 m_xMetricField4->set_sensitive( bChecked );
664 void SmDistanceDialog::SetCategory(sal_uInt16 nCategory)
666 assert(nCategory < NOCATEGORIES && "Sm: wrong category number in SmDistanceDialog");
668 // array to convert category- and metricfield-number in help ids.
669 // 0 is used in case of unused combinations.
670 assert(NOCATEGORIES == 10 && "Sm : array doesn't fit into the number of categories");
671 static const char * aCatMf2Hid[10][4] =
673 { HID_SMA_DEFAULT_DIST, HID_SMA_LINE_DIST, HID_SMA_ROOT_DIST, nullptr },
674 { HID_SMA_SUP_DIST, HID_SMA_SUB_DIST , nullptr, nullptr },
675 { HID_SMA_NUMERATOR_DIST, HID_SMA_DENOMINATOR_DIST, nullptr, nullptr },
676 { HID_SMA_FRACLINE_EXCWIDTH, HID_SMA_FRACLINE_LINEWIDTH, nullptr, nullptr },
677 { HID_SMA_UPPERLIMIT_DIST, HID_SMA_LOWERLIMIT_DIST, nullptr, nullptr },
678 { HID_SMA_BRACKET_EXCHEIGHT, HID_SMA_BRACKET_DIST, nullptr, HID_SMA_BRACKET_EXCHEIGHT2 },
679 { HID_SMA_MATRIXROW_DIST, HID_SMA_MATRIXCOL_DIST, nullptr, nullptr },
680 { HID_SMA_ATTRIBUT_DIST, HID_SMA_INTERATTRIBUT_DIST, nullptr, nullptr },
681 { HID_SMA_OPERATOR_EXCHEIGHT, HID_SMA_OPERATOR_DIST, nullptr, nullptr },
682 { HID_SMA_LEFTBORDER_DIST, HID_SMA_RIGHTBORDER_DIST, HID_SMA_UPPERBORDER_DIST, HID_SMA_LOWERBORDER_DIST }
685 // array to help iterate over the controls
686 std::pair<weld::Label*, weld::MetricSpinButton*> const aWin[4] =
688 { m_xFixedText1.get(), m_xMetricField1.get() },
689 { m_xFixedText2.get(), m_xMetricField2.get() },
690 { m_xFixedText3.get(), m_xMetricField3.get() },
691 { m_xFixedText4.get(), m_xMetricField4.get() }
694 SmCategoryDesc *pCat;
696 // remember the (maybe new) settings of the active SmCategoryDesc
697 // before switching to the new one
698 if (nActiveCategory != CATEGORY_NONE)
700 pCat = m_xCategories[nActiveCategory].get();
701 pCat->SetValue(0, sal::static_int_cast<sal_uInt16>(m_xMetricField1->get_value(FieldUnit::NONE)));
702 pCat->SetValue(1, sal::static_int_cast<sal_uInt16>(m_xMetricField2->get_value(FieldUnit::NONE)));
703 pCat->SetValue(2, sal::static_int_cast<sal_uInt16>(m_xMetricField3->get_value(FieldUnit::NONE)));
704 pCat->SetValue(3, sal::static_int_cast<sal_uInt16>(m_xMetricField4->get_value(FieldUnit::NONE)));
706 if (nActiveCategory == 5)
707 bScaleAllBrackets = m_xCheckBox1->get_active();
709 m_xMenuButton->set_item_active("menuitem" + OString::number(nActiveCategory + 1), false);
712 // activation/deactivation of the associated controls depending on the chosen category
713 bool bActive;
714 for (sal_uInt16 i = 0; i < 4; i++)
716 weld::Label *pFT = aWin[i].first;
717 weld::MetricSpinButton *pMF = aWin[i].second;
719 // To determine which Controls should be active, the existence
720 // of an associated HelpID is checked
721 bActive = aCatMf2Hid[nCategory][i] != nullptr;
723 pFT->set_visible(bActive);
724 pFT->set_sensitive(bActive);
725 pMF->set_visible(bActive);
726 pMF->set_sensitive(bActive);
728 // set measurement unit and number of decimal places
729 FieldUnit eUnit;
730 sal_uInt16 nDigits;
731 if (nCategory < 9)
733 eUnit = FieldUnit::PERCENT;
734 nDigits = 0;
736 else
738 eUnit = FieldUnit::MM_100TH;
739 nDigits = 2;
741 pMF->set_unit(eUnit); // changes the value
742 pMF->set_digits(nDigits);
744 if (bActive)
746 pCat = m_xCategories[nCategory].get();
747 pFT->set_label(pCat->GetString(i));
749 pMF->set_range(pCat->GetMinimum(i), pCat->GetMaximum(i), FieldUnit::NONE);
750 pMF->set_value(pCat->GetValue(i), FieldUnit::NONE);
752 pMF->set_help_id(aCatMf2Hid[nCategory][i]);
755 // activate the CheckBox and the associated MetricField if we're dealing with the brackets menu
756 bActive = nCategory == 5;
757 m_xCheckBox1->set_visible(bActive);
758 m_xCheckBox1->set_sensitive(bActive);
759 if (bActive)
761 m_xCheckBox1->set_active(bScaleAllBrackets);
763 bool bChecked = m_xCheckBox1->get_active();
764 m_xFixedText4->set_sensitive( bChecked );
765 m_xMetricField4->set_sensitive( bChecked );
768 m_xMenuButton->set_item_active("menuitem" + OString::number(nCategory + 1), true);
769 m_xFrame->set_label(m_xCategories[nCategory]->GetName());
771 nActiveCategory = nCategory;
773 m_xMetricField1->grab_focus();
776 SmDistanceDialog::SmDistanceDialog(weld::Window *pParent)
777 : GenericDialogController(pParent, "modules/smath/ui/spacingdialog.ui", "SpacingDialog")
778 , m_xFrame(m_xBuilder->weld_frame("template"))
779 , m_xFixedText1(m_xBuilder->weld_label("label1"))
780 , m_xMetricField1(m_xBuilder->weld_metric_spin_button("spinbutton1", FieldUnit::CM))
781 , m_xFixedText2(m_xBuilder->weld_label("label2"))
782 , m_xMetricField2(m_xBuilder->weld_metric_spin_button("spinbutton2", FieldUnit::CM))
783 , m_xFixedText3(m_xBuilder->weld_label("label3"))
784 , m_xMetricField3(m_xBuilder->weld_metric_spin_button("spinbutton3", FieldUnit::CM))
785 , m_xCheckBox1(m_xBuilder->weld_check_button("checkbutton"))
786 , m_xFixedText4(m_xBuilder->weld_label("label4"))
787 , m_xMetricField4(m_xBuilder->weld_metric_spin_button("spinbutton4", FieldUnit::CM))
788 , m_xMenuButton(m_xBuilder->weld_menu_button("category"))
789 , m_xDefaultButton(m_xBuilder->weld_button("default"))
790 , m_xBitmap(m_xBuilder->weld_widget("image"))
791 , m_pCurrentImage(m_xBitmap.get())
793 for (sal_uInt16 i = 0; i < NOCATEGORIES; ++i)
794 m_xCategories[i].reset( new SmCategoryDesc(*m_xBuilder, i) );
795 nActiveCategory = CATEGORY_NONE;
796 bScaleAllBrackets = false;
798 m_xMetricField1->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
799 m_xMetricField2->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
800 m_xMetricField3->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
801 m_xMetricField4->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
802 m_xCheckBox1->connect_toggled(LINK(this, SmDistanceDialog, CheckBoxClickHdl));
803 m_xMenuButton->connect_selected(LINK(this, SmDistanceDialog, MenuSelectHdl));
804 m_xDefaultButton->connect_clicked(LINK(this, SmDistanceDialog, DefaultButtonClickHdl));
806 //set the initial size, with max visible widgets visible, as preferred size
807 m_xDialog->set_size_request(-1, m_xDialog->get_preferred_size().Height());
810 SmDistanceDialog::~SmDistanceDialog()
814 void SmDistanceDialog::ReadFrom(const SmFormat &rFormat)
816 m_xCategories[0]->SetValue(0, rFormat.GetDistance(DIS_HORIZONTAL));
817 m_xCategories[0]->SetValue(1, rFormat.GetDistance(DIS_VERTICAL));
818 m_xCategories[0]->SetValue(2, rFormat.GetDistance(DIS_ROOT));
819 m_xCategories[1]->SetValue(0, rFormat.GetDistance(DIS_SUPERSCRIPT));
820 m_xCategories[1]->SetValue(1, rFormat.GetDistance(DIS_SUBSCRIPT));
821 m_xCategories[2]->SetValue(0, rFormat.GetDistance(DIS_NUMERATOR));
822 m_xCategories[2]->SetValue(1, rFormat.GetDistance(DIS_DENOMINATOR));
823 m_xCategories[3]->SetValue(0, rFormat.GetDistance(DIS_FRACTION));
824 m_xCategories[3]->SetValue(1, rFormat.GetDistance(DIS_STROKEWIDTH));
825 m_xCategories[4]->SetValue(0, rFormat.GetDistance(DIS_UPPERLIMIT));
826 m_xCategories[4]->SetValue(1, rFormat.GetDistance(DIS_LOWERLIMIT));
827 m_xCategories[5]->SetValue(0, rFormat.GetDistance(DIS_BRACKETSIZE));
828 m_xCategories[5]->SetValue(1, rFormat.GetDistance(DIS_BRACKETSPACE));
829 m_xCategories[5]->SetValue(3, rFormat.GetDistance(DIS_NORMALBRACKETSIZE));
830 m_xCategories[6]->SetValue(0, rFormat.GetDistance(DIS_MATRIXROW));
831 m_xCategories[6]->SetValue(1, rFormat.GetDistance(DIS_MATRIXCOL));
832 m_xCategories[7]->SetValue(0, rFormat.GetDistance(DIS_ORNAMENTSIZE));
833 m_xCategories[7]->SetValue(1, rFormat.GetDistance(DIS_ORNAMENTSPACE));
834 m_xCategories[8]->SetValue(0, rFormat.GetDistance(DIS_OPERATORSIZE));
835 m_xCategories[8]->SetValue(1, rFormat.GetDistance(DIS_OPERATORSPACE));
836 m_xCategories[9]->SetValue(0, rFormat.GetDistance(DIS_LEFTSPACE));
837 m_xCategories[9]->SetValue(1, rFormat.GetDistance(DIS_RIGHTSPACE));
838 m_xCategories[9]->SetValue(2, rFormat.GetDistance(DIS_TOPSPACE));
839 m_xCategories[9]->SetValue(3, rFormat.GetDistance(DIS_BOTTOMSPACE));
841 bScaleAllBrackets = rFormat.IsScaleNormalBrackets();
843 // force update (even of category 0) by setting nActiveCategory to a
844 // non-existent category number
845 nActiveCategory = CATEGORY_NONE;
846 SetCategory(0);
850 void SmDistanceDialog::WriteTo(SmFormat &rFormat) /*const*/
852 // TODO can they actually be different?
853 // if that's not the case 'const' could be used above!
854 SetCategory(nActiveCategory);
856 rFormat.SetDistance( DIS_HORIZONTAL, m_xCategories[0]->GetValue(0) );
857 rFormat.SetDistance( DIS_VERTICAL, m_xCategories[0]->GetValue(1) );
858 rFormat.SetDistance( DIS_ROOT, m_xCategories[0]->GetValue(2) );
859 rFormat.SetDistance( DIS_SUPERSCRIPT, m_xCategories[1]->GetValue(0) );
860 rFormat.SetDistance( DIS_SUBSCRIPT, m_xCategories[1]->GetValue(1) );
861 rFormat.SetDistance( DIS_NUMERATOR, m_xCategories[2]->GetValue(0) );
862 rFormat.SetDistance( DIS_DENOMINATOR, m_xCategories[2]->GetValue(1) );
863 rFormat.SetDistance( DIS_FRACTION, m_xCategories[3]->GetValue(0) );
864 rFormat.SetDistance( DIS_STROKEWIDTH, m_xCategories[3]->GetValue(1) );
865 rFormat.SetDistance( DIS_UPPERLIMIT, m_xCategories[4]->GetValue(0) );
866 rFormat.SetDistance( DIS_LOWERLIMIT, m_xCategories[4]->GetValue(1) );
867 rFormat.SetDistance( DIS_BRACKETSIZE, m_xCategories[5]->GetValue(0) );
868 rFormat.SetDistance( DIS_BRACKETSPACE, m_xCategories[5]->GetValue(1) );
869 rFormat.SetDistance( DIS_MATRIXROW, m_xCategories[6]->GetValue(0) );
870 rFormat.SetDistance( DIS_MATRIXCOL, m_xCategories[6]->GetValue(1) );
871 rFormat.SetDistance( DIS_ORNAMENTSIZE, m_xCategories[7]->GetValue(0) );
872 rFormat.SetDistance( DIS_ORNAMENTSPACE, m_xCategories[7]->GetValue(1) );
873 rFormat.SetDistance( DIS_OPERATORSIZE, m_xCategories[8]->GetValue(0) );
874 rFormat.SetDistance( DIS_OPERATORSPACE, m_xCategories[8]->GetValue(1) );
875 rFormat.SetDistance( DIS_LEFTSPACE, m_xCategories[9]->GetValue(0) );
876 rFormat.SetDistance( DIS_RIGHTSPACE, m_xCategories[9]->GetValue(1) );
877 rFormat.SetDistance( DIS_TOPSPACE, m_xCategories[9]->GetValue(2) );
878 rFormat.SetDistance( DIS_BOTTOMSPACE, m_xCategories[9]->GetValue(3) );
879 rFormat.SetDistance( DIS_NORMALBRACKETSIZE, m_xCategories[5]->GetValue(3) );
881 rFormat.SetScaleNormalBrackets( bScaleAllBrackets );
883 rFormat.RequestApplyChanges();
886 IMPL_LINK_NOARG( SmAlignDialog, DefaultButtonClickHdl, weld::Button&, void )
888 SaveDefaultsQuery aQuery(m_xDialog.get());
889 if (aQuery.run() == RET_YES)
891 SmModule *pp = SM_MOD();
892 SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
893 WriteTo( aFmt );
894 pp->GetConfig()->SetStandardFormat( aFmt );
898 SmAlignDialog::SmAlignDialog(weld::Window* pParent)
899 : GenericDialogController(pParent, "modules/smath/ui/alignmentdialog.ui", "AlignmentDialog")
900 , m_xLeft(m_xBuilder->weld_radio_button("left"))
901 , m_xCenter(m_xBuilder->weld_radio_button("center"))
902 , m_xRight(m_xBuilder->weld_radio_button("right"))
903 , m_xDefaultButton(m_xBuilder->weld_button("default"))
905 m_xDefaultButton->connect_clicked(LINK(this, SmAlignDialog, DefaultButtonClickHdl));
908 SmAlignDialog::~SmAlignDialog()
912 void SmAlignDialog::ReadFrom(const SmFormat &rFormat)
914 switch (rFormat.GetHorAlign())
916 case SmHorAlign::Left:
917 m_xLeft->set_active(true);
918 break;
919 case SmHorAlign::Center:
920 m_xCenter->set_active(true);
921 break;
922 case SmHorAlign::Right:
923 m_xRight->set_active(true);
924 break;
928 void SmAlignDialog::WriteTo(SmFormat &rFormat) const
930 if (m_xLeft->get_active())
931 rFormat.SetHorAlign(SmHorAlign::Left);
932 else if (m_xRight->get_active())
933 rFormat.SetHorAlign(SmHorAlign::Right);
934 else
935 rFormat.SetHorAlign(SmHorAlign::Center);
937 rFormat.RequestApplyChanges();
940 SmShowSymbolSet::SmShowSymbolSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow)
941 : nLen(0)
942 , nRows(0)
943 , nColumns(0)
944 , nXOffset(0)
945 , nYOffset(0)
946 , nSelectSymbol(SYMBOL_NONE)
947 , m_xScrolledWindow(std::move(pScrolledWindow))
949 m_xScrolledWindow->connect_vadjustment_changed(LINK(this, SmShowSymbolSet, ScrollHdl));
952 Point SmShowSymbolSet::OffsetPoint(const Point &rPoint) const
954 return Point(rPoint.X() + nXOffset, rPoint.Y() + nYOffset);
957 void SmShowSymbolSet::Resize()
959 CustomWidgetController::Resize();
960 Size aWinSize(GetOutputSizePixel());
961 if (aWinSize != m_aOldSize)
963 calccols(GetDrawingArea()->get_ref_device());
964 m_aOldSize = aWinSize;
968 void SmShowSymbolSet::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
970 Color aBackgroundColor;
971 Color aTextColor;
972 lclGetSettingColors(aBackgroundColor, aTextColor);
974 rRenderContext.SetBackground(Wallpaper(aBackgroundColor));
975 rRenderContext.SetTextColor(aTextColor);
977 rRenderContext.Push(vcl::PushFlags::MAPMODE);
979 // set MapUnit for which 'nLen' has been calculated
980 rRenderContext.SetMapMode(MapMode(MapUnit::MapPixel));
982 sal_uInt16 v = sal::static_int_cast< sal_uInt16 >(m_xScrolledWindow->vadjustment_get_value() * nColumns);
983 size_t nSymbols = aSymbolSet.size();
985 Color aTxtColor(rRenderContext.GetTextColor());
986 for (size_t i = v; i < nSymbols ; i++)
988 SmSym aSymbol(*aSymbolSet[i]);
989 vcl::Font aFont(aSymbol.GetFace());
990 aFont.SetAlignment(ALIGN_TOP);
992 // taking a FontSize which is a bit smaller (compared to nLen) in order to have a buffer
993 // (hopefully enough for left and right, too)
994 aFont.SetFontSize(Size(0, nLen - (nLen / 3)));
995 rRenderContext.SetFont(aFont);
996 // keep text color
997 rRenderContext.SetTextColor(aTxtColor);
999 int nIV = i - v;
1000 sal_UCS4 cChar = aSymbol.GetCharacter();
1001 OUString aText(&cChar, 1);
1002 Size aSize(rRenderContext.GetTextWidth( aText ), rRenderContext.GetTextHeight());
1004 Point aPoint((nIV % nColumns) * nLen + (nLen - aSize.Width()) / 2,
1005 (nIV / nColumns) * nLen + (nLen - aSize.Height()) / 2);
1007 rRenderContext.DrawText(OffsetPoint(aPoint), aText);
1010 if (nSelectSymbol != SYMBOL_NONE)
1012 Point aPoint(((nSelectSymbol - v) % nColumns) * nLen,
1013 ((nSelectSymbol - v) / nColumns) * nLen);
1015 rRenderContext.Invert(tools::Rectangle(OffsetPoint(aPoint), Size(nLen, nLen)));
1019 rRenderContext.Pop();
1022 bool SmShowSymbolSet::MouseButtonDown(const MouseEvent& rMEvt)
1024 GrabFocus();
1026 Size aOutputSize(nColumns * nLen, nRows * nLen);
1027 aOutputSize.AdjustWidth(nXOffset );
1028 aOutputSize.AdjustHeight(nYOffset );
1029 Point aPoint(rMEvt.GetPosPixel());
1030 aPoint.AdjustX( -nXOffset );
1031 aPoint.AdjustY( -nYOffset );
1033 if (rMEvt.IsLeft() && tools::Rectangle(Point(0, 0), aOutputSize).Contains(rMEvt.GetPosPixel()))
1035 tools::Long nPos = (aPoint.Y() / nLen) * nColumns + (aPoint.X() / nLen) +
1036 m_xScrolledWindow->vadjustment_get_value() * nColumns;
1037 SelectSymbol( sal::static_int_cast< sal_uInt16 >(nPos) );
1039 aSelectHdlLink.Call(*this);
1041 if (rMEvt.GetClicks() > 1)
1042 aDblClickHdlLink.Call(*this);
1045 return true;
1048 bool SmShowSymbolSet::KeyInput(const KeyEvent& rKEvt)
1050 sal_uInt16 n = nSelectSymbol;
1052 if (n != SYMBOL_NONE)
1054 switch (rKEvt.GetKeyCode().GetCode())
1056 case KEY_DOWN: n = n + nColumns; break;
1057 case KEY_UP: n = n - nColumns; break;
1058 case KEY_LEFT: n -= 1; break;
1059 case KEY_RIGHT: n += 1; break;
1060 case KEY_HOME: n = 0; break;
1061 case KEY_END: n = static_cast< sal_uInt16 >(aSymbolSet.size() - 1); break;
1062 case KEY_PAGEUP: n -= nColumns * nRows; break;
1063 case KEY_PAGEDOWN: n += nColumns * nRows; break;
1064 default:
1065 return false;
1068 else
1069 n = 0;
1071 if (n >= aSymbolSet.size())
1072 n = nSelectSymbol;
1074 // adjust scrollbar
1075 if ((n < sal::static_int_cast<sal_uInt16>(m_xScrolledWindow->vadjustment_get_value() * nColumns)) ||
1076 (n >= sal::static_int_cast<sal_uInt16>((m_xScrolledWindow->vadjustment_get_value() + nRows) * nColumns)))
1078 m_xScrolledWindow->vadjustment_set_value(n / nColumns);
1079 Invalidate();
1082 SelectSymbol(n);
1083 aSelectHdlLink.Call(*this);
1085 return true;
1088 void SmShowSymbolSet::calccols(const vcl::RenderContext& rRenderContext)
1090 // Height of 16pt in pixels (matching 'aOutputSize')
1091 nLen = rRenderContext.LogicToPixel(Size(0, 16), MapMode(MapUnit::MapPoint)).Height();
1093 Size aOutputSize(GetOutputSizePixel());
1095 nColumns = aOutputSize.Width() / nLen;
1096 nRows = aOutputSize.Height() / nLen;
1097 nColumns = std::max<tools::Long>(1, nColumns);
1098 nRows = std::max<tools::Long>(1, nRows);
1100 nXOffset = (aOutputSize.Width() - (nColumns * nLen)) / 2;
1101 nYOffset = (aOutputSize.Height() - (nRows * nLen)) / 2;
1103 SetScrollBarRange();
1106 void SmShowSymbolSet::SetSymbolSet(const SymbolPtrVec_t & rSymbolSet)
1108 aSymbolSet = rSymbolSet;
1109 SetScrollBarRange();
1110 Invalidate();
1113 void SmShowSymbolSet::SetScrollBarRange()
1115 const int nLastRow = (aSymbolSet.size() - 1 + nColumns) / nColumns;
1116 m_xScrolledWindow->vadjustment_configure(m_xScrolledWindow->vadjustment_get_value(), 0, nLastRow, 1, nRows - 1, nRows);
1117 Invalidate();
1120 void SmShowSymbolSet::SelectSymbol(sal_uInt16 nSymbol)
1122 int v = m_xScrolledWindow->vadjustment_get_value() * nColumns;
1124 if (nSelectSymbol != SYMBOL_NONE && nColumns)
1126 Point aPoint(OffsetPoint(Point(((nSelectSymbol - v) % nColumns) * nLen,
1127 ((nSelectSymbol - v) / nColumns) * nLen)));
1128 Invalidate(tools::Rectangle(aPoint, Size(nLen, nLen)));
1131 if (nSymbol < aSymbolSet.size())
1132 nSelectSymbol = nSymbol;
1134 if (aSymbolSet.empty())
1135 nSelectSymbol = SYMBOL_NONE;
1137 if (nSelectSymbol != SYMBOL_NONE && nColumns)
1139 Point aPoint(OffsetPoint(Point(((nSelectSymbol - v) % nColumns) * nLen,
1140 ((nSelectSymbol - v) / nColumns) * nLen)));
1141 Invalidate(tools::Rectangle(aPoint, Size(nLen, nLen)));
1144 if (!nColumns)
1145 Invalidate();
1148 IMPL_LINK_NOARG(SmShowSymbolSet, ScrollHdl, weld::ScrolledWindow&, void)
1150 Invalidate();
1153 SmShowSymbol::SmShowSymbol()
1157 void SmShowSymbol::setFontSize(vcl::Font &rFont) const
1159 Size aSize(GetOutputSizePixel());
1160 rFont.SetFontSize(Size(0, aSize.Height() - aSize.Height() / 3));
1163 void SmShowSymbol::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
1165 Color aBackgroundColor;
1166 Color aTextColor;
1167 lclGetSettingColors(aBackgroundColor, aTextColor);
1168 rRenderContext.SetBackground(Wallpaper(aBackgroundColor));
1169 rRenderContext.SetTextColor(aTextColor);
1170 rRenderContext.Erase();
1172 vcl::Font aFont(GetFont());
1173 setFontSize(aFont);
1174 rRenderContext.SetFont(aFont);
1176 const OUString &rText = GetText();
1177 Size aTextSize(rRenderContext.GetTextWidth(rText), rRenderContext.GetTextHeight());
1179 rRenderContext.DrawText(Point((rRenderContext.GetOutputSize().Width() - aTextSize.Width()) / 2,
1180 (rRenderContext.GetOutputSize().Height() * 7 / 10)), rText);
1183 bool SmShowSymbol::MouseButtonDown(const MouseEvent& rMEvt)
1185 if (rMEvt.GetClicks() > 1)
1186 aDblClickHdlLink.Call(*this);
1187 return true;
1190 void SmShowSymbol::SetSymbol(const SmSym *pSymbol)
1192 if (pSymbol)
1194 vcl::Font aFont(pSymbol->GetFace());
1195 aFont.SetAlignment(ALIGN_BASELINE);
1196 SetFont(aFont);
1198 sal_UCS4 cChar = pSymbol->GetCharacter();
1199 OUString aText(&cChar, 1);
1200 SetText( aText );
1203 Invalidate();
1206 void SmSymbolDialog::FillSymbolSets()
1207 // populate the entries of possible SymbolsSets in the dialog with
1208 // current values of the SymbolSet manager but selects none of those
1210 m_xSymbolSets->clear();
1211 m_xSymbolSets->set_active(-1);
1213 std::set< OUString > aSymbolSetNames( rSymbolMgr.GetSymbolSetNames() );
1214 for (const auto& rSymbolSetName : aSymbolSetNames)
1215 m_xSymbolSets->append_text(rSymbolSetName);
1218 IMPL_LINK_NOARG( SmSymbolDialog, SymbolSetChangeHdl, weld::ComboBox&, void )
1220 SelectSymbolSet(m_xSymbolSets->get_active_text());
1223 IMPL_LINK_NOARG( SmSymbolDialog, SymbolChangeHdl, SmShowSymbolSet&, void )
1225 SelectSymbol(m_xSymbolSetDisplay->GetSelectSymbol());
1228 IMPL_LINK_NOARG(SmSymbolDialog, EditClickHdl, weld::Button&, void)
1230 SmSymDefineDialog aDialog(m_xDialog.get(), pFontListDev, rSymbolMgr);
1232 // set current symbol and SymbolSet for the new dialog
1233 const OUString aSymSetName (m_xSymbolSets->get_active_text()),
1234 aSymName (m_xSymbolName->get_label());
1235 aDialog.SelectOldSymbolSet(aSymSetName);
1236 aDialog.SelectOldSymbol(aSymName);
1237 aDialog.SelectSymbolSet(aSymSetName);
1238 aDialog.SelectSymbol(aSymName);
1240 // remember old SymbolSet
1241 OUString aOldSymbolSet (m_xSymbolSets->get_active_text());
1243 sal_uInt16 nSymPos = m_xSymbolSetDisplay->GetSelectSymbol();
1245 // adapt dialog to data of the SymbolSet manager, which might have changed
1246 if (aDialog.run() == RET_OK && rSymbolMgr.IsModified())
1248 rSymbolMgr.Save();
1249 FillSymbolSets();
1252 // if the old SymbolSet doesn't exist anymore, go to the first one SymbolSet (if one exists)
1253 if (!SelectSymbolSet(aOldSymbolSet) && m_xSymbolSets->get_count() > 0)
1254 SelectSymbolSet(m_xSymbolSets->get_text(0));
1255 else
1257 // just update display of current symbol set
1258 assert(aSymSetName == aSymSetName); //unexpected change in symbol set name
1259 aSymbolSet = rSymbolMgr.GetSymbolSet( aSymbolSetName );
1260 m_xSymbolSetDisplay->SetSymbolSet( aSymbolSet );
1263 if (nSymPos >= aSymbolSet.size())
1264 nSymPos = static_cast< sal_uInt16 >(aSymbolSet.size()) - 1;
1265 SelectSymbol( nSymPos );
1268 IMPL_LINK_NOARG( SmSymbolDialog, SymbolDblClickHdl2, SmShowSymbolSet&, void )
1270 SymbolDblClickHdl();
1273 IMPL_LINK_NOARG( SmSymbolDialog, SymbolDblClickHdl, SmShowSymbol&, void )
1275 SymbolDblClickHdl();
1278 void SmSymbolDialog::SymbolDblClickHdl()
1280 GetClickHdl(*m_xGetBtn);
1281 m_xDialog->response(RET_OK);
1284 IMPL_LINK_NOARG(SmSymbolDialog, GetClickHdl, weld::Button&, void)
1286 const SmSym *pSym = GetSymbol();
1287 if (pSym)
1289 OUString aText = "%" + pSym->GetName() + " ";
1291 rViewSh.GetViewFrame()->GetDispatcher()->ExecuteList(
1292 SID_INSERTSPECIAL, SfxCallMode::RECORD,
1293 { new SfxStringItem(SID_INSERTSPECIAL, aText) });
1297 SmSymbolDialog::SmSymbolDialog(weld::Window *pParent, OutputDevice *pFntListDevice,
1298 SmSymbolManager &rMgr, SmViewShell &rViewShell)
1299 : GenericDialogController(pParent, "modules/smath/ui/catalogdialog.ui", "CatalogDialog")
1300 , rViewSh(rViewShell)
1301 , rSymbolMgr(rMgr)
1302 , pFontListDev(pFntListDevice)
1303 , m_xSymbolSets(m_xBuilder->weld_combo_box("symbolset"))
1304 , m_xSymbolSetDisplay(new SmShowSymbolSet(m_xBuilder->weld_scrolled_window("scrolledwindow", true)))
1305 , m_xSymbolSetDisplayArea(new weld::CustomWeld(*m_xBuilder, "symbolsetdisplay", *m_xSymbolSetDisplay))
1306 , m_xSymbolName(m_xBuilder->weld_label("symbolname"))
1307 , m_xSymbolDisplay(new weld::CustomWeld(*m_xBuilder, "preview", m_aSymbolDisplay))
1308 , m_xGetBtn(m_xBuilder->weld_button("ok"))
1309 , m_xEditBtn(m_xBuilder->weld_button("edit"))
1311 m_xSymbolSets->make_sorted();
1313 aSymbolSetName.clear();
1314 aSymbolSet.clear();
1315 FillSymbolSets();
1316 if (m_xSymbolSets->get_count() > 0)
1317 SelectSymbolSet(m_xSymbolSets->get_text(0));
1319 m_xSymbolSets->connect_changed(LINK(this, SmSymbolDialog, SymbolSetChangeHdl));
1320 m_xSymbolSetDisplay->SetSelectHdl(LINK(this, SmSymbolDialog, SymbolChangeHdl));
1321 m_xSymbolSetDisplay->SetDblClickHdl(LINK(this, SmSymbolDialog, SymbolDblClickHdl2));
1322 m_aSymbolDisplay.SetDblClickHdl(LINK(this, SmSymbolDialog, SymbolDblClickHdl));
1323 m_xEditBtn->connect_clicked(LINK(this, SmSymbolDialog, EditClickHdl));
1324 m_xGetBtn->connect_clicked(LINK(this, SmSymbolDialog, GetClickHdl));
1327 SmSymbolDialog::~SmSymbolDialog()
1331 bool SmSymbolDialog::SelectSymbolSet(const OUString &rSymbolSetName)
1333 bool bRet = false;
1334 sal_Int32 nPos = m_xSymbolSets->find_text(rSymbolSetName);
1336 aSymbolSetName.clear();
1337 aSymbolSet.clear();
1338 if (nPos != -1)
1340 m_xSymbolSets->set_active(nPos);
1342 aSymbolSetName = rSymbolSetName;
1343 aSymbolSet = rSymbolMgr.GetSymbolSet( aSymbolSetName );
1345 // sort symbols by Unicode position (useful for displaying Greek characters alphabetically)
1346 std::sort( aSymbolSet.begin(), aSymbolSet.end(),
1347 [](const SmSym *pSym1, const SmSym *pSym2)
1349 return pSym1->GetCharacter() < pSym2->GetCharacter();
1350 } );
1352 const bool bEmptySymbolSet = aSymbolSet.empty();
1353 m_xSymbolSetDisplay->SetSymbolSet( aSymbolSet );
1354 if (!bEmptySymbolSet)
1355 SelectSymbol(0);
1357 bRet = true;
1359 else
1360 m_xSymbolSets->set_active(-1);
1362 return bRet;
1365 void SmSymbolDialog::SelectSymbol(sal_uInt16 nSymbolNo)
1367 const SmSym *pSym = nullptr;
1368 if (!aSymbolSetName.isEmpty() && nSymbolNo < static_cast< sal_uInt16 >(aSymbolSet.size()))
1369 pSym = aSymbolSet[ nSymbolNo ];
1371 m_xSymbolSetDisplay->SelectSymbol(nSymbolNo);
1372 m_aSymbolDisplay.SetSymbol(pSym);
1373 m_xSymbolName->set_label(pSym ? pSym->GetName() : OUString());
1376 const SmSym* SmSymbolDialog::GetSymbol() const
1378 sal_uInt16 nSymbolNo = m_xSymbolSetDisplay->GetSelectSymbol();
1379 bool bValid = !aSymbolSetName.isEmpty() && nSymbolNo < static_cast< sal_uInt16 >(aSymbolSet.size());
1380 return bValid ? aSymbolSet[ nSymbolNo ] : nullptr;
1383 void SmShowChar::Resize()
1385 const OUString &rText = GetText();
1386 if (rText.isEmpty())
1387 return;
1388 sal_UCS4 cChar = rText.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
1389 SetSymbol(cChar, GetFont()); //force recalculation of size
1392 void SmShowChar::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
1394 Color aTextCol = rRenderContext.GetTextColor();
1395 Color aFillCol = rRenderContext.GetFillColor();
1397 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1398 const Color aWindowTextColor(rStyleSettings.GetDialogTextColor());
1399 const Color aWindowColor(rStyleSettings.GetWindowColor());
1400 rRenderContext.SetTextColor(aWindowTextColor);
1401 rRenderContext.SetFillColor(aWindowColor);
1403 Size aSize(GetOutputSizePixel());
1404 rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize));
1406 OUString aText(GetText());
1407 if (!aText.isEmpty())
1409 vcl::Font aFont(m_aFont);
1410 aFont.SetAlignment(ALIGN_TOP);
1411 rRenderContext.SetFont(aFont);
1413 Size aTextSize(rRenderContext.GetTextWidth(aText), rRenderContext.GetTextHeight());
1415 rRenderContext.DrawText(Point((aSize.Width() - aTextSize.Width()) / 2,
1416 (aSize.Height() - aTextSize.Height()) / 2), aText);
1419 rRenderContext.SetTextColor(aTextCol);
1420 rRenderContext.SetFillColor(aFillCol);
1423 void SmShowChar::SetSymbol( const SmSym *pSym )
1425 if (pSym)
1426 SetSymbol( pSym->GetCharacter(), pSym->GetFace() );
1430 void SmShowChar::SetSymbol( sal_UCS4 cChar, const vcl::Font &rFont )
1432 vcl::Font aFont( rFont );
1433 Size aSize(GetOutputSizePixel());
1434 aFont.SetFontSize(Size(0, aSize.Height() - aSize.Height() / 3));
1435 aFont.SetAlignment(ALIGN_BASELINE);
1436 SetFont(aFont);
1438 OUString aText(&cChar, 1);
1439 SetText( aText );
1441 Invalidate();
1444 void SmSymDefineDialog::FillSymbols(weld::ComboBox& rComboBox, bool bDeleteText)
1446 assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong ComboBox");
1448 rComboBox.clear();
1449 if (bDeleteText)
1450 rComboBox.set_entry_text(OUString());
1452 weld::ComboBox& rBox = &rComboBox == m_xOldSymbols.get() ? *m_xOldSymbolSets : *m_xSymbolSets;
1453 SymbolPtrVec_t aSymSet(m_aSymbolMgrCopy.GetSymbolSet(rBox.get_active_text()));
1454 for (const SmSym* i : aSymSet)
1455 rComboBox.append_text(i->GetName());
1458 void SmSymDefineDialog::FillSymbolSets(weld::ComboBox& rComboBox, bool bDeleteText)
1460 assert((&rComboBox == m_xOldSymbolSets.get() || &rComboBox == m_xSymbolSets.get()) && "Sm : wrong ComboBox");
1462 rComboBox.clear();
1463 if (bDeleteText)
1464 rComboBox.set_entry_text(OUString());
1466 const std::set< OUString > aSymbolSetNames( m_aSymbolMgrCopy.GetSymbolSetNames() );
1467 for (const auto& rSymbolSetName : aSymbolSetNames)
1468 rComboBox.append_text(rSymbolSetName);
1471 void SmSymDefineDialog::FillFonts()
1473 m_xFonts->clear();
1474 m_xFonts->set_active(-1);
1476 // Include all fonts of FontList into the font list.
1477 // If there are duplicates, only include one entry of each font since the style will be
1478 // already selected using the FontStyleBox.
1479 if (m_xFontList)
1481 sal_uInt16 nCount = m_xFontList->GetFontNameCount();
1482 for (sal_uInt16 i = 0; i < nCount; ++i)
1483 m_xFonts->append_text(m_xFontList->GetFontName(i).GetFamilyName());
1487 void SmSymDefineDialog::FillStyles()
1489 m_xStyles->clear();
1490 // pStyles->SetText(OUString());
1492 OUString aText(m_xFonts->get_active_text());
1493 if (!aText.isEmpty())
1495 // use own StyleNames
1496 const SmFontStyles &rStyles = GetFontStyles();
1497 for (sal_uInt16 i = 0; i < SmFontStyles::GetCount(); ++i)
1498 m_xStyles->append_text(rStyles.GetStyleName(i));
1500 assert(m_xStyles->get_count() > 0 && "Sm : no styles available");
1501 m_xStyles->set_active(0);
1505 SmSym* SmSymDefineDialog::GetSymbol(const weld::ComboBox& rComboBox)
1507 assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong combobox");
1508 return m_aSymbolMgrCopy.GetSymbolByName(rComboBox.get_active_text());
1511 IMPL_LINK(SmSymDefineDialog, OldSymbolChangeHdl, weld::ComboBox&, rComboBox, void)
1513 (void) rComboBox;
1514 assert(&rComboBox == m_xOldSymbols.get() && "Sm : wrong argument");
1515 SelectSymbol(*m_xOldSymbols, m_xOldSymbols->get_active_text(), false);
1518 IMPL_LINK( SmSymDefineDialog, OldSymbolSetChangeHdl, weld::ComboBox&, rComboBox, void )
1520 (void) rComboBox;
1521 assert(&rComboBox == m_xOldSymbolSets.get() && "Sm : wrong argument");
1522 SelectSymbolSet(*m_xOldSymbolSets, m_xOldSymbolSets->get_active_text(), false);
1525 IMPL_LINK(SmSymDefineDialog, ModifyHdl, weld::ComboBox&, rComboBox, void)
1527 // remember cursor position for later restoring of it
1528 int nStartPos, nEndPos;
1529 rComboBox.get_entry_selection_bounds(nStartPos, nEndPos);
1531 if (&rComboBox == m_xSymbols.get())
1532 SelectSymbol(*m_xSymbols, m_xSymbols->get_active_text(), false);
1533 else if (&rComboBox == m_xSymbolSets.get())
1534 SelectSymbolSet(*m_xSymbolSets, m_xSymbolSets->get_active_text(), false);
1535 else if (&rComboBox == m_xOldSymbols.get())
1536 // allow only names from the list
1537 SelectSymbol(*m_xOldSymbols, m_xOldSymbols->get_active_text(), true);
1538 else if (&rComboBox == m_xOldSymbolSets.get())
1539 // allow only names from the list
1540 SelectSymbolSet(*m_xOldSymbolSets, m_xOldSymbolSets->get_active_text(), true);
1541 else if (&rComboBox == m_xStyles.get())
1542 // allow only names from the list (that's the case here anyway)
1543 SelectStyle(m_xStyles->get_active_text(), true);
1544 else
1545 SAL_WARN("starmath", "wrong combobox argument");
1547 rComboBox.select_entry_region(nStartPos, nEndPos);
1549 UpdateButtons();
1552 IMPL_LINK(SmSymDefineDialog, FontChangeHdl, weld::ComboBox&, rListBox, void)
1554 (void) rListBox;
1555 assert(&rListBox == m_xFonts.get() && "Sm : wrong argument");
1557 SelectFont(m_xFonts->get_active_text());
1560 IMPL_LINK_NOARG(SmSymDefineDialog, SubsetChangeHdl, weld::ComboBox&, void)
1562 int nPos = m_xFontsSubsetLB->get_active();
1563 if (nPos != -1)
1565 const Subset* pSubset = weld::fromId<const Subset*>(m_xFontsSubsetLB->get_active_id());
1566 if (pSubset)
1568 m_xCharsetDisplay->SelectCharacter( pSubset->GetRangeMin() );
1573 IMPL_LINK( SmSymDefineDialog, StyleChangeHdl, weld::ComboBox&, rComboBox, void )
1575 (void) rComboBox;
1576 assert(&rComboBox == m_xStyles.get() && "Sm : wrong argument");
1578 SelectStyle(m_xStyles->get_active_text());
1581 IMPL_LINK_NOARG(SmSymDefineDialog, CharHighlightHdl, SvxShowCharSet*, void)
1583 sal_UCS4 cChar = m_xCharsetDisplay->GetSelectCharacter();
1585 if (m_xSubsetMap)
1587 const Subset* pSubset = m_xSubsetMap->GetSubsetByUnicode(cChar);
1588 if (pSubset)
1589 m_xFontsSubsetLB->set_active_text(pSubset->GetName());
1590 else
1591 m_xFontsSubsetLB->set_active(-1);
1594 m_aSymbolDisplay.SetSymbol(cChar, m_xCharsetDisplay->GetFont());
1596 UpdateButtons();
1598 // display Unicode position as symbol name while iterating over characters
1599 const OUString aHex(OUString::number(cChar, 16).toAsciiUpperCase());
1600 const OUString aPattern( (aHex.getLength() > 4) ? OUString("Ux000000") : OUString("Ux0000") );
1601 OUString aUnicodePos = aPattern.subView( 0, aPattern.getLength() - aHex.getLength() ) +
1602 aHex;
1603 m_xSymbols->set_entry_text(aUnicodePos);
1604 m_xSymbolName->set_label(aUnicodePos);
1607 IMPL_LINK( SmSymDefineDialog, AddClickHdl, weld::Button&, rButton, void )
1609 (void) rButton;
1610 assert(&rButton == m_xAddBtn.get() && "Sm : wrong argument");
1611 assert(rButton.get_sensitive() && "Sm : requirements met ??");
1613 // add symbol
1614 const SmSym aNewSymbol(m_xSymbols->get_active_text(), m_xCharsetDisplay->GetFont(),
1615 m_xCharsetDisplay->GetSelectCharacter(), m_xSymbolSets->get_active_text());
1616 //OSL_ENSURE( m_aSymbolMgrCopy.GetSymbolByName(aTmpSymbolName) == NULL, "symbol already exists" );
1617 m_aSymbolMgrCopy.AddOrReplaceSymbol( aNewSymbol );
1619 // update display of new symbol
1620 m_aSymbolDisplay.SetSymbol( &aNewSymbol );
1621 m_xSymbolName->set_label(aNewSymbol.GetName());
1622 m_xSymbolSetName->set_label(aNewSymbol.GetSymbolSetName());
1624 // update list box entries
1625 FillSymbolSets(*m_xOldSymbolSets, false);
1626 FillSymbolSets(*m_xSymbolSets, false);
1627 FillSymbols(*m_xOldSymbols, false);
1628 FillSymbols(*m_xSymbols, false);
1630 UpdateButtons();
1633 IMPL_LINK( SmSymDefineDialog, ChangeClickHdl, weld::Button&, rButton, void )
1635 (void) rButton;
1636 assert(&rButton == m_xChangeBtn.get() && "Sm : wrong argument");
1637 assert(m_xChangeBtn->get_sensitive() && "Sm : requirements met ??");
1639 // get new Symbol to use
1640 //! get font from symbol-disp lay since charset-display does not keep
1641 //! the bold attribute.
1642 const SmSym aNewSymbol(m_xSymbols->get_active_text(), m_xCharsetDisplay->GetFont(),
1643 m_xCharsetDisplay->GetSelectCharacter(), m_xSymbolSets->get_active_text());
1645 // remove old symbol if the name was changed then add new one
1646 const bool bNameChanged = m_xOldSymbols->get_active_text() != m_xSymbols->get_active_text();
1647 if (bNameChanged)
1648 m_aSymbolMgrCopy.RemoveSymbol(m_xOldSymbols->get_active_text());
1649 m_aSymbolMgrCopy.AddOrReplaceSymbol( aNewSymbol, true );
1651 // clear display for original symbol if necessary
1652 if (bNameChanged)
1653 SetOrigSymbol(nullptr, OUString());
1655 // update display of new symbol
1656 m_aSymbolDisplay.SetSymbol(&aNewSymbol);
1657 m_xSymbolName->set_label(aNewSymbol.GetName());
1658 m_xSymbolSetName->set_label(aNewSymbol.GetSymbolSetName());
1660 // update list box entries
1661 FillSymbolSets(*m_xOldSymbolSets, false);
1662 FillSymbolSets(*m_xSymbolSets, false);
1663 FillSymbols(*m_xOldSymbols, false);
1664 FillSymbols(*m_xSymbols, false);
1666 UpdateButtons();
1669 IMPL_LINK(SmSymDefineDialog, DeleteClickHdl, weld::Button&, rButton, void)
1671 (void) rButton;
1672 assert(&rButton == m_xDeleteBtn.get() && "Sm : wrong argument");
1673 assert(m_xDeleteBtn->get_sensitive() && "Sm : requirements met ??");
1675 if (m_xOrigSymbol)
1677 m_aSymbolMgrCopy.RemoveSymbol(m_xOrigSymbol->GetName());
1679 // clear display for original symbol
1680 SetOrigSymbol(nullptr, OUString());
1682 // update list box entries
1683 FillSymbolSets(*m_xOldSymbolSets, false);
1684 FillSymbolSets(*m_xSymbolSets, false);
1685 FillSymbols(*m_xOldSymbols ,false);
1686 FillSymbols(*m_xSymbols ,false);
1689 UpdateButtons();
1692 void SmSymDefineDialog::UpdateButtons()
1694 bool bAdd = false,
1695 bChange = false,
1696 bDelete = false;
1697 OUString aTmpSymbolName(m_xSymbols->get_active_text()),
1698 aTmpSymbolSetName(m_xSymbolSets->get_active_text());
1700 if (!aTmpSymbolName.isEmpty() && !aTmpSymbolSetName.isEmpty())
1702 // are all settings equal?
1703 //! (Font-, Style- and SymbolSet name comparison is not case sensitive)
1704 bool bEqual = m_xOrigSymbol
1705 && aTmpSymbolSetName.equalsIgnoreAsciiCase(m_xOldSymbolSetName->get_label())
1706 && aTmpSymbolName == m_xOrigSymbol->GetName()
1707 && m_xFonts->get_active_text().equalsIgnoreAsciiCase(
1708 m_xOrigSymbol->GetFace().GetFamilyName())
1709 && m_xStyles->get_active_text().equalsIgnoreAsciiCase(
1710 GetFontStyles().GetStyleName(m_xOrigSymbol->GetFace()))
1711 && m_xCharsetDisplay->GetSelectCharacter() == m_xOrigSymbol->GetCharacter();
1713 // only add it if there isn't already a symbol with the same name
1714 bAdd = m_aSymbolMgrCopy.GetSymbolByName(aTmpSymbolName) == nullptr;
1716 // only delete it if all settings are equal
1717 bDelete = bool(m_xOrigSymbol);
1719 // only change it if the old symbol exists and the new one is different
1720 bChange = m_xOrigSymbol && !bEqual;
1723 m_xAddBtn->set_sensitive(bAdd);
1724 m_xChangeBtn->set_sensitive(bChange);
1725 m_xDeleteBtn->set_sensitive(bDelete);
1728 SmSymDefineDialog::SmSymDefineDialog(weld::Window* pParent, OutputDevice *pFntListDevice, SmSymbolManager &rMgr)
1729 : GenericDialogController(pParent, "modules/smath/ui/symdefinedialog.ui", "EditSymbols")
1730 , m_xVirDev(VclPtr<VirtualDevice>::Create())
1731 , m_rSymbolMgr(rMgr)
1732 , m_xFontList(new FontList(pFntListDevice))
1733 , m_xOldSymbols(m_xBuilder->weld_combo_box("oldSymbols"))
1734 , m_xOldSymbolSets(m_xBuilder->weld_combo_box("oldSymbolSets"))
1735 , m_xSymbols(m_xBuilder->weld_combo_box("symbols"))
1736 , m_xSymbolSets(m_xBuilder->weld_combo_box("symbolSets"))
1737 , m_xFonts(m_xBuilder->weld_combo_box("fonts"))
1738 , m_xFontsSubsetLB(m_xBuilder->weld_combo_box("fontsSubsetLB"))
1739 , m_xStyles(m_xBuilder->weld_combo_box("styles"))
1740 , m_xOldSymbolName(m_xBuilder->weld_label("oldSymbolName"))
1741 , m_xOldSymbolSetName(m_xBuilder->weld_label("oldSymbolSetName"))
1742 , m_xSymbolName(m_xBuilder->weld_label("symbolName"))
1743 , m_xSymbolSetName(m_xBuilder->weld_label("symbolSetName"))
1744 , m_xAddBtn(m_xBuilder->weld_button("add"))
1745 , m_xChangeBtn(m_xBuilder->weld_button("modify"))
1746 , m_xDeleteBtn(m_xBuilder->weld_button("delete"))
1747 , m_xOldSymbolDisplay(new weld::CustomWeld(*m_xBuilder, "oldSymbolDisplay", m_aOldSymbolDisplay))
1748 , m_xSymbolDisplay(new weld::CustomWeld(*m_xBuilder, "symbolDisplay", m_aSymbolDisplay))
1749 , m_xCharsetDisplay(new SvxShowCharSet(m_xBuilder->weld_scrolled_window("showscroll", true), m_xVirDev))
1750 , m_xCharsetDisplayArea(new weld::CustomWeld(*m_xBuilder, "charsetDisplay", *m_xCharsetDisplay))
1752 // auto completion is troublesome since that symbols character also gets automatically selected in the
1753 // display and if the user previously selected a character to define/redefine that one this is bad
1754 m_xOldSymbols->set_entry_completion(false);
1755 m_xSymbols->set_entry_completion(false);
1757 FillFonts();
1758 if (m_xFonts->get_count() > 0)
1759 SelectFont(m_xFonts->get_text(0));
1761 SetSymbolSetManager(m_rSymbolMgr);
1763 m_xOldSymbols->connect_changed(LINK(this, SmSymDefineDialog, OldSymbolChangeHdl));
1764 m_xOldSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, OldSymbolSetChangeHdl));
1765 m_xSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1766 m_xOldSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1767 m_xSymbols->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1768 m_xOldSymbols->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1769 m_xStyles->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
1770 m_xFonts->connect_changed(LINK(this, SmSymDefineDialog, FontChangeHdl));
1771 m_xFontsSubsetLB->connect_changed(LINK(this, SmSymDefineDialog, SubsetChangeHdl));
1772 m_xStyles->connect_changed(LINK(this, SmSymDefineDialog, StyleChangeHdl));
1773 m_xAddBtn->connect_clicked(LINK(this, SmSymDefineDialog, AddClickHdl));
1774 m_xChangeBtn->connect_clicked(LINK(this, SmSymDefineDialog, ChangeClickHdl));
1775 m_xDeleteBtn->connect_clicked(LINK(this, SmSymDefineDialog, DeleteClickHdl));
1776 m_xCharsetDisplay->SetHighlightHdl( LINK( this, SmSymDefineDialog, CharHighlightHdl ) );
1779 SmSymDefineDialog::~SmSymDefineDialog()
1783 short SmSymDefineDialog::run()
1785 short nResult = GenericDialogController::run();
1787 // apply changes if dialog was closed by clicking OK
1788 if (m_aSymbolMgrCopy.IsModified() && nResult == RET_OK)
1789 m_rSymbolMgr = m_aSymbolMgrCopy;
1791 return nResult;
1794 void SmSymDefineDialog::SetSymbolSetManager(const SmSymbolManager &rMgr)
1796 m_aSymbolMgrCopy = rMgr;
1798 // Set the modified flag of the copy to false so that
1799 // we can check later on if anything has been changed
1800 m_aSymbolMgrCopy.SetModified(false);
1802 FillSymbolSets(*m_xOldSymbolSets);
1803 if (m_xOldSymbolSets->get_count() > 0)
1804 SelectSymbolSet(m_xOldSymbolSets->get_text(0));
1805 FillSymbolSets(*m_xSymbolSets);
1806 if (m_xSymbolSets->get_count() > 0)
1807 SelectSymbolSet(m_xSymbolSets->get_text(0));
1808 FillSymbols(*m_xOldSymbols);
1809 if (m_xOldSymbols->get_count() > 0)
1810 SelectSymbol(m_xOldSymbols->get_text(0));
1811 FillSymbols(*m_xSymbols);
1812 if (m_xSymbols->get_count() > 0)
1813 SelectSymbol(m_xSymbols->get_text(0));
1815 UpdateButtons();
1818 bool SmSymDefineDialog::SelectSymbolSet(weld::ComboBox& rComboBox,
1819 std::u16string_view rSymbolSetName, bool bDeleteText)
1821 assert((&rComboBox == m_xOldSymbolSets.get() || &rComboBox == m_xSymbolSets.get()) && "Sm : wrong ComboBox");
1823 // trim SymbolName (no leading and trailing blanks)
1824 OUString aNormName( comphelper::string::strip(rSymbolSetName, ' ') );
1825 // and remove possible deviations within the input
1826 rComboBox.set_entry_text(aNormName);
1828 bool bRet = false;
1829 int nPos = rComboBox.find_text(aNormName);
1831 if (nPos != -1)
1833 rComboBox.set_active(nPos);
1834 bRet = true;
1836 else if (bDeleteText)
1837 rComboBox.set_entry_text(OUString());
1839 bool bIsOld = &rComboBox == m_xOldSymbolSets.get();
1841 // setting the SymbolSet name at the associated display
1842 weld::Label& rFT = bIsOld ? *m_xOldSymbolSetName : *m_xSymbolSetName;
1843 rFT.set_label(rComboBox.get_active_text());
1845 // set the symbol name which belongs to the SymbolSet at the associated combobox
1846 weld::ComboBox& rCB = bIsOld ? *m_xOldSymbols : *m_xSymbols;
1847 FillSymbols(rCB, false);
1849 // display a valid respectively no symbol when changing the SymbolSets
1850 if (bIsOld)
1852 OUString aTmpOldSymbolName;
1853 if (m_xOldSymbols->get_count() > 0)
1854 aTmpOldSymbolName = m_xOldSymbols->get_text(0);
1855 SelectSymbol(*m_xOldSymbols, aTmpOldSymbolName, true);
1858 UpdateButtons();
1860 return bRet;
1863 void SmSymDefineDialog::SetOrigSymbol(const SmSym *pSymbol,
1864 const OUString &rSymbolSetName)
1866 // clear old symbol
1867 m_xOrigSymbol.reset();
1869 OUString aSymName,
1870 aSymSetName;
1871 if (pSymbol)
1873 // set new symbol
1874 m_xOrigSymbol.reset(new SmSym(*pSymbol));
1876 aSymName = pSymbol->GetName();
1877 aSymSetName = rSymbolSetName;
1878 m_aOldSymbolDisplay.SetSymbol( pSymbol );
1880 else
1881 { // delete displayed symbols
1882 m_aOldSymbolDisplay.SetText(OUString());
1883 m_aOldSymbolDisplay.Invalidate();
1885 m_xOldSymbolName->set_label(aSymName);
1886 m_xOldSymbolSetName->set_label(aSymSetName);
1890 bool SmSymDefineDialog::SelectSymbol(weld::ComboBox& rComboBox,
1891 const OUString &rSymbolName, bool bDeleteText)
1893 assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong ComboBox");
1895 // trim SymbolName (no blanks)
1896 OUString aNormName = rSymbolName.replaceAll(" ", "");
1897 // and remove possible deviations within the input
1898 rComboBox.set_entry_text(aNormName);
1900 bool bRet = false;
1901 int nPos = rComboBox.find_text(aNormName);
1903 bool bIsOld = &rComboBox == m_xOldSymbols.get();
1905 if (nPos != -1)
1907 rComboBox.set_active(nPos);
1909 if (!bIsOld)
1911 const SmSym *pSymbol = GetSymbol(*m_xSymbols);
1912 if (pSymbol)
1914 // choose font and style accordingly
1915 const vcl::Font &rFont = pSymbol->GetFace();
1916 SelectFont(rFont.GetFamilyName(), false);
1917 SelectStyle(GetFontStyles().GetStyleName(rFont), false);
1919 // Since setting the Font via the Style name of the SymbolFonts doesn't
1920 // work really well (e.g. it can be empty even though the font itself is
1921 // bold or italic) we're manually setting the Font with respect to the Symbol
1922 m_xCharsetDisplay->SetFont(rFont);
1923 m_aSymbolDisplay.SetFont(rFont);
1925 // select associated character
1926 SelectChar(pSymbol->GetCharacter());
1928 // since SelectChar will also set the unicode point as text in the
1929 // symbols box, we have to set the symbol name again to get that one displayed
1930 m_xSymbols->set_entry_text(pSymbol->GetName());
1934 bRet = true;
1936 else if (bDeleteText)
1937 rComboBox.set_entry_text(OUString());
1939 if (bIsOld)
1941 // if there's a change of the old symbol, show only the available ones, otherwise show none
1942 const SmSym *pOldSymbol = nullptr;
1943 OUString aTmpOldSymbolSetName;
1944 if (nPos != -1)
1946 pOldSymbol = m_aSymbolMgrCopy.GetSymbolByName(aNormName);
1947 aTmpOldSymbolSetName = m_xOldSymbolSets->get_active_text();
1949 SetOrigSymbol(pOldSymbol, aTmpOldSymbolSetName);
1951 else
1952 m_xSymbolName->set_label(rComboBox.get_active_text());
1954 UpdateButtons();
1956 return bRet;
1960 void SmSymDefineDialog::SetFont(const OUString &rFontName, std::u16string_view rStyleName)
1962 // get Font (FontInfo) matching name and style
1963 FontMetric aFontMetric;
1964 if (m_xFontList)
1965 aFontMetric = m_xFontList->Get(rFontName, WEIGHT_NORMAL, ITALIC_NONE);
1966 SetFontStyle(rStyleName, aFontMetric);
1968 m_xCharsetDisplay->SetFont(aFontMetric);
1969 m_aSymbolDisplay.SetFont(aFontMetric);
1971 // update subset listbox for new font's unicode subsets
1972 FontCharMapRef xFontCharMap = m_xCharsetDisplay->GetFontCharMap();
1973 m_xSubsetMap.reset(new SubsetMap( xFontCharMap ));
1975 m_xFontsSubsetLB->clear();
1976 bool bFirst = true;
1977 for (auto & subset : m_xSubsetMap->GetSubsetMap())
1979 m_xFontsSubsetLB->append(weld::toId(&subset), subset.GetName());
1980 // subset must live at least as long as the selected font !!!
1981 if (bFirst)
1982 m_xFontsSubsetLB->set_active(0);
1983 bFirst = false;
1985 if (bFirst)
1986 m_xFontsSubsetLB->set_active(-1);
1987 m_xFontsSubsetLB->set_sensitive(!bFirst);
1990 bool SmSymDefineDialog::SelectFont(const OUString &rFontName, bool bApplyFont)
1992 bool bRet = false;
1993 int nPos = m_xFonts->find_text(rFontName);
1995 if (nPos != -1)
1997 m_xFonts->set_active(nPos);
1998 if (m_xStyles->get_count() > 0)
1999 SelectStyle(m_xStyles->get_text(0));
2000 if (bApplyFont)
2002 SetFont(m_xFonts->get_active_text(), m_xStyles->get_active_text());
2003 m_aSymbolDisplay.SetSymbol(m_xCharsetDisplay->GetSelectCharacter(), m_xCharsetDisplay->GetFont());
2005 bRet = true;
2007 else
2008 m_xFonts->set_active(-1);
2009 FillStyles();
2011 UpdateButtons();
2013 return bRet;
2017 bool SmSymDefineDialog::SelectStyle(const OUString &rStyleName, bool bApplyFont)
2019 bool bRet = false;
2020 int nPos = m_xStyles->find_text(rStyleName);
2022 // if the style is not available take the first available one (if existent)
2023 if (nPos == -1 && m_xStyles->get_count() > 0)
2024 nPos = 0;
2026 if (nPos != -1)
2028 m_xStyles->set_active(nPos);
2029 if (bApplyFont)
2031 SetFont(m_xFonts->get_active_text(), m_xStyles->get_active_text());
2032 m_aSymbolDisplay.SetSymbol(m_xCharsetDisplay->GetSelectCharacter(), m_xCharsetDisplay->GetFont());
2034 bRet = true;
2036 else
2037 m_xStyles->set_entry_text(OUString());
2039 UpdateButtons();
2041 return bRet;
2044 void SmSymDefineDialog::SelectChar(sal_Unicode cChar)
2046 m_xCharsetDisplay->SelectCharacter( cChar );
2047 m_aSymbolDisplay.SetSymbol(cChar, m_xCharsetDisplay->GetFont());
2049 UpdateButtons();
2052 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */