diff options
author | László Németh <nemeth@numbertext.org> | 2024-02-29 14:07:34 +0100 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2024-03-04 23:39:51 +0100 |
commit | 9574a62add8e4901405e12117e75c86c2d2c2f21 (patch) | |
tree | 519ec81796776b97d2ea72f3a0f08c344c1779c2 /cui | |
parent | 2eba8bb8d43d39eb229a81947907e70f50859a76 (diff) |
tdf#132599 cui offapi sw xmloff: implement hyphenate-keep
Both parts of a hyphenated word shall lie within a single
page with ODF paragraph setting fo:hyphenation-keep="page".
The implementation follows the default page layout of
MSO 2016 and newer by shifting the bottom hyphenated line
to the next page (and to the next column, see last note).
Note: this is a MSO DOCX interoperability feature, used
also in DTP software, XSL and CSS.
* Add checkbox/combobox to Text Flow in paragraph dialog
* Store property in paragraph model (com::sun::star::style::ParagraphProperties::ParaHyphenationKeep)
* Add ODF import/export
* Add ODF unit tests
New constants of com::sun::star::text::ParagraphHyphenationKeepType,
containing ODF AUTO and PAGE (borrowed from XSL), and for the
planned extension ParaHyphenationKeepType of ParagraphProperties:
– COLUMN (standard XSL value, defined in
https://www.w3.org/TR/2001/REC-xsl-20011015/slice7.html#hyphenation-keep)
– SPREAD and ALWAYS (CSS 4 values of hyphenate-limit-last,
equivalent of hyphenation-keep, defined in
https://www.w3.org/TR/css-text-4/#hyphenate-line-limits).
Note: the implementation truncates only a single hyphenated
line, like MSO does: the pages can end in hyphenated
lines (i.e. in the case of consecutive hyphenated lines),
but less often, than before.
Clean-up hyphenation dialog by collecting "Don't hyphenate"
options at the end of the hyphenation settings, and negating them
(similar to MSO and DTP), adding also the new option
"Hyphenate across column and page":
[x] Hyphenate words in CAPS
[x] Hyphenate last word
[x] Hyphenate across column and page
Note: ODF fo:hyphenation-keep has got only "auto" and
"page" attributes, while XSL defines also "column".
Because of the interoperability with MSO and DTP,
fo:hyphenation-keep="page" is interpreted as
XSL "column", avoiding hyphenation at the end
of column, not only at the end of page.
Change-Id: I5c6b7adc0671a5a790568e7bf1d33256e607f85f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164158
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'cui')
-rw-r--r-- | cui/source/inc/paragrph.hxx | 5 | ||||
-rw-r--r-- | cui/source/tabpages/paragrph.cxx | 37 | ||||
-rw-r--r-- | cui/uiconfig/ui/textflowpage.ui | 100 |
3 files changed, 96 insertions, 46 deletions
diff --git a/cui/source/inc/paragrph.hxx b/cui/source/inc/paragrph.hxx index 9e78c8311015..0972203be73f 100644 --- a/cui/source/inc/paragrph.hxx +++ b/cui/source/inc/paragrph.hxx @@ -223,6 +223,7 @@ private: weld::TriStateEnabled aKeepParaState; weld::TriStateEnabled aOrphanState; weld::TriStateEnabled aWidowState; + weld::TriStateEnabled aKeepState; bool bPageBreak; bool bHtmlMode; @@ -267,6 +268,9 @@ private: std::unique_ptr<weld::SpinButton> m_xWidowRowNo; std::unique_ptr<weld::Label> m_xWidowRowLabel; + // avoid hyphenation across + std::unique_ptr<weld::CheckButton> m_xKeepBox; + void HyphenClickHdl(); void PageNumBoxClickHdl(); void ApplyCollClickHdl(); @@ -285,6 +289,7 @@ private: DECL_LINK(PageBreakTypeHdl_Impl, weld::ComboBox&, void); DECL_LINK(PageNumBoxClickHdl_Impl, weld::Toggleable&, void); DECL_LINK(KeepParaBoxClickHdl_Impl, weld::Toggleable&, void); + DECL_LINK(KeepHdl_Impl, weld::Toggleable&, void); virtual void PageCreated(const SfxAllItemSet& aSet) override; }; diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx index d644570784e6..a1403b30ea74 100644 --- a/cui/source/tabpages/paragrph.cxx +++ b/cui/source/tabpages/paragrph.cxx @@ -1627,13 +1627,14 @@ bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet ) m_xExtHyphenAfterBox->get_value_changed_from_saved() || m_xMaxHyphenEdit->get_value_changed_from_saved() || m_xMinWordLength->get_value_changed_from_saved() || - m_aHyphenZone.get_value_changed_from_saved() ) + m_aHyphenZone.get_value_changed_from_saved() || + m_xKeepBox->get_state_changed_from_saved() ) { SvxHyphenZoneItem aHyphen( static_cast<const SvxHyphenZoneItem&>(GetItemSet().Get( _nWhich )) ); aHyphen.SetHyphen( eHyphenState == TRISTATE_TRUE ); - aHyphen.SetNoCapsHyphenation(m_xHyphenNoCapsBox->get_state() == TRISTATE_TRUE); - aHyphen.SetNoLastWordHyphenation(m_xHyphenNoLastWordBox->get_state() == TRISTATE_TRUE); + aHyphen.SetNoCapsHyphenation(m_xHyphenNoCapsBox->get_state() != TRISTATE_TRUE); + aHyphen.SetNoLastWordHyphenation(m_xHyphenNoLastWordBox->get_state() != TRISTATE_TRUE); if ( eHyphenState == TRISTATE_TRUE ) { @@ -1647,6 +1648,18 @@ bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet ) DBG_ASSERT( pPool, "Where is the pool?" ); MapUnit eUnit = pPool->GetMetric( _nWhich ); aHyphen.GetTextHyphenZone() = static_cast<sal_uInt16>(m_aHyphenZone.GetCoreValue(eUnit)); + aHyphen.SetHyphen( eHyphenState == TRISTATE_TRUE ); + + const TriState eKeepState = m_xKeepBox->get_state(); + aHyphen.SetNoLastWordHyphenation(m_xHyphenNoLastWordBox->get_state() != TRISTATE_TRUE); + if ( eKeepState == TRISTATE_TRUE ) + { + // hyphenate across column and page -> 0 (AUTO) + aHyphen.GetKeep() = static_cast<sal_uInt8>(0); + } + else + // don't hyphenate across column -> 3 (COLUMN) + aHyphen.GetKeep() = static_cast<sal_uInt8>(3); if ( !pOld || *static_cast<const SvxHyphenZoneItem*>(pOld) != aHyphen || @@ -1857,8 +1870,8 @@ void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet ) bIsHyphen = rHyphen.IsHyphen(); m_xHyphenBox->set_state(bIsHyphen ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xHyphenNoCapsBox->set_state(rHyphen.IsNoCapsHyphenation() ? TRISTATE_TRUE : TRISTATE_FALSE); - m_xHyphenNoLastWordBox->set_state(rHyphen.IsNoLastWordHyphenation() ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xHyphenNoCapsBox->set_state(rHyphen.IsNoCapsHyphenation() ? TRISTATE_FALSE : TRISTATE_TRUE); + m_xHyphenNoLastWordBox->set_state(rHyphen.IsNoLastWordHyphenation() ? TRISTATE_FALSE : TRISTATE_TRUE); m_xExtHyphenBeforeBox->set_value(rHyphen.GetMinLead()); m_xExtHyphenAfterBox->set_value(rHyphen.GetMinTrail()); @@ -1866,6 +1879,9 @@ void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet ) m_xMinWordLength->set_value(rHyphen.GetMinWordLength()); m_aHyphenZone.SetFieldUnit(eFUnit); m_aHyphenZone.SetMetricValue(rHyphen.GetTextHyphenZone(), MapUnit::MapTwip); + // don't hyphenate column or paragraph -> disable checkbox + m_xKeepBox->set_state(rHyphen.GetKeep() < 3 ? TRISTATE_TRUE : TRISTATE_FALSE); + aKeepState.bTriStateEnabled = false; } else { @@ -1886,6 +1902,7 @@ void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet ) m_xMinWordLength->set_sensitive(bEnable); m_xHyphenZoneLabel->set_sensitive(bEnable); m_aHyphenZone.set_sensitive(bEnable); + m_xKeepBox->set_sensitive(bEnable); switch (rSet->GetItemState(SID_ATTR_PARA_PAGENUM)) { @@ -2147,6 +2164,7 @@ void SvxExtParagraphTabPage::ChangesApplied() m_xMaxHyphenEdit->save_value(); m_xMinWordLength->save_value(); m_aHyphenZone.save_value(); + m_xKeepBox->save_state(); m_xPageBreakBox->save_state(); m_xBreakPositionLB->save_value(); m_xBreakTypeLB->save_value(); @@ -2220,6 +2238,8 @@ SvxExtParagraphTabPage::SvxExtParagraphTabPage(weld::Container* pPage, weld::Dia , m_xWidowBox(m_xBuilder->weld_check_button("checkWidow")) , m_xWidowRowNo(m_xBuilder->weld_spin_button("spinWidow")) , m_xWidowRowLabel(m_xBuilder->weld_label("labelWidow")) + // Avoid hyphenation across + , m_xKeepBox(m_xBuilder->weld_check_button("checkKeep")) { // this page needs ExchangeSupport SetExchangeSupport(); @@ -2234,6 +2254,7 @@ SvxExtParagraphTabPage::SvxExtParagraphTabPage(weld::Container* pPage, weld::Dia m_xBreakPositionLB->connect_changed(LINK(this, SvxExtParagraphTabPage, PageBreakPosHdl_Impl)); m_xPageNumBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, PageNumBoxClickHdl_Impl)); m_xKeepParaBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, KeepParaBoxClickHdl_Impl)); + m_xKeepBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, KeepHdl_Impl)); if (SfxObjectShell* pSh = SfxObjectShell::Current()) { @@ -2409,6 +2430,7 @@ void SvxExtParagraphTabPage::HyphenClickHdl() m_xMinWordLength->set_sensitive(bEnable); m_xHyphenZoneLabel->set_sensitive(bEnable); m_aHyphenZone.set_sensitive(bEnable); + m_xKeepBox->set_sensitive(bEnable); m_xHyphenBox->set_state(bEnable ? TRISTATE_TRUE : TRISTATE_FALSE); } @@ -2510,6 +2532,11 @@ void SvxExtParagraphTabPage::PageCreated(const SfxAllItemSet& aSet) DisablePageBreak(); } +IMPL_LINK(SvxExtParagraphTabPage, KeepHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aKeepState.ButtonToggled(rToggle); +} + SvxAsianTabPage::SvxAsianTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) : SfxTabPage(pPage, pController, "cui/ui/asiantypography.ui", "AsianTypography", &rSet) , m_xForbiddenRulesCB(m_xBuilder->weld_check_button("checkForbidList")) diff --git a/cui/uiconfig/ui/textflowpage.ui b/cui/uiconfig/ui/textflowpage.ui index 9937427cf8c2..47bfc39de261 100644 --- a/cui/uiconfig/ui/textflowpage.ui +++ b/cui/uiconfig/ui/textflowpage.ui @@ -114,7 +114,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">6</property> + <property name="top-attach">4</property> </packing> </child> <child> @@ -134,7 +134,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">5</property> + <property name="top-attach">3</property> </packing> </child> <child> @@ -154,7 +154,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">4</property> + <property name="top-attach">2</property> </packing> </child> <child> @@ -174,7 +174,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">3</property> + <property name="top-attach">1</property> </packing> </child> <child> @@ -188,7 +188,7 @@ </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">3</property> + <property name="top-attach">1</property> </packing> </child> <child> @@ -202,7 +202,7 @@ </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">4</property> + <property name="top-attach">2</property> </packing> </child> <child> @@ -216,7 +216,7 @@ </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">5</property> + <property name="top-attach">3</property> </packing> </child> <child> @@ -230,37 +230,7 @@ </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">6</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="checkNoCaps"> - <property name="label" translatable="yes" context="textflowpage|checkNoCaps">Don't hyphenate words in _CAPS</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="use-underline">True</property> - <property name="draw-indicator">True</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">1</property> - <property name="width">2</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="checkNoLastWord"> - <property name="label" translatable="yes" context="textflowpage|checkNoLastWord">Don't hyphenate the last word</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="use-underline">True</property> - <property name="draw-indicator">True</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">2</property> - <property name="width">2</property> + <property name="top-attach">4</property> </packing> </child> <child> @@ -306,6 +276,57 @@ <property name="width">2</property> </packing> </child> + <child> + <object class="GtkCheckButton" id="checkNoCaps"> + <property name="label" translatable="yes" context="textflowpage|checkNoCaps">Hyphenate words in _CAPS</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">8</property> + <property name="width">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="checkNoLastWord"> + <property name="label" translatable="yes" context="textflowpage|checkNoLastWord">Hyphenate last word</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">9</property> + <property name="width">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="checkKeep"> + <property name="label" translatable="yes" context="textflowpage|checkKeep">Hyphenate _across column and page</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="inconsistent">True</property> + <property name="draw-indicator">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="checkKeep-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="textflowpage|extended_tip|checkKeep">Deselect this check box, if you don't want to hyphenate across column and page.</property> + </object> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">10</property> + <property name="width">2</property> + </packing> + </child> </object> </child> <child type="label"> @@ -720,9 +741,6 @@ <property name="top-attach">1</property> </packing> </child> - <child> - <placeholder/> - </child> <child internal-child="accessible"> <object class="AtkObject" id="TextFlowPage-atkobject"> <property name="AtkObject::accessible-description" translatable="yes" context="textflowpage|extended_tip|TextFlowPage">Specify hyphenation and pagination options.</property> |