office-gobmx/starmath/source/dialog.cxx
Mike Kaganski eecdaa02b6 Turn a macro to a function
Change-Id: I39cfbe43e7f27ada9999daf93aa6ccfd38fb0c52
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176561
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-11-14 08:57:32 +01:00

2170 lines
78 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sal/config.h>
#include <sal/log.hxx>
#include <comphelper/string.hxx>
#include <o3tl/temporary.hxx>
#include <svl/eitem.hxx>
#include <svl/intitem.hxx>
#include <svl/stritem.hxx>
#include <vcl/event.hxx>
#include <vcl/svapp.hxx>
#include <vcl/virdev.hxx>
#include <vcl/weld.hxx>
#include <svtools/ctrltool.hxx>
#include <vcl/settings.hxx>
#include <vcl/wall.hxx>
#include <vcl/fontcharmap.hxx>
#include <sfx2/dispatch.hxx>
#include <svx/charmap.hxx>
#include <svx/ucsubset.hxx>
#include <dialog.hxx>
#include <starmath.hrc>
#include <strings.hrc>
#include <helpids.h>
#include <cfgitem.hxx>
#include <officecfg/Office/Math.hxx>
#include <smmod.hxx>
#include <symbol.hxx>
#include <view.hxx>
#include <algorithm>
namespace
{
void lclGetSettingColors(Color& rBackgroundColor, Color& rTextColor)
{
const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
if (rStyleSettings.GetHighContrastMode())
{
rBackgroundColor = rStyleSettings.GetFieldColor();
rTextColor = rStyleSettings.GetFieldTextColor();
}
else
{
rBackgroundColor = rStyleSettings.GetFaceColor();
rTextColor = rStyleSettings.GetLabelTextColor();
}
}
// Since it's better to set/query the FontStyle via its attributes rather
// than via the StyleName we create a way to translate
// Attribute <-> StyleName
class SmFontStyles
{
OUString aNormal;
OUString aBold;
OUString aItalic;
OUString aBoldItalic;
public:
SmFontStyles();
static sal_uInt16 GetCount() { return 4; }
const OUString& GetStyleName(const vcl::Font& rFont) const;
const OUString& GetStyleName(sal_uInt16 nIdx) const;
};
vcl::Font lclGetSymbolFont(const SmViewShell& rViewShell, const SmSym &rSymbol)
{
const SmDocShell* pDoc = rViewShell.GetDoc();
if (pDoc)
{
// If we have a document, we want to render the symbol using the font and style used in
// the document, so we do that by creating a node and preparing it, then get the resolved
// font and style from it.
SmToken token(TSPECIAL, '\0', "%" + rSymbol.GetUiName());
SmSpecialNode aNode(token);
aNode.Prepare(pDoc->GetFormat(), *pDoc, 1);
aNode.PrepareAttributes();
return aNode.GetFont();
}
return rSymbol.GetFace();
}
} // end anonymous namespace
SmFontStyles::SmFontStyles()
: aNormal(SmResId(RID_FONTREGULAR))
, aBold(SmResId(RID_FONTBOLD))
, aItalic(SmResId(RID_FONTITALIC))
{
aBoldItalic = aBold;
aBoldItalic += ", ";
aBoldItalic += aItalic;
}
const OUString& SmFontStyles::GetStyleName(const vcl::Font& rFont) const
{
//! compare also SmSpecialNode::Prepare
bool bBold = IsBold( rFont ),
bItalic = IsItalic( rFont );
if (bBold && bItalic)
return aBoldItalic;
else if (bItalic)
return aItalic;
else if (bBold)
return aBold;
return aNormal;
}
const OUString& SmFontStyles::GetStyleName( sal_uInt16 nIdx ) const
{
// 0 = "normal", 1 = "italic",
// 2 = "bold", 3 = "bold italic"
assert( nIdx < GetCount() );
switch (nIdx)
{
case 0 : return aNormal;
case 1 : return aItalic;
case 2 : return aBold;
default: /*case 3:*/ return aBoldItalic;
}
}
static const SmFontStyles & GetFontStyles()
{
static const SmFontStyles aImpl;
return aImpl;
}
void SetFontStyle(std::u16string_view rStyleName, vcl::Font &rFont)
{
// Find index related to StyleName. For an empty StyleName it's assumed to be
// 0 (neither bold nor italic).
sal_uInt16 nIndex = 0;
if (!rStyleName.empty())
{
sal_uInt16 i;
const SmFontStyles &rStyles = GetFontStyles();
for (i = 0; i < SmFontStyles::GetCount(); ++i)
if (rStyleName == rStyles.GetStyleName(i))
break;
assert(i < SmFontStyles::GetCount() && "style-name unknown");
nIndex = i;
}
rFont.SetItalic((nIndex & 0x1) ? ITALIC_NORMAL : ITALIC_NONE);
rFont.SetWeight((nIndex & 0x2) ? WEIGHT_BOLD : WEIGHT_NORMAL);
}
IMPL_LINK_NOARG(SmPrintOptionsTabPage, SizeButtonClickHdl, weld::Toggleable&, void)
{
m_xZoom->set_sensitive(m_xSizeZoomed->get_active());
}
SmPrintOptionsTabPage::SmPrintOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rOptions)
: SfxTabPage(pPage, pController, u"modules/smath/ui/smathsettings.ui"_ustr, u"SmathSettings"_ustr, &rOptions)
, m_xTitle(m_xBuilder->weld_check_button(u"title"_ustr))
, m_xTitleImg(m_xBuilder->weld_widget(u"locktitle"_ustr))
, m_xText(m_xBuilder->weld_check_button(u"text"_ustr))
, m_xTextImg(m_xBuilder->weld_widget(u"locktext"_ustr))
, m_xFrame(m_xBuilder->weld_check_button(u"frame"_ustr))
, m_xFrameImg(m_xBuilder->weld_widget(u"lockframe"_ustr))
, m_xSizeNormal(m_xBuilder->weld_radio_button(u"sizenormal"_ustr))
, m_xSizeScaled(m_xBuilder->weld_radio_button(u"sizescaled"_ustr))
, m_xSizeZoomed(m_xBuilder->weld_radio_button(u"sizezoomed"_ustr))
, m_xLockPrintImg(m_xBuilder->weld_widget(u"lockprintformat"_ustr))
, m_xZoom(m_xBuilder->weld_metric_spin_button(u"zoom"_ustr, FieldUnit::PERCENT))
, m_xEnableInlineEdit(m_xBuilder->weld_check_button(u"enableinlineedit"_ustr))
, m_xEnableInlineEditImg(m_xBuilder->weld_widget(u"lockenableinlineedit"_ustr))
, m_xNoRightSpaces(m_xBuilder->weld_check_button(u"norightspaces"_ustr))
, m_xNoRightSpacesImg(m_xBuilder->weld_widget(u"locknorightspaces"_ustr))
, m_xSaveOnlyUsedSymbols(m_xBuilder->weld_check_button(u"saveonlyusedsymbols"_ustr))
, m_xSaveOnlyUsedSymbolsImg(m_xBuilder->weld_widget(u"locksaveonlyusedsymbols"_ustr))
, m_xAutoCloseBrackets(m_xBuilder->weld_check_button(u"autoclosebrackets"_ustr))
, m_xAutoCloseBracketsImg(m_xBuilder->weld_widget(u"lockautoclosebrackets"_ustr))
, m_xSmZoom(m_xBuilder->weld_metric_spin_button(u"smzoom"_ustr, FieldUnit::PERCENT))
, m_xSmZoomImg(m_xBuilder->weld_widget(u"locksmzoom"_ustr))
{
m_xSizeNormal->connect_toggled(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl));
m_xSizeScaled->connect_toggled(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl));
m_xSizeZoomed->connect_toggled(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl));
Reset(&rOptions);
}
SmPrintOptionsTabPage::~SmPrintOptionsTabPage()
{
if (SmViewShell *pViewSh = SmGetActiveView())
if (SmEditWindow* pEdit = pViewSh->GetEditWindow())
pEdit->UpdateStatus();
}
OUString SmPrintOptionsTabPage::GetAllStrings()
{
OUString sAllStrings;
OUString labels[] = { u"label4"_ustr, u"label5"_ustr, u"label1"_ustr, u"label6"_ustr };
for (const auto& label : labels)
{
if (const auto pString = m_xBuilder->weld_label(label))
sAllStrings += pString->get_label() + " ";
}
OUString checkButton[]
= { u"title"_ustr, u"text"_ustr, u"frame"_ustr, u"norightspaces"_ustr, u"saveonlyusedsymbols"_ustr, u"autoclosebrackets"_ustr };
for (const auto& check : checkButton)
{
if (const auto pString = m_xBuilder->weld_check_button(check))
sAllStrings += pString->get_label() + " ";
}
OUString radioButton[] = { u"sizenormal"_ustr, u"sizescaled"_ustr, u"sizezoomed"_ustr };
for (const auto& radio : radioButton)
{
if (const auto pString = m_xBuilder->weld_radio_button(radio))
sAllStrings += pString->get_label() + " ";
}
return sAllStrings.replaceAll("_", "");
}
bool SmPrintOptionsTabPage::FillItemSet(SfxItemSet* rSet)
{
sal_uInt16 nPrintSize;
if (m_xSizeNormal->get_active())
nPrintSize = PRINT_SIZE_NORMAL;
else if (m_xSizeScaled->get_active())
nPrintSize = PRINT_SIZE_SCALED;
else
nPrintSize = PRINT_SIZE_ZOOMED;
rSet->Put(SfxUInt16Item(SID_PRINTSIZE, nPrintSize));
rSet->Put(SfxUInt16Item(SID_PRINTZOOM, sal::static_int_cast<sal_uInt16>(m_xZoom->get_value(FieldUnit::PERCENT))));
rSet->Put(SfxBoolItem(SID_PRINTTITLE, m_xTitle->get_active()));
rSet->Put(SfxBoolItem(SID_PRINTTEXT, m_xText->get_active()));
rSet->Put(SfxBoolItem(SID_PRINTFRAME, m_xFrame->get_active()));
rSet->Put(SfxBoolItem(SID_INLINE_EDIT_ENABLE, m_xEnableInlineEdit->get_active()));
rSet->Put(SfxBoolItem(SID_NO_RIGHT_SPACES, m_xNoRightSpaces->get_active()));
rSet->Put(SfxBoolItem(SID_SAVE_ONLY_USED_SYMBOLS, m_xSaveOnlyUsedSymbols->get_active()));
rSet->Put(SfxBoolItem(SID_AUTO_CLOSE_BRACKETS, m_xAutoCloseBrackets->get_active()));
rSet->Put(SfxUInt16Item(SID_SMEDITWINDOWZOOM, sal::static_int_cast<sal_uInt16>(m_xSmZoom->get_value(FieldUnit::PERCENT))));
if (SmViewShell *pViewSh = SmGetActiveView())
if (SmEditWindow* pEdit = pViewSh->GetEditWindow())
pEdit->UpdateStatus();
return true;
}
void SmPrintOptionsTabPage::Reset(const SfxItemSet* rSet)
{
SmPrintSize ePrintSize = static_cast<SmPrintSize>(rSet->Get(SID_PRINTSIZE).GetValue());
m_xSizeNormal->set_active(ePrintSize == PRINT_SIZE_NORMAL);
m_xSizeScaled->set_active(ePrintSize == PRINT_SIZE_SCALED);
m_xSizeZoomed->set_active(ePrintSize == PRINT_SIZE_ZOOMED);
bool bReadOnly = officecfg::Office::Math::Print::Size::isReadOnly();
if (bReadOnly)
{
m_xSizeNormal->set_sensitive(false);
m_xSizeScaled->set_sensitive(false);
m_xSizeZoomed->set_sensitive(false);
m_xLockPrintImg->set_visible(true);
}
bReadOnly = officecfg::Office::Math::Print::ZoomFactor::isReadOnly();
m_xZoom->set_value(rSet->Get(SID_PRINTZOOM).GetValue(), FieldUnit::PERCENT);
m_xZoom->set_sensitive(m_xSizeZoomed->get_active() && !bReadOnly);
bReadOnly = officecfg::Office::Math::Misc::SmEditWindowZoomFactor::isReadOnly();
m_xSmZoom->set_value(rSet->Get(SID_SMEDITWINDOWZOOM).GetValue(), FieldUnit::PERCENT);
m_xSmZoom->set_sensitive(!bReadOnly);
m_xSmZoomImg->set_visible(bReadOnly);
bReadOnly = officecfg::Office::Math::Print::Title::isReadOnly();
m_xTitle->set_active(rSet->Get(SID_PRINTTITLE).GetValue());
m_xTitle->set_sensitive(!bReadOnly);
m_xTitleImg->set_visible(bReadOnly);
bReadOnly = officecfg::Office::Math::Print::FormulaText::isReadOnly();
m_xText->set_active(rSet->Get(GetWhich(SID_PRINTTEXT)).GetValue());
m_xText->set_sensitive(!bReadOnly);
m_xTextImg->set_visible(bReadOnly);
bReadOnly = officecfg::Office::Math::Print::Frame::isReadOnly();
m_xFrame->set_active(rSet->Get(GetWhich(SID_PRINTFRAME)).GetValue());
m_xFrame->set_sensitive(!bReadOnly);
m_xFrameImg->set_visible(bReadOnly);
bReadOnly = officecfg::Office::Math::Misc::InlineEditEnable::isReadOnly();
m_xEnableInlineEdit->set_active(rSet->Get(SID_INLINE_EDIT_ENABLE).GetValue());
m_xEnableInlineEdit->set_sensitive(!bReadOnly);
m_xEnableInlineEditImg->set_visible(bReadOnly);
bReadOnly = officecfg::Office::Math::Misc::IgnoreSpacesRight::isReadOnly();
m_xNoRightSpaces->set_active(rSet->Get(SID_NO_RIGHT_SPACES).GetValue());
m_xNoRightSpaces->set_sensitive(!bReadOnly);
m_xNoRightSpacesImg->set_visible(bReadOnly);
bReadOnly = officecfg::Office::Math::LoadSave::IsSaveOnlyUsedSymbols::isReadOnly();
m_xSaveOnlyUsedSymbols->set_active(rSet->Get(SID_SAVE_ONLY_USED_SYMBOLS).GetValue());
m_xSaveOnlyUsedSymbols->set_sensitive(!bReadOnly);
m_xSaveOnlyUsedSymbolsImg->set_visible(bReadOnly);
bReadOnly = officecfg::Office::Math::Misc::AutoCloseBrackets::isReadOnly();
m_xAutoCloseBrackets->set_active(rSet->Get(SID_AUTO_CLOSE_BRACKETS).GetValue());
m_xAutoCloseBrackets->set_sensitive(!bReadOnly);
m_xAutoCloseBracketsImg->set_visible(bReadOnly);
}
std::unique_ptr<SfxTabPage> SmPrintOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
{
return std::make_unique<SmPrintOptionsTabPage>(pPage, pController, rSet);
}
void SmShowFont::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
{
Color aBackColor;
Color aTextColor;
lclGetSettingColors(aBackColor, aTextColor);
rRenderContext.SetBackground(Wallpaper(aBackColor));
vcl::Font aFont(maFont);
aFont.SetFontSize(Size(0, 24 * rRenderContext.GetDPIScaleFactor()));
aFont.SetAlignment(ALIGN_TOP);
rRenderContext.SetFont(aFont);
rRenderContext.SetTextColor(aTextColor);
OUString sText(rRenderContext.GetFont().GetFamilyName());
Size aTextSize(rRenderContext.GetTextWidth(sText), rRenderContext.GetTextHeight());
rRenderContext.DrawText(Point((rRenderContext.GetOutputSize().Width() - aTextSize.Width()) / 2,
(rRenderContext.GetOutputSize().Height() - aTextSize.Height()) / 2), sText);
}
void SmShowFont::SetDrawingArea(weld::DrawingArea* pDrawingArea)
{
CustomWidgetController::SetDrawingArea(pDrawingArea);
Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(111 , 31), MapMode(MapUnit::MapAppFont)));
pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
}
void SmShowFont::SetFont(const vcl::Font& rFont)
{
maFont = rFont;
Invalidate();
}
IMPL_LINK( SmFontDialog, FontSelectHdl, weld::ComboBox&, rComboBox, void )
{
maFont.SetFamilyName(rComboBox.get_active_text());
m_aShowFont.SetFont(maFont);
}
IMPL_LINK_NOARG(SmFontDialog, AttrChangeHdl, weld::Toggleable&, void)
{
if (m_xBoldCheckBox->get_active())
maFont.SetWeight(WEIGHT_BOLD);
else
maFont.SetWeight(WEIGHT_NORMAL);
if (m_xItalicCheckBox->get_active())
maFont.SetItalic(ITALIC_NORMAL);
else
maFont.SetItalic(ITALIC_NONE);
m_aShowFont.SetFont(maFont);
}
void SmFontDialog::SetFont(const vcl::Font &rFont)
{
maFont = rFont;
m_xFontBox->set_active_text(maFont.GetFamilyName());
m_xBoldCheckBox->set_active(IsBold(maFont));
m_xItalicCheckBox->set_active(IsItalic(maFont));
m_aShowFont.SetFont(maFont);
}
SmFontDialog::SmFontDialog(weld::Window * pParent, OutputDevice *pFntListDevice, bool bHideCheckboxes)
: GenericDialogController(pParent, u"modules/smath/ui/fontdialog.ui"_ustr, u"FontDialog"_ustr)
, m_xFontBox(m_xBuilder->weld_entry_tree_view(u"fontgrid"_ustr, u"font"_ustr, u"fonts"_ustr))
, m_xAttrFrame(m_xBuilder->weld_widget(u"attrframe"_ustr))
, m_xBoldCheckBox(m_xBuilder->weld_check_button(u"bold"_ustr))
, m_xItalicCheckBox(m_xBuilder->weld_check_button(u"italic"_ustr))
, m_xShowFont(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aShowFont))
{
m_xFontBox->set_height_request_by_rows(8);
{
weld::WaitObject aWait(pParent);
FontList aFontList( pFntListDevice );
sal_uInt16 nCount = aFontList.GetFontNameCount();
for (sal_uInt16 i = 0; i < nCount; ++i)
{
m_xFontBox->append_text(aFontList.GetFontName(i).GetFamilyName());
}
maFont.SetFontSize(Size(0, 24));
maFont.SetWeight(WEIGHT_NORMAL);
maFont.SetItalic(ITALIC_NONE);
maFont.SetFamily(FAMILY_DONTKNOW);
maFont.SetPitch(PITCH_DONTKNOW);
maFont.SetCharSet(RTL_TEXTENCODING_DONTKNOW);
maFont.SetTransparent(true);
}
m_xFontBox->connect_changed(LINK(this, SmFontDialog, FontSelectHdl));
m_xBoldCheckBox->connect_toggled(LINK(this, SmFontDialog, AttrChangeHdl));
m_xItalicCheckBox->connect_toggled(LINK(this, SmFontDialog, AttrChangeHdl));
if (bHideCheckboxes)
{
m_xBoldCheckBox->set_active(false);
m_xBoldCheckBox->set_sensitive(false);
m_xItalicCheckBox->set_active(false);
m_xItalicCheckBox->set_sensitive(false);
m_xAttrFrame->hide();
}
}
SmFontDialog::~SmFontDialog()
{
}
namespace {
class SaveDefaultsQuery : public weld::MessageDialogController
{
public:
explicit SaveDefaultsQuery(weld::Widget* pParent)
: MessageDialogController(pParent, u"modules/smath/ui/savedefaultsdialog.ui"_ustr,
u"SaveDefaultsDialog"_ustr)
{
}
};
}
IMPL_LINK_NOARG( SmFontSizeDialog, DefaultButtonClickHdl, weld::Button&, void )
{
SaveDefaultsQuery aQuery(m_xDialog.get());
if (aQuery.run() == RET_YES)
{
auto* config = SmModule::get()->GetConfig();
SmFormat aFmt(config->GetStandardFormat());
WriteTo( aFmt );
config->SetStandardFormat(aFmt);
}
}
SmFontSizeDialog::SmFontSizeDialog(weld::Window* pParent)
: GenericDialogController(pParent, u"modules/smath/ui/fontsizedialog.ui"_ustr, u"FontSizeDialog"_ustr)
, m_xBaseSize(m_xBuilder->weld_metric_spin_button(u"spinB_baseSize"_ustr, FieldUnit::POINT))
, m_xTextSize(m_xBuilder->weld_metric_spin_button(u"spinB_text"_ustr, FieldUnit::PERCENT))
, m_xIndexSize(m_xBuilder->weld_metric_spin_button(u"spinB_index"_ustr, FieldUnit::PERCENT))
, m_xFunctionSize(m_xBuilder->weld_metric_spin_button(u"spinB_function"_ustr, FieldUnit::PERCENT))
, m_xOperatorSize(m_xBuilder->weld_metric_spin_button(u"spinB_operator"_ustr, FieldUnit::PERCENT))
, m_xBorderSize(m_xBuilder->weld_metric_spin_button(u"spinB_limit"_ustr, FieldUnit::PERCENT))
, m_xDefaultButton(m_xBuilder->weld_button(u"default"_ustr))
{
m_xDefaultButton->connect_clicked(LINK(this, SmFontSizeDialog, DefaultButtonClickHdl));
}
SmFontSizeDialog::~SmFontSizeDialog()
{
}
void SmFontSizeDialog::ReadFrom(const SmFormat &rFormat)
{
//! watch out: round properly!
m_xBaseSize->set_value(
o3tl::convert(rFormat.GetBaseSize().Height(), SmO3tlLengthUnit(), o3tl::Length::pt),
FieldUnit::NONE);
m_xTextSize->set_value( rFormat.GetRelSize(SIZ_TEXT), FieldUnit::NONE );
m_xIndexSize->set_value( rFormat.GetRelSize(SIZ_INDEX), FieldUnit::NONE );
m_xFunctionSize->set_value( rFormat.GetRelSize(SIZ_FUNCTION), FieldUnit::NONE );
m_xOperatorSize->set_value( rFormat.GetRelSize(SIZ_OPERATOR), FieldUnit::NONE );
m_xBorderSize->set_value( rFormat.GetRelSize(SIZ_LIMITS), FieldUnit::NONE );
}
void SmFontSizeDialog::WriteTo(SmFormat &rFormat) const
{
rFormat.SetBaseSize( Size(0, o3tl::convert(m_xBaseSize->get_value(FieldUnit::NONE), o3tl::Length::pt, SmO3tlLengthUnit())) );
rFormat.SetRelSize(SIZ_TEXT, sal::static_int_cast<sal_uInt16>(m_xTextSize->get_value(FieldUnit::NONE)));
rFormat.SetRelSize(SIZ_INDEX, sal::static_int_cast<sal_uInt16>(m_xIndexSize->get_value(FieldUnit::NONE)));
rFormat.SetRelSize(SIZ_FUNCTION, sal::static_int_cast<sal_uInt16>(m_xFunctionSize->get_value(FieldUnit::NONE)));
rFormat.SetRelSize(SIZ_OPERATOR, sal::static_int_cast<sal_uInt16>(m_xOperatorSize->get_value(FieldUnit::NONE)));
rFormat.SetRelSize(SIZ_LIMITS, sal::static_int_cast<sal_uInt16>(m_xBorderSize->get_value(FieldUnit::NONE)));
const Size aTmp (rFormat.GetBaseSize());
for (sal_uInt16 i = FNT_BEGIN; i <= FNT_END; i++)
rFormat.SetFontSize(i, aTmp);
rFormat.RequestApplyChanges();
}
IMPL_LINK(SmFontTypeDialog, MenuSelectHdl, const OUString&, rIdent, void)
{
SmFontPickListBox *pActiveListBox;
bool bHideCheckboxes = false;
if (rIdent == "math")
pActiveListBox = m_xMathFont.get();
else if (rIdent == "variables")
pActiveListBox = m_xVariableFont.get();
else if (rIdent == "functions")
pActiveListBox = m_xFunctionFont.get();
else if (rIdent == "numbers")
pActiveListBox = m_xNumberFont.get();
else if (rIdent == "text")
pActiveListBox = m_xTextFont.get();
else if (rIdent == "serif")
{
pActiveListBox = m_xSerifFont.get();
bHideCheckboxes = true;
}
else if (rIdent == "sansserif")
{
pActiveListBox = m_xSansFont.get();
bHideCheckboxes = true;
}
else if (rIdent == "fixedwidth")
{
pActiveListBox = m_xFixedFont.get();
bHideCheckboxes = true;
}
else
pActiveListBox = nullptr;
if (pActiveListBox)
{
SmFontDialog aFontDialog(m_xDialog.get(), pFontListDev, bHideCheckboxes);
pActiveListBox->WriteTo(aFontDialog);
if (aFontDialog.run() == RET_OK)
pActiveListBox->ReadFrom(aFontDialog);
}
}
IMPL_LINK_NOARG(SmFontTypeDialog, DefaultButtonClickHdl, weld::Button&, void)
{
SaveDefaultsQuery aQuery(m_xDialog.get());
if (aQuery.run() == RET_YES)
{
auto* config = SmModule::get()->GetConfig();
SmFormat aFmt(config->GetStandardFormat());
WriteTo( aFmt );
config->SetStandardFormat(aFmt, true);
}
}
SmFontTypeDialog::SmFontTypeDialog(weld::Window* pParent, OutputDevice *pFntListDevice)
: GenericDialogController(pParent, u"modules/smath/ui/fonttypedialog.ui"_ustr, u"FontsDialog"_ustr)
, pFontListDev(pFntListDevice)
, m_xMathFont(new SmFontPickListBox(m_xBuilder->weld_combo_box(u"mathCB"_ustr)))
, m_xVariableFont(new SmFontPickListBox(m_xBuilder->weld_combo_box(u"variableCB"_ustr)))
, m_xFunctionFont(new SmFontPickListBox(m_xBuilder->weld_combo_box(u"functionCB"_ustr)))
, m_xNumberFont(new SmFontPickListBox(m_xBuilder->weld_combo_box(u"numberCB"_ustr)))
, m_xTextFont(new SmFontPickListBox(m_xBuilder->weld_combo_box(u"textCB"_ustr)))
, m_xSerifFont(new SmFontPickListBox(m_xBuilder->weld_combo_box(u"serifCB"_ustr)))
, m_xSansFont(new SmFontPickListBox(m_xBuilder->weld_combo_box(u"sansCB"_ustr)))
, m_xFixedFont(new SmFontPickListBox(m_xBuilder->weld_combo_box(u"fixedCB"_ustr)))
, m_xMenuButton(m_xBuilder->weld_menu_button(u"modify"_ustr))
, m_xDefaultButton(m_xBuilder->weld_button(u"default"_ustr))
{
m_xDefaultButton->connect_clicked(LINK(this, SmFontTypeDialog, DefaultButtonClickHdl));
m_xMenuButton->connect_selected(LINK(this, SmFontTypeDialog, MenuSelectHdl));
}
SmFontTypeDialog::~SmFontTypeDialog()
{
}
void SmFontTypeDialog::ReadFrom(const SmFormat &rFormat)
{
auto* config = SmModule::get()->GetConfig();
*m_xMathFont = config->GetFontPickList(FNT_MATH);
*m_xVariableFont = config->GetFontPickList(FNT_VARIABLE);
*m_xFunctionFont = config->GetFontPickList(FNT_FUNCTION);
*m_xNumberFont = config->GetFontPickList(FNT_NUMBER);
*m_xTextFont = config->GetFontPickList(FNT_TEXT);
*m_xSerifFont = config->GetFontPickList(FNT_SERIF);
*m_xSansFont = config->GetFontPickList(FNT_SANS);
*m_xFixedFont = config->GetFontPickList(FNT_FIXED);
m_xMathFont->Insert( rFormat.GetFont(FNT_MATH) );
m_xVariableFont->Insert( rFormat.GetFont(FNT_VARIABLE) );
m_xFunctionFont->Insert( rFormat.GetFont(FNT_FUNCTION) );
m_xNumberFont->Insert( rFormat.GetFont(FNT_NUMBER) );
m_xTextFont->Insert( rFormat.GetFont(FNT_TEXT) );
m_xSerifFont->Insert( rFormat.GetFont(FNT_SERIF) );
m_xSansFont->Insert( rFormat.GetFont(FNT_SANS) );
m_xFixedFont->Insert( rFormat.GetFont(FNT_FIXED) );
}
void SmFontTypeDialog::WriteTo(SmFormat &rFormat) const
{
auto* config = SmModule::get()->GetConfig();
config->GetFontPickList(FNT_MATH) = *m_xMathFont;
config->GetFontPickList(FNT_VARIABLE) = *m_xVariableFont;
config->GetFontPickList(FNT_FUNCTION) = *m_xFunctionFont;
config->GetFontPickList(FNT_NUMBER) = *m_xNumberFont;
config->GetFontPickList(FNT_TEXT) = *m_xTextFont;
config->GetFontPickList(FNT_SERIF) = *m_xSerifFont;
config->GetFontPickList(FNT_SANS) = *m_xSansFont;
config->GetFontPickList(FNT_FIXED) = *m_xFixedFont;
rFormat.SetFont( FNT_MATH, SmFace(m_xMathFont->Get()) );
rFormat.SetFont( FNT_VARIABLE, SmFace(m_xVariableFont->Get()) );
rFormat.SetFont( FNT_FUNCTION, SmFace(m_xFunctionFont->Get()) );
rFormat.SetFont( FNT_NUMBER, SmFace(m_xNumberFont->Get()) );
rFormat.SetFont( FNT_TEXT, SmFace(m_xTextFont->Get()) );
rFormat.SetFont( FNT_SERIF, SmFace(m_xSerifFont->Get()) );
rFormat.SetFont( FNT_SANS, SmFace(m_xSansFont->Get()) );
rFormat.SetFont( FNT_FIXED, SmFace(m_xFixedFont->Get()) );
rFormat.RequestApplyChanges();
}
/**************************************************************************/
namespace {
struct FieldMinMax
{
sal_uInt16 nMin, nMax;
};
}
// Data for min and max values of the 4 metric fields
// for each of the 10 categories
const FieldMinMax pMinMaxData[10][4] =
{
// 0
{{ 0, 200 }, { 0, 200 }, { 0, 100 }, { 0, 0 }},
// 1
{{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
// 2
{{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
// 3
{{ 0, 100 }, { 1, 100 }, { 0, 0 }, { 0, 0 }},
// 4
{{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
// 5
{{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 100 }},
// 6
{{ 0, 300 }, { 0, 300 }, { 0, 0 }, { 0, 0 }},
// 7
{{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
// 8
{{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }},
// 9
{{ 0, 10000 }, { 0, 10000 }, { 0, 10000 }, { 0, 10000 }}
};
SmCategoryDesc::SmCategoryDesc(weld::Builder& rBuilder, sal_uInt16 nCategoryIdx)
{
++nCategoryIdx;
std::unique_ptr<weld::Label> xTitle(rBuilder.weld_label(OUString::number(nCategoryIdx)+"title"));
if (xTitle)
{
Name = xTitle->get_label();
}
for (int i = 0; i < 4; ++i)
{
std::unique_ptr<weld::Label> xLabel(rBuilder.weld_label(OUString::number(nCategoryIdx)+"label"+OUString::number(i+1)));
if (xLabel)
{
Strings[i] = xLabel->get_label();
Graphics[i] = rBuilder.weld_widget(OUString::number(nCategoryIdx)+"image"+OUString::number(i+1));
}
else
{
Strings[i].clear();
Graphics[i].reset();
}
const FieldMinMax& rMinMax = pMinMaxData[ nCategoryIdx-1 ][i];
Value[i] = Minimum[i] = rMinMax.nMin;
Maximum[i] = rMinMax.nMax;
}
}
SmCategoryDesc::~SmCategoryDesc()
{
}
/**************************************************************************/
IMPL_LINK( SmDistanceDialog, GetFocusHdl, weld::Widget&, rControl, void )
{
if (!m_xCategories[nActiveCategory])
return;
sal_uInt16 i;
if (&rControl == &m_xMetricField1->get_widget())
i = 0;
else if (&rControl == &m_xMetricField2->get_widget())
i = 1;
else if (&rControl == &m_xMetricField3->get_widget())
i = 2;
else if (&rControl == &m_xMetricField4->get_widget())
i = 3;
else
return;
if (m_pCurrentImage)
m_pCurrentImage->hide();
m_pCurrentImage = m_xCategories[nActiveCategory]->GetGraphic(i);
m_pCurrentImage->show();
}
IMPL_LINK(SmDistanceDialog, MenuSelectHdl, const OUString&, rId, void)
{
assert(rId.startsWith("menuitem"));
SetCategory(rId.replaceFirst("menuitem", "").toInt32() - 1);
}
IMPL_LINK_NOARG( SmDistanceDialog, DefaultButtonClickHdl, weld::Button&, void )
{
SaveDefaultsQuery aQuery(m_xDialog.get());
if (aQuery.run() == RET_YES)
{
auto* config = SmModule::get()->GetConfig();
SmFormat aFmt(config->GetStandardFormat());
WriteTo( aFmt );
config->SetStandardFormat( aFmt );
}
}
IMPL_LINK( SmDistanceDialog, CheckBoxClickHdl, weld::Toggleable&, rCheckBox, void )
{
if (&rCheckBox == m_xCheckBox1.get())
{
bool bChecked = m_xCheckBox1->get_active();
m_xFixedText4->set_sensitive( bChecked );
m_xMetricField4->set_sensitive( bChecked );
}
}
void SmDistanceDialog::SetCategory(sal_uInt16 nCategory)
{
assert(nCategory < NOCATEGORIES && "Sm: wrong category number in SmDistanceDialog");
// array to convert category- and metricfield-number in help ids.
// 0 is used in case of unused combinations.
assert(NOCATEGORIES == 10 && "Sm : array doesn't fit into the number of categories");
static constexpr OUString EMPTY(u""_ustr);
static constexpr OUString aCatMf2Hid[10][4] =
{
{ HID_SMA_DEFAULT_DIST, HID_SMA_LINE_DIST, HID_SMA_ROOT_DIST, EMPTY },
{ HID_SMA_SUP_DIST, HID_SMA_SUB_DIST , EMPTY, EMPTY },
{ HID_SMA_NUMERATOR_DIST, HID_SMA_DENOMINATOR_DIST, EMPTY, EMPTY },
{ HID_SMA_FRACLINE_EXCWIDTH, HID_SMA_FRACLINE_LINEWIDTH, EMPTY, EMPTY },
{ HID_SMA_UPPERLIMIT_DIST, HID_SMA_LOWERLIMIT_DIST, EMPTY, EMPTY },
{ HID_SMA_BRACKET_EXCHEIGHT, HID_SMA_BRACKET_DIST, EMPTY, HID_SMA_BRACKET_EXCHEIGHT2 },
{ HID_SMA_MATRIXROW_DIST, HID_SMA_MATRIXCOL_DIST, EMPTY, EMPTY },
{ HID_SMA_ATTRIBUT_DIST, HID_SMA_INTERATTRIBUT_DIST, EMPTY, EMPTY },
{ HID_SMA_OPERATOR_EXCHEIGHT, HID_SMA_OPERATOR_DIST, EMPTY, EMPTY },
{ HID_SMA_LEFTBORDER_DIST, HID_SMA_RIGHTBORDER_DIST, HID_SMA_UPPERBORDER_DIST, HID_SMA_LOWERBORDER_DIST }
};
// array to help iterate over the controls
std::pair<weld::Label*, weld::MetricSpinButton*> const aWin[4] =
{
{ m_xFixedText1.get(), m_xMetricField1.get() },
{ m_xFixedText2.get(), m_xMetricField2.get() },
{ m_xFixedText3.get(), m_xMetricField3.get() },
{ m_xFixedText4.get(), m_xMetricField4.get() }
};
SmCategoryDesc *pCat;
// remember the (maybe new) settings of the active SmCategoryDesc
// before switching to the new one
if (nActiveCategory != CATEGORY_NONE)
{
pCat = m_xCategories[nActiveCategory].get();
pCat->SetValue(0, sal::static_int_cast<sal_uInt16>(m_xMetricField1->get_value(FieldUnit::NONE)));
pCat->SetValue(1, sal::static_int_cast<sal_uInt16>(m_xMetricField2->get_value(FieldUnit::NONE)));
pCat->SetValue(2, sal::static_int_cast<sal_uInt16>(m_xMetricField3->get_value(FieldUnit::NONE)));
pCat->SetValue(3, sal::static_int_cast<sal_uInt16>(m_xMetricField4->get_value(FieldUnit::NONE)));
if (nActiveCategory == 5)
bScaleAllBrackets = m_xCheckBox1->get_active();
m_xMenuButton->set_item_active("menuitem" + OUString::number(nActiveCategory + 1), false);
}
// activation/deactivation of the associated controls depending on the chosen category
bool bActive;
for (sal_uInt16 i = 0; i < 4; i++)
{
weld::Label *pFT = aWin[i].first;
weld::MetricSpinButton *pMF = aWin[i].second;
// To determine which Controls should be active, the existence
// of an associated HelpID is checked
bActive = !aCatMf2Hid[nCategory][i].isEmpty();
pFT->set_visible(bActive);
pFT->set_sensitive(bActive);
pMF->set_visible(bActive);
pMF->set_sensitive(bActive);
// set measurement unit and number of decimal places
FieldUnit eUnit;
sal_uInt16 nDigits;
if (nCategory < 9)
{
eUnit = FieldUnit::PERCENT;
nDigits = 0;
}
else
{
eUnit = FieldUnit::MM_100TH;
nDigits = 2;
}
pMF->set_unit(eUnit); // changes the value
pMF->set_digits(nDigits);
if (bActive)
{
pCat = m_xCategories[nCategory].get();
pFT->set_label(pCat->GetString(i));
pMF->set_range(pCat->GetMinimum(i), pCat->GetMaximum(i), FieldUnit::NONE);
pMF->set_value(pCat->GetValue(i), FieldUnit::NONE);
pMF->set_help_id(aCatMf2Hid[nCategory][i]);
}
}
// activate the CheckBox and the associated MetricField if we're dealing with the brackets menu
bActive = nCategory == 5;
m_xCheckBox1->set_visible(bActive);
m_xCheckBox1->set_sensitive(bActive);
if (bActive)
{
m_xCheckBox1->set_active(bScaleAllBrackets);
bool bChecked = m_xCheckBox1->get_active();
m_xFixedText4->set_sensitive( bChecked );
m_xMetricField4->set_sensitive( bChecked );
}
m_xMenuButton->set_item_active("menuitem" + OUString::number(nCategory + 1), true);
m_xFrame->set_label(m_xCategories[nCategory]->GetName());
nActiveCategory = nCategory;
m_xMetricField1->grab_focus();
}
SmDistanceDialog::SmDistanceDialog(weld::Window *pParent)
: GenericDialogController(pParent, u"modules/smath/ui/spacingdialog.ui"_ustr, u"SpacingDialog"_ustr)
, m_xFrame(m_xBuilder->weld_frame(u"template"_ustr))
, m_xFixedText1(m_xBuilder->weld_label(u"label1"_ustr))
, m_xMetricField1(m_xBuilder->weld_metric_spin_button(u"spinbutton1"_ustr, FieldUnit::CM))
, m_xFixedText2(m_xBuilder->weld_label(u"label2"_ustr))
, m_xMetricField2(m_xBuilder->weld_metric_spin_button(u"spinbutton2"_ustr, FieldUnit::CM))
, m_xFixedText3(m_xBuilder->weld_label(u"label3"_ustr))
, m_xMetricField3(m_xBuilder->weld_metric_spin_button(u"spinbutton3"_ustr, FieldUnit::CM))
, m_xCheckBox1(m_xBuilder->weld_check_button(u"checkbutton"_ustr))
, m_xFixedText4(m_xBuilder->weld_label(u"label4"_ustr))
, m_xMetricField4(m_xBuilder->weld_metric_spin_button(u"spinbutton4"_ustr, FieldUnit::CM))
, m_xMenuButton(m_xBuilder->weld_menu_button(u"category"_ustr))
, m_xDefaultButton(m_xBuilder->weld_button(u"default"_ustr))
, m_xBitmap(m_xBuilder->weld_widget(u"image"_ustr))
, m_pCurrentImage(m_xBitmap.get())
{
for (sal_uInt16 i = 0; i < NOCATEGORIES; ++i)
m_xCategories[i].reset( new SmCategoryDesc(*m_xBuilder, i) );
nActiveCategory = CATEGORY_NONE;
bScaleAllBrackets = false;
m_xMetricField1->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
m_xMetricField2->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
m_xMetricField3->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
m_xMetricField4->connect_focus_in(LINK(this, SmDistanceDialog, GetFocusHdl));
m_xCheckBox1->connect_toggled(LINK(this, SmDistanceDialog, CheckBoxClickHdl));
m_xMenuButton->connect_selected(LINK(this, SmDistanceDialog, MenuSelectHdl));
m_xDefaultButton->connect_clicked(LINK(this, SmDistanceDialog, DefaultButtonClickHdl));
//set the initial size, with max visible widgets visible, as preferred size
m_xDialog->set_size_request(-1, m_xDialog->get_preferred_size().Height());
}
SmDistanceDialog::~SmDistanceDialog()
{
}
void SmDistanceDialog::ReadFrom(const SmFormat &rFormat)
{
m_xCategories[0]->SetValue(0, rFormat.GetDistance(DIS_HORIZONTAL));
m_xCategories[0]->SetValue(1, rFormat.GetDistance(DIS_VERTICAL));
m_xCategories[0]->SetValue(2, rFormat.GetDistance(DIS_ROOT));
m_xCategories[1]->SetValue(0, rFormat.GetDistance(DIS_SUPERSCRIPT));
m_xCategories[1]->SetValue(1, rFormat.GetDistance(DIS_SUBSCRIPT));
m_xCategories[2]->SetValue(0, rFormat.GetDistance(DIS_NUMERATOR));
m_xCategories[2]->SetValue(1, rFormat.GetDistance(DIS_DENOMINATOR));
m_xCategories[3]->SetValue(0, rFormat.GetDistance(DIS_FRACTION));
m_xCategories[3]->SetValue(1, rFormat.GetDistance(DIS_STROKEWIDTH));
m_xCategories[4]->SetValue(0, rFormat.GetDistance(DIS_UPPERLIMIT));
m_xCategories[4]->SetValue(1, rFormat.GetDistance(DIS_LOWERLIMIT));
m_xCategories[5]->SetValue(0, rFormat.GetDistance(DIS_BRACKETSIZE));
m_xCategories[5]->SetValue(1, rFormat.GetDistance(DIS_BRACKETSPACE));
m_xCategories[5]->SetValue(3, rFormat.GetDistance(DIS_NORMALBRACKETSIZE));
m_xCategories[6]->SetValue(0, rFormat.GetDistance(DIS_MATRIXROW));
m_xCategories[6]->SetValue(1, rFormat.GetDistance(DIS_MATRIXCOL));
m_xCategories[7]->SetValue(0, rFormat.GetDistance(DIS_ORNAMENTSIZE));
m_xCategories[7]->SetValue(1, rFormat.GetDistance(DIS_ORNAMENTSPACE));
m_xCategories[8]->SetValue(0, rFormat.GetDistance(DIS_OPERATORSIZE));
m_xCategories[8]->SetValue(1, rFormat.GetDistance(DIS_OPERATORSPACE));
m_xCategories[9]->SetValue(0, rFormat.GetDistance(DIS_LEFTSPACE));
m_xCategories[9]->SetValue(1, rFormat.GetDistance(DIS_RIGHTSPACE));
m_xCategories[9]->SetValue(2, rFormat.GetDistance(DIS_TOPSPACE));
m_xCategories[9]->SetValue(3, rFormat.GetDistance(DIS_BOTTOMSPACE));
bScaleAllBrackets = rFormat.IsScaleNormalBrackets();
// force update (even of category 0) by setting nActiveCategory to a
// non-existent category number
nActiveCategory = CATEGORY_NONE;
SetCategory(0);
}
void SmDistanceDialog::WriteTo(SmFormat &rFormat) /*const*/
{
// TODO can they actually be different?
// if that's not the case 'const' could be used above!
SetCategory(nActiveCategory);
rFormat.SetDistance( DIS_HORIZONTAL, m_xCategories[0]->GetValue(0) );
rFormat.SetDistance( DIS_VERTICAL, m_xCategories[0]->GetValue(1) );
rFormat.SetDistance( DIS_ROOT, m_xCategories[0]->GetValue(2) );
rFormat.SetDistance( DIS_SUPERSCRIPT, m_xCategories[1]->GetValue(0) );
rFormat.SetDistance( DIS_SUBSCRIPT, m_xCategories[1]->GetValue(1) );
rFormat.SetDistance( DIS_NUMERATOR, m_xCategories[2]->GetValue(0) );
rFormat.SetDistance( DIS_DENOMINATOR, m_xCategories[2]->GetValue(1) );
rFormat.SetDistance( DIS_FRACTION, m_xCategories[3]->GetValue(0) );
rFormat.SetDistance( DIS_STROKEWIDTH, m_xCategories[3]->GetValue(1) );
rFormat.SetDistance( DIS_UPPERLIMIT, m_xCategories[4]->GetValue(0) );
rFormat.SetDistance( DIS_LOWERLIMIT, m_xCategories[4]->GetValue(1) );
rFormat.SetDistance( DIS_BRACKETSIZE, m_xCategories[5]->GetValue(0) );
rFormat.SetDistance( DIS_BRACKETSPACE, m_xCategories[5]->GetValue(1) );
rFormat.SetDistance( DIS_MATRIXROW, m_xCategories[6]->GetValue(0) );
rFormat.SetDistance( DIS_MATRIXCOL, m_xCategories[6]->GetValue(1) );
rFormat.SetDistance( DIS_ORNAMENTSIZE, m_xCategories[7]->GetValue(0) );
rFormat.SetDistance( DIS_ORNAMENTSPACE, m_xCategories[7]->GetValue(1) );
rFormat.SetDistance( DIS_OPERATORSIZE, m_xCategories[8]->GetValue(0) );
rFormat.SetDistance( DIS_OPERATORSPACE, m_xCategories[8]->GetValue(1) );
rFormat.SetDistance( DIS_LEFTSPACE, m_xCategories[9]->GetValue(0) );
rFormat.SetDistance( DIS_RIGHTSPACE, m_xCategories[9]->GetValue(1) );
rFormat.SetDistance( DIS_TOPSPACE, m_xCategories[9]->GetValue(2) );
rFormat.SetDistance( DIS_BOTTOMSPACE, m_xCategories[9]->GetValue(3) );
rFormat.SetDistance( DIS_NORMALBRACKETSIZE, m_xCategories[5]->GetValue(3) );
rFormat.SetScaleNormalBrackets( bScaleAllBrackets );
rFormat.RequestApplyChanges();
}
IMPL_LINK_NOARG( SmAlignDialog, DefaultButtonClickHdl, weld::Button&, void )
{
SaveDefaultsQuery aQuery(m_xDialog.get());
if (aQuery.run() == RET_YES)
{
auto* config = SmModule::get()->GetConfig();
SmFormat aFmt(config->GetStandardFormat());
WriteTo( aFmt );
config->SetStandardFormat(aFmt);
}
}
SmAlignDialog::SmAlignDialog(weld::Window* pParent)
: GenericDialogController(pParent, u"modules/smath/ui/alignmentdialog.ui"_ustr, u"AlignmentDialog"_ustr)
, m_xLeft(m_xBuilder->weld_radio_button(u"left"_ustr))
, m_xCenter(m_xBuilder->weld_radio_button(u"center"_ustr))
, m_xRight(m_xBuilder->weld_radio_button(u"right"_ustr))
, m_xDefaultButton(m_xBuilder->weld_button(u"default"_ustr))
{
m_xDefaultButton->connect_clicked(LINK(this, SmAlignDialog, DefaultButtonClickHdl));
}
SmAlignDialog::~SmAlignDialog()
{
}
void SmAlignDialog::ReadFrom(const SmFormat &rFormat)
{
switch (rFormat.GetHorAlign())
{
case SmHorAlign::Left:
m_xLeft->set_active(true);
break;
case SmHorAlign::Center:
m_xCenter->set_active(true);
break;
case SmHorAlign::Right:
m_xRight->set_active(true);
break;
}
}
void SmAlignDialog::WriteTo(SmFormat &rFormat) const
{
if (m_xLeft->get_active())
rFormat.SetHorAlign(SmHorAlign::Left);
else if (m_xRight->get_active())
rFormat.SetHorAlign(SmHorAlign::Right);
else
rFormat.SetHorAlign(SmHorAlign::Center);
rFormat.RequestApplyChanges();
}
SmShowSymbolSet::SmShowSymbolSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow, SmViewShell &rViewShell)
: m_rViewShell(rViewShell)
, nLen(0)
, nRows(0)
, nColumns(0)
, nXOffset(0)
, nYOffset(0)
, nSelectSymbol(SYMBOL_NONE)
, m_xScrolledWindow(std::move(pScrolledWindow))
{
m_xScrolledWindow->connect_vadjustment_changed(LINK(this, SmShowSymbolSet, ScrollHdl));
}
Point SmShowSymbolSet::OffsetPoint(const Point &rPoint) const
{
return Point(rPoint.X() + nXOffset, rPoint.Y() + nYOffset);
}
void SmShowSymbolSet::Resize()
{
CustomWidgetController::Resize();
Size aWinSize(GetOutputSizePixel());
if (aWinSize != m_aOldSize)
{
calccols(GetDrawingArea()->get_ref_device());
m_aOldSize = aWinSize;
}
}
void SmShowSymbolSet::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
{
Color aBackgroundColor;
Color aTextColor;
lclGetSettingColors(aBackgroundColor, aTextColor);
rRenderContext.SetBackground(Wallpaper(aBackgroundColor));
rRenderContext.SetTextColor(aTextColor);
rRenderContext.Push(vcl::PushFlags::MAPMODE);
// set MapUnit for which 'nLen' has been calculated
rRenderContext.SetMapMode(MapMode(MapUnit::MapPixel));
sal_uInt16 v = sal::static_int_cast< sal_uInt16 >(m_xScrolledWindow->vadjustment_get_value() * nColumns);
size_t nSymbols = aSymbolSet.size();
Color aTxtColor(rRenderContext.GetTextColor());
for (size_t i = v; i < nSymbols ; i++)
{
SmSym aSymbol(*aSymbolSet[i]);
vcl::Font aFont(lclGetSymbolFont(m_rViewShell, aSymbol));
aFont.SetAlignment(ALIGN_TOP);
// taking a FontSize which is a bit smaller (compared to nLen) in order to have a buffer
// (hopefully enough for left and right, too)
aFont.SetFontSize(Size(0, nLen - (nLen / 3)));
rRenderContext.SetFont(aFont);
// keep text color
rRenderContext.SetTextColor(aTxtColor);
int nIV = i - v;
sal_UCS4 cChar = aSymbol.GetCharacter();
OUString aText(&cChar, 1);
Size aSize(rRenderContext.GetTextWidth( aText ), rRenderContext.GetTextHeight());
Point aPoint((nIV % nColumns) * nLen + (nLen - aSize.Width()) / 2,
(nIV / nColumns) * nLen + (nLen - aSize.Height()) / 2);
rRenderContext.DrawText(OffsetPoint(aPoint), aText);
}
if (nSelectSymbol != SYMBOL_NONE)
{
Point aPoint(((nSelectSymbol - v) % nColumns) * nLen,
((nSelectSymbol - v) / nColumns) * nLen);
rRenderContext.Invert(tools::Rectangle(OffsetPoint(aPoint), Size(nLen, nLen)));
}
rRenderContext.Pop();
}
bool SmShowSymbolSet::MouseButtonDown(const MouseEvent& rMEvt)
{
GrabFocus();
Size aOutputSize(nColumns * nLen, nRows * nLen);
aOutputSize.AdjustWidth(nXOffset );
aOutputSize.AdjustHeight(nYOffset );
Point aPoint(rMEvt.GetPosPixel());
aPoint.AdjustX( -nXOffset );
aPoint.AdjustY( -nYOffset );
if (rMEvt.IsLeft() && tools::Rectangle(Point(0, 0), aOutputSize).Contains(rMEvt.GetPosPixel()))
{
tools::Long nPos = (aPoint.Y() / nLen) * nColumns + (aPoint.X() / nLen) +
m_xScrolledWindow->vadjustment_get_value() * nColumns;
SelectSymbol( sal::static_int_cast< sal_uInt16 >(nPos) );
aSelectHdlLink.Call(*this);
if (rMEvt.GetClicks() > 1)
aDblClickHdlLink.Call(*this);
}
return true;
}
bool SmShowSymbolSet::KeyInput(const KeyEvent& rKEvt)
{
sal_uInt16 n = nSelectSymbol;
if (n != SYMBOL_NONE)
{
switch (rKEvt.GetKeyCode().GetCode())
{
case KEY_DOWN: n = n + nColumns; break;
case KEY_UP: n = n - nColumns; break;
case KEY_LEFT: n -= 1; break;
case KEY_RIGHT: n += 1; break;
case KEY_HOME: n = 0; break;
case KEY_END: n = static_cast< sal_uInt16 >(aSymbolSet.size() - 1); break;
case KEY_PAGEUP: n -= nColumns * nRows; break;
case KEY_PAGEDOWN: n += nColumns * nRows; break;
default:
return false;
}
}
else
n = 0;
if (n >= aSymbolSet.size())
n = nSelectSymbol;
// adjust scrollbar
if ((n < sal::static_int_cast<sal_uInt16>(m_xScrolledWindow->vadjustment_get_value() * nColumns)) ||
(n >= sal::static_int_cast<sal_uInt16>((m_xScrolledWindow->vadjustment_get_value() + nRows) * nColumns)))
{
m_xScrolledWindow->vadjustment_set_value(n / nColumns);
Invalidate();
}
SelectSymbol(n);
aSelectHdlLink.Call(*this);
return true;
}
void SmShowSymbolSet::calccols(const vcl::RenderContext& rRenderContext)
{
// Height of 16pt in pixels (matching 'aOutputSize')
nLen = rRenderContext.LogicToPixel(Size(0, 16), MapMode(MapUnit::MapPoint)).Height();
Size aOutputSize(GetOutputSizePixel());
nColumns = aOutputSize.Width() / nLen;
nRows = aOutputSize.Height() / nLen;
nColumns = std::max<tools::Long>(1, nColumns);
nRows = std::max<tools::Long>(1, nRows);
nXOffset = (aOutputSize.Width() - (nColumns * nLen)) / 2;
nYOffset = (aOutputSize.Height() - (nRows * nLen)) / 2;
SetScrollBarRange();
}
void SmShowSymbolSet::SetSymbolSet(const SymbolPtrVec_t & rSymbolSet)
{
aSymbolSet = rSymbolSet;
SetScrollBarRange();
Invalidate();
}
void SmShowSymbolSet::SetScrollBarRange()
{
const int nLastRow = (aSymbolSet.size() - 1 + nColumns) / nColumns;
m_xScrolledWindow->vadjustment_configure(m_xScrolledWindow->vadjustment_get_value(), 0, nLastRow, 1, nRows - 1, nRows);
Invalidate();
}
void SmShowSymbolSet::SelectSymbol(sal_uInt16 nSymbol)
{
int v = m_xScrolledWindow->vadjustment_get_value() * nColumns;
if (nSelectSymbol != SYMBOL_NONE && nColumns)
{
Point aPoint(OffsetPoint(Point(((nSelectSymbol - v) % nColumns) * nLen,
((nSelectSymbol - v) / nColumns) * nLen)));
Invalidate(tools::Rectangle(aPoint, Size(nLen, nLen)));
}
if (nSymbol < aSymbolSet.size())
nSelectSymbol = nSymbol;
if (aSymbolSet.empty())
nSelectSymbol = SYMBOL_NONE;
if (nSelectSymbol != SYMBOL_NONE && nColumns)
{
Point aPoint(OffsetPoint(Point(((nSelectSymbol - v) % nColumns) * nLen,
((nSelectSymbol - v) / nColumns) * nLen)));
Invalidate(tools::Rectangle(aPoint, Size(nLen, nLen)));
}
if (!nColumns)
Invalidate();
}
IMPL_LINK_NOARG(SmShowSymbolSet, ScrollHdl, weld::ScrolledWindow&, void)
{
Invalidate();
}
SmShowSymbol::SmShowSymbol(SmViewShell& rViewShell)
: m_rViewShell(rViewShell)
{
}
void SmShowSymbol::setFontSize(vcl::Font &rFont) const
{
Size aSize(GetOutputSizePixel());
rFont.SetFontSize(Size(0, aSize.Height() - aSize.Height() / 3));
}
void SmShowSymbol::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
{
Color aBackgroundColor;
Color aTextColor;
lclGetSettingColors(aBackgroundColor, aTextColor);
rRenderContext.SetBackground(Wallpaper(aBackgroundColor));
rRenderContext.SetTextColor(aTextColor);
rRenderContext.Erase();
vcl::Font aFont(GetFont());
setFontSize(aFont);
rRenderContext.SetFont(aFont);
const OUString &rText = GetText();
Size aTextSize(rRenderContext.GetTextWidth(rText), rRenderContext.GetTextHeight());
rRenderContext.DrawText(Point((rRenderContext.GetOutputSize().Width() - aTextSize.Width()) / 2,
(rRenderContext.GetOutputSize().Height() * 7 / 10)), rText);
}
bool SmShowSymbol::MouseButtonDown(const MouseEvent& rMEvt)
{
if (rMEvt.GetClicks() > 1)
aDblClickHdlLink.Call(*this);
return true;
}
void SmShowSymbol::SetSymbol(const SmSym *pSymbol)
{
if (pSymbol)
{
vcl::Font aFont(lclGetSymbolFont(m_rViewShell, *pSymbol));
aFont.SetAlignment(ALIGN_BASELINE);
SetFont(aFont);
sal_UCS4 cChar = pSymbol->GetCharacter();
OUString aText(&cChar, 1);
SetText( aText );
}
Invalidate();
}
void SmSymbolDialog::FillSymbolSets()
// populate the entries of possible SymbolsSets in the dialog with
// current values of the SymbolSet manager but selects none of those
{
m_xSymbolSets->clear();
m_xSymbolSets->set_active(-1);
std::set< OUString > aSymbolSetNames( m_rSymbolMgr.GetSymbolSetNames() );
for (const auto& rSymbolSetName : aSymbolSetNames)
m_xSymbolSets->append_text(rSymbolSetName);
}
IMPL_LINK_NOARG( SmSymbolDialog, SymbolSetChangeHdl, weld::ComboBox&, void )
{
SelectSymbolSet(m_xSymbolSets->get_active_text());
}
IMPL_LINK_NOARG( SmSymbolDialog, SymbolChangeHdl, SmShowSymbolSet&, void )
{
SelectSymbol(m_xSymbolSetDisplay->GetSelectSymbol());
}
IMPL_LINK_NOARG(SmSymbolDialog, EditClickHdl, weld::Button&, void)
{
SmSymDefineDialog aDialog(m_xDialog.get(), m_pFontListDev, m_rSymbolMgr);
// set current symbol and SymbolSet for the new dialog
const OUString aSymSetName (m_xSymbolSets->get_active_text()),
aSymName (m_xSymbolName->get_label());
aDialog.SelectOldSymbolSet(aSymSetName);
aDialog.SelectOldSymbol(aSymName);
aDialog.SelectSymbolSet(aSymSetName);
aDialog.SelectSymbol(aSymName);
// remember old SymbolSet
OUString aOldSymbolSet (m_xSymbolSets->get_active_text());
sal_uInt16 nSymPos = m_xSymbolSetDisplay->GetSelectSymbol();
// adapt dialog to data of the SymbolSet manager, which might have changed
if (aDialog.run() == RET_OK && m_rSymbolMgr.IsModified())
{
m_rSymbolMgr.Save();
FillSymbolSets();
}
// if the old SymbolSet doesn't exist anymore, go to the first one SymbolSet (if one exists)
if (!SelectSymbolSet(aOldSymbolSet) && m_xSymbolSets->get_count() > 0)
SelectSymbolSet(m_xSymbolSets->get_text(0));
else
{
// just update display of current symbol set
assert(m_aSymbolSetName == aSymSetName); //unexpected change in symbol set name
m_aSymbolSet = m_rSymbolMgr.GetSymbolSet( m_aSymbolSetName );
m_xSymbolSetDisplay->SetSymbolSet( m_aSymbolSet );
}
if (nSymPos >= m_aSymbolSet.size())
nSymPos = static_cast< sal_uInt16 >(m_aSymbolSet.size()) - 1;
SelectSymbol( nSymPos );
}
IMPL_LINK_NOARG( SmSymbolDialog, SymbolDblClickHdl2, SmShowSymbolSet&, void )
{
SymbolDblClickHdl();
}
IMPL_LINK_NOARG( SmSymbolDialog, SymbolDblClickHdl, SmShowSymbol&, void )
{
SymbolDblClickHdl();
}
void SmSymbolDialog::SymbolDblClickHdl()
{
GetClickHdl(*m_xGetBtn);
m_xDialog->response(RET_OK);
}
IMPL_LINK_NOARG(SmSymbolDialog, GetClickHdl, weld::Button&, void)
{
const SmSym *pSym = GetSymbol();
if (pSym)
{
OUString aText = "%" + pSym->GetUiName() + " ";
m_rViewSh.GetViewFrame().GetDispatcher()->ExecuteList(
SID_INSERTSPECIAL, SfxCallMode::RECORD,
{ new SfxStringItem(SID_INSERTSPECIAL, aText) });
}
}
SmSymbolDialog::SmSymbolDialog(weld::Window *pParent, OutputDevice *pFntListDevice,
SmSymbolManager &rMgr, SmViewShell &rViewShell)
: GenericDialogController(pParent, u"modules/smath/ui/catalogdialog.ui"_ustr, u"CatalogDialog"_ustr)
, m_rViewSh(rViewShell)
, m_rSymbolMgr(rMgr)
, m_pFontListDev(pFntListDevice)
, m_aSymbolDisplay(rViewShell)
, m_xSymbolSets(m_xBuilder->weld_combo_box(u"symbolset"_ustr))
, m_xSymbolSetDisplay(new SmShowSymbolSet(m_xBuilder->weld_scrolled_window(u"scrolledwindow"_ustr, true), rViewShell))
, m_xSymbolSetDisplayArea(new weld::CustomWeld(*m_xBuilder, u"symbolsetdisplay"_ustr, *m_xSymbolSetDisplay))
, m_xSymbolName(m_xBuilder->weld_label(u"symbolname"_ustr))
, m_xSymbolDisplay(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aSymbolDisplay))
, m_xGetBtn(m_xBuilder->weld_button(u"ok"_ustr))
, m_xEditBtn(m_xBuilder->weld_button(u"edit"_ustr))
{
m_xSymbolSets->make_sorted();
m_aSymbolSetName.clear();
m_aSymbolSet.clear();
FillSymbolSets();
if (m_xSymbolSets->get_count() > 0)
SelectSymbolSet(m_xSymbolSets->get_text(0));
m_xSymbolSets->connect_changed(LINK(this, SmSymbolDialog, SymbolSetChangeHdl));
m_xSymbolSetDisplay->SetSelectHdl(LINK(this, SmSymbolDialog, SymbolChangeHdl));
m_xSymbolSetDisplay->SetDblClickHdl(LINK(this, SmSymbolDialog, SymbolDblClickHdl2));
m_aSymbolDisplay.SetDblClickHdl(LINK(this, SmSymbolDialog, SymbolDblClickHdl));
m_xEditBtn->connect_clicked(LINK(this, SmSymbolDialog, EditClickHdl));
m_xGetBtn->connect_clicked(LINK(this, SmSymbolDialog, GetClickHdl));
}
SmSymbolDialog::~SmSymbolDialog()
{
}
bool SmSymbolDialog::SelectSymbolSet(const OUString &rSymbolSetName)
{
bool bRet = false;
sal_Int32 nPos = m_xSymbolSets->find_text(rSymbolSetName);
m_aSymbolSetName.clear();
m_aSymbolSet.clear();
if (nPos != -1)
{
m_xSymbolSets->set_active(nPos);
m_aSymbolSetName = rSymbolSetName;
m_aSymbolSet = m_rSymbolMgr.GetSymbolSet( m_aSymbolSetName );
// sort symbols by Unicode position (useful for displaying Greek characters alphabetically)
std::sort( m_aSymbolSet.begin(), m_aSymbolSet.end(),
[](const SmSym *pSym1, const SmSym *pSym2)
{
return pSym1->GetCharacter() < pSym2->GetCharacter();
} );
const bool bEmptySymbolSet = m_aSymbolSet.empty();
m_xSymbolSetDisplay->SetSymbolSet( m_aSymbolSet );
if (!bEmptySymbolSet)
SelectSymbol(0);
bRet = true;
}
else
m_xSymbolSets->set_active(-1);
return bRet;
}
void SmSymbolDialog::SelectSymbol(sal_uInt16 nSymbolNo)
{
const SmSym *pSym = nullptr;
if (!m_aSymbolSetName.isEmpty() && nSymbolNo < static_cast< sal_uInt16 >(m_aSymbolSet.size()))
pSym = m_aSymbolSet[ nSymbolNo ];
m_xSymbolSetDisplay->SelectSymbol(nSymbolNo);
m_aSymbolDisplay.SetSymbol(pSym);
m_xSymbolName->set_label(pSym ? pSym->GetUiName() : OUString());
}
const SmSym* SmSymbolDialog::GetSymbol() const
{
sal_uInt16 nSymbolNo = m_xSymbolSetDisplay->GetSelectSymbol();
bool bValid = !m_aSymbolSetName.isEmpty() && nSymbolNo < static_cast< sal_uInt16 >(m_aSymbolSet.size());
return bValid ? m_aSymbolSet[ nSymbolNo ] : nullptr;
}
void SmShowChar::Resize()
{
const OUString &rText = GetText();
if (rText.isEmpty())
return;
sal_UCS4 cChar = rText.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
SetSymbol(cChar, GetFont()); //force recalculation of size
}
void SmShowChar::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
{
Color aTextCol = rRenderContext.GetTextColor();
Color aFillCol = rRenderContext.GetFillColor();
const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
const Color aWindowTextColor(rStyleSettings.GetDialogTextColor());
const Color aWindowColor(rStyleSettings.GetWindowColor());
rRenderContext.SetTextColor(aWindowTextColor);
rRenderContext.SetFillColor(aWindowColor);
Size aSize(GetOutputSizePixel());
rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize));
OUString aText(GetText());
if (!aText.isEmpty())
{
vcl::Font aFont(m_aFont);
aFont.SetAlignment(ALIGN_TOP);
rRenderContext.SetFont(aFont);
Size aTextSize(rRenderContext.GetTextWidth(aText), rRenderContext.GetTextHeight());
rRenderContext.DrawText(Point((aSize.Width() - aTextSize.Width()) / 2,
(aSize.Height() - aTextSize.Height()) / 2), aText);
}
rRenderContext.SetTextColor(aTextCol);
rRenderContext.SetFillColor(aFillCol);
}
void SmShowChar::SetSymbol( const SmSym *pSym )
{
if (pSym)
SetSymbol( pSym->GetCharacter(), pSym->GetFace() );
}
void SmShowChar::SetSymbol( sal_UCS4 cChar, const vcl::Font &rFont )
{
vcl::Font aFont( rFont );
Size aSize(GetOutputSizePixel());
aFont.SetFontSize(Size(0, aSize.Height() - aSize.Height() / 3));
aFont.SetAlignment(ALIGN_BASELINE);
SetFont(aFont);
OUString aText(&cChar, 1);
SetText( aText );
Invalidate();
}
void SmSymDefineDialog::FillSymbols(weld::ComboBox& rComboBox, bool bDeleteText)
{
assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong ComboBox");
rComboBox.clear();
if (bDeleteText)
rComboBox.set_entry_text(OUString());
weld::ComboBox& rBox = &rComboBox == m_xOldSymbols.get() ? *m_xOldSymbolSets : *m_xSymbolSets;
SymbolPtrVec_t aSymSet(m_aSymbolMgrCopy.GetSymbolSet(rBox.get_active_text()));
for (const SmSym* i : aSymSet)
rComboBox.append_text(i->GetUiName());
}
void SmSymDefineDialog::FillSymbolSets(weld::ComboBox& rComboBox, bool bDeleteText)
{
assert((&rComboBox == m_xOldSymbolSets.get() || &rComboBox == m_xSymbolSets.get()) && "Sm : wrong ComboBox");
rComboBox.clear();
if (bDeleteText)
rComboBox.set_entry_text(OUString());
const std::set< OUString > aSymbolSetNames( m_aSymbolMgrCopy.GetSymbolSetNames() );
for (const auto& rSymbolSetName : aSymbolSetNames)
rComboBox.append_text(rSymbolSetName);
}
void SmSymDefineDialog::FillFonts()
{
m_xFonts->clear();
m_xFonts->set_active(-1);
// Include all fonts of FontList into the font list.
// If there are duplicates, only include one entry of each font since the style will be
// already selected using the FontStyleBox.
if (m_xFontList)
{
sal_uInt16 nCount = m_xFontList->GetFontNameCount();
for (sal_uInt16 i = 0; i < nCount; ++i)
m_xFonts->append_text(m_xFontList->GetFontName(i).GetFamilyName());
}
}
void SmSymDefineDialog::FillStyles()
{
m_xStyles->clear();
// pStyles->SetText(OUString());
OUString aText(m_xFonts->get_active_text());
if (!aText.isEmpty())
{
// use own StyleNames
const SmFontStyles &rStyles = GetFontStyles();
for (sal_uInt16 i = 0; i < SmFontStyles::GetCount(); ++i)
m_xStyles->append_text(rStyles.GetStyleName(i));
assert(m_xStyles->get_count() > 0 && "Sm : no styles available");
m_xStyles->set_active(0);
}
}
SmSym* SmSymDefineDialog::GetSymbol(const weld::ComboBox& rComboBox)
{
assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong combobox");
return m_aSymbolMgrCopy.GetSymbolByUiName(rComboBox.get_active_text());
}
IMPL_LINK(SmSymDefineDialog, OldSymbolChangeHdl, weld::ComboBox&, rComboBox, void)
{
(void) rComboBox;
assert(&rComboBox == m_xOldSymbols.get() && "Sm : wrong argument");
SelectSymbol(*m_xOldSymbols, m_xOldSymbols->get_active_text(), false);
}
IMPL_LINK( SmSymDefineDialog, OldSymbolSetChangeHdl, weld::ComboBox&, rComboBox, void )
{
(void) rComboBox;
assert(&rComboBox == m_xOldSymbolSets.get() && "Sm : wrong argument");
SelectSymbolSet(*m_xOldSymbolSets, m_xOldSymbolSets->get_active_text(), false);
}
IMPL_LINK(SmSymDefineDialog, ModifyHdl, weld::ComboBox&, rComboBox, void)
{
// remember cursor position for later restoring of it
int nStartPos, nEndPos;
rComboBox.get_entry_selection_bounds(nStartPos, nEndPos);
if (&rComboBox == m_xSymbols.get())
SelectSymbol(*m_xSymbols, m_xSymbols->get_active_text(), false);
else if (&rComboBox == m_xSymbolSets.get())
SelectSymbolSet(*m_xSymbolSets, m_xSymbolSets->get_active_text(), false);
else if (&rComboBox == m_xOldSymbols.get())
// allow only names from the list
SelectSymbol(*m_xOldSymbols, m_xOldSymbols->get_active_text(), true);
else if (&rComboBox == m_xOldSymbolSets.get())
// allow only names from the list
SelectSymbolSet(*m_xOldSymbolSets, m_xOldSymbolSets->get_active_text(), true);
else if (&rComboBox == m_xStyles.get())
// allow only names from the list (that's the case here anyway)
SelectStyle(m_xStyles->get_active_text(), true);
else
SAL_WARN("starmath", "wrong combobox argument");
rComboBox.select_entry_region(nStartPos, nEndPos);
UpdateButtons();
}
IMPL_LINK(SmSymDefineDialog, FontChangeHdl, weld::ComboBox&, rListBox, void)
{
(void) rListBox;
assert(&rListBox == m_xFonts.get() && "Sm : wrong argument");
SelectFont(m_xFonts->get_active_text());
}
IMPL_LINK_NOARG(SmSymDefineDialog, SubsetChangeHdl, weld::ComboBox&, void)
{
int nPos = m_xFontsSubsetLB->get_active();
if (nPos != -1)
{
const Subset* pSubset = weld::fromId<const Subset*>(m_xFontsSubsetLB->get_active_id());
if (pSubset)
{
m_xCharsetDisplay->SelectCharacter( pSubset->GetRangeMin() );
}
}
}
IMPL_LINK( SmSymDefineDialog, StyleChangeHdl, weld::ComboBox&, rComboBox, void )
{
(void) rComboBox;
assert(&rComboBox == m_xStyles.get() && "Sm : wrong argument");
SelectStyle(m_xStyles->get_active_text());
}
IMPL_LINK_NOARG(SmSymDefineDialog, CharHighlightHdl, SvxShowCharSet*, void)
{
sal_UCS4 cChar = m_xCharsetDisplay->GetSelectCharacter();
if (m_xSubsetMap)
{
const Subset* pSubset = m_xSubsetMap->GetSubsetByUnicode(cChar);
if (pSubset)
m_xFontsSubsetLB->set_active_text(pSubset->GetName());
else
m_xFontsSubsetLB->set_active(-1);
}
m_aSymbolDisplay.SetSymbol(cChar, m_xCharsetDisplay->GetFont());
UpdateButtons();
// display Unicode position as symbol name while iterating over characters
const OUString aHex(OUString::number(cChar, 16).toAsciiUpperCase());
const OUString aPattern( (aHex.getLength() > 4) ? u"Ux000000"_ustr : u"Ux0000"_ustr );
OUString aUnicodePos = aPattern.subView( 0, aPattern.getLength() - aHex.getLength() ) +
aHex;
m_xSymbols->set_entry_text(aUnicodePos);
m_xSymbolName->set_label(aUnicodePos);
}
IMPL_LINK( SmSymDefineDialog, AddClickHdl, weld::Button&, rButton, void )
{
(void) rButton;
assert(&rButton == m_xAddBtn.get() && "Sm : wrong argument");
assert(rButton.get_sensitive() && "Sm : requirements met ??");
// add symbol
const SmSym aNewSymbol(m_xSymbols->get_active_text(), m_xCharsetDisplay->GetFont(),
m_xCharsetDisplay->GetSelectCharacter(), m_xSymbolSets->get_active_text());
//OSL_ENSURE( m_aSymbolMgrCopy.GetSymbolByUiName(aTmpSymbolName) == NULL, "symbol already exists" );
m_aSymbolMgrCopy.AddOrReplaceSymbol( aNewSymbol );
// update display of new symbol
m_aSymbolDisplay.SetSymbol( &aNewSymbol );
m_xSymbolName->set_label(aNewSymbol.GetUiName());
m_xSymbolSetName->set_label(aNewSymbol.GetSymbolSetName());
// update list box entries
FillSymbolSets(*m_xOldSymbolSets, false);
FillSymbolSets(*m_xSymbolSets, false);
FillSymbols(*m_xOldSymbols, false);
FillSymbols(*m_xSymbols, false);
UpdateButtons();
}
IMPL_LINK( SmSymDefineDialog, ChangeClickHdl, weld::Button&, rButton, void )
{
(void) rButton;
assert(&rButton == m_xChangeBtn.get() && "Sm : wrong argument");
assert(m_xChangeBtn->get_sensitive() && "Sm : requirements met ??");
// get new Symbol to use
//! get font from symbol-disp lay since charset-display does not keep
//! the bold attribute.
const SmSym aNewSymbol(m_xSymbols->get_active_text(), m_xCharsetDisplay->GetFont(),
m_xCharsetDisplay->GetSelectCharacter(), m_xSymbolSets->get_active_text());
// remove old symbol if the name was changed then add new one
const bool bNameChanged = m_xOldSymbols->get_active_text() != m_xSymbols->get_active_text();
if (bNameChanged)
m_aSymbolMgrCopy.RemoveSymbol(m_xOldSymbols->get_active_text());
m_aSymbolMgrCopy.AddOrReplaceSymbol( aNewSymbol, true );
// clear display for original symbol if necessary
if (bNameChanged)
SetOrigSymbol(nullptr, OUString());
// update display of new symbol
m_aSymbolDisplay.SetSymbol(&aNewSymbol);
m_xSymbolName->set_label(aNewSymbol.GetUiName());
m_xSymbolSetName->set_label(aNewSymbol.GetSymbolSetName());
// update list box entries
FillSymbolSets(*m_xOldSymbolSets, false);
FillSymbolSets(*m_xSymbolSets, false);
FillSymbols(*m_xOldSymbols, false);
FillSymbols(*m_xSymbols, false);
UpdateButtons();
}
IMPL_LINK(SmSymDefineDialog, DeleteClickHdl, weld::Button&, rButton, void)
{
(void) rButton;
assert(&rButton == m_xDeleteBtn.get() && "Sm : wrong argument");
assert(m_xDeleteBtn->get_sensitive() && "Sm : requirements met ??");
if (m_xOrigSymbol)
{
m_aSymbolMgrCopy.RemoveSymbol(m_xOrigSymbol->GetUiName());
// clear display for original symbol
SetOrigSymbol(nullptr, OUString());
// update list box entries
FillSymbolSets(*m_xOldSymbolSets, false);
FillSymbolSets(*m_xSymbolSets, false);
FillSymbols(*m_xOldSymbols ,false);
FillSymbols(*m_xSymbols ,false);
}
UpdateButtons();
}
void SmSymDefineDialog::UpdateButtons()
{
bool bAdd = false,
bChange = false,
bDelete = false;
OUString aTmpSymbolName(m_xSymbols->get_active_text()),
aTmpSymbolSetName(m_xSymbolSets->get_active_text());
if (!aTmpSymbolName.isEmpty() && !aTmpSymbolSetName.isEmpty())
{
// are all settings equal?
//! (Font-, Style- and SymbolSet name comparison is not case sensitive)
bool bEqual = m_xOrigSymbol
&& aTmpSymbolSetName.equalsIgnoreAsciiCase(m_xOldSymbolSetName->get_label())
&& aTmpSymbolName == m_xOrigSymbol->GetUiName()
&& m_xFonts->get_active_text().equalsIgnoreAsciiCase(
m_xOrigSymbol->GetFace().GetFamilyName())
&& m_xStyles->get_active_text().equalsIgnoreAsciiCase(
GetFontStyles().GetStyleName(m_xOrigSymbol->GetFace()))
&& m_xCharsetDisplay->GetSelectCharacter() == m_xOrigSymbol->GetCharacter();
// only add it if there isn't already a symbol with the same name
bAdd = m_aSymbolMgrCopy.GetSymbolByUiName(aTmpSymbolName) == nullptr;
// only delete it if all settings are equal
bDelete = bool(m_xOrigSymbol);
// only change it if the old symbol exists and the new one is different
bChange = m_xOrigSymbol && !bEqual;
}
m_xAddBtn->set_sensitive(bAdd);
m_xChangeBtn->set_sensitive(bChange);
m_xDeleteBtn->set_sensitive(bDelete);
}
SmSymDefineDialog::SmSymDefineDialog(weld::Window* pParent, OutputDevice *pFntListDevice, SmSymbolManager &rMgr)
: GenericDialogController(pParent, u"modules/smath/ui/symdefinedialog.ui"_ustr, u"EditSymbols"_ustr)
, m_xVirDev(VclPtr<VirtualDevice>::Create())
, m_rSymbolMgr(rMgr)
, m_xFontList(new FontList(pFntListDevice))
, m_xOldSymbols(m_xBuilder->weld_combo_box(u"oldSymbols"_ustr))
, m_xOldSymbolSets(m_xBuilder->weld_combo_box(u"oldSymbolSets"_ustr))
, m_xSymbols(m_xBuilder->weld_combo_box(u"symbols"_ustr))
, m_xSymbolSets(m_xBuilder->weld_combo_box(u"symbolSets"_ustr))
, m_xFonts(m_xBuilder->weld_combo_box(u"fonts"_ustr))
, m_xFontsSubsetLB(m_xBuilder->weld_combo_box(u"fontsSubsetLB"_ustr))
, m_xStyles(m_xBuilder->weld_combo_box(u"styles"_ustr))
, m_xOldSymbolName(m_xBuilder->weld_label(u"oldSymbolName"_ustr))
, m_xOldSymbolSetName(m_xBuilder->weld_label(u"oldSymbolSetName"_ustr))
, m_xSymbolName(m_xBuilder->weld_label(u"symbolName"_ustr))
, m_xSymbolSetName(m_xBuilder->weld_label(u"symbolSetName"_ustr))
, m_xAddBtn(m_xBuilder->weld_button(u"add"_ustr))
, m_xChangeBtn(m_xBuilder->weld_button(u"modify"_ustr))
, m_xDeleteBtn(m_xBuilder->weld_button(u"delete"_ustr))
, m_xOldSymbolDisplay(new weld::CustomWeld(*m_xBuilder, u"oldSymbolDisplay"_ustr, m_aOldSymbolDisplay))
, m_xSymbolDisplay(new weld::CustomWeld(*m_xBuilder, u"symbolDisplay"_ustr, m_aSymbolDisplay))
, m_xCharsetDisplay(new SvxShowCharSet(m_xBuilder->weld_scrolled_window(u"showscroll"_ustr, true), m_xVirDev))
, m_xCharsetDisplayArea(new weld::CustomWeld(*m_xBuilder, u"charsetDisplay"_ustr, *m_xCharsetDisplay))
{
// auto completion is troublesome since that symbols character also gets automatically selected in the
// display and if the user previously selected a character to define/redefine that one this is bad
m_xOldSymbols->set_entry_completion(false);
m_xSymbols->set_entry_completion(false);
FillFonts();
if (m_xFonts->get_count() > 0)
SelectFont(m_xFonts->get_text(0));
SetSymbolSetManager(m_rSymbolMgr);
m_xOldSymbols->connect_changed(LINK(this, SmSymDefineDialog, OldSymbolChangeHdl));
m_xOldSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, OldSymbolSetChangeHdl));
m_xSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
m_xOldSymbolSets->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
m_xSymbols->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
m_xOldSymbols->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
m_xStyles->connect_changed(LINK(this, SmSymDefineDialog, ModifyHdl));
m_xFonts->connect_changed(LINK(this, SmSymDefineDialog, FontChangeHdl));
m_xFontsSubsetLB->connect_changed(LINK(this, SmSymDefineDialog, SubsetChangeHdl));
m_xStyles->connect_changed(LINK(this, SmSymDefineDialog, StyleChangeHdl));
m_xAddBtn->connect_clicked(LINK(this, SmSymDefineDialog, AddClickHdl));
m_xChangeBtn->connect_clicked(LINK(this, SmSymDefineDialog, ChangeClickHdl));
m_xDeleteBtn->connect_clicked(LINK(this, SmSymDefineDialog, DeleteClickHdl));
m_xCharsetDisplay->SetHighlightHdl( LINK( this, SmSymDefineDialog, CharHighlightHdl ) );
}
SmSymDefineDialog::~SmSymDefineDialog()
{
}
short SmSymDefineDialog::run()
{
short nResult = GenericDialogController::run();
// apply changes if dialog was closed by clicking OK
if (m_aSymbolMgrCopy.IsModified() && nResult == RET_OK)
m_rSymbolMgr = m_aSymbolMgrCopy;
return nResult;
}
void SmSymDefineDialog::SetSymbolSetManager(const SmSymbolManager &rMgr)
{
m_aSymbolMgrCopy = rMgr;
// Set the modified flag of the copy to false so that
// we can check later on if anything has been changed
m_aSymbolMgrCopy.SetModified(false);
FillSymbolSets(*m_xOldSymbolSets);
if (m_xOldSymbolSets->get_count() > 0)
SelectSymbolSet(m_xOldSymbolSets->get_text(0));
FillSymbolSets(*m_xSymbolSets);
if (m_xSymbolSets->get_count() > 0)
SelectSymbolSet(m_xSymbolSets->get_text(0));
FillSymbols(*m_xOldSymbols);
if (m_xOldSymbols->get_count() > 0)
SelectSymbol(m_xOldSymbols->get_text(0));
FillSymbols(*m_xSymbols);
if (m_xSymbols->get_count() > 0)
SelectSymbol(m_xSymbols->get_text(0));
UpdateButtons();
}
bool SmSymDefineDialog::SelectSymbolSet(weld::ComboBox& rComboBox,
std::u16string_view rSymbolSetName, bool bDeleteText)
{
assert((&rComboBox == m_xOldSymbolSets.get() || &rComboBox == m_xSymbolSets.get()) && "Sm : wrong ComboBox");
// trim SymbolName (no leading and trailing blanks)
OUString aNormName( comphelper::string::strip(rSymbolSetName, ' ') );
// and remove possible deviations within the input
rComboBox.set_entry_text(aNormName);
bool bRet = false;
int nPos = rComboBox.find_text(aNormName);
if (nPos != -1)
{
rComboBox.set_active(nPos);
bRet = true;
}
else if (bDeleteText)
rComboBox.set_entry_text(OUString());
bool bIsOld = &rComboBox == m_xOldSymbolSets.get();
// setting the SymbolSet name at the associated display
weld::Label& rFT = bIsOld ? *m_xOldSymbolSetName : *m_xSymbolSetName;
rFT.set_label(rComboBox.get_active_text());
// set the symbol name which belongs to the SymbolSet at the associated combobox
weld::ComboBox& rCB = bIsOld ? *m_xOldSymbols : *m_xSymbols;
FillSymbols(rCB, false);
// display a valid respectively no symbol when changing the SymbolSets
if (bIsOld)
{
OUString aTmpOldSymbolName;
if (m_xOldSymbols->get_count() > 0)
aTmpOldSymbolName = m_xOldSymbols->get_text(0);
SelectSymbol(*m_xOldSymbols, aTmpOldSymbolName, true);
}
UpdateButtons();
return bRet;
}
void SmSymDefineDialog::SetOrigSymbol(const SmSym *pSymbol,
const OUString &rSymbolSetName)
{
// clear old symbol
m_xOrigSymbol.reset();
OUString aSymName,
aSymSetName;
if (pSymbol)
{
// set new symbol
m_xOrigSymbol.reset(new SmSym(*pSymbol));
aSymName = pSymbol->GetUiName();
aSymSetName = rSymbolSetName;
m_aOldSymbolDisplay.SetSymbol( pSymbol );
}
else
{ // delete displayed symbols
m_aOldSymbolDisplay.SetText(OUString());
m_aOldSymbolDisplay.Invalidate();
}
m_xOldSymbolName->set_label(aSymName);
m_xOldSymbolSetName->set_label(aSymSetName);
}
bool SmSymDefineDialog::SelectSymbol(weld::ComboBox& rComboBox,
const OUString &rSymbolName, bool bDeleteText)
{
assert((&rComboBox == m_xOldSymbols.get() || &rComboBox == m_xSymbols.get()) && "Sm : wrong ComboBox");
// trim SymbolName (no blanks)
OUString aNormName = rSymbolName.replaceAll(" ", "");
// and remove possible deviations within the input
rComboBox.set_entry_text(aNormName);
bool bRet = false;
int nPos = rComboBox.find_text(aNormName);
bool bIsOld = &rComboBox == m_xOldSymbols.get();
if (nPos != -1)
{
rComboBox.set_active(nPos);
if (!bIsOld)
{
const SmSym *pSymbol = GetSymbol(*m_xSymbols);
if (pSymbol)
{
// choose font and style accordingly
const vcl::Font &rFont = pSymbol->GetFace();
SelectFont(rFont.GetFamilyName(), false);
SelectStyle(GetFontStyles().GetStyleName(rFont), false);
// Since setting the Font via the Style name of the SymbolFonts doesn't
// work really well (e.g. it can be empty even though the font itself is
// bold or italic) we're manually setting the Font with respect to the Symbol
m_xCharsetDisplay->SetFont(rFont);
m_aSymbolDisplay.SetFont(rFont);
// select associated character
SelectChar(pSymbol->GetCharacter());
// since SelectChar will also set the unicode point as text in the
// symbols box, we have to set the symbol name again to get that one displayed
m_xSymbols->set_entry_text(pSymbol->GetUiName());
}
}
bRet = true;
}
else if (bDeleteText)
rComboBox.set_entry_text(OUString());
if (bIsOld)
{
// if there's a change of the old symbol, show only the available ones, otherwise show none
const SmSym *pOldSymbol = nullptr;
OUString aTmpOldSymbolSetName;
if (nPos != -1)
{
pOldSymbol = m_aSymbolMgrCopy.GetSymbolByUiName(aNormName);
aTmpOldSymbolSetName = m_xOldSymbolSets->get_active_text();
}
SetOrigSymbol(pOldSymbol, aTmpOldSymbolSetName);
}
else
m_xSymbolName->set_label(rComboBox.get_active_text());
UpdateButtons();
return bRet;
}
void SmSymDefineDialog::SetFont(const OUString &rFontName, std::u16string_view rStyleName)
{
// get Font (FontInfo) matching name and style
FontMetric aFontMetric;
if (m_xFontList)
aFontMetric = m_xFontList->Get(rFontName, WEIGHT_NORMAL, ITALIC_NONE);
SetFontStyle(rStyleName, aFontMetric);
m_xCharsetDisplay->SetFont(aFontMetric);
m_aSymbolDisplay.SetFont(aFontMetric);
// update subset listbox for new font's unicode subsets
FontCharMapRef xFontCharMap = m_xCharsetDisplay->GetFontCharMap();
m_xSubsetMap.reset(new SubsetMap( xFontCharMap ));
m_xFontsSubsetLB->clear();
bool bFirst = true;
for (auto & subset : m_xSubsetMap->GetSubsetMap())
{
m_xFontsSubsetLB->append(weld::toId(&subset), subset.GetName());
// subset must live at least as long as the selected font !!!
if (bFirst)
m_xFontsSubsetLB->set_active(0);
bFirst = false;
}
if (bFirst)
m_xFontsSubsetLB->set_active(-1);
m_xFontsSubsetLB->set_sensitive(!bFirst);
}
bool SmSymDefineDialog::SelectFont(const OUString &rFontName, bool bApplyFont)
{
bool bRet = false;
int nPos = m_xFonts->find_text(rFontName);
if (nPos != -1)
{
m_xFonts->set_active(nPos);
if (m_xStyles->get_count() > 0)
SelectStyle(m_xStyles->get_text(0));
if (bApplyFont)
{
SetFont(m_xFonts->get_active_text(), m_xStyles->get_active_text());
m_aSymbolDisplay.SetSymbol(m_xCharsetDisplay->GetSelectCharacter(), m_xCharsetDisplay->GetFont());
}
bRet = true;
}
else
m_xFonts->set_active(-1);
FillStyles();
UpdateButtons();
return bRet;
}
bool SmSymDefineDialog::SelectStyle(const OUString &rStyleName, bool bApplyFont)
{
bool bRet = false;
int nPos = m_xStyles->find_text(rStyleName);
// if the style is not available take the first available one (if existent)
if (nPos == -1 && m_xStyles->get_count() > 0)
nPos = 0;
if (nPos != -1)
{
m_xStyles->set_active(nPos);
if (bApplyFont)
{
SetFont(m_xFonts->get_active_text(), m_xStyles->get_active_text());
m_aSymbolDisplay.SetSymbol(m_xCharsetDisplay->GetSelectCharacter(), m_xCharsetDisplay->GetFont());
}
bRet = true;
}
else
m_xStyles->set_entry_text(OUString());
UpdateButtons();
return bRet;
}
void SmSymDefineDialog::SelectChar(sal_Unicode cChar)
{
m_xCharsetDisplay->SelectCharacter( cChar );
m_aSymbolDisplay.SetSymbol(cChar, m_xCharsetDisplay->GetFont());
UpdateButtons();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */