Remove non-const Sequence::begin()/end() in internal code
[LibreOffice.git] / svx / source / dialog / rubydialog.cxx
blobb10e6deb580e07dbae03504d12cc6ee0db339c02
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include <memory>
20 #include <sal/config.h>
21 #include <tools/debug.hxx>
22 #include <tools/diagnose_ex.h>
24 #include <svx/rubydialog.hxx>
25 #include <sfx2/dispatch.hxx>
26 #include <sfx2/sfxsids.hrc>
27 #include <sfx2/viewfrm.hxx>
28 #include <sfx2/viewsh.hxx>
29 #include <svl/eitem.hxx>
30 #include <com/sun/star/frame/XController.hpp>
31 #include <com/sun/star/style/XStyle.hpp>
32 #include <com/sun/star/text/XRubySelection.hpp>
33 #include <com/sun/star/beans/PropertyValues.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <com/sun/star/container/XNameContainer.hpp>
37 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
38 #include <com/sun/star/text/RubyAdjust.hpp>
39 #include <com/sun/star/view/XSelectionChangeListener.hpp>
40 #include <com/sun/star/view/XSelectionSupplier.hpp>
41 #include <cppuhelper/implbase.hxx>
42 #include <svtools/colorcfg.hxx>
43 #include <vcl/event.hxx>
44 #include <vcl/settings.hxx>
45 #include <vcl/svapp.hxx>
47 using namespace css::uno;
48 using namespace css::frame;
49 using namespace css::text;
50 using namespace css::beans;
51 using namespace css::style;
52 using namespace css::view;
53 using namespace css::lang;
54 using namespace css::container;
56 SFX_IMPL_CHILDWINDOW(SvxRubyChildWindow, SID_RUBY_DIALOG);
58 namespace
60 constexpr OUStringLiteral cRubyBaseText = u"RubyBaseText";
61 constexpr OUStringLiteral cRubyText = u"RubyText";
62 constexpr OUStringLiteral cRubyAdjust = u"RubyAdjust";
63 constexpr OUStringLiteral cRubyPosition = u"RubyPosition";
64 constexpr OUStringLiteral cRubyCharStyleName = u"RubyCharStyleName";
66 } // end anonymous namespace
68 SvxRubyChildWindow::SvxRubyChildWindow(vcl::Window* _pParent, sal_uInt16 nId,
69 SfxBindings* pBindings, SfxChildWinInfo const* pInfo)
70 : SfxChildWindow(_pParent, nId)
72 auto xDlg = std::make_shared<SvxRubyDialog>(pBindings, this, _pParent->GetFrameWeld());
73 SetController(xDlg);
74 xDlg->Initialize(pInfo);
77 SfxChildWinInfo SvxRubyChildWindow::GetInfo() const { return SfxChildWindow::GetInfo(); }
79 class SvxRubyData_Impl : public cppu::WeakImplHelper<css::view::XSelectionChangeListener>
81 Reference<XModel> xModel;
82 Reference<XRubySelection> xSelection;
83 Sequence<PropertyValues> aRubyValues;
84 Reference<XController> xController;
85 bool bHasSelectionChanged;
87 public:
88 SvxRubyData_Impl();
89 virtual ~SvxRubyData_Impl() override;
91 void SetController(const Reference<XController>& xCtrl);
92 Reference<XModel> const& GetModel()
94 if (!xController.is())
95 xModel = nullptr;
96 else
97 xModel = xController->getModel();
98 return xModel;
100 bool HasSelectionChanged() const { return bHasSelectionChanged; }
101 Reference<XRubySelection> const& GetRubySelection()
103 xSelection.set(xController, UNO_QUERY);
104 return xSelection;
106 void UpdateRubyValues()
108 if (!xSelection.is())
109 aRubyValues.realloc(0);
110 else
111 aRubyValues = xSelection->getRubyList(false);
112 bHasSelectionChanged = false;
114 Sequence<PropertyValues>& GetRubyValues() { return aRubyValues; }
115 void AssertOneEntry();
117 virtual void SAL_CALL selectionChanged(const css::lang::EventObject& aEvent) override;
118 virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
121 SvxRubyData_Impl::SvxRubyData_Impl()
122 : bHasSelectionChanged(false)
126 SvxRubyData_Impl::~SvxRubyData_Impl() {}
128 void SvxRubyData_Impl::SetController(const Reference<XController>& xCtrl)
130 if (xCtrl.get() == xController.get())
131 return;
135 Reference<XSelectionSupplier> xSelSupp(xController, UNO_QUERY);
136 if (xSelSupp.is())
137 xSelSupp->removeSelectionChangeListener(this);
139 bHasSelectionChanged = true;
140 xController = xCtrl;
141 xSelSupp.set(xController, UNO_QUERY);
142 if (xSelSupp.is())
143 xSelSupp->addSelectionChangeListener(this);
145 catch (const Exception&)
150 void SvxRubyData_Impl::selectionChanged(const EventObject&) { bHasSelectionChanged = true; }
152 void SvxRubyData_Impl::disposing(const EventObject&)
156 Reference<XSelectionSupplier> xSelSupp(xController, UNO_QUERY);
157 if (xSelSupp.is())
158 xSelSupp->removeSelectionChangeListener(this);
160 catch (const Exception&)
163 xController = nullptr;
166 void SvxRubyData_Impl::AssertOneEntry()
168 //create one entry
169 if (!aRubyValues.hasElements())
171 aRubyValues.realloc(1);
172 Sequence<PropertyValue>& rValues = aRubyValues.getArray()[0];
173 rValues.realloc(5);
174 PropertyValue* pValues = rValues.getArray();
175 pValues[0].Name = cRubyBaseText;
176 pValues[1].Name = cRubyText;
177 pValues[2].Name = cRubyAdjust;
178 pValues[3].Name = cRubyPosition;
179 pValues[4].Name = cRubyCharStyleName;
183 SvxRubyDialog::SvxRubyDialog(SfxBindings* pBind, SfxChildWindow* pCW, weld::Window* pParent)
184 : SfxModelessDialogController(pBind, pCW, pParent, "svx/ui/asianphoneticguidedialog.ui",
185 "AsianPhoneticGuideDialog")
186 , nLastPos(0)
187 , nCurrentEdit(0)
188 , bModified(false)
189 , pBindings(pBind)
190 , m_pImpl(new SvxRubyData_Impl)
191 , m_xLeftFT(m_xBuilder->weld_label("basetextft"))
192 , m_xRightFT(m_xBuilder->weld_label("rubytextft"))
193 , m_xLeft1ED(m_xBuilder->weld_entry("Left1ED"))
194 , m_xRight1ED(m_xBuilder->weld_entry("Right1ED"))
195 , m_xLeft2ED(m_xBuilder->weld_entry("Left2ED"))
196 , m_xRight2ED(m_xBuilder->weld_entry("Right2ED"))
197 , m_xLeft3ED(m_xBuilder->weld_entry("Left3ED"))
198 , m_xRight3ED(m_xBuilder->weld_entry("Right3ED"))
199 , m_xLeft4ED(m_xBuilder->weld_entry("Left4ED"))
200 , m_xRight4ED(m_xBuilder->weld_entry("Right4ED"))
201 , m_xScrolledWindow(m_xBuilder->weld_scrolled_window("scrolledwindow", true))
202 , m_xAdjustLB(m_xBuilder->weld_combo_box("adjustlb"))
203 , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb"))
204 , m_xCharStyleFT(m_xBuilder->weld_label("styleft"))
205 , m_xCharStyleLB(m_xBuilder->weld_combo_box("stylelb"))
206 , m_xStylistPB(m_xBuilder->weld_button("styles"))
207 , m_xApplyPB(m_xBuilder->weld_button("ok"))
208 , m_xClosePB(m_xBuilder->weld_button("close"))
209 , m_xContentArea(m_xDialog->weld_content_area())
210 , m_xGrid(m_xBuilder->weld_widget("grid"))
211 , m_xPreviewWin(new RubyPreview)
212 , m_xPreview(new weld::CustomWeld(*m_xBuilder, "preview", *m_xPreviewWin))
214 m_xCharStyleLB->make_sorted();
215 m_xPreviewWin->setRubyDialog(this);
216 m_xScrolledWindow->set_size_request(-1, m_xGrid->get_preferred_size().Height());
217 m_xScrolledWindow->set_vpolicy(VclPolicyType::NEVER);
219 aEditArr[0] = m_xLeft1ED.get();
220 aEditArr[1] = m_xRight1ED.get();
221 aEditArr[2] = m_xLeft2ED.get();
222 aEditArr[3] = m_xRight2ED.get();
223 aEditArr[4] = m_xLeft3ED.get();
224 aEditArr[5] = m_xRight3ED.get();
225 aEditArr[6] = m_xLeft4ED.get();
226 aEditArr[7] = m_xRight4ED.get();
228 m_xApplyPB->connect_clicked(LINK(this, SvxRubyDialog, ApplyHdl_Impl));
229 m_xClosePB->connect_clicked(LINK(this, SvxRubyDialog, CloseHdl_Impl));
230 m_xStylistPB->connect_clicked(LINK(this, SvxRubyDialog, StylistHdl_Impl));
231 m_xAdjustLB->connect_changed(LINK(this, SvxRubyDialog, AdjustHdl_Impl));
232 m_xPositionLB->connect_changed(LINK(this, SvxRubyDialog, PositionHdl_Impl));
233 m_xCharStyleLB->connect_changed(LINK(this, SvxRubyDialog, CharStyleHdl_Impl));
235 Link<weld::ScrolledWindow&, void> aScrLk(LINK(this, SvxRubyDialog, ScrollHdl_Impl));
236 m_xScrolledWindow->connect_vadjustment_changed(aScrLk);
238 Link<weld::Entry&, void> aEditLk(LINK(this, SvxRubyDialog, EditModifyHdl_Impl));
239 Link<weld::Widget&, void> aFocusLk(LINK(this, SvxRubyDialog, EditFocusHdl_Impl));
240 Link<const KeyEvent&, bool> aKeyUpDownLk(LINK(this, SvxRubyDialog, KeyUpDownHdl_Impl));
241 Link<const KeyEvent&, bool> aKeyTabUpDownLk(LINK(this, SvxRubyDialog, KeyUpDownTabHdl_Impl));
242 for (sal_uInt16 i = 0; i < 8; i++)
244 aEditArr[i]->connect_changed(aEditLk);
245 aEditArr[i]->connect_focus_in(aFocusLk);
246 if (!i || 7 == i)
247 aEditArr[i]->connect_key_press(aKeyTabUpDownLk);
248 else
249 aEditArr[i]->connect_key_press(aKeyUpDownLk);
253 SvxRubyDialog::~SvxRubyDialog()
255 ClearCharStyleList();
256 EventObject aEvent;
257 m_pImpl->disposing(aEvent);
260 void SvxRubyDialog::ClearCharStyleList() { m_xCharStyleLB->clear(); }
262 void SvxRubyDialog::Close()
264 if (IsClosing())
265 return;
266 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
267 if (pViewFrame)
268 pViewFrame->ToggleChildWindow(SID_RUBY_DIALOG);
271 void SvxRubyDialog::Activate()
273 SfxModelessDialogController::Activate();
274 if (!m_xContentArea)
276 // tdf#141967 if Activate is called during tear down bail early
277 return;
279 //get selection from current view frame
280 SfxViewFrame* pCurFrm = SfxViewFrame::Current();
281 Reference<XController> xCtrl = pCurFrm->GetFrame().GetController();
282 m_pImpl->SetController(xCtrl);
283 if (!m_pImpl->HasSelectionChanged())
284 return;
286 Reference<XRubySelection> xRubySel = m_pImpl->GetRubySelection();
287 m_pImpl->UpdateRubyValues();
288 EnableControls(xRubySel.is());
289 if (xRubySel.is())
291 Reference<XModel> xModel = m_pImpl->GetModel();
292 const OUString sCharStyleSelect = m_xCharStyleLB->get_active_text();
293 ClearCharStyleList();
294 Reference<XStyleFamiliesSupplier> xSupplier(xModel, UNO_QUERY);
295 if (xSupplier.is())
299 Reference<XNameAccess> xFam = xSupplier->getStyleFamilies();
300 Any aChar = xFam->getByName("CharacterStyles");
301 Reference<XNameContainer> xChar;
302 aChar >>= xChar;
303 Reference<XIndexAccess> xCharIdx(xChar, UNO_QUERY);
304 if (xCharIdx.is())
306 OUString sUIName("DisplayName");
307 for (sal_Int32 nStyle = 0; nStyle < xCharIdx->getCount(); nStyle++)
309 Any aStyle = xCharIdx->getByIndex(nStyle);
310 Reference<XStyle> xStyle;
311 aStyle >>= xStyle;
312 Reference<XPropertySet> xPrSet(xStyle, UNO_QUERY);
313 OUString sName, sCoreName;
314 if (xPrSet.is())
316 Reference<XPropertySetInfo> xInfo = xPrSet->getPropertySetInfo();
317 if (xInfo->hasPropertyByName(sUIName))
319 Any aName = xPrSet->getPropertyValue(sUIName);
320 aName >>= sName;
323 if (xStyle.is())
325 sCoreName = xStyle->getName();
326 if (sName.isEmpty())
327 sName = sCoreName;
329 if (!sName.isEmpty())
331 m_xCharStyleLB->append(sCoreName, sName);
336 catch (const Exception&)
338 TOOLS_WARN_EXCEPTION("svx.dialog", "exception in style access");
340 if (!sCharStyleSelect.isEmpty())
341 m_xCharStyleLB->set_active_text(sCharStyleSelect);
343 m_xCharStyleLB->set_sensitive(xSupplier.is());
344 m_xCharStyleFT->set_sensitive(xSupplier.is());
346 Update();
347 m_xPreviewWin->Invalidate();
350 void SvxRubyDialog::SetRubyText(sal_Int32 nPos, weld::Entry& rLeft, weld::Entry& rRight)
352 OUString sLeft, sRight;
353 const Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
354 bool bEnable = aRubyValues.getLength() > nPos;
355 if (bEnable)
357 const Sequence<PropertyValue> aProps = aRubyValues.getConstArray()[nPos];
358 for (const PropertyValue& rProp : aProps)
360 if (rProp.Name == cRubyBaseText)
361 rProp.Value >>= sLeft;
362 else if (rProp.Name == cRubyText)
363 rProp.Value >>= sRight;
366 else if (!nPos)
368 bEnable = true;
370 rLeft.set_sensitive(bEnable);
371 rRight.set_sensitive(bEnable);
372 rLeft.set_text(sLeft);
373 rRight.set_text(sRight);
374 rLeft.save_value();
375 rRight.save_value();
378 void SvxRubyDialog::GetRubyText()
380 tools::Long nTempLastPos = GetLastPos();
381 for (int i = 0; i < 8; i += 2)
383 if (aEditArr[i]->get_sensitive()
384 && (aEditArr[i]->get_value_changed_from_saved()
385 || aEditArr[i + 1]->get_value_changed_from_saved()))
387 Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
388 DBG_ASSERT(aRubyValues.getLength() > (i / 2 + nTempLastPos), "wrong index");
389 SetModified(true);
390 for (PropertyValue& propVal : asNonConstRange(aRubyValues[i / 2 + nTempLastPos]))
392 if (propVal.Name == cRubyBaseText)
393 propVal.Value <<= aEditArr[i]->get_text();
394 else if (propVal.Name == cRubyText)
395 propVal.Value <<= aEditArr[i + 1]->get_text();
401 void SvxRubyDialog::Update()
403 const Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
404 sal_Int32 nLen = aRubyValues.getLength();
405 m_xScrolledWindow->vadjustment_configure(0, 0, !nLen ? 1 : nLen, 1, 4, 4);
406 if (nLen > 4)
407 m_xScrolledWindow->set_vpolicy(VclPolicyType::ALWAYS);
408 else
409 m_xScrolledWindow->set_vpolicy(VclPolicyType::NEVER);
410 SetLastPos(0);
411 SetModified(false);
413 sal_Int16 nAdjust = -1;
414 sal_Int16 nPosition = -1;
415 OUString sCharStyleName, sTmp;
416 bool bCharStyleEqual = true;
417 for (sal_Int32 nRuby = 0; nRuby < nLen; nRuby++)
419 const Sequence<PropertyValue>& rProps = aRubyValues.getConstArray()[nRuby];
420 for (const PropertyValue& rProp : rProps)
422 if (nAdjust > -2 && rProp.Name == cRubyAdjust)
424 sal_Int16 nTmp = sal_Int16();
425 rProp.Value >>= nTmp;
426 if (!nRuby)
427 nAdjust = nTmp;
428 else if (nAdjust != nTmp)
429 nAdjust = -2;
431 if (nPosition > -2 && rProp.Name == cRubyPosition)
433 sal_Int16 nTmp = sal_Int16();
434 rProp.Value >>= nTmp;
435 if (!nRuby)
436 nPosition = nTmp;
437 else if (nPosition != nTmp)
438 nPosition = -2;
440 if (bCharStyleEqual && rProp.Name == cRubyCharStyleName)
442 rProp.Value >>= sTmp;
443 if (!nRuby)
444 sCharStyleName = sTmp;
445 else if (sCharStyleName != sTmp)
446 bCharStyleEqual = false;
450 if (!nLen)
452 //enable selection if the ruby list is empty
453 nAdjust = 0;
454 nPosition = 0;
456 if (nAdjust > -1)
457 m_xAdjustLB->set_active(nAdjust);
458 else
459 m_xAdjustLB->set_active(-1);
460 if (nPosition > -1)
461 m_xPositionLB->set_active(nPosition);
462 if (!nLen || (bCharStyleEqual && sCharStyleName.isEmpty()))
463 sCharStyleName = "Rubies";
464 if (!sCharStyleName.isEmpty())
466 for (int i = 0, nEntryCount = m_xCharStyleLB->get_count(); i < nEntryCount; i++)
468 OUString sCoreName = m_xCharStyleLB->get_id(i);
469 if (sCharStyleName == sCoreName)
471 m_xCharStyleLB->set_active(i);
472 break;
476 else
477 m_xCharStyleLB->set_active(-1);
479 ScrollHdl_Impl(*m_xScrolledWindow);
482 void SvxRubyDialog::GetCurrentText(OUString& rBase, OUString& rRuby)
484 rBase = aEditArr[nCurrentEdit * 2]->get_text();
485 rRuby = aEditArr[nCurrentEdit * 2 + 1]->get_text();
488 IMPL_LINK(SvxRubyDialog, ScrollHdl_Impl, weld::ScrolledWindow&, rScroll, void)
490 int nPos = rScroll.vadjustment_get_value();
491 if (GetLastPos() != nPos)
493 GetRubyText();
495 SetRubyText(nPos++, *m_xLeft1ED, *m_xRight1ED);
496 SetRubyText(nPos++, *m_xLeft2ED, *m_xRight2ED);
497 SetRubyText(nPos++, *m_xLeft3ED, *m_xRight3ED);
498 SetRubyText(nPos, *m_xLeft4ED, *m_xRight4ED);
499 SetLastPos(nPos - 3);
500 m_xPreviewWin->Invalidate();
503 IMPL_LINK_NOARG(SvxRubyDialog, ApplyHdl_Impl, weld::Button&, void)
505 const Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
506 if (!aRubyValues.hasElements())
508 AssertOneEntry();
509 PositionHdl_Impl(*m_xPositionLB);
510 AdjustHdl_Impl(*m_xAdjustLB);
511 CharStyleHdl_Impl(*m_xCharStyleLB);
513 GetRubyText();
514 //reset all edit fields - SaveValue is called
515 ScrollHdl_Impl(*m_xScrolledWindow);
517 Reference<XRubySelection> xSelection = m_pImpl->GetRubySelection();
518 if (IsModified() && xSelection.is())
522 xSelection->setRubyList(aRubyValues, false);
524 catch (const Exception&)
526 TOOLS_WARN_EXCEPTION("svx.dialog", "");
531 IMPL_LINK_NOARG(SvxRubyDialog, CloseHdl_Impl, weld::Button&, void) { Close(); }
533 IMPL_LINK_NOARG(SvxRubyDialog, StylistHdl_Impl, weld::Button&, void)
535 std::unique_ptr<SfxPoolItem> pState;
536 SfxItemState eState = pBindings->QueryState(SID_STYLE_DESIGNER, pState);
537 if (eState <= SfxItemState::SET || !pState
538 || !static_cast<SfxBoolItem*>(pState.get())->GetValue())
540 pBindings->GetDispatcher()->Execute(SID_STYLE_DESIGNER,
541 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
545 IMPL_LINK(SvxRubyDialog, AdjustHdl_Impl, weld::ComboBox&, rBox, void)
547 AssertOneEntry();
548 sal_Int16 nAdjust = rBox.get_active();
549 for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues()))
551 for (PropertyValue& propVal : asNonConstRange(rProps))
553 if (propVal.Name == cRubyAdjust)
554 propVal.Value <<= nAdjust;
556 SetModified(true);
558 m_xPreviewWin->Invalidate();
561 IMPL_LINK(SvxRubyDialog, PositionHdl_Impl, weld::ComboBox&, rBox, void)
563 AssertOneEntry();
564 sal_Int16 nPosition = rBox.get_active();
565 for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues()))
567 for (PropertyValue& propVal : asNonConstRange(rProps))
569 if (propVal.Name == cRubyPosition)
570 propVal.Value <<= nPosition;
572 SetModified(true);
574 m_xPreviewWin->Invalidate();
577 IMPL_LINK_NOARG(SvxRubyDialog, CharStyleHdl_Impl, weld::ComboBox&, void)
579 AssertOneEntry();
580 OUString sStyleName;
581 if (m_xCharStyleLB->get_active() != -1)
582 sStyleName = m_xCharStyleLB->get_active_id();
583 for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues()))
585 for (PropertyValue& propVal : asNonConstRange(rProps))
587 if (propVal.Name == cRubyCharStyleName)
589 propVal.Value <<= sStyleName;
592 SetModified(true);
596 IMPL_LINK(SvxRubyDialog, EditFocusHdl_Impl, weld::Widget&, rEdit, void)
598 for (sal_uInt16 i = 0; i < 8; i++)
600 if (&rEdit == aEditArr[i])
602 nCurrentEdit = i / 2;
603 break;
606 m_xPreviewWin->Invalidate();
609 IMPL_LINK(SvxRubyDialog, EditModifyHdl_Impl, weld::Entry&, rEdit, void)
611 EditFocusHdl_Impl(rEdit);
614 bool SvxRubyDialog::EditScrollHdl_Impl(sal_Int32 nParam)
616 bool bRet = false;
617 //scroll forward
618 if (nParam > 0 && (aEditArr[7]->has_focus() || aEditArr[6]->has_focus()))
620 if (m_xScrolledWindow->vadjustment_get_upper()
621 > m_xScrolledWindow->vadjustment_get_value()
622 + m_xScrolledWindow->vadjustment_get_page_size())
624 m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_value()
625 + 1);
626 aEditArr[6]->grab_focus();
627 bRet = true;
630 //scroll backward
631 else if (m_xScrolledWindow->vadjustment_get_value()
632 && (aEditArr[0]->has_focus() || aEditArr[1]->has_focus()))
634 m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_value() - 1);
635 aEditArr[1]->grab_focus();
636 bRet = true;
638 if (bRet)
639 ScrollHdl_Impl(*m_xScrolledWindow);
640 return bRet;
643 bool SvxRubyDialog::EditJumpHdl_Impl(sal_Int32 nParam)
645 bool bHandled = false;
646 sal_uInt16 nIndex = USHRT_MAX;
647 for (sal_uInt16 i = 0; i < 8; i++)
649 if (aEditArr[i]->has_focus())
650 nIndex = i;
652 if (nIndex < 8)
654 if (nParam > 0)
656 if (nIndex < 6)
657 aEditArr[nIndex + 2]->grab_focus();
658 else if (EditScrollHdl_Impl(nParam))
659 aEditArr[nIndex]->grab_focus();
661 else
663 if (nIndex > 1)
664 aEditArr[nIndex - 2]->grab_focus();
665 else if (EditScrollHdl_Impl(nParam))
666 aEditArr[nIndex]->grab_focus();
668 bHandled = true;
670 return bHandled;
673 void SvxRubyDialog::AssertOneEntry() { m_pImpl->AssertOneEntry(); }
675 void SvxRubyDialog::EnableControls(bool bEnable)
677 m_xContentArea->set_sensitive(bEnable);
678 m_xApplyPB->set_sensitive(bEnable);
681 RubyPreview::RubyPreview()
682 : m_pParentDlg(nullptr)
686 RubyPreview::~RubyPreview() {}
688 void RubyPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
690 rRenderContext.Push(vcl::PushFlags::ALL);
692 rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip));
694 Size aWinSize = rRenderContext.GetOutputSize();
696 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
697 svtools::ColorConfig aColorConfig;
699 Color aNewTextColor(aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor);
700 Color aNewFillColor(rStyleSettings.GetWindowColor());
702 vcl::Font aFont = rRenderContext.GetFont();
703 aFont.SetFontHeight(aWinSize.Height() / 4);
704 aFont.SetFillColor(aNewFillColor);
705 aFont.SetColor(aNewTextColor);
706 rRenderContext.SetFont(aFont);
708 tools::Rectangle aRect(Point(0, 0), aWinSize);
709 rRenderContext.SetLineColor();
710 rRenderContext.SetFillColor(aFont.GetFillColor());
711 rRenderContext.DrawRect(aRect);
713 OUString sBaseText, sRubyText;
714 m_pParentDlg->GetCurrentText(sBaseText, sRubyText);
716 tools::Long nTextHeight = rRenderContext.GetTextHeight();
717 tools::Long nBaseWidth = rRenderContext.GetTextWidth(sBaseText);
719 vcl::Font aRubyFont(aFont);
720 aRubyFont.SetFontHeight(aRubyFont.GetFontHeight() * 70 / 100);
721 rRenderContext.SetFont(aRubyFont);
722 tools::Long nRubyWidth = rRenderContext.GetTextWidth(sRubyText);
723 rRenderContext.SetFont(aFont);
725 RubyAdjust nAdjust = static_cast<RubyAdjust>(m_pParentDlg->m_xAdjustLB->get_active());
726 //use center if no adjustment is available
727 if (nAdjust > RubyAdjust_INDENT_BLOCK)
728 nAdjust = RubyAdjust_CENTER;
730 //which part is stretched ?
731 bool bRubyStretch = nBaseWidth >= nRubyWidth;
733 tools::Long nCenter = aWinSize.Width() / 2;
734 tools::Long nHalfWidth = std::max(nBaseWidth, nRubyWidth) / 2;
735 tools::Long nLeftStart = nCenter - nHalfWidth;
736 tools::Long nRightEnd = nCenter + nHalfWidth;
738 // Default values for TOP or no selection
739 tools::Long nYRuby = aWinSize.Height() / 4 - nTextHeight / 2;
740 tools::Long nYBase = aWinSize.Height() * 3 / 4 - nTextHeight / 2;
742 sal_Int16 nRubyPos = m_pParentDlg->m_xPositionLB->get_active();
743 if (nRubyPos == 1) // BOTTOM
745 tools::Long nTmp = nYRuby;
746 nYRuby = nYBase;
747 nYBase = nTmp;
749 else if (nRubyPos == 2) // RIGHT ( vertically )
751 // Align the ruby text and base text to the vertical center.
752 nYBase = (aWinSize.Height() - nTextHeight) / 2;
753 nYRuby = (aWinSize.Height() - nRubyWidth) / 2;
755 // Align the ruby text at the right side of the base text
756 nAdjust = RubyAdjust_RIGHT;
757 nHalfWidth = nBaseWidth / 2;
758 nLeftStart = nCenter - nHalfWidth;
759 nRightEnd = nCenter + nHalfWidth + nRubyWidth + nTextHeight;
760 // Render base text first, then render ruby text on the right.
761 bRubyStretch = true;
763 aRubyFont.SetVertical(true);
764 aRubyFont.SetOrientation(2700_deg10);
767 tools::Long nYOutput;
768 tools::Long nOutTextWidth;
769 OUString sOutputText;
771 if (bRubyStretch)
773 rRenderContext.DrawText(Point(nLeftStart, nYBase), sBaseText);
774 nYOutput = nYRuby;
775 sOutputText = sRubyText;
776 nOutTextWidth = nRubyWidth;
777 rRenderContext.SetFont(aRubyFont);
779 else
781 rRenderContext.SetFont(aRubyFont);
782 rRenderContext.DrawText(Point(nLeftStart, nYRuby), sRubyText);
783 nYOutput = nYBase;
784 sOutputText = sBaseText;
785 nOutTextWidth = nBaseWidth;
786 rRenderContext.SetFont(aFont);
789 switch (nAdjust)
791 case RubyAdjust_LEFT:
792 rRenderContext.DrawText(Point(nLeftStart, nYOutput), sOutputText);
793 break;
794 case RubyAdjust_RIGHT:
795 rRenderContext.DrawText(Point(nRightEnd - nOutTextWidth, nYOutput), sOutputText);
796 break;
797 case RubyAdjust_INDENT_BLOCK:
799 tools::Long nCharWidth = rRenderContext.GetTextWidth("X");
800 if (nOutTextWidth < (nRightEnd - nLeftStart - nCharWidth))
802 nCharWidth /= 2;
803 nLeftStart += nCharWidth;
804 nRightEnd -= nCharWidth;
806 [[fallthrough]];
808 case RubyAdjust_BLOCK:
810 if (sOutputText.getLength() > 1)
812 sal_Int32 nCount = sOutputText.getLength();
813 tools::Long nSpace
814 = ((nRightEnd - nLeftStart) - rRenderContext.GetTextWidth(sOutputText))
815 / (nCount - 1);
816 for (sal_Int32 i = 0; i < nCount; i++)
818 OUString sChar(sOutputText[i]);
819 rRenderContext.DrawText(Point(nLeftStart, nYOutput), sChar);
820 tools::Long nCharWidth = rRenderContext.GetTextWidth(sChar);
821 nLeftStart += nCharWidth + nSpace;
823 break;
825 [[fallthrough]];
827 case RubyAdjust_CENTER:
828 rRenderContext.DrawText(Point(nCenter - nOutTextWidth / 2, nYOutput), sOutputText);
829 break;
830 default:
831 break;
833 rRenderContext.Pop();
836 void RubyPreview::SetDrawingArea(weld::DrawingArea* pDrawingArea)
838 pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 40,
839 pDrawingArea->get_text_height() * 7);
840 CustomWidgetController::SetDrawingArea(pDrawingArea);
843 IMPL_LINK(SvxRubyDialog, KeyUpDownHdl_Impl, const KeyEvent&, rKEvt, bool)
845 bool bHandled = false;
846 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
847 sal_uInt16 nCode = rKeyCode.GetCode();
848 if (KEY_UP == nCode || KEY_DOWN == nCode)
850 sal_Int32 nParam = KEY_UP == nCode ? -1 : 1;
851 bHandled = EditJumpHdl_Impl(nParam);
853 return bHandled;
856 IMPL_LINK(SvxRubyDialog, KeyUpDownTabHdl_Impl, const KeyEvent&, rKEvt, bool)
858 bool bHandled = false;
859 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
860 sal_uInt16 nMod = rKeyCode.GetModifier();
861 sal_uInt16 nCode = rKeyCode.GetCode();
862 if (nCode == KEY_TAB && (!nMod || KEY_SHIFT == nMod))
864 sal_Int32 nParam = KEY_SHIFT == nMod ? -1 : 1;
865 if (EditScrollHdl_Impl(nParam))
866 bHandled = true;
868 if (!bHandled)
869 bHandled = KeyUpDownHdl_Impl(rKEvt);
870 return bHandled;
873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */