/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace css::uno; using namespace css::frame; using namespace css::text; using namespace css::beans; using namespace css::style; using namespace css::view; using namespace css::lang; using namespace css::container; SFX_IMPL_CHILDWINDOW(SvxRubyChildWindow, SID_RUBY_DIALOG); namespace { constexpr OUString cRubyBaseText = u"RubyBaseText"_ustr; constexpr OUString cRubyText = u"RubyText"_ustr; constexpr OUString cRubyAdjust = u"RubyAdjust"_ustr; constexpr OUString cRubyPosition = u"RubyPosition"_ustr; constexpr OUString cRubyCharStyleName = u"RubyCharStyleName"_ustr; } // end anonymous namespace SvxRubyChildWindow::SvxRubyChildWindow(vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo const* pInfo) : SfxChildWindow(_pParent, nId) { auto xDlg = std::make_shared(pBindings, this, _pParent->GetFrameWeld()); SetController(xDlg); xDlg->Initialize(pInfo); } SfxChildWinInfo SvxRubyChildWindow::GetInfo() const { return SfxChildWindow::GetInfo(); } class SvxRubyData_Impl : public cppu::WeakImplHelper { Reference xModel; Reference xSelection; Sequence aRubyValues; Reference xController; bool bHasSelectionChanged; bool bDisposing; public: SvxRubyData_Impl(); virtual ~SvxRubyData_Impl() override; void SetController(const Reference& xCtrl); Reference const& GetModel() { if (!xController.is()) xModel = nullptr; else xModel = xController->getModel(); return xModel; } bool HasSelectionChanged() const { return bHasSelectionChanged; } bool IsDisposing() const { return bDisposing; } Reference const& GetRubySelection() { xSelection.set(xController, UNO_QUERY); return xSelection; } void UpdateRubyValues() { if (!xSelection.is()) aRubyValues.realloc(0); else aRubyValues = xSelection->getRubyList(false); bHasSelectionChanged = false; } Sequence& GetRubyValues() { return aRubyValues; } void AssertOneEntry(); virtual void SAL_CALL selectionChanged(const css::lang::EventObject& aEvent) override; virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; }; SvxRubyData_Impl::SvxRubyData_Impl() : bHasSelectionChanged(false) , bDisposing(false) { } SvxRubyData_Impl::~SvxRubyData_Impl() {} void SvxRubyData_Impl::SetController(const Reference& xCtrl) { if (xCtrl.get() == xController.get()) return; try { Reference xSelSupp(xController, UNO_QUERY); if (xSelSupp.is()) xSelSupp->removeSelectionChangeListener(this); bHasSelectionChanged = true; xController = xCtrl; xSelSupp.set(xController, UNO_QUERY); if (xSelSupp.is()) xSelSupp->addSelectionChangeListener(this); } catch (const Exception&) { } } void SvxRubyData_Impl::selectionChanged(const EventObject&) { bHasSelectionChanged = true; } void SvxRubyData_Impl::disposing(const EventObject&) { try { Reference xSelSupp(xController, UNO_QUERY); if (xSelSupp.is()) xSelSupp->removeSelectionChangeListener(this); } catch (const Exception&) { } xController = nullptr; bDisposing = true; } void SvxRubyData_Impl::AssertOneEntry() { //create one entry if (!aRubyValues.hasElements()) { aRubyValues.realloc(1); Sequence& rValues = aRubyValues.getArray()[0]; rValues.realloc(5); PropertyValue* pValues = rValues.getArray(); pValues[0].Name = cRubyBaseText; pValues[1].Name = cRubyText; pValues[2].Name = cRubyAdjust; pValues[3].Name = cRubyPosition; pValues[4].Name = cRubyCharStyleName; } } SvxRubyDialog::SvxRubyDialog(SfxBindings* pBind, SfxChildWindow* pCW, weld::Window* pParent) : SfxModelessDialogController(pBind, pCW, pParent, "svx/ui/asianphoneticguidedialog.ui", "AsianPhoneticGuideDialog") , nLastPos(0) , nCurrentEdit(0) , bModified(false) , pBindings(pBind) , m_pImpl(new SvxRubyData_Impl) , m_xLeft1ED(m_xBuilder->weld_entry("Left1ED")) , m_xRight1ED(m_xBuilder->weld_entry("Right1ED")) , m_xLeft2ED(m_xBuilder->weld_entry("Left2ED")) , m_xRight2ED(m_xBuilder->weld_entry("Right2ED")) , m_xLeft3ED(m_xBuilder->weld_entry("Left3ED")) , m_xRight3ED(m_xBuilder->weld_entry("Right3ED")) , m_xLeft4ED(m_xBuilder->weld_entry("Left4ED")) , m_xRight4ED(m_xBuilder->weld_entry("Right4ED")) , m_xScrolledWindow(m_xBuilder->weld_scrolled_window("scrolledwindow", true)) , m_xAdjustLB(m_xBuilder->weld_combo_box("adjustlb")) , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb")) , m_xCharStyleFT(m_xBuilder->weld_label("styleft")) , m_xCharStyleLB(m_xBuilder->weld_combo_box("stylelb")) , m_xStylistPB(m_xBuilder->weld_button("styles")) , m_xApplyPB(m_xBuilder->weld_button("ok")) , m_xClosePB(m_xBuilder->weld_button("close")) , m_xContentArea(m_xDialog->weld_content_area()) , m_xGrid(m_xBuilder->weld_widget("grid")) , m_xPreviewWin(new RubyPreview) , m_xPreview(new weld::CustomWeld(*m_xBuilder, "preview", *m_xPreviewWin)) { m_xCharStyleLB->make_sorted(); m_xPreviewWin->setRubyDialog(this); m_xScrolledWindow->set_size_request(-1, m_xGrid->get_preferred_size().Height()); m_xScrolledWindow->set_vpolicy(VclPolicyType::NEVER); aEditArr[0] = m_xLeft1ED.get(); aEditArr[1] = m_xRight1ED.get(); aEditArr[2] = m_xLeft2ED.get(); aEditArr[3] = m_xRight2ED.get(); aEditArr[4] = m_xLeft3ED.get(); aEditArr[5] = m_xRight3ED.get(); aEditArr[6] = m_xLeft4ED.get(); aEditArr[7] = m_xRight4ED.get(); m_xApplyPB->connect_clicked(LINK(this, SvxRubyDialog, ApplyHdl_Impl)); m_xClosePB->connect_clicked(LINK(this, SvxRubyDialog, CloseHdl_Impl)); m_xStylistPB->connect_clicked(LINK(this, SvxRubyDialog, StylistHdl_Impl)); m_xAdjustLB->connect_changed(LINK(this, SvxRubyDialog, AdjustHdl_Impl)); m_xPositionLB->connect_changed(LINK(this, SvxRubyDialog, PositionHdl_Impl)); m_xCharStyleLB->connect_changed(LINK(this, SvxRubyDialog, CharStyleHdl_Impl)); Link aScrLk(LINK(this, SvxRubyDialog, ScrollHdl_Impl)); m_xScrolledWindow->connect_vadjustment_changed(aScrLk); Link aEditLk(LINK(this, SvxRubyDialog, EditModifyHdl_Impl)); Link aFocusLk(LINK(this, SvxRubyDialog, EditFocusHdl_Impl)); Link aKeyUpDownLk(LINK(this, SvxRubyDialog, KeyUpDownHdl_Impl)); Link aKeyTabUpDownLk(LINK(this, SvxRubyDialog, KeyUpDownTabHdl_Impl)); for (sal_uInt16 i = 0; i < 8; i++) { aEditArr[i]->connect_changed(aEditLk); aEditArr[i]->connect_focus_in(aFocusLk); if (!i || 7 == i) aEditArr[i]->connect_key_press(aKeyTabUpDownLk); else aEditArr[i]->connect_key_press(aKeyUpDownLk); } } SvxRubyDialog::~SvxRubyDialog() { ClearCharStyleList(); EventObject aEvent; m_pImpl->disposing(aEvent); } void SvxRubyDialog::ClearCharStyleList() { m_xCharStyleLB->clear(); } void SvxRubyDialog::Close() { if (IsClosing()) return; SfxViewFrame* pViewFrame = SfxViewFrame::Current(); if (pViewFrame) pViewFrame->ToggleChildWindow(SID_RUBY_DIALOG); } void SvxRubyDialog::Activate() { SfxModelessDialogController::Activate(); if (m_pImpl->IsDisposing()) { // tdf#141967/tdf#152495 if Activate is called during tear down bail early return; } //get selection from current view frame SfxViewFrame* pCurFrm = SfxViewFrame::Current(); Reference xCtrl(pCurFrm ? pCurFrm->GetFrame().GetController() : nullptr); m_pImpl->SetController(xCtrl); if (!m_pImpl->HasSelectionChanged()) return; Reference xRubySel = m_pImpl->GetRubySelection(); m_pImpl->UpdateRubyValues(); EnableControls(xRubySel.is()); if (xRubySel.is()) { Reference xModel = m_pImpl->GetModel(); const OUString sCharStyleSelect = m_xCharStyleLB->get_active_text(); ClearCharStyleList(); Reference xSupplier(xModel, UNO_QUERY); if (xSupplier.is()) { try { Reference xFam = xSupplier->getStyleFamilies(); Any aChar = xFam->getByName("CharacterStyles"); Reference xChar; aChar >>= xChar; Reference xCharIdx(xChar, UNO_QUERY); if (xCharIdx.is()) { OUString sUIName("DisplayName"); for (sal_Int32 nStyle = 0; nStyle < xCharIdx->getCount(); nStyle++) { Any aStyle = xCharIdx->getByIndex(nStyle); Reference xStyle; aStyle >>= xStyle; Reference xPrSet(xStyle, UNO_QUERY); OUString sName, sCoreName; if (xPrSet.is()) { Reference xInfo = xPrSet->getPropertySetInfo(); if (xInfo->hasPropertyByName(sUIName)) { Any aName = xPrSet->getPropertyValue(sUIName); aName >>= sName; } } if (xStyle.is()) { sCoreName = xStyle->getName(); if (sName.isEmpty()) sName = sCoreName; } if (!sName.isEmpty()) { m_xCharStyleLB->append(sCoreName, sName); } } } } catch (const Exception&) { TOOLS_WARN_EXCEPTION("svx.dialog", "exception in style access"); } if (!sCharStyleSelect.isEmpty()) m_xCharStyleLB->set_active_text(sCharStyleSelect); } m_xCharStyleLB->set_sensitive(xSupplier.is()); m_xCharStyleFT->set_sensitive(xSupplier.is()); } Update(); m_xPreviewWin->Invalidate(); } void SvxRubyDialog::SetRubyText(sal_Int32 nPos, weld::Entry& rLeft, weld::Entry& rRight) { OUString sLeft, sRight; const Sequence& aRubyValues = m_pImpl->GetRubyValues(); bool bEnable = aRubyValues.getLength() > nPos; if (bEnable) { const Sequence aProps = aRubyValues.getConstArray()[nPos]; for (const PropertyValue& rProp : aProps) { if (rProp.Name == cRubyBaseText) rProp.Value >>= sLeft; else if (rProp.Name == cRubyText) rProp.Value >>= sRight; } } else if (!nPos) { bEnable = true; } rLeft.set_sensitive(bEnable); rRight.set_sensitive(bEnable); rLeft.set_text(sLeft); rRight.set_text(sRight); rLeft.save_value(); rRight.save_value(); } void SvxRubyDialog::GetRubyText() { tools::Long nTempLastPos = GetLastPos(); Sequence& aRubyValues = m_pImpl->GetRubyValues(); auto aRubyValuesRange = asNonConstRange(aRubyValues); for (int i = 0; i < 8; i += 2) { if (aEditArr[i]->get_sensitive() && (aEditArr[i]->get_value_changed_from_saved() || aEditArr[i + 1]->get_value_changed_from_saved())) { DBG_ASSERT(aRubyValues.getLength() > (i / 2 + nTempLastPos), "wrong index"); SetModified(true); for (PropertyValue& propVal : asNonConstRange(aRubyValuesRange[i / 2 + nTempLastPos])) { if (propVal.Name == cRubyBaseText) propVal.Value <<= aEditArr[i]->get_text(); else if (propVal.Name == cRubyText) propVal.Value <<= aEditArr[i + 1]->get_text(); } } } } void SvxRubyDialog::Update() { const Sequence& aRubyValues = m_pImpl->GetRubyValues(); sal_Int32 nLen = aRubyValues.getLength(); m_xScrolledWindow->vadjustment_configure(0, 0, !nLen ? 1 : nLen, 1, 4, 4); if (nLen > 4) m_xScrolledWindow->set_vpolicy(VclPolicyType::ALWAYS); else m_xScrolledWindow->set_vpolicy(VclPolicyType::NEVER); SetLastPos(0); SetModified(false); sal_Int16 nAdjust = -1; sal_Int16 nPosition = -1; OUString sCharStyleName, sTmp; bool bCharStyleEqual = true; for (sal_Int32 nRuby = 0; nRuby < nLen; nRuby++) { const Sequence& rProps = aRubyValues.getConstArray()[nRuby]; for (const PropertyValue& rProp : rProps) { if (nAdjust > -2 && rProp.Name == cRubyAdjust) { sal_Int16 nTmp = sal_Int16(); rProp.Value >>= nTmp; if (!nRuby) nAdjust = nTmp; else if (nAdjust != nTmp) nAdjust = -2; } if (nPosition > -2 && rProp.Name == cRubyPosition) { sal_Int16 nTmp = sal_Int16(); rProp.Value >>= nTmp; if (!nRuby) nPosition = nTmp; else if (nPosition != nTmp) nPosition = -2; } if (bCharStyleEqual && rProp.Name == cRubyCharStyleName) { rProp.Value >>= sTmp; if (!nRuby) sCharStyleName = sTmp; else if (sCharStyleName != sTmp) bCharStyleEqual = false; } } } if (!nLen) { //enable selection if the ruby list is empty nAdjust = 0; nPosition = 0; } if (nAdjust > -1) m_xAdjustLB->set_active(nAdjust); else m_xAdjustLB->set_active(-1); if (nPosition > -1) m_xPositionLB->set_active(nPosition); if (!nLen || (bCharStyleEqual && sCharStyleName.isEmpty())) sCharStyleName = "Rubies"; if (!sCharStyleName.isEmpty()) { for (int i = 0, nEntryCount = m_xCharStyleLB->get_count(); i < nEntryCount; i++) { OUString sCoreName = m_xCharStyleLB->get_id(i); if (sCharStyleName == sCoreName) { m_xCharStyleLB->set_active(i); break; } } } else m_xCharStyleLB->set_active(-1); ScrollHdl_Impl(*m_xScrolledWindow); } void SvxRubyDialog::GetCurrentText(OUString& rBase, OUString& rRuby) { rBase = aEditArr[nCurrentEdit * 2]->get_text(); rRuby = aEditArr[nCurrentEdit * 2 + 1]->get_text(); } IMPL_LINK(SvxRubyDialog, ScrollHdl_Impl, weld::ScrolledWindow&, rScroll, void) { int nPos = rScroll.vadjustment_get_value(); if (GetLastPos() != nPos) { GetRubyText(); } SetRubyText(nPos++, *m_xLeft1ED, *m_xRight1ED); SetRubyText(nPos++, *m_xLeft2ED, *m_xRight2ED); SetRubyText(nPos++, *m_xLeft3ED, *m_xRight3ED); SetRubyText(nPos, *m_xLeft4ED, *m_xRight4ED); SetLastPos(nPos - 3); m_xPreviewWin->Invalidate(); } IMPL_LINK_NOARG(SvxRubyDialog, ApplyHdl_Impl, weld::Button&, void) { const Sequence& aRubyValues = m_pImpl->GetRubyValues(); if (!aRubyValues.hasElements()) { AssertOneEntry(); PositionHdl_Impl(*m_xPositionLB); AdjustHdl_Impl(*m_xAdjustLB); CharStyleHdl_Impl(*m_xCharStyleLB); } GetRubyText(); //reset all edit fields - SaveValue is called ScrollHdl_Impl(*m_xScrolledWindow); Reference xSelection = m_pImpl->GetRubySelection(); if (IsModified() && xSelection.is()) { try { xSelection->setRubyList(aRubyValues, false); } catch (const Exception&) { TOOLS_WARN_EXCEPTION("svx.dialog", ""); } } } IMPL_LINK_NOARG(SvxRubyDialog, CloseHdl_Impl, weld::Button&, void) { Close(); } IMPL_LINK_NOARG(SvxRubyDialog, StylistHdl_Impl, weld::Button&, void) { std::unique_ptr pState; SfxItemState eState = pBindings->QueryState(SID_STYLE_DESIGNER, pState); if (eState <= SfxItemState::SET || !pState || !pState->GetValue()) { pBindings->GetDispatcher()->Execute(SID_STYLE_DESIGNER, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); } } IMPL_LINK(SvxRubyDialog, AdjustHdl_Impl, weld::ComboBox&, rBox, void) { AssertOneEntry(); sal_Int16 nAdjust = rBox.get_active(); for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues())) { for (PropertyValue& propVal : asNonConstRange(rProps)) { if (propVal.Name == cRubyAdjust) propVal.Value <<= nAdjust; } SetModified(true); } m_xPreviewWin->Invalidate(); } IMPL_LINK(SvxRubyDialog, PositionHdl_Impl, weld::ComboBox&, rBox, void) { AssertOneEntry(); sal_Int16 nPosition = rBox.get_active(); for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues())) { for (PropertyValue& propVal : asNonConstRange(rProps)) { if (propVal.Name == cRubyPosition) propVal.Value <<= nPosition; } SetModified(true); } m_xPreviewWin->Invalidate(); } IMPL_LINK_NOARG(SvxRubyDialog, CharStyleHdl_Impl, weld::ComboBox&, void) { AssertOneEntry(); OUString sStyleName; if (m_xCharStyleLB->get_active() != -1) sStyleName = m_xCharStyleLB->get_active_id(); for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues())) { for (PropertyValue& propVal : asNonConstRange(rProps)) { if (propVal.Name == cRubyCharStyleName) { propVal.Value <<= sStyleName; } } SetModified(true); } } IMPL_LINK(SvxRubyDialog, EditFocusHdl_Impl, weld::Widget&, rEdit, void) { for (sal_uInt16 i = 0; i < 8; i++) { if (&rEdit == aEditArr[i]) { nCurrentEdit = i / 2; break; } } m_xPreviewWin->Invalidate(); } IMPL_LINK(SvxRubyDialog, EditModifyHdl_Impl, weld::Entry&, rEdit, void) { EditFocusHdl_Impl(rEdit); } bool SvxRubyDialog::EditScrollHdl_Impl(sal_Int32 nParam) { bool bRet = false; //scroll forward if (nParam > 0 && (aEditArr[7]->has_focus() || aEditArr[6]->has_focus())) { if (m_xScrolledWindow->vadjustment_get_upper() > m_xScrolledWindow->vadjustment_get_value() + m_xScrolledWindow->vadjustment_get_page_size()) { m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_value() + 1); aEditArr[6]->grab_focus(); bRet = true; } } //scroll backward else if (m_xScrolledWindow->vadjustment_get_value() && (aEditArr[0]->has_focus() || aEditArr[1]->has_focus())) { m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_value() - 1); aEditArr[1]->grab_focus(); bRet = true; } if (bRet) ScrollHdl_Impl(*m_xScrolledWindow); return bRet; } bool SvxRubyDialog::EditJumpHdl_Impl(sal_Int32 nParam) { bool bHandled = false; sal_uInt16 nIndex = USHRT_MAX; for (sal_uInt16 i = 0; i < 8; i++) { if (aEditArr[i]->has_focus()) nIndex = i; } if (nIndex < 8) { if (nParam > 0) { if (nIndex < 6) aEditArr[nIndex + 2]->grab_focus(); else if (EditScrollHdl_Impl(nParam)) aEditArr[nIndex]->grab_focus(); } else { if (nIndex > 1) aEditArr[nIndex - 2]->grab_focus(); else if (EditScrollHdl_Impl(nParam)) aEditArr[nIndex]->grab_focus(); } bHandled = true; } return bHandled; } void SvxRubyDialog::AssertOneEntry() { m_pImpl->AssertOneEntry(); } void SvxRubyDialog::EnableControls(bool bEnable) { m_xContentArea->set_sensitive(bEnable); m_xApplyPB->set_sensitive(bEnable); } RubyPreview::RubyPreview() : m_pParentDlg(nullptr) { } RubyPreview::~RubyPreview() {} void RubyPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) { rRenderContext.Push(vcl::PushFlags::ALL); rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip)); Size aWinSize = rRenderContext.GetOutputSize(); const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); svtools::ColorConfig aColorConfig; Color aNewTextColor(aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor); Color aNewFillColor(rStyleSettings.GetWindowColor()); vcl::Font aFont = rRenderContext.GetFont(); aFont.SetFontHeight(aWinSize.Height() / 4); aFont.SetFillColor(aNewFillColor); aFont.SetColor(aNewTextColor); rRenderContext.SetFont(aFont); tools::Rectangle aRect(Point(0, 0), aWinSize); rRenderContext.SetLineColor(); rRenderContext.SetFillColor(aFont.GetFillColor()); rRenderContext.DrawRect(aRect); OUString sBaseText, sRubyText; m_pParentDlg->GetCurrentText(sBaseText, sRubyText); tools::Long nTextHeight = rRenderContext.GetTextHeight(); tools::Long nBaseWidth = rRenderContext.GetTextWidth(sBaseText); vcl::Font aRubyFont(aFont); aRubyFont.SetFontHeight(aRubyFont.GetFontHeight() * 70 / 100); rRenderContext.SetFont(aRubyFont); tools::Long nRubyWidth = rRenderContext.GetTextWidth(sRubyText); rRenderContext.SetFont(aFont); RubyAdjust nAdjust = static_cast(m_pParentDlg->m_xAdjustLB->get_active()); //use center if no adjustment is available if (nAdjust > RubyAdjust_INDENT_BLOCK) nAdjust = RubyAdjust_CENTER; //which part is stretched ? bool bRubyStretch = nBaseWidth >= nRubyWidth; tools::Long nCenter = aWinSize.Width() / 2; tools::Long nHalfWidth = std::max(nBaseWidth, nRubyWidth) / 2; tools::Long nLeftStart = nCenter - nHalfWidth; tools::Long nRightEnd = nCenter + nHalfWidth; // Default values for TOP or no selection tools::Long nYRuby = aWinSize.Height() / 4 - nTextHeight / 2; tools::Long nYBase = aWinSize.Height() * 3 / 4 - nTextHeight / 2; sal_Int16 nRubyPos = m_pParentDlg->m_xPositionLB->get_active(); if (nRubyPos == 1) // BOTTOM std::swap(nYRuby, nYBase); else if (nRubyPos == 2) // RIGHT ( vertically ) { // Align the ruby text and base text to the vertical center. nYBase = (aWinSize.Height() - nTextHeight) / 2; nYRuby = (aWinSize.Height() - nRubyWidth) / 2; // Align the ruby text at the right side of the base text nAdjust = RubyAdjust_RIGHT; nHalfWidth = nBaseWidth / 2; nLeftStart = nCenter - nHalfWidth; nRightEnd = nCenter + nHalfWidth + nRubyWidth + nTextHeight; // Render base text first, then render ruby text on the right. bRubyStretch = true; aRubyFont.SetVertical(true); aRubyFont.SetOrientation(2700_deg10); } tools::Long nYOutput; tools::Long nOutTextWidth; OUString sOutputText; if (bRubyStretch) { rRenderContext.DrawText(Point(nLeftStart, nYBase), sBaseText); nYOutput = nYRuby; sOutputText = sRubyText; nOutTextWidth = nRubyWidth; rRenderContext.SetFont(aRubyFont); } else { rRenderContext.SetFont(aRubyFont); rRenderContext.DrawText(Point(nLeftStart, nYRuby), sRubyText); nYOutput = nYBase; sOutputText = sBaseText; nOutTextWidth = nBaseWidth; rRenderContext.SetFont(aFont); } switch (nAdjust) { case RubyAdjust_LEFT: rRenderContext.DrawText(Point(nLeftStart, nYOutput), sOutputText); break; case RubyAdjust_RIGHT: rRenderContext.DrawText(Point(nRightEnd - nOutTextWidth, nYOutput), sOutputText); break; case RubyAdjust_INDENT_BLOCK: { tools::Long nCharWidth = rRenderContext.GetTextWidth("X"); if (nOutTextWidth < (nRightEnd - nLeftStart - nCharWidth)) { nCharWidth /= 2; nLeftStart += nCharWidth; nRightEnd -= nCharWidth; } [[fallthrough]]; } case RubyAdjust_BLOCK: { if (sOutputText.getLength() > 1) { sal_Int32 nCount = sOutputText.getLength(); tools::Long nSpace = ((nRightEnd - nLeftStart) - rRenderContext.GetTextWidth(sOutputText)) / (nCount - 1); for (sal_Int32 i = 0; i < nCount; i++) { OUString sChar(sOutputText[i]); rRenderContext.DrawText(Point(nLeftStart, nYOutput), sChar); tools::Long nCharWidth = rRenderContext.GetTextWidth(sChar); nLeftStart += nCharWidth + nSpace; } break; } [[fallthrough]]; } case RubyAdjust_CENTER: rRenderContext.DrawText(Point(nCenter - nOutTextWidth / 2, nYOutput), sOutputText); break; default: break; } rRenderContext.Pop(); } void RubyPreview::SetDrawingArea(weld::DrawingArea* pDrawingArea) { pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 40, pDrawingArea->get_text_height() * 7); CustomWidgetController::SetDrawingArea(pDrawingArea); } IMPL_LINK(SvxRubyDialog, KeyUpDownHdl_Impl, const KeyEvent&, rKEvt, bool) { bool bHandled = false; const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); sal_uInt16 nCode = rKeyCode.GetCode(); if (KEY_UP == nCode || KEY_DOWN == nCode) { sal_Int32 nParam = KEY_UP == nCode ? -1 : 1; bHandled = EditJumpHdl_Impl(nParam); } return bHandled; } IMPL_LINK(SvxRubyDialog, KeyUpDownTabHdl_Impl, const KeyEvent&, rKEvt, bool) { bool bHandled = false; const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); sal_uInt16 nMod = rKeyCode.GetModifier(); sal_uInt16 nCode = rKeyCode.GetCode(); if (nCode == KEY_TAB && (!nMod || KEY_SHIFT == nMod)) { sal_Int32 nParam = KEY_SHIFT == nMod ? -1 : 1; if (EditScrollHdl_Impl(nParam)) bHandled = true; } if (!bHandled) bHandled = KeyUpDownHdl_Impl(rKEvt); return bHandled; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ ice-4-0-6'>libreoffice-4-0-6 LibreOffice 核心代码仓库文档基金会
summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2022-12-12Update config.guess & .sub to latestThorsten Behrens
General updates & streamlining, plus addition of loongarch32 and managarm as probably most relevant additions here. Change-Id: Iff94f05c5e9240204eb3f844a05a7cad519522a5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143988 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
2020-08-07Fix typoAndrea Gelmini
Change-Id: Ie022017c333e19a2732e19a64efea1695dc01e03 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100335 Tested-by: Julien Nabet <serval2412@yahoo.fr> Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
2020-08-07Update config.{guess,sub} with latest versions and handle fallout of thatTor Lillqvist
From http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD and http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD . This time, do not apply the add-on change from 25a09c8776cc6088a5b2bf13dc84eb386c26bb7e to config.sub, but keep it pristine. Instead, let's start using the name "aarch64" instead of "arm64" for macOS and iOS in the autofoo context, as that is what those tools call it. Clang and Apple call it arm64, though. Change-Id: I1e05866c5fb08e0800cdfeaf7f6a71bfb43d1777 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100272 Tested-by: Jenkins Reviewed-by: Tor Lillqvist <tml@collabora.com>
2019-05-13Update config.{guess,sub}Caolán McNamara
...to latest versions from <http://git.savannah.gnu.org/gitweb/?p=config.git; a=blob_plain;f=config.guess;hb=HEAD> and <http://git.savannah.gnu.org/gitweb/? p=config.git;a=blob_plain;f=config.sub;hb=HEAD> but retain... commit 25a09c8776cc6088a5b2bf13dc84eb386c26bb7e Date: Wed Jun 7 12:23:17 2017 +0200 iOS, add support for arm64 Added general support for arm64 Removed experimental/prototype from normal build Change-Id: Ic36a9fb9d20344ff0ddc6b293ed3bd48cf140a31 Reviewed-on: https://gerrit.libreoffice.org/72200 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
2018-01-20Update config.{guess,sub}Caolán McNamara
...to latest versions from <http://git.savannah.gnu.org/gitweb/?p=config.git; a=blob_plain;f=config.guess;hb=HEAD> and <http://git.savannah.gnu.org/gitweb/? p=config.git;a=blob_plain;f=config.sub;hb=HEAD> but retain... commit 25a09c8776cc6088a5b2bf13dc84eb386c26bb7e Date: Wed Jun 7 12:23:17 2017 +0200 iOS, add support for arm64 Added general support for arm64 Removed experimental/prototype from normal build Change-Id: I82f9a549bb5004ff25266c50985569af53ba5f0e Reviewed-on: https://gerrit.libreoffice.org/48180 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
2017-06-07iOS, add support for arm64jan Iversen
Added general support for arm64 Removed experimental/prototype from normal build Change-Id: I832256c72fbd408084bc802440343c874e7e6d28
2014-06-18Update config.{guess,sub}Stephan Bergmann
...to latest versions from <http://git.savannah.gnu.org/gitweb/?p=config.git; a=blob_plain;f=config.guess;hb=HEAD> and <http://git.savannah.gnu.org/gitweb/? p=config.git;a=blob_plain;f=config.sub;hb=HEAD>, for aarch64 support. Change-Id: If4ed1a6ced85947ee5b1b923fd09b4d679140145