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 .
20 #include <sal/config.h>
21 #include <tools/debug.hxx>
22 #include <comphelper/diagnose_ex.hxx>
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
);
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());
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
;
90 virtual ~SvxRubyData_Impl() override
;
92 void SetController(const Reference
<XController
>& xCtrl
);
93 Reference
<XModel
> const& GetModel()
95 if (!xController
.is())
98 xModel
= xController
->getModel();
101 bool HasSelectionChanged() const { return bHasSelectionChanged
; }
102 bool IsDisposing() const { return bDisposing
; }
103 Reference
<XRubySelection
> const& GetRubySelection()
105 xSelection
.set(xController
, UNO_QUERY
);
108 void UpdateRubyValues()
110 if (!xSelection
.is())
111 aRubyValues
.realloc(0);
113 aRubyValues
= xSelection
->getRubyList(false);
114 bHasSelectionChanged
= false;
116 Sequence
<PropertyValues
>& GetRubyValues() { return aRubyValues
; }
117 void AssertOneEntry();
119 virtual void SAL_CALL
selectionChanged(const css::lang::EventObject
& aEvent
) override
;
120 virtual void SAL_CALL
disposing(const css::lang::EventObject
& Source
) override
;
123 SvxRubyData_Impl::SvxRubyData_Impl()
124 : bHasSelectionChanged(false)
129 SvxRubyData_Impl::~SvxRubyData_Impl() {}
131 void SvxRubyData_Impl::SetController(const Reference
<XController
>& xCtrl
)
133 if (xCtrl
.get() == xController
.get())
138 Reference
<XSelectionSupplier
> xSelSupp(xController
, UNO_QUERY
);
140 xSelSupp
->removeSelectionChangeListener(this);
142 bHasSelectionChanged
= true;
144 xSelSupp
.set(xController
, UNO_QUERY
);
146 xSelSupp
->addSelectionChangeListener(this);
148 catch (const Exception
&)
153 void SvxRubyData_Impl::selectionChanged(const EventObject
&) { bHasSelectionChanged
= true; }
155 void SvxRubyData_Impl::disposing(const EventObject
&)
159 Reference
<XSelectionSupplier
> xSelSupp(xController
, UNO_QUERY
);
161 xSelSupp
->removeSelectionChangeListener(this);
163 catch (const Exception
&)
166 xController
= nullptr;
170 void SvxRubyData_Impl::AssertOneEntry()
173 if (!aRubyValues
.hasElements())
175 aRubyValues
.realloc(1);
176 Sequence
<PropertyValue
>& rValues
= aRubyValues
.getArray()[0];
178 PropertyValue
* pValues
= rValues
.getArray();
179 pValues
[0].Name
= cRubyBaseText
;
180 pValues
[1].Name
= cRubyText
;
181 pValues
[2].Name
= cRubyAdjust
;
182 pValues
[3].Name
= cRubyPosition
;
183 pValues
[4].Name
= cRubyCharStyleName
;
187 SvxRubyDialog::SvxRubyDialog(SfxBindings
* pBind
, SfxChildWindow
* pCW
, weld::Window
* pParent
)
188 : SfxModelessDialogController(pBind
, pCW
, pParent
, "svx/ui/asianphoneticguidedialog.ui",
189 "AsianPhoneticGuideDialog")
194 , m_pImpl(new SvxRubyData_Impl
)
195 , m_xLeft1ED(m_xBuilder
->weld_entry("Left1ED"))
196 , m_xRight1ED(m_xBuilder
->weld_entry("Right1ED"))
197 , m_xLeft2ED(m_xBuilder
->weld_entry("Left2ED"))
198 , m_xRight2ED(m_xBuilder
->weld_entry("Right2ED"))
199 , m_xLeft3ED(m_xBuilder
->weld_entry("Left3ED"))
200 , m_xRight3ED(m_xBuilder
->weld_entry("Right3ED"))
201 , m_xLeft4ED(m_xBuilder
->weld_entry("Left4ED"))
202 , m_xRight4ED(m_xBuilder
->weld_entry("Right4ED"))
203 , m_xScrolledWindow(m_xBuilder
->weld_scrolled_window("scrolledwindow", true))
204 , m_xAdjustLB(m_xBuilder
->weld_combo_box("adjustlb"))
205 , m_xPositionLB(m_xBuilder
->weld_combo_box("positionlb"))
206 , m_xCharStyleFT(m_xBuilder
->weld_label("styleft"))
207 , m_xCharStyleLB(m_xBuilder
->weld_combo_box("stylelb"))
208 , m_xStylistPB(m_xBuilder
->weld_button("styles"))
209 , m_xApplyPB(m_xBuilder
->weld_button("ok"))
210 , m_xClosePB(m_xBuilder
->weld_button("close"))
211 , m_xContentArea(m_xDialog
->weld_content_area())
212 , m_xGrid(m_xBuilder
->weld_widget("grid"))
213 , m_xPreviewWin(new RubyPreview
)
214 , m_xPreview(new weld::CustomWeld(*m_xBuilder
, "preview", *m_xPreviewWin
))
216 m_xCharStyleLB
->make_sorted();
217 m_xPreviewWin
->setRubyDialog(this);
218 m_xScrolledWindow
->set_size_request(-1, m_xGrid
->get_preferred_size().Height());
219 m_xScrolledWindow
->set_vpolicy(VclPolicyType::NEVER
);
221 aEditArr
[0] = m_xLeft1ED
.get();
222 aEditArr
[1] = m_xRight1ED
.get();
223 aEditArr
[2] = m_xLeft2ED
.get();
224 aEditArr
[3] = m_xRight2ED
.get();
225 aEditArr
[4] = m_xLeft3ED
.get();
226 aEditArr
[5] = m_xRight3ED
.get();
227 aEditArr
[6] = m_xLeft4ED
.get();
228 aEditArr
[7] = m_xRight4ED
.get();
230 m_xApplyPB
->connect_clicked(LINK(this, SvxRubyDialog
, ApplyHdl_Impl
));
231 m_xClosePB
->connect_clicked(LINK(this, SvxRubyDialog
, CloseHdl_Impl
));
232 m_xStylistPB
->connect_clicked(LINK(this, SvxRubyDialog
, StylistHdl_Impl
));
233 m_xAdjustLB
->connect_changed(LINK(this, SvxRubyDialog
, AdjustHdl_Impl
));
234 m_xPositionLB
->connect_changed(LINK(this, SvxRubyDialog
, PositionHdl_Impl
));
235 m_xCharStyleLB
->connect_changed(LINK(this, SvxRubyDialog
, CharStyleHdl_Impl
));
237 Link
<weld::ScrolledWindow
&, void> aScrLk(LINK(this, SvxRubyDialog
, ScrollHdl_Impl
));
238 m_xScrolledWindow
->connect_vadjustment_changed(aScrLk
);
240 Link
<weld::Entry
&, void> aEditLk(LINK(this, SvxRubyDialog
, EditModifyHdl_Impl
));
241 Link
<weld::Widget
&, void> aFocusLk(LINK(this, SvxRubyDialog
, EditFocusHdl_Impl
));
242 Link
<const KeyEvent
&, bool> aKeyUpDownLk(LINK(this, SvxRubyDialog
, KeyUpDownHdl_Impl
));
243 Link
<const KeyEvent
&, bool> aKeyTabUpDownLk(LINK(this, SvxRubyDialog
, KeyUpDownTabHdl_Impl
));
244 for (sal_uInt16 i
= 0; i
< 8; i
++)
246 aEditArr
[i
]->connect_changed(aEditLk
);
247 aEditArr
[i
]->connect_focus_in(aFocusLk
);
249 aEditArr
[i
]->connect_key_press(aKeyTabUpDownLk
);
251 aEditArr
[i
]->connect_key_press(aKeyUpDownLk
);
255 SvxRubyDialog::~SvxRubyDialog()
257 ClearCharStyleList();
259 m_pImpl
->disposing(aEvent
);
262 void SvxRubyDialog::ClearCharStyleList() { m_xCharStyleLB
->clear(); }
264 void SvxRubyDialog::Close()
268 SfxViewFrame
* pViewFrame
= SfxViewFrame::Current();
270 pViewFrame
->ToggleChildWindow(SID_RUBY_DIALOG
);
273 void SvxRubyDialog::Activate()
275 SfxModelessDialogController::Activate();
276 if (m_pImpl
->IsDisposing())
278 // tdf#141967/tdf#152495 if Activate is called during tear down bail early
282 //get selection from current view frame
283 SfxViewFrame
* pCurFrm
= SfxViewFrame::Current();
284 Reference
<XController
> xCtrl(pCurFrm
? pCurFrm
->GetFrame().GetController() : nullptr);
285 m_pImpl
->SetController(xCtrl
);
286 if (!m_pImpl
->HasSelectionChanged())
289 Reference
<XRubySelection
> xRubySel
= m_pImpl
->GetRubySelection();
290 m_pImpl
->UpdateRubyValues();
291 EnableControls(xRubySel
.is());
294 Reference
<XModel
> xModel
= m_pImpl
->GetModel();
295 const OUString sCharStyleSelect
= m_xCharStyleLB
->get_active_text();
296 ClearCharStyleList();
297 Reference
<XStyleFamiliesSupplier
> xSupplier(xModel
, UNO_QUERY
);
302 Reference
<XNameAccess
> xFam
= xSupplier
->getStyleFamilies();
303 Any aChar
= xFam
->getByName("CharacterStyles");
304 Reference
<XNameContainer
> xChar
;
306 Reference
<XIndexAccess
> xCharIdx(xChar
, UNO_QUERY
);
309 OUString
sUIName("DisplayName");
310 for (sal_Int32 nStyle
= 0; nStyle
< xCharIdx
->getCount(); nStyle
++)
312 Any aStyle
= xCharIdx
->getByIndex(nStyle
);
313 Reference
<XStyle
> xStyle
;
315 Reference
<XPropertySet
> xPrSet(xStyle
, UNO_QUERY
);
316 OUString sName
, sCoreName
;
319 Reference
<XPropertySetInfo
> xInfo
= xPrSet
->getPropertySetInfo();
320 if (xInfo
->hasPropertyByName(sUIName
))
322 Any aName
= xPrSet
->getPropertyValue(sUIName
);
328 sCoreName
= xStyle
->getName();
332 if (!sName
.isEmpty())
334 m_xCharStyleLB
->append(sCoreName
, sName
);
339 catch (const Exception
&)
341 TOOLS_WARN_EXCEPTION("svx.dialog", "exception in style access");
343 if (!sCharStyleSelect
.isEmpty())
344 m_xCharStyleLB
->set_active_text(sCharStyleSelect
);
346 m_xCharStyleLB
->set_sensitive(xSupplier
.is());
347 m_xCharStyleFT
->set_sensitive(xSupplier
.is());
350 m_xPreviewWin
->Invalidate();
353 void SvxRubyDialog::SetRubyText(sal_Int32 nPos
, weld::Entry
& rLeft
, weld::Entry
& rRight
)
355 OUString sLeft
, sRight
;
356 const Sequence
<PropertyValues
>& aRubyValues
= m_pImpl
->GetRubyValues();
357 bool bEnable
= aRubyValues
.getLength() > nPos
;
360 const Sequence
<PropertyValue
> aProps
= aRubyValues
.getConstArray()[nPos
];
361 for (const PropertyValue
& rProp
: aProps
)
363 if (rProp
.Name
== cRubyBaseText
)
364 rProp
.Value
>>= sLeft
;
365 else if (rProp
.Name
== cRubyText
)
366 rProp
.Value
>>= sRight
;
373 rLeft
.set_sensitive(bEnable
);
374 rRight
.set_sensitive(bEnable
);
375 rLeft
.set_text(sLeft
);
376 rRight
.set_text(sRight
);
381 void SvxRubyDialog::GetRubyText()
383 tools::Long nTempLastPos
= GetLastPos();
384 Sequence
<PropertyValues
>& aRubyValues
= m_pImpl
->GetRubyValues();
385 auto aRubyValuesRange
= asNonConstRange(aRubyValues
);
386 for (int i
= 0; i
< 8; i
+= 2)
388 if (aEditArr
[i
]->get_sensitive()
389 && (aEditArr
[i
]->get_value_changed_from_saved()
390 || aEditArr
[i
+ 1]->get_value_changed_from_saved()))
392 DBG_ASSERT(aRubyValues
.getLength() > (i
/ 2 + nTempLastPos
), "wrong index");
394 for (PropertyValue
& propVal
: asNonConstRange(aRubyValuesRange
[i
/ 2 + nTempLastPos
]))
396 if (propVal
.Name
== cRubyBaseText
)
397 propVal
.Value
<<= aEditArr
[i
]->get_text();
398 else if (propVal
.Name
== cRubyText
)
399 propVal
.Value
<<= aEditArr
[i
+ 1]->get_text();
405 void SvxRubyDialog::Update()
407 const Sequence
<PropertyValues
>& aRubyValues
= m_pImpl
->GetRubyValues();
408 sal_Int32 nLen
= aRubyValues
.getLength();
409 m_xScrolledWindow
->vadjustment_configure(0, 0, !nLen
? 1 : nLen
, 1, 4, 4);
411 m_xScrolledWindow
->set_vpolicy(VclPolicyType::ALWAYS
);
413 m_xScrolledWindow
->set_vpolicy(VclPolicyType::NEVER
);
417 sal_Int16 nAdjust
= -1;
418 sal_Int16 nPosition
= -1;
419 OUString sCharStyleName
, sTmp
;
420 bool bCharStyleEqual
= true;
421 for (sal_Int32 nRuby
= 0; nRuby
< nLen
; nRuby
++)
423 const Sequence
<PropertyValue
>& rProps
= aRubyValues
.getConstArray()[nRuby
];
424 for (const PropertyValue
& rProp
: rProps
)
426 if (nAdjust
> -2 && rProp
.Name
== cRubyAdjust
)
428 sal_Int16 nTmp
= sal_Int16();
429 rProp
.Value
>>= nTmp
;
432 else if (nAdjust
!= nTmp
)
435 if (nPosition
> -2 && rProp
.Name
== cRubyPosition
)
437 sal_Int16 nTmp
= sal_Int16();
438 rProp
.Value
>>= nTmp
;
441 else if (nPosition
!= nTmp
)
444 if (bCharStyleEqual
&& rProp
.Name
== cRubyCharStyleName
)
446 rProp
.Value
>>= sTmp
;
448 sCharStyleName
= sTmp
;
449 else if (sCharStyleName
!= sTmp
)
450 bCharStyleEqual
= false;
456 //enable selection if the ruby list is empty
461 m_xAdjustLB
->set_active(nAdjust
);
463 m_xAdjustLB
->set_active(-1);
465 m_xPositionLB
->set_active(nPosition
);
466 if (!nLen
|| (bCharStyleEqual
&& sCharStyleName
.isEmpty()))
467 sCharStyleName
= "Rubies";
468 if (!sCharStyleName
.isEmpty())
470 for (int i
= 0, nEntryCount
= m_xCharStyleLB
->get_count(); i
< nEntryCount
; i
++)
472 OUString sCoreName
= m_xCharStyleLB
->get_id(i
);
473 if (sCharStyleName
== sCoreName
)
475 m_xCharStyleLB
->set_active(i
);
481 m_xCharStyleLB
->set_active(-1);
483 ScrollHdl_Impl(*m_xScrolledWindow
);
486 void SvxRubyDialog::GetCurrentText(OUString
& rBase
, OUString
& rRuby
)
488 rBase
= aEditArr
[nCurrentEdit
* 2]->get_text();
489 rRuby
= aEditArr
[nCurrentEdit
* 2 + 1]->get_text();
492 IMPL_LINK(SvxRubyDialog
, ScrollHdl_Impl
, weld::ScrolledWindow
&, rScroll
, void)
494 int nPos
= rScroll
.vadjustment_get_value();
495 if (GetLastPos() != nPos
)
499 SetRubyText(nPos
++, *m_xLeft1ED
, *m_xRight1ED
);
500 SetRubyText(nPos
++, *m_xLeft2ED
, *m_xRight2ED
);
501 SetRubyText(nPos
++, *m_xLeft3ED
, *m_xRight3ED
);
502 SetRubyText(nPos
, *m_xLeft4ED
, *m_xRight4ED
);
503 SetLastPos(nPos
- 3);
504 m_xPreviewWin
->Invalidate();
507 IMPL_LINK_NOARG(SvxRubyDialog
, ApplyHdl_Impl
, weld::Button
&, void)
509 const Sequence
<PropertyValues
>& aRubyValues
= m_pImpl
->GetRubyValues();
510 if (!aRubyValues
.hasElements())
513 PositionHdl_Impl(*m_xPositionLB
);
514 AdjustHdl_Impl(*m_xAdjustLB
);
515 CharStyleHdl_Impl(*m_xCharStyleLB
);
518 //reset all edit fields - SaveValue is called
519 ScrollHdl_Impl(*m_xScrolledWindow
);
521 Reference
<XRubySelection
> xSelection
= m_pImpl
->GetRubySelection();
522 if (IsModified() && xSelection
.is())
526 xSelection
->setRubyList(aRubyValues
, false);
528 catch (const Exception
&)
530 TOOLS_WARN_EXCEPTION("svx.dialog", "");
535 IMPL_LINK_NOARG(SvxRubyDialog
, CloseHdl_Impl
, weld::Button
&, void) { Close(); }
537 IMPL_LINK_NOARG(SvxRubyDialog
, StylistHdl_Impl
, weld::Button
&, void)
539 std::unique_ptr
<SfxBoolItem
> pState
;
540 SfxItemState eState
= pBindings
->QueryState(SID_STYLE_DESIGNER
, pState
);
541 if (eState
<= SfxItemState::SET
|| !pState
|| !pState
->GetValue())
543 pBindings
->GetDispatcher()->Execute(SID_STYLE_DESIGNER
,
544 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
548 IMPL_LINK(SvxRubyDialog
, AdjustHdl_Impl
, weld::ComboBox
&, rBox
, void)
551 sal_Int16 nAdjust
= rBox
.get_active();
552 for (PropertyValues
& rProps
: asNonConstRange(m_pImpl
->GetRubyValues()))
554 for (PropertyValue
& propVal
: asNonConstRange(rProps
))
556 if (propVal
.Name
== cRubyAdjust
)
557 propVal
.Value
<<= nAdjust
;
561 m_xPreviewWin
->Invalidate();
564 IMPL_LINK(SvxRubyDialog
, PositionHdl_Impl
, weld::ComboBox
&, rBox
, void)
567 sal_Int16 nPosition
= rBox
.get_active();
568 for (PropertyValues
& rProps
: asNonConstRange(m_pImpl
->GetRubyValues()))
570 for (PropertyValue
& propVal
: asNonConstRange(rProps
))
572 if (propVal
.Name
== cRubyPosition
)
573 propVal
.Value
<<= nPosition
;
577 m_xPreviewWin
->Invalidate();
580 IMPL_LINK_NOARG(SvxRubyDialog
, CharStyleHdl_Impl
, weld::ComboBox
&, void)
584 if (m_xCharStyleLB
->get_active() != -1)
585 sStyleName
= m_xCharStyleLB
->get_active_id();
586 for (PropertyValues
& rProps
: asNonConstRange(m_pImpl
->GetRubyValues()))
588 for (PropertyValue
& propVal
: asNonConstRange(rProps
))
590 if (propVal
.Name
== cRubyCharStyleName
)
592 propVal
.Value
<<= sStyleName
;
599 IMPL_LINK(SvxRubyDialog
, EditFocusHdl_Impl
, weld::Widget
&, rEdit
, void)
601 for (sal_uInt16 i
= 0; i
< 8; i
++)
603 if (&rEdit
== aEditArr
[i
])
605 nCurrentEdit
= i
/ 2;
609 m_xPreviewWin
->Invalidate();
612 IMPL_LINK(SvxRubyDialog
, EditModifyHdl_Impl
, weld::Entry
&, rEdit
, void)
614 EditFocusHdl_Impl(rEdit
);
617 bool SvxRubyDialog::EditScrollHdl_Impl(sal_Int32 nParam
)
621 if (nParam
> 0 && (aEditArr
[7]->has_focus() || aEditArr
[6]->has_focus()))
623 if (m_xScrolledWindow
->vadjustment_get_upper()
624 > m_xScrolledWindow
->vadjustment_get_value()
625 + m_xScrolledWindow
->vadjustment_get_page_size())
627 m_xScrolledWindow
->vadjustment_set_value(m_xScrolledWindow
->vadjustment_get_value()
629 aEditArr
[6]->grab_focus();
634 else if (m_xScrolledWindow
->vadjustment_get_value()
635 && (aEditArr
[0]->has_focus() || aEditArr
[1]->has_focus()))
637 m_xScrolledWindow
->vadjustment_set_value(m_xScrolledWindow
->vadjustment_get_value() - 1);
638 aEditArr
[1]->grab_focus();
642 ScrollHdl_Impl(*m_xScrolledWindow
);
646 bool SvxRubyDialog::EditJumpHdl_Impl(sal_Int32 nParam
)
648 bool bHandled
= false;
649 sal_uInt16 nIndex
= USHRT_MAX
;
650 for (sal_uInt16 i
= 0; i
< 8; i
++)
652 if (aEditArr
[i
]->has_focus())
660 aEditArr
[nIndex
+ 2]->grab_focus();
661 else if (EditScrollHdl_Impl(nParam
))
662 aEditArr
[nIndex
]->grab_focus();
667 aEditArr
[nIndex
- 2]->grab_focus();
668 else if (EditScrollHdl_Impl(nParam
))
669 aEditArr
[nIndex
]->grab_focus();
676 void SvxRubyDialog::AssertOneEntry() { m_pImpl
->AssertOneEntry(); }
678 void SvxRubyDialog::EnableControls(bool bEnable
)
680 m_xContentArea
->set_sensitive(bEnable
);
681 m_xApplyPB
->set_sensitive(bEnable
);
684 RubyPreview::RubyPreview()
685 : m_pParentDlg(nullptr)
689 RubyPreview::~RubyPreview() {}
691 void RubyPreview::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/)
693 rRenderContext
.Push(vcl::PushFlags::ALL
);
695 rRenderContext
.SetMapMode(MapMode(MapUnit::MapTwip
));
697 Size aWinSize
= rRenderContext
.GetOutputSize();
699 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
700 svtools::ColorConfig aColorConfig
;
702 Color
aNewTextColor(aColorConfig
.GetColorValue(svtools::FONTCOLOR
).nColor
);
703 Color
aNewFillColor(rStyleSettings
.GetWindowColor());
705 vcl::Font aFont
= rRenderContext
.GetFont();
706 aFont
.SetFontHeight(aWinSize
.Height() / 4);
707 aFont
.SetFillColor(aNewFillColor
);
708 aFont
.SetColor(aNewTextColor
);
709 rRenderContext
.SetFont(aFont
);
711 tools::Rectangle
aRect(Point(0, 0), aWinSize
);
712 rRenderContext
.SetLineColor();
713 rRenderContext
.SetFillColor(aFont
.GetFillColor());
714 rRenderContext
.DrawRect(aRect
);
716 OUString sBaseText
, sRubyText
;
717 m_pParentDlg
->GetCurrentText(sBaseText
, sRubyText
);
719 tools::Long nTextHeight
= rRenderContext
.GetTextHeight();
720 tools::Long nBaseWidth
= rRenderContext
.GetTextWidth(sBaseText
);
722 vcl::Font
aRubyFont(aFont
);
723 aRubyFont
.SetFontHeight(aRubyFont
.GetFontHeight() * 70 / 100);
724 rRenderContext
.SetFont(aRubyFont
);
725 tools::Long nRubyWidth
= rRenderContext
.GetTextWidth(sRubyText
);
726 rRenderContext
.SetFont(aFont
);
728 RubyAdjust nAdjust
= static_cast<RubyAdjust
>(m_pParentDlg
->m_xAdjustLB
->get_active());
729 //use center if no adjustment is available
730 if (nAdjust
> RubyAdjust_INDENT_BLOCK
)
731 nAdjust
= RubyAdjust_CENTER
;
733 //which part is stretched ?
734 bool bRubyStretch
= nBaseWidth
>= nRubyWidth
;
736 tools::Long nCenter
= aWinSize
.Width() / 2;
737 tools::Long nHalfWidth
= std::max(nBaseWidth
, nRubyWidth
) / 2;
738 tools::Long nLeftStart
= nCenter
- nHalfWidth
;
739 tools::Long nRightEnd
= nCenter
+ nHalfWidth
;
741 // Default values for TOP or no selection
742 tools::Long nYRuby
= aWinSize
.Height() / 4 - nTextHeight
/ 2;
743 tools::Long nYBase
= aWinSize
.Height() * 3 / 4 - nTextHeight
/ 2;
745 sal_Int16 nRubyPos
= m_pParentDlg
->m_xPositionLB
->get_active();
746 if (nRubyPos
== 1) // BOTTOM
747 std::swap(nYRuby
, nYBase
);
748 else if (nRubyPos
== 2) // RIGHT ( vertically )
750 // Align the ruby text and base text to the vertical center.
751 nYBase
= (aWinSize
.Height() - nTextHeight
) / 2;
752 nYRuby
= (aWinSize
.Height() - nRubyWidth
) / 2;
754 // Align the ruby text at the right side of the base text
755 nAdjust
= RubyAdjust_RIGHT
;
756 nHalfWidth
= nBaseWidth
/ 2;
757 nLeftStart
= nCenter
- nHalfWidth
;
758 nRightEnd
= nCenter
+ nHalfWidth
+ nRubyWidth
+ nTextHeight
;
759 // Render base text first, then render ruby text on the right.
762 aRubyFont
.SetVertical(true);
763 aRubyFont
.SetOrientation(2700_deg10
);
766 tools::Long nYOutput
;
767 tools::Long nOutTextWidth
;
768 OUString sOutputText
;
772 rRenderContext
.DrawText(Point(nLeftStart
, nYBase
), sBaseText
);
774 sOutputText
= sRubyText
;
775 nOutTextWidth
= nRubyWidth
;
776 rRenderContext
.SetFont(aRubyFont
);
780 rRenderContext
.SetFont(aRubyFont
);
781 rRenderContext
.DrawText(Point(nLeftStart
, nYRuby
), sRubyText
);
783 sOutputText
= sBaseText
;
784 nOutTextWidth
= nBaseWidth
;
785 rRenderContext
.SetFont(aFont
);
790 case RubyAdjust_LEFT
:
791 rRenderContext
.DrawText(Point(nLeftStart
, nYOutput
), sOutputText
);
793 case RubyAdjust_RIGHT
:
794 rRenderContext
.DrawText(Point(nRightEnd
- nOutTextWidth
, nYOutput
), sOutputText
);
796 case RubyAdjust_INDENT_BLOCK
:
798 tools::Long nCharWidth
= rRenderContext
.GetTextWidth("X");
799 if (nOutTextWidth
< (nRightEnd
- nLeftStart
- nCharWidth
))
802 nLeftStart
+= nCharWidth
;
803 nRightEnd
-= nCharWidth
;
807 case RubyAdjust_BLOCK
:
809 if (sOutputText
.getLength() > 1)
811 sal_Int32 nCount
= sOutputText
.getLength();
813 = ((nRightEnd
- nLeftStart
) - rRenderContext
.GetTextWidth(sOutputText
))
815 for (sal_Int32 i
= 0; i
< nCount
; i
++)
817 OUString
sChar(sOutputText
[i
]);
818 rRenderContext
.DrawText(Point(nLeftStart
, nYOutput
), sChar
);
819 tools::Long nCharWidth
= rRenderContext
.GetTextWidth(sChar
);
820 nLeftStart
+= nCharWidth
+ nSpace
;
826 case RubyAdjust_CENTER
:
827 rRenderContext
.DrawText(Point(nCenter
- nOutTextWidth
/ 2, nYOutput
), sOutputText
);
832 rRenderContext
.Pop();
835 void RubyPreview::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
837 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 40,
838 pDrawingArea
->get_text_height() * 7);
839 CustomWidgetController::SetDrawingArea(pDrawingArea
);
842 IMPL_LINK(SvxRubyDialog
, KeyUpDownHdl_Impl
, const KeyEvent
&, rKEvt
, bool)
844 bool bHandled
= false;
845 const vcl::KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
846 sal_uInt16 nCode
= rKeyCode
.GetCode();
847 if (KEY_UP
== nCode
|| KEY_DOWN
== nCode
)
849 sal_Int32 nParam
= KEY_UP
== nCode
? -1 : 1;
850 bHandled
= EditJumpHdl_Impl(nParam
);
855 IMPL_LINK(SvxRubyDialog
, KeyUpDownTabHdl_Impl
, const KeyEvent
&, rKEvt
, bool)
857 bool bHandled
= false;
858 const vcl::KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
859 sal_uInt16 nMod
= rKeyCode
.GetModifier();
860 sal_uInt16 nCode
= rKeyCode
.GetCode();
861 if (nCode
== KEY_TAB
&& (!nMod
|| KEY_SHIFT
== nMod
))
863 sal_Int32 nParam
= KEY_SHIFT
== nMod
? -1 : 1;
864 if (EditScrollHdl_Impl(nParam
))
868 bHandled
= KeyUpDownHdl_Impl(rKEvt
);
872 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */