LibreOffice Module svx (master) 1
rubydialog.cxx
Go to the documentation of this file.
1/*
2 * This file is part of the LibreOffice project.
3 *
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/.
7 *
8 * This file incorporates work covered by the following license notice:
9 *
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 .
17 */
18
19#include <memory>
20#include <sal/config.h>
21#include <tools/debug.hxx>
22#include <tools/diagnose_ex.h>
23
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>
42#include <svtools/colorcfg.hxx>
43#include <vcl/event.hxx>
44#include <vcl/settings.hxx>
45#include <vcl/svapp.hxx>
46
47using namespace css::uno;
48using namespace css::frame;
49using namespace css::text;
50using namespace css::beans;
51using namespace css::style;
52using namespace css::view;
53using namespace css::lang;
54using namespace css::container;
55
57
58namespace
59{
60constexpr OUStringLiteral cRubyBaseText = u"RubyBaseText";
61constexpr OUStringLiteral cRubyText = u"RubyText";
62constexpr OUStringLiteral cRubyAdjust = u"RubyAdjust";
63constexpr OUStringLiteral cRubyPosition = u"RubyPosition";
64constexpr OUStringLiteral cRubyCharStyleName = u"RubyCharStyleName";
65
66} // end anonymous namespace
67
69 SfxBindings* pBindings, SfxChildWinInfo const* pInfo)
70 : SfxChildWindow(_pParent, nId)
71{
72 auto xDlg = std::make_shared<SvxRubyDialog>(pBindings, this, _pParent->GetFrameWeld());
73 SetController(xDlg);
74 xDlg->Initialize(pInfo);
75}
76
78
79class SvxRubyData_Impl : public cppu::WeakImplHelper<css::view::XSelectionChangeListener>
80{
81 Reference<XModel> xModel;
82 Reference<XRubySelection> xSelection;
83 Sequence<PropertyValues> aRubyValues;
84 Reference<XController> xController;
86
87public:
89 virtual ~SvxRubyData_Impl() override;
90
91 void SetController(const Reference<XController>& xCtrl);
92 Reference<XModel> const& GetModel()
93 {
94 if (!xController.is())
95 xModel = nullptr;
96 else
97 xModel = xController->getModel();
98 return xModel;
99 }
101 Reference<XRubySelection> const& GetRubySelection()
102 {
103 xSelection.set(xController, UNO_QUERY);
104 return xSelection;
105 }
107 {
108 if (!xSelection.is())
109 aRubyValues.realloc(0);
110 else
111 aRubyValues = xSelection->getRubyList(false);
112 bHasSelectionChanged = false;
113 }
114 Sequence<PropertyValues>& GetRubyValues() { return aRubyValues; }
115 void AssertOneEntry();
116
117 virtual void SAL_CALL selectionChanged(const css::lang::EventObject& aEvent) override;
118 virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
119};
120
122 : bHasSelectionChanged(false)
123{
124}
125
127
128void SvxRubyData_Impl::SetController(const Reference<XController>& xCtrl)
129{
130 if (xCtrl.get() == xController.get())
131 return;
132
133 try
134 {
135 Reference<XSelectionSupplier> xSelSupp(xController, UNO_QUERY);
136 if (xSelSupp.is())
137 xSelSupp->removeSelectionChangeListener(this);
138
140 xController = xCtrl;
141 xSelSupp.set(xController, UNO_QUERY);
142 if (xSelSupp.is())
143 xSelSupp->addSelectionChangeListener(this);
144 }
145 catch (const Exception&)
146 {
147 }
148}
149
151
152void SvxRubyData_Impl::disposing(const EventObject&)
153{
154 try
155 {
156 Reference<XSelectionSupplier> xSelSupp(xController, UNO_QUERY);
157 if (xSelSupp.is())
158 xSelSupp->removeSelectionChangeListener(this);
159 }
160 catch (const Exception&)
161 {
162 }
163 xController = nullptr;
164}
165
167{
168 //create one entry
169 if (!aRubyValues.hasElements())
170 {
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;
180 }
181}
182
184 : SfxModelessDialogController(pBind, pCW, pParent, "svx/ui/asianphoneticguidedialog.ui",
185 "AsianPhoneticGuideDialog")
186 , nLastPos(0)
187 , nCurrentEdit(0)
188 , bModified(false)
189 , pBindings(pBind)
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))
213{
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);
218
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();
227
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));
234
235 Link<weld::ScrolledWindow&, void> aScrLk(LINK(this, SvxRubyDialog, ScrollHdl_Impl));
236 m_xScrolledWindow->connect_vadjustment_changed(aScrLk);
237
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++)
243 {
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);
250 }
251}
252
254{
256 EventObject aEvent;
257 m_pImpl->disposing(aEvent);
258}
259
261
263{
264 if (IsClosing())
265 return;
266 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
267 if (pViewFrame)
268 pViewFrame->ToggleChildWindow(SID_RUBY_DIALOG);
269}
270
272{
274 if (!m_xContentArea)
275 {
276 // tdf#141967 if Activate is called during tear down bail early
277 return;
278 }
279 //get selection from current view frame
281 Reference<XController> xCtrl = pCurFrm->GetFrame().GetController();
282 m_pImpl->SetController(xCtrl);
283 if (!m_pImpl->HasSelectionChanged())
284 return;
285
286 Reference<XRubySelection> xRubySel = m_pImpl->GetRubySelection();
287 m_pImpl->UpdateRubyValues();
288 EnableControls(xRubySel.is());
289 if (xRubySel.is())
290 {
291 Reference<XModel> xModel = m_pImpl->GetModel();
292 const OUString sCharStyleSelect = m_xCharStyleLB->get_active_text();
294 Reference<XStyleFamiliesSupplier> xSupplier(xModel, UNO_QUERY);
295 if (xSupplier.is())
296 {
297 try
298 {
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())
305 {
306 OUString sUIName("DisplayName");
307 for (sal_Int32 nStyle = 0; nStyle < xCharIdx->getCount(); nStyle++)
308 {
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())
315 {
316 Reference<XPropertySetInfo> xInfo = xPrSet->getPropertySetInfo();
317 if (xInfo->hasPropertyByName(sUIName))
318 {
319 Any aName = xPrSet->getPropertyValue(sUIName);
320 aName >>= sName;
321 }
322 }
323 if (xStyle.is())
324 {
325 sCoreName = xStyle->getName();
326 if (sName.isEmpty())
327 sName = sCoreName;
328 }
329 if (!sName.isEmpty())
330 {
331 m_xCharStyleLB->append(sCoreName, sName);
332 }
333 }
334 }
335 }
336 catch (const Exception&)
337 {
338 TOOLS_WARN_EXCEPTION("svx.dialog", "exception in style access");
339 }
340 if (!sCharStyleSelect.isEmpty())
341 m_xCharStyleLB->set_active_text(sCharStyleSelect);
342 }
343 m_xCharStyleLB->set_sensitive(xSupplier.is());
344 m_xCharStyleFT->set_sensitive(xSupplier.is());
345 }
346 Update();
347 m_xPreviewWin->Invalidate();
348}
349
350void SvxRubyDialog::SetRubyText(sal_Int32 nPos, weld::Entry& rLeft, weld::Entry& rRight)
351{
352 OUString sLeft, sRight;
353 const Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
354 bool bEnable = aRubyValues.getLength() > nPos;
355 if (bEnable)
356 {
357 const Sequence<PropertyValue> aProps = aRubyValues.getConstArray()[nPos];
358 for (const PropertyValue& rProp : aProps)
359 {
360 if (rProp.Name == cRubyBaseText)
361 rProp.Value >>= sLeft;
362 else if (rProp.Name == cRubyText)
363 rProp.Value >>= sRight;
364 }
365 }
366 else if (!nPos)
367 {
368 bEnable = true;
369 }
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();
376}
377
379{
380 tools::Long nTempLastPos = GetLastPos();
381 Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
382 auto aRubyValuesRange = asNonConstRange(aRubyValues);
383 for (int i = 0; i < 8; i += 2)
384 {
385 if (aEditArr[i]->get_sensitive()
386 && (aEditArr[i]->get_value_changed_from_saved()
387 || aEditArr[i + 1]->get_value_changed_from_saved()))
388 {
389 DBG_ASSERT(aRubyValues.getLength() > (i / 2 + nTempLastPos), "wrong index");
390 SetModified(true);
391 for (PropertyValue& propVal : asNonConstRange(aRubyValuesRange[i / 2 + nTempLastPos]))
392 {
393 if (propVal.Name == cRubyBaseText)
394 propVal.Value <<= aEditArr[i]->get_text();
395 else if (propVal.Name == cRubyText)
396 propVal.Value <<= aEditArr[i + 1]->get_text();
397 }
398 }
399 }
400}
401
403{
404 const Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
405 sal_Int32 nLen = aRubyValues.getLength();
406 m_xScrolledWindow->vadjustment_configure(0, 0, !nLen ? 1 : nLen, 1, 4, 4);
407 if (nLen > 4)
408 m_xScrolledWindow->set_vpolicy(VclPolicyType::ALWAYS);
409 else
410 m_xScrolledWindow->set_vpolicy(VclPolicyType::NEVER);
411 SetLastPos(0);
412 SetModified(false);
413
414 sal_Int16 nAdjust = -1;
415 sal_Int16 nPosition = -1;
416 OUString sCharStyleName, sTmp;
417 bool bCharStyleEqual = true;
418 for (sal_Int32 nRuby = 0; nRuby < nLen; nRuby++)
419 {
420 const Sequence<PropertyValue>& rProps = aRubyValues.getConstArray()[nRuby];
421 for (const PropertyValue& rProp : rProps)
422 {
423 if (nAdjust > -2 && rProp.Name == cRubyAdjust)
424 {
425 sal_Int16 nTmp = sal_Int16();
426 rProp.Value >>= nTmp;
427 if (!nRuby)
428 nAdjust = nTmp;
429 else if (nAdjust != nTmp)
430 nAdjust = -2;
431 }
432 if (nPosition > -2 && rProp.Name == cRubyPosition)
433 {
434 sal_Int16 nTmp = sal_Int16();
435 rProp.Value >>= nTmp;
436 if (!nRuby)
437 nPosition = nTmp;
438 else if (nPosition != nTmp)
439 nPosition = -2;
440 }
441 if (bCharStyleEqual && rProp.Name == cRubyCharStyleName)
442 {
443 rProp.Value >>= sTmp;
444 if (!nRuby)
445 sCharStyleName = sTmp;
446 else if (sCharStyleName != sTmp)
447 bCharStyleEqual = false;
448 }
449 }
450 }
451 if (!nLen)
452 {
453 //enable selection if the ruby list is empty
454 nAdjust = 0;
455 nPosition = 0;
456 }
457 if (nAdjust > -1)
458 m_xAdjustLB->set_active(nAdjust);
459 else
460 m_xAdjustLB->set_active(-1);
461 if (nPosition > -1)
462 m_xPositionLB->set_active(nPosition);
463 if (!nLen || (bCharStyleEqual && sCharStyleName.isEmpty()))
464 sCharStyleName = "Rubies";
465 if (!sCharStyleName.isEmpty())
466 {
467 for (int i = 0, nEntryCount = m_xCharStyleLB->get_count(); i < nEntryCount; i++)
468 {
469 OUString sCoreName = m_xCharStyleLB->get_id(i);
470 if (sCharStyleName == sCoreName)
471 {
472 m_xCharStyleLB->set_active(i);
473 break;
474 }
475 }
476 }
477 else
478 m_xCharStyleLB->set_active(-1);
479
480 ScrollHdl_Impl(*m_xScrolledWindow);
481}
482
483void SvxRubyDialog::GetCurrentText(OUString& rBase, OUString& rRuby)
484{
485 rBase = aEditArr[nCurrentEdit * 2]->get_text();
486 rRuby = aEditArr[nCurrentEdit * 2 + 1]->get_text();
487}
488
489IMPL_LINK(SvxRubyDialog, ScrollHdl_Impl, weld::ScrolledWindow&, rScroll, void)
490{
491 int nPos = rScroll.vadjustment_get_value();
492 if (GetLastPos() != nPos)
493 {
494 GetRubyText();
495 }
496 SetRubyText(nPos++, *m_xLeft1ED, *m_xRight1ED);
497 SetRubyText(nPos++, *m_xLeft2ED, *m_xRight2ED);
498 SetRubyText(nPos++, *m_xLeft3ED, *m_xRight3ED);
499 SetRubyText(nPos, *m_xLeft4ED, *m_xRight4ED);
500 SetLastPos(nPos - 3);
501 m_xPreviewWin->Invalidate();
502}
503
505{
506 const Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
507 if (!aRubyValues.hasElements())
508 {
509 AssertOneEntry();
510 PositionHdl_Impl(*m_xPositionLB);
511 AdjustHdl_Impl(*m_xAdjustLB);
512 CharStyleHdl_Impl(*m_xCharStyleLB);
513 }
514 GetRubyText();
515 //reset all edit fields - SaveValue is called
516 ScrollHdl_Impl(*m_xScrolledWindow);
517
518 Reference<XRubySelection> xSelection = m_pImpl->GetRubySelection();
519 if (IsModified() && xSelection.is())
520 {
521 try
522 {
523 xSelection->setRubyList(aRubyValues, false);
524 }
525 catch (const Exception&)
526 {
527 TOOLS_WARN_EXCEPTION("svx.dialog", "");
528 }
529 }
530}
531
532IMPL_LINK_NOARG(SvxRubyDialog, CloseHdl_Impl, weld::Button&, void) { Close(); }
533
535{
536 std::unique_ptr<SfxBoolItem> pState;
537 SfxItemState eState = pBindings->QueryState(SID_STYLE_DESIGNER, pState);
538 if (eState <= SfxItemState::SET || !pState || !pState->GetValue())
539 {
540 pBindings->GetDispatcher()->Execute(SID_STYLE_DESIGNER,
541 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
542 }
543}
544
545IMPL_LINK(SvxRubyDialog, AdjustHdl_Impl, weld::ComboBox&, rBox, void)
546{
547 AssertOneEntry();
548 sal_Int16 nAdjust = rBox.get_active();
549 for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues()))
550 {
551 for (PropertyValue& propVal : asNonConstRange(rProps))
552 {
553 if (propVal.Name == cRubyAdjust)
554 propVal.Value <<= nAdjust;
555 }
556 SetModified(true);
557 }
558 m_xPreviewWin->Invalidate();
559}
560
561IMPL_LINK(SvxRubyDialog, PositionHdl_Impl, weld::ComboBox&, rBox, void)
562{
563 AssertOneEntry();
564 sal_Int16 nPosition = rBox.get_active();
565 for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues()))
566 {
567 for (PropertyValue& propVal : asNonConstRange(rProps))
568 {
569 if (propVal.Name == cRubyPosition)
570 propVal.Value <<= nPosition;
571 }
572 SetModified(true);
573 }
574 m_xPreviewWin->Invalidate();
575}
576
578{
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()))
584 {
585 for (PropertyValue& propVal : asNonConstRange(rProps))
586 {
587 if (propVal.Name == cRubyCharStyleName)
588 {
589 propVal.Value <<= sStyleName;
590 }
591 }
592 SetModified(true);
593 }
594}
595
596IMPL_LINK(SvxRubyDialog, EditFocusHdl_Impl, weld::Widget&, rEdit, void)
597{
598 for (sal_uInt16 i = 0; i < 8; i++)
599 {
600 if (&rEdit == aEditArr[i])
601 {
602 nCurrentEdit = i / 2;
603 break;
604 }
605 }
606 m_xPreviewWin->Invalidate();
607}
608
609IMPL_LINK(SvxRubyDialog, EditModifyHdl_Impl, weld::Entry&, rEdit, void)
610{
611 EditFocusHdl_Impl(rEdit);
612}
613
615{
616 bool bRet = false;
617 //scroll forward
618 if (nParam > 0 && (aEditArr[7]->has_focus() || aEditArr[6]->has_focus()))
619 {
620 if (m_xScrolledWindow->vadjustment_get_upper()
621 > m_xScrolledWindow->vadjustment_get_value()
622 + m_xScrolledWindow->vadjustment_get_page_size())
623 {
624 m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_value()
625 + 1);
626 aEditArr[6]->grab_focus();
627 bRet = true;
628 }
629 }
630 //scroll backward
631 else if (m_xScrolledWindow->vadjustment_get_value()
632 && (aEditArr[0]->has_focus() || aEditArr[1]->has_focus()))
633 {
634 m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_value() - 1);
635 aEditArr[1]->grab_focus();
636 bRet = true;
637 }
638 if (bRet)
639 ScrollHdl_Impl(*m_xScrolledWindow);
640 return bRet;
641}
642
644{
645 bool bHandled = false;
646 sal_uInt16 nIndex = USHRT_MAX;
647 for (sal_uInt16 i = 0; i < 8; i++)
648 {
649 if (aEditArr[i]->has_focus())
650 nIndex = i;
651 }
652 if (nIndex < 8)
653 {
654 if (nParam > 0)
655 {
656 if (nIndex < 6)
657 aEditArr[nIndex + 2]->grab_focus();
658 else if (EditScrollHdl_Impl(nParam))
660 }
661 else
662 {
663 if (nIndex > 1)
664 aEditArr[nIndex - 2]->grab_focus();
665 else if (EditScrollHdl_Impl(nParam))
667 }
668 bHandled = true;
669 }
670 return bHandled;
671}
672
673void SvxRubyDialog::AssertOneEntry() { m_pImpl->AssertOneEntry(); }
674
676{
677 m_xContentArea->set_sensitive(bEnable);
678 m_xApplyPB->set_sensitive(bEnable);
679}
680
682 : m_pParentDlg(nullptr)
683{
684}
685
687
688void RubyPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
689{
690 rRenderContext.Push(vcl::PushFlags::ALL);
691
692 rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip));
693
694 Size aWinSize = rRenderContext.GetOutputSize();
695
696 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
697 svtools::ColorConfig aColorConfig;
698
699 Color aNewTextColor(aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor);
700 Color aNewFillColor(rStyleSettings.GetWindowColor());
701
702 vcl::Font aFont = rRenderContext.GetFont();
703 aFont.SetFontHeight(aWinSize.Height() / 4);
704 aFont.SetFillColor(aNewFillColor);
705 aFont.SetColor(aNewTextColor);
706 rRenderContext.SetFont(aFont);
707
708 tools::Rectangle aRect(Point(0, 0), aWinSize);
709 rRenderContext.SetLineColor();
710 rRenderContext.SetFillColor(aFont.GetFillColor());
711 rRenderContext.DrawRect(aRect);
712
713 OUString sBaseText, sRubyText;
714 m_pParentDlg->GetCurrentText(sBaseText, sRubyText);
715
716 tools::Long nTextHeight = rRenderContext.GetTextHeight();
717 tools::Long nBaseWidth = rRenderContext.GetTextWidth(sBaseText);
718
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);
724
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;
729
730 //which part is stretched ?
731 bool bRubyStretch = nBaseWidth >= nRubyWidth;
732
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;
737
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;
741
742 sal_Int16 nRubyPos = m_pParentDlg->m_xPositionLB->get_active();
743 if (nRubyPos == 1) // BOTTOM
744 {
745 tools::Long nTmp = nYRuby;
746 nYRuby = nYBase;
747 nYBase = nTmp;
748 }
749 else if (nRubyPos == 2) // RIGHT ( vertically )
750 {
751 // Align the ruby text and base text to the vertical center.
752 nYBase = (aWinSize.Height() - nTextHeight) / 2;
753 nYRuby = (aWinSize.Height() - nRubyWidth) / 2;
754
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;
762
763 aRubyFont.SetVertical(true);
764 aRubyFont.SetOrientation(2700_deg10);
765 }
766
767 tools::Long nYOutput;
768 tools::Long nOutTextWidth;
769 OUString sOutputText;
770
771 if (bRubyStretch)
772 {
773 rRenderContext.DrawText(Point(nLeftStart, nYBase), sBaseText);
774 nYOutput = nYRuby;
775 sOutputText = sRubyText;
776 nOutTextWidth = nRubyWidth;
777 rRenderContext.SetFont(aRubyFont);
778 }
779 else
780 {
781 rRenderContext.SetFont(aRubyFont);
782 rRenderContext.DrawText(Point(nLeftStart, nYRuby), sRubyText);
783 nYOutput = nYBase;
784 sOutputText = sBaseText;
785 nOutTextWidth = nBaseWidth;
786 rRenderContext.SetFont(aFont);
787 }
788
789 switch (nAdjust)
790 {
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:
798 {
799 tools::Long nCharWidth = rRenderContext.GetTextWidth("X");
800 if (nOutTextWidth < (nRightEnd - nLeftStart - nCharWidth))
801 {
802 nCharWidth /= 2;
803 nLeftStart += nCharWidth;
804 nRightEnd -= nCharWidth;
805 }
806 [[fallthrough]];
807 }
808 case RubyAdjust_BLOCK:
809 {
810 if (sOutputText.getLength() > 1)
811 {
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++)
817 {
818 OUString sChar(sOutputText[i]);
819 rRenderContext.DrawText(Point(nLeftStart, nYOutput), sChar);
820 tools::Long nCharWidth = rRenderContext.GetTextWidth(sChar);
821 nLeftStart += nCharWidth + nSpace;
822 }
823 break;
824 }
825 [[fallthrough]];
826 }
827 case RubyAdjust_CENTER:
828 rRenderContext.DrawText(Point(nCenter - nOutTextWidth / 2, nYOutput), sOutputText);
829 break;
830 default:
831 break;
832 }
833 rRenderContext.Pop();
834}
835
837{
838 pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 40,
839 pDrawingArea->get_text_height() * 7);
840 CustomWidgetController::SetDrawingArea(pDrawingArea);
841}
842
843IMPL_LINK(SvxRubyDialog, KeyUpDownHdl_Impl, const KeyEvent&, rKEvt, bool)
844{
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)
849 {
850 sal_Int32 nParam = KEY_UP == nCode ? -1 : 1;
851 bHandled = EditJumpHdl_Impl(nParam);
852 }
853 return bHandled;
854}
855
856IMPL_LINK(SvxRubyDialog, KeyUpDownTabHdl_Impl, const KeyEvent&, rKEvt, bool)
857{
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))
863 {
864 sal_Int32 nParam = KEY_SHIFT == nMod ? -1 : 1;
865 if (EditScrollHdl_Impl(nParam))
866 bHandled = true;
867 }
868 if (!bHandled)
869 bHandled = KeyUpDownHdl_Impl(rKEvt);
870 return bHandled;
871}
872
873/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
OUString sCharStyleName
Reference< XExecutableDialog > m_xDialog
AnyEventRef aEvent
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Size GetOutputSize() const
const vcl::Font & GetFont() const
void SetFont(const vcl::Font &rNewFont)
void DrawRect(const tools::Rectangle &rRect)
void SetLineColor()
void SetMapMode()
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void SetFillColor()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
tools::Long GetTextHeight() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
virtual void SetDrawingArea(weld::DrawingArea *pDrawingArea) override
Definition: rubydialog.cxx:836
SvxRubyDialog * m_pParentDlg
Definition: rubydialog.hxx:34
virtual ~RubyPreview() override
Definition: rubydialog.cxx:686
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
Definition: rubydialog.cxx:688
void SetController(std::shared_ptr< SfxDialogController > controller)
virtual SfxChildWinInfo GetInfo() const
css::uno::Reference< css::frame::XController > GetController() const
virtual void Activate() override
void ToggleChildWindow(sal_uInt16)
static SfxViewFrame * Current()
SfxFrame & GetFrame() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
const Color & GetWindowColor() const
SvxRubyChildWindow(vcl::Window *, sal_uInt16, SfxBindings *, SfxChildWinInfo const *)
Definition: rubydialog.cxx:68
Reference< XController > xController
Definition: rubydialog.cxx:84
virtual void SAL_CALL selectionChanged(const css::lang::EventObject &aEvent) override
Definition: rubydialog.cxx:150
void UpdateRubyValues()
Definition: rubydialog.cxx:106
bool bHasSelectionChanged
Definition: rubydialog.cxx:85
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: rubydialog.cxx:152
Reference< XRubySelection > const & GetRubySelection()
Definition: rubydialog.cxx:101
Sequence< PropertyValues > & GetRubyValues()
Definition: rubydialog.cxx:114
void SetController(const Reference< XController > &xCtrl)
Definition: rubydialog.cxx:128
Sequence< PropertyValues > aRubyValues
Definition: rubydialog.cxx:83
Reference< XModel > xModel
Definition: rubydialog.cxx:81
virtual ~SvxRubyData_Impl() override
Definition: rubydialog.cxx:126
Reference< XRubySelection > xSelection
Definition: rubydialog.cxx:82
bool HasSelectionChanged() const
Definition: rubydialog.cxx:100
Reference< XModel > const & GetModel()
Definition: rubydialog.cxx:92
std::unique_ptr< weld::Entry > m_xRight1ED
Definition: rubydialog.hxx:70
std::unique_ptr< weld::Widget > m_xGrid
Definition: rubydialog.hxx:92
tools::Long nCurrentEdit
Definition: rubydialog.hxx:61
std::unique_ptr< weld::Button > m_xStylistPB
Definition: rubydialog.hxx:86
virtual ~SvxRubyDialog() override
Definition: rubydialog.cxx:253
std::unique_ptr< weld::Entry > m_xRight4ED
Definition: rubydialog.hxx:76
std::unique_ptr< weld::Button > m_xClosePB
Definition: rubydialog.hxx:89
rtl::Reference< SvxRubyData_Impl > m_pImpl
Definition: rubydialog.hxx:64
std::unique_ptr< weld::Entry > m_xRight3ED
Definition: rubydialog.hxx:74
void EnableControls(bool bEnable)
Definition: rubydialog.cxx:675
std::unique_ptr< weld::Entry > m_xLeft3ED
Definition: rubydialog.hxx:73
virtual void Activate() override
Definition: rubydialog.cxx:271
std::unique_ptr< weld::Entry > m_xLeft2ED
Definition: rubydialog.hxx:71
std::unique_ptr< weld::Entry > m_xLeft1ED
Definition: rubydialog.hxx:69
void GetCurrentText(OUString &rBase, OUString &rRuby)
Definition: rubydialog.cxx:483
bool EditJumpHdl_Impl(sal_Int32 nParam)
Definition: rubydialog.cxx:643
weld::Entry * aEditArr[8]
Definition: rubydialog.hxx:65
void ClearCharStyleList()
Definition: rubydialog.cxx:260
std::unique_ptr< weld::ScrolledWindow > m_xScrolledWindow
Definition: rubydialog.hxx:78
bool EditScrollHdl_Impl(sal_Int32 nParam)
Definition: rubydialog.cxx:614
void AssertOneEntry()
Definition: rubydialog.cxx:673
std::unique_ptr< weld::Button > m_xApplyPB
Definition: rubydialog.hxx:88
std::unique_ptr< weld::ComboBox > m_xCharStyleLB
Definition: rubydialog.hxx:85
std::unique_ptr< weld::Container > m_xContentArea
Definition: rubydialog.hxx:91
void SetRubyText(sal_Int32 nPos, weld::Entry &rLeft, weld::Entry &rRight)
Definition: rubydialog.cxx:350
SvxRubyDialog(SfxBindings *pBindings, SfxChildWindow *pCW, weld::Window *pParent)
Definition: rubydialog.cxx:183
std::unique_ptr< weld::Entry > m_xLeft4ED
Definition: rubydialog.hxx:75
virtual void Close() override
Definition: rubydialog.cxx:262
void SetModified(bool bSet)
Definition: rubydialog.hxx:124
std::unique_ptr< weld::ComboBox > m_xPositionLB
Definition: rubydialog.hxx:82
std::unique_ptr< weld::Label > m_xCharStyleFT
Definition: rubydialog.hxx:84
std::unique_ptr< RubyPreview > m_xPreviewWin
Definition: rubydialog.hxx:94
void GetRubyText()
Definition: rubydialog.cxx:378
void SetLastPos(tools::Long nSet)
Definition: rubydialog.hxx:121
tools::Long GetLastPos() const
Definition: rubydialog.hxx:120
std::unique_ptr< weld::Entry > m_xRight2ED
Definition: rubydialog.hxx:72
std::unique_ptr< weld::ComboBox > m_xAdjustLB
Definition: rubydialog.hxx:80
ColorConfigValue GetColorValue(ColorConfigEntry eEntry, bool bSmart=true) const
tools::Long GetFontHeight() const
void SetOrientation(Degree10 nLineOrientation)
void SetVertical(bool bVertical)
void SetFillColor(const Color &)
void SetColor(const Color &)
void SetFontHeight(tools::Long nHeight)
const Color & GetFillColor() const
sal_uInt16 GetCode() const
sal_uInt16 GetModifier() const
weld::Window * GetFrameWeld() const
virtual void set_text(const OUString &rText)=0
virtual void connect_changed(const Link< Entry &, void > &rLink)
void save_value()
virtual OUString get_text() const=0
virtual int get_text_height() const=0
virtual void grab_focus()=0
virtual void set_sensitive(bool sensitive)=0
virtual void set_size_request(int nWidth, int nHeight)=0
virtual float get_approximate_digit_width() const=0
virtual bool has_focus() const=0
virtual void connect_key_press(const Link< const KeyEvent &, bool > &rLink)
virtual void connect_focus_in(const Link< Widget &, void > &rLink)
int nCount
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
float u
OUString sName
sal_Int32 nIndex
OUString aName
constexpr sal_uInt16 KEY_TAB
constexpr sal_uInt16 KEY_UP
constexpr sal_uInt16 KEY_DOWN
constexpr sal_uInt16 KEY_SHIFT
sal_uInt16 nPos
sal_uInt16 nCode
@ Exception
std::map< sal_Int32, std::shared_ptr< SetItemPropertyStorage > > PropertyValues
int i
Close
long Long
sal_Int16 nId
std::string GetValue
SfxItemState
SFX_IMPL_CHILDWINDOW(SvxRubyChildWindow, SID_RUBY_DIALOG)
IMPL_LINK(SvxRubyDialog, ScrollHdl_Impl, weld::ScrolledWindow &, rScroll, void)
Definition: rubydialog.cxx:489
IMPL_LINK_NOARG(SvxRubyDialog, ApplyHdl_Impl, weld::Button &, void)
Definition: rubydialog.cxx:504
Reference< XModel > xModel