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>
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;
87
88public:
90 virtual ~SvxRubyData_Impl() override;
91
92 void SetController(const Reference<XController>& xCtrl);
93 Reference<XModel> const& GetModel()
94 {
95 if (!xController.is())
96 xModel = nullptr;
97 else
98 xModel = xController->getModel();
99 return xModel;
100 }
102 bool IsDisposing() const { return bDisposing; }
103 Reference<XRubySelection> const& GetRubySelection()
104 {
105 xSelection.set(xController, UNO_QUERY);
106 return xSelection;
107 }
109 {
110 if (!xSelection.is())
111 aRubyValues.realloc(0);
112 else
113 aRubyValues = xSelection->getRubyList(false);
114 bHasSelectionChanged = false;
115 }
116 Sequence<PropertyValues>& GetRubyValues() { return aRubyValues; }
117 void AssertOneEntry();
118
119 virtual void SAL_CALL selectionChanged(const css::lang::EventObject& aEvent) override;
120 virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
121};
122
124 : bHasSelectionChanged(false)
125 , bDisposing(false)
126{
127}
128
130
131void SvxRubyData_Impl::SetController(const Reference<XController>& xCtrl)
132{
133 if (xCtrl.get() == xController.get())
134 return;
135
136 try
137 {
138 Reference<XSelectionSupplier> xSelSupp(xController, UNO_QUERY);
139 if (xSelSupp.is())
140 xSelSupp->removeSelectionChangeListener(this);
141
143 xController = xCtrl;
144 xSelSupp.set(xController, UNO_QUERY);
145 if (xSelSupp.is())
146 xSelSupp->addSelectionChangeListener(this);
147 }
148 catch (const Exception&)
149 {
150 }
151}
152
154
155void SvxRubyData_Impl::disposing(const EventObject&)
156{
157 try
158 {
159 Reference<XSelectionSupplier> xSelSupp(xController, UNO_QUERY);
160 if (xSelSupp.is())
161 xSelSupp->removeSelectionChangeListener(this);
162 }
163 catch (const Exception&)
164 {
165 }
166 xController = nullptr;
167 bDisposing = true;
168}
169
171{
172 //create one entry
173 if (!aRubyValues.hasElements())
174 {
175 aRubyValues.realloc(1);
176 Sequence<PropertyValue>& rValues = aRubyValues.getArray()[0];
177 rValues.realloc(5);
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;
184 }
185}
186
188 : SfxModelessDialogController(pBind, pCW, pParent, "svx/ui/asianphoneticguidedialog.ui",
189 "AsianPhoneticGuideDialog")
190 , nLastPos(0)
191 , nCurrentEdit(0)
192 , bModified(false)
193 , pBindings(pBind)
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))
215{
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);
220
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();
229
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));
236
237 Link<weld::ScrolledWindow&, void> aScrLk(LINK(this, SvxRubyDialog, ScrollHdl_Impl));
238 m_xScrolledWindow->connect_vadjustment_changed(aScrLk);
239
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++)
245 {
246 aEditArr[i]->connect_changed(aEditLk);
247 aEditArr[i]->connect_focus_in(aFocusLk);
248 if (!i || 7 == i)
249 aEditArr[i]->connect_key_press(aKeyTabUpDownLk);
250 else
251 aEditArr[i]->connect_key_press(aKeyUpDownLk);
252 }
253}
254
256{
258 EventObject aEvent;
259 m_pImpl->disposing(aEvent);
260}
261
263
265{
266 if (IsClosing())
267 return;
268 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
269 if (pViewFrame)
270 pViewFrame->ToggleChildWindow(SID_RUBY_DIALOG);
271}
272
274{
276 if (m_pImpl->IsDisposing())
277 {
278 // tdf#141967/tdf#152495 if Activate is called during tear down bail early
279 return;
280 }
281
282 //get selection from current view frame
284 Reference<XController> xCtrl(pCurFrm ? pCurFrm->GetFrame().GetController() : nullptr);
285 m_pImpl->SetController(xCtrl);
286 if (!m_pImpl->HasSelectionChanged())
287 return;
288
289 Reference<XRubySelection> xRubySel = m_pImpl->GetRubySelection();
290 m_pImpl->UpdateRubyValues();
291 EnableControls(xRubySel.is());
292 if (xRubySel.is())
293 {
294 Reference<XModel> xModel = m_pImpl->GetModel();
295 const OUString sCharStyleSelect = m_xCharStyleLB->get_active_text();
297 Reference<XStyleFamiliesSupplier> xSupplier(xModel, UNO_QUERY);
298 if (xSupplier.is())
299 {
300 try
301 {
302 Reference<XNameAccess> xFam = xSupplier->getStyleFamilies();
303 Any aChar = xFam->getByName("CharacterStyles");
304 Reference<XNameContainer> xChar;
305 aChar >>= xChar;
306 Reference<XIndexAccess> xCharIdx(xChar, UNO_QUERY);
307 if (xCharIdx.is())
308 {
309 OUString sUIName("DisplayName");
310 for (sal_Int32 nStyle = 0; nStyle < xCharIdx->getCount(); nStyle++)
311 {
312 Any aStyle = xCharIdx->getByIndex(nStyle);
313 Reference<XStyle> xStyle;
314 aStyle >>= xStyle;
315 Reference<XPropertySet> xPrSet(xStyle, UNO_QUERY);
316 OUString sName, sCoreName;
317 if (xPrSet.is())
318 {
319 Reference<XPropertySetInfo> xInfo = xPrSet->getPropertySetInfo();
320 if (xInfo->hasPropertyByName(sUIName))
321 {
322 Any aName = xPrSet->getPropertyValue(sUIName);
323 aName >>= sName;
324 }
325 }
326 if (xStyle.is())
327 {
328 sCoreName = xStyle->getName();
329 if (sName.isEmpty())
330 sName = sCoreName;
331 }
332 if (!sName.isEmpty())
333 {
334 m_xCharStyleLB->append(sCoreName, sName);
335 }
336 }
337 }
338 }
339 catch (const Exception&)
340 {
341 TOOLS_WARN_EXCEPTION("svx.dialog", "exception in style access");
342 }
343 if (!sCharStyleSelect.isEmpty())
344 m_xCharStyleLB->set_active_text(sCharStyleSelect);
345 }
346 m_xCharStyleLB->set_sensitive(xSupplier.is());
347 m_xCharStyleFT->set_sensitive(xSupplier.is());
348 }
349 Update();
350 m_xPreviewWin->Invalidate();
351}
352
353void SvxRubyDialog::SetRubyText(sal_Int32 nPos, weld::Entry& rLeft, weld::Entry& rRight)
354{
355 OUString sLeft, sRight;
356 const Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
357 bool bEnable = aRubyValues.getLength() > nPos;
358 if (bEnable)
359 {
360 const Sequence<PropertyValue> aProps = aRubyValues.getConstArray()[nPos];
361 for (const PropertyValue& rProp : aProps)
362 {
363 if (rProp.Name == cRubyBaseText)
364 rProp.Value >>= sLeft;
365 else if (rProp.Name == cRubyText)
366 rProp.Value >>= sRight;
367 }
368 }
369 else if (!nPos)
370 {
371 bEnable = true;
372 }
373 rLeft.set_sensitive(bEnable);
374 rRight.set_sensitive(bEnable);
375 rLeft.set_text(sLeft);
376 rRight.set_text(sRight);
377 rLeft.save_value();
378 rRight.save_value();
379}
380
382{
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)
387 {
388 if (aEditArr[i]->get_sensitive()
389 && (aEditArr[i]->get_value_changed_from_saved()
390 || aEditArr[i + 1]->get_value_changed_from_saved()))
391 {
392 DBG_ASSERT(aRubyValues.getLength() > (i / 2 + nTempLastPos), "wrong index");
393 SetModified(true);
394 for (PropertyValue& propVal : asNonConstRange(aRubyValuesRange[i / 2 + nTempLastPos]))
395 {
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();
400 }
401 }
402 }
403}
404
406{
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);
410 if (nLen > 4)
411 m_xScrolledWindow->set_vpolicy(VclPolicyType::ALWAYS);
412 else
413 m_xScrolledWindow->set_vpolicy(VclPolicyType::NEVER);
414 SetLastPos(0);
415 SetModified(false);
416
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++)
422 {
423 const Sequence<PropertyValue>& rProps = aRubyValues.getConstArray()[nRuby];
424 for (const PropertyValue& rProp : rProps)
425 {
426 if (nAdjust > -2 && rProp.Name == cRubyAdjust)
427 {
428 sal_Int16 nTmp = sal_Int16();
429 rProp.Value >>= nTmp;
430 if (!nRuby)
431 nAdjust = nTmp;
432 else if (nAdjust != nTmp)
433 nAdjust = -2;
434 }
435 if (nPosition > -2 && rProp.Name == cRubyPosition)
436 {
437 sal_Int16 nTmp = sal_Int16();
438 rProp.Value >>= nTmp;
439 if (!nRuby)
440 nPosition = nTmp;
441 else if (nPosition != nTmp)
442 nPosition = -2;
443 }
444 if (bCharStyleEqual && rProp.Name == cRubyCharStyleName)
445 {
446 rProp.Value >>= sTmp;
447 if (!nRuby)
448 sCharStyleName = sTmp;
449 else if (sCharStyleName != sTmp)
450 bCharStyleEqual = false;
451 }
452 }
453 }
454 if (!nLen)
455 {
456 //enable selection if the ruby list is empty
457 nAdjust = 0;
458 nPosition = 0;
459 }
460 if (nAdjust > -1)
461 m_xAdjustLB->set_active(nAdjust);
462 else
463 m_xAdjustLB->set_active(-1);
464 if (nPosition > -1)
465 m_xPositionLB->set_active(nPosition);
466 if (!nLen || (bCharStyleEqual && sCharStyleName.isEmpty()))
467 sCharStyleName = "Rubies";
468 if (!sCharStyleName.isEmpty())
469 {
470 for (int i = 0, nEntryCount = m_xCharStyleLB->get_count(); i < nEntryCount; i++)
471 {
472 OUString sCoreName = m_xCharStyleLB->get_id(i);
473 if (sCharStyleName == sCoreName)
474 {
475 m_xCharStyleLB->set_active(i);
476 break;
477 }
478 }
479 }
480 else
481 m_xCharStyleLB->set_active(-1);
482
483 ScrollHdl_Impl(*m_xScrolledWindow);
484}
485
486void SvxRubyDialog::GetCurrentText(OUString& rBase, OUString& rRuby)
487{
488 rBase = aEditArr[nCurrentEdit * 2]->get_text();
489 rRuby = aEditArr[nCurrentEdit * 2 + 1]->get_text();
490}
491
492IMPL_LINK(SvxRubyDialog, ScrollHdl_Impl, weld::ScrolledWindow&, rScroll, void)
493{
494 int nPos = rScroll.vadjustment_get_value();
495 if (GetLastPos() != nPos)
496 {
497 GetRubyText();
498 }
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();
505}
506
508{
509 const Sequence<PropertyValues>& aRubyValues = m_pImpl->GetRubyValues();
510 if (!aRubyValues.hasElements())
511 {
512 AssertOneEntry();
513 PositionHdl_Impl(*m_xPositionLB);
514 AdjustHdl_Impl(*m_xAdjustLB);
515 CharStyleHdl_Impl(*m_xCharStyleLB);
516 }
517 GetRubyText();
518 //reset all edit fields - SaveValue is called
519 ScrollHdl_Impl(*m_xScrolledWindow);
520
521 Reference<XRubySelection> xSelection = m_pImpl->GetRubySelection();
522 if (IsModified() && xSelection.is())
523 {
524 try
525 {
526 xSelection->setRubyList(aRubyValues, false);
527 }
528 catch (const Exception&)
529 {
530 TOOLS_WARN_EXCEPTION("svx.dialog", "");
531 }
532 }
533}
534
535IMPL_LINK_NOARG(SvxRubyDialog, CloseHdl_Impl, weld::Button&, void) { Close(); }
536
538{
539 std::unique_ptr<SfxBoolItem> pState;
540 SfxItemState eState = pBindings->QueryState(SID_STYLE_DESIGNER, pState);
541 if (eState <= SfxItemState::SET || !pState || !pState->GetValue())
542 {
543 pBindings->GetDispatcher()->Execute(SID_STYLE_DESIGNER,
544 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
545 }
546}
547
548IMPL_LINK(SvxRubyDialog, AdjustHdl_Impl, weld::ComboBox&, rBox, void)
549{
550 AssertOneEntry();
551 sal_Int16 nAdjust = rBox.get_active();
552 for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues()))
553 {
554 for (PropertyValue& propVal : asNonConstRange(rProps))
555 {
556 if (propVal.Name == cRubyAdjust)
557 propVal.Value <<= nAdjust;
558 }
559 SetModified(true);
560 }
561 m_xPreviewWin->Invalidate();
562}
563
564IMPL_LINK(SvxRubyDialog, PositionHdl_Impl, weld::ComboBox&, rBox, void)
565{
566 AssertOneEntry();
567 sal_Int16 nPosition = rBox.get_active();
568 for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues()))
569 {
570 for (PropertyValue& propVal : asNonConstRange(rProps))
571 {
572 if (propVal.Name == cRubyPosition)
573 propVal.Value <<= nPosition;
574 }
575 SetModified(true);
576 }
577 m_xPreviewWin->Invalidate();
578}
579
581{
582 AssertOneEntry();
583 OUString sStyleName;
584 if (m_xCharStyleLB->get_active() != -1)
585 sStyleName = m_xCharStyleLB->get_active_id();
586 for (PropertyValues& rProps : asNonConstRange(m_pImpl->GetRubyValues()))
587 {
588 for (PropertyValue& propVal : asNonConstRange(rProps))
589 {
590 if (propVal.Name == cRubyCharStyleName)
591 {
592 propVal.Value <<= sStyleName;
593 }
594 }
595 SetModified(true);
596 }
597}
598
599IMPL_LINK(SvxRubyDialog, EditFocusHdl_Impl, weld::Widget&, rEdit, void)
600{
601 for (sal_uInt16 i = 0; i < 8; i++)
602 {
603 if (&rEdit == aEditArr[i])
604 {
605 nCurrentEdit = i / 2;
606 break;
607 }
608 }
609 m_xPreviewWin->Invalidate();
610}
611
612IMPL_LINK(SvxRubyDialog, EditModifyHdl_Impl, weld::Entry&, rEdit, void)
613{
614 EditFocusHdl_Impl(rEdit);
615}
616
618{
619 bool bRet = false;
620 //scroll forward
621 if (nParam > 0 && (aEditArr[7]->has_focus() || aEditArr[6]->has_focus()))
622 {
623 if (m_xScrolledWindow->vadjustment_get_upper()
624 > m_xScrolledWindow->vadjustment_get_value()
625 + m_xScrolledWindow->vadjustment_get_page_size())
626 {
627 m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_value()
628 + 1);
629 aEditArr[6]->grab_focus();
630 bRet = true;
631 }
632 }
633 //scroll backward
634 else if (m_xScrolledWindow->vadjustment_get_value()
635 && (aEditArr[0]->has_focus() || aEditArr[1]->has_focus()))
636 {
637 m_xScrolledWindow->vadjustment_set_value(m_xScrolledWindow->vadjustment_get_value() - 1);
638 aEditArr[1]->grab_focus();
639 bRet = true;
640 }
641 if (bRet)
642 ScrollHdl_Impl(*m_xScrolledWindow);
643 return bRet;
644}
645
647{
648 bool bHandled = false;
649 sal_uInt16 nIndex = USHRT_MAX;
650 for (sal_uInt16 i = 0; i < 8; i++)
651 {
652 if (aEditArr[i]->has_focus())
653 nIndex = i;
654 }
655 if (nIndex < 8)
656 {
657 if (nParam > 0)
658 {
659 if (nIndex < 6)
660 aEditArr[nIndex + 2]->grab_focus();
661 else if (EditScrollHdl_Impl(nParam))
663 }
664 else
665 {
666 if (nIndex > 1)
667 aEditArr[nIndex - 2]->grab_focus();
668 else if (EditScrollHdl_Impl(nParam))
670 }
671 bHandled = true;
672 }
673 return bHandled;
674}
675
676void SvxRubyDialog::AssertOneEntry() { m_pImpl->AssertOneEntry(); }
677
679{
680 m_xContentArea->set_sensitive(bEnable);
681 m_xApplyPB->set_sensitive(bEnable);
682}
683
685 : m_pParentDlg(nullptr)
686{
687}
688
690
691void RubyPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
692{
693 rRenderContext.Push(vcl::PushFlags::ALL);
694
695 rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip));
696
697 Size aWinSize = rRenderContext.GetOutputSize();
698
699 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
700 svtools::ColorConfig aColorConfig;
701
702 Color aNewTextColor(aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor);
703 Color aNewFillColor(rStyleSettings.GetWindowColor());
704
705 vcl::Font aFont = rRenderContext.GetFont();
706 aFont.SetFontHeight(aWinSize.Height() / 4);
707 aFont.SetFillColor(aNewFillColor);
708 aFont.SetColor(aNewTextColor);
709 rRenderContext.SetFont(aFont);
710
711 tools::Rectangle aRect(Point(0, 0), aWinSize);
712 rRenderContext.SetLineColor();
713 rRenderContext.SetFillColor(aFont.GetFillColor());
714 rRenderContext.DrawRect(aRect);
715
716 OUString sBaseText, sRubyText;
717 m_pParentDlg->GetCurrentText(sBaseText, sRubyText);
718
719 tools::Long nTextHeight = rRenderContext.GetTextHeight();
720 tools::Long nBaseWidth = rRenderContext.GetTextWidth(sBaseText);
721
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);
727
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;
732
733 //which part is stretched ?
734 bool bRubyStretch = nBaseWidth >= nRubyWidth;
735
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;
740
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;
744
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 )
749 {
750 // Align the ruby text and base text to the vertical center.
751 nYBase = (aWinSize.Height() - nTextHeight) / 2;
752 nYRuby = (aWinSize.Height() - nRubyWidth) / 2;
753
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.
760 bRubyStretch = true;
761
762 aRubyFont.SetVertical(true);
763 aRubyFont.SetOrientation(2700_deg10);
764 }
765
766 tools::Long nYOutput;
767 tools::Long nOutTextWidth;
768 OUString sOutputText;
769
770 if (bRubyStretch)
771 {
772 rRenderContext.DrawText(Point(nLeftStart, nYBase), sBaseText);
773 nYOutput = nYRuby;
774 sOutputText = sRubyText;
775 nOutTextWidth = nRubyWidth;
776 rRenderContext.SetFont(aRubyFont);
777 }
778 else
779 {
780 rRenderContext.SetFont(aRubyFont);
781 rRenderContext.DrawText(Point(nLeftStart, nYRuby), sRubyText);
782 nYOutput = nYBase;
783 sOutputText = sBaseText;
784 nOutTextWidth = nBaseWidth;
785 rRenderContext.SetFont(aFont);
786 }
787
788 switch (nAdjust)
789 {
790 case RubyAdjust_LEFT:
791 rRenderContext.DrawText(Point(nLeftStart, nYOutput), sOutputText);
792 break;
793 case RubyAdjust_RIGHT:
794 rRenderContext.DrawText(Point(nRightEnd - nOutTextWidth, nYOutput), sOutputText);
795 break;
796 case RubyAdjust_INDENT_BLOCK:
797 {
798 tools::Long nCharWidth = rRenderContext.GetTextWidth("X");
799 if (nOutTextWidth < (nRightEnd - nLeftStart - nCharWidth))
800 {
801 nCharWidth /= 2;
802 nLeftStart += nCharWidth;
803 nRightEnd -= nCharWidth;
804 }
805 [[fallthrough]];
806 }
807 case RubyAdjust_BLOCK:
808 {
809 if (sOutputText.getLength() > 1)
810 {
811 sal_Int32 nCount = sOutputText.getLength();
812 tools::Long nSpace
813 = ((nRightEnd - nLeftStart) - rRenderContext.GetTextWidth(sOutputText))
814 / (nCount - 1);
815 for (sal_Int32 i = 0; i < nCount; i++)
816 {
817 OUString sChar(sOutputText[i]);
818 rRenderContext.DrawText(Point(nLeftStart, nYOutput), sChar);
819 tools::Long nCharWidth = rRenderContext.GetTextWidth(sChar);
820 nLeftStart += nCharWidth + nSpace;
821 }
822 break;
823 }
824 [[fallthrough]];
825 }
826 case RubyAdjust_CENTER:
827 rRenderContext.DrawText(Point(nCenter - nOutTextWidth / 2, nYOutput), sOutputText);
828 break;
829 default:
830 break;
831 }
832 rRenderContext.Pop();
833}
834
836{
837 pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 40,
838 pDrawingArea->get_text_height() * 7);
839 CustomWidgetController::SetDrawingArea(pDrawingArea);
840}
841
842IMPL_LINK(SvxRubyDialog, KeyUpDownHdl_Impl, const KeyEvent&, rKEvt, bool)
843{
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)
848 {
849 sal_Int32 nParam = KEY_UP == nCode ? -1 : 1;
850 bHandled = EditJumpHdl_Impl(nParam);
851 }
852 return bHandled;
853}
854
855IMPL_LINK(SvxRubyDialog, KeyUpDownTabHdl_Impl, const KeyEvent&, rKEvt, bool)
856{
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))
862 {
863 sal_Int32 nParam = KEY_SHIFT == nMod ? -1 : 1;
864 if (EditScrollHdl_Impl(nParam))
865 bHandled = true;
866 }
867 if (!bHandled)
868 bHandled = KeyUpDownHdl_Impl(rKEvt);
869 return bHandled;
870}
871
872/* 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:835
SvxRubyDialog * m_pParentDlg
Definition: rubydialog.hxx:34
virtual ~RubyPreview() override
Definition: rubydialog.cxx:689
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
Definition: rubydialog.cxx:691
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 SAL_WARN_UNUSED_RESULT 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:153
void UpdateRubyValues()
Definition: rubydialog.cxx:108
bool bHasSelectionChanged
Definition: rubydialog.cxx:85
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: rubydialog.cxx:155
Reference< XRubySelection > const & GetRubySelection()
Definition: rubydialog.cxx:103
Sequence< PropertyValues > & GetRubyValues()
Definition: rubydialog.cxx:116
void SetController(const Reference< XController > &xCtrl)
Definition: rubydialog.cxx:131
bool IsDisposing() const
Definition: rubydialog.cxx:102
Sequence< PropertyValues > aRubyValues
Definition: rubydialog.cxx:83
Reference< XModel > xModel
Definition: rubydialog.cxx:81
virtual ~SvxRubyData_Impl() override
Definition: rubydialog.cxx:129
Reference< XRubySelection > xSelection
Definition: rubydialog.cxx:82
bool HasSelectionChanged() const
Definition: rubydialog.cxx:101
Reference< XModel > const & GetModel()
Definition: rubydialog.cxx:93
std::unique_ptr< weld::Entry > m_xRight1ED
Definition: rubydialog.hxx:68
std::unique_ptr< weld::Widget > m_xGrid
Definition: rubydialog.hxx:90
tools::Long nCurrentEdit
Definition: rubydialog.hxx:61
std::unique_ptr< weld::Button > m_xStylistPB
Definition: rubydialog.hxx:84
virtual ~SvxRubyDialog() override
Definition: rubydialog.cxx:255
std::unique_ptr< weld::Entry > m_xRight4ED
Definition: rubydialog.hxx:74
std::unique_ptr< weld::Button > m_xClosePB
Definition: rubydialog.hxx:87
rtl::Reference< SvxRubyData_Impl > m_pImpl
Definition: rubydialog.hxx:64
std::unique_ptr< weld::Entry > m_xRight3ED
Definition: rubydialog.hxx:72
void EnableControls(bool bEnable)
Definition: rubydialog.cxx:678
std::unique_ptr< weld::Entry > m_xLeft3ED
Definition: rubydialog.hxx:71
virtual void Activate() override
Definition: rubydialog.cxx:273
std::unique_ptr< weld::Entry > m_xLeft2ED
Definition: rubydialog.hxx:69
std::unique_ptr< weld::Entry > m_xLeft1ED
Definition: rubydialog.hxx:67
void GetCurrentText(OUString &rBase, OUString &rRuby)
Definition: rubydialog.cxx:486
bool EditJumpHdl_Impl(sal_Int32 nParam)
Definition: rubydialog.cxx:646
weld::Entry * aEditArr[8]
Definition: rubydialog.hxx:65
void ClearCharStyleList()
Definition: rubydialog.cxx:262
std::unique_ptr< weld::ScrolledWindow > m_xScrolledWindow
Definition: rubydialog.hxx:76
bool EditScrollHdl_Impl(sal_Int32 nParam)
Definition: rubydialog.cxx:617
void AssertOneEntry()
Definition: rubydialog.cxx:676
std::unique_ptr< weld::Button > m_xApplyPB
Definition: rubydialog.hxx:86
std::unique_ptr< weld::ComboBox > m_xCharStyleLB
Definition: rubydialog.hxx:83
std::unique_ptr< weld::Container > m_xContentArea
Definition: rubydialog.hxx:89
void SetRubyText(sal_Int32 nPos, weld::Entry &rLeft, weld::Entry &rRight)
Definition: rubydialog.cxx:353
SvxRubyDialog(SfxBindings *pBindings, SfxChildWindow *pCW, weld::Window *pParent)
Definition: rubydialog.cxx:187
std::unique_ptr< weld::Entry > m_xLeft4ED
Definition: rubydialog.hxx:73
virtual void Close() override
Definition: rubydialog.cxx:264
void SetModified(bool bSet)
Definition: rubydialog.hxx:122
std::unique_ptr< weld::ComboBox > m_xPositionLB
Definition: rubydialog.hxx:80
std::unique_ptr< weld::Label > m_xCharStyleFT
Definition: rubydialog.hxx:82
std::unique_ptr< RubyPreview > m_xPreviewWin
Definition: rubydialog.hxx:92
void GetRubyText()
Definition: rubydialog.cxx:381
void SetLastPos(tools::Long nSet)
Definition: rubydialog.hxx:119
tools::Long GetLastPos() const
Definition: rubydialog.hxx:118
std::unique_ptr< weld::Entry > m_xRight2ED
Definition: rubydialog.hxx:70
std::unique_ptr< weld::ComboBox > m_xAdjustLB
Definition: rubydialog.hxx:78
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_Int16 nAdjust
@ Exception
std::map< sal_Int32, std::shared_ptr< SetItemPropertyStorage > > PropertyValues
int i
Close
long Long
sal_Int16 nId
const char GetValue[]
SfxItemState
SFX_IMPL_CHILDWINDOW(SvxRubyChildWindow, SID_RUBY_DIALOG)
IMPL_LINK(SvxRubyDialog, ScrollHdl_Impl, weld::ScrolledWindow &, rScroll, void)
Definition: rubydialog.cxx:492
IMPL_LINK_NOARG(SvxRubyDialog, ApplyHdl_Impl, weld::Button &, void)
Definition: rubydialog.cxx:507
Reference< XModel > xModel